首页
社区
课程
招聘
[原创]PEDIY CrackMe竞赛2016---第七题简单分析
发表于: 2016-11-16 17:28 5232

[原创]PEDIY CrackMe竞赛2016---第七题简单分析

2016-11-16 17:28
5232

简单分析原则,最近论坛发图老是挂掉,烦恼啊!这几天没怎么合眼有点逻辑混乱大家包含,我直接上代码大家自己看看吧。
第七题刚开始拿到题抽象不出模型,一堆递归调用,完全懵了,注册码在最后面哈!
代码如下:


得到这个数组后,输入序列号了。


unsigned __int64 Calc4(int minv, int maxv, unsigned __int64 Buf[][MAX_COUNT], unsigned int *Init)
{
        if (minv > maxv) return 0;
        if (Buf[minv][maxv] != 0xFFFFFFFFFFFFFFFF) return Buf[minv][maxv];
        if (minv == maxv)
        {
                Buf[minv][maxv] = Init[minv];
                return Buf[minv][maxv];
        }       
        Buf[minv][maxv] = Calc4(minv + 1, maxv, Buf, Init) + Init[minv];
        return Buf[minv][maxv];
}

unsigned __int64 Calc3(int minv, int maxv, unsigned __int64 Buf[][MAX_COUNT], unsigned int *Init)
{
        if (minv > maxv) return 0;
        if (Buf[minv][maxv] != 0xFFFFFFFFFFFFFFFF) return Buf[minv][maxv];
        if (minv == maxv)
        {
                Buf[minv][maxv] = Init[minv];
                return Buf[minv][maxv];
        }
        unsigned __int64 v1 = Calc3(minv + 1, maxv, Buf, Init);
        unsigned __int64 v2 = Calc3(minv, maxv - 1, Buf, Init);
        unsigned __int64 v3;
        if (v2 < v1)
        {
                v3 = Calc3(minv, maxv - 1, Buf, Init);
        }
        else
        {
                v3 = Calc3(minv + 1, maxv, Buf, Init);
        }
        Buf[minv][maxv] = Calc4(minv, maxv, Buff2, Init) - v3;
        return Buf[minv][maxv];
}
初始化代码中的关键代码,也应该从这里面推算出序列号。
        Init[0] = 0x6C35B49D;
        Init[1] = 0xA645500D;
        Init[2] = 0xCB9E682E;
        s = Init[0];
        s += Init[1];
        s += Init[2];
        for (int i = 3; i < MAX_COUNT; i++)
        {
                Init[i] = Init[i-3] + Init[i-2] * Init[i-1];
                s += Init[i];
        }
        memset( Buff1, 0xFF, sizeof(Buff1));
        memset( Buff2, 0xFF, sizeof(Buff2));
        unsigned __int64 kc = Calc3( 0, MAX_COUNT - 1, Buff1, &Init[0]);//=a  ok
        unsigned __int64 ke = Calc4( 0, MAX_COUNT - 1, Buff2, &Init[0]);;
        unsigned __int64 kd = ke -kc;
这是全部初始化过程。
#define MAX_COUNT 1010

unsigned int Init[1010];
unsigned __int64 Buff1[1010][1010];
unsigned __int64 Buff2[1010][1010];
if (IS_DEC_INDEX == 0)
                        {
                                if (ab == 0) {a += Init[indexi];} else b += Init[indexi];
                                indexi++;
                        }
                        else
                        {
                                if (ab == 0) {a += Init[indexj];} else b += Init[indexj];
                                indexj--;
                        }
                        ab = (ab == 0) ? 1: 0;
这里是关键运算的子函数,如果计算结果, 能够让
c=000000FEF635D82A        d=000000FAD883E964
a=c; b=d;答案就出来了。
BCBCBCBCBFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBBBBBBBBBBBBBBBBBBBBBBBB
用这个序列号可以过Check0/Check1/Check2
         
