https://www.52pojie.cn/thread-709699-1-1.html
将上面链接中的160个CrackMe的打包文件
下载下来之后, 打开该chm
, 选择第一个Acid burn
, 下载保存到本地, 然后解压, 运行其中的 exe 程序
壳是啥? 为啥要查壳脱壳? 不懂, 先跳过!
程序是使用delphi
编写的无壳
首先了解下这个软件运行时的情况,记录下有哪几个需要破解的位置。
程序运行时会弹出一个NAG窗口
, 标题是hello you have to kill me
,这个窗口是要去除的
NAG窗口
: 软件未注册或软件的试用版经常会弹出一些提示窗口要求注册,这些窗口被称为nag窗口
然后点击确定
后进入程序的主窗口
进去后发现有两个按钮, 根据按钮上的字符串判断应该是需要输入序列号和名称的位置。
首先看下左边那个按钮,点击进去看下情况,发现有两个输入框,分别是输入用户名和序列号,然后点击Check it Baby
,程序会进行校验,校验失败会弹出下面窗口,提醒你Try Again!!
可以发现上面这个位置是一个需要破解的点。
然后点击I give up
按钮返回到程序的主界面,看下右边那个按钮的情况。
点击进去后发现有一个输入框,提醒你输入序列号,然后点击Check it Baby
,程序会进行校验,校验失败会弹出下面窗口,提示你Failed!
记录下这个位置也是一个需要破解的点。
综上所述,我们可以看到这个程序有三个点需要破解:
首先我们先要破解第一个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
重新运行, 不断使用F9
和F7
使得程序运行到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窗口去除成功
随便输入一组错误的序列号, 程序弹出一个失败的提示框
可以从这个字符串入手, 启动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
, 以达到随便输入都弹出正确的框框, 具体操作此处不再重复.
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!
, 如下:
最后, 按照上面讲过的流程, 保存下来即可
至此, 这个程序的破解工作已经全部完成!
我们大概学了如下内容:
jnz
的跳转, 即改成NOP; 强制跳转, 即改成jmp
欢迎大家访问我的博客: https://fengwenhua.top , 虽然博客上面没啥东西!