动态线条
动态线条end

逆向:关于C语言函数调用时堆栈变化情况

高级语言源代码

#include <stdio.h>

//计算a + b + c的结果,并将结果返回
int fun(int a,int b,int c){
	return a + b + c;
}

int main(){
	fun(1,2,3);//调用函数计算1 + 2 + 3
	return 0;
}

函数调用时汇编指令的操作

1)将传递的参数push到栈中

image-20220209173517670

2)利用call指令更改eip值,进行函数的跳转调用

      注意:call指令会将 当前指令地址 的下一条 指令地址 push到寄存器中

image-20220209173615405

3)进入被调用函数后,首先向低地址位提升堆栈

image-20220209174059221

4)保存函数调用前的现场

image-20220209173858782

5)提升堆栈的初始化操作

image-20220209174423703

6)执行函数功能代码

image-20220209174522323

7)恢复现场

image-20220209174629577

8)栈回溯,与栈提升相反

image-20220209174756231

9)调整堆栈,保持堆栈平衡(外平栈)

      由于传入了三个参数,占用了十二个字节,因此在平衡栈时,栈顶向高地址方向移动0x0c

image-20220209174926354

裸函数书写调用过程

#include <stdio.h>

//声明一个裸函数,编译器不对其生成汇编代码
int __declspec(naked) fun(int a, int b){

	__asm{
		//栈提升
		push ebp//将栈底保存到栈中
			mov ebp, esp//栈底指向栈顶
			sub esp, 0x40//栈顶向低地址位移4 * 16个字节
			//保存现场
			push ebx
			push esi
			push edi
			//初始化提升栈
			mov eax,0xcccccccc
			mov ecx, 0x10
			lea edi, dword ptr ds : [ebp - 0x40]
			rep stosd
			//进行函数的功能运算
			mov eax, dword ptr ds : [ebp + 0x8]
			add eax, dword ptr ds : [ebp + 0xc]
			//恢复现场
			pop edi
			pop esi
			pop ebx
			//堆栈还原
			mov esp, ebp
			pop ebp
			//返回
			ret
	}
}

int main(){
	fun(1, 2);
	return 0;
}
posted @ 2022-02-09 18:01  v1v1v1  阅读(123)  评论(0编辑  收藏  举报