函数逆向分析
作者:ONDragon
环境:Windows 7 VC6.0。
一、 函数源码
__cdecl int CTestPlus(int a,int b,int c) { return a + b + c; }
__stdcall int STestPlus(int a,int b,int c) { return a + b + c; }
__fastcall int FTestPlus(int a,int b,int c) { return a + b + c; }
int TestPlus(int a,int b,int c) { return a + b + c; }
int main(int argc, char* argv[]) {
TestPlus(10,11,12); CTestPlus(1,2,3); STestPlus(4,5,6); FTestPlus(7,8,9);
return 0; } |
二、 解释函数作用
//__cdecl 标准C语言调用函数,函数参数从右至左入栈,调用者平衡堆栈(后面详细解释) __cdecl int CTestPlus(int a,int b,int c) { return a + b + c; }
//__stdcall 标准调用函数,函数参数从右至左入栈,函数自己平衡堆栈(后面详细解释)
__stdcall int STestPlus(int a,int b,int c) { return a + b + c; }
//__fastcall 快速调用函数,参数从右至左入栈,除去前两个参数,例如:c入栈,但是a,b,不入栈,而是进入寄存器,因为CPU使用寄存器最快,所以叫做__fastcall __fastcall int FTestPlus(int a,int b,int c) { return a + b + c; }
// 默认则是__cdecl 标准C语言调用函数 int TestPlus(int a,int b,int c) { return a + b + c; }
int main(int argc, char* argv[]) {
TestPlus(10,11,12); CTestPlus(1,2,3); STestPlus(4,5,6); FTestPlus(7,8,9);
return 0; } |
三、 具体分析过程
1. 下断点
在调试窗口中,可以打开相应的窗口,我们打开内存,堆栈,寄存器窗口就行。
然后转到汇编操作界面,选择Disassembly.
2. 分析TestPlus函数(CTestPlus相同只分析一个)
如上图:
1,是三个函数参数10,11,12(__cdecl 标准C语言调用函数,函数参数从右至左入栈,调用者平衡堆栈。)
2,从右至左入栈,依次是12,11,10.
3,调用者平衡堆栈是哪个函数调用了TestPlus,哪个函数就平衡堆栈,例如这个TestPlus是Main函数调用的,所以就由Main函数平衡堆栈 add esp 0C,C的十六进制刚好是12,一个参数四个字节3 * 4 刚好12个字节。
4,单步调试进入函数TestPlus,Call汇编对应C语言函数的意思。
5,进入TestPlus函数
6, 解释函数汇编代码
Push ebp 保护现场,保存上一个函数的Ebp
Mov ebp,esp
Sub esp,40h 开辟缓存区
Push ebx
Push esi
Push edi 保护现场保存上一个函数的ebx,esi,edi的值
Lea edi,[ebp-40h]
Mov ecx,10h
Mov eax,0ccccccccch
Rep stos dword ptr[edi] 用CC int 3断点填充刚开辟的缓冲区域(原因:保护程序,程序出错直接进入CC中断不执行)
7, 进入函数的主要功能区域a + b + c
[ebp + 8] 第一个参数 10 记做var_1
[ebp + 0Ch] 第二个参数 11 记做var_2
[ebp + 10h] 第三个参数 12 记做 var_3
8, 加法开始
Mov eax ,var_1
Add eax,var_2
Add eax,var_3
这几条汇编十分简单就不讲了。
9, 返回值一般放到eax寄存器里面。
恢复现场:
pop edi
pop esi
pop ebx
mov esp,ebp
pop ebp
返回,汇编ret相当于C语言的return.
Ret
3. 分析STestPlus函数
1,函数开始和返回和前面的函数相同,就不分析了,直接分析有差异的部分。
2, __cdecl 调用时add esp ,0Ch平衡堆栈,__stdcall则没有,因为是函数本身平衡堆栈,继续看。
3, __stdcall 与 __cdecl 只有平衡堆栈方法不同,是通过ret 0Ch来平衡堆栈的刚好3个参数每个4个字节3 * 4 刚好12位Ch.
4. 分析FTestPlus函数
1,__fastcall 处理函数参数的顺序从右至左,但是如上图,9入栈,但是8,7都是通过寄存器来处理的参数,所以快。
2,加法部分差不多,平衡堆栈方式是 ret 4。
四、 总结:
普通函数和__cdecl:
参数入栈从右到左,调用者平衡堆栈。
__stdcall:
参数入栈从右到左,自己平衡堆栈。
__fastcall:
参数入栈从右到左,但是前两个参数依次进入ecx,edx寄存器,自己平衡堆栈。