160个破解练习之CrackMe 004 CKme

程序的界面如下:

160个破解练习之CrackMe 004 CKme_第1张图片


        比较郁闷的是,不管我怎么点击它,就是没有任何反应,也就是说在注册码输入错误的情况下是没有任何反应的。通过查壳发现是Delphi程序,没有壳,由于对Delphi不了解,先打开OD搜索关键字,看有没有突破

       通过智能搜索,得到了一个“注册成功”字符串,定位到此处:

00458031  |.  81BE 0C030000>cmp dword ptr ds:[esi+0x30C],0x85
0045803B  |.  75 76         jnz short CKme.004580B3                  ;  关键跳,不能跳
0045803D  |.  33DB          xor ebx,ebx
0045803F  |>  8D55 E4       /lea edx,[local.7]
00458042  |.  8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
00458048  |.  E8 FBB2FCFF   |call CKme.00423348
0045804D  |.  8B45 E4       |mov eax,[local.7]
00458050  |.  E8 27BBFAFF   |call CKme.00403B7C
00458055  |.  83C0 03       |add eax,0x3
00458058  |.  8D55 E8       |lea edx,[local.6]
0045805B  |.  E8 A4FAFAFF   |call CKme.00407B04
00458060  |.  FF75 E8       |push [local.6]
00458063  |.  8D55 E0       |lea edx,[local.8]
00458066  |.  8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
0045806C  |.  E8 D7B2FCFF   |call CKme.00423348
00458071  |.  FF75 E0       |push [local.8]
00458074  |.  8D55 DC       |lea edx,[local.9]
00458077  |.  8BC3          |mov eax,ebx
00458079  |.  E8 86FAFAFF   |call CKme.00407B04
0045807E  |.  FF75 DC       |push [local.9]
00458081  |.  8D45 FC       |lea eax,[local.1]
00458084  |.  BA 03000000   |mov edx,0x3
00458089  |.  E8 AEBBFAFF   |call CKme.00403C3C
0045808E  |.  43            |inc ebx
0045808F  |.  83FB 13       |cmp ebx,0x13
00458092  |.^ 75 AB         \jnz short CKme.0045803F
00458094  |.  33D2          xor edx,edx                              ;  CKme.
00458096  |.  8B86 F0020000 mov eax,dword ptr ds:[esi+0x2F0]
0045809C  |.  E8 BFB1FCFF   call CKme.00423260
004580A1  |.  A1 20B84500   mov eax,dword ptr ds:[0x45B820]
004580A6  |.  83C0 70       add eax,0x70
004580A9  |.  BA 14814500   mov edx,CKme.00458114                    ;  恭喜恭喜!注册成功
004580AE  |.  E8 9DB8FAFF   call CKme.00403950


        从这里的代码可以看出,在上面有一个关键跳,此处的跳转可以进行爆破。接下来的分析就无从下手了,怎么点击程序都没反应,也不断下。几经泽腾,发现有DarkDe这款软件可以专门针对Delphi程序进行反汇编,可以看到程序的事件调用,因此下载后分析如下:


160个破解练习之CrackMe 004 CKme_第2张图片


       在过程选项中,发现程序有五个事件,第一个窗体创建与输入的字符应该无关,而后面的键盘按键放下、面板单击和面板双击、还有检查密码,应该就和用户名/注册码的获取和检测有关了,还可以看到“注册成功”的代码段就是面板单击事件中。通过测试发现,KeyUp事件是为了获取输入的用户名,chkcode事件是为了获取输入的注册码并检测我们对这个四个事件下断点,当输入注册码时断在了此处:

