Madness
Madness

Reputation: 41

How to get the instruction pointer in x86_64 without 0x00 or 0xFF bytes?

Is there a way to access the value in the instruction pointer (RIP) without using a call followed by a pop in assembly language? Or is there a machine code opcode that can do it?

I have been googling with no clear results.

My problem is that I can't have any zeroes in the machine code, or else I get a SIGSEGV error. It's due to the way the server loads the code and executes it from a string of bytes. A near call has zeroes in the distance to the subroutine, so using call is not an option.

I'm on linux, 64-bit, and have nasm and yasm.

Upvotes: 3

Views: 6434

Answers (1)

phuclv
phuclv

Reputation: 41805

In x86_64 the standard way is to use RIP-relative addressing instead of CALL like in x86. Even then, call/pop is not a recommended way1

Normally you'll use lea rax, [rip] to get RIP into RAX (which is actually encoded as lea rax, [rip + 0] with four bytes for the immediate at the end). However since LEA doesn't dereference the memory address, you can just add any constant displacements to the RIP and subtract it later

0:  48 8d 05 04 03 02 01    lea    rax,[rip+0x1020304]
7:  48 2d 04 03 02 01       sub    rax,0x1020304

You can choose any immediate values that don't have a zero or 0xFF byte. If you want the address of the instruction after lea (which is 7 bytes long) you can fix up accordingly with sub rax, 0x01020304 - 7


1The recommended way is

GetCurrentAddress:
    mov eax, [esp]
    ret
...
    call GetCurrentAddress
    mov [currentInstruction], eax

in order to avoid mismatching between the call stack and the return stack buffer (RSB). But probably it isn't important in shellcode

Upvotes: 6

Related Questions