首页 > 代码库 > [反汇编练习] 160个CrackMe之029

[反汇编练习] 160个CrackMe之029

[反汇编练习] 160个CrackMe之029.

本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将160个CrackMe全部破解,如果可以,通过任何方式写出一个类似于注册机的东西。

其中,文章中按照如下逻辑编排(解决如下问题):

1、使用什么环境和工具

2、程序分析

3、思路分析和破解流程

4、注册机的探索

----------------------------------

提醒各位看客: 如果文章中的逻辑看不明白,那你一定是没有亲手操刀!OD中的跳转提示很强大,只要你跟踪了,不用怎么看代码就理解了!

----------------------------------

1、工具和环境:

WinXP SP3 + 52Pojie六周年纪念版OD + PEID + 汇编金手指。

160个CrackMe的打包文件。

下载地址: http://pan.baidu.com/s/1xUWOY 密码: jbnq

注:

1、Win7系统对于模块和程序开启了随机初始地址的功能,会给分析带来很大的负担,所以不建议使用Win7进行分析。

2、以上工具都是在52PoJie论坛下的原版程序,NOD32不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。

wps_clip_image-880

2、程序分析:

想要破解一个程序,必须先了解这个程序。所以,在破解过程中,对最初程序的分析很重要,他可以帮助我们理解作者的目的和意图,特别是对于注册码的处理细节,从而方便我们反向跟踪和推导。

和上一节一样,打开CHM,选择第29个CoSH.2.exe,保存下来。运行程序,程序界面如下:

0

点击上面的Check按钮,弹出了信息框,很好。

注意的是,点击确定按钮后,程序直接退出了。

PEID:Microsoft Visual C++ 6.0

哈哈哈,VC++的,我最喜欢了!

 

3、思路分析和破解流程

没有信息框,我们可以试试查找文本的办法。

1、打开OD,将exe拖到OD窗口中,等程序暂停后,直接点击运行按钮(F9),不用理会。

2、随意输入伪码:BBDXF   123123。点击CHECK按钮,弹出信息框,不要关闭,回到OD。

3、Ctrl+K查看堆栈信息:

0

和之前的一样,找到Messagebox的下一个调用处,右键->Show call。

4、在反汇编窗口查看代码信息:

004015C1  |.  EB 16         jmp short 004015D9                       ;  // 关键跳转?没有判断,肯定不是的004015C3  |>  6A 00         push 0x0004015C5  |.  68 6C304000   push 0040306C                            ;  ASCII "ERROR"004015CA  |.  68 40304000   push 00403040                            ;  ASCII "One of the Details you entered was wrong"004015CF  |.  8B4D E0       mov ecx,[local.8]004015D2  |.  E8 BB020000   call <jmp.&MFC42.#4224>                  ;  // 返回到这里

附近的几个随意看看,没有找到关键跳转,哎,全部都看看吧:

