Performing AOBScan automatically when address changes

Memory scanning, code injection, debugger internals and other gamemodding related discussion
Post Reply
User avatar
EyeOfTheMind86
Expert Cheater
Expert Cheater
Posts: 50
Joined: Sun Mar 12, 2017 5:39 pm
Reputation: 14

Performing AOBScan automatically when address changes

Post by EyeOfTheMind86 »

Good evening, I'm a long time browser of this website, even though I don't post much. Thank you very much for everything you're doing here, I'm also learning to create my own cheats thanks to the information I gather here.
Anyway, I have an issue concerning a script I'm trying to create.
The game is Soulstice, there is already a cheat table here but I'm making my own from scratch.
My problem is that I found my AOB for the main character's health, however the retrieved address changes everytime I reload a checkpoint or I enter a different room/location, requiring me to run the AOBscan again to update the address by disabling and re-enabling the script manually.

See below for my script:

Code: Select all

[ENABLE]

{$lua}
local results = assert(AOBScan("01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 B4 41 01 00 00 00 CD CC 4C 3E CD CC 4C 3D 00 00 48 43 00 00 40 40"), 'no results found')
local address = results[0]
results.destroy()
return string.format('define(_health,%s)', address)
{$asm}

registersymbol(_health)
 
[DISABLE]

unregistersymbol(_health)
The health value is obtained by adding +7C to the address found by the AOB.

My question is: Is there a way to make this process automatic?
I tried using the register obtained by the opcode required to update the health value, but this opcode is shared across everything (main character, enemies, and also breakable objects) and using the commonality scan didn't allow me to find the most suitable register offset and value to use for a conditional jump.
This is the opcode anyway: F3 0F11 41 0C - movss [rcx+0C],xmm0

Is there someone with more knowledge of LUA and assembly who can point me to the right direction? My skillset is very limited.

User avatar
Rixef
Cheater
Cheater
Posts: 27
Joined: Wed May 10, 2023 7:43 am
Reputation: 21

Re: Performing AOBScan automatically when address changes

Post by Rixef »

EyeOfTheMind86 wrote:
Wed May 24, 2023 9:44 pm
Good evening, I'm a long time browser of this website, even though I don't post much. Thank you very much for everything you're doing here, I'm also learning to create my own cheats thanks to the information I gather here.
Anyway, I have an issue concerning a script I'm trying to create.
The game is Soulstice, there is already a cheat table here but I'm making my own from scratch.
My problem is that I found my AOB for the main character's health, however the retrieved address changes everytime I reload a checkpoint or I enter a different room/location, requiring me to run the AOBscan again to update the address by disabling and re-enabling the script manually.

See below for my script:

Code: Select all

[ENABLE]

{$lua}
local results = assert(AOBScan("01 00 00 00 03 00 00 00 00 00 00 00 00 00 00 00 05 00 00 00 00 00 B4 41 01 00 00 00 CD CC 4C 3E CD CC 4C 3D 00 00 48 43 00 00 40 40"), 'no results found')
local address = results[0]
results.destroy()
return string.format('define(_health,%s)', address)
{$asm}

registersymbol(_health)
 
[DISABLE]

unregistersymbol(_health)
The health value is obtained by adding +7C to the address found by the AOB.

My question is: Is there a way to make this process automatic?
I tried using the register obtained by the opcode required to update the health value, but this opcode is shared across everything (main character, enemies, and also breakable objects) and using the commonality scan didn't allow me to find the most suitable register offset and value to use for a conditional jump.
This is the opcode anyway: F3 0F11 41 0C - movss [rcx+0C],xmm0

Is there someone with more knowledge of LUA and assembly who can point me to the right direction? My skillset is very limited.
Okay, I'm gonna attempt to explain and teach ya a bit more of an advanced technique to try to extract your desired value from a register. I don't have the game so idk the way it works or what the memory looks like at all so this may prove difficult lol. However, I've done this many times before with various games.

So, you found your health address. You right click on it and find out what writes to/accesses it. You find a good enough instruction that seems to access it through and through as in changing maps, going elsewhere etc; it still looks like the count is going up meaning it's still accessing your health address. It seems to be the golden instruction to hook into. So you click "Show disassembler" and it takes you to the instruction in the Memory Viewer window. You then right click on the instruction and click "Find out what addresses this instruction accesses"....Only to find absolute chaos. The function that the golden instruction resides in, there in the memory, is accessing hundreds if not thousands of other addresses besides just your health. What do?

Making some assumptions; rcx+0C is your health address moving through that register. xmm0 is the health value being put into/updating your health address value.

So we know we need to weed out every other address except the health, 'cause just simply trying to do

Code: Select all

movss [rcx+0C],(float)999999999
Isn't going to cut it 'cause that will change a bunch of other values to 99999999. Which could potentially brick your save file or kill the game on a crucial part. No bueno.

