Why is my branch instruction not jumping to the given address?
Asked Answered
P

1

0

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.

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

Full function code:

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

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

Pifer answered 5/2, 2021 at 22:46 Comment(6)
Can you post a minimal reproducible example?Newburg
You do know that the conditional jump instructions, like all direct near jumps on x86, take a relative displacement? So if you don't know where your code will be located, you can't use it to jump to an absolute address. You can instead reverse the condition and jump over an absolute indirect jump, with the absolute address in register or memory.Newburg
Conversely, if you do know where your code will be located, you can use ORG to tell the assembler about it, and it can calculate the proper displacement.Newburg
@NateEldredge First of all thanks for your reply! I posted the full function code above now.Haversack
@NateEldredge The first line of code is where it writes 99 everytime on my current ammo. The rest of it are just stolen bytes and at the end of the code, the goal was to go back whatever comes next after my injected function, so that the program doesn't crash. But it jumps not to "0x7FF7847902EE", instead it keeps jumping to the first instruction of the function, which causes to crash. Btw im using 64x architecture and as I said in my code I wrote "je short 0x7FF7847902EE", 'cause it gives me an error without that "short".Haversack
Where is 0x7FF7847902EE? Jumping out of your function is a bad idea. If it is inside your function just use a label. Then the assembler can generate the proper offset.Quell
N
3

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.

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.

You could do

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.

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

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

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?

Newburg answered 6/2, 2021 at 1:39 Comment(4)
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 - correction: at link time, at least with YASM (NASM seems to be getting something wrong). You can use jcc numeric_address when targeting an object file format like ELF that allows calculating the right relative displacement to reach an absolute address. Of course you can only link it into position-dependent code (a non-PIE executable), though.Sojourn
je 0x123 with yasm -felf64 produces this objdump -drwC -Mintel ouptut: 0: 0f 84 00 00 00 00 je 0x6 2: R_X86_64_PC32 *ABS*+0x11f. Linked into a static executable: 401000: 0f 84 1d f1 bf ff je 123.Sojourn
But apparently Windows object files don't support (properly) such relocations, and the OP appears to be using Windows (from the LNK2016 error and the calling convention): How to write an absolute target for a near direct relative call/jmp in MASM - that's why NASM won't support it for -fwin32 and MASM doesn't have syntax for it at all.Sojourn
This WOULD work, but it causes "access violation error". The good thing is that I got my code working, but unfortunately without jumps due that error...Haversack

© 2022 - 2024 — McMap. All rights reserved.