004014B0  /.  55            push ebp004014B1  |.  8BEC          mov ebp,esp004014B3  |.  6A FF         push -0x1004014B5  |.  68 C21B4000   push 00401BC2                            ;  SE handler installation004014BA  |.  64:A1 0000000>mov eax,dword ptr fs:[0]004014C0  |.  50            push eax004014C1  |.  64:8925 00000>mov dword ptr fs:[0],esp004014C8  |.  83EC 14       sub esp,0x14004014CB  |.  53            push ebx004014CC  |.  56            push esi004014CD  |.  57            push edi004014CE  |.  894D E0       mov [local.8],ecx004014D1  |.  8D4D E4       lea ecx,[local.7]004014D4  |.  E8 83030000   call <jmp.&MFC42.#540>004014D9  |.  C745 FC 00000>mov [local.1],0x0004014E0  |.  8D4D F0       lea ecx,[local.4]004014E3  |.  E8 74030000   call <jmp.&MFC42.#540>004014E8  |.  C645 FC 01    mov byte ptr ss:[ebp-0x4],0x1004014EC  |.  8B4D E0       mov ecx,[local.8]004014EF  |.  81C1 A0000000 add ecx,0xA0004014F5  |.  E8 AA030000   call <jmp.&MFC42.#3876>                  ;  // 猜测是获取文本长度004014FA  |.  8945 EC       mov [local.5],eax                        ;  // eax = 5004014FD  |.  837D EC 05    cmp [local.5],0x5                        ;  // 文本长度大于500401501      7F 05         jg short 00401508                        ;  // 这个才是关键跳转00401503      E9 BB000000   jmp 004015C3                             ;  // 直接跳到失败00401508  |>  8B4D E0       mov ecx,[local.8]0040150B  |.  83C1 60       add ecx,0x600040150E  |.  E8 91030000   call <jmp.&MFC42.#3876>00401513  |.  8945 E8       mov [local.6],eax00401516  |.  837D E8 05    cmp [local.6],0x50040151A  |.  7F 05         jg short 004015210040151C  |.  E9 A2000000   jmp 004015C300401521  |>  8B45 E0       mov eax,[local.8]00401524  |.  05 E0000000   add eax,0xE000401529  |.  50            push eax0040152A  |.  8B4D E0       mov ecx,[local.8]0040152D  |.  81C1 A0000000 add ecx,0xA000401533  |.  E8 66030000   call <jmp.&MFC42.#3874>00401538  |.  8B4D E0       mov ecx,[local.8]0040153B  |.  81C1 E4000000 add ecx,0xE400401541  |.  51            push ecx00401542  |.  8B4D E0       mov ecx,[local.8]00401545  |.  83C1 60       add ecx,0x6000401548  |.  E8 51030000   call <jmp.&MFC42.#3874>0040154D  |.  8B55 E0       mov edx,[local.8]00401550  |.  81C2 E0000000 add edx,0xE000401556  |.  52            push edx00401557  |.  8D4D E4       lea ecx,[local.7]0040155A  |.  E8 39030000   call <jmp.&MFC42.#858>0040155F  |.  8B45 E0       mov eax,[local.8]00401562  |.  05 E4000000   add eax,0xE400401567  |.  50            push eax00401568  |.  8D4D F0       lea ecx,[local.4]0040156B  |.  E8 28030000   call <jmp.&MFC42.#858>00401570  |.  33C0          xor eax,eax                              ;  // eax = 000401572  |.  33DB          xor ebx,ebx                              ;  // ebx = 000401574  |.  33C9          xor ecx,ecx                              ;  // ecx = 000401576  |.  B9 01000000   mov ecx,0x1                              ;  // ecx = 10040157B  |.  33D2          xor edx,edx                              ;  // edx = 00040157D  |.  8B45 E4       mov eax,[local.7]                        ;  // "bbdxf1"00401580  |>  8A18          /mov bl,byte ptr ds:[eax]00401582  |.  32D9          |xor bl,cl00401584  |.  8818          |mov byte ptr ds:[eax],bl00401586  |.  41            |inc ecx                                 ;  // ecx++00401587  |.  40            |inc eax                                 ;  // eax++, 字符串向右一个00401588  |.  8038 00       |cmp byte ptr ds:[eax],0x00040158B  |.^ 75 F3         \jnz short 00401580                      ;  // 得到字符串 "c`g|c7"0040158D  |.  33C0          xor eax,eax                              ;  00040158F  |.  33DB          xor ebx,ebx                              ;  000401591  |.  33C9          xor ecx,ecx                              ;  000401593  |.  B9 0A000000   mov ecx,0xA                              ;  0x0A00401598  |.  33D2          xor edx,edx                              ;  00040159A  |.  8B45 F0       mov eax,[local.4]                        ;  // "123123"0040159D  |>  8A18          /mov bl,byte ptr ds:[eax]0040159F  |.  32D9          |xor bl,cl004015A1  |.  8818          |mov byte ptr ds:[eax],bl004015A3  |.  41            |inc ecx004015A4  |.  40            |inc eax004015A5  |.  8038 00       |cmp byte ptr ds:[eax],0x0               ;  // 得到字符串 ";9?<<<"004015A8  |.^ 75 F3         \jnz short 0040159D004015AA  |.  8B45 E4       mov eax,[local.7]                        ;  ASCII "c`g|c7"004015AD  |.  8B55 F0       mov edx,[local.4]                        ;  ASCII ";9?<<<"004015B0  |>  33C9          /xor ecx,ecx                             ;  0004015B2  |.  8A18          |mov bl,byte ptr ds:[eax]004015B4  |.  8A0A          |mov cl,byte ptr ds:[edx]004015B6  |.  3AD9          |cmp bl,cl                               ;  // 循环比较字符串的每一个字符004015B8  |.  75 09         |jnz short 004015C3                      ;  // 有一个不相等则失败004015BA  |.  40            |inc eax004015BB  |.  42            |inc edx004015BC  |.  8038 00       |cmp byte ptr ds:[eax],0x0004015BF  |.^ 75 EF         \jnz short 004015B0004015C1  |.  EB 16         jmp short 004015D9                       ;  // 关键跳转?没有判断,肯定不是的004015C3  |>  6A 00         push 0x0004015C5  |.  68 6C304000   push 0040306C                            ;  ASCII "ERROR"004015CA  |.  68 40304000   push 00403040                            ;  ASCII "One of the Details you entered was wrong"004015CF  |.  8B4D E0       mov ecx,[local.8]004015D2  |.  E8 BB020000   call <jmp.&MFC42.#4224>                  ;  // 返回到这里004015D7  |.  EB 14         jmp short 004015ED004015D9  |>  6A 00         push 0x0004015DB  |.  68 34304000   push 00403034                            ;  ASCII "YOU DID IT"004015E0  |.  68 20304000   push 00403020                            ;  ASCII "Well done,Cracker"004015E5  |.  8B4D E0       mov ecx,[local.8]004015E8  |.  E8 A5020000   call <jmp.&MFC42.#4224>004015ED  |>  6A 64         push 0x64                                ; /Timeout = 100. ms004015EF  |.  FF15 00204000 call dword ptr ds:[<&KERNEL32.Sleep>]    ; \Sleep004015F5  |.  C645 FC 00    mov byte ptr ss:[ebp-0x4],0x0004015F9  |.  8D4D F0       lea ecx,[local.4]004015FC  |.  E8 65010000   call <jmp.&MFC42.#800>00401601  |.  C745 FC FFFFF>mov [local.1],-0x100401608  |.  8D4D E4       lea ecx,[local.7]0040160B  |.  E8 56010000   call <jmp.&MFC42.#800>00401610  |.  8B4D F4       mov ecx,[local.3]00401613  |.  64:890D 00000>mov dword ptr fs:[0],ecx0040161A  |.  5F            pop edi0040161B  |.  5E            pop esi0040161C  |.  5B            pop ebx0040161D  |.  8BE5          mov esp,ebp0040161F  |.  5D            pop ebp00401620  \.  C3            retn