So there's two different ways to go about this.
Method 1
Method 1:
Go to your health address in the hex view portion of the Memory Viewer window and try to find a nearby value that seems to be unique to the structure that your health is in. To make this a bit less of an eye sore open the address in Structure Dissect. This unique value you're looking for could be a NaN value, a string(bonus if it says ✨"Player"✨), a pointer, some weird number that's not found anywhere else in the memory or not many other places, or even a VTable(which is quite possibly what the rcx base is without adding the 0C offset to it, might want to take a look at your (health address - 0C) and see if the value of that address is another address, if so then it's most likely a pointer to a VTable; which could prove very useful as it might be unique to the player and also won't change until the game gets an update or patch)

Once you've found an address you believe is unique to your player structure or the structure that your health is in, then you'll want to
test it without bricking your save file. How do?
In this example I'm going to pretend like rcx is a unique VTable pointer for your character.
Something like so (I never use Lua btw, 'cause I'm bad at it lol so pure Auto Assembler scripting):

Code: Select all

[ENABLE]
aobscanmodule(ExtractHealth, Game.exe, F3 0F11 41 0C) //unique AOB scan for the instruction(ctrl+A,then ctrl+shift+A)
alloc(newmem, $1000, ExtractHealth)
alloc(MyHealth,8) //allocate some memory to store your health address when we extract it from the register
registersymbol(MyHealth) //register your allocated memory so it's easy to access with a symbol name
label(code)
label(return)

MyHealth: //define and initialize your allocated MyHealth space as 0 just to make sure it's clear and ready for use
  dq 0

newmem:
  cmp [rcx],7FF61337      //(pretend 7FF61337 is a unique player VTable address lol, so this would be your health address - 0C)
  jne code                //jump if not equal(jne) to original code, in other words run as normal, so we don't mess with anything
  push rcx                //otherwise if it is equal then we do this stuff starting with pushing rcx onto the stack to save it's value while we temporarily utilize this register
  add rcx,0C             //adding 0C to rcx gets us to the health address
  mov [MyHealth],rcx      //now move rcx which is now our health address into the value of MyHealth
  pop rcx                //pop rcx back off the stack to restore it to it's original state when we pushed it off the stack
  jmp code                //now jump to the original code label below so it can run like normal

code: //original instruction code
  movss [rcx+0C],xmm0
  jmp return
  
ExtractHealth:
  jmp newmem
  nop x?
return:
registersymbol(ExtractHealth)

[DISABLE]
ExtractHealth:
  db F3 0F 11 41 0C //og bytes of instruction here
  
unregistersymbol(ExtractHealth)
unregistersymbol(MyHealth)
dealloc(newmem)
dealloc(MyHealth)

So, now that we've done that, time to test if it extracts the correct address.
To do so; on the main CE window, click "Add Address Manually" and then where you would put an address in the window that pops up put:
[MyHealth]
Just like that, brackets and all. And then click "OK".
Now in the Auto Assembler window, save your script to the cheat table via "File" > "Assign to current cheat table" and then close that window once you confirm that it's on the cheat table.
Now enable that script from the cheat table and see if the value and address are correct that you added with the [MyHealth] address. If so, boom, done-zo. You've successfully extracted the correct address from that crazy instruction. So in that case, you can now modify the script a bit to update your health with a value you want(I'll go into that more if you can't figure it out)
Method 2
Method 2:
This method is a bit more intense but makes you feel smart as hell and proud of yourself in the end lol. Bare with me. It's a lot a reading here.

With this method we're going to see if there's any unique register values being passed through the other registers at the same time as our health address is being accessed. So there's a couple different ways to try this but I won't be making a sub section of method 2 here 'cause that'd be way too much typing lol. So for now we're just gonna do one of them and not even worry about the other one.

With that out a the way, let's get into it. Go to your golden instruction in the Memory Viewer window, select it and either click "Debug" > "Toggle breakpoint" or just hit "F5" on the keyboard. This will probably freeze your game at this point. This is normal, just don't go clicking on the game window once you've done this or that will most likely crash it. So continuing on; your golden instruction should be highlighted at this point and a little side window showing the register states should appear to the right along with some debugging buttons along the top. First you want to watch those register values while clicking the green triangle "Run" button ▶ NOT the far right one that says "Run Til..." just the first one.

The registers should change. Click this a few times and kind of take a mental note of which registers are changing the most and whether they have patterns or not like maybe one of them is counting up like 0000000000000001 and then 0000000000000002 and 0000000000000003....000000000000000A, 000000000000000B, 000000000000000C, etc. each time you click "Run" or just something that seems like it's completely different and unique each time you click the run button.

