Skip to main content
2 of 4
Clarity.
dsasmblr
  • 2.3k
  • 11
  • 19

The joy of shared instructions! Here are a couple of ideas for you to consider, both of which I'm going to be using Cheat Engine to demonstrate because it's fast becoming the superior dynamic analysis tool for game-hacking.

1. Instead of looking for the instruction that writes to the address, right-click on it and look for instructions that access the address. There, you will find instructions that read the value from the address, as well as instructions that write to it. An example of an instruction that reads the value might be for the HUD representation of health. To know how far up to show your health bar being filled, it reads the value from your health address.

What that means is if you find an address that reads your health value, that may be the only thing that instruction does. You can then create a code injection just before that instruction and move a custom value into the address that's being referenced or pointed at.

For example, let's say this is an instruction that reads from your health address:

mov eax,[ecx+0C]

In that case, your health address is being pointed to by [ecx+0C]. The value there is being moved into the eax register. What you could do is create a code injection at that instruction with which to write a custom health value to [ecx+0C] before the mov instruction runs. This is easy to do with Cheat Engine (via its native code injection functionality), but otherwise requires you to look into code-caving.

2. To use a shared instruction like the one you've found, you have to find a way to differentiate what you want to influence, from the rest of the addresses being written to. This can look like a daunting task, especially when you find a shared instruction like in GameMaker games where HUNDREDS of addresses are all being written to through one instruction, but fear not!

Your options are to find differences in the following places:

A) Memory addresses (Including the stack)
B) Registers (General purpose, FPU/XMM, special purpose, etc.)

Right-click on the shared instruction and choose "Find out what addresses this instruction accesses." A new window will pop up showing addresses that instruction is writing to. From that window, you can do a whole lot of neat things.

First, Cheat Engine provides a handy Data/Structure Dissect tool that you can use to compare values between multiple memory addresses. If you select all the addresses (Shift-click, or Ctrl-click the ones you're interested in), then right-click, you'll see an option to open the data dissect tool. There, you can compare values to find differences in the same offsets!

Something else you can do from that list of addresses is hit Ctrl + R to view the contents of registers. There, you can usually find a register containing a different value between all addresses (you'll want to look for a differing value that's NOT a dynamic memory addresses, because that value will change when restarting the game).

Finally, when viewing the contents of registers, there are two little buttons on that window: 'S' and 'F'.

'S' lets your view the stack. There, you can look for values to differentiate. 'F' lets you view the contents of the FPU, and XMM registers. Sometimes, the latter can be helpful because, say, the FPU might have been used ONLY for health and not for any other values that shared instruction is writing to.

Bringing it all together, you'll use whatever unique value(s) you find to write a custom code injection that will allow you to single out the value you're interested in. Let's say your instruction is this:

mov [edx+0C],eax

And let's say that, in register ebx, you found a unique value of 2B.

Your injected code might look something like this:

label(customCode)
label(restoreFlags)
label(originalCode)
label(return)

customCode:
  pushf //Preserve flags register by pushing onto the stack
  cmp ebx,2B //Does ebx contain the offset you're interested in?
  jne restoreFlags //If not, restore flags register and resume normal execution
  mov eax,(float)100 //If so, move a custom health value into eax for originalCode
  //Execution flow from here moves to restoreFlags

restoreFlags:
  popf //Restore flags register
  //Execution flow from here moves to originalCode

originalCode:
  mov [edx+0C],eax //eax contains either value from normal execution, or custom health
  jmp return //Return to the point we injected and resume normal execution

I don't mean this as shameless self-promotion, but I've been running a YouTube channel for the better part of 3 years that teaches reversing via game-hacking. If games are your medium and you enjoy learning via videos, I think you'd really learn a lot from my CE tutorial series, specifically. I also teach game-specific hacks, like Cuphead, ELEX, etc.

Good luck!

dsasmblr
  • 2.3k
  • 11
  • 19