【问题标题】:Why is my branch instruction not jumping to the given address?为什么我的分支指令没有跳转到给定的地址?
【发布时间】:2021-02-05 22:46:12
【问题描述】:

我目前正在学习逆向工程,因此我需要学习汇编。代码运行良好,但在JEJNE 指令上出现错误。更具体地说:我正在做一个绕道钩子作为练习,程序崩溃了,因为它跳转到了错误的地址。

我想写这个,但是编译器给了我一个错误(LNK2016):

JE 0x123 (0x123 example address)

我通过写作解决了这个问题:

JE short 0x123

完整功能代码:

my_hook:
    push rbp        
    mov rbp, rsp

    mov dword [rcx + 0x18], 99   

    test rcx, rcx
    je 0x7FF7847902EE
    lock dec dword [rcx + 0x08]
    jne 0x7FF7847902EE
    mov rcx, [rsp + 0x30]

    leave   
    ret

但现在的问题是,在我们的例子中,它跳转到了函数的开头而不是 0x123

【问题讨论】:

  • 你能发一个minimal reproducible example吗?
  • 你知道条件跳转指令,就像 x86 上的所有直接近跳转一样,采用相对位移吗?所以如果你不知道你的代码将被定位在哪里,你就不能用它来跳转到一个绝对地址。相反,您可以反转条件并跳过绝对间接跳转,使用寄存器或内存中的绝对地址。
  • 反之,如果你知道你的代码在哪里,你可以用ORG告诉汇编器,它可以计算出合适的位移。
  • @NateEldredge 首先感谢您的回复!我现在把完整的功能代码贴在上面了。
  • 0x7FF7847902EE 在哪里?跳出你的功能是个坏主意。如果它在您的函数内,只需使用标签。然后汇编器可以生成正确的偏移量。

标签: visual-studio assembly 64-bit x86-64 nasm


【解决方案1】:

x86 上的条件跳转指令都采用相对位移,而不是绝对地址。它们可以跳转到代码中的另一个标签,因为汇编器可以计算跳转指令和目标之间的位移,但是您不能使用它们跳转到绝对地址,除非您在汇编时知道您所在的地址代码将被加载。

x86 上的近似绝对跳转是间接的:您需要将地址保存在寄存器或内存中。而且这种跳转只能以无条件的形式使用,因此您必须使用有条件的跳转才能到达它们。

你可以的

my_hook:
    push rbp        
    mov rbp, rsp

    mov dword [rcx + 0x18], 99   

    test rcx, rcx
    je jump_elsewhere
    lock dec dword [rcx + 0x08]
    jne jump_elsewhere
    mov rcx, [rsp + 0x30]

    leave   
    ret

jump_elsewhere:
    mov rax, 0x7FF7847902EE
    jmp rax

如果你不能腾出一个寄存器,你可以这样做

jump_elsewhere:
    jmp [rel elsewhere_addr]
elsewhere_addr: 
    dq 0x7FF7847902EE

但这是更多字节的代码。

如果您确实知道将加载代码的地址,并且该地址在目标地址的 2 GB 范围内,则可以使用 ORG 指令将其告知汇编程序。所以如果my_hook 的地址是0x7ff7DEADBEEF,你可以这样做

    org 0x7ff7DEADBEEF
my_hook:
    ; ...
    je 0x7FF7847902EE

汇编器将计算正确的 32 位位移。

顺便说一句,test rcx, rcx 并没有真正的意义:如果rcx 为零,那么前面的指令mov dword [rcx + 0x18], 99 就会出错,因为在任何体面的操作系统上,零页都将被取消映射。也许您希望这个测试和条件跳转在mov 之前进行。除非这是您正在修补的某种奇怪的裸机代码?

【讨论】:

  • 但是你不能使用它们跳转到绝对地址,除非你在汇编时知道你的代码将被加载的地址 - 更正:在 链接 时间,至少使用 YASM(NASM 似乎出了点问题)。当目标文件格式(如 ELF)允许计算正确的相对位移以到达绝对地址时,您可以使用 jcc numeric_address。当然,您只能将其链接到与位置相关的代码(非 PIE 可执行文件)中。
  • je 0x123yasm -felf64 生成此 objdump -drwC -Mintel 输出:0: 0f 84 00 00 00 00 je 0x6 2: R_X86_64_PC32 *ABS*+0x11f。链接到静态可执行文件:401000: 0f 84 1d f1 bf ff je 123.
  • 但显然 Windows 对象文件不支持(正确)此类重定位,并且 OP 似乎正在使用 Windows(来自 LNK2016 错误和调用约定):How to write an absolute target for a near direct relative call/jmp in MASM - 这就是 NASM 获胜的原因-fwin32 不支持它,MASM 根本没有它的语法。
  • 这会起作用,但会导致“访问冲突错误”。好消息是我的代码可以正常工作,但不幸的是,由于该错误没有跳转......
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-17
  • 2019-03-20
  • 2016-10-21
  • 2015-12-22
  • 2016-03-21
  • 2021-05-11
相关资源
最近更新 更多