CrackMe001

江南小虫虫 2020年02月08日 72次浏览

https://www.52pojie.cn/thread-709699-1-1.html

下载下来之后, 打开该chm, 选择第一个Acid burn, 下载保存到本地, 然后解压, 运行其中的 exe 程序

0x00 查壳

壳是啥? 为啥要查壳脱壳? 不懂, 先跳过!

程序是使用delphi编写的无壳

0x01 分析程序

首先了解下这个软件运行时的情况,记录下有哪几个需要破解的位置。

程序运行时会弹出一个NAG窗口, 标题是hello you have to kill me,这个窗口是要去除的

NAG窗口: 软件未注册或软件的试用版经常会弹出一些提示窗口要求注册,这些窗口被称为nag窗口

然后点击确定后进入程序的主窗口

进去后发现有两个按钮, 根据按钮上的字符串判断应该是需要输入序列号和名称的位置。

首先看下左边那个按钮,点击进去看下情况,发现有两个输入框,分别是输入用户名和序列号,然后点击Check it Baby,程序会进行校验,校验失败会弹出下面窗口,提醒你Try Again!!

可以发现上面这个位置是一个需要破解的点。

然后点击I give up按钮返回到程序的主界面,看下右边那个按钮的情况。

点击进去后发现有一个输入框,提醒你输入序列号,然后点击Check it Baby,程序会进行校验,校验失败会弹出下面窗口,提示你Failed!

记录下这个位置也是一个需要破解的点。

综上所述,我们可以看到这个程序有三个点需要破解:

  1. 程序主界面之前的一个NAG窗口
  2. Serial/Name校验页面
  3. Serial校验页面

0x02 NAG窗口去除

首先我们先要破解第一个NAG窗口, 启动OllyDbg软件, 选择菜单的文件-> 打开-> 选择Acid burn.exe

此时文件会停留在如下位置, 双击注释位置能添加自定义注释

用OD打开后可以按F8单步步过, 调试一遍看下程序的调用情况. 可以发现单步调试到 call Acid_bur.00429F8C 时, 第一个NAG窗口出现了

每按一次F8, 将执行反汇编窗口中的一条指令, 遇到CALL等子程序不进入其代码

很明显第一个NAG窗口的主函数在这个调用函数里面, 所以在这个点按F2下一个断点, 断点下成功会变红

F2之后, 程序运行到此处会暂停, 再按一次F2键会删除断点

然后按Ctrl+F2重新加载程序, 按F9运行到断点call Acid_bur.00429F8C处, 按F7单步步入 进入该函数, 然后再继续按F8单步步过调试,在call dword ptr ds:[esi+0x24] 这个位置NAG窗口又出来了

Ctrl+F2: 重新运行程序.
F9: 如果没有设置断点, 被调试的程序会直接开始运行; 如果设置了断点, 程序会停在断点处.
F7: 单步步入, 功能和单步步过F8类似, 区别是遇到CALL等子程序时会进入其中

老方法, 按F2下断点、Ctrl+F2重新加载程序,按F9运行到第一个断点call Acid_bur.00429F8C处, F7进入函数, 按F9运行到第二个断点call dword ptr ds:[esi+0x24], 按F7进入该函数, 继续F8单步调试,在call dword ptr ds:[ebx+0x1CC]位置NAG窗口继续弹出

老规矩, F2下断点, Ctrl+F2重新运行, 不断使用F9F7使得程序运行到call dword ptr ds:[ebx+0x1CC]

然后我们直接按F7单步步入进去, F7进入call Acid_bur.0042A170

此时我们可以看到熟悉的字眼MessageBoxA, 显然这个第四次进入的函数call dword ptr ds:[ebx+0x1CC], 就是调用弹出对话框的函数. 所以, 不应该继续往下分析了, 应该往回看.

Esc, 回到第四次进入, 调用弹框的地方, 没啥好分析的, 就是一些赋值, 应该是对话框的标题, 内容之类的

再按几次Esc, 回到第三次进入的地方

在这个位置我们需要注意一下, 此处存在比较语句cmp和跳转语句je

cmp: 用第一个操作减去第二个操作数, 若执行指令后, ZF=1, 则说明两个数相等, 因为zero为1说明结果为0.
zf 代表 Zero Flag, 表示零标志位
je 代表 jmp equal, 表示等于就跳转, 是否等于可以看zf的值, zf=1, 则跳转; zf=0则不跳转

我们将代码重新执行一次, F8运行到这个je语句这里, 留意到右边寄存器窗口, 此时的zf=0, 说明不会跳转, 因为不跳转, 所以执行了弹框函数call dword ptr ds:[ebx+0x1CC]

