Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C# Theoretical: Write a JMP to a codecave in asm

Lets assume I've allocated the address where my codecave is placed using VirtualAllocEx (it returns the address) and I write my code into that address using WriteProcessMemory().

Here's the question:

How do I write a jump to my codecave? I know that jumps start with "E9", but how do I convert the address returned by VirtualAllocEx into a correct UInt32 (dword) so the debugger/compiler will understand the instruction?

For example:

I'm at address 00402020 (OEP of the native app). I write a jump to 004028CF (empty place) "JMP 004028CF". The instruction in bytes looks like this:

CPU Disasm
Address   Hex dump      Command                                  Comments
00402020  E9 AA080000   JMP 004028CF

"E9" is how we indicate a JMP. What about "AA080000", how do I generate this?

I need to do something similar so I can initialize a JMP to my codecave, which will be located at an address returned by VirtualAllocEx().

Any help will be gratefully appreciated!

Thanks in advance.

like image 835
Ivan Prodanov Avatar asked Apr 24 '09 18:04

Ivan Prodanov


2 Answers

E9 is a relative jump so the later 32 bits are just an offset to the current instruction pointer. See Intel® 64 and IA-32 Architectures Software Developer’s Manual Volume 2A: Instruction Set Reference, A-M pages 549ff for details. For more information see Intel® 64 and IA-32 Architectures Software Developer's Manuals.

So the opcode to jump from 00402020 to 004028CF should be the following.

    E9  00 00 08 AA
Offset   = DestinationAddress - CurrentInstructionPointer
000008AA = 004028CF           - 00402025

When the jump instruction is executed, the instruction pointer is already set to the next instruction. So the offset of the jump instruction and the current instruction pointer value differ by 5.

CurrentInstructionPointer = AddressOfJumpInstruction + 5

UPDATE

Corrected error about the current instruction pointer value. Thanks jn.

like image 197
Daniel Brückner Avatar answered Sep 29 '22 23:09

Daniel Brückner


to get the relative offset just subtract the addresses:

uint32_t patch_address = (uint32_t) VirtualAlloc(...);
uint32_t jmp_offset = patch_address - (current_offset + current_len);

note: current_len is 5 bytes on x86 E9 JMP instruction. see my post on this thread for more information:

VirtualAlloc C++ , injected dll, asm

like image 35
mschmoock Avatar answered Sep 29 '22 23:09

mschmoock