05.分析 abex'crackme

1. abex'crackme

运行这个 abex'crackme 这个程序,会提示两个信息
Pasted image 20250311174925
Pasted image 20250311174932

2. 开始调试

虽然看不到在搞什么名堂,还是直接用OD进行调试吧
Pasted image 20250311175255
进来后会发现EP代码非常短。这是因为这个程序是用汇编语言编写出来的可执行文件

使用VC++、VC、Delphi等开发工具编写程序时,除了自己编写的代码外,还有一部分启动函数是由编译器添加的,经过反编译后,代码看上去就变得非常复杂。

但是如果直接使用汇编语言编写程序,汇编代码会直接变为反汇编代码。观察图6-3中的代码可以看到,main 直接出现在EP中,简洁又直观,充分证明了这是一个直接用汇编语言编写的程序。

分析代码可以发现 在第一个弹框点击确认后,程序会调用 GetDriveType() API,获取C驱动器的类型。 (大部分都是HDD类型),然后操作它使之被识别为CD-ROM类型。然后就会输出 成功后的提示

2.1. 破解

我们使用f8去一步一步执行,可以发现在 JE short 0040103D 处因为条件不满足导致无法跳转到 40103D
从而进入了错误的判断当中
Pasted image 20250311180635
这里我们对 je short 40103d 反汇编 把 je 改成 jmp即可
Pasted image 20250311180723
然后运行即可进入正确的代码逻辑中
Pasted image 20250311180809

2.2. 将参数压入栈

这里介绍一下函数调用时将函数参数压入栈中的方法

我们查看 40100-40100E 之间的命令
Pasted image 20250311180931
可以发现调用 messageboxwA 函数之前使用了4个PUSH命令,把函数需要的参数 逆序压入栈
然后这是C语言的函数调用代码

MessageBox(NULL, "Make me think your HD is a CD-Rom.", "abex' 1stCrackme", MB_OK|MB_APPLMODAL);

可以发现两者传入参数的顺序是不同的。
函数调用时的参数顺序(正序)与参数入栈时的顺序(逆序)相反。

这里就是因为栈的结构是FILO 先进后出,即出入栈会交换顺序
我们是要先把参数入栈,然后再出栈传递给函数进行调用。所以需要逆序入栈,从而使得是正序出栈

我们把程序执行到EIP= 40100E 处观察栈窗口
Pasted image 20250311181809
从这个栈中取出数据就是正序的了。也就可以正确的传递给函数参数进行调用

个人理解:因为栈是向低地址延申的。所以低地址是栈顶,高地址是栈底。所以出来的顺序就是 NULL Make me .... 也就是正序的了。