《逆向工程核心原理》--- 函数调用约定
Posted mysky007
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了《逆向工程核心原理》--- 函数调用约定相关的知识,希望对你有一定的参考价值。
函数的约定:
对函数调用时如何传递参数的一种约定,我们知道调用函数前需要将参数压入栈然后再传递给函数,栈就是定义在进程中的一段内存,向下扩展,大小记录在PE头中,运行时确定栈的大小
函数执行完毕后,ESP的值如何变化?
ESP的值恢复到函数调用之前,这样可引用的栈大小不会缩减
函数:
1 int function(int a, int b) 2 { 3 return a + b; 4 } 5 void main() 6 { 7 function(10, 20); 8 }
主要函数约定如下:
__cdecl约定
__cdecl函数调用约定是我们最长见的一种约定,我们平时在写程序的时候默认会使用该种约定,其特点如下:
- 参数从右向左依次传递,存放在堆栈中。
- 堆栈平衡由调用函数来维护。
- C语言编译时的函数命名规则为下划线加名称:__functionName
1 _function 2 push ebp 3 mov ebp, esp 4 mov eax, [ebp+8] ;参数1 5 add eax, [ebp+C] ;加上参数2 6 pop ebp 7 retn 8 _main 9 push ebp 10 mov ebp, esp 11 push 14h ;参数 2入栈 12 push 0Ah ;参数 1入栈 13 call _function ;调用函数 14 add esp, 8 ;修正栈 15 xor eax, eax 16 pop ebp 17 retn
__stdcall约定
__stdcall约定是我们在写WinAPI的时候经常用的约定,很多windows下面的API都是该种调用约定,其特点如下:
- 参数从右向左依次传递,存放在堆栈中。
- 堆栈平衡由被调用函数来维护
- C语言编译时的函数命名规则为下划线加名称加@加参数字节大小:__functionName@len
_function@8 push ebp mov ebp, esp mov eax, [ebp] ;参数 1 add eax, [ebp+C] ;加上参数 2 pop ebp retn 8 ;修复栈 _main push ebp mov ebp, esp push 14h ;参数 2入栈 push 0Ah ;参数 1入栈 call _function@8 ;函数调用 xor eax, eax pop ebp retn
__fastcall约定
从名称上可以看出是速度快,因为其参数是可以放在寄存器中传递的,通常需要在要求高效率的函数中使用此约定,其特点如下:
- 最右侧两个参数由ecx和edx两个寄存器来传递,剩余参数从右往左依次存放在堆栈中。
- 堆栈平衡由被调用函数来维护
- C语言编译时的函数命名规则为@加函数名加@加参数大小:@functionName@len
该约定是高效率的调用约定,和另外两种约定最大的区别就是参数的传递方式,利用了寄存器来快速的传递
1 @function@8 2 push ebp 3 mov ebp, esp ;保存栈指针 4 sub esp, 8 ;多了两个局部变量 5 mov [ebp-8], edx ;保存参数 2 6 mov [ebp-4], ecx ;保存参数 1 7 mov eax, [ebp-4] ;参数 1 8 add eax, [ebp-8] ;加上参数 2 9 mov esp, ebp ;修正栈 10 pop ebp 11 retn 12 _main 13 push ebp 14 mov ebp, esp 15 mov edx, 14h ;参数 2给EDX 16 mov ecx, 0Ah ;参数 1给ECX 17 call @function@8 ;调用函数 18 xor eax, eax 19 pop ebp 20 retn
以上是关于《逆向工程核心原理》--- 函数调用约定的主要内容,如果未能解决你的问题,请参考以下文章