这个流程已经很简单了,爆破似乎都没什么必要了!

比如:00401501      7F 05         jg short 00401508 原本用来判断字符串长度的跳转就可以,我们直接修改为jmp 004015D9.哈哈!!

2

4、注册机的探索

算法其实很简单,核心内容为:

00401570  |.  33C0          xor eax,eax                              ;  // eax = 000401572  |.  33DB          xor ebx,ebx                              ;  // ebx = 000401574  |.  33C9          xor ecx,ecx                              ;  // ecx = 000401576  |.  B9 01000000   mov ecx,0x1                              ;  // ecx = 10040157B  |.  33D2          xor edx,edx                              ;  // edx = 00040157D  |.  8B45 E4       mov eax,[local.7]                        ;  // "bbdxf1"00401580  |>  8A18          /mov bl,byte ptr ds:[eax]00401582  |.  32D9          |xor bl,cl00401584  |.  8818          |mov byte ptr ds:[eax],bl00401586  |.  41            |inc ecx                                 ;  // ecx++00401587  |.  40            |inc eax                                 ;  // eax++, 字符串向右一个00401588  |.  8038 00       |cmp byte ptr ds:[eax],0x00040158B  |.^ 75 F3         \jnz short 00401580                      ;  // 得到字符串 "c`g|c7"

就是将Name的每一个字符都与ecx异或,ecx从1每次递增1,最后得到的字符串1。然后再对Serial做类似的处理得到字符串2,最后将字符串1和2比较,如果相等,则通过。

总体来讲就是两个大于5个字符的字符串,通过只有一个常量不同的算法,得到的字符串相等。这…..

C/CPP算法模拟:

// 用户名算法模拟char* pName = "bbdxf1";char pOut[10] = {0};for(int i=0;i<strlen(pName);i++){    pOut[i] = pName[i] ^ (i+1);}printf("%s\r\n",pOut);// 注册码算法模拟char* pKey = "123123";char pOut[10] = {0};for(int i=0;i<strlen(pKey);i++){    pOut[i] = pKey[i] ^ (i+0x0A);}printf("%s\r\n",pOut);

好吧,算法出来了,但是我们不可能凭空想到一个字符串能够完成这样的结果。所以,只有反算法了!

算法是通过异或得到【密文】比较相等,我们可以反过来,指定一个密文,分别反出来两个【原文】,即CPP算法中的Name和Key内容相同,输出的两个非别为Name和Key即可。

// CrackMeDemo.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include "iostream"int _tmain(int argc, _TCHAR* argv[]){	// 用户名算法模拟	char* pName = "bbdxf1";	printf("%s\r\n",pName);	char pOut[10] = {0};	for(int i=0;i<strlen(pName);i++)	{		pOut[i] = pName[i] ^ (i+1);	}	printf("Name:%s\r\n",pOut);	// 注册码算法模拟	char* pKey = pName;	for(int i=0;i<strlen(pKey);i++)	{		pOut[i] = pKey[i] ^ (i+0x0A);	}	printf("key:%s\r\n",pOut);	system("pause");	return 0;}

111

BY  笨笨D幸福