2
votes

I need to make a jump opcode for an exploit demonstration.

I need to jump to about 200 bytes after the jump instruction. This is too much for a jmp short.

If I generate an opcode with a regular jump, jmp $200 I get this:

e9 fb 01 00 00

The problem here is that opcode contains 00 which is interpreted as an end of string when passing the string to the program (as such I can't pass the full shellcode with this in it).

I thought my approach was screwed but then I checked the manual and on the second line there is apparently a "near jump" that takes 2 bytes (there's also the other one that takes 4 bytes, the one I showed above). Both these jumps start with the same byte, e9.

How can I pass e9 fb 01 as the near jump that takes only two bytes arguments? How do I prevent the OS from looking for four bytes after the e9, ie: e9 fb 01 90 90?

2
Why do you need to pass the program as string? Can you use length prefixed string?phuclv
It's definately not the OS which is looking for four bytes, it's the processorrebrec

2 Answers

6
votes

You cannot.

The 0xE9 opcode uses a 32-bit offset when the processor is running in 32-bit mode, and a 16-bit offset only when the processor is in 16-bit mode.

2
votes

If you have access to the current EIP address within the shellcode and the memory area is writeable you could do something like this:

; say in ECX you have shellcode start address
; (calculated with delta offset etc.)
_start:

...

; ECX = offset _start

; decrypt zero bytes in jmp instruction relative address

; 80 69 xx  AB
sub byte ptr[ecx+(_fix1-_start)], 0ABh

; 80 69 xx+1 BA
sub byte ptr[ecx+(_fix2-_start) + 1], 0BAh

; jmp instruction with those 00s encrypted
_jmp  db 0E9h, 0FBh, 01h ; first 3 bytes of jmp near instruction
_fix1 db 0 + 0ABh        ; encrypted displacement (last 2 bytes)
_fix2 db 0 + 0BAh     

So the relative address encoded in jmp near instruction doesn't contain 00s, but at runtime those bytes are restored.

Keep in mind that the decryption instruction might contain 00s also if the difference from the calculation (_fix1-_start) contains zeros, more probably if the generated instruction is the long form of sub [r32 + imm32], imm8), so check it manually too.