《逆向工程核心原理》--- 函数调用约定

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

 

以上是关于《逆向工程核心原理》--- 函数调用约定的主要内容,如果未能解决你的问题,请参考以下文章

逆向工程核心原理——第十章

逆向知识十一讲,识别函数的调用约定,函数参数,函数返回值.

逆向知识十一讲,识别函数的调用约定,函数参数,函数返回值.

约定的目录结构说明

《逆向工程核心原理》读书笔记——第7章 栈帧

逆向工程核心原理——第五章