首页
社区
课程
招聘
[原创]破解CR-Game0.83.rar_832
发表于: 2016-3-2 18:06 4644

[原创]破解CR-Game0.83.rar_832

2016-3-2 18:06
4644

CrackMe提供者:JiP
原帖:http://bbs.pediy.com/showthread.php?t=8695
工具:od,vc
平台:winxpsp3

Level 001:
一、破
为阻挠简单爆破,作者在本关设计了一个伪正确序列号:
00401475   .  43 52 2D 47 6>ascii   "CR-Game JiP",0

同时使用了验证标志变量:
004014E3   > \C705 04504000>mov     dword ptr ds:[405004], 1

所以,Level 001爆破必须要修改两处才行。建议如下:
第一处:
00401459   > \FFD0          call    eax
0040145B   .  83F8 03       cmp     eax, 3
0040145E   .  0F8E B0000000 jle     00401514                ;爆破点

第二处:
00402614   > \0BC0          or      eax, eax
00402616   .  0F84 C8010000 je      004027E4                ;爆破点

二、解
正确序列号:
004014EF   .  43 52 2D 47 6>ascii   "CR-Game JPO",0

算法描述:
1、序列号长度不能小于3个字符
0040145B   .  83F8 03       cmp     eax, 3
0040145E   .  0F8E B0000000 jle     00401514

2、第八个字符是空格
00401468   .  807A 07 20    cmp     byte ptr ds:[edx+7], 20
0040146C   .  75 04         jnz     short 00401472

3、第十一个字符+0x1f
0040146E   .  8042 0A 1F    add     byte ptr ds:[edx+A], 1F

4、结果要等于“CR-Game JPO”
004014FB   > \68 EF144000   push    004014EF                         ;  ASCII "CR-Game JPO"
00401500   .  8D45 F4       lea     eax, dword ptr ss:[ebp-C]
00401503   .  50            push    eax
00401504   .  E8 3DFCFFFF   call    00401146                         ;  strcmp
00401509   .  0BC0          or      eax, eax
0040150B   .  75 07         jnz     short 00401514

Level 001 Keygen:
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char sn[]="CR-Game JPO";
        char *psn;

        psn = sn;
        while(*psn != '\0')
                psn++;
        psn--;
        *psn = *psn - 0x1f;

        printf("Level 001 注册码:%s",sn);
        getchar();

        return 0;
}


[培训]内核驱动高级班,冲击BAT一流互联网大厂工作,每周日13:00-18:00直播授课

收藏
免费 3
支持
分享
最新回复 (12)
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
2
刚才漏讲了该程序的反调试,这里补上(使用看雪ollyice的可以无视)。
作者一开始就给初学者一个下马威:
00402137 > $  6A 00         push    0
00402139   .  68 42214000   push    00402142                         ;  ASCII "OLLYDBG"

0040214A   .  B8 90304000   mov     eax, 00403090
0040214F   .  83E8 04       sub     eax, 4

0040216C   .  FFD0          call    eax                              ;  <jmp.&user32.FindWindowA>
0040216E   .  83F8 00       cmp     eax, 0
00402171   .  75 6B         jnz     short 004021DE

兜头一棒,进来就检测od。这还不算完,
00402EAF   .  6A 00         push    0                                ; /Timerproc = NULL
00402EB1   .  68 E8030000   push    3E8                              ; |Timeout = 1000. ms
00402EB6   .  68 05040000   push    405                              ; |TimerID = 405 (1029.)
00402EBB   .  FF75 08       push    dword ptr ss:[ebp+8]             ; |hWnd
00402EBE   .  E8 41020000   call    <jmp.&user32.SetTimer>           ; \SetTimer

创建完窗口后顺手建立一个定时器。进去看看
00402887   .  FF75 08       push    dword ptr ss:[ebp+8]             ;  Case 113 (WM_TIMER) of switch 004022ED
0040288A   .  E8 59F8FFFF   call    004020E8

又是反od,
004020E8   $  55            push    ebp
004020E9   .  8BEC          mov     ebp, esp
004020EB   .  6A 00         push    0
004020ED   .  68 F6204000   push    004020F6                         ;  ASCII "OLLYDBG"

004020FE   .  B8 90304000   mov     eax, 00403090
00402103   .  83E8 04       sub     eax, 4

0040210C   > \FFD0          call    eax                              ;  <jmp.&user32.FindWindowA>

所以要想不受干扰,要么使用ollyice,要么就爆掉这两处反调试。
2016-3-2 18:46
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
3
Level 002 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为2
0040157E   .  C705 04504000>mov     dword ptr ds:[405004], 2

2、确保eax返回时为2
004015AB   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、序列号长度要超过8个字符
00401545   .  83F8 08       cmp     eax, 8
00401548   .  7E 68         jle     short 004015B2

2、第一个子符 + 1 = 0x32
0040154D   .  8003 01       add     byte ptr ds:[ebx], 1

00401588   .  803B 32       cmp     byte ptr ds:[ebx], 32
0040158B   .  75 25         jnz     short 004015B2

