Difference between revisions of "Tutorials:Create cheat table full:health hack"
(Created page with '<!-- Syntax Highlighter: url: http://pinetools.com/syntax-highlighter Lang: x86asm Lang: cpp Theme: Monokai Sublime --> Category:Tutorial <!-- Tutoria…') |
(→One hit kills: "sense" -> "since".) |
||
(2 intermediate revisions by 2 users not shown) | |||
Line 16: | Line 16: | ||
− | And if you have | + | And if you have followed along then you already have the health address so lets just start with the hook. |
* Else you will need to complete these sections first: | * Else you will need to complete these sections first: | ||
Line 39: | Line 39: | ||
− | And it looks like we found the player's death check. | + | And it looks like we found the player's death check. But these may just be checks the compiler or engine put in place to stop arithmetic problems. |
<pre>cmp dword ptr [ecx+00000344],00 | <pre>cmp dword ptr [ecx+00000344],00 | ||
cmp dword ptr [ebx+00000344],00</pre> | cmp dword ptr [ebx+00000344],00</pre> | ||
Line 57: | Line 57: | ||
So this instruction works on the player's and the combatants' health, probably shared by all actor objects in the game. So I think that the actor class will hold some kind of "Decrease Health" function that the player inherits. | So this instruction works on the player's and the combatants' health, probably shared by all actor objects in the game. So I think that the actor class will hold some kind of "Decrease Health" function that the player inherits. | ||
− | When the game or engine is written, actors and players | + | When the game or engine is written, actors and players might be written like this. |
<!-- <pre>//// Actor, base for all actors | <!-- <pre>//// Actor, base for all actors | ||
class Actor(object){ | class Actor(object){ | ||
Line 99: | Line 99: | ||
Now there are different ways of handling shared instructions, we could look at the structures to find a unique identifier. But since we have a good base address for the player we can just check against that to determine if the actor is the player, no need for guess work here. | Now there are different ways of handling shared instructions, we could look at the structures to find a unique identifier. But since we have a good base address for the player we can just check against that to determine if the actor is the player, no need for guess work here. | ||
− | |||
− | |||
=== Step 2 === | === Step 2 === | ||
Line 133: | Line 131: | ||
Note: The "Coord. Hook" must be enabled to have access to the "ptrCoordBase" symbol, if not enabled then this script will fail on syntax check and on injection. | Note: The "Coord. Hook" must be enabled to have access to the "ptrCoordBase" symbol, if not enabled then this script will fail on syntax check and on injection. | ||
− | + | Note: Later I will set the "Coord. Hook" as a primary script with the other script(s) as it's child record(s), or in the table Lua script, to be run first. | |
[[File:Tutorials.Dishonored.HealthHack.06.png|border]] | [[File:Tutorials.Dishonored.HealthHack.06.png|border]] | ||
Line 141: | Line 139: | ||
=== Step 3 === | === Step 3 === | ||
− | But if we look back at the debugger form we see that | + | But if we look back at the debugger form we see that 1 instruction is constantly checking the player health, and another is constantly writing to the player health. My bet is that some where in there it checks to see if we are over the maximum health and the the other sets it to the maximum if over. |
[[File:Tutorials.Dishonored.HealthHack.07.png|border]] | [[File:Tutorials.Dishonored.HealthHack.07.png|border]] | ||
Line 151: | Line 149: | ||
− | And here I am betting that the "+348" is our health max which is just 4 bytes down from our health (this is so common that I always check around the value's address for it's maximum, but this was my | + | And here I am betting that the "+348" is our health max which is just 4 bytes down from our health (this is so common that I always check around the value's address for it's maximum, but this was my process when first learning) so let's add that to the table. If it looks good then let's add it to the script, so if the health maximum goes up the script will still fill it. |
− | Now some people will just cram a large value in the address, but I have even seen this done on a 2 byte address with a 3 byte number being used, so there was [https://en.wikipedia.org/wiki/Integer_overflow numeric overflow] that would corrupt the game saves (and that's no good, plus if it overflows to say the health maximum then that would get set very low and that is the opposite of what I am looking for). | + | Now some people will just cram a large value in the address, but I have even seen this done on a 2 byte address with a 3 byte number being used, so there was [https://en.wikipedia.org/wiki/Integer_overflow numeric overflow] that would corrupt the game saves (and that's no good, plus if it overflows to say the health maximum then that would get set very low and that is the opposite of what I am looking for, at least with this hack). |
So let's work on that script again. | So let's work on that script again. | ||
Line 163: | Line 161: | ||
And let's test the script (remember to save your tables before injections just in case, even saving be for AOB scans is a good idea to me). | And let's test the script (remember to save your tables before injections just in case, even saving be for AOB scans is a good idea to me). | ||
+ | |||
+ | But mine didn't work and if you just copied mine then I bet yours didn't work too. | ||
==== Debugging your script ==== | ==== Debugging your script ==== | ||
− | |||
− | |||
Now I found my type-o but lets debug our script to find the problem. So lets look at that instruction when injecting to see that it is, in fact, injecting to the right spot. | Now I found my type-o but lets debug our script to find the problem. So lets look at that instruction when injecting to see that it is, in fact, injecting to the right spot. | ||
Line 210: | Line 208: | ||
</pre> | </pre> | ||
− | Now having | + | Now, having written to an unknown address or addresses, I will be closing the game to keep from screwing up the game or hack testing (I will close it with task manager or the form close button if in windowed mode, knowing that it doesn't save then, to insure nothing gets saved). And because Cheat Engine can't account for my mistakes, I will also be restarting Cheat Engine to make sure I didn't mess it up too. |
Latest revision as of 12:57, 14 August 2020
This page is a sub page of: Creating a cheat table - Full guide
Now after a restart, this is what my table looks like.
And if you have followed along then you already have the health address so lets just start with the hook.
- Else you will need to complete these sections first:
- And the super speed and super jump hacks include stuff that I will not be going over, and are required information.
But all we really need is the health address to start.
Step 1[edit]
With the health address in the address list let's check to see what accesses the address, in both normal conditions and when in combat.
So here is what I found, the green is normal conditions, purple is when the player hits a combatant, and red is the player being hit by a combatant.
And it looks like we found the player's death check. But these may just be checks the compiler or engine put in place to stop arithmetic problems.
cmp dword ptr [ecx+00000344],00 cmp dword ptr [ebx+00000344],00
Top is when hitting a combatant, and the bottom is when being hit:
So let's start with the player hit death check (bottom death check), select the instruction and click the Show disassembler button. And in the memory view form right click the instruction line and select Find out what addresses this instruction accesses.
And here is what I found.
So this instruction works on the player's and the combatants' health, probably shared by all actor objects in the game. So I think that the actor class will hold some kind of "Decrease Health" function that the player inherits.
When the game or engine is written, actors and players might be written like this.
//// Actor, base for all actors class Actor(object){ string Name = 'Actor'; ... int Health = 70; ... function decreaseHealth(self, amount) { ... if (self.Health == 0) { self.Die() } } } //// Player class Player(Actor){ //// Player inherits form Actor string Name = 'Player'; ... }
Now there are different ways of handling shared instructions, we could look at the structures to find a unique identifier. But since we have a good base address for the player we can just check against that to determine if the actor is the player, no need for guess work here.
Step 2[edit]
So lets get a base script up, and then work from there.
So if the base address was a multi-level pointer then to check it we would need some thing like this:
n_code: push esi mov esi,[ptrCoordBase] test exi,esi jz @f // jump forward to the next label (@b is jmp back). mov esi,[esi+{the base offset}] test esi,esi jz @f cmp esi,ebx jne @f mov [ebx+{health offset}],(int)100 @@: pop esi o_code: cmp dword ptr [ebx+00000344],00
But our base address is at the same level as the health address, so this is all we need.
Note: The "Coord. Hook" must be enabled to have access to the "ptrCoordBase" symbol, if not enabled then this script will fail on syntax check and on injection.
Note: Later I will set the "Coord. Hook" as a primary script with the other script(s) as it's child record(s), or in the table Lua script, to be run first.
Step 3[edit]
But if we look back at the debugger form we see that 1 instruction is constantly checking the player health, and another is constantly writing to the player health. My bet is that some where in there it checks to see if we are over the maximum health and the the other sets it to the maximum if over.
So let's look for our health maximum, in the memory view form.
And here I am betting that the "+348" is our health max which is just 4 bytes down from our health (this is so common that I always check around the value's address for it's maximum, but this was my process when first learning) so let's add that to the table. If it looks good then let's add it to the script, so if the health maximum goes up the script will still fill it.
Now some people will just cram a large value in the address, but I have even seen this done on a 2 byte address with a 3 byte number being used, so there was numeric overflow that would corrupt the game saves (and that's no good, plus if it overflows to say the health maximum then that would get set very low and that is the opposite of what I am looking for, at least with this hack).
So let's work on that script again.
Step 4[edit]
And let's test the script (remember to save your tables before injections just in case, even saving be for AOB scans is a good idea to me).
But mine didn't work and if you just copied mine then I bet yours didn't work too.
Debugging your script[edit]
Now I found my type-o but lets debug our script to find the problem. So lets look at that instruction when injecting to see that it is, in fact, injecting to the right spot.
Now re-enable the script while looking at the memory view form.
Then let's follow that to our assembled memory for the health hack. So right click the instruction line and select Follow.
Then on the first line "cmp [ptrCoordBase],ebx" let's see what's going on, so right click and select Find out what addresses this instruction accesses, and go back to the game and get hit again to test.
Now since we are looking at a base address let's view it in hexadecimal format, so right click the debugger form and select Show as hexadecimal.
Now let's check the registry so in the debugger form right click the address and select Show register states.
So I first check EDX and see that the address is wrong, but I see that EBX is the right address and then see that I used the wrong registry, so lets disable the script and then make the correction.
n_code: cmp [ptrCoordBase],ebx // here I typed the right one jne @f push eax mov eax,[edx+348] // wrong one used here mov [edx+344],eax // wrong one used here again pop eax o_code: cmp dword ptr [ebx+00000344],00
Now, having written to an unknown address or addresses, I will be closing the game to keep from screwing up the game or hack testing (I will close it with task manager or the form close button if in windowed mode, knowing that it doesn't save then, to insure nothing gets saved). And because Cheat Engine can't account for my mistakes, I will also be restarting Cheat Engine to make sure I didn't mess it up too.
So let's restart (the game and Cheat Engine) and correct the script re-inject and retest the script.
So here is my corrected script.
So let's retest that script, don't just test to see if you have infinite health also test if the combatants can still be killed.
So I will kill a combatant (try both standard sword kill and an animated stealth kill) and then stand in the middle of a group for a minute to see how this works out.
And I now have a working health hack.
This was after about 20 hits, now we could look for a better spot so our meter stays filled, but I am fine with it so moving on.
Tip: The best place to insure that the display value and the real value match is in a write instruction.
One hit kills[edit]
And sense this instruction handles all actors health let's just set this up as a primary script with 2 flags one for the player and the second for the combatants.
So here is the new script.
Now add the flags to the address list right click the player health flag and select Set/Change dropdown selection options.
And set it like this.
Then right click the combatant health flag and select Set/Change dropdown selection options.
And set it like this.
We could also add a toggle script for the flags:
//// //// ------------------------------ ENABLE ------------------------------ [ENABLE] flgPlayerHealthHook: db 01 //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] flgPlayerHealthHook: db 00
//// //// ------------------------------ ENABLE ------------------------------ [ENABLE] flgCombatantHealthHook: db 01 //// //// ------------------------------ DISABLE ------------------------------ [DISABLE] flgCombatantHealthHook: db 00
Now time to test. So let's inject the new script, and set a flag to test it out.
Let's test the infinite health first, then one hit kills, then disable infinite health with one hit kills enabled to make sure we are not subject to one hit kills.
So It looks like the infinite health works but one hit kills is not working, so let's have look at the other death check instruction.
But in checking what addresses that instruction accesses I find only the player's health, so what we want is instruction that writes to actor health, this is where I had to just try different ones until I found the right area, test what addresses the instruction accesses to find a write that has all health run thought it.
This is the one hit kills script that ended up working.
And this is the cleaned up infinite health script.
So I will be doing a little more testing (the best kind of testing), to insure it is working be for moving one. I also like to test going though load screens to insure no crashes for new scripts that write values.
And, with every thing working, on to the next hack.