注意左边的线, 白色说明不跳, 红色则会跳

因此这里我们可以使用暴力破解的方式直接jmp过来, 跳过弹窗函数

双击je short Acid_bur.00425643, 将弹框内的je short 00425643改成jmp 00425643, 点击汇编

这样修改是为了程序运行到0042562F处直接跳到00425643处, 越过弹窗函数

修改完毕后我们右键->复制到可执行文件->所有修改->全部复制

然后自动跳到D窗口右键->保存文件, 将程序重命名为Acid_burn1.exe

然后按F3加载Acid burn1.exe程序,按F9直接运行可以发现没有了NAG窗口, 至此, 第一个NAG窗口去除成功

0x03 分析Serial

随便输入一组错误的序列号, 程序弹出一个失败的提示框

可以从这个字符串入手, 启动OllyDbg软件,选择菜单的文件-> 打开-> 选择Acid burn.exe

此时文件会停留在如下位置, 双击注释位置能添加自定义注释

在反汇编窗口右键鼠标,选择查找->所有参考文本字串

弹出如下图所示的对话框

右键选择查找文本-> 输入Try定位Try Again!!位置

接着右键鼠标,点击反汇编窗口中跟随

接着定位到如下图所示位置

可以看到, 除了Try Agained!!, Failed之外, 上面还有Congratz!God Job dude!!

我们先看看Try Again!!在哪先, 选中该语句右键查找参考->选定地址(快捷键Ctrl+R)

弹出如下图所示的参考页面

双击上面的地址(0042F4F8), 去到对应的位置

然后我们按Esc返回, 再查看其他的位置, 在反汇编窗口加上注释如下:

注意查看此时的反汇编窗口的汇编代码

JNZ = jump if not zero 运算结果不为零则跳转, 即ZF不为1时跳转

简单讲一下这里的逻辑: 先调用一个函数call Acid_bur.004039FC, 如果返回结果不为0, 则jnz short Acid_bur.0042F4F1, 即跳转到下面的失败弹框; 如果返回结果为0, 则不跳转, 执行成功的弹框.

成功弹框执行完成之后, 会有一个jmp short Acid_bur.0042F509, 跳过失败弹框的逻辑, 因为前面已经执行完成功弹框的逻辑了, 当然要跳过失败弹框的逻辑啦!

走到这一步就很好解决了, 得出方法一: 修改上面的JNZ改为NOP, 让他直接往下执行就行了呗

NOP是英语No Operation的缩写。NOP无操作数,所以称为空操作。

方法一

双击jnz short Acid_bur.0042F4F1, 改成nop

修改完毕后我们右键->复制到可执行文件->所有修改->全部复制

然后自动跳到D窗口右键->保存文件, 将程序重命名为Acid_burn2.exe

然后按F3加载Acid burn2.exe程序, 按F9直接运行, 此时随便输入一个序列号, 如下图:

方法二

方法一的思路是, 不管前面的函数返回啥, 我将jnz short Acid_bur.0042F4F1, 改成nop, 直接不跳转, 让程序继续往下执行.

这里我们不妨在这个jnz前面的函数call Acid_bur.004039FC上按F2插入一个断点, 看看发生了这个函数发生了啥

插入断点后, Ctrl+F2重新运行, F9运行, 然后打开Serial窗口, 随便输入一个序列号, 比如我输入了sdfsdf, 然后点击Check it Baby!

切换OD, 程序自动停到当前断点处, 此时注意右边寄存器窗口中出现了两个值, EAX的值是我们输入的sdfsdf, 而EDX的值是Hello Dude!, 很可能这个值就是真正的序列号

验证的方法很简单, Ctrl+F2重新运行 ->F9运行, 输入该字符串Hello Dude!->F9继续运行, 弹框如下:

发现Hello Dude!就是正确的序列号

秉着严谨的态度, 我们按F7进去该函数看一下, 看到了熟悉的cmp, 以及下面的je

这里的je跳转没有实现, 所以, 我们可以参考上面的NAG窗口去除, 直接修改成jmp, 直接跳到00403A9A, 以达到随便输入都弹出正确的框框, 具体操作此处不再重复.

0x04 分析Serial/Name

F3 加载解决Serial之后保存的的Acid burn2.exe, F9直接运行, 然后随便输入, 点击Check it Baby!, 此时的错误弹框先不要关

回到OD, 按F12暂停, 点击堆栈K小图标(Ctrl+K), 如下图:

这里有两个MessageBox的地址,第一个地址为77D5082F这个地址明显太大, 不在模块的领空, 不是的。第二个地址为0042A1AE, 和00400100地址非常接近,十有八九就是它了。

