【问题标题】:How to check the EIP value with assembly language? [duplicate]如何用汇编语言检查 EIP 值? [复制]
【发布时间】:2011-05-03 00:31:03
【问题描述】:

我想用汇编语言获取 EIP 寄存器的当前值。这可能吗?

【问题讨论】:

    标签: assembly x86


    【解决方案1】:

    在 x86-64(相对于 32 位 x86)上,有 RIP-相对寻址(RIPEIP 的 64 位类似物)。所以在 64 位代码中,你可以这样做

    lea rax, [rip]
    

    RIP 的当前内容移动到RAX(您可以使用lea,但不能使用mov)。

    【讨论】:

    • 优秀的评论。我已经删除了我的错误答案。不应将评论作为答案发布。
    • 嗯,这在 VC++ 2015 __asm{} 块中不起作用。 :( 获取error C2415: improper operand type 错误。
    • @Adrian:MSVC 在为 x86-64(64 位模式)编译时不支持内联汇编,因此如果您想使用其笨重的内联代码,您会遇到过时的 32 位代码asm 支持。当然,如果你用 C 语言编写,你可以只取一个函数的地址,编译器 + 链接器会做任何必要的事情来给你地址。 RIP 相对寻址是 x86-64 中的新功能,显着提高了与位置无关的代码的效率。
    【解决方案2】:

    假设 32 位 x86,使用以下函数:

    get_eip: mov eax, [esp]
             ret
    

    那么,要获取 EAX 中 EIP 的值,只需:

    call get_eip
    

    【讨论】:

    • 我希望有一种方法可以做到这一点,无需标签或字节计数
    • 有一种不用标签的方法。 call $+0 / ret / mov eax, [esp-4]
    • @GregoryMorse:call $+0 是一个无限循环。 (直到您在尝试推送另一个返回地址时填满堆栈和段错误)。即使call $+5 / ret 也行不通;第一个ret 将返回到它自己,然后它会再次运行并将堆栈中的下一个东西弹出到EIP 中。此外,从 ESP 下方阅读也不安全;它可能已被信号处理程序或调试器异步破坏。 (或者在内核堆栈上,通过中断。)
    • 是的,由于这两个原因,我的评论都是错误的。 call $+5 / pop eax 毫无疑问是最好的序列。但是 $+5 不能保证正确,它假定E9 CD 其中 CD 是 rel32 或 32 位位移。在 16 位模式下,它将是 E9 CW,其中 CW 是 rel16 或 16 位位移。但是,您错误地认为在堆栈指针下方读取是不安全的。我们谈论的是硬件,而不是操作系统的恶作剧。是的,实际上操作系统在进行任务切换时不会保留它,尽管可能有一些技巧可以保证它会。
    • @GregoryMorse:没有看到你的回复,因为你没有\@通知。除非您使用具有特定红区保证的 ABI(如用户空间 x86-64 System V),否则堆栈指针下方的内存可能不会读回您刚刚编写的内容。如果您谈论的是裸硬件,那么在内核模式下,ESP 通常与用于处理中断的堆栈相同。除非禁用中断,否则“刚刚写入”实际上可能是在中断将 cs:eip 推入堆栈之前/之后,然后中断返回。对于用户空间,请参阅Is it valid to write below ESP?
    【解决方案3】:
        call foo
    foo:
        pop eax ; address of foo
    

    【讨论】:

    • 这种方法有一个微妙的问题。现代处理器试图预测返回地址——没有与返回配对的调用会破坏预测。见blogs.msdn.com/b/oldnewthing/archive/2004/12/16/317157.aspx
    • @Jens Björnhager 这是无限循环。 call foo / foo: pop eax / add eax, bar-foo / push eax / ret / bar:
    • @Abyx 那么至少你知道你的程序卡在哪个EIP了! :)
    • 如果 foo 不是内联的,那么你就不会卡住,会得到*下一条指令的EIP。
    • @user200783:令人惊讶的是,call next_insn 是特殊情况下 破坏大多数 CPU 上的返回地址预测器堆栈:blog.stuffedcow.net/2018/04/ras-microbenchmarks/#call0 - 这只是硬壳旧的问题PPro(大概到 PIII)。所以这个答案很好。 Reading program counter directly
    猜你喜欢
    • 2020-12-18
    • 1970-01-01
    • 2011-02-08
    • 1970-01-01
    • 2023-03-23
    • 2018-11-11
    • 1970-01-01
    • 2018-04-12
    • 2018-05-14
    相关资源
    最近更新 更多