Auto-Assembler and SSE Mnemonics

CoMPMStR
I've gotten a little bored with my GTA4 projects so I started hacking some more games. I've been using this method for quite awhile now so I decided to post a little tutorial for those who hack games with SSE mnemonics.

Some tools you will need:
- MHS (...!)
- Simple .NET Disassembler (a little disassembler I created thanks to the cheat engine source that supports SSE byte codes)


This tutorial assumes that you know how to search for values so I will not go in depth on that, there are plenty of others for that. I will say that I am using Wolfenstein v1.0 for this tutorial and will show how to get infinite ammo that's using SSE mnemonics then put it into an auto assembler script to use in MHS.

Note: If you are searching for the ammo, it's a float value instead of long. And I used the MP40 (the gun first acquired at the beginning of the game), with a full clip it has 32 shots. 


Determine the function location and identify the ASM mnemonic...


After you find the ammo address, right click on the entry in the list and select "Find What Accesses This Address".





After that, go back into the game for a few seconds to let the debugger work, then ALT+Tab back to MHS. For this situation, it will be the address that has the most hits (although it may not always be the same for every game). So right click the address in the disassembler auto-hack window then select Go To->In Current Tab. For simplicity sake, the static address I'm referring to is gamex86.dll+38B090 or 0B22B090. Note that the module changes on each game start so you may get a completely different hex address than I've gotten, the module+offset combination should still be the same as long as you have the same game version.





Now that you have the function location, it's time to see what the code disassembly actually is. So now you need to open the hex editor and enter the address for the function that you just found in the disassembler.





Now you need to copy all the bytes of the function as Hex Text.





Once the bytes are copied to the clipboard you can switch over to the Simple .NET Disassembler program and paste the bytes in the left textbox (under the button) then click the button; you can enter the address if you choose but it's not necessary for this situation.





You can see in the disassembly that the two incorrect code mnemonics are REPE MOVSS XMM0,[ECX+38] and COMISS XMM0,[0B422140] but for this particular case the only concern is the first.





Now you must be wondering "How am I supposed to turn this into infinite ammo?" and you're about to find out. First since every weapon should have a max ammo amount, you need to try to find the address for it. To do this you need to go back to the hex editor and enter the current ammo address (this is to check if the max ammo value is stored somewhere near the current ammo value).





Luckily, if you look 4 bytes after the current ammo value, you find the max ammo value only 1 float distance away (ie: 4 bytes).





So since [ECX+38] is the current ammo value, [ECX+3C] would be the max ammo value; great now you can set up the auto assemble script.


Writing the auto assembler script:


First you need to declare some things: a label, a fullaccess request, and a memory allocation. So at the top of the auto assemble text you should have this:


label(ammoret)
fullaccess(gamex86.dll+38B090, 5)
alloc(infammo, 90)


Now that you have the declarations written, you can continue with the [enable] and [disable] sections. Under [enable] all you need is a jmp call followed by the allocated code cave then the return jump back to the original code, but how is this done? Easy:


[enable]
jmp infammo

infammo:
push eax
mov eax, dword ptr [ECX+3C]
mov dword ptr [ECX+38], eax
pop eax
db 0xF3 0x0F 0x10 0x41 0x38
jmp ammoret


If you're looking at this like wtf then continue reading. This code simply says that it will jump to the new location, push eax onto the stack (because you don't know what value it holds or what is its use, all you know is that it isn't used in the code you're modifying), copy the max ammo value into the eax register, copy the eax register (which now contains the max ammo value) to the current ammo value, then pops the value eax had previously back into the proper register. For this situation you might not need the push and pop mnemonics but it's a good habit to get into, it will definately avoid any unnecessary game crashes.

The db command allows you to specify a set of bytes without typing an actual mnemonic, and it works great for something like this where you have a mnemonic that isn't supported. This specific db statement is just the original SSE mnemonic that is being overwritten by the initial jump. Lastly, it will jump back to the original location; even though you haven't specified it yet (I'm getting to it, it comes after the [disable] section).

The [disable] section is really short, basically it just reverts the inital jump back to the original mnemonic it was at first. Then the dealloc function is called to remove the previous memory allocation that was used for the jump:


[disable]
db 0xF3 0x0F 0x10 0x41 0x38
dealloc(jmpammo)


Finally, you can get to the return jump. At the very bottom of the auto assemble text should be the return jump label, specified as such:


ammoret:
gamex86.dll+38B095:


The reason for gamex86.dll+38B095 is because the mnemonic you have to overwrite is 5 bytes in length, so 38B090+5 is 38B095. Now before clicking the OK button make sure to tick the box 'Use Auto-Assemble for Locking'.

To sum it up, the complete auto assembler script should look something like this:


label(ammoret)
fullaccess(gamex86.dll+38B090, 5)
alloc(jmpammo, 90)

[enable]
jmp jmpammo

jmpammo:
push eax
mov eax, dword ptr [ECX+3C]
mov dword ptr [ECX+38], eax
pop eax
db 0xF3 0x0F 0x10 0x41 0x38
jmp ammoret

[disable]
db 0xF3 0x0F 0x10 0x41 0x38
dealloc(jmpammo)

ammoret:
gamex86.dll+38B095:


If you've gotten everything correctly then you should be able to go back into the game and shoot without reloading. Also with this particular hack you will also get all weapons plus infinite grenades. ;) Don't blame me if it doesn't work online!


Thus ends my tutorial. All questions, comments, suggestions, or corrections are welcome. :D I'll do my best with any questions.