好友
阅读权限 35
听众
最后登录 1970-1-1
solly
发表于 2019-7-24 01:43
本帖最后由 solly 于 2019-7-25 16:22 编辑
160 个 CrackMe 之 098 - woody 是一个比较特殊的CrackMe,有点猜迷类游戏的意思,启动后如下图所示:
显示一套黑黝黝房子,下面有説明:
[HTML] 纯文本查看 复制代码
K ... You're a thief, and the taget is to get into the house, and to the computer .. and download the very secret file ;)
The easiest thing to do is just go through the door ... but try it the "real" way first.
There are several ways to get into the house.
The real way would be:
1) Find the tool to open the window.
2) Then find the tool to open the door.
3) Then crack the keyhole with the tool
4) Now you should be in the house ...
5) Crack the password on the computer
6) Download the file
that's it ..
The wrong way ... kick the door in, and download the file.
But remember .. the police is right behind the corner, so be quiet :)
Here's a hint .. the texts isn't what it should be :) heh
意思就是要偷偷溜进房子,打开电脑,下载一个加密文件。。。
还告诉我们破解 步骤就是:
[HTML] 纯文本查看 复制代码
1)找到工具打开窗户;
2)然后用工具打开门;
3)再用工具撬开门锁;
4)现在你进入房子。。。
5)破解电脑密码;
6)下载文件。
既然是 CrackMe,我认为其説的工具就是破解工具,下面就综合使用各类工具来完成这个迷题。
工具包括:exeInfo PE,DeDeDark,ExeScope,IDA ,OD,Delphi 等。
首先看看文件信息,如下图所示:
显示这是一个 Delphi 编译的 CrackMe,拿出 DeDeDark 来查看控件和事件,如下图所示:
CrackMe 一共有 3 个表单(TForm),其中表单 1 事件较多,如上图所示,有 5 个 Click 事件、1 个定时器事件和 1 个 FormCreate 事件(表单创建时执行的事件)。
再看 Form2,如下图:
只有一个 Button 的 Click 事件。
再看看 Form3 的,如下图:
也只有一个事件,一个时间定时器事件 Timer1Timer。
下面看看控件信息,看看 From1 的 Timer 控件,属性 Enabled = False ,默认没有启动,看来是通过代码来启动的。
再看看 Form3 的 Timer 控件,也一样默认没有启动,同样是通过代码启动的。
下面打开 DeDeDark 的 DFM Inspector 查看 Form1 其它控件信息,如下图所示:
通过它可以看到哪些控件有事件处理,哪些没有,没有事件处理的基本就是显示用的。
整理一下,我们得到如下信息:
[HTML] 纯文本查看 复制代码
一、标签:
1. Label1~ Label4没有内容也没有事件。
2. Label5和Label12有显示内容,没有事件。
3. Label6、Label9和Label13没有显示内容,拥有同一个Click事件:Label6Click。
4. Lable7 没有显示内容,有事件:Label7Click。
5. Lable8 没有显示内容,也没有事件。
6. Label10 没有显示内容,有事件:Label10Click。
7. Label11 没有内容,有事件:Lable11Click。
二、按钮
只有一个按钮,事件为:Button1Click。
三、定时器
只有一个定时器,事件为:Timer1Timer。
另外,我们把事件的地址也整理出来:
[HTML] 纯文本查看 复制代码
一、Form1
FormCreate: 0x00459270
Button1Click: 0x0045D67C
Timer1Timer: 0x0045D614
Label6Click: 0x00459134
Lable7Click: 0x0045D574
Label10Click: 0x0045D694
Label11Click: 0x00459158
二、Form2
Button1Click: 0x00458CD4
三、Form3:
Timer1Timer: 0x00458A7C
这些入口地址,是等下在OD中下断点的地方。
控件找出来了,但好多 Label 没有显示文字内容,只有事件,那它们在哪里呢,DeDe也没显示或不明显(DFM预览功能)。
下面,我们用 eXeScope 打开 CrackMe,在左边资源树中,展开 RCData 项,选中 TForm1,如下图所示:
然后,导出为 Unit1.DFM。
我们用 Delphi7 创建一个 Delphi 项目,其Form代码保存为 Unit1.pas(表单资源会自动保存为 Unit1.DFM),关闭并保存该项目。将前面在 eXeScope 中导出的 Unit1.DFM 拷贝到这个项目目录中,覆盖掉原来的 Unit1.DFM。再重新用 Delphi 打开项目,就可以观看各个控件的位置了,如下图所示:
最后,我们定位了所有不可见控件,如下图所示:
标红框 的都是标签(Label)控件,红框大小与标签大小基本相同。数字代表标签名序号,如1代表 Label1,6代表 Label6,A 代表 Label10,B 代表 Label11,D 代表 Label13,等等。
根据上面的事件表,我们知道哪些 Label 控件有事件处理过程。
我们先用 IDA7 打开 CrackMe,根据上面的事件表,跳转到各个事件看看,了解一下 Delphi 内部函数调用的情况,等一下在 OD 中就不用 F7 到一些内部函数中去参观了。
下图是 _start() ,Delphi 程序的入口,创建了三个表单,具体如下图所示:
Form1.Button1Click() 事件代码,如下图所示,时间控件启停函数解析有误(即 Timer1.Enabled = True/False),在 DeDeDark中也可看到,不过 DeDeDark 将几个可能的函数名都列举出来了:
再看 Label11Click()的事件,有两次文件是否存在的检查(FileExists()),如下图所示:
下面还有写文件的过程,都是调用的 Delphi 函数,在 OD 中就不用进入这些函数去跟踪了,如下图:
其它过程就不细説了,根据需要可以全部查看一遍,了解 Delphi 内部函数的调用情况。参观完各个事件代码后,现在我们进行动态跟踪尝试破解迷题。
用 OD 载入 CrackMe,根据前面 DeDe 的信息,如下图:
我们先看看一些事件代码:
上图是 CrackMe 入口代码,创建了三个表单。
我们用OD的“转到”功能,输入 Button1Click 入口地址 0x0045D67C,如上图,点“确定”,来到其事件代码处:
具体代码如下:
[Asm] 纯文本查看 复制代码
0045D67C . C605 67084600 01 mov byte ptr [460867], 1 ; 开始游戏
0045D683 . B2 01 mov dl, 1 ; dl == 1, Enabled
0045D685 . 8B80 F4020000 mov eax, dword ptr [eax+2F4]
0045D68B . E8 505BFEFF call 004431E0 ; 启动 Timer1
0045D690 . C3 retn
这段代码很短,完成两个功能:
1、将一个全局变量设置为1,应该是游戏开始标志。
2、启动定时器,进行倒计时。
然后看看 FormCreate 事件,如下图:
选中部分是初始化一些全局变量。后面还初始化了一些字符串,并解密一些字符串,这些字符串是用来做提示的,后面都会用到。本方法的代码很长,不需多看,主要是以下几个变量关注一下:
[Asm] 纯文本查看 复制代码
00459290 |. C605 64084600 00 mov byte ptr [460864], 0
00459297 |. C605 65084600 00 mov byte ptr [460865], 0
0045929E |. C605 66084600 00 mov byte ptr [460866], 0
004592A5 |. C605 6D084600 1E mov byte ptr [46086D], 1E ; 30, 30 秒?
004592AC |. C605 67084600 00 mov byte ptr [460867], 0 ; 置 1, 在 Button.Click() 中
004592B3 |. C605 68084600 00 mov byte ptr [460868], 0
前面 Button1Click 启动了定时器,我们看看定时器事件代码:
[Asm] 纯文本查看 复制代码
;;------------------------- Form1.Timer1Timer() ------------------------------------------------------------------------
0045D614 . 53 push ebx ; Form1.Timer()
0045D615 . 8BD8 mov ebx, eax ; ebx == Sender
0045D617 . FE0D 6D084600 dec byte ptr [46086D] ; 计时(计次: 30 次),正是 FormCreate 中初始化的
0045D61D . 33D2 xor edx, edx
0045D61F . 8A15 6D084600 mov dl, byte ptr [46086D]
0045D625 . 8B83 10030000 mov eax, dword ptr [ebx+310]
0045D62B . E8 74B1FFFF call 004587A4 ; SetPosition()
0045D630 . 803D 6D084600 00 cmp byte ptr [46086D], 0 ; 等于 0 就结束,表示游戏结束
0045D637 . 77 3D ja short 0045D676
0045D639 . 6A 00 push 0
0045D63B . 66:8B0D 78D64500 mov cx, word ptr [45D678]
0045D642 . B2 03 mov dl, 3
0045D644 . A1 3C0A4600 mov eax, dword ptr [460A3C] ; 游戏结束提示,eax ===> "Sorry .. the police caught you :) "
0045D649 . E8 E26AFEFF call 00444130 ; MessageDlg()
0045D64E . A1 94F54500 mov eax, dword ptr [45F594] ; Form3
0045D653 . 8B00 mov eax, dword ptr [eax]
0045D655 . 8078 47 01 cmp byte ptr [eax+47], 1 ; Form3.Timer1 是否 enabled,即是否正在下载
0045D659 . 75 14 jnz short 0045D66F
0045D65B . A1 94F54500 mov eax, dword ptr [45F594] ; Form3
0045D660 . 8B00 mov eax, dword ptr [eax]
0045D662 . 8B80 CC020000 mov eax, dword ptr [eax+2CC]
0045D668 . 33D2 xor edx, edx ; dl == 0, Disabled
0045D66A . E8 715BFEFF call 004431E0 ; Form3.Timer1.SetEnabled(false),停止 Form3.Timer1,即停止模拟下载
0045D66F > 8BC3 mov eax, ebx
0045D671 . E8 5600FEFF call 0043D6CC ; Form1.Close() //Termelate()
0045D676 > 5B pop ebx
0045D677 . C3 retn
就是一个倒计时,30次(秒)后弹出一个消息后,结束 CrackMe。
按 F9 直接运行 CrackMe,来到主界面:
按照按钮标题提示,要点按钮(Button1)开始游戏,我们点击按钮,可以看到,下面的进度条变短,应该定时器启动了,正在倒计时了,如下图:
等这个进度条走完,弹出一个消息框,表示游戏失败(“被警察抓住了”),如下图所示:
点“OK”后,CrackMe 退出了,只有重新来了,再次加载 CrackMe,F9运行,点击“开始”,这次,我们先在那三个有 Label6Click 事件的标签位置点点鼠标,弹出下面消息:
説位置太高,不行,看来不是这里,再点一下门(Label7),又弹出:
再点一下窗户(Label10),没有反应,看来也不对。只剩下 Label11没有点了,那个位置最小,点击后,弹出:
噫,卡住了,要 Patch?立马在这个事件中下断点,看看patch哪里,如下图所示:
上面图中显示下了一个断点 ,Label11Click 事件的具体代码如下:
[Asm] 纯文本查看 复制代码
00459158 /. 55 push ebp ; Label11Click(),寻找工具
00459159 |. 8BEC mov ebp, esp
0045915B |. 6A 00 push 0
0045915D |. 33C0 xor eax, eax
0045915F |. 55 push ebp
00459160 |. 68 53924500 push 00459253
00459165 |. 64:FF30 push dword ptr fs:[eax]
00459168 |. 64:8920 mov dword ptr fs:[eax], esp
0045916B |. 803D 67084600 01 cmp byte ptr [460867], 1 ; 是否已开始游戏
00459172 |. 0F85 C5000000 jnz 0045923D
00459178 803D 6E084600 01 cmp byte ptr [46086E], 1 ; 前题条件1, [0046086E]为0, patch 成与0比较: cmp byte ptr [46086E], 0
0045917F |. 75 5F jnz short 004591E0 ; 跳转去提示需要 patch,并生成文件 annoy.txt
00459181 |. A1 580A4600 mov eax, dword ptr [460A58]
00459186 |. E8 91E7FAFF call 0040791C ; FileExists(), 文件检查,是否存在文件 "annoy.txt"
0045918B |. 84C0 test al, al
0045918D |. 75 51 jnz short 004591E0 ; 不能跳转,因此如果当前目录下有这个文件,必须先删除
0045918F |. 6A 00 push 0 ; MessageDlg()参数4
00459191 |. FF35 4C0A4600 push dword ptr [460A4C] ; "Yer .. that looks like a tool to break a window :)"
00459197 |. 68 68924500 push 00459268 ; '\n'
0045919C |. FF35 500A4600 push dword ptr [460A50] ; "You picked it up"
004591A2 |. 8D45 FC lea eax, dword ptr [ebp-4] ; result
004591A5 |. BA 03000000 mov edx, 3 ; n = 3, 3 个字符串连接
004591AA |. E8 8DA9FAFF call 00403B3C ; LStrCatN(),字符串连接
004591AF |. 8B45 FC mov eax, dword ptr [ebp-4] ; string
004591B2 |. 66:8B0D 6C924500 mov cx, word ptr [45926C] ; [0]
004591B9 |. B2 03 mov dl, 3 ; [mbAbort], [mbOK, mbCancel]
004591BB |. E8 70AFFEFF call 00444130 ; MessageDlg(),显示可以进行下一步的提示
004591C0 |. A1 580A4600 mov eax, dword ptr [460A58]
004591C5 |. E8 52E7FAFF call 0040791C ; FileExists(), 文件检查,是否存在文件 "annoy.txt"
004591CA |. 84C0 test al, al ; al == 0 表示文件不存在,非0表示存在
004591CC |. 75 12 jnz short 004591E0 ; 存在文件则跳转去报错!!!
004591CE |. 803D 6E084600 00 cmp byte ptr [46086E], 0 ; [46086E] 不能大于 0
004591D5 |. 77 09 ja short 004591E0
004591D7 |. C605 64084600 01 mov byte ptr [460864], 1 ; 设置标志,已完成任务1,表示找到工具
004591DE |. EB 15 jmp short 004591F5 ; 跳转去生成文件:annoy.txt,不生成文件改成 jmp 0045923D,就没有文件干拢了
004591E0 |> 6A 00 push 0 ; MessageDlg()参数4
004591E2 |. 66:8B0D 6C924500 mov cx, word ptr [45926C] ; cx == 0x0004, mtConfirmation
004591E9 |. B2 03 mov dl, 3 ; [mbOK]
004591EB |. A1 480A4600 mov eax, dword ptr [460A48] ; [eax] ===> "Dammit ... it's stuck, maybe it needs a patch?"
004591F0 |. E8 3BAFFEFF call 00444130 ; MessageDlg,显示错误信息
004591F5 |> 8B15 580A4600 mov edx, dword ptr [460A58] ; edx ===> "annoy.txt",文件名
004591FB |. B8 70084600 mov eax, 00460870
00459200 |. E8 A5BFFAFF call 004051AA ; Assign(),文件操作
00459205 |. B8 70084600 mov eax, 00460870
0045920A |. E8 BBC0FAFF call 004052CA ; ReWriteText(),创建文件 annoy.txt
0045920F |. E8 6895FAFF call 0040277C ; _IOTest(void)
00459214 |. 8B15 540A4600 mov edx, dword ptr [460A54] ; edx ===> "heh...", 文件内容
0045921A |. B8 70084600 mov eax, 00460870
0045921F |. E8 90ABFAFF call 00403DB4 ; 写入文件
00459224 |. E8 FCBFFAFF call 00405225 ; Flush(),生成磁盘文件并写入内容到磁盘
00459229 |. E8 4E95FAFF call 0040277C ; _IOTest(void)
0045922E |. B8 70084600 mov eax, 00460870
00459233 |. E8 14C0FAFF call 0040524C ; Close()
00459238 |. E8 3F95FAFF call 0040277C ; _IOTest(void)
0045923D |> 33C0 xor eax, eax
0045923F |. 5A pop edx
00459240 |. 59 pop ecx
00459241 |. 59 pop ecx
00459242 |. 64:8910 mov dword ptr fs:[eax], edx
00459245 |. 68 5A924500 push 0045925A
0045924A |> 8D45 FC lea eax, dword ptr [ebp-4]
0045924D |. E8 AEA5FAFF call 00403800 ; 释放字符串资源
00459252 \. C3 retn
00459253 .^ E9 68A0FAFF jmp 004032C0
00459258 .^ EB F0 jmp short 0045924A
0045925A . 59 pop ecx
0045925B . 5D pop ebp
0045925C . C3 retn
上面代码中,有一个文件检查,如果当前目录中存在文件 annoy.txt 的话,也会弹出这条消息,然后退出。
所以,我运行 CrackMe 前,需要删除这个文件,不然也会一直无法往下走 。
每次启动前删除 annoy.txt,就不会有提示了:
回到 patch 问题,继续执行,当执行到以下位置时,会有一个跳转:
就跳转到显示我们前面説的那个消息框了,所以这一个比对需要处理,我们先看 [0x0046086E]的引用情况,在 IDA 中查看引用情况如下:
没有看到有赋值的指令,全部是比较,并且分别与 0,1,2 比较,OD 中显示 [0x0046086E] 当前值为 0,所以这里要将
[Asm] 纯文本查看 复制代码
cmp byte ptr [46086E], 1
改成
cmp byte ptr [46086E], 0
如下图所示:
就可顺利执行下一个逻辑了。继续执行,会弹出:
弹出消息说找到开窗工具,好了,那就去点窗户了(Label10),点后,弹出一消息框:
噫,patch不正确,还要patch,找到 Lable10Click 查看,如下图:
具体代码如下:
[Asm] 纯文本查看 复制代码
0045D694 /. 55 push ebp ; Label10Click(),打开窗户
0045D695 |. 8BEC mov ebp, esp
0045D697 |. 6A 00 push 0
0045D699 |. 33C0 xor eax, eax
0045D69B |. 55 push ebp
0045D69C |. 68 52D74500 push 0045D752
0045D6A1 |. 64:FF30 push dword ptr fs:[eax]
0045D6A4 |. 64:8920 mov dword ptr fs:[eax], esp
0045D6A7 |. 803D 67084600 01 cmp byte ptr [460867], 1 ; 是否开始游戏
0045D6AE |. 0F85 88000000 jnz 0045D73C
0045D6B4 |. 803D 64084600 01 cmp byte ptr [460864], 1 ; 是否已完成任务1,即是否 Lable11Click() 已通过验证
0045D6BB |. 75 7F jnz short 0045D73C
0045D6BD 803D 6E084600 02 cmp byte ptr [46086E], 2 ; 前题条件2, [0046086E]为0, patch 成与0比较: cmp byte ptr [46086E], 0
0045D6C4 |. 75 45 jnz short 0045D70B ; 跳转去提示没有正确 patch,需要 patch 后才可继续
0045D6C6 |. 6A 00 push 0 ; MessageDlg() 参数4
0045D6C8 |. FF35 680A4600 push dword ptr [460A68] ; "You through the thing in the window, and it broke :))"
0045D6CE |. 68 64D74500 push 0045D764 ; '\n'
0045D6D3 |. FF35 6C0A4600 push dword ptr [460A6C] ; "You're in the house .. what's that on the floor??"
0045D6D9 |. 68 64D74500 push 0045D764 ; '\n'
0045D6DE |. FF35 700A4600 push dword ptr [460A70] ; "It's erhm something to open a do or with ... and you picked it up"
0045D6E4 |. 8D45 FC lea eax, dword ptr [ebp-4]
0045D6E7 |. BA 05000000 mov edx, 5 ; 字符串个数,5个
0045D6EC |. E8 4B64FAFF call 00403B3C ; LStrCatN(),连接字符串
0045D6F1 |. 8B45 FC mov eax, dword ptr [ebp-4] ; string
0045D6F4 |. 66:8B0D 68D74500 mov cx, word ptr [45D768] ; cx == 0x0004, mtConfirmation
0045D6FB |. B2 03 mov dl, 3 ; [mbOK]
0045D6FD |. E8 2E6AFEFF call 00444130 ; MessageDlg(),显示成功提示
0045D702 |. C605 69084600 01 mov byte ptr [460869], 1 ; 设置已完成任务2,打开窗口
0045D709 |. EB 31 jmp short 0045D73C
0045D70B |> 6A 00 push 0 ; MessageDlg() 参数4
0045D70D |. FF35 740A4600 push dword ptr [460A74] ; "You through the thing in the window, but it pansered"
0045D713 |. 68 64D74500 push 0045D764 ; '\n'
0045D718 |. FF35 780A4600 push dword ptr [460A78] ; "maybe it needs a fix? yer that's right patch it :)"
0045D71E |. 8D45 FC lea eax, dword ptr [ebp-4]
0045D721 |. BA 03000000 mov edx, 3 ; 字符串个数,3个
0045D726 |. E8 1164FAFF call 00403B3C ; LStrCatN(),连接字符串
0045D72B |. 8B45 FC mov eax, dword ptr [ebp-4] ; string
0045D72E |. 66:8B0D 68D74500 mov cx, word ptr [45D768] ; [4], [mbRetry]
0045D735 |. B2 03 mov dl, 3
0045D737 |. E8 F469FEFF call 00444130 ; MessageDlg(),显示失败提示
0045D73C |> 33C0 xor eax, eax
0045D73E |. 5A pop edx
0045D73F |. 59 pop ecx
0045D740 |. 59 pop ecx
0045D741 |. 64:8910 mov dword ptr fs:[eax], edx
0045D744 |. 68 59D74500 push 0045D759
0045D749 |> 8D45 FC lea eax, dword ptr [ebp-4]
0045D74C |. E8 AF60FAFF call 00403800
0045D751 \. C3 retn
0045D752 .^ E9 695BFAFF jmp 004032C0
0045D757 .^ EB F0 jmp short 0045D749
0045D759 . 59 pop ecx
0045D75A . 5D pop ebp
0045D75B . C3 retn
看到没有,在IDA中出现的 cmp ds:byte_4608E, 2 就在这个事件里,与 2 比较,就预示着这是第二个需要 patch 的地方了,因为不 patch 就会跳转去弹出前面那个消息框,于是将:
[Asm] 纯文本查看 复制代码
cmp byte ptr [46086E], 2
改成
cmp byte ptr [46086E], 0
如下图所示:
重新点击 Label10,激发 Click 事件,这次显示消息框如下:
说是你爬窗而入了,到房子里了。。。地板上有啥?好象是开门用的。。。(密码),捡起 来吧。于是再去点门(Label7),这次没有弹出消息框,弹出 Form2 了:
果然,要输入进门密码了。
先看看 Label7Click事件代码,如下图所示:
具体代码如下:
[Asm] 纯文本查看 复制代码
;;; =========================================================== Form1.Label7Click(), Door =====================================
0045D574 . 803D 67084600 01 cmp byte ptr [460867], 1 ; 是否开始游戏
0045D57B . 0F85 8C000000 jnz 0045D60D
0045D581 . 803D 69084600 01 cmp byte ptr [460869], 1 ; 是否已完成任务2
0045D588 . 75 65 jnz short 0045D5EF
0045D58A . A1 C8F64500 mov eax, dword ptr [45F6C8] ; Form2
0045D58F . 8B00 mov eax, dword ptr [eax]
0045D591 . B2 01 mov dl, 1 ; dl == 0x01,显示
0045D593 . E8 F8D1FDFF call 0043A790 ; Form2.Show(),显示 Form2,用于输入密码
0045D598 . A1 C8F64500 mov eax, dword ptr [45F6C8] ; Form2
0045D59D . 8B00 mov eax, dword ptr [eax]
0045D59F . 8B80 C4020000 mov eax, dword ptr [eax+2C4] ; 文本框
0045D5A5 . 33D2 xor edx, edx ; edx ===> null string,清空文本框
0045D5A7 . E8 6475FCFF call 00424B10 ; TControl.SetText()
0045D5AC . A1 C8F64500 mov eax, dword ptr [45F6C8] ; Form2
0045D5B1 . 8B00 mov eax, dword ptr [eax]
0045D5B3 . 8B80 C8020000 mov eax, dword ptr [eax+2C8] ; 文本框提示
0045D5B9 . 8B15 840A4600 mov edx, dword ptr [460A84] ; edx ===> "Enter the correct code"
0045D5BF . E8 4C75FCFF call 00424B10 ; TControl.SetText()
0045D5C4 . 803D 6B084600 00 cmp byte ptr [46086B], 0 ; 进入次数,Form2,Button1Click() 修改
0045D5CB . 75 40 jnz short 0045D60D
0045D5CD . 803D 6C084600 01 cmp byte ptr [46086C], 1 ; 提示次数,Form2,Button1Click() 修改
0045D5D4 . 75 37 jnz short 0045D60D
0045D5D6 . A1 C8F64500 mov eax, dword ptr [45F6C8] ; Form2
0045D5DB . 8B00 mov eax, dword ptr [eax]
0045D5DD . 8B80 C8020000 mov eax, dword ptr [eax+2C8] ; 文本框提示
0045D5E3 . 8B15 900A4600 mov edx, dword ptr [460A90] ; edx ===> "What's the code for the computer ??"
0045D5E9 . E8 2275FCFF call 00424B10 ; TControl.SetText(), 第1次正确后,修改 Form2 提示信息
0045D5EE . C3 retn
0045D5EF > 803D 66084600 00 cmp byte ptr [460866], 0 ; Form1Create()中初始化为 0
0045D5F6 . 75 15 jnz short 0045D60D
0045D5F8 . 6A 00 push 0
0045D5FA . 66:8B0D 10D64500 mov cx, word ptr [45D610] ; ex == 0x0004,mtConfirmation
0045D601 . B2 03 mov dl, 3
0045D603 . A1 400A4600 mov eax, dword ptr [460A40] ; eax ===> "kicking the door in?? Uhhh that's gotta hurt .. without boots damn .. :)"
0045D608 . E8 236BFEFF call 00444130 ; 显示失败提示信息,先要完成任务2
0045D60D > C3 retn
主要就是满足条件后,显示 Form2,不然就提示失败(不能踹门而入,要撬锁而入的意思)。
为了便于跟踪,我们先保存刚才修改好的两处 Patch,不然超时退出后,每次都要去改代码,利用 OD 保存 patch 功能:
选择“所有修改”,并确认后,如下,再右键保存:
选择”保存文件“,取一个新文件名,就可以了,然后用 OD 加载新的 CrackMe 程序。
我们先进入 Form2 的 Button1Click()事件看看,先找到其入口:
在 OD 中 Ctrl + G,输入上面找到的入口地址:
直接来到其事件代码入口,如下图所示:
在其事件代码中下一断点,便于动态跟踪分析。
再次 F9 直接运行程序,这次我们很快就可以弹出 Form2 了(按 Label11Click()-->Label10Click()-->Label7Click() 的顺序点击,不会再有patch的提醒了,如果还有的话,老老实实的去删除文件 annoy.txt 吧),Form2 中只有一个 Button1Click 事件,其代码如下:
[Asm] 纯文本查看 复制代码
;;;;=========================================================== Form2. Button1Click() =========================================
00458CD4 /. 55 push ebp ; Form2.Button1Click()
00458CD5 |. 8BEC mov ebp, esp
00458CD7 |. 6A 00 push 0
00458CD9 |. 53 push ebx
00458CDA |. 8BD8 mov ebx, eax
00458CDC |. 33C0 xor eax, eax
00458CDE |. 55 push ebp
00458CDF |. 68 F88D4500 push 00458DF8
00458CE4 |. 64:FF30 push dword ptr fs:[eax]
00458CE7 |. 64:8920 mov dword ptr fs:[eax], esp
00458CEA |. 8D55 FC lea edx, dword ptr [ebp-4] ; 返回地址缓冲区
00458CED |. 8B83 C4020000 mov eax, dword ptr [ebx+2C4]
00458CF3 |. E8 E8BDFCFF call 00424AE0 ; TControl.GetText(), 取假码 "78787878",eax 返回长度
00458CF8 |. 8B45 FC mov eax, dword ptr [ebp-4] ; eax ===> "78787878"
00458CFB |. 8B15 C8F54500 mov edx, dword ptr [45F5C8] ; CRACKME_.00460A88
00458D01 |. 8B12 mov edx, dword ptr [edx] ; edx ===> "123-456-789-000",第1次点门输入这个密码
00458D03 |. E8 84AEFAFF call 00403B8C ; LStrCmp(), 字符比较
00458D08 |. 75 08 jnz short 00458D12 ; 不相等跳转
00458D0A |. A1 88F54500 mov eax, dword ptr [45F588]
00458D0F |. C600 01 mov byte ptr [eax], 1 ; 设置标志1
00458D12 |> 8D55 FC lea edx, dword ptr [ebp-4]
00458D15 |. 8B83 C4020000 mov eax, dword ptr [ebx+2C4]
00458D1B |. E8 C0BDFCFF call 00424AE0 ; TControl.GetText(),再次取假码 "78787878"
00458D20 |. 8B45 FC mov eax, dword ptr [ebp-4] ; eax ===> "78787878"
00458D23 |. 8B15 8CF34500 mov edx, dword ptr [45F38C] ; CRACKME_.00460A8C
00458D29 |. 8B12 mov edx, dword ptr [edx] ; edx ===> "456-678",第2次点门输入这个密码
00458D2B |. E8 5CAEFAFF call 00403B8C ; LStrCmp(), 字符比较
00458D30 |. 75 08 jnz short 00458D3A ; 不相等跳转
00458D32 |. A1 00F54500 mov eax, dword ptr [45F500]
00458D37 |. C600 01 mov byte ptr [eax], 1 ; 设置标志2
00458D3A |> A1 88F54500 mov eax, dword ptr [45F588]
00458D3F |. 8038 01 cmp byte ptr [eax], 1 ; 检查标志1
00458D42 |. 75 7B jnz short 00458DBF
00458D44 |. A1 00F54500 mov eax, dword ptr [45F500]
00458D49 |. 8038 00 cmp byte ptr [eax], 0 ; 检查标志2
00458D4C |. 75 29 jnz short 00458D77
00458D4E |. A1 94F44500 mov eax, dword ptr [45F494]
00458D53 |. 8038 00 cmp byte ptr [eax], 0 ; 检查标志3
00458D56 |. 75 1F jnz short 00458D77
00458D58 |. 6A 00 push 0
00458D5A |. A1 9CF34500 mov eax, dword ptr [45F39C] ; [eax] ===> "and the door opens! :)"
00458D5F |. 8B00 mov eax, dword ptr [eax]
00458D61 |. 66:8B0D 048E4500 mov cx, word ptr [458E04] ; mtConfirmation
00458D68 |. B2 03 mov dl, 3
00458D6A |. E8 C1B3FEFF call 00444130 ; MessageDlg(),提示进门密码正确
00458D6F |. A1 94F44500 mov eax, dword ptr [45F494]
00458D74 |. C600 01 mov byte ptr [eax], 1 ; 设置标志3
00458D77 |> A1 00F54500 mov eax, dword ptr [45F500]
00458D7C |. 8038 01 cmp byte ptr [eax], 1 ; 检查标志2
00458D7F |. 75 55 jnz short 00458DD6 ; 第1次检查门密码,从这里退出
00458D81 |. A1 94F54500 mov eax, dword ptr [45F594] ; Form3
00458D86 |. 8B00 mov eax, dword ptr [eax]
00458D88 |. B2 01 mov dl, 1 ; dl == 1,显示
00458D8A |. E8 011AFEFF call 0043A790 ; Form.Show(),显示 Form3
00458D8F |. A1 94F54500 mov eax, dword ptr [45F594] ; Form3
00458D94 |. 8B00 mov eax, dword ptr [eax]
00458D96 |. 8B80 CC020000 mov eax, dword ptr [eax+2CC]
00458D9C |. B2 01 mov dl, 1 ; dl == 1, enabled
00458D9E |. E8 3DA4FEFF call 004431E0 ; 启动 Form3 的 Timer,显示下载进度
00458DA3 |. 8B15 00F74500 mov edx, dword ptr [45F700] ; CRACKME_.00460A98
00458DA9 |. 8B12 mov edx, dword ptr [edx] ; [edx] ===> "Downloading file ...."
00458DAB |. A1 94F54500 mov eax, dword ptr [45F594] ; Form3
00458DB0 |. 8B00 mov eax, dword ptr [eax]
00458DB2 |. 8B80 C4020000 mov eax, dword ptr [eax+2C4]
00458DB8 |. E8 53BDFCFF call 00424B10 ; TControl.SetText()
00458DBD |. EB 17 jmp short 00458DD6
00458DBF |> 6A 00 push 0
00458DC1 |. A1 44F44500 mov eax, dword ptr [45F444]
00458DC6 |. 8B00 mov eax, dword ptr [eax] ; eax ===> "nope the code isn't correct :`"
00458DC8 |. 66:8B0D 048E4500 mov cx, word ptr [458E04] ; cx == 0x0004, mtConfirmation
00458DCF |. B2 03 mov dl, 3
00458DD1 |. E8 5AB3FEFF call 00444130 ; MessageDlg(),提示输入的密码不正确
00458DD6 |> 33D2 xor edx, edx ; dl == 0, 隐藏
00458DD8 |. A1 58084600 mov eax, dword ptr [460858]
00458DDD |. E8 AE19FEFF call 0043A790 ; Form.Hide(),关闭(隐藏) Form2
00458DE2 |. 33C0 xor eax, eax
00458DE4 |. 5A pop edx
00458DE5 |. 59 pop ecx
00458DE6 |. 59 pop ecx
00458DE7 |. 64:8910 mov dword ptr fs:[eax], edx
00458DEA |. 68 FF8D4500 push 00458DFF
00458DEF |> 8D45 FC lea eax, dword ptr [ebp-4]
00458DF2 |. E8 09AAFAFF call 00403800
00458DF7 \. C3 retn
00458DF8 .^ E9 C3A4FAFF jmp 004032C0
00458DFD .^ EB F0 jmp short 00458DEF
00458DFF . 5B pop ebx
00458E00 . 59 pop ecx
00458E01 . 5D pop ebp
00458E02 . C3 retn
代码比较简单,就是两次明文密码比较,第一次为 "123-456-789-000",如下所示:
如果密码不正确,比如输入下面的假码:
则会提示:
输入正确的密码(123-456-789-000)后,会弹出一个消息:
显示门已开,点确定后,回到主界面。我们再次点门(Label7),这次又弹出如下界面:
需要输入电脑密码,我们输入前面发现的第二个明文密码”456-678”,如下图所示:
点“okay" 后,弹出一个带进度条的下载界面(Form3),模拟一个下载过程,如下图所示:
这个进度条也是由定时器来处理的,代码如下:
[Asm] 纯文本查看 复制代码
00458A7C . 53 push ebx ; Fotm3.Timer1Timer()
00458A7D . 56 push esi
00458A7E . 8BD8 mov ebx, eax ; Sender, Form3
00458A80 . 8BB3 C8020000 mov esi, dword ptr [ebx+2C8]
00458A86 . 8BC6 mov eax, esi
00458A88 . E8 67FBFFFF call 004585F4 ; GetPosition()
00458A8D . 8BD0 mov edx, eax
00458A8F . 42 inc edx
00458A90 . 8BC6 mov eax, esi
00458A92 . E8 0DFDFFFF call 004587A4 ; SetPosition()
00458A97 . 8B83 C8020000 mov eax, dword ptr [ebx+2C8]
00458A9D . E8 52FBFFFF call 004585F4 ; GetPosition()
00458AA2 . 83F8 64 cmp eax, 64 ; 100,循环100次,模拟下载过程
00458AA5 . 7C 53 jl short 00458AFA
00458AA7 . 33D2 xor edx, edx ; dl == 0
00458AA9 . 8B83 CC020000 mov eax, dword ptr [ebx+2CC]
00458AAF . E8 2CA7FEFF call 004431E0 ; 停止 Form3 的 Timer
00458AB4 . A1 A8F64500 mov eax, dword ptr [45F6A8] ; Form1
00458AB9 . 8B00 mov eax, dword ptr [eax]
00458ABB . 8B80 F4020000 mov eax, dword ptr [eax+2F4]
00458AC1 . 33D2 xor edx, edx ; dl == 0, disabled
00458AC3 . E8 18A7FEFF call 004431E0 ; 停止 Form1 的 Timer
00458AC8 . 6A 00 push 0
00458ACA . A1 30F44500 mov eax, dword ptr [45F430]
00458ACF . 8B00 mov eax, dword ptr [eax] ; [eax] ===> "You've succeded this crackme .. cool :) now write to [url=mailto:woody@post9.tele.dk]woody@post9.tele.dk[/url] and tell me all about it"
00458AD1 . 66:8B0D 008B4500 mov cx, word ptr [458B00] ; cx == 0x0004, mtConfirmation
00458AD8 . B2 03 mov dl, 3
00458ADA . E8 51B6FEFF call 00444130 ; MessageDlg(),显示成功破解的提示
00458ADF . 48 dec eax
00458AE0 . 75 18 jnz short 00458AFA
00458AE2 . 33D2 xor edx, edx ; dl == 0,隐藏
00458AE4 . A1 50084600 mov eax, dword ptr [460850]
00458AE9 . E8 A21CFEFF call 0043A790 ; Form.Hide(),关闭 Form3
00458AEE . A1 A8F64500 mov eax, dword ptr [45F6A8] ; Form1
00458AF3 . 8B00 mov eax, dword ptr [eax]
00458AF5 . E8 D24BFEFF call 0043D6CC ; Form1.Close(),结束 CrackMe
00458AFA > 5E pop esi
00458AFB . 5B pop ebx
00458AFC . C3 retn
如果下载结束还没有超时,就会将 Form1 的倒计时定时器停止,不再倒计时。
并且,等进度条走完后,就会弹出下面的消息框:
显示成功了!!!只有点”OK“后,才会退出 CrackMe 了,不会再由 Form1 的定时器强行退出了。
下面附加分析一下。
因为主界面上按”开始“后,有一个30秒计时,30秒一到,没有解开游戏就会 结束,所以,我们只要把那个定时器不启动,就可以成”无敌 “状态了,Button1Click()事件改动如下:
[Asm] 纯文本查看 复制代码
0045D67C . C605 67084600 01 mov byte ptr [460867], 1 ; 开始游戏
0045D683 . B2 00 mov dl, 0 ; dl == 1, Enabled, 当 dl == 0 时,禁用定时器,变成无敌状态
0045D685 . 8B80 F4020000 mov eax, dword ptr [eax+2F4]
0045D68B . E8 505BFEFF call 004431E0 ; 启动 Timer1,或禁用 Timer1
0045D690 . C3 retn
按上面改动后,就无敌了。
还有就是那个文件 的问题,当CrackMe启动时会检测文件是否存在,如果存在也会报需要 patch 而无法往下走,我们也把这个问题 patch 一下,让 CrackMe 无法生成这个 annoy.txt 文件,我们修改 Label11Click() 事件的代码,具体修改如下:
[Asm] 纯文本查看 复制代码
;; Label11Click() 部分代码
;
004591CE |. 803D 6E084600 00 cmp byte ptr [46086E], 0 ; [46086E] 不能大于 0
004591D5 |. 77 09 ja short 004591E0
004591D7 |. C605 64084600 01 mov byte ptr [460864], 1 ; 设置标志,已完成任务1,表示找到工具
004591DE |. EB 15 jmp short 004591F5 ; 跳转去生成文件:annoy.txt
; 最后的jmp 改成如下代码:
004591DE |. EB 5D jmp short 0045923D ; 不生成文件改成 jmp 0045923D,就没有文件干拢了
上面两处代码改好后,同样用 OD 保存 Patch 的功能,保存到一个新文件即可。
分析完毕!!!
免费评分
查看全部评分