2、第二个字符 + 2 = 任意  (作者本意估计要 sn[1] + 2 = 0x6c,可能疏忽写掉了一条指令)
00401550   .  8043 01 02    add     byte ptr ds:[ebx+1], 2
00401554   .  807B 01 6C    cmp     byte ptr ds:[ebx+1], 6C

3、第三个字符 + 0x20 = 0x6a
00401558   .  8043 02 20    add     byte ptr ds:[ebx+2], 20
0040158D   .  807B 02 6A    cmp     byte ptr ds:[ebx+2], 6A
00401591   .  75 1F         jnz     short 004015B2

4、第四个字符 or 0x20 = 0x69
0040155C   .  804B 03 20    or      byte ptr ds:[ebx+3], 20
00401593   .  807B 03 69    cmp     byte ptr ds:[ebx+3], 69
00401597   .  75 19         jnz     short 004015B2

5、第五个字符 xor 0x20 = 0x50
00401560   .  8073 04 20    xor     byte ptr ds:[ebx+4], 20
00401564   .  807B 04 50    cmp     byte ptr ds:[ebx+4], 50
00401568   .  75 48         jnz     short 004015B2

6、第六个字符 or 0x20 = 0x76
0040156A   .  804B 05 20    or      byte ptr ds:[ebx+5], 20
00401599   .  807B 05 4C    cmp     byte ptr ds:[ebx+5], 4C
0040159D   .  74 13         je      short 004015B2

7、第七个字符 + 0x3b = 0x6c
0040156E   .  8043 06 3B    add     byte ptr ds:[ebx+6], 3B
004015A5   .  807B 06 6C    cmp     byte ptr ds:[ebx+6], 6C
004015A9   .  75 07         jnz     short 004015B2

8、第八个字符 = 0x47
00401572   .  807B 07 47    cmp     byte ptr ds:[ebx+7], 47
00401576   .  75 3A         jnz     short 004015B2

9、第九个字符 = 0x43
00401578   .  807B 08 43    cmp     byte ptr ds:[ebx+8], 43
0040157C   .  75 34         jnz     short 004015B2

Level 002 keygen:
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char sn[10];

        sn[0] = 0x32 -1;
        sn[1] = '*';
        sn[2] = 0x6a - 0x20;
        sn[3] = 0x69 ^ 0x20;
        sn[4] =        0x50 ^ 0x20;
        sn[5] = 0x76 ^ 0x20;
        sn[6] = 0x6c - 0x3b;
        sn[7] = 0x47;
        sn[8] = 0x43;
        sn[9] = 0;

        printf("Level 001 注册码:%s",sn);
        getchar();

        return 0;
}
2016-3-2 22:42
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
4
Level 002 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为2
0040157E   .  C705 04504000>mov     dword ptr ds:[405004], 2

2、确保eax返回时为2
004015AB   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、序列号长度要超过8个字符
00401545   .  83F8 08       cmp     eax, 8
00401548   .  7E 68         jle     short 004015B2

2、第一个子符 + 1 = 0x32
0040154D   .  8003 01       add     byte ptr ds:[ebx], 1

00401588   .  803B 32       cmp     byte ptr ds:[ebx], 32
0040158B   .  75 25         jnz     short 004015B2

2、第二个字符 + 2 = 任意  (作者本意估计要 sn[1] + 2 = 0x6c,可能疏忽写掉了一条指令)
00401550   .  8043 01 02    add     byte ptr ds:[ebx+1], 2
00401554   .  807B 01 6C    cmp     byte ptr ds:[ebx+1], 6C

3、第三个字符 + 0x20 = 0x6a
00401558   .  8043 02 20    add     byte ptr ds:[ebx+2], 20
0040158D   .  807B 02 6A    cmp     byte ptr ds:[ebx+2], 6A
00401591   .  75 1F         jnz     short 004015B2

4、第四个字符 or 0x20 = 0x69
0040155C   .  804B 03 20    or      byte ptr ds:[ebx+3], 20
00401593   .  807B 03 69    cmp     byte ptr ds:[ebx+3], 69
00401597   .  75 19         jnz     short 004015B2

5、第五个字符 xor 0x20 = 0x50
00401560   .  8073 04 20    xor     byte ptr ds:[ebx+4], 20
00401564   .  807B 04 50    cmp     byte ptr ds:[ebx+4], 50
00401568   .  75 48         jnz     short 004015B2

6、第六个字符 or 0x20 = 0x76
0040156A   .  804B 05 20    or      byte ptr ds:[ebx+5], 20
00401599   .  807B 05 4C    cmp     byte ptr ds:[ebx+5], 4C
0040159D   .  74 13         je      short 004015B2

7、第七个字符 + 0x3b = 0x6c
0040156E   .  8043 06 3B    add     byte ptr ds:[ebx+6], 3B
004015A5   .  807B 06 6C    cmp     byte ptr ds:[ebx+6], 6C
004015A9   .  75 07         jnz     short 004015B2

8、第八个字符 = 0x47
00401572   .  807B 07 47    cmp     byte ptr ds:[ebx+7], 47
00401576   .  75 3A         jnz     short 004015B2

