逆向:关于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到栈中
2)利用call指令更改eip值,进行函数的跳转调用
注意:call指令会将 当前指令地址 的下一条 指令地址 push到寄存器中
3)进入被调用函数后,首先向低地址位提升堆栈
4)保存函数调用前的现场
5)提升堆栈的初始化操作
6)执行函数功能代码
7)恢复现场
8)栈回溯,与栈提升相反
9)调整堆栈,保持堆栈平衡(外平栈)
由于传入了三个参数,占用了十二个字节,因此在平衡栈时,栈顶向高地址方向移动0x0c
裸函数书写调用过程
#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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通