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
  • 相关阅读:
    ASP.NET网页动态添加数据行
    动态生成自定义控件ascx如何给ascx传值
    读取txt文件将文本行组合成特定格式
    怎样对文本文件内的文本行排序
    动态变更Repeater控件HeaderTemplate列名
    减少代码冗余,封装你的程序
    在Repeater控件的OnItemDataBound获取数据源记录总数
    查看服务器系统资源(cpu,内容)利用率前几位的进程的方法
    Nginx反向代理+缓存开启+url重写+负载均衡(带健康探测)的部署记录
    gerrit代码简单备份方案分享
  • 原文地址:https://www.cnblogs.com/mysky007/p/12913778.html
Copyright © 2011-2022 走看看