【问题标题】:Will arguments to a function be passed on the stack or in a register?函数的参数是在堆栈上传递还是在寄存器中传递?
【发布时间】:2010-11-01 20:56:11
【问题描述】:

我目前正在分析我在汇编中编写的程序,并正在考虑在汇编中移动一些代码。我有一个带有一个参数的过程,但我不确定它是通过堆栈还是寄存器传递。

当我在 IDA Pro 中打开我的程序时,程序的第一行是:

ThreadID= dword ptr -4

如果我将光标悬停在声明上,还会出现以下内容:

ThreadID dd ?
 r db 4 dup(?)

我认为它会指向一个堆栈变量?

但是,当我在 OllyDbg 中打开同一个程序时,堆栈上的这个位置有一个很大的值,这与可能传递的任何参数不一致,这让我相信它是在寄存器中传递的。

谁能指出我正确的方向?

【问题讨论】:

    标签: reverse-engineering ollydbg ida


    【解决方案1】:

    参数传递给函数的方式取决于函数的calling convention。默认调用约定取决于语言、编译器和体系结构。

    对于您提供的信息,我不能肯定地说什么,但是您不应该忘记,像 OllyDbg 这样的汇编级调试器和像 IDA 这样的反汇编器经常使用启发式方法对程序进行逆向工程。研究编译器生成的代码的最好方法是指导它编写汇编列表。大多数编译器都可以选择这样做。

    【讨论】:

    • 调用约定是__fastcall
    • “通常,fastcall 调用约定在寄存器中传递一个或多个参数,从而减少调用所需的内存访问次数。” -- en.wikipedia.org/wiki/X86_calling_conventions#fastcall
    • 还有一件事我没有注意到。堆栈中的正偏移量(相对于基指针)是局部变量,因此 ThreadID 很可能是局部变量。
    【解决方案2】:

    它肯定是一个局部变量。要检查参数,请查找 [esp+XXX] 值。 IDA 自动命名那些 [esp+arg_XXX]。

    .text:0100346A sub_100346A     proc near               ; CODE XREF: sub_100347C+44p
    .text:0100346A                                         ; sub_100367A+C6p ...
    .text:0100346A
    .text:0100346A arg_0           = dword ptr  4
    .text:0100346A
    .text:0100346A                 mov     eax, [esp+arg_0]
    .text:0100346E                 add     dword_1005194, eax
    .text:01003474                 call    sub_1002801
    .text:01003474
    .text:01003479                 retn    4
    .text:01003479
    .text:01003479 sub_100346A     endp
    

    上面评论中概述的 fastcall 约定使用寄存器来传递参数。我打赌微软或 GCC 编译器,因为它们使用更广泛。所以先检查 ECX 和 EDX 寄存器。

    Microsoft 或 GCC [2] __fastcall[3] 约定(又名 __msfastcall)通过 前两个参数(评估 从左到右)适合 ECX 和 EDX。剩余的参数被推送 从右到左放到栈上。 http://en.wikipedia.org/wiki/X86_calling_conventions#fastcall

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多