9、第九个字符 = 0x43
00401578   .  807B 08 43    cmp     byte ptr ds:[ebx+8], 43
0040157C   .  75 34         jnz     short 004015B2

Level 002 keygen:
#include "stdafx.h"
#include "stdLib.h"
#include "time.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char sn[10];

        sn[0] = 0x32 -1;
        srand((unsigned int)time(NULL));
        sn[1] = rand() % 90 + 0x21;
        sn[2] = 0x6a - 0x20;
        sn[3] = 0x69 ^ 0x20;
        sn[4] =        0x50 ^ 0x20;
        sn[5] = 0x76 ^ 0x20;
        sn[6] = 0x6c - 0x3b;
        sn[7] = 0x47;
        sn[8] = 0x43;
        sn[9] = 0;

        printf("Level 001 注册码:%s",sn);
        getchar();

        return 0;
}
2016-3-2 22:44
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
5
Level 003 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为3
00401632   .  C705 04504000>mov     dword ptr ds:[405004], 3

2、确保eax返回时为3
00401659   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、5 <= 用户名长度 <= 0x14
004015E1   .  FFD0          call    eax                              ;  GetUserName
004015E3   .  83F8 05       cmp     eax, 5
004015E6   .  72 78         jb      short 00401660
004015E8   .  83F8 14       cmp     eax, 14
004015EB   .  7F 73         jg      short 00401660

2、把用户名字符串中的小写字母转换为大写
00401621   > /803C19 61     cmp     byte ptr ds:[ecx+ebx], 61
00401625   . |72 04         jb      short 0040162B
00401627   . |802C19 20     sub     byte ptr ds:[ecx+ebx], 20

3、查字符表得到序列号
00401618   .  BF 08504000   mov     edi, 00405008                    ;  ASCII "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| "

00401647   > /2C 41         sub     al, 41
00401649   . |8A0438        mov     al, byte ptr ds:[eax+edi]

keygen:

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char csUserName[21],*pUserName,*pKey;
        char csTable[] = "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ";
        int nTable;

        do
        {
                printf("请输入用户名(5-20个字符):");
                gets_s(csUserName,21);
                pUserName = csUserName;

                nTable = 0;
                while(*pUserName != '\0')
                {
                        nTable ++;
                        if(*pUserName >= 0x61)
                        {
                                *pUserName -= 0x20;
                        }
                        pUserName ++;
                }
        }while(nTable < 5);

        pKey = csUserName;
        while(*pKey != '\0')
        {
                nTable = *pKey - 0x41;
                *pKey = csTable[nTable];
                pKey ++;
        }

        pKey = csUserName;
        printf("注册码:%s",pKey);

        getchar();
        return 0;
}

三、评论
该函数仅演示一种思路,作者随手而写,未认真处理输入,所以该函数存在数组越界问题。比如:用户名中包含数字或者汉字。
2016-3-5 18:37
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
6
Level 004 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为4
0040171F   .  C705 04504000>mov     dword ptr ds:[405004], 4         ;  Case 0 of switch 0040171B

2、确保eax返回时为4
0040175F   .  A1 04504000   mov     eax, dword ptr ds:[405004]       ;  Case 0 of switch 0040175B

二、解
算法描述:
1、5 <= 用户名字符串长度 <= 0x14
00401695   .  83F8 05       cmp     eax, 5
00401698   .  0F82 C8000000 jb      00401766
0040169E   .  83F8 14       cmp     eax, 14
004016A1   .  0F8F BF000000 jg      00401766

2、修正了Level 003 中没有检查输入的问题,限定输入必须是大小写字母
004016ED   > /3C 61         cmp     al, 61
004016EF   . |72 10         jb      short 00401701
004016F1   . |3C 7A         cmp     al, 7A
004016F3   . |77 0C         ja      short 00401701

00401701   > \3C 41         cmp     al, 41                           ;  Default case of switch 0040171B
00401703   .  72 10         jb      short 00401715
00401705   .  3C 5A         cmp     al, 5A
00401707   .  77 0C         ja      short 00401715

3、根据大小写分别查表得到注册码前半部分
004016D8   .  BE 22504000   mov     esi, 00405022                    ;  ASCII "qwertyuioplkjhgfdsazxcvbnm1357908642| "
(1)大写
00401709   .  2C 41         sub     al, 41
0040170B   .  8A0438        mov     al, byte ptr ds:[eax+edi]

(2)小写
004016F5   .  2C 61         sub     al, 61                           
004016F7   .  8A0430        mov     al, byte ptr ds:[eax+esi]

4、再根据大小写分别查表得到注册码后半部分
004016DD   .  BF 08504000   mov     edi, 00405008                    ;  ASCII

"PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| "
(1)大写
00401749   .  2C 41         sub     al, 41
0040174B   .  8A0430        mov     al, byte ptr ds:[eax+esi]

(2)小写
00401735   .  2C 61         sub     al, 61                           
00401737   .  8A0438        mov     al, byte ptr ds:[eax+edi]

keygen:

