6

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.

starblue
  • 55,348
  • 14
  • 97
  • 151
Ivan Prodanov
  • 34,634
  • 78
  • 176
  • 248

2 Answers2

4

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.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
Daniel Brückner
  • 59,031
  • 16
  • 99
  • 143
  • 1
    I'm asking how to convert "004028CF" to "AA080000",How do I convert the destination address into those 32 bits so the instrction becomes valid? – Ivan Prodanov Apr 24 '09 at 18:38
  • You could have told me "Destination address -(minus) current address" instead giving me that pdf of 600 pages.However,As previously I mentioned,I appreciate any of your efforts,so I accept your answer.Thanks! – Ivan Prodanov Apr 24 '09 at 18:42
  • @Daniel: what you are saying here is wrong! The correct formula for this case is: to - from - 5 – newgre Apr 24 '09 at 18:47
  • If thought "E9 is a relative jump so the later 32 bits are just an offset to the current instruction pointer." clearifies the meaning. ^^ I was a bit confused about your AA080000 because it does not match the difference and I wanted to assert that I am right before I add an example. – Daniel Brückner Apr 24 '09 at 18:49
  • Actually,you're wrong!Its AA,not AF.The jmp has length 5 bytes,it starts to count after those 5 bytes,so AF-5 = AA. Correct? ;) – Ivan Prodanov Apr 24 '09 at 18:51
  • Thanks jn. Verified in the manual and updated answer. I have not done assembler coding for a while ... begining to forget and cannot rember what push SP pushes on the stack, too. SP or SP + 4? – Daniel Brückner Apr 24 '09 at 19:01
  • ESP (on x86) always points to the last recently pushed item on the stack. When you push an item to the stack, ESP is decremented first, and then the parameter is stored at [ESP]. – newgre Apr 24 '09 at 19:06
1

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

Community
  • 1
  • 1
mschmoock
  • 20,084
  • 6
  • 33
  • 35