int indexi = 0;
        int indexj = MAX_COUNT - 1;
        int sum = 0;
        int IS_DEC_INDEX = 1;
        int ab = 0;
        unsigned __int64 a = 0, b = 0;       
        unsigned char sn[85];//969//=15*61+54//
        for (size_t i = 0; i < strlen(SN); i++)
        {
                //char *p = ;
                //假设字符都没问题
                int j = strchr(charTab, SN[i]) - charTab;
                sum += j;
                for (int k = 0; k < j; k++)
                {
                        if (IS_DEC_INDEX == 0)
                        {
                                if (ab == 0) {a += Init[indexi];} else b += Init[indexi];
                                indexi++;
                        }
                        else
                        {
                                if (ab == 0) {a += Init[indexj];} else b += Init[indexj];
                                indexj--;
                        }
                        ab = (ab == 0) ? 1: 0;
                }
               
                IS_DEC_INDEX = (IS_DEC_INDEX == 0) ? 1 : 0;
        }
这个就是a需要用到的索引。
其它0-1009,不包含在内的,是b要用到的索引。
//                 unsigned __int64 a = 0;
//                 for (int i = 0; i < 505; i++)
//                 {
//                         a += Init[aa[i]];
//                 }
b与这类似。
字符控制后,//i = 470, j = 510
471-509之间的数据不用管
        char charTab[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";//62=0x3E
        //[1-3D]
只能取1-3D闭区间的值, 0不行,间隔为2个可以认为是同一个序列号范围控制;
突然为1,那一定序列号变索引了,关键把构成a,b的组合,转成序列号。
那个关键过程,每次调用a+; b+; a+; b+;这么切换;一旦出现不是这样的序列,序列号肯定要做下一个字符了。

红色是表示,一次a+, 一次b+,进行切换;
绿色则表示序列号索引切换了。

最后不解释了直接贴码大家好好看看吧:
// k7.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <memory.h>
//#include <set>
//#include <list>
#include <vector>
#include <algorithm>

#define MAX_COUNT 1010

unsigned int Init[1010];
//一维数组
unsigned __int64 Buf1[1010*1010];
unsigned __int64 Buf2[1010*1010];
//二维数组
unsigned __int64 Buff1[1010][1010];
unsigned __int64 Buff2[1010][1010];
//二维数组, 非递归
unsigned __int64 Bufff1[1010][1010];
unsigned __int64 Bufff2[1010][1010];

//求解构成a=c使用
using namespace std;

unsigned __int64 fff[MAX_COUNT][MAX_COUNT];
unsigned __int64 ggg[MAX_COUNT][MAX_COUNT];
vector<int>hhh[MAX_COUNT][MAX_COUNT];

//////////////////////////////////////////////////////////////////////////
//一维数组
unsigned __int64 Calc2(int minv, int maxv, unsigned __int64 *Buf, unsigned int *Init)
{
        if (minv > maxv)
        {
                return 0;
        }
        if (Buf[minv * MAX_COUNT + maxv] != 0xFFFFFFFFFFFFFFFF)
        {
                return Buf[minv * MAX_COUNT + maxv];
        }
        if (minv == maxv)
        {
                Buf[minv * MAX_COUNT + maxv] = Init[minv];
                return Buf[minv * MAX_COUNT + maxv];
        }
        Buf[minv * MAX_COUNT + maxv] = Calc2(minv + 1, maxv, Buf, Init) + Init[minv];
        return Buf[minv * MAX_COUNT + maxv];
}

unsigned __int64 Calc1(int minv, int maxv, unsigned __int64 *Buf, unsigned int *Init)
{
        if (minv > maxv)
        {
                return 0;
        }
        if (Buf[minv * MAX_COUNT + maxv] != 0xFFFFFFFFFFFFFFFF)
        {
                return Buf[minv * MAX_COUNT + maxv];
        }
        if (minv == maxv)
        {
                Buf[minv * MAX_COUNT + maxv] = Init[minv];
                return Buf[minv * MAX_COUNT + maxv];
        }
        unsigned __int64 v1 = Calc1(minv + 1, maxv, Buf, Init);
        unsigned __int64 v2 = Calc1(minv, maxv - 1, Buf, Init);
        unsigned __int64 v3;
        if (v2 < v1)
        {
                v3 = Calc1(minv, maxv - 1, Buf, Init);
        }
        else
        {
                v3 = Calc1(minv + 1, maxv, Buf, Init);
        }
        Buf[minv * MAX_COUNT + maxv] = Calc2(minv, maxv, &Buf2[0], Init) - v3;
        return Buf[minv * MAX_COUNT + maxv];
}

//////////////////////////////////////////////////////////////////////////
//二维数组
unsigned __int64 Calc4(int minv, int maxv, unsigned __int64 Buf[][MAX_COUNT], unsigned int *Init)
{
        if (minv > maxv) return 0;
        if (Buf[minv][maxv] != 0xFFFFFFFFFFFFFFFF) return Buf[minv][maxv];
        if (minv == maxv)
        {
                Buf[minv][maxv] = Init[minv];
                return Buf[minv][maxv];
        }       
        Buf[minv][maxv] = Calc4(minv + 1, maxv, Buf, Init) + Init[minv];
        return Buf[minv][maxv];
}

unsigned __int64 Calc3(int minv, int maxv, unsigned __int64 Buf[][MAX_COUNT], unsigned int *Init)
{
        if (minv > maxv) return 0;
        if (Buf[minv][maxv] != 0xFFFFFFFFFFFFFFFF) return Buf[minv][maxv];
        if (minv == maxv)
        {
                Buf[minv][maxv] = Init[minv];
                return Buf[minv][maxv];
        }
        unsigned __int64 v1 = Calc3(minv + 1, maxv, Buf, Init);
        unsigned __int64 v2 = Calc3(minv, maxv - 1, Buf, Init);
        unsigned __int64 v3;
        if (v2 < v1)
        {
                v3 = Calc3(minv, maxv - 1, Buf, Init);
        }
        else
        {
                v3 = Calc3(minv + 1, maxv, Buf, Init);
        }
        Buf[minv][maxv] = Calc4(minv, maxv, Buff2, Init) - v3;
        return Buf[minv][maxv];
}

char charTab[]="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";//62=0x3E

首先看检查序列号函数
bool check_serial(const char *SN)
{
        //0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF0123456789ABCDEF12345
        //BBBBBBBBBFBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCCC
        //BCBCBCBCBFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBBBBBBBBBBBBBBBBBBBBBBBB
        //10+26+26=62个字符, [0-61]
        //1-61
        //0042E220     c=000000FEF635D82A        d=000000FAD883E964   
        //sum=000001F9CEB9C18E

        //////////////////////////////////////////////////////////////////////////
        // b +=;IndexI++;
        //char SN[] = "BCBCBCBCBFCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBCBBBBBBBBBBBBBBBBBBBBBBBB";       
        //check0//0040284B
        if (strlen(SN) != 85) return false;
        if (SN[9] != 'F') return false;       

        //////////////////////////////////////////////////////////////////////////       
        //序列号处理//0040284B
        //1010
        //969
        //1010-969=41
        //checkserial
        int indexi = 0;
        int indexj = MAX_COUNT - 1;
        int sum = 0;
        int IS_DEC_INDEX = 1;
        int ab = 0;
        unsigned __int64 a = 0, b = 0;       
        unsigned char sn[85];//969//=15*61+54//
        for (size_t i = 0; i < strlen(SN); i++)
        {
                //char *p = ;
                //假设字符都没问题
                //004027DC//对每个字符进行处理
                int j = strchr(charTab, SN[i]) - charTab;
                sum += j;
                for (int k = 0; k < j; k++)
                {
                        if (IS_DEC_INDEX == 0)
                        {
                                if (ab == 0) {a += Init[indexi];} else b += Init[indexi];
                                indexi++;
                        }
                        else
                        {
                                if (ab == 0) {a += Init[indexj];} else b += Init[indexj];
                                indexj--;
                        }
                        ab = (ab == 0) ? 1: 0;
                }
               
                IS_DEC_INDEX = (IS_DEC_INDEX == 0) ? 1 : 0;
        }

        //////////////////////////////////////////////////////////////////////////
        //后面的数据需要继续处理//004028D0
        while (indexi <= indexj)
        {
                if (IS_DEC_INDEX == 0)
                {
                        if (ab == 0) {a += Init[indexi];} else b += Init[indexi];
                        indexi++;//后来全在这个里面, 且第一次ab=1;
                }
                else
                {
                        if (ab == 0) {a += Init[indexj];} else b += Init[indexj];
                        indexj--;
                }
                ab = (ab == 0) ? 1: 0;
        }

        //c=000000FEF635D82A        d=000000FAD883E964    //c-d=41DB1EEC6  c^d=42EB6314E
        //0042E200     a=000000FC08D3A291        b=000000FDC5E61EFD   
        //i = 470, j = 510
    //sa=000000F4B9B59850, sb=000000F060FD60E8

        /*
        //Check0
        lenSN= 0x55
        SN[9] = 'F';

        //Check1//004029D3
        sum + d + c - sum - sum == 0 => d + c = sum   //OK

        //Check2//00402930
        sum == 969;
        i = 470;
        j = 510;

        //Check3//0040295F
        num_c + num_b - num_a - num_d == 0  => c - d = a - b; a=c; b= d那就OK

        //Check4//00402999
        num_d == (num_c ^ num_b ^ num_a) = >   c ^ d  = a ^ b

        //最简单的答案就是a=c; b=d;
        if a =5E77DDEBB, b=1C9CBEFF5  =>        a-b=  41DB1EEC6 a^b = 42EB6314E

        */
        //上诉条件全部满足则返回成功

        return true;

}

int _tmain(int argc, _TCHAR* argv[])
{
       

        //////////////////////////////////////////////////////////////////////////
        //数据初始化, //004026CD
        unsigned __int64 s = 0;
        Init[0] = 0x6C35B49D;
        Init[1] = 0xA645500D;
        Init[2] = 0xCB9E682E;
        s = Init[0];
        s += Init[1];
        s += Init[2];
        for (int i = 3; i < MAX_COUNT; i++)
        {
                Init[i] = Init[i-3] + Init[i-2] * Init[i-1];
                s += Init[i];
        }
       
        //[1-3D]
        //////////////////////////////////////////////////////////////////////////
        //00402C34//以为数组方式初始化, 递归调用
        memset( Buf1, 0xFF, sizeof(Buf1));
        memset( Buf2, 0xFF, sizeof(Buf2));
        unsigned __int64 c = Calc1( 0, MAX_COUNT - 1, &Buf1[0], &Init[0]);//=a  ok
        unsigned __int64 e = Calc2( 0, MAX_COUNT - 1, &Buf2[0], &Init[0]);;
        unsigned __int64 d = e - c;//=b  ok
        //转成2维数组[1010][1010]
        memcpy(Buff1, Buf1, sizeof(Buff1));
        memcpy(Buff2, Buf2, sizeof(Buff2));
        //////////////////////////////////////////////////////////////////////////
        //二维数组的方式初始化, 递归调用(源程序可能使用这个办法)
        //memset( Buff1, 0xFF, sizeof(Buff1));
        //memset( Buff2, 0xFF, sizeof(Buff2));
        //unsigned __int64 kc = Calc3( 0, MAX_COUNT - 1, Buff1, &Init[0]);//=a  ok
        //unsigned __int64 ke = Calc4( 0, MAX_COUNT - 1, Buff2, &Init[0]);;
        //unsigned __int64 kd = ke -kc;
        //经比较两种方式数据一致
        //if (memcmp(Buf1, Buff1, sizeof(Buf1)) == 0)
        //{
        //        printf("ok");
        //}
        //else
        //{
        //        printf("failed");
        //}
        //////////////////////////////////////////////////////////////////////////
        //去除递归调用, 二维数组初始化, 便于理解原理
        //////////////////////////////////////////////////////////////////////////
        //非递归调用
        memset( Bufff1, 0xFF, sizeof(Bufff1));
        memset( Bufff2, 0xFF, sizeof(Bufff2));
        for (int  i = MAX_COUNT-1; i >= 1; i--)
        {
                Bufff2[i][i] = Init[i];
                for (int j = i - 1; j >= 0; j--)
                {
                        Bufff2[j][i] = Bufff2[j+1][i] + Init[j];
                }
        }
        for (int  i = 0; i < MAX_COUNT; i++)
        {
                Bufff1[i][i] = Init[i];
        }
        for (int i = 0; i < MAX_COUNT - 1; i++)
        {               
                for (int j = 0; j < MAX_COUNT- i - 1; j++)
                {
                        unsigned __int64 v1 = Bufff1[j] [j+i];
                        unsigned __int64 v2 = Bufff1[j+1] [j+i+1];
                        unsigned __int64 v3;
                        if (v2 < v1)
                        {
                                v3 = v2;
                        }
                        else
                        {
                                v3 = v1;
                        }

                        Bufff1[j][j+i+1] = Bufff2[j][j+i+1] - v3;
                }
        }

        //////////////////////////////////////////////////////////////////////////
        //原理知道了, 计算c=[0][1009]是由哪些数组累加成的
//////////////////////////////////////////////////////////////////////////
        //求解a=c的构成
        memset(fff, 0xFF, sizeof(fff));
        memset(ggg, 0xFF, sizeof(ggg));
        /*
            Buff2[i][j] = Buff2[i+ 1, j] + Init[i]
                            = Buff2[i+ 2, j] + Init[i+1] + Init[i]
                                        = ...
                                        = Init[j]+[]+[]+[i]
        */
        for (int i = 0; i < MAX_COUNT; i++)
        {
                for (int j = 1; j < MAX_COUNT; j++)
                {
                        if (i > j) continue;
                        unsigned __int64 aa = 0;
                        for (int k = i; k <= j; k++)
                        {
                                aa += Init[k];
                        }
                        fff[i][j] = aa;
                }
        }

        for (int  i = 0; i < MAX_COUNT; i++)
        {
                ggg[i][i] = Init[i];
                //list/set太耗内存了
                hhh[i][i].push_back(i);//list/vector
        }
       
        for (int i = 0; i < MAX_COUNT - 1; i++)
        {               
                for (int j = 0; j < MAX_COUNT- i - 1; j++)
                {
                        unsigned __int64 v1 = ggg[j] [j+i];
                        unsigned __int64 v2 = ggg[j+1] [j+i+1];
                        unsigned __int64 v3;
                                               
                        if (v2 < v1)
                        {
                                v3 = v2;
                                //[  j+1,j+ 2,...j+i+1]
                                //[j,j+1,....j+i+1]
                                //hhh[j+1][j+i+1]
                                //hhh[j][j+i+1].push_back(j);
                                //hhh[j][j+i+1] -= hhh[0][0];
                                for (int k = j; k <= j + i + 1; k++)
                                {
                                        if (find(hhh[j+1] [j+i+1].begin(), hhh[j+1] [j+i+1].end(), k) == hhh[j+1] [j+i+1].end())
                                        {
                                                hhh[j][j+i+1].push_back( k );
                                        }                                       
                                }
                        }
                        else
                        {
                                v3 = v1;
                                //ggg[j] [j+i];
                                //hhh[j][j+i+1].push_back(j+i+1);
                                for (int k = j; k <= j + i + 1; k++)
                                {
                                        if (find(hhh[j] [j+i].begin(), hhh[j] [j+i].end(), k) == hhh[j] [j+i].end())
                                        {
                                                hhh[j][j+i+1].push_back( k );
                                        }                                       
                                }

                        }

                        ggg[j][j+i+1] = fff[j][j+i+1] - v3;                       
                       
                }
        }
for (size_t i = 0; i < hhh[0][1009].size(); i++)
        {
                printf("%d,", hhh[0][1009][i]);
}

       
这是求解组成c=a的所有数据索引。

c=a=Buff1[0][1090];
intaa[]= 1,3,4,6,8,10,12,14,16,18,20,22,24,26,28,30,32,34,36,38,40,42,44,46,48,50,52,54,56,57,59,61,63,65,67,69,71,73,75,77,79,81,83,85,87,89,91,93,95,97,99,101,103,105,107,109,111,113,115,117,119,121,123,125,127,129,131,133,135,137,138,140,142,144,146,148,150,152,154,156,158,160,162,164,166,168,170,172,174,176,178,180,182,184,186,188,190,192,194,196,198,200,202,204,206,208,210,212,214,216,218,220,222,224,226,228,230,232,234,236,238,240,242,244,246,248,250,252,254,256,258,260,262,264,266,268,270,272,274,276,278,280,282,284,286,288,290,292,294,296,298,300,302,304,306,308,310,312,314,316,318,320,322,324,326,328,330,332,334,336,338,340,342,344,346,348,350,352,354,356,358,360,362,364,366,368,370,372,374,376,378,380,382,384,386,387,389,391,393,395,397,399,401,403,405,407,409,411,413,415,417,419,421,423,425,427,429,431,433,435,437,439,441,443,445,447,449,451,453,455,457,459,461,463,465,467,469,471,473,475,477,479,481,483,485,487,489,491,493,495,497,499,501,503,505,507,509,511,513,515,517,519,521,523,525,527,529,531,533,535,537,539,541,543,545,547,549,551,553,555,557,559,561,563,565,567,569,571,573,575,577,579,581,583,585,587,589,591,593,595,597,599,601,603,605,607,609,611,613,615,617,619,621,623,625,627,629,631,633,635,637,639,641,643,645,647,649,651,653,655,657,659,661,663,665,667,669,671,673,675,677,679,681,683,685,687,689,691,693,695,697,699,701,703,705,707,709,711,713,716,718,720,722,724,726,728,730,732,734,736,738,740,742,744,746,748,750,752,754,756,758,760,762,764,766,768,770,772,774,776,778,780,782,784,786,788,790,792,794,796,798,800,802,804,806,808,810,812,814,816,818,820,822,824,826,828,830,832,834,836,838,840,842,844,846,848,850,852,854,856,858,860,862,864,866,868,870,872,874,876,878,880,883,885,887,889,891,893,895,897,899,901,903,905,907,909,911,913,915,917,919,921,923,925,927,930,932,934,936,938,940,942,944,946,948,950,952,954,956,958,960,962,964,966,968,970,972,974,976,978,980,982,984,986,988,990,992,994,996,998,1001,1003,1005,1007,1009   
就是这组数据构成了a=c, 其余的数据组成了b=d;

for (size_t i = 0; i < hhh[0][1009].size(); i++)
{
                printf("%d,", hhh[0][1009][i]);
}

        //虽然知道了//程序仍不知道怎么计算结果??手工计算了~~~:(
        //
        int vv[33] = {
                9,       4,                1,                53,                29,                40,                42,                41,                47,                15,
                40,                58,                40,                58,                40,                58,                40,                58,                6,                2,               
                1,                1,                18,                8,                6,                8,                6,                8,                6,                2,
                6,                2,                6
        };
        for (int i = 0; i < 85; i++)
        {

                if (i >= 33)
                {
                        if (i & 1)
                        {printf("%c", charTab[2]);}
                        else
                        {printf("%c", charTab[6]);}
                }
                else
                {
                        printf("%c", charTab[vv[i]]);

                }
        }

        //////////////////////////////////////////////////////////////////////////
        //检查序列号
        check_serial("941rTegflFcwgwewew6211I86868646262626262626262626262626262626262626262626262626262626");

        return 0;
}


[招生]科锐逆向工程师培训(2024年11月15日实地,远程教学同时开班, 第51期)

上传的附件:
收藏
免费 2
支持
分享
最新回复 (3)
雪    币: 79
活跃值: (373)
能力值: ( LV11,RANK:195 )
在线值:
发帖
回帖
粉丝
2
膜拜  大牛 看ida 如有源码
2016-11-16 19:52
0
雪    币: 25430
活跃值: (4777)
能力值: ( LV2,RANK:10 )
在线值:
发帖
回帖
粉丝
3
图片挂了
2016-11-16 20:53
0
雪    币: 134
活跃值: (11)
能力值: ( LV3,RANK:30 )
在线值:
发帖
回帖
粉丝
4
都是神人
2016-11-17 15:42
0
游客
登录 | 注册 方可回帖
返回
//