0
Recreating Geri's tutorials and articles before his site got wiped out. Wealth of information in it!
-----
This tutorial will not be long, I just want to share something that may help some people when they are making cheats for games that are using memory integrity checks. Of course the best way is to somehow circumvent the memory check so it will not get you, but let's say that you are not skilled enough for it, or it would take too much time and effort and it doesn't worth it. In that case, you may consider making an option that doesn't have to be turned on all the time, eg it is adding some health or ammo and then it can be turned off.
At this moment, Cheat Engine doesn't have an option to execute a script only once, but Dark Byte has provided a neat template that you can use in your AA scripts. The purpose of the script is to change back the code to the original if your cheat script has been executed, so if you use a code that is executed let's say 100 times per second, chances that a protection will find you in that fraction of second is pretty low. So here is Dark Byte's script:
alloc(mycode,512)
alloc(originalcode,6)
label(returnhere)
originalcode:
db or ig in al co de
fullaccess(game.exe+1234) //make read/write/execute
game.exe+1234:
jmp mycode
returnhere:
mycode:
do your stuff like storing the address
//restore with original bytes
pushad //can't be bothered
pushfd
cld
mov ecx,6 //nr of bytes
mov esi, originalcode
mov edi, originaladdress
rep movsb
popfd
popad
(originalinstruction)
jmp returnhere
It may be confusing if you are not familiar with all of the instructions in the code, but it will do the job perfectly. Here is the same script with my comments:
alloc(mycode,512) //allocate 512 bytes for your cheat script
alloc(originalcode,6) //allocate 6 bytes, assuming that the original code is 6 bytes. if it is more or less, adjust the number
label(returnhere) //usual returnhere label as in every script, the code after the original code
originalcode: //define originalcode
db or ig in al co de //here you need to put the bytes that are making up the original code
fullaccess(game.exe+1234) //make read/write/execute //don't forget to give the size parameter, in this case it is 6 bytes
game.exe+1234: //change the original code to...
jmp mycode //...a jump, and as the jump will take up 5 bytes, you will also need a nop after it to have your 6 bytes
returnhere: //the code after the original code
mycode: //here is the place of your cheat script, whatever it is
do your stuff like storing the address
//restore with original bytes
pushad //can't be bothered //save registers
pushfd //save flags
cld //clear direction flag, see below
mov ecx,6 //nr of bytes
mov esi, originalcode
mov edi, originaladdress
rep movsb //move the bytes of the original code to the original code's address, see below
popfd //load flags
popad //load registers
(originalinstruction)
jmp returnhere
cld instruction:
Clears the DF flag in the EFLAGS register. When the DF flag is set to 0, string operations
increment the index registers (ESI and/or EDI). Operation is the same in all
non-64-bit modes and 64-bit mode.
rep movsb instruction:
This is a bit complicated to explain in just a few words, but here is the short story. It will copy the bytes from the address on ESI to the address on EDI. In our case, copy the original code to the original code's address. Usually you will not see this command when you are hacking games (it is used for strings, not for values like health etc), but it is useful here. In case you are interested in the long description of the command, just look it up on the net.
Maybe it is helpful if I put up some actually working code and not just a template, so here are 2 examples. Both of them is for the tutorial of Cheat Engine 6.1. Their purpose is to change your health to 999 if you click on the Hit me button in the 2nd step of the tutorial, then if this happened, change back the code to the original. Here is the first, pretty much the same as what Dark Byte has posted:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
alloc(mycode,512)
alloc(originalcode,6)
label(returnhere)
originalcode:
db 29 83 58 04 00 00 //these are the original bytes of the code line
fullaccess(00420F3E,6) //make read/write/execute //00420F3E is the address of the original code
00420F3E:
jmp mycode
nop
returnhere:
mycode:
mov [ebx+0458],(int)999 //change health to 999
//restore with original bytes
pushad //can't be bothered
pushfd
cld
mov ecx,6 //nr of bytes
mov esi, originalcode
mov edi, 00420F3E
rep movsb
popfd
popad
jmp returnhere
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
The script above is having a little problem, it is not doing anything when you disable the code, so users would actually hit the hotkey twice to enable the cheat after every use. To solve that, here is another example:
[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
globalalloc(mycode,512)
globalalloc(originalcode,6)
label(returnhere)
originalcode:
db 29 83 58 04 00 00
fullaccess(00420F3E,6) //make read/write/execute
00420F3E:
jmp mycode
nop
returnhere:
mycode:
mov [ebx+0458],(int)999
//restore with original bytes
pushad //can't be bothered
pushfd
cld
mov ecx,6 //nr of bytes
mov esi, originalcode
mov edi, 00420F3E
rep movsb
popfd
popad
jmp returnhere
[DISABLE]
//code from here till the end of the code will be used to disable the cheat
globalalloc(mycode,512) //I have changed the alloc to globalalloc so it is allocated only once, not all the time when you run the script
globalalloc(originalcode,6)
label(returnhere)
originalcode:
db 29 83 58 04 00 00
fullaccess(00420F3E,6) //make read/write/execute
00420F3E:
jmp mycode
nop
returnhere:
mycode:
mov [ebx+0458],(int)999
//restore with original bytes
pushad //can't be bothered
pushfd
cld
mov ecx,6 //nr of bytes
mov esi, originalcode
mov edi, 00420F3E
rep movsb
popfd
popad
jmp returnhere
Hope this will be helpful for some people who are looking for this kind of option in Cheat Engine, because sometimes memory checks can be a real pain for beginners and I think that this is an acceptable solution for those who don't want to bother with it too much.