关于程序领空系统领空, 具体请查看 https://www.52pojie.cn/thread-75582-1-1.html , 我们只需要明白 00400000这个基址开始的地址,一直到00488000结束的基址都是程序领空

右键-> 显示调用

注意观察弹框开始的 push ebp左边, 那里有一根线, 可以帮助我们定界

在头部push ebp下按F2下断点, Ctrl+F2重新运行, F9运行, 重新随便输入序列号和名字, 点击Check it baby!! 按钮, 程序停在断电处, 此时在右下角堆栈处找到最近一条Return语句

0012F974   0042FB37  返回到 Acid_bur.0042FB37 来自 Acid_bur.0042A170

右键->反汇编窗口中跟随

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
0042FAF8  |.  8B55 F0       mov edx,[local.4]
0042FAFB  |.  8B45 F4       mov eax,[local.3]
0042FAFE  |.  E8 F93EFDFF   call Acid_bur.004039FC
0042FB03  |.  75 1A         jnz short Acid_bur.0042FB1F              ;  这是个关键的判断
0042FB05  |.  6A 00         push 0x0
0042FB07  |.  B9 CCFB4200   mov ecx,Acid_bur.0042FBCC
0042FB0C  |.  BA D8FB4200   mov edx,Acid_bur.0042FBD8
0042FB11  |.  A1 480A4300   mov eax,dword ptr ds:[0x430A48]
0042FB16  |.  8B00          mov eax,dword ptr ds:[eax]               ;  Acid_bur.00424090
0042FB18  |.  E8 53A6FFFF   call Acid_bur.0042A170
0042FB1D  |.  EB 18         jmp short Acid_bur.0042FB37              ;  这个跳转跳过了错误弹框
0042FB1F  |>  6A 00         push 0x0
0042FB21  |.  B9 74FB4200   mov ecx,Acid_bur.0042FB74                ;  ASCII 54,"ry Again!"
0042FB26  |.  BA 80FB4200   mov edx,Acid_bur.0042FB80                ;  ASCII 53,"orry , The serial is incorect !"
0042FB2B  |.  A1 480A4300   mov eax,dword ptr ds:[0x430A48]
0042FB30  |.  8B00          mov eax,dword ptr ds:[eax]               ;  Acid_bur.00424090
0042FB32  |.  E8 39A6FFFF   call Acid_bur.0042A170                   ;  错误弹框
0042FB37  |>  33C0          xor eax,eax                              ;  返回到了这里

简单分析一下上面的代码: jnz short Acid_bur.0042FB1F会通过它上面的call Acid_bur.004039FC 判断我们的输入是否正确,判断的结果存在EAX中,如果EAX不等于就跳转到错误提示信息框那里

我们的目的是无论输入是否正确都通过验证, 所以最简单的办法就是将jnz short Acid_bur.0042FB1F这句使用NOP填充

我们尝试一下:选择JNZ这句,右键->二进制->用NOP填充. 按F9继续运行程序

回到原始程序,再次点击Check it baby!, 发现它卡住了, 莫慌, 是因为我们之前在push ebp下了一个断点, 切换回OD, 再按F9运行, 如下图:

此时我们重新打开未修改过Acid burn2.exe, 再让它弹出错误窗口, 切换OD, 再按F12暂停一下, 按堆栈k小图标(Ctrl+K)窗口, 看一下最后一个调用, 是不是发现什么特殊的地方?

对啦!那个CALL就是调用MessageBox的地方,所以,下次我们就不用在MessageBox处下断跟踪了,直接最后一个地址->右键->显示调用

得知这个小技巧之后, 我们还需要处理最后一个小问题, 如果输入的Serial的长度小于4, 就会弹出错误的窗口.

我们保持当前错误窗口别关掉, 回到OD, 按F12暂停->点堆栈k小图标->最后一个地址->显示调用

显然, 我们的目的就是让它无论如何都要跳, 所以直接将jge short Acid_bur.0042FA79改成jmp 0042FA79即可

F9运行->切换程序->再点一下Check it Baby!, 如下:

最后, 按照上面讲过的流程, 保存下来即可

0x05 总结

至此, 这个程序的破解工作已经全部完成!

我们大概学了如下内容:

  1. OD的一些快捷键, 如F7, F8, F9, F12等等
  2. 字符串搜索定位
  3. F12暂停法分析程序
  4. 修改完后怎么保存
  5. 取消类似jnz的跳转, 即改成NOP; 强制跳转, 即改成jmp
  6. 还有复习了一些汇编语法