I recently bought Alien Breed: Impact from Steam, an Arcade Shooter (as they call it themselves) that gave me back 'old' feelings (they don't make that many games like it anymore). Anyways, I played it for a while but the controls of the game are horrid. I ended up getting annoyed by the controls. So the logical next step is to hack it ;) By the way, if the controls where better, it would be a lot more fun to play.
However, Alien Breed uses the Unreal 3 Engine. Several other games use it too, like Mass Effect 2, which made me 'worry' a bit. The Unreal 3 Engine takes OO-programing to another level. As soon as I found some values (ammo/health) my suspicions where confirmed. Just like Mass Effect 2, Alien Breed uses 1 function to subtract nearly every value in the game.
Initially I wanted to give up, not that hacking it is impossible. It is just a lot of work and is it really worth it? I decided not to give up. And my decision will probably make me look into Mass Effect 2 again.
After putting a (memory-write) break-point on the ammo value, I saw that the instruction at 0x4BE228 is responsible for subtracting health, ammo, enemies health, cash, etc. Replacing the the "sub [ebx], eax" instruction with nothing (nop's) worked. Ammo was frozen and I couldn't die. But it also made it creatures, windows, etc invincible.
The next step in the chain was to trace (using Syser) the function's return address (which was 0x4C5331), that was a dead-end too. All values used this same function. Instead of digging deeper, I decided to try and find something in the call-arguments of the subtract function (0x4BE180) that allowed me to identify the values it was subtracting from.
To do this I had to figure out a bit on how the subtract function worked. This wasn't easy, mainly because the function accepts a wide array of values it has to subtract from. Through tracing I found out that the first call within the function (call edx at 0x4BE1B5) retrieves the pointer to the value it is going to subtract from.
Looking at the first call that it does, we find out it bases this call on the value that is present at the first argument + 0x18 (it loads the first argument in esi @ 0x4BE183 and then loads a the pointer from [esi+0x18] into eax). It loads a byte from the pointer that it gets, and then uses that to call the function for the address to the value. For ammo, health, cash, that value is 1. The function that it calls when the value is 1 is 0x4BB610.
Inspecting this function gets us to the following conclusion, [[[first argument + 0x18] + 0] + 0x64] contains the offset of value compared to the class that is calling the subtract function. While checking out the memory address that [[first argument + 0x18] + 0] points to, I saw that [[[first argument + 0x18] + 0] + 4] points to a value identifier. For ammo this identifier is 32810 and for health its 5685.
With this info we can determine when to subtract the value, and when to keep the value the same. The problem however was that the function overwrites several things before it finally gets to the actual subtract instruction (at 0x4BE228). So the decision to subtract or not would have to be made at the start of the function. (perhaps its possible to get the original esi value back, but I gave up looking for it)
This brought me back to the function that calls our subtract function, which was the 0x4C5331 function (or well, thats the return address). In this function we see that it gets the subtract function from a look up array (see 0x4C5322), using Cheat Engine we find that the subtract function-address is stored in 0x11C9438. I decided to make a detour function and write its address into 0x11C9438.
With the detour function in place, my first try was to not-execute the subtract function if it concerned ammo/health/etc. This quickly led to a crash. Apparently the subtract function does more then subtract. My next try was to get the pointer to the value, and increase it with the value being subtracted (as such, subtract would then have no effect). This quickly led to an issue, the value it subtracts from the main value (ok too many value's in one sentence) is also stored in an object.
It was getting late, and I was getting bored real quick with these objects in objects. So I decided to actually change the code depending on the main value. If the value is ammo/etc, I change the subtract instruction at 0x4BE228 to nop, if the value is something else, I change subtract the instruction at 0x4BE228 back to its normal value.
This worked! So while probably not the most elegant method to success, it definitely works. I had to put in one additional check for Health. Because the Health identifier was the same for everyone (e.g. also enemies), I had to check if the health was player-health or enemy-health, I did this by checking the v-table of the calling-class (for the player its 0xF4FE60).
The end result is this +4 trainer.