逆向基础(二)--- 函数调用过程完整分析

在逆向工程汇编分析过程中,我们很关心关键函数的功能及其参数的意义。总会遇到很多的函数调用。我们需要关注的是:参数的传递,函数返回,函数调用,参数引用,返回值,函数返回,堆栈平衡这些问题。下面我们用实例来分析一下函数整个调用过程。
首先给一张函数调用全景图
逆向基础(二)--- 函数调用过程完整分析_第1张图片为了方便说明,写一个简单测试用例。C代码实例如下:

int funWith4args(int A, int B, int C,int D)
{
	int sum = A + B + C + D;
	return sum;
}

int __stdcall fun_stdcall_5args(int A, int B, int C, int D, int E)
{
	int sum = A + B + C + D+ E;
	return sum;
}

int  __cdecl fun_cdecl_5args(int A, int B, int C, int D, int E)
{
	int sum = A + B + C + D + E;
	return sum;
}

int  __fastcall fun_fastcall_5args(int A, int B, int C, int D, int E)
{
	int sum = A + B + C + D + E;
	return sum;
}

int _tmain(int argc, _TCHAR* argv[])
{
	int A,B,C,D,E;
	A = 0x100;
	B = 0x200;
	C = 0x300;
	D = 0x400;
	E = 0x500;

	int sum1 = fun_stdcall_5args(A, B, C, D, E);
	printf("sum = %d\r\n", sum1);
	int sum2 = fun_cdecl_5args(A, B, C, D, E);
	printf("sum = %d\r\n", sum2);
	int sum3 = fun_fastcall_5args(A, B, C, D, E);
	printf("sum = %d\r\n", sum3);

	return 0;
}

函数调用过程

1、 参数准备,按照调用协议(__stdcall,__cdecl,__fastcall)压入堆栈

函数调用协议可以参考文章:
函数调用协议汇总X86/X64/ARM/ARM64
如图1所示,参数由右向左依次入栈
逆向基础(二)--- 函数调用过程完整分析_第2张图片 图1

2、 函数调用

call 指令可以分写为两个动作,push 和jump。Push当前函数返回地址,jump到函数处。我们在IDA中F7进入函数,栈中情况如图2所示。
逆向基础(二)--- 函数调用过程完整分析_第3张图片图2
0x791586指向函数的返回地址,如图3
逆向基础(二)--- 函数调用过程完整分析_第4张图片图3

3、 参数引用,返回值

这里看看被代用函数是如何使用参数的。
首先了解C代码,很简单的求和。那么我们在汇编代码中学习一下如何引用A,B,C,D,E五个参数

int __stdcall fun_stdcall_5args(int A, int B, int C, int D, int E)
{
	int sum = A + B + C + D+ E;
	return sum;
}

如图4所示,ebp是本函数的栈底,从上面的分析我们知道,ebp+4保存的函数返回地址,从ebp+8开始保存着函数调用所使用的参数。
函数返回
当函数将返回值设置好后,函数开始准备返回。

逆向基础(二)--- 函数调用过程完整分析_第5张图片图4
eax保存着函数的返回值。

4、函数返回

图5中,返回关键代码参见方框中。首先恢复函数体内使用的寄存器,恢复函数体临时申请栈空间,弹出调用者的ebp,最后调用retn函数返回。
逆向基础(二)--- 函数调用过程完整分析_第6张图片图5
retn指令表示取出当前栈顶值 作为返回地址 将eip修改为该地址。

看看函数返回栈的情况。如图6所以,retn指令后eip指向被调用函数的下面一条指令。esp和ebp恢复到了代用函数前的状态。
逆向基础(二)--- 函数调用过程完整分析_第7张图片图6

5、 堆栈平衡

根据规则进行堆栈平衡,可能是函数体内负责堆栈平衡,也可能是调用者负责堆栈平衡。

逆向基础(二)--- 函数调用过程完整分析_第8张图片本例汇编如图7
逆向基础(二)--- 函数调用过程完整分析_第9张图片图7
堆栈恢复平衡后如图8,调用函数之前将参数压栈使用的栈空间,释放了。达到调用的平衡。
逆向基础(二)--- 函数调用过程完整分析_第10张图片至此,一个函数的代用过程结束。我们在回头看看开篇给出的函数调用全景图,回顾整个调用过程。

你可能感兴趣的:(逆向)