160个CrackMe之001

今天对第一个程序Acid burn.exe进行破解。此篇主要分爆破、寻找内置算法及密码两部分进行分析。

首先使用PEID对程序进行分析,可以知道程序是使用Delphi写的,且没有加壳。

 160个CrackMe之001_第1张图片

进入程序,可以看到有两个输入密码的按钮,分别是“Serial/Name”和“Serial”,将它们分别作为入口1与入口2。下面先进入入口1,可以看到要求输入用户名以及对应的密码,在这里我分别输入123456,可以看到程序出现了提示,说输入的有误:

 160个CrackMe之001_第2张图片

在这里需要注意的是提示的标题以及内容!!!这在下面的分析中有用。

上面是入口1处的提示,下面我们来到入口2,看看那里是什么情况。可以看到进入入口2之后,程序要求输入字符串,在这里我输入123456,程序弹出相应的提示:

 160个CrackMe之001_第3张图片

在这里可以看到这个提示的标题,与入口1处的提示是不同的!将提示的不同作为接下来分析的依据。

由于入口2的数据比入口1少,因此首先对入口2进行分析,主要分爆破、寻找内置算法及密码两部分分析。

首先对入口2处进行爆破。将入口2处提示标题“Failed”作为寻找的目标,使用IDA打开程序,在字符串窗口中找到相应的字符:

 160个CrackMe之001_第4张图片

这样就可以找到这个字符串所在的位置:

 160个CrackMe之001_第5张图片

可以看到这个字符串所在位置是经过跳转之后的地址,那么往上寻找,看一看跳转的位置。

 160个CrackMe之001_第6张图片

可以看到,在E:0042F4D这个位置是跳转的语句,这就是爆破和寻找密码的关键所在。

只要更改它跳转的条件就可以实现爆破了。这里我使用OD将跳转的语句更改为NOP

 160个CrackMe之001_第7张图片

将修改后程序保存,再次运行,在入口2处输入123456,如我们所愿,成功爆破。

 160个CrackMe之001_第8张图片

下面开始寻找入口2处的密码。

正如上面所说,在E:0042F4D这个位置是跳转的语句,这就是爆破和寻找密码的关键所在。要实现跳转,首先要对进行判断。那么判断是什么?在这里显然就是我们输入的字符与内置密码的比较判断。

CODE:0042F4D5这个跳转位置的前面有一个call语句以及两个mov语句,这两个mov语句实际上是作为参数参与到call所在函数的运算中,我们使用OD进行动态调试看看到跳转语句的过程中发生了什么,在第一个mov语句即CODE:0042F4CA位置设置一个断点,开始调试。

 160个CrackMe之001_第9张图片

当运行到call语句时,可以看一下eaxedx的值,可以看到eax的值是“123456,edx的值是“Hello Dude!”,好了,这个 “Hello Dude!”是什么?这就是程序内置的密码!我们尝试使用“Hello Dude!”进行测试,看看我们找的这个对不对。

 160个CrackMe之001_第10张图片

对啦!至此,对于入口2的处理就结束了。

 

下面对入口1分别进行爆破与注册码的处理。

上面说过,入口1与入口2处的提示存在明显的不同,这里我们将“Sorry,The serial is incorect!”作为处理的第一步, 使用IDA打开程序,并在字符串窗口中找到这个字符串

 160个CrackMe之001_第11张图片

 160个CrackMe之001_第12张图片

来到字符串相应的位置,并利用X找到调用字符串的位置,这里有两个对应的字符串位置,分别是CODE:0042FB1FCODE:0042FA63。我们首先处理CODE:0042FB1F处。

 160个CrackMe之001_第13张图片

可以看到,CODE:0042FB1F是一个跳转之后的一个位置,那么我们就循着这个跳转往上走

 160个CrackMe之001_第14张图片

可以看到,CODE:0042FB03是跳转语句,它是实现是否正确提示的关键,这里首先对入口1进行爆破。

要实现爆破, 只需将CODE:0042FB03处的跳转语句修改为NOP就可以实现正确的提示了。

 160个CrackMe之001_第15张图片

修改完成之后,我们再次在入口1处输入123456,可以看到,出现了错误的提示,这是为什么?

 160个CrackMe之001_第16张图片

在暂时找不到原因的情况下,看一看另一个字符串所在的位置,或许在那里会有收获。

我们来到CODE:0042FA63这个位置,

 160个CrackMe之001_第17张图片

可以看到这也是在一个跳转语句的后面,往上看,jge     short loc_42FA79”,再往上看,有一个“cmp     eax, 4”,这是什么?后面我们可以知道,这是判断字符串长度的语句。那先不管了,这里设置一个断点,另外在下面我们处理过的地方再次设置一个断点,看看到底是什么情况。

调试的过程中,依然使用123/456作为输入,程序运行到cmp     eax, 4”时,我们要注意寄存器的值,

 160个CrackMe之001_第18张图片

可以看到,运行到CODE:0042FA57时,EAX= 1,这是什么情况?明明输入的是123啊!重新调试,输入12/354,再到这个断点看一下,EAX还是1!有问题。 那么输入4位以上的用户名是什么情况呢?再次调试并输入1234/5678,到达断点处,再看一下EAX,这次EAX=5,继续执行,看看怎么样,

 160个CrackMe之001_第19张图片