00457C40  /.  55            push ebp
00457C41  |.  8BEC          mov ebp,esp
00457C43  |.  51            push ecx
00457C44  |.  B9 05000000   mov ecx,0x5
00457C49  |>  6A 00         /push 0x0
00457C4B  |.  6A 00         |push 0x0
00457C4D  |.  49            |dec ecx
00457C4E  |.^ 75 F9         \jnz short CKme.00457C49
00457C50  |.  51            push ecx
00457C51  |.  874D FC       xchg [local.1],ecx
00457C54  |.  53            push ebx
00457C55  |.  56            push esi
00457C56  |.  8BD8          mov ebx,eax
00457C58  |.  33C0          xor eax,eax
00457C5A  |.  55            push ebp
00457C5B  |.  68 3D7E4500   push CKme.00457E3D
00457C60  |.  64:FF30       push dword ptr fs:[eax]
00457C63  |.  64:8920       mov dword ptr fs:[eax],esp
00457C66  |.  8BB3 F8020000 mov esi,dword ptr ds:[ebx+0x2F8]
00457C6C  |.  83C6 05       add esi,0x5
00457C6F  |.  FFB3 10030000 push dword ptr ds:[ebx+0x310]            ;  黑头Sun Bird
00457C75  |.  8D55 F8       lea edx,[local.2]
00457C78  |.  8BC6          mov eax,esi
00457C7A  |.  E8 85FEFAFF   call CKme.00407B04                       ;  整数转字符串
00457C7F  |.  FF75 F8       push [local.2]                           ;  字符串长度+5
00457C82  |.  FFB3 14030000 push dword ptr ds:[ebx+0x314]            ;  dseloffc-012-OK
00457C88  |.  8D55 F4       lea edx,[local.3]
00457C8B  |.  8B83 D4020000 mov eax,dword ptr ds:[ebx+0x2D4]
00457C91  |.  E8 B2B6FCFF   call CKme.00423348
00457C96  |.  FF75 F4       push [local.3]                           ;  输入的用户名
00457C99  |.  8D83 18030000 lea eax,dword ptr ds:[ebx+0x318]
00457C9F  |.  BA 04000000   mov edx,0x4
00457CA4  |.  E8 93BFFAFF   call CKme.00403C3C
00457CA9  |.  33D2          xor edx,edx
00457CAB  |.  8B83 F4020000 mov eax,dword ptr ds:[ebx+0x2F4]
00457CB1  |.  E8 AAB5FCFF   call CKme.00423260
00457CB6  |.  8B93 18030000 mov edx,dword ptr ds:[ebx+0x318]         ;  疑似正确的序列号
00457CBC  |.  8B83 F4020000 mov eax,dword ptr ds:[ebx+0x2F4]
00457CC2  |.  E8 B1B6FCFF   call CKme.00423378
00457CC7  |.  33F6          xor esi,esi
00457CC9  |>  8D55 EC       /lea edx,[local.5]
00457CCC  |.  8B83 D4020000 |mov eax,dword ptr ds:[ebx+0x2D4]
00457CD2  |.  E8 71B6FCFF   |call CKme.00423348
00457CD7  |.  8B45 EC       |mov eax,[local.5]                       ;  输入的用户名
00457CDA  |.  E8 9DBEFAFF   |call CKme.00403B7C
00457CDF  |.  83C0 03       |add eax,0x3
00457CE2  |.  8D55 F0       |lea edx,[local.4]
00457CE5  |.  E8 1AFEFAFF   |call CKme.00407B04
00457CEA  |.  FF75 F0       |push [local.4]
00457CED  |.  8D55 E8       |lea edx,[local.6]
00457CF0  |.  8B83 D4020000 |mov eax,dword ptr ds:[ebx+0x2D4]
00457CF6  |.  E8 4DB6FCFF   |call CKme.00423348
00457CFB  |.  FF75 E8       |push [local.6]
00457CFE  |.  8D55 E4       |lea edx,[local.7]
00457D01  |.  8BC6          |mov eax,esi
00457D03  |.  E8 FCFDFAFF   |call CKme.00407B04
00457D08  |.  FF75 E4       |push [local.7]
00457D0B  |.  8D45 FC       |lea eax,[local.1]
00457D0E  |.  BA 03000000   |mov edx,0x3
00457D13  |.  E8 24BFFAFF   |call CKme.00403C3C
00457D18  |.  46            |inc esi
00457D19  |.  83FE 13       |cmp esi,0x13
00457D1C  |.^ 75 AB         \jnz short CKme.00457CC9
00457D1E  |.  8D55 E0       lea edx,[local.8]
00457D21  |.  8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]         ;  CKme.004428F8
00457D27  |.  E8 1CB6FCFF   call CKme.00423348
00457D2C  |.  8B45 E0       mov eax,[local.8]                        ;  输入的序列号
00457D2F  |.  8B93 18030000 mov edx,dword ptr ds:[ebx+0x318]         ;  正确的序列号
00457D35  |.  E8 52BFFAFF   call CKme.00403C8C                       ;  比较
00457D3A  |.  75 0A         jnz short CKme.00457D46



这段代码获取了用户输入的用户名、序列号,以及生成了一个待比较的序列号如下:


160个破解练习之CrackMe 004 CKme_第3张图片


然后返回来看最开始的“注册成功”的地方:

