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?
ORG
to tell the assembler about it, and it can calculate the proper displacement. – Newburg0x7FF7847902EE
? 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