#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char csUserName[21],*pUserName,csKey[41],*pKey;
        char csTable1[] = "qwertyuioplkjhgfdsazxcvbnm1357908642| ";
        char csTable2[] = "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ";
        int nCount,nTable;

        do
        {
                printf("请输入用户名(5-20个字符,只能是大小写字母):");
                gets_s(csUserName,21);
                pKey = csKey;

                pUserName = csUserName;
                nCount = 0;
                while(*pUserName != '\0')
                {
                        nCount ++;
                        if(*pUserName >= 0x61 && *pUserName <= 0x7a)
                        {
                                nTable = *pUserName - 0x61;
                        }
                        else
                        {
                                if(*pUserName >= 0x41 && *pUserName <= 0x5a)
                                {
                                        nTable = *pUserName - 0x41;
                                }
                                else
                                {
                                        printf("用户名不符合要求,请重新输入\r\n\r\n");
                                        nCount = 0;
                                        break;
                                }
                        }
                        *pKey = csTable1[nTable];
                        pUserName ++;
                        pKey ++;
                }
        }while(nCount < 5);

        nCount = 0;
        while(csUserName[nCount] != '\0')
        {
                if(csUserName[nCount] >= 0x61)
                {
                        nTable = csUserName[nCount] - 0x61;
                }
                else
                {
                        nTable = csUserName[nCount] - 0x41;               
                }
                *pKey = csTable2[nTable];
                nCount ++;
                pKey ++;
        }
        *pKey = '\0';
        printf("注册码:%s",csKey);

        getchar();
        return 0;
}
2016-3-5 22:05
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
7
Level 005 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为5
004017E3   .  C705 04504000>mov     dword ptr ds:[405004], 5

2、确保eax返回时为5
0040182E   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、5 <= 用户名字符串长度 <= 0x14
00401695   .  83F8 05       cmp     eax, 5
00401698   .  0F82 C8000000 jb      00401766
0040169E   .  83F8 14       cmp     eax, 14
004016A1   .  0F8F BF000000 jg      00401766

2、转换字符值大于0x61的字符(又未考虑输入汉字等非预期情况)
004017F1   > /803C19 61     cmp     byte ptr ds:[ecx+ebx], 61
004017F5   . |72 04         jb      short 004017FB
004017F7   . |803419 20     xor     byte ptr ds:[ecx+ebx], 20

3、根据转换完毕的字符查表取索引值
004017D9   .  BE 08504000   mov     esi, 00405008                    ;  ASCII "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| "

00401810   > /3A0431        cmp     al, byte ptr ds:[ecx+esi]
00401813   . |74 07         je      short 0040181C

4、查表得到注册码
004017DE   .  BF 22504000   mov     edi, 00405022                    ;  ASCII "qwertyuioplkjhgfdsazxcvbnm1357908642| "

0040181C   > \8A4439 F3     mov     al, byte ptr ds:[ecx+edi-D]

keygen:
#include "stdafx.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char csUserName[21],*pUserName,csKey[41],*pTempTable;
        char csTable1[] = "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ";
        char *pTable2 = &csTable1[26];

        int nCount,nTable;

        do
        {
                printf("请输入用户名(5-20个字符):");
                gets_s(csUserName,21);

                pUserName = csUserName;
                nCount = 0;
                while(*pUserName != '\0')
                {
                        nCount ++;
                        if(*pUserName >= 0x61)
                        {
                                *pUserName ^= 0x20;
                        }
                        pUserName ++;
                }
                if(nCount < 5)
                {
                        printf("用户名不符合要求,请重新输入\r\n\r\n");
                }
        }while(nCount < 5);

        nCount = 0;
        pTable2 -= 0xd;
        while(csUserName[nCount] != '\0')
        {
                pTempTable = pTable2;
                nTable = 0;
                while(csTable1[nTable] != '\0')
                {
                        if(csUserName[nCount] == csTable1[nTable])
                        {
                                pTempTable += nTable;
                                csKey[nCount] = *pTempTable;
                                break;
                        }
                        nTable ++;
                }
                nCount ++;
        }
        csKey[nCount] = '\0';
        printf("注册码:%s",csKey);

        getchar();
        return 0;
}
2016-3-11 16:07
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
8
Level 006 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为6
00401952   .  C705 04504000>mov     dword ptr ds:[405004], 6

2、确保eax返回时为5
0040182E   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、用户名字符串长度 >= 5
00401865   .  FFD0          call    eax
00401867   .  83F8 05       cmp     eax, 5
0040186A   .  0F82 14010000 jb      00401984

2、公司名字符串长度 >= 1
00401890   .  FFD0          call    eax
00401892   .  83F8 01       cmp     eax, 1
00401895   .  0F82 E9000000 jb      00401984

3、注册码字符串长度 >= 0xa
004018BB   .  FFD0          call    eax
004018BD   .  83F8 0A       cmp     eax, 0A
004018C0   .  0F82 BE000000 jb      00401984

4、注册码分析:
(1)第一个子符 = 0x4d - 3
004018C6   .  8D5D A0       lea     ebx, dword ptr ss:[ebp-60]
004018C9   .  8A03          mov     al, byte ptr ds:[ebx]
004018CB   .  04 03         add     al, 3
004018CD   .  3C 4D         cmp     al, 4D
004018CF   .  74 0A         je      short 004018DB

