逆向工程核心原理笔记(五)——分析abex’ crackme#1
下面我们将分析一个很简单的crackme小程序,从而进一步熟悉调试器和汇编代码,当然我们的目标不是进行crack(破解)而是加深汇编打吗和调试技术的认识。
Abex’ crackme是一个著名的小程序,这是一个公开用作破解练习的小程序。
首先我们先运行abex’ crackme#1这个程序:
显示一个消息窗口,显示"Make me think your HD is a CD-Rom"消息。我们此时并不知道程序在这里是在干什么。于是我们点击确定运行下一步。
此时程序弹出 Error 窗口后运行终止,但是这个小程序的真正用途并不清楚。接下来我们尝试调试分析这个小程序。
接下来我们用 OD 载入小程序,看到汇编代码。
EP代码很简短,是因为 abex’ crackme 程序是使用汇编语言编写的可执行文件,使用编译器编写程序时,除了自己编写的代码,由于一部分启动函数由编译器自动添加,经过反编译后,代码看上去会十分复杂,但是如果直接使用汇编语言编写代码时候,汇编代码会直接反汇编为反汇编代码,程序较为简单和直观。
由于代码本身很简短,我们可以一点点分析。
上面的代码片是关于 Win32 API 调用的内容。
在消息窗口按确定后,程序独调用 GetDriveType()API 从而获取C驱动器的类型(大部分返回的是 HDD 类型),然后操作它,使之被识别为 CD-ROM 类型,之后再消息窗口输出 “OK, I really think that your HD is a CD-ROM!:p”.
接下来备注一些需要用到的汇编指令:
指令 | 说明 |
---|---|
PUSH | 入栈指令 |
CALL | 调用指定位置的函数 |
INC | 值加一 |
DEC | 值减一 |
JMP | 跳转到指定位置 |
CMP | 标胶给定的两个操作数,与 SUB 命令类似,但是操作数的值并不会被改变,仅改变 EFlags 寄存器,如果两个操作数的值相同那么 SUB 结果为0,ZF被置为1 |
JE | 条件跳转指令,如果ZF为1,那么跳转 |
接下来我们尝试修改指令来破解这个程序。
我们看到 401026 处,我们将汇编指令 JE SHORT 0040103D 修改为 JMP 0040103D
因为在 00401026 处的代码,当两值相等那么执行 0040103D ,否则执行 00401028 ,此时我们将比较函数直接去掉直接转到跳转函数,跳转到结束调用的消息框即可。于是将 JE 命令改变为 JMP 命令即可。
接下来我们再运行程序:
点击确定后即可输出正确的结果:
接下来,再将文件保存即可。
下面,我们再介绍函数调用时将函数参数压入栈的方法。
在地址 00401000 - 0040100E 之间的命令中:
这里我们将代码汇编为 C 语言函数的调用代码如下:
MessageBox(NULL, "Make me think your HD is a CD-Rom.", "abex' 1st crackme", MB_OK|MB_APPLMODAL)
比较 C 语言的代码和汇编代码可以发现,函数调用时的参数顺序和参数入栈时的顺序恰好相反,这是由于栈内存结构属于 FILO 型,在 x86 环境下,栈向低地址延伸,即当向栈中压入数据的时候,EPS 的值减小,向低地址方向移动,当 MessageBox 函数需要获取参数的时候,参数会按原来的顺序弹出。