【问题标题】:Why poping register changes the IP pointer为什么弹出寄存器会改变IP指针
【发布时间】:2018-09-18 06:25:17
【问题描述】:

我在玩一些汇编代码

func:
    pop ax
    ret
main:
    push 0x44
    call func

我注意到 ip 指针现在指向堆栈上的最后一项 0x44
我这样做是为了了解ROP 技术
我需要了解这种行为,因为当我这样做时

func:
    ret
main:
   call func

它按预期工作,EIP 指针指向原始代码 那么pop 改变代码流程有什么不同呢?
pop ax 是否将堆栈上的最后一个值分配给 ax

【问题讨论】:

  • 因为callret也使用栈。
  • 你为什么不阅读手册,callret 是做什么的?
  • 查阅指令集参考以了解每条指令的作用。 TL;DR:call 将返回地址放在堆栈上,ret 将其删除。如果你在它之前插入一个pop,那么这个返回地址当然会被删除,ret 将使用下一个可能错误的项目。
  • 如果有人投反对票,请至少向我解释原因.. 请:)
  • 下次如果您真的尝试阅读手册,请说出来并引用您无法理解的相关部分,以便我们进行解释。无论如何,在继续学习逆向工程和 ROP 等高级主题之前,您可能想多了解一些基本知识。另外,学习使用调试器单步执行代码,看看它在做什么。

标签: assembly x86 reverse-engineering


【解决方案1】:

要理解这段代码,看看真实的程序流程可能会有所帮助(颠倒代码的顺序并假设一个线性流程):

main:           ; entry point IP = main
    push 0x44   ; 0x44 on top of stack
    call func   ; PUSH 'next cur IP'(=func) on the stack
func:
    pop ax      ; POP 'next cur IP' from the stack(=this)
    ret         ; return to current stack value (=0x44 = IP) which is probably invalid

这与以下获取当前 IP 的技术非常相似:

因为没有指令可以获取指令指针 (IP) 的当前值,所以下面的代码是获取其值的便捷解决方法:

    call next   ; call next address
next:
    pop ax      ; POP the current value of the IP (AX=this address)

【讨论】:

    【解决方案2】:

    EIP 是一个寄存器。堆栈上的值(还)不是 EIP,它是一个返回地址或一个可能成为 EIP 的值,如果您通过执行 ret 将其弹出到 EIP 中。

    ret 想象成x86 拼写pop eip


    执行push 0x44会将EIP寄存器增加2,即指令长度。

    如果您通过在ESP 指向它时执行ret 来使用0x44 作为返回地址,那么EIP 将变为0x44

    请注意,IP 是 EIP 的低 16 位。除非你真的是指低 16 位,否则写 EIP 而不是 IP。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-05-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-19
      • 1970-01-01
      • 2012-08-29
      • 2019-12-23
      相关资源
      最近更新 更多