(2)第二个字符 = 0x69
004018DB   > \8A43 01       mov     al, byte ptr ds:[ebx+1]
004018DE   .  34 69         xor     al, 69
004018E0   .  74 0D         je      short 004018EF

(3)第三个字符 = 0x4d + 3
004018EF   > \8A43 02       mov     al, byte ptr ds:[ebx+2]
004018F2   .  2C 03         sub     al, 3
004018F4   .  3C 4D         cmp     al, 4D
004018F6   .  74 0D         je      short 00401905

(4)第四个字符 = (company[0] & 6) + username[0]
00401905   > \8D75 E0       lea     esi, dword ptr ss:[ebp-20]
00401908   .  8D7D C0       lea     edi, dword ptr ss:[ebp-40]
0040190B   .  8A27          mov     ah, byte ptr ds:[edi]
0040190D   .  80E4 06       and     ah, 6
00401910   .  8A06          mov     al, byte ptr ds:[esi]
00401912   .  02C4          add     al, ah
00401914   .  2A43 03       sub     al, byte ptr ds:[ebx+3]
00401917   .  75 6B         jnz     short 00401984

(5)第五个字符 = (username[0] & 9) + company[0]
00401919   .  8A26          mov     ah, byte ptr ds:[esi]
0040191B   .  80E4 09       and     ah, 9
0040191E   .  8A07          mov     al, byte ptr ds:[edi]
00401920   .  02C4          add     al, ah
00401922   .  2A43 04       sub     al, byte ptr ds:[ebx+4]
00401925   .  75 5D         jnz     short 00401984

(6)第六、七、八、九个字符 = 任意字符,
第十、十一、十二、十三个字符 =  (dword(username0123) ^ dword(sn6789) & 0x9070503) + dword(username0123)
00401927   .  8B43 05       mov     eax, dword ptr ds:[ebx+5]
0040192A   .  8B16          mov     edx, dword ptr ds:[esi]
0040192C   .  33D0          xor     edx, eax
0040192E   .  81E2 03050709 and     edx, 9070503
00401934   .  0316          add     edx, dword ptr ds:[esi]
00401936   .  8B43 09       mov     eax, dword ptr ds:[ebx+9]
00401939   .  2BC2          sub     eax, edx
0040193B   .^ 75 C6         jnz     short 00401903

5、转换用户名字符串中大于等于0x61的字符,username[x] &= 0xdf
00401941   > /803C31 61     cmp     byte ptr ds:[ecx+esi], 61
00401945   . |72 04         jb      short 0040194B
00401947   . |802431 DF     and     byte ptr ds:[ecx+esi], 0DF

6、查表得到后面的注册码
0040195C   .  BF 11504000   mov     edi, 00405011                    ;  ASCII "HUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| "

00401969   > /2C 3D         sub     al, 3D
0040196B   . |8A0438        mov     al, byte ptr ds:[eax+edi]
0040196E   . |3A4419 0D     cmp     al, byte ptr ds:[ecx+ebx+D]
00401972   . |75 10         jnz     short 00401984

kengen:
#include "stdafx.h"
#include "stdLib.h"
#include "time.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char csUserName[21],*pUserName,csKey[41],csUserName1[21],csCompany[16];
        char csTable[] = "HUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ";
        char *pKey;

        int nCount,nTable;

        do
        {
                printf("请输入用户名(5个字符以上):");
                gets_s(csUserName,21);

                pUserName = csUserName;
                nCount = 0;
                while(*pUserName != '\0')
                {
                        if(*pUserName >= 0x61)
                        {
                                csUserName1[nCount] = *pUserName & 0xdf;
                        }
                        nCount ++;
                        pUserName ++;
                }
                csUserName1[nCount] = '\0';
                if(nCount < 5)
                {
                        printf("用户名不符合要求,请重新输入\r\n\r\n");
                }
        }while(nCount < 5);

        csKey[0] = 0x4d - 3;
        csKey[1] = 0x69;
        csKey[2] = 0x4d + 3;

        do
        {
                printf("请输入公司名称:");
                gets_s(csCompany,16);
                if(csCompany[0] != '\0')
                {
                        csKey[3] = (csCompany[0] & 6) + csUserName[0];
                        csKey[4] = (csUserName[0] & 9) + csCompany[0];
                        break;
                }
                else
                {
                        printf("公司名称不符合要求,请重新输入\r\n\r\n");
                }
        }while(nCount);

        srand((unsigned int)time(NULL));
        csKey[5] = rand() % 90 + 0x21;
        csKey[6] = rand() % 90 + 0x21;
        csKey[7] = rand() % 90 + 0x21;
        csKey[8] = rand() % 90 + 0x21;
        _asm
        {
                lea esi,csUserName
                lea ebx,csKey
                mov eax,[ebx+5]
                mov edx,[esi]
                xor edx,eax
                and edx,0x9070503
                add edx,[esi]
                mov [ebx+9],edx
        }
        nCount = 0;
        while(csUserName1[nCount] != '\0')
        {
                nTable = csUserName1[nCount] - 0x3d;
                csKey[nCount+0xd] = csTable[nTable];
                nCount ++;
        }
        csKey[nCount+0xd] = '\0';
        printf("注册码:%s",csKey);

        getchar();
        return 0;
}
2016-3-11 23:35
0
雪    币: 58782
活跃值: (21926)
能力值: (RANK:350 )
在线值:
发帖
回帖
粉丝
9
水平不错,欢迎加入看雪论坛
2016-3-12 20:00
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
10
过奖啦!谢谢!
2016-3-16 15:25
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
11
Level 007 :
一、破
作者在防简单爆破上下了功夫,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为7
00401A14   .  C705 04504000>mov     dword ptr ds:[405004], 7

