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

时间:2023-01-12 15:25:13

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

本系列文章的目的是从一个没有任何经验的新手的角度(其实就是我自己),一步步尝试将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不报毒,个人承诺绝对不会进行任何和木马病毒相关内容。

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

2、程序分析:

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

和上一节一样,打开CHM,选择第4个ajj,保存下来。运行程序,程序界面如下:

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

这似乎是一个标准的Name/Serial注册码方式,二话不说,来个伪码测试:

Name: 3333     Serial: 44445555

但是,但是什么提示也没有,只有一个鼠标提示,我点,我点,编辑框,灰色的小框框,我单击,我双击,KAO,啥提示也没有。

还是看看说明书吧:

前两天我和[CCG]的大哥Sun Bird兄闲聊时引出一个话题,
我要想想办法难为一下Sun Bird兄。
因此就用了两个半天的时间,作了一个小东东。
这个CKme与一般的软件注册过程不一样,它没有"确定"键,
当然CK这样的软件其实一点也不麻烦,没遇到过的朋友可要动动脑子了。     8)
另外这个CKme还作了一点别的手脚,不多说了,自己看着办吧。
这个软件是用Delphi编的,由于我刚学了一星期的Delphi,
有很多想法在这个小程序里没有实现,因此这个CKme应该算是比较简单的了。
如果你成功的注册了,请给我来封信好吗?谢谢!!!
还有你千万不要告诉我你只用了2分钟就搞定了,如果是这样我就。。8~~~(

                            ajj
                            2000/08/30

好吧,这位大哥再给我们玩猜谜呢!

 

3、思路分析和破解流程:

这个程序就像作者说的,诡异的不知道到底是那里出发判断,无论点什么地方都没有任何提示。查一下壳:Delphi的,没有加壳。对Delphi不了解,没关系,我们先尝试熟悉的程序的方式看看是否能行。

个人比较擅长VC,先按照VC思路思考一下程序可能会通过什么方式触发检测序列号动作:

1、要进行序列号检测,必须的获取Name/Serial的文本,在VC中WM_GETTEXT消息用来获取文本使用,我们可以通过对Edit控件下消息断点,然后看看是否能得到一些信息。操作:菜单->View->Windows,很容易就看到了标题,Class名称为TForm1,右键Message Breakpoint on callproc,找到WM_GetText消息,确定。这时无论我们怎么尝试都无法断下。没办法,对delphi不了解,再试试别的。

2、在第一个的基础上尝试WM_KEYDOWN/WM_KEYUP消息,API断点(GetWindowTextW/A),发现都无法获得任何信息。

尝试到这里,只说明了一个问题,Delphi并不是简单地封装了API函数,所以我们无法通过这方面来进行筛选和拦截。

退一步,我们的目的是破解这个程序,所以只要能够找到和关键跳转相关的东西就行。进论坛,搜了一大桶,原来除了堆栈找法,还有很多看起来很小白的方法,比如最碰运气的【字符串查找】,如果程序中有很多和流程相关的字符串,我们就可以根据字符串的意思猜测程序的流程。Ctrl+E(E图标),选中CKme.exe模块,右键->Follow entry,这样我们就在主程序模块,然后右键->中文搜索引擎->智能搜索,哈哈哈,终于露出狐狸的小尾巴了!我们发现有一个很明显的中文字符串【恭喜恭喜!注册成功】,二话不说,跟进去。

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

到CALL的地方后,向上查看代码,很容易就找到了两个JNZ,最近的那个一直在循环,不会跳过中文的提示,而最上面的那个jnz short 004580B3 一眼就能看到它会跳出正确提示,SO,爆破很easy啦!选中这个JNZ,右键->Binary->Fill with NOPs. 随意输入Name/Serial试试,OK,非常完美,收工!

4、注册机的探索:

我们的目的不单单是爆破他,尽量算出注册码,SO,找到代码头,输入伪码:

Name: 112233   Serial: 44445555

下断,F8分析:

00457FB8  /.  55            push ebp                                   ;  00A053D8
00457FB9 |. 8BEC mov ebp,esp
00457FBB |. B9 04000000 mov ecx,0x4
00457FC0 |> 6A 00 /push 0x0
00457FC2 |. 6A 00 |push 0x0
00457FC4 |. 49 |dec ecx
00457FC5 |.^ 75 F9 \jnz short 00457FC0 ; // 毫无意义地循环了4次
00457FC7 |. 51 push ecx
00457FC8 |. 53 push ebx
00457FC9 |. 56 push esi ; //00A053D8
00457FCA |. 8BF0 mov esi,eax ; // esi=00A019CC=纹E
00457FCC |. 33C0 xor eax,eax
00457FCE |. 55 push ebp
00457FCF |. 68 FD804500 push 004580FD
00457FD4 |. 64:FF30 push dword ptr fs:[eax]
00457FD7 |. 64:8920 mov dword ptr fs:[eax],esp
00457FDA |. 33DB xor ebx,ebx
00457FDC |> 8D55 F4 /lea edx,[local.3]
00457FDF |. 8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
00457FE5 |. E8 5EB3FCFF |call 00423348
00457FEA |. 8B45 F4 |mov eax,[local.3] ; // eax=112233 字符串地址
00457FED |. E8 8ABBFAFF |call 00403B7C
00457FF2 |. 83C0 1E |add eax,0x1E ; // eax=6+1E=0x24
00457FF5 |. 8D55 F8 |lea edx,[local.2]
00457FF8 |. E8 07FBFAFF |call 00407B04 ; // 修改了edx地址处的值为36
00457FFD |. FF75 F8 |push [local.2] ; // ecx=0x24
00458000 |. 8D55 F0 |lea edx,[local.4]
00458003 |. 8B86 D4020000 |mov eax,dword ptr ds:[esi+0x2D4]
00458009 |. E8 3AB3FCFF |call 00423348
0045800E |. FF75 F0 |push [local.4] ; // ss=112233
00458011 |. 8D55 EC |lea edx,[local.5]
00458014 |. 8BC3 |mov eax,ebx
00458016 |. E8 E9FAFAFF |call 00407B04
0045801B |. FF75 EC |push [local.5]
0045801E |. 8D45 FC |lea eax,[local.1]
00458021 |. BA 03000000 |mov edx,0x3
00458026 |. E8 11BCFAFF |call 00403C3C
0045802B |. 43 |inc ebx ; ebx=0++
0045802C |. 83FB 13 |cmp ebx,0x13 ; // 不知道为什么比较了0x13次
0045802F |.^ 75 AB \jnz short 00457FDC ; // 这个形成了一个xxName18的字符串,3611223318
00458031 |. 81BE 0C030000>cmp dword ptr ds:[esi+0x30C],0x85 ; // esi是关键点
0045803B 75 76 jnz short 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 00423348
0045804D |. 8B45 E4 |mov eax,[local.7]
00458050 |. E8 27BBFAFF |call 00403B7C
00458055 |. 83C0 03 |add eax,0x3
00458058 |. 8D55 E8 |lea edx,[local.6]
0045805B |. E8 A4FAFAFF |call 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 00423348
00458071 |. FF75 E0 |push [local.8]
00458074 |. 8D55 DC |lea edx,[local.9]
00458077 |. 8BC3 |mov eax,ebx
00458079 |. E8 86FAFAFF |call 00407B04
0045807E |. FF75 DC |push [local.9]
00458081 |. 8D45 FC |lea eax,[local.1]
00458084 |. BA 03000000 |mov edx,0x3
00458089 |. E8 AEBBFAFF |call 00403C3C
0045808E |. 43 |inc ebx
0045808F |. 83FB 13 |cmp ebx,0x13
00458092 |.^ 75 AB \jnz short 0045803F
00458094 |. 33D2 xor edx,edx
00458096 |. 8B86 F0020000 mov eax,dword ptr ds:[esi+0x2F0]
0045809C |. E8 BFB1FCFF call 00423260
004580A1 |. A1 20B84500 mov eax,dword ptr ds:[0x45B820]
004580A6 |. 83C0 70 add eax,0x70
004580A9 |. BA 14814500 mov edx,00458114 ; 恭喜恭喜!注册成功
004580AE |. E8 9DB8FAFF call 00403950
004580B3 |> 33C0 xor eax,eax

这段代码对Name进行了处理,在堆栈中得到了一个类似3611223318的字符串,但是比较的时候使用的是cmp dword ptr ds:[esi+0x30C],0x85,esi+0x30C地址处的值才是真正影响结果的,翻看代码发现,没有任何地方修改了这个值,没办法,重新断在循环头部,db [esi+0x30C],对内容下内容写入断点,取消其他断点,F9运行,尝试。。。

悲剧了,什么也找不到。

多次尝试此代码段的上层代码和跟踪内部CALL代码,无法找到有用的信息。实在没办法了,继续求救大神吧!

搜索发现了两点有用的信息:

1、看雪论坛找到了一个正确的Name/Serial。Name: findlakes   Serial: 黑头Sun Bird14dseloffc-012-OKfindlakes

2、OD对于Delphi程序确实有些乏力,反汇编Delphi有更好的软件Dede。

 

下面我们尝试使用Dede反编译它(工具下载链接里有):

如图,在窗体选项中发现注册码编辑框TEdit2有OnKeyUp事件chkcode。

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

在过程选项中,双击chkcode查看代码:

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

代码如下:

00457C40   55                     push    ebp
00457C41 8BEC mov ebp, esp
00457C43 51 push ecx
00457C44 B905000000 mov ecx, $00000005
00457C49 6A00 push $00
00457C4B 6A00 push $00
00457C4D 49 dec ecx
00457C4E 75F9 jnz 00457C49
00457C50 51 push ecx
00457C51 874DFC xchg [ebp-$04], ecx
00457C54 53 push ebx
00457C55 56 push esi
00457C56 8BD8 mov ebx, eax
00457C58 33C0 xor eax, eax
00457C5A 55 push ebp
00457C5B 683D7E4500 push $00457E3D
...

OK,关闭Dede,我们在OD中加载它:

Ctrl+G 转到开头地址: 00457C40,向上找到段头,开始F8分析:

00457C1C   .  53 75 6E 20 4>ascii "Sun Bird",0
00457C25 00 db 00
00457C26 00 db 00
00457C27 00 db 00
00457C28 . FFFFFFFF dd FFFFFFFF
00457C2C . 0F000000 dd 0000000F
00457C30 . 64 73 65 6C 6>ascii "dseloffc-012-OK",0
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 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 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] ; // (ASCII "黑头Sun Bird")
00457C75 |. 8D55 F8 lea edx,[local.2]
00457C78 |. 8BC6 mov eax,esi
00457C7A |. E8 85FEFAFF call 00407B04
00457C7F |. FF75 F8 push [local.2] ; // 10
00457C82 |. FFB3 14030000 push dword ptr ds:[ebx+0x314] ; // (ASCII "dseloffc-012-OK")
00457C88 |. 8D55 F4 lea edx,[local.3]
00457C8B |. 8B83 D4020000 mov eax,dword ptr ds:[ebx+0x2D4]
00457C91 |. E8 B2B6FCFF call 00423348
00457C96 |. FF75 F4 push [local.3] ; // ASCII bbdxf
00457C99 |. 8D83 18030000 lea eax,dword ptr ds:[ebx+0x318]
00457C9F |. BA 04000000 mov edx,0x4
00457CA4 |. E8 93BFFAFF call 00403C3C
00457CA9 |. 33D2 xor edx,edx
00457CAB |. 8B83 F4020000 mov eax,dword ptr ds:[ebx+0x2F4]
00457CB1 |. E8 AAB5FCFF call 00423260
00457CB6 |. 8B93 18030000 mov edx,dword ptr ds:[ebx+0x318] ; //(ASCII "黑头Sun Bird10dseloffc-012-OKbbdxf")
00457CBC |. 8B83 F4020000 mov eax,dword ptr ds:[ebx+0x2F4]
00457CC2 |. E8 B1B6FCFF call 00423378 ; // 根据我们之前查找的资料,上面的字符串其实就是注册码了
00457CC7 |. 33F6 xor esi,esi
00457CC9 |> 8D55 EC /lea edx,[local.5] ; // 0x13 次不知道干什么的循环
00457CCC |. 8B83 D4020000 |mov eax,dword ptr ds:[ebx+0x2D4]
00457CD2 |. E8 71B6FCFF |call 00423348
00457CD7 |. 8B45 EC |mov eax,[local.5]
00457CDA |. E8 9DBEFAFF |call 00403B7C
00457CDF |. 83C0 03 |add eax,0x3
00457CE2 |. 8D55 F0 |lea edx,[local.4]
00457CE5 |. E8 1AFEFAFF |call 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 00423348
00457CFB |. FF75 E8 |push [local.6]
00457CFE |. 8D55 E4 |lea edx,[local.7]
00457D01 |. 8BC6 |mov eax,esi
00457D03 |. E8 FCFDFAFF |call 00407B04
00457D08 |. FF75 E4 |push [local.7]
00457D0B |. 8D45 FC |lea eax,[local.1]
00457D0E |. BA 03000000 |mov edx,0x3
00457D13 |. E8 24BFFAFF |call 00403C3C
00457D18 |. 46 |inc esi
00457D19 |. 83FE 13 |cmp esi,0x13
00457D1C |.^ 75 AB \jnz short 00457CC9
00457D1E |. 8D55 E0 lea edx,[local.8]
00457D21 |. 8B83 D8020000 mov eax,dword ptr ds:[ebx+0x2D8]
00457D27 |. E8 1CB6FCFF call 00423348

实在是被Delphi折磨的不能行了,注册码很简单,特别是根据开头的几个ANSI能够看出来,他就是固定的字符串加上我们的Name,即"黑头Sun Bird10dseloffc-012-OK"+Name。随便怎么搞都没问题。

总结一下:这个CrackMe就像作者说的,更多的算是一个小游戏,再加上Delphi不熟,做完之后实在感到有些鸡肋,不过,相信,所有的付出都会有收获的,只是时间的问题。加油!

 

BY  笨笨D幸福