逆向 - 函数调用约定
逆向 - C语言调用约定
基础代码如下
1 | |
x86 部分
cdecl 调用约定
参数从右向左入栈
调用者清理栈
1 | |
stdcall 调用约定
参数从右向左入栈
被调用者使用
ret清理栈
1 | |
fastcall 调用约定
参数从右向左入栈
第1个参数和第2个参数分别存储在
ECX和EDX寄存器中被调用者使用
ret清理栈
1 | |
x64 部分
x64调用 只有 fastcall 一种调用约定
参数从右向左入栈
1~4 个参数分别存储在
RCX,RDX,R8,R9寄存器中其他参数压栈
被调用者使用
ret清理栈
1 | |
1 | |
在调用前其栈如下
rsp | 当前 | 0 |
+8 | ||
+10 | ||
+18 | ||
参数6 | +20 | |
参数5 | +28 |
在调用call后, RSP上移动, 此时栈如下
rsp | RETADDR | 0 |
+8 | ||
+10 | ||
+18 | ||
+20 | ||
参数6 | +28 | |
参数5 | +30 |
然后放入参数4, 参数3, 参数2, 参数1
rsp | RETADDR | 0 |
参数1 ecx | +8 | |
参数2 edx | +10 | |
参数3 r8d | +18 | |
参数4 r9d | +20 | |
参数6 | +28 | |
参数5 | +30 |
压入rbp和rdi
rsp | old rdi | 0 |
old rbp | +8 | |
RETADDR | +10 | |
参数1 ecx | +18 | |
参数2 edx | +20 | |
参数3 r8d | +28 | |
参数4 r9d | +30 | |
参数6 | +38 | |
参数5 | +40 |
分配栈空间
rsp | +20 | |
+18 | ||
+10 | ||
+8 | ||
rbp | +0 | |
… | ||
old rdi | +E8 | |
old rbp | +F0 | |
RETADDR | +F8 | |
参数1 ecx | +100 | |
参数2 edx | +108 | |
参数3 r8d | +110 | |
参数4 r9d | +118 | |
参数6 | +120 | |
参数5 | +128 | |
即可对应到栈上的参数
1 | |
在返回清理时, rsp恢复到old rdi位置, 并弹出rdi和rbp, 最后返回
1 | |
逆向 - 函数调用约定
https://simonkimi.githubio.io/2026/02/22/逆向-C语言调用约定/