Now, second part to this after taking some mental notes is; go and copy your health address and then right click your highlighted golden instruction(don't toggle the breakpoint off yet, the game should still be frozen and the instruction highlighted) and then select "Set/Change break condition" And then a little window should popup. In that window type RCX==0xPasteYourHealthAddressHere yes, the RCX needs to be capitalized, there needs to be 2 equal signs, and there needs to be a 0x before your pasted health address or else it won't work.
After you've done that, click "OK". Now once again click the first green triangle "Run" button one time. Now look at the register states again to the right. Check if RCX is minus 12(0C hex) from your health address. If so then so far so good. Click run a few times again and see if any of the registers change. If they don't then take mental note(or be smarter than Rix at 4am and just Windows key+Shift+S and screen snip that little section real quick and paste the snip in Paint or somewhere).

After that you can take the breakpoint off with "F5" and click "Run" and the game should unfreeze now. Don't get too excited yet lol. Put that breakpoint back on. Yes. Hit F5 again. "Rix, what the hell, man..." I know. It gets a bit easier the more you do it. It's time for another round of inspecting and analyzing what's goin' on in those registerrrrs ayooo! 🙌 "No but really, why tf did we take the breakpoint off just to put it right back on?" Because now, it reset the break condition. So now it's no longer following the special little RCX==0xYourHealthAddress break condition and is now back to just breaking on every time that instruction is accessed or accessing. So once again the golden instruction should highlight and the game should be frozen. You're gonna do like before and click the first green "Run" button while paying attention to the register states but this time you're gonna kinda compare them to the ones that you screen snipped of when your health was passed through the registers. If there's even one register that's unique to your health while looking through each of these other ones(like for example maybe you've looked through 50 of them and none of those 50 had the same RDI value as it did with your health, then you can utilize RDI as a unique register in a script to weed out all the others).

Alright! The hard part's out a the way.

In this example I'm going to pretend like RDI is a register with a unique value that is only that value when the health is passed through. We're gonna pretend like RDI is 0000000000001337 when health is passed through and RDI is never that same value with any of the other addresses passed through(making it unique to your health).
Something like so:

Code: Select all

[ENABLE]
aobscanmodule(ExtractHealth, Game.exe, F3 0F11 41 0C) //unique AOB scan for the instruction(ctrl+A,then ctrl+shift+A)
alloc(newmem, $1000, ExtractHealth)
alloc(MyHealth,8) //allocate some memory to store your health address when we extract it from the register
registersymbol(MyHealth) //register your allocated memory so it's easy to access with a symbol name
label(code)
label(return)

MyHealth: //define and initialize your allocated MyHealth space as 0 just to make sure it's clear and ready for use
  dq 0

newmem:
  cmp rdi,1337      //compare RDI to 0000000000001337
  jne code                //jump if not equal(jne) to original code, in other words run as normal, so we don't mess with anything
  push rcx                //otherwise if it is equal then we do this stuff starting with pushing rcx onto the stack to save it's value while we temporarily utilize this register
  add rcx,0C             //adding 0C to rcx gets us to the health address
  mov [MyHealth],rcx      //now move rcx which is now our health address into the value of MyHealth
  pop rcx                //pop rcx back off the stack to restore it to it's original state when we pushed it off the stack
  jmp code                //now jump to the original code label below so it can run like normal

code: //original instruction code
  movss [rcx+0C],xmm0
  jmp return
  
ExtractHealth:
  jmp newmem
  nop x?
return:
registersymbol(ExtractHealth)

[DISABLE]
ExtractHealth:
  db F3 0F 11 41 0C //og bytes of instruction here
  
unregistersymbol(ExtractHealth)
unregistersymbol(MyHealth)
dealloc(newmem)
dealloc(MyHealth)