2、确保eax返回时为7
00401A3D   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、序列号字符串长度 >= 0x10
004019B0   .  83F8 10       cmp     eax, 10
004019B3   .  0F82 8B000000 jb      00401A44

2、公司名字符串长度 >= 5
004019E8   .  83F8 05       cmp     eax, 5
004019EB   .  72 57         jb      short 00401A44

3、用户名字符串长度 >= 5
00401A0F   .  83F8 05       cmp     eax, 5
00401A12   .  72 30         jb      short 00401A44

4、加密序列号
004019B9   .  8D45 AD       lea     eax, dword ptr ss:[ebp-53]
004019BC   .  50            push    eax
004019BD   .  8D45 DF       lea     eax, dword ptr ss:[ebp-21]       ;  sn
004019C0   .  50            push    eax
004019C1   .  E8 57F9FFFF   call    0040131D

5、合成的序列号
00401A1E   .  8D45 CE       lea     eax, dword ptr ss:[ebp-32]       ;  company
00401A21   .  50            push    eax
00401A22   .  8D45 DF       lea     eax, dword ptr ss:[ebp-21]       ;  username
00401A25   .  50            push    eax
00401A26   .  E8 83F7FFFF   call    004011AE                         ;  strcat

6、验证序列号
00401A2B   .  8D45 AD       lea     eax, dword ptr ss:[ebp-53]
00401A2E   .  50            push    eax
00401A2F   .  8D45 DF       lea     eax, dword ptr ss:[ebp-21]
00401A32   .  50            push    eax
00401A33   .  E8 0EF7FFFF   call    00401146                         ;  strcmp

7、关键加密函数CR-Game0.83.0040131D解析
(1)每四个字符一组
(2)每个字符用CR-Game0.83.00401210函数进行加密转换
0040134A   > \8A17          mov     dl, byte ptr ds:[edi]
0040134C   .  52            push    edx
0040134D   .  E8 BEFEFFFF   call    00401210
(3)遇字符0x3d忽略后面字符结束加密序列号
00401388   .  807F 02 3D    cmp     byte ptr ds:[edi+2], 3D

(4)保存结果
00401357   .  8BC8          mov     ecx, eax
00401364   > \C1E1 06       shl     ecx, 6
004013A1   .  03C8          add     ecx, eax

8、加密函数CR-Game0.83.00401210解析
查表获得索引值
00401215   .  8D05 08504000 lea     eax, dword ptr ds:[405008]
Address=00405008, (ASCII "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ")

0040121B   .  8BD8          mov     ebx, eax
0040121D   .  8B4D 08       mov     ecx, dword ptr ss:[ebp+8]
00401220   >  803B 00       cmp     byte ptr ds:[ebx], 0
00401223   .  75 0D         jnz     short 00401232
00401232   > \380B          cmp     byte ptr ds:[ebx], cl
00401234   .  75 0A         jnz     short 00401240

keygen:

#include "stdafx.h"
#include "stdLib.h"
#include "time.h"
#include "string.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char csUserName[21],csKey[256],csTemp[256],csCompany[48];
        char csTable[] = "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ";
        char *pKey,*pKeyTemp;
        unsigned long ltemp;
        int nCount,nTable;

        do
        {
                printf("请输入用户名(5个字符以上):");
                gets_s(csUserName,21);

                nCount = strlen(csUserName);
                if(nCount >= 5)
                {
                        break;
                }
                printf("用户名不符合要求,请重新输入\r\n\r\n");
        }while(true);

        do
        {
                printf("请输入公司名称(5个字符以上):");
                gets_s(csCompany,48);
                nCount = strlen(csCompany);
                if(nCount >= 5)
                {
                        break;
                }
                printf("公司名称不符合要求,请重新输入\r\n\r\n");
        }while(true);

        strcpy(csTemp,csUserName);
        strcat(csTemp,csCompany);

        pKey = csKey;
        pKeyTemp = csTemp;
        do
        {
                ltemp = 0;
                for(int i = 0; i < 3; i++)
                {
                        if(*pKeyTemp == '\0')
                        {
                                do
                                {
                                        ltemp = ltemp << 8;
                                        i ++;
                                }while(i < 3);
                                break;
                        }
                        ltemp += *pKeyTemp;
                        ltemp = ltemp << 8;
                        pKeyTemp ++;
                }
                ltemp = ltemp >> 8;
                nTable =  (ltemp & 0xfc0000) >> 18;
                *pKey = csTable[nTable];
                pKey ++;
                nTable = (ltemp & 0x3f000) >> 12;
                *pKey = csTable[nTable];
                pKey ++;
                nTable = (ltemp & 0xfc0) >> 6;
                *pKey = csTable[nTable];
                pKey ++;
                nTable = ltemp & 0x3f;
                *pKey = csTable[nTable];
                pKey ++;

        }while(*pKeyTemp != '\0');

        *pKey = '\0';
        printf("注册码:%s",csKey);

        getchar();
        return 0;
}
2016-3-17 14:36
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
12
请管理员帮忙把我注册用的邮箱改为:wenbuxiu@139.com。原邮箱丢失,本站登陆密码忘了,无法自己更改。谢谢!