这次对啦!原来这是对用户名还有长度的限制。那这样就好办了,将CODE:0042FA5A 7D 1D             jge     short loc_42FA79”这里的jge改为jmp就可以绕过长度的限制了。

再次运行程序并在入口1处输入123/456,提示成功!

 160个CrackMe之001_第20张图片

下面对入口1处的注册码进行寻找。

 

0042FA52  |.  E8 D96EFDFF   call Acid_bur.00406930

0042FA57  |.  83F8 04       cmp eax,0x4                              ;  比较字符串的长度是否大于等于4

0042FA5A  |.  7D 1D         jge short Acid_bur.0042FA79

0042FA5C  |.  6A 00         push 0x0

0042FA5E  |.  B9 74FB4200   mov ecx,Acid_bur.0042FB74                ;  ASCII 54,"ry Again!"

0042FA63  |.  BA 80FB4200   mov edx,Acid_bur.0042FB80                ;  ASCII 53,"orry , The serial is incorect !"

0042FA68  |.  A1 480A4300   mov eax,dword ptr ds:[0x430A48]

0042FA6D  |.  8B00          mov eax,dword ptr ds:[eax]               ;  Acid_bur.00424090

0042FA6F  |.  E8 FCA6FFFF   call Acid_bur.0042A170                   ;  字符串长度小于4回到0042A170位置,输错错误对话框

0042FA74  |.  E9 BE000000   jmp Acid_bur.0042FB37

0042FA79  |>  8D55 F0       lea edx,[local.4]

0042FA7C  |.  8B83 DC010000 mov eax,dword ptr ds:[ebx+0x1DC]

0042FA82  |.  E8 D1AFFEFF   call Acid_bur.0041AA58

0042FA87  |.  8B45 F0       mov eax,[local.4]

0042FA8A  |.  0FB600        movzx eax,byte ptr ds:[eax]              ;  取出name字符串中的第一个字符

0042FA8D  |.  F72D 50174300 imul dword ptr ds:[0x431750]             ;  乘以0x29(地址431750)

0042FA93  |.  A3 50174300   mov dword ptr ds:[0x431750],eax

0042FA98  |.  A1 50174300   mov eax,dword ptr ds:[0x431750]

0042FA9D  |.  0105 50174300 add dword ptr ds:[0x431750],eax          ;  再乘以2存在0x431750

0042FAA3  |.  8D45 FC       lea eax,[local.1]

0042FAA6  |.  BA ACFB4200   mov edx,Acid_bur.0042FBAC

0042FAAB  |.  E8 583CFDFF   call Acid_bur.00403708

0042FAB0  |.  8D45 F8       lea eax,[local.2]

0042FAB3  |.  BA B8FB4200   mov edx,Acid_bur.0042FBB8

0042FAB8  |.  E8 4B3CFDFF   call Acid_bur.00403708

0042FABD  |.  FF75 FC       push [local.1]                           ;  Acid_bur.0042FBAC

0042FAC0  |.  68 C8FB4200   push Acid_bur.0042FBC8                   ;  UNICODE "-"

0042FAC5  |.  8D55 E8       lea edx,[local.6]

0042FAC8  |.  A1 50174300   mov eax,dword ptr ds:[0x431750]

0042FACD  |.  E8 466CFDFF   call Acid_bur.00406718                   ;  这个call函数中的内容就是生成serial中间数字串的部分

0042FAD2  |.  FF75 E8       push [local.6]                           ;  local.6是中间生成的password数字串

0042FAD5  |.  68 C8FB4200   push Acid_bur.0042FBC8                   ;  UNICODE "-"

0042FADA  |.  FF75 F8       push [local.2]                           ;  Acid_bur.0042FBB8

0042FADD  |.  8D45 F4       lea eax,[local.3]

0042FAE0  |.  BA 05000000   mov edx,0x5

0042FAE5  |.  E8 C23EFDFF   call Acid_bur.004039AC                   ;  字符串拼接

0042FAEA  |.  8D55 F0       lea edx,[local.4]

0042FAED  |.  8B83 E0010000 mov eax,dword ptr ds:[ebx+0x1E0]

0042FAF3  |.  E8 60AFFEFF   call Acid_bur.0041AA58                  ;得到正确的password

0042FAF8  |.  8B55 F0       mov edx,[local.4]                        ;  输入的Password:12345

0042FAFB  |.  8B45 F4       mov eax,[local.3]                        ;  正确的password

0042FAFE  |.  E8 F93EFDFF   call Acid_bur.004039FC                 ;  明显就是两个字符串比较喽

0042FB03  |.  75 1A         jnz short Acid_bur.0042FB1F

 

 

算法就是name输入后先根据上面的结果生成数字字符串,然后再与其他的字母,符号拼接,生成成最后的serial。这就是这个name/serial算法的求算过程。

以下是注册机程序:

#include 
#include 

int main()
{
    char buffer[200] = {0};
    short int c;
	while (1)
	{
		printf("please input name:\n");
		scanf("%s",buffer);
		if(strlen(buffer)<4)  //判断序列号长度
			printf("Too short!\n");
		else
		{
			c=buffer[0]*0x29*2;
			printf("Serial: CW-%4d-CRACKED\r\n",c);
		}
	}
  
    return 0;
}

你可能感兴趣的:(破解)