So, now that we've done that, time to test if it extracts the correct address the same way as before.
To do so again(I'm just copy pasta-ing a bit here from method 1); on the main CE window, click "Add Address Manually" and then where you would put an address in the window that pops up put:
[MyHealth]
Just like that, brackets and all. And then click "OK".
Now in the Auto Assembler window, save your script to the cheat table via "File" > "Assign to current cheat table" and then close that window once you confirm that it's on the cheat table.
Now enable that script from the cheat table and see if the value and address are correct that you added with the [MyHealth] address. If so, boom, done-zo. You've successfully extracted the correct address from that crazy instruction. So in that case, you can now modify the script a bit to update your health with a value you want(I'll go into that more if you can't figure it out)
And powskies. Hopefully one a those methods will have helped you extract your health address from the register. And if so congratulations and pat yourself on the back. It's a bit of a complex task. 👍

User avatar
EyeOfTheMind86
Expert Cheater
Expert Cheater
Posts: 50
Joined: Sun Mar 12, 2017 5:39 pm
Reputation: 14

Re: Performing AOBScan automatically when address changes

Post by EyeOfTheMind86 »

Rixef, thank you very much for your help, you provided me with new useful techniques I wasn't completely familiar with.
Method 1, however, reminds me a lot of the commonality scan where you use a specific register and offset, with its relevant value, to filter when and how run the default instruction. I think the concept is the same.
The structure dissect is kind of an eye sore as well cause everything is green or red but it really makes everything a bit easier.
I still need to try method 2, and I let you know.
By the way, base RCX points to the player, enemy, item,etc. max health. So basically the value displayed is the max health while 0C points to the current health. It makes things easier when you know what is the max health of your character so I just used that for the cmp and it worked.
There is a catch though, even though the script just points and retrieves the player health, everything else doesn't die or gets destroyed, even though their health decreases as expected. If I deactivate the script to bring everything to default, the game still behaves like this until I find, kill or destroy a new different enemy/item.

The full default instruction is the following:

Code: Select all

cmp dword ptr [rcx+70],00
movss [rcx+0C],xmm0
Basically, everytime the script is activated, the address [rcx+70] changes his default value from 00 to 01, and everytime you get hit it rises by 1.
Everything acts normally when that value stays to 0. I guess by adding a new script which operates right before the cmp and force that value to 00 could be a solution as I keep the condition to be true, but why is this happening? Could the push and pop of the script "pollute" the register somehow? I think here I need to know more theory about how register works and are handled by the system.

User avatar
Rixef
Cheater
Cheater
Posts: 27
Joined: Wed May 10, 2023 7:43 am
Reputation: 21

Re: Performing AOBScan automatically when address changes

Post by Rixef »

EyeOfTheMind86 wrote:
Thu May 25, 2023 6:20 pm
Rixef, thank you very much for your help, you provided me with new useful techniques I wasn't completely familiar with.
Method 1, however, reminds me a lot of the commonality scan where you use a specific register and offset, with its relevant value, to filter when and how run the default instruction. I think the concept is the same.
The structure dissect is kind of an eye sore as well cause everything is green or red but it really makes everything a bit easier.
I still need to try method 2, and I let you know.
By the way, base RCX points to the player, enemy, item,etc. max health. So basically the value displayed is the max health while 0C points to the current health. It makes things easier when you know what is the max health of your character so I just used that for the cmp and it worked.
There is a catch though, even though the script just points and retrieves the player health, everything else doesn't die or gets destroyed, even though their health decreases as expected. If I deactivate the script to bring everything to default, the game still behaves like this until I find, kill or destroy a new different enemy/item.

The full default instruction is the following:

Code: Select all

cmp dword ptr [rcx+70],00
movss [rcx+0C],xmm0
Basically, everytime the script is activated, the address [rcx+70] changes his default value from 00 to 01, and everytime you get hit it rises by 1.
Everything acts normally when that value stays to 0. I guess by adding a new script which operates right before the cmp and force that value to 00 could be a solution as I keep the condition to be true, but why is this happening? Could the push and pop of the script "pollute" the register somehow? I think here I need to know more theory about how register works and are handled by the system.
Hey, no problem! Glad I could shed some light on new techniques! Lol whenever I'm tryin' to help someone and I don't know how much they know, I try to make it as detailed as possible so as not to miss anything just in case. So if I'm ever pointing out something that seems obvious to you, that's the reasoning. 👍

Oh okay! Yee, Method 1 is the same concept as that.
To summarize and try to clarify method 1 more; it looks for a unique value near your player health in memory to compare to so we know we're messing with the correct one.
To summarize and try to clarify method 2 more; somewhat similar to method 1 except it more-so disregards the memory around your player health and mostly just pays attention to the register states when health is passed through which can sometimes be in completely different memory regions nowhere near your health. But that doesn't matter as long as it's consistent and unique to when it's dealing with your player health.

Oh okay! So RCX is max health, RCX+ 0C is current health, and RCX + 70 is a flag saying whether an entity is being hit or not at that time. 1 = true if your player or an entity is hit, 0 = false.

So a question; are you going for a Godmode script or a OneHitKill script? Or both? :P

Sounds like you might be going for a combo of both in one script so I'll carry on with that in mind. Okay yeah so in the Memory Viewer window, go one address up to that cmp dword ptr [rcx+70],00 (make sure it's at the top of the Memory Viewer Window and selected) and then hit Ctrl+A and then the scripting window should pop up, so in that window hit Ctrl+Shift+A and then a little window should pop up saying "On what address do you want the jump?" Just hit "OK", that's fine as is. And then another window will pop up and you can give it a name like GodmodeOHK. In the script window this should set it up mostly similar to how it was in the script I put in my previous post.

So your script at the moment should look something like (spoiler tags to save some space lol):
Godmode + OneHitKill

Code: Select all

{
  default info
}
[ENABLE]
aobscanmodule(GodmodeOHK, Game.exe, XX XX XX XX F3 0F11 41 0C) //unique AOB
alloc(newmem, $1000, GodmodeOHK)

label(code)
label(return)

newmem:

code:
  cmp dword ptr [rcx+70],00
  movss [rcx+0C],xmm0

GodmodeOHK:
  jmp newmem
  nop 4
return:
registersymbol(GodmodeOHK)

[DISABLE]
GodmodeOHK:
  db XX XX XX XX F3 0F 11 41 0C

unregistersymbol(GodmodeOHK)
dealloc(newmem)

So using your max health as a unique value to your player we'll edit the script like so (it might be easier on the eyes to read these scripts if you copy paste this into the CE Auto Assembler scripting window since it will color all the text appropriately lol):
Godmode + OneHitKill Revision 1

Code: Select all

