【问题标题】:Assembly return address装配返回地址
【发布时间】:2012-03-13 21:26:48
【问题描述】:

我想在汇编中获取函数的返回地址,然后将该返回地址值与另一个值进行比较,而不破坏堆栈或更改堆栈中的任何内容,

如何在汇编中做到这一点?

我正在使用 x86

【问题讨论】:

  • 一般情况下你不能。请指定架构、arm、mips、x86 等。这是一个非常特定于编译器的问题。我假设这是您正在编写的 asm 函数等?请在问题中提供更多详细信息。
  • 使用x86,有什么好的方法吗?最好的方法是什么?
  • 假设返回地址是堆栈上的最后一件事,您可以使用堆栈指针来检查它(假设堆栈指针没有针对堆栈帧进行修改)然后......好吧检查它...您会认为需要使用内联汇编或手动编写函数以避免再次调用。创建的堆栈内容和堆栈帧都是特定于当天代码的编译器,您不能一般地这样做,您必须知道编译器是如何创建该特定函数的。或者更好的是,自己创建函数。

标签: assembly x86


【解决方案1】:

通常在 x86 上,如果使用 stdcall 约定返回地址存储在寄存器 ebp +4 的内容中。所以cmp ebp, whatever; 应该完成这项工作。实际上,它不依赖于调用约定,而是取决于您的编译器是否将 push ebp 作为函数的第一条指令,它通常会这样做。一般来说,函数看起来像:

push ebp
mov ebp,esp
sub esp,size_of_local_variables
...
somehting something something
...
mov esp, ebp
pop ebp
ret

【讨论】:

    【解决方案2】:

    一般来说,您需要手动或使用您的某些代码来反汇编有问题的函数并分析反汇编(同样,手动或使用代码中的某种启发式算法)以查看堆栈指针的行为和该函数中的任何相关寄存器(例如 ebp)或变量,直到开始需要返回地址的代码为止。

    如果您手动完成所有操作,则很容易找到返回地址位置并对其进行硬编码,但生成的代码将非常脆弱,因为任何代码更改以及编译方式的更改都可能破坏它。

    OTOH,在代码中实现一个始终(或几乎总是)工作的解决方案,尽管代码发生了变化并且编译中的变化将是非常乏味和困难的。

    您能告诉我们为什么需要退货地址吗?你想用这个解决什么问题?

    【讨论】:

      【解决方案3】:

      您可以创建一个包装函数。

      int the_real_function ( unsigned int a, unsigned int b )
      {
      //stuff
      return(something);
      }
      

      创建几行汇编程序:

      function_name:
        save registers if needed
        grab the return address here
        if passed on stack copy parameters
        call the_real_function
        if return is stack based place it where needed
        restore registers if needed
        return
      

      显然不是真正的 asm 代码。您希望检查的函数将重命名,然后 asm 将具有函数的名称、编译和链接,并且对该函数的所有调用都通过包装器。要编写上述内容,您必须知道该目标、编译器、编译器选项等的调用约定。

      【讨论】:

        猜你喜欢
        • 2016-01-10
        • 1970-01-01
        • 2017-01-26
        • 1970-01-01
        • 1970-01-01
        • 2013-10-20
        • 1970-01-01
        • 2013-01-06
        • 2016-06-19
        相关资源
        最近更新 更多