Level 008 :
一、破
又见反调试:
00402522   .  68 2B254000   push    0040252B                         ;  ASCII "OLLYDBG"
00402541   .  FFD0          call    eax                              ;  <jmp.&user32.FindWindowA>
00402543   .  83F8 00       cmp     eax, 0
00402546   .^ 0F85 92FCFFFF jnz     004021DE                        ;建议爆破点

作者在防简单爆破上下了功夫,加了简单的干扰字节,故意打乱代码顺序。但只要掌握两点仍然随意爆破。
1、确保验证标志变量赋值为8
00401BDB   > \C705 04504000>mov     dword ptr ds:[405004], 8

2、确保eax返回时为8
00401C5A   .  A1 04504000   mov     eax, dword ptr ds:[405004]

二、解
算法描述:
1、公司名字符串长度 >= 5
00401A7F   .  83F8 05             cmp     eax, 5
00401A82   .  0F82 D9010000       jb      00401C61

2、系统当前用户名
00401AA8   .  FFD0                call    eax                              ;  GetSystemUserName

2、用户名字符串长度 >= 5
00401ADC   .  83F8 05             cmp     eax, 5
00401ADF   .  0F82 7C010000       jb      00401C61

3、系统当前用户名、用户输入用户名合成新用户名1
00401AE5   .  8D45 80             lea     eax, dword ptr ss:[ebp-80]
00401AE8   .  50                  push    eax
00401AE9   .  8D85 00FFFFFF       lea     eax, dword ptr ss:[ebp-100]
00401AEF   .  50                  push    eax
00401AF0   .  E8 B9F6FFFF         call    004011AE                         ;  strcat

4、新用户名查表转换得到新用户名2
Address=00405008, (ASCII "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ")
00401AF5   .  8DB5 00FFFFFF       lea     esi, dword ptr ss:[ebp-100]
00401AFB   .  8D3D 08504000       lea     edi, dword ptr ds:[405008]
00401B01   .  33C0                xor     eax, eax
00401B03   .  33C9                xor     ecx, ecx
00401B05   .  8A06                mov     al, byte ptr ds:[esi]

00401B11   .  8A2439              mov     ah, byte ptr ds:[ecx+edi]
00401B14   >  38E0                cmp     al, ah
00401B16   .  74 04               je      short 00401B1C

以索引0x1a为界
00401B1C   > \83F9 1A             cmp     ecx, 1A
00401B1F   .  77 06               ja      short 00401B27
00401B21   .  8A4439 1A           mov     al, byte ptr ds:[ecx+edi+1A]
00401B25   . /EB 04               jmp     short 00401B2B
00401B27   > |8A4439 E6           mov     al, byte ptr ds:[ecx+edi-1A]

5、新用户名2、程序作者网名合成新用户名3
00401B4C   .  4A 69 50 00         ascii   "JiP",0
00401B50   >  68 4C1B4000         push    00401B4C                         ;  ASCII "JiP"
00401B55   .  8D85 00FFFFFF       lea     eax, dword ptr ss:[ebp-100]
00401B5B   .  50                  push    eax
00401B5C   .  E8 29F6FFFF         call    0040118A                         ;  strcpy
00401B61   .  8D85 00FEFFFF       lea     eax, dword ptr ss:[ebp-200]
00401B67   .  50                  push    eax
00401B68   .  8D85 00FFFFFF       lea     eax, dword ptr ss:[ebp-100]
00401B6E   .  50                  push    eax
00401B6F   .  E8 3AF6FFFF         call    004011AE                         ;  strcat

6、新用户名3限长0x20,不足取用户输入用户名补充,超出截断。

7、要求输入的序列号长度 >= 0x10
00401C08   .  FFD0                call    eax                              ;  getsn
00401C0A   .  83F8 10             cmp     eax, 10
00401C0D   .  72 52               jb      short 00401C61

8、改动转换表
00401C20   .  6A 20         push    20                               ; /Arg2 = 00000020
00401C22   .  6A 0C         push    0C                               ; |Arg1 = 0000000C
00401C24   .  E8 B2F5FFFF   call    004011DB                         ; \CR-Game0.004011DB
Address=00405008, (ASCII "PLMKOIJNBHUYTRDXGVCFQAqwZSEWuiopertylkjhgfdsazxcvbnm1357908642| ")

