为什么我的分支指令没有跳转到给定的地址? [英] Why is my branch instruction not jumping to the given address?

查看:115
本文介绍了为什么我的分支指令没有跳转到给定的地址?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm currently learning reverse engineering and therefore I need to learn assembly. The code is running well, but I got an error on JE and JNE instructions. To be more specific: I'm doing a detour hook as a practice and the program crashes, because it jumps to the false address.

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

I wanted to write this, but the compiler gave me an error (LNK2016):

JE 0x123 (0x123 example address)

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

I fixed that problem by writing:

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.

But the problem now is, that it is jumping to the beginning of the function instead of 0x123 in our case.

推荐答案

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

The conditional jump instructions on x86 all take a relative displacement, not an absolute address. They work to jump to another label in your code, since the assembler can compute the displacement between the jump instruction and the destination, but you can't use them jump to an absolute address unless you know, at assembly time, the address where your code will be loaded.

x86 上的近绝对跳转是间接的:您需要在寄存器或内存中获得地址.并且此类跳转仅以无条件形式提供,因此您必须使用条件跳转才能到达它们.

Near absolute jumps on x86 are indirect: you need to have the address in a register or memory. And such jumps are only available in an unconditional form, so you'll have to use the conditional jump to get to them.

你可以这样做

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

如果你不能节省寄存器,你可以代替

If you can't spare a register, you could instead do

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

但这是更多字节的代码.

but this is more bytes of code.

如果你知道你的代码将被加载的地址,并且它在目标地址的 2 GB 之内,你可以使用 ORG 指令告诉汇编器它.所以如果 my_hook 将在地址 0x7ff7DEADBEEF,你可以做

If you do know the address where your code will be loaded, and it's within 2 GB of the destination address, you can use the ORG directive to tell the assembler about it. So if my_hook will be at address 0x7ff7DEADBEEF, you can do

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

并且汇编器将计算正确的 32 位位移.

and the assembler will compute the correct 32-bit displacement.

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

By the way, the test rcx, rcx doesn't really make sense: if rcx were zero then the previous instruction mov dword [rcx + 0x18], 99 would have faulted, since on any decent operating system, the zero page will be unmapped. Maybe you wanted this test and conditional jump to go before the mov. Unless this is some sort of strange bare-metal code that you're patching?

这篇关于为什么我的分支指令没有跳转到给定的地址?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