{
  default info
}
[ENABLE]
aobscanmodule(GodmodeOHK, Game.exe, XX XX XX XX F3 0F11 41 0C) //unique AOB
alloc(newmem, $1000, GodmodeOHK) //allocate a thousand bytes near GodmodeOHK address(this is our memory space)
define(PlayerMaxHealth, (float)1337) //define your max health here (note; do (float) if your player health is a float or (double) if double, (int), etc.)
label(code)
label(return)
label(OHK) //we're adding an extra label for OneHitKill here

newmem:
  cmp [rcx],PlayerMaxHealth    //compare the value of RCX to PlayerMaxHealth
  jne OHK    //jump if not equal(jne) to OHK
  movss xmm0,[rcx]    //but if it is equal then move our player's max health into xmm0 register
  mov dword ptr [rcx+70],00    //move 00 into our player's hit flag to trick the game into thinking we're not even being hit
  jmp code    //and then jump to the original code with these new set values

OHK:    //this is where we are going to kill enemies
  cmp dword ptr [rcx+70],01    //compare the entity's hit flag to 1 to see if they're even being hit
  jne code    //jump if not equal to the original code. Why? 'cause you said items are also being passed through this function. So this will weed those out from the enemy entities. We don't want to kill the item loots
  movss [rcx+0C],(float)0    //otherwise if it is equal then move (float)0 into the enemies' current health
  jmp return    //and then jump straight over the original code to return 'cause otherwise the original code will just undo what we just did to enemies

code:
  cmp dword ptr [rcx+70],00
  movss [rcx+0C],xmm0
  jmp return

GodmodeOHK:
  jmp newmem
  nop 4
return:
registersymbol(GodmodeOHK)

[DISABLE]
GodmodeOHK:
  db XX XX XX XX F3 0F 11 41 0C

unregistersymbol(GodmodeOHK)
dealloc(newmem)

So it seems we actually don't even need to push and pop things here. But let me try to explain push and pop a bit anyways 'cause they do come in handy very often.

So nope, push and pop do not pollute the register.
When you push a register onto the stack it basically saves it's value and the state it was in at that very moment. It sets it on top of the stack exactly in the state that it's in. So now that we have that saved we can use that register however we want. So long as we restore it's value once we're done with it.

Which brings us to pop. When you pop a register off the stack, you're restoring/loading the exact state it was in when it was pushed onto the stack. So it's as if you'd never even touched it. The game you're messing with is none-the-wiser that you just borrowed it's register used it and then put it back exactly how you found it.

User avatar
EyeOfTheMind86
Expert Cheater
Expert Cheater
Posts: 50
Joined: Sun Mar 12, 2017 5:39 pm
Reputation: 14

Re: Performing AOBScan automatically when address changes

Post by EyeOfTheMind86 »

Thank you very much, I did it. Even though I needed to change a few things to make it work.
For example, considering you can't move stuff directly into xmm0 with movss, I needed to use the push/pop technique you taught me.

Code: Select all

  cmp dword ptr [rcx+70],00
  push eax
  mov eax,(float)0
  movd xmm0,eax
  pop eax
  movss [rcx+0C],xmm0
  jmp return
This was the actual kill code. using mov directly into [rcx+0C] would make the health value to 0 but the kill instruction wouldn't be triggered. By instead following the natural flow of execution, and editing xmm0 directly using the movd command, then it worked.
Movss refers to "scalar single precision scalar floating point", even though I don't fully understand what it means, it's enough for me to understand that "moves" values differently compared to the classic "mov", hence I tried doing this instead and it worked.
I still didn't find necessary to use method 2 for this script but it does come in handy later on I'm sure.
I managed to create both a godmode and a one hit kill which can be used together or separately by adding a custom address for each which can be used to toggle the one you need.

User avatar
Rixef
Cheater
Cheater
Posts: 27
Joined: Wed May 10, 2023 7:43 am
Reputation: 21

Re: Performing AOBScan automatically when address changes

Post by Rixef »

EyeOfTheMind86 wrote:
Sat May 27, 2023 8:46 am
Thank you very much, I did it. Even though I needed to change a few things to make it work.
For example, considering you can't move stuff directly into xmm0 with movss, I needed to use the push/pop technique you taught me.

Code: Select all

  cmp dword ptr [rcx+70],00
  push eax
  mov eax,(float)0
  movd xmm0,eax
  pop eax
  movss [rcx+0C],xmm0
  jmp return
This was the actual kill code. using mov directly into [rcx+0C] would make the health value to 0 but the kill instruction wouldn't be triggered. By instead following the natural flow of execution, and editing xmm0 directly using the movd command, then it worked.
Movss refers to "scalar single precision scalar floating point", even though I don't fully understand what it means, it's enough for me to understand that "moves" values differently compared to the classic "mov", hence I tried doing this instead and it worked.
I still didn't find necessary to use method 2 for this script but it does come in handy later on I'm sure.
I managed to create both a godmode and a one hit kill which can be used together or separately by adding a custom address for each which can be used to toggle the one you need.
Ayyy right on! Glad to hear and no prob! 🙌