9、转换序列号
00401C29   .  8D85 00FEFFFF lea     eax, dword ptr ss:[ebp-200]
00401C2F   .  50            push    eax
00401C30   .  8D45 80       lea     eax, dword ptr ss:[ebp-80]
00401C33   .  50            push    eax
00401C34   .  E8 E4F6FFFF   call    0040131D       ;该函数在上关已经解析过,本次不在赘述

10、还原转换表(掩耳盗铃)
00401C39   .  6A 20         push    20                               ; /Arg2 = 00000020
00401C3B   .  6A 0C         push    0C                               ; |Arg1 = 0000000C
00401C3D   .  E8 99F5FFFF   call    004011DB                         ; \CR-Game0.004011DB

11、比较转换序列号和新用户名3
00401C42   .  8D85 00FEFFFF lea     eax, dword ptr ss:[ebp-200]
00401C48   .  50            push    eax
00401C49   .  8D85 00FFFFFF lea     eax, dword ptr ss:[ebp-100]
00401C4F   .  50            push    eax
00401C50   .  E8 F1F4FFFF   call    00401146                         ;  strcmp

keygen:

#include "stdafx.h"
#include "stdLib.h"
#include "time.h"
#include "string.h"
#include "windows.h"

int _tmain(int argc, _TCHAR* argv[])
{
        char csUserName[21],csKey[256],csTemp[256],csCompany[48];
        char csTable[] = "PLMKOIJNBHUYGVCFTRDXZSEWQAqwertyuioplkjhgfdsazxcvbnm1357908642| ";
        char csTable1[] = "PLMKOIJNBHUYTRDXGVCFQAqwZSEWuiopertylkjhgfdsazxcvbnm1357908642| ";
        char *pKey,*pKeyTemp;
        unsigned long ltemp;
        int nCount,nTable;
        DWORD dwsize;

        do
        {
                printf("请输入用户名(5个字符以上):");
                gets_s(csUserName,21);

                nCount = strlen(csUserName);
                if(nCount >= 5)
                {
                        break;
                }
                printf("用户名不符合要求,请重新输入\r\n\r\n");
        }while(true);

        do
        {
                printf("请输入公司名称(5个字符以上):");
                gets_s(csCompany,48);
                nCount = strlen(csCompany);
                if(nCount >= 5)
                {
                        break;
                }
                printf("公司名称不符合要求,请重新输入\r\n\r\n");
        }while(true);

        dwsize = 48;
        GetUserNameA((char*)csCompany,&dwsize);
        strcat(csCompany,csUserName);
        nCount = 0;
        while(csCompany[nCount] != '\0')
        {
                nTable = 0;
                while(csTable[nTable] != '\0')
                {
                        if(csCompany[nCount] == csTable[nTable])
                        {
                                if(nTable > 0x1a)
                                {
                                        csCompany[nCount] = csTable[nTable - 0x1a];
                                }
                                else
                                {
                                        csCompany[nCount] = csTable[nTable + 0x1a];
                                }
                                break;
                        }
                        nTable ++;
                }
                nCount ++;
        }
        strcpy(csTemp,"JiP");
        strcat(csTemp,csCompany);
        dwsize = strlen(csTemp);
        if(dwsize < 0x20)
        {
                strcat(csTemp,csUserName);
        }
        csTemp[0x20] = '\0';

        pKey = csKey;
        pKeyTemp = csTemp;
        do
        {
                ltemp = 0;
                for(int i = 0; i < 3; i++)
                {
                        if(*pKeyTemp == '\0')
                        {
                                do
                                {
                                        ltemp = ltemp << 8;
                                        i ++;
                                }while(i < 3);
                                break;
                        }
                        ltemp += *pKeyTemp;
                        ltemp = ltemp << 8;
                        pKeyTemp ++;
                }
                ltemp = ltemp >> 8;
                nTable =  (ltemp & 0xfc0000) >> 18;
                *pKey = csTable1[nTable];
                pKey ++;
                nTable = (ltemp & 0x3f000) >> 12;
                *pKey = csTable1[nTable];
                pKey ++;
                nTable = (ltemp & 0xfc0) >> 6;
                *pKey = csTable1[nTable];
                pKey ++;
                nTable = ltemp & 0x3f;
                *pKey = csTable1[nTable];
                pKey ++;

        }while(*pKeyTemp != '\0');

        *pKey = '\0';
        printf("注册码:%s",csKey);

        getchar();
        return 0;
}
2016-3-20 20:42
0
雪    币: 106
活跃值: (25)
能力值: ( LV4,RANK:50 )
在线值:
发帖
回帖
粉丝
13
本程序尚有疑问求解:
      作者为增加难度,特意使用地址调用如下:
0040214A   > \B8 90304000   mov     eax, 00403090
0040214F   .  83E8 04       sub     eax, 4
0040216C   > \FFD0          call    eax

我的问题是:作者怎么能在程序一开始就能确定该地址处是期望的调用呢?
2016-3-20 20:59
0
游客
登录 | 注册 方可回帖
返回