The x86-64 architecture is very annoying sometimes. Especially when you want to hook functions or do some magical assembly tricks
Suppose you want to hook a function, you will have to change its first instruction to a jump instruction to your code, so the next time the function is being called, the control will be transferred to your stub. Everybody knows this technique, basically you will need 5 bytes, for the opcode E9 (JMP relative) and another DWORD for the relative offset itself. Then you are able to jump backward or forward by 2GB. Sometimes, it’s not enough, just because you have some limitations.
Now the problem with the processor is that there’s no instruction that can branch to an absolute address which is given straight to the instruction as an immediate operand. Try to think of a MOV EAX, 0x12345678,
but instead, JMPABS 0x12345678. What a shame, really. But no worries, of course it’s possible to work it out, the cost is a few more bytes. Sometimes you are short on bytes. However, just to open your appetite you can sometimes even hook a 1 byte function that only RETs in an efficient way. That’s worth another blog post sometime.
Anyway, what you can do is changing the code a bit and do something like this:
JMP EAX ; <— Suddenly the processor supports absolute addresses, ah ha!
But now, this code takes 7 bytes and it also screws up one of the registers. There are two possible fixes, either store and then reload EAX at the callee site (BAHH!!) or change the code again, which is trivial:
This is very nice one, although, technically, I am not sure whether it’s slower than a simple JMP. The algorithm for the RET instruction is quite impressive (to branch predict the caller(/return) address…), mind you. Now the code takes only 6 bytes, plus, you can access the whole address space.
Let’s move to another similar issue, suppose you want to CALL an absolute address, what you gonna do now?
CALL $ + 5
LEA EBX, [EBX + NEXT-HERE]
MOV EBP, ESP
XCHG EBX, [EBP + 4] ; 1337
PUSH <Absolute Address>
I will leave it to you to figure it out, hint – it doesn’t screw any register.