Yee whenever you see "floating point", it just means that it's moving a float value which is often times used with xmm registers and movss instructions. Scalar single(the "ss" in "movss") means it's picking a single object out of a structure. For example a Vector3 float would be a struct with 3 float values in it(12 bytes, 'cause each float is 4bytes in size), or a float array and if it's moving a scalar single floating point, then it's picking one a those out a the struct or array to move.

Hell yeah! Nicely done! 👍

AlexS
Expert Cheater
Expert Cheater
Posts: 307
Joined: Sun Apr 08, 2018 3:46 pm
Reputation: 184

Re: Performing AOBScan automatically when address changes

Post by AlexS »

EyeOfTheMind86 wrote:
Sat May 27, 2023 8:46 am
and editing xmm0 directly using the movd command, then it worked
(Google translate)

Note that after this instruction from your code:

Code: Select all

movd xmm0,eax
the contents of the xmm0 register are completely set to zero, including the upper bits. If there was any data in the high bits, then they will be lost.

User avatar
EyeOfTheMind86
Expert Cheater
Expert Cheater
Posts: 50
Joined: Sun Mar 12, 2017 5:39 pm
Reputation: 14

Re: Performing AOBScan automatically when address changes

Post by EyeOfTheMind86 »

Rixef wrote:
Sat May 27, 2023 10:55 am
EyeOfTheMind86 wrote:
Sat May 27, 2023 8:46 am
Thank you very much, I did it. Even though I needed to change a few things to make it work.
For example, considering you can't move stuff directly into xmm0 with movss, I needed to use the push/pop technique you taught me.

Code: Select all

  cmp dword ptr [rcx+70],00
  push eax
  mov eax,(float)0
  movd xmm0,eax
  pop eax
  movss [rcx+0C],xmm0
  jmp return
This was the actual kill code. using mov directly into [rcx+0C] would make the health value to 0 but the kill instruction wouldn't be triggered. By instead following the natural flow of execution, and editing xmm0 directly using the movd command, then it worked.
Movss refers to "scalar single precision scalar floating point", even though I don't fully understand what it means, it's enough for me to understand that "moves" values differently compared to the classic "mov", hence I tried doing this instead and it worked.
I still didn't find necessary to use method 2 for this script but it does come in handy later on I'm sure.
I managed to create both a godmode and a one hit kill which can be used together or separately by adding a custom address for each which can be used to toggle the one you need.
Ayyy right on! Glad to hear and no prob! 🙌

Yee whenever you see "floating point", it just means that it's moving a float value which is often times used with xmm registers and movss instructions. Scalar single(the "ss" in "movss") means it's picking a single object out of a structure. For example a Vector3 float would be a struct with 3 float values in it(12 bytes, 'cause each float is 4bytes in size), or a float array and if it's moving a scalar single floating point, then it's picking one a those out a the struct or array to move.

Hell yeah! Nicely done! 👍
Thank you very much for your help, it really allowed me to write some useful stuff, however I discovered later on that the value I was using for the cmp is shared with other entities so I needed to change it. I found a different one which should be unique, however when I perform a cmp with it the game just freezes and crashes.

Code: Select all

cmp [rcx+388],1
The above seems to be unique for the player, it's set to 1 while everything else is 0. When I use it, however, it just crashes.
I was looking around google to see if others encountered a similar issue but I couldn't find a proper explanation, just that "maybe" it could be "shared code", but I don't understand what exactly mean. Do you have any clue? I never encountered this issue before.
AlexS wrote:
Sat May 27, 2023 10:21 pm
EyeOfTheMind86 wrote:
Sat May 27, 2023 8:46 am
and editing xmm0 directly using the movd command, then it worked
(Google translate)

Note that after this instruction from your code:

Code: Select all

movd xmm0,eax
the contents of the xmm0 register are completely set to zero, including the upper bits. If there was any data in the high bits, then they will be lost.
Hey AlexS, thank you for the hint, however I don't know what kind of "mov" command I can use, as movss doesn't work with eax. Do you have any clue?

User avatar
Rixef
Cheater
Cheater
Posts: 27
Joined: Wed May 10, 2023 7:43 am
Reputation: 21

Re: Performing AOBScan automatically when address changes

Post by Rixef »

EyeOfTheMind86 wrote:
Sat May 27, 2023 11:16 pm
Rixef wrote:
Sat May 27, 2023 10:55 am
EyeOfTheMind86 wrote:
Sat May 27, 2023 8:46 am
...
...
Thank you very much for your help, it really allowed me to write some useful stuff, however I discovered later on that the value I was using for the cmp is shared with other entities so I needed to change it. I found a different one which should be unique, however when I perform a cmp with it the game just freezes and crashes.

Code: Select all

cmp [rcx+388],1
The above seems to be unique for the player, it's set to 1 while everything else is 0. When I use it, however, it just crashes.
I was looking around google to see if others encountered a similar issue but I couldn't find a proper explanation, just that "maybe" it could be "shared code", but I don't understand what exactly mean. Do you have any clue? I never encountered this issue before.
AlexS wrote:
Sat May 27, 2023 10:21 pm
EyeOfTheMind86 wrote:
Sat May 27, 2023 8:46 am
...
...
Hey AlexS, thank you for the hint, however I don't know what kind of "mov" command I can use, as movss doesn't work with eax. Do you have any clue?
Hmm couple things just off the top a my mind; are you using it just like that? Like; cmp [rcx+388],1 ? If so try using it like:

Code: Select all

cmp dword ptr [rcx+388],01
And then also a suggestion; try the very first method I showed you where you just simply do an extraction of that value and not actually using it in a script yet, like just put it into your own allocated value just to double check it's always that value but if you add it to the table and you see it flickering real quick or changing then that means something else is also being passed through that.
Like make a separate script just to test that out with(don't have both scripts enabled since they're both using the same instruction or else one won't find the AOB address)

User avatar
EyeOfTheMind86
Expert Cheater
Expert Cheater
Posts: 50
Joined: Sun Mar 12, 2017 5:39 pm
Reputation: 14

Re: Performing AOBScan automatically when address changes

Post by EyeOfTheMind86 »

Rixef wrote:
Sat May 27, 2023 11:35 pm
EyeOfTheMind86 wrote:
Sat May 27, 2023 11:16 pm
Rixef wrote:
Sat May 27, 2023 10:55 am


...
Thank you very much for your help, it really allowed me to write some useful stuff, however I discovered later on that the value I was using for the cmp is shared with other entities so I needed to change it. I found a different one which should be unique, however when I perform a cmp with it the game just freezes and crashes.

Code: Select all

cmp [rcx+388],1
The above seems to be unique for the player, it's set to 1 while everything else is 0. When I use it, however, it just crashes.
I was looking around google to see if others encountered a similar issue but I couldn't find a proper explanation, just that "maybe" it could be "shared code", but I don't understand what exactly mean. Do you have any clue? I never encountered this issue before.
AlexS wrote:
Sat May 27, 2023 10:21 pm

...
Hey AlexS, thank you for the hint, however I don't know what kind of "mov" command I can use, as movss doesn't work with eax. Do you have any clue?
Hmm couple things just off the top a my mind; are you using it just like that? Like; cmp [rcx+388],1 ? If so try using it like:

Code: Select all

cmp dword ptr [rcx+388],01
And then also a suggestion; try the very first method I showed you where you just simply do an extraction of that value and not actually using it in a script yet, like just put it into your own allocated value just to double check it's always that value but if you add it to the table and you see it flickering real quick or changing then that means something else is also being passed through that.
Like make a separate script just to test that out with(don't have both scripts enabled since they're both using the same instruction or else one won't find the AOB address)
Thank you very much for your reply, it seems that the mistake was me calling the wrong label in the script, maybe it was a copy/paste error. I did try looking at it in the table and it was a fixed value that's why I've chosen it, I'm basically following along with what you taught me.
It worked the way I wrote it but I changed it with the way you suggested and it still works and is more elegant, I guess it is also the better approach. Thank you again.

User avatar
Rixef
Cheater
Cheater
Posts: 27
Joined: Wed May 10, 2023 7:43 am
Reputation: 21

Re: Performing AOBScan automatically when address changes

Post by Rixef »

EyeOfTheMind86 wrote:
Sat May 27, 2023 11:42 pm
Rixef wrote:
Sat May 27, 2023 11:35 pm
EyeOfTheMind86 wrote:
Sat May 27, 2023 11:16 pm


Thank you very much for your help, it really allowed me to write some useful stuff, however I discovered later on that the value I was using for the cmp is shared with other entities so I needed to change it. I found a different one which should be unique, however when I perform a cmp with it the game just freezes and crashes.

Code: Select all

cmp [rcx+388],1
The above seems to be unique for the player, it's set to 1 while everything else is 0. When I use it, however, it just crashes.
I was looking around google to see if others encountered a similar issue but I couldn't find a proper explanation, just that "maybe" it could be "shared code", but I don't understand what exactly mean. Do you have any clue? I never encountered this issue before.



Hey AlexS, thank you for the hint, however I don't know what kind of "mov" command I can use, as movss doesn't work with eax. Do you have any clue?
Hmm couple things just off the top a my mind; are you using it just like that? Like; cmp [rcx+388],1 ? If so try using it like:

Code: Select all

cmp dword ptr [rcx+388],01
And then also a suggestion; try the very first method I showed you where you just simply do an extraction of that value and not actually using it in a script yet, like just put it into your own allocated value just to double check it's always that value but if you add it to the table and you see it flickering real quick or changing then that means something else is also being passed through that.
Like make a separate script just to test that out with(don't have both scripts enabled since they're both using the same instruction or else one won't find the AOB address)
Thank you very much for your reply, it seems that the mistake was me calling the wrong label in the script, maybe it was a copy/paste error. I did try looking at it in the table and it was a fixed value that's why I've chosen it, I'm basically following along with what you taught me.
It worked the way I wrote it but I changed it with the way you suggested and it still works and is more elegant, I guess it is also the better approach. Thank you again.
Oh okay right on! 🙌 No prob at all, happy to help!

AlexS
Expert Cheater
Expert Cheater
Posts: 307
Joined: Sun Apr 08, 2018 3:46 pm
Reputation: 184

Re: Performing AOBScan automatically when address changes

Post by AlexS »

EyeOfTheMind86 wrote:
Sat May 27, 2023 11:16 pm
Do you have any clue?
(Google translate)

It depends on the specific game. In your case, it's possible that setting the high bits of the register to 0 won't cause a crash if the "xmm" register is only used to store the value you want to change. However, in order not to lose data, you need to check the contents of the "xmm" register before changing it.

In your example, in order not to change the contents of the register, you can do, for example, like this:

Code: Select all

mov eax,#100 // put an integer value into the "eax" register (any value, including zero)
cvtsi2ss xmm0,eax // convert the integer value from the "eax" register to a floating point value in the "xmm0" register.
In this case, the upper bits of the "xmm0" register are not set to zero.

Also note that the "movss" command works differently depending on the source.
For example, in this assembler instruction:

Code: Select all

movss xmm0,xmm1
the upper bits of the "xmm0" register are not set to zero.
However, in this assembler instruction:

Code: Select all

movss xmm0,[rax]
the upper bits of the "xmm0" register are set to zero.

User avatar
Rixef
Cheater
Cheater
Posts: 27
Joined: Wed May 10, 2023 7:43 am
Reputation: 21

Re: Performing AOBScan automatically when address changes

Post by Rixef »

Rixef wrote:
Fri May 26, 2023 12:01 am
So nope, push and pop do not pollute the register.
When you push a register onto the stack it basically saves it's value and the state it was in at that very moment. It sets it on top of the stack exactly in the state that it's in. So now that we have that saved we can use that register however we want. So long as we restore it's value once we're done with it.

Which brings us to pop. When you pop a register off the stack, you're restoring/loading the exact state it was in when it was pushed onto the stack. So it's as if you'd never even touched it. The game you're messing with is none-the-wiser that you just borrowed it's register used it and then put it back exactly how you found it.
Not sure if you have notifications on for this thread or not, Eye, but; I've come back to this thread to add some important info about push/pop that AlexS actually reminded me of in one a my cheat table release topics.

So when you're using multiple registers, the order of the push/pop matters. For example:

Code: Select all

//the CORRECT way:
push eax
push ecx
//use the registers
pop ecx
pop eax

//the WRONG way:
push eax
push ecx
//use the registers
pop eax   //<----Here
pop ecx   //<----And here is where it's wrong
You've gotta pop them back off the stack in the reverse order that you push'd them onto the stack. Here's an analogy example on why:
Consider a pile of boxes each labeled after a register; one has eax written on it, another ecx, ebx, edx, so on and so forth.

Let's say you push eax onto a separate, organized, stack of boxes. So you push eax from the pile, onto the stack. You then push eCx onto the same stack you just pushed eAx onto. So now eCx is sitting on top of eAx. So what happens if you pop eAx first back off the stack into the pile? Anything on top of eAx(in this example just eCx) would topple and make a mess. You'd have to follow FILO(First In, Last Out) for it to not make a mess. Occasionally you can magically get away with making this mistake without any consequence like I did lol, my script still worked how I wanted it to, but it's good practice to make sure you follow FILO when push'ing and pop'ing. 👍

User avatar
EyeOfTheMind86
Expert Cheater
Expert Cheater
Posts: 50
Joined: Sun Mar 12, 2017 5:39 pm
Reputation: 14

Re: Performing AOBScan automatically when address changes

Post by EyeOfTheMind86 »

Hey Rixef, thank you for this. I understand the analogy. I can imagine this as having a box inside another box. I need to close the box inside before closing the box containing the first one. however I noticed that certain values are, by default, stored in the addresses as float and if I want to reuse the same value of such addresses in the registers, I can just edit the movss with the address and offset.

Code: Select all

Instead of doing:

push eax
mov eax,(float)800
movd xmm0, eax
pop eax
movss [rcx+0C],xmm0

If I want an "invincibility" code, and I know that [rcx] as the max health value (float 800), I can just do:

movss xmm0,[rcx]
movss [rcx+0C],xmm0
So I avoid adding unnecessary uses of stacks. I wonder, however, if doing "movss [rcx+0C],rcx" is possible and vould lead to the same result. using rcx without the bracket uses the full register and not the address referenced by it, but I wonder if it could work. Didn't try it though, not on the pc at the moment. I don't even know if it is a valid ASR command.

Edit: Actually now that I think about it, it wouldn't work, as "rcx" without brackets would assign the address number as value and not its own value. So would assign something like 7ff678912 blah blah which is the address having the value of (float)800.

Post Reply

Who is online

Users browsing this forum: No registered users