00458021  |.  BA 03000000   |mov edx,0x3
00458026  |.  E8 11BCFAFF   |call CKme.00403C3C
0045802B  |.  43            |inc ebx
0045802C  |.  83FB 13       |cmp ebx,0x13
0045802F  |.^ 75 AB         \jnz short CKme.00457FDC
00458031  |.  81BE 0C030000>cmp dword ptr ds:[esi+0x30C],0x85
0045803B  |.  75 76         jnz short CKme.004580B3                  ;  关键跳,不能跳
0045803D  |.  33DB          xor ebx,ebx
0045803F  |>  8D55 E4       /lea edx,[local.7]
00458042  |.  8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
00458048  |.  E8 FBB2FCFF   |call CKme.00423348
0045804D  |.  8B45 E4       |mov eax,[local.7]
00458050  |.  E8 27BBFAFF   |call CKme.00403B7C


      这里的关键跳的比较条件是地址 [esi+0x30c] 和 0x85比较,从chkcode事件的代码中可以看到,如果输入的序列号正确,则往地址  [esi+0x30c] 中写入 0x3E 。

接着来看面板双击事件代码如下:

00457E7C  /.  55            push ebp
00457E7D  |.  8BEC          mov ebp,esp
00457E7F  |.  B9 04000000   mov ecx,0x4
00457E84  |>  6A 00         /push 0x0
00457E86  |.  6A 00         |push 0x0
00457E88  |.  49            |dec ecx                                 ;  wow64cpu.776E2AD2
00457E89  |.^ 75 F9         \jnz short CKme.00457E84
00457E8B  |.  51            push ecx                                 ;  wow64cpu.776E2AD2
00457E8C  |.  53            push ebx
00457E8D  |.  56            push esi
00457E8E  |.  8BF0          mov esi,eax
00457E90  |.  33C0          xor eax,eax
00457E92  |.  55            push ebp
00457E93  |.  68 A97F4500   push CKme.00457FA9
00457E98  |.  64:FF30       push dword ptr fs:[eax]
00457E9B  |.  64:8920       mov dword ptr fs:[eax],esp
00457E9E  |.  33DB          xor ebx,ebx
00457EA0  |>  8D55 F4       /lea edx,[local.3]
00457EA3  |.  8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
00457EA9  |.  E8 9AB4FCFF   |call CKme.00423348
00457EAE  |.  8B45 F4       |mov eax,[local.3]                       ;  用户名
00457EB1  |.  E8 C6BCFAFF   |call CKme.00403B7C
00457EB6  |.  83C0 09       |add eax,0x9
00457EB9  |.  8D55 F8       |lea edx,[local.2]
00457EBC  |.  E8 43FCFAFF   |call CKme.00407B04
00457EC1  |.  FF75 F8       |push [local.2]
00457EC4  |.  8D55 F0       |lea edx,[local.4]
00457EC7  |.  8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
00457ECD  |.  E8 76B4FCFF   |call CKme.00423348
00457ED2  |.  FF75 F0       |push [local.4]
00457ED5  |.  8D55 EC       |lea edx,[local.5]
00457ED8  |.  8BC3          |mov eax,ebx
00457EDA  |.  E8 25FCFAFF   |call CKme.00407B04
00457EDF  |.  FF75 EC       |push [local.5]                          ;  CKme.0040D6BD
00457EE2  |.  8D45 FC       |lea eax,[local.1]
00457EE5  |.  BA 03000000   |mov edx,0x3
00457EEA  |.  E8 4DBDFAFF   |call CKme.00403C3C
00457EEF  |.  43            |inc ebx
00457EF0  |.  83FB 13       |cmp ebx,0x13
00457EF3  |.^ 75 AB         \jnz short CKme.00457EA0
00457EF5  |.  83BE 0C030000>cmp dword ptr ds:[esi+0x30C],0x3E
00457EFC  |.  75 0A         jnz short CKme.00457F08
00457EFE  |.  C786 0C030000>mov dword ptr ds:[esi+0x30C],0x85
00457F08  |>  33DB          xor ebx,ebx
00457F0A  |>  8D55 E4       /lea edx,[local.7]


可以看到在代码的后面,有将地址 [esi+0x3C] 与 0x3E比较,如果相等则写入 0x85那么,现在思路清晰了:

       每次输入用户名的时候,事件KeyUp都会获取用户输入的字符,并保存起来,并获取输入的用户名的长度保存起来,每次输入序列号的时候,事件chkcode都会获取输入的字符并保存起来,在生成正确的字符串(正确的序列号时代码中出现字符串的拼接)并与之对比,如果正确,就向地址[esi+0x3C] 中写入 0x3E。

       在面板双击事件中会检测地址[esi+0x3C] 的值是否为0x3E,是的话就向地址[esi+0x3C] 写入0x85 ,在面板单击事件中检测地址[esi+0x3C] 的值是否为0x85是的话顺序执行到注册成功处,否则跳过注册成功。





你可能感兴趣的:(逆向破解练习)