1

I'm very new to all this, so sorry if I mess up and/or am unclear. I'm working on reverse engineering assault cube, where a lot of people start, and I'm struggling to understand how this one AOB injection works. In order to make this more universal, I'll try to omit specific things about assault cube. This is all in x86 32-bit, and I'm on Windows 64-bit.

My goal is to replace 5 bytes at the address of ac_client.exe (base address) + 29D1F (<-00429D1F) to a jmp instruction to a function that I dynamically allocated in C++. cheat engine shows that in their AOB injection version, the bytes at that address become E9 DC622600, and they label it as jmp 00690000. Following that, at the code at address 00690000, there's another jmp instruction later to return control. these instructions bytes are E9 189DD9FF and its labeled jmp ac_client.exe+29D24 (<- 00429D22, the address of the instruction after the one it replaced). In short, I'll need to be able to inject the compiled bytes of a jump instruction to a specific memory address into memory during runtime.

So, in trying to replicate that, I have not been able to draw a link between the bytes and the addresses they represent (DC622600 : 00690000, 189DD9FF : 00429D1F). I have tried big endian, small endian, octals, hex ofc, absolute vs relative, and I can't find anything. I've also tried reassembling and dissembling all of these values / instructions with https://defuse.ca/online-x86-assembler.htm#disassembly and cannot find a link. If any of you may know what I'm doing wrong, I would hugely appreciate any help, and if you need any more info, I'm on it! Thanks a ton!

2 Answers 2

1

E9 is jump relative

it jumps to an address relative to the next instruction address

E9 is a five byte sequence 1 byte for opcode and 4 byte for calculating the relative location

assume you are at address 0x1000 the next instruction will start at 0x1005

the jump location is calculated by adding 0x1005 with the constant in the current instruction

in your case the constant is DC622600 or 0x002662dc adding 5 makes it 0x002662E1

this is the address it will jump to which in your case happens to be 0x00690000

so current instruction address must be 0x690000-0x2662e1

which is '0x429d1f'

>>> ip = 0x429d1f
>>> len = 5
>>> nextaddress=ip+len
>>> jmpconst = 0x2662dc
>>> jmploc = nextaddress+jmpconst
>>> print("%x %x %x %x %x\n" % (ip,len,nextaddress,jmpconst,jmploc))
429d1f 5 429d24 2662dc 690000
1

These jumps use 4 byte little-endian offsets relative to the next instruction's address.

That's a mouthful so a walkthrough should make it easier:

Your first example is a jump from address 0x429D1F to 0x690000. The jmp instruction itself will be 5 bytes, the opcode E9 plus a 4 byte little-endian offset. But the offset is relative to the next instruction's address, so it is relative to 5 bytes further.

So to calculate that offset, we calculate:

offset = destination - (source + 5)
offset = 0x690000 - (0x429D1F + 5)
offset = 0x2662DC

If you look closely, that is almost the bytes you found - DC622600 but not quite because of the endianness. 0x2662DC as 4 bytes little-endian is DC 62 26 00 which is what CheatEngine showed you.

And to add a bit - another instruction for jumps is the short jmp, opcode EB which only uses a 1 byte relative offset instead of 4 bytes (sometimes that's all you need and you can save space!), so there you'd calculate

offset = destination - (source + 2)

So same principle, opcode plus offset relative to the next instruction's address.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.