zoukankan      html  css  js  c++  java
  • 《逆向工程核心原理》--- 函数调用约定

    函数的约定:

      对函数调用时如何传递参数的一种约定,我们知道调用函数前需要将参数压入栈然后再传递给函数,栈就是定义在进程中的一段内存,向下扩展,大小记录在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
  • 相关阅读:
    ACM实用C语言函数
    Java中的数组和方法
    eclipse常用快捷键
    【转载】第十章 五种对称加密算法总结
    【转载】ZooKeeper学习第二期--ZooKeeper安装配置
    【转载】Java垃圾回收机制
    【转载】JVM系列三:JVM参数设置、分析
    【转载】JVM系列二:GC策略&内存申请、对象衰老
    【转载】JVM系列一:JVM内存组成及分配
    java项目性能测试过程记录
  • 原文地址:https://www.cnblogs.com/mysky007/p/12913778.html
Copyright © 2011-2022 走看看