10

I'm trying to code a exe packer/protector as a way of learning more about assembler, c++, and how PE files work. I've currently got it working so the section containing the EP is XORed with a key and a new section is created that contains my decryption code. Everything works out great except when I try and JMP to the original EP after decryption.

Basically I do this:

DWORD originalEntryPoint = optionalHeader->AddressOfEntryPoint;
// -- snip -- //
    crypted.put(0xE9);
 crypted.write((char*)&orginalEntryPoint, sizeof(DWORD)); 

But instead of it jumping to the entry point, ollydbg shows that this code disassembles to:

00404030   .-E9 00100000    JMP 00405035 ; should be 00401000 =[

and when I try to change it manually in olly the new opcode shows up as

00404030    -E9 CBCFFFFF    JMP crypted.00401000

Where did 0xCBCFFFFF come from? How would I generate that from the C++ side?

Qix - MONICA WAS MISTREATED
  • 14,451
  • 16
  • 82
  • 145
Christopher Tarquini
  • 11,176
  • 16
  • 55
  • 73
  • 2
    To whomever might stumble upon this, there was a similar question over at RE.SE where I provided a very detailed explanation: https://reverseengineering.stackexchange.com/questions/19459/calculation-of-jmp-address-through-subtraction – NirIzr Sep 26 '18 at 19:59

3 Answers3

20

you could use:

push DESTINATION_VA
ret

or

mov eax,DESTINATION_VA
jmp eax

relative E9 jmp encoding is used like this:

CURRENT_RVA: jmp (DESTINATION_RVA - CURRENT_RVA - 5 [sizeof(E9 xx xx xx xx)])

push + ret is the best solution if you have VA address and the image is not relocated

Bartosz Wójcik
  • 1,079
  • 2
  • 13
  • 31
  • I'm looking for a similar method for 64 bit address space, with op codes. – Thomas Tempelmann Sep 03 '18 at 16:21
  • 1
    @ThomasTempelmann: [Call an absolute pointer in x86 machine code](//stackoverflow.com/q/19552158) covers x86-64. – Peter Cordes Nov 24 '19 at 20:43
  • 3
    [My edit on this answer](https://stackoverflow.com/revisions/2049606/2) addressed serious performance problems with `push`/`ret` but unfortunately the poster rolled it back. If you care about performance on modern x86, use `mov eax, dst` / `jmp eax` instead of unbalancing the return-address predictor with a `ret` that doesn't match up with a `call` (https://agner.org/optimize/). And/or see [Call an absolute pointer in x86 machine code](//stackoverflow.com/q/19552158). **`mov`/`jmp` costs 1 extra byte vs. `push`/`ret` and avoids future branch mispredicts if you `ret` from the target** – Peter Cordes Nov 26 '19 at 04:30
7

I think that E9 is an opcode for a relative jump: its operand specifies a relative distance to be jumped, plus or minus from the start of the next instruction.

If you want the operand to specify an absolute address, you would need a different opcode.

ChrisW
  • 54,973
  • 13
  • 116
  • 224
  • Any ideas as to what would be a replacement for E9? – Christopher Tarquini Oct 09 '09 at 22:07
  • 1
    Jumps are usually relative. There's an opcode `EA` for a jump to an absolute far address, and opcodes for jumps to an indirect address (where the operand specifies the memory location wich contains the address to be jumped to). – ChrisW Oct 09 '09 at 22:17
  • 2
    This didn't answer the question, just confirmed that the OP had the wrong answer. – MrSynAckSter Aug 01 '16 at 00:15
  • @baordog The question was, "Where did 0xCBCFFFFF come from?" Anyway apparently the OP understood the answer, and/or was satisfied by `EA` in the comment. – ChrisW Aug 01 '16 at 00:38
6

opcode for absolute indirect jump is FF + 4byte address. This is most often used for jumptables of addresses stored in data.

Absolute addresses do require relocation when not loaded to the expected address, so relative addresses are generally preferred. Code for relative jumps is also 2 bytes smaller.

Intel optimization manual states that the cpu expects call and ret to be used in pairs, so the ret without a call suggested in answer 2 would cause what they call a "performance penalty".

Also, if the code was not loaded to the same address that the compiler assumed, the ret would probably crash the program. It would be safer to calculate a relative address.

Ann
  • 77
  • 1
  • 1
  • 3
    perhaps you mean FF 25 4byte.. FF 4 byte makes no sense at all. – Laie Oct 10 '14 at 03:49
  • 1
    @Laie it still makes sense since `FF` is the opcode and we know the mnemonic is `jmp`. It could be `FF /4` or `FF /5` since they are both jump absolute indirect -- one being a near and the other a far jump. But yes, `FF 25 aa bb cc dd` is how you would observe `FF /4` (the more common of the two) in machine code. – Graeme Wicksted Feb 16 '17 at 19:33
  • 1
    The last paragraph isn't right: `push imm32` / `ret` won't crash, relocating the code won't change the absolute target address that `ret` jumps to. The problem is performance: unbalancing the return-address stack will make some future returns mispredict. A `mov reg,imm32` + 2-byte register-indirect jump is probably your best bet (rather than loading a pointer from memory) if for some reason you can't just encode a `jmp rel32` *from* a known address,. [Call an absolute pointer in x86 machine code](//stackoverflow.com/q/19552158). – Peter Cordes Apr 27 '18 at 04:35
  • It would be nice to mention a matching jmp opcode for 64 bit mode as well. – Thomas Tempelmann Sep 03 '18 at 16:20
  • 1
    @ThomasTempelmann: [How to jump to memory location in intel syntax for both x64 and x32](https://stackoverflow.com/q/72179508) has both, including the machine code, and [Call an absolute pointer in x86 machine code](https://stackoverflow.com/q/19552158) is about x86-64, and works for jmp as well as call. Normally `mov rax, imm64` / `jmp rax` is your best bet. (Pick any register you can clobber at this point.) – Peter Cordes Oct 13 '22 at 04:02