1

How would I jump to a known memory address in intel assembly syntax (both x32 and x64).

I think I have the 64 bit syntax down. For example, if in x64 I wanted to jmp to the code at 0x75767 and I was located at 0000, I would do:

0000: FF 25 01 00 00 00         jmp QWORD PTR [rip+0x75761]

Is that ^ correct? I thought I could dissemble those bytes that into x32 instruction using objdump objdump.exe -D -Mintel,i386 -b binary -m i386 test.bin which results in:

jmp    DWORD PTR 0x75761

Then just use clang++.exe -masm=intel -m32 -c test.o to convert this instruction to x32 bytes but it says:

error: invalid operand for instruction
jmp DWORD PTR 0x75761
^

I want to avoid writing into any registers.

Is my x64 jmp instruction correct?

How would I accomplish something similar in x32? Let's say in x32 I need to jmp to 0x400107 and I'm at 0x400000

I'm messing around with tweaking running process memory on Windows. Forgive me if my question has inaccuracies, I'm learning.

Peter Cordes
  • 286,368
  • 41
  • 520
  • 731
ChrisMan
  • 109
  • 1
  • 2
  • 10
  • Already your first code is wrong. You can clearly see it uses 32 bit offset not 64. If you want to jump to an absolute address then in 64 bit mode use an embedded pointer addressed rip relative. In 32 bit mode you can use the `push`+`ret` trick. If you know the offset you can of course encode that directly. – Jester May 10 '22 at 00:35
  • All addressing modes you can use take a 32 bit displacement, so the jump target has to be within ±2 GiB of where the jump instruction is. So no, the instruction is not correct: the displacement you desire is out of range. – fuz May 10 '22 at 00:35
  • I sorta noticed that when I just wrote this. Let me modify. – ChrisMan May 10 '22 at 00:36
  • 1
    @Jester so you're saying I could do `push 0x75767` and then `ret` if I wanted to get to `0x75767` ? (for x32) If so will that mess the stack up for future execution? – ChrisMan May 10 '22 at 00:41
  • 1
    Since `ret` removes the address pushed, no, it does not mess up the stack. – Jester May 10 '22 at 00:45

1 Answers1

4

It's unclear whether you need assembly or machine code. If you want to jump to an absolute address then in 64 bit mode use an embedded pointer addressed rip relative:

jmp [rip+foo]
foo: .quad target_address

Machine code: ff 25 00 00 00 00 xx xx xx xx xx xx xx xx (with the last 8 bytes being the target absolute address).

In 32 bit code you can use the push+ret trick if you are not worried about branch prediction:

push offset foo
ret

Machine code: 68 xx xx xx xx c3

If you can calculate the relative address you can of course just use a normal jmp which is e9 xx xx xx xx with the last 4 bytes being the distance to jump (counted from the byte following the instruction, where execution would normally continue).

Jester
  • 54,538
  • 4
  • 72
  • 115
  • Nice, I think this could do the trick. I'll have to test this out. – ChrisMan May 10 '22 at 00:57
  • What assembler uses the syntax `[rip+foo]`? In nasm it would be `[rel foo]` and in gas it would be `(%rip+foo)`. – prl May 10 '22 at 07:53
  • @ChrisMan: Note that `[rip+foo]` targets `foo` using relative addressing, but `[rip+0x75761]` uses `0x75761` literally as an offset relative to the end of this instruction. So they're interpreted differently. See [How do RIP-relative variable references like "\[RIP + \_a\]" in x86-64 GAS Intel-syntax work?](https://stackoverflow.com/q/54745872) – Peter Cordes May 10 '22 at 08:08
  • @prl: GAS/clang `.intel_syntax noprefix`; like the question said, it's using clang to assemble. – Peter Cordes May 10 '22 at 08:09
  • @ChrisMan: Fun fact: GAS assembles `jmp 0x75761` to a relative jump to reach that absolute address from wherever it ends up at link time. It works in a `gcc -nostdlib -static -m32 foo.s` executable, but unfortunately clang doesn't support it. But it doesn't get a runtime fixup to make it work properly in a non-PIE executable, so it's kinda hacky. [Call an absolute pointer in x86 machine code](https://stackoverflow.com/q/19552158) – Peter Cordes May 10 '22 at 08:14
  • @Jester wait so `ff 25 00 00 00 00 xx xx xx xx xx xx xx xx` would be a jmp to an absolute address? – ChrisMan May 10 '22 at 18:15
  • Yes, that is an absolute address. Only the pointer is addressed relative :) – Jester May 10 '22 at 18:34
  • 1
    Yup, that did the trick in both cases. push ret for x32 was too ez. Thanks! – ChrisMan May 10 '22 at 20:49