Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 


Updating AoB after game update

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
GoreGrindGeek
Newbie cheater
Reputation: 0

Joined: 30 Apr 2017
Posts: 11

PostPosted: Wed Oct 11, 2017 3:36 am    Post subject: Updating AoB after game update Reply with quote

G'day, everyone.

I have a Cheat Engine table that used to work but stopped working after a game has been updated. It looks for an AoB to find a pointer to the player structure and then fill out the rest of the pointers and values (health, money, etc.). I'm guessing it no longer works because the AoB has changed (the script entry can no longer be activated, if the AoB were present but the player structure itself changed or had values appended to it, the entry would still be working, just present invalid results).
How can I find the new AoB? I have no idea how the original author located it, and none of my googling has provided me with any new insights. I would probably write such scripts myself if I knew how, but even after completing all tutorials in different ways I am still not feeling familiar enough with Cheat Engine and get absolutely plastered by problems like this one.
Anyway, enough rambling. Could you please help me? Being nudged in the right direction would be more than enough, as I haven't been able to find any solutions through Google.

Thank you in advance for your help. I will provide examples if needed.

P.S. Another entry is no longer working, but it's even more complicated and I am not even hoping to fix it. It was previously affecting the results of a randomised encounter within the game in favour of the player. It's AoB-based as well. Once more: no idea how the table author managed to produce something like that.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Wed Oct 11, 2017 8:58 am    Post subject: Reply with quote

If the script included the original code (usually near the bottom):
Code:
[ENABLE]
...

[DISABLE]
...

{
// ORIGINAL CODE - INJECTION POINT: ...

address: bytes      - disassembly
...
}

Then it's usually not too hard to find the original injection point. If the script didn't include that information, you should still see what code was there in the [disable] section, but that's usually only a few instructions.

The thing that caused the AoB signature to change was probably something small, like an offset or a register was changed. Start scanning for bytes around the injection point and gradually get more generic with the search pattern until something is found. Replace offsets with wildcards first, then start removing operand information, check different instruction sizes (an offset moving from +7C to +80 would require a disp32 instead of a disp8), and finally reorder instructions if you really want to.

For example:
Code:
8B 56 74   - mov edx,[esi+74]

8B 56 ??    -- offset changed
8B ?? ??    -- registers changed
8B ?? ?? ?? ?? ??   -- offset changed to more than +7F

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
GoreGrindGeek
Newbie cheater
Reputation: 0

Joined: 30 Apr 2017
Posts: 11

PostPosted: Wed Oct 11, 2017 4:32 pm    Post subject: Reply with quote

Hello, good sir ParkourPenguin, it's good to see you again.

ParkourPenguin wrote:
If the script included the original code (usually near the bottom)
It did, and I have tried looking for that code in the memory viewer.

ParkourPenguin wrote:
The thing that caused the AoB signature to change was probably something small, like an offset or a register was changed.
That's a good point. I've tried substituting the register name with asterisks (because opcode search supports wildcards), but I didn't think the offset could change, so I didn't check it. Running a search in memory viewer seems generally ineffective, as it always returns the first result only, or so it appeared to me.

ParkourPenguin wrote:
Start scanning for bytes around the injection point and gradually get more generic with the search pattern until something is found. Replace offsets with wildcards first, then start removing operand information, check different instruction sizes (an offset moving from +7C to +80 would require a disp32 instead of a disp8), and finally reorder instructions if you really want to.
I haven't thought of that at all! Thank you! I'm still not particularly familiar with assembly, so I wouldn't be able to translate offsets to instruction changes like you did, but I'll try what I can first.

And, once again, thank you for supporting your post with some good examples: I find them very helpful.

Update 0: scanning returns a lot of results, but they all seem to be referencing call instructions, whereas the initial injection point was a cmp instruction. If I were to search for the initial byte only plus some wildcards, I'd get hundreds of results... And assemblyscan is extremely slow, but I hope it'll return something when it finishes.

Update 1: checked hundreds of results for different registers and offsets. Nada. Seems like I will have to find the health value, attach a debugger to it and look for which register holds the player data (previous script simply copied the value of a register into a variable from a cmp instruction). In other words, it looks (to me) like the script is unupdatable and needs to be replaced with a new one.

Update 2: attaching debugger crashes the game. I have no more ideas.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Thu Oct 12, 2017 8:58 am    Post subject: Reply with quote

GoreGrindGeek wrote:
If I were to search for the initial byte only plus some wildcards, I'd get hundreds of results...

Did you include multiple instructions in the AoB signature? Did you only scan through non-writable, executable memory (and mark CoW grey)?
If you post the original bytes around the injection point, I can replace the correct bytes with wildcards.

GoreGrindGeek wrote:
attaching debugger crashes the game.

You could try the VEH debugger or the kernelmode debugger. Edit -> Settings -> Debugger Options.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
GoreGrindGeek
Newbie cheater
Reputation: 0

Joined: 30 Apr 2017
Posts: 11

PostPosted: Fri Oct 13, 2017 4:33 am    Post subject: Reply with quote

ParkourPenguin wrote:
Did you include multiple instructions in the AoB signature?
Yes. I have also searched for assembly code (Memory view -> Search -> Find assembly code).
ParkourPenguin wrote:
Did you only scan through non-writable, executable memory (and mark CoW grey)?
Yes, it was suggested in one of the Youtube tutorials I've watched. This is the configuration I had:
/* had to remove image, because I can't post URLs yet, but basically I had a dot in squares for "Writable" and "Executable" and nothing in "CopyOnWrite" */
ParkourPenguin wrote:
If you post the original bytes around the injection point, I can replace the correct bytes with wildcards.
Initial AoB:
Code:
aobscanmodule(player,game.exe,83 B9 ** ** ** ** 00 ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** ** 8B C7 25 01 00 00 80 79 05)
Original code from the script file (substituted .exe name to conceal the game I'm trying to "hack"):
Code:
// ORIGINAL CODE - INJECTION POINT: "game.exe"+2560F5
"game.exe"+2560D1: 2B 86 EC 9F 00 00        -  sub eax,[esi+00009FEC]
"game.exe"+2560D7: C1 F8 02                 -  sar eax,02
"game.exe"+2560DA: 39 44 24 24              -  cmp [esp+24],eax
"game.exe"+2560DE: 8B 86 EC 9F 00 00        -  mov eax,[esi+00009FEC]
"game.exe"+2560E4: 73 08                    -  jae game.exe+2560EE
"game.exe"+2560E6: 03 44 24 40              -  add eax,[esp+40]
"game.exe"+2560EA: 03 44 24 34              -  add eax,[esp+34]
"game.exe"+2560EE: 8B 08                    -  mov ecx,[eax]
"game.exe"+2560F0: 8B 74 24 10              -  mov esi,[esp+10]
"game.exe"+2560F4: 4E                       -  dec esi
// ---------- INJECTING HERE ----------
"game.exe"+2560F5: 83 B9 18 1B 00 00 00     -  cmp dword ptr [ecx+00001B18],00
// ---------- DONE INJECTING  ----------
"game.exe"+2560FC: 89 4C 24 1C              -  mov [esp+1C],ecx
"game.exe"+256100: 89 74 24 2C              -  mov [esp+2C],esi
"game.exe"+256104: C7 44 24 18 00 00 00 00  -  mov [esp+18],00000000
"game.exe"+25610C: 7E 5F                    -  jle game.exe+25616D
"game.exe"+25610E: 8B 7C 24 18              -  mov edi,[esp+18]
"game.exe"+256112: 83 C2 EC                 -  add edx,-14
"game.exe"+256115: 8B C7                    -  mov eax,edi
"game.exe"+256117: 25 01 00 00 80           -  and eax,80000001
"game.exe"+25611C: 79 05                    -  jns game.exe+256123
"game.exe"+25611E: 48                       -  dec eax
I'm assuming the original author found an instruction that compares character health against zero and captured the pointer to the player structure from health minus offset.
ParkourPenguin wrote:
You could try the VEH debugger or the kernelmode debugger. Edit -> Settings -> Debugger Options.
This seems to be a common problem with Steam games, and I've noticed this suggestion in another thread, but all those options are greyed out for some reason.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Fri Oct 13, 2017 9:17 am    Post subject: Reply with quote

GoreGrindGeek wrote:
I had a dot in squares for "Writable" and "Executable" and nothing in "CopyOnWrite"
If the checkbox is filled, that means it's grey, and CE will check both possibilities of that particular option. If it's checked, CE will only look through memory that conforms to that specification, and the opposite is true for if it's blank. If you want to scan through executable memory, make sure the "Executable" checkbox is checked (i.e. neither blank nor filled), and set the other ones to whatever you want. I'd uncheck the writable checkbox and set CoW to grey, but you can set them both to grey if you want.
GoreGrindGeek wrote:
Original code...
If the code was located in a module, it probably still is. Restrict your search range to the module (i.e. set the start and stop address to the beginning and end of the module). If you don't know how to do get that information, run this Lua code:
Code:
local moduleName = 'game.exe'   -- replace this
local start = getAddress(moduleName)
print(('start:\t%08X\r\nstop:\t%08X'):format(start, start + getModuleSize(moduleName)))

You could try scanning for something like this:
Code:
83 B? ?? ?? ?? 00 00 89 ?? ?? ?? 89 ?? ?? ?? C7
If it doesn't work, try removing some bytes (like the C7 at the end), or look at a different sequence of instructions.
GoreGrindGeek wrote:
all those options are greyed out for some reason.
If you've already tried to attach the debugger to a process, those radio buttons will be disabled. Restart CE and set the debugger method then.
_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
GoreGrindGeek
Newbie cheater
Reputation: 0

Joined: 30 Apr 2017
Posts: 11

PostPosted: Sun Oct 15, 2017 12:38 am    Post subject: Reply with quote

ParkourPenguin wrote:
If the checkbox is filled, that means it's grey, and CE will check both possibilities of that particular option. If it's checked, CE will only look through memory that conforms to that specification, and the opposite is true for if it's blank. If you want to scan through executable memory, make sure the "Executable" checkbox is checked (i.e. neither blank nor filled), and set the other ones to whatever you want. I'd uncheck the writable checkbox and set CoW to grey, but you can set them both to grey if you want.
Thank you! I didn't know. And was, apparently, not intelligent enough to hover over the checkboxes for tooltips.

ParkourPenguin wrote:
If the code was located in a module, it probably still is.
What exactly do you mean by "module" in this context?

ParkourPenguin wrote:
If you don't know how to do get that information, run this Lua code...
Thank you, this is excellent! Finally I didn't have to wait for ages to get results, and the results were narrowed down to what I wanted to look through.

ParkourPenguin wrote:
You could try scanning for something like this...
Tried. The only returns are call instructions, not cmp... Oh, and it's not health, apparently. The offset for health was and is +24C0, so +1B18 from the code is a different kind of fish.
If I knew what +1B18 from the original code was, it'd be much easier to just rewrite the script (perform an injection somewhere else where the same +1B18 offset is accessed). But I don't know what to look for.
I ran a search for "cmp dword ptr [???+0000????],00" as well (for the memory address range returned by Lua), but that yielded no results at all.
I guess I could try looking for +1B18 as well.

ParkourPenguin wrote:
If you've already tried to attach the debugger to a process, those radio buttons will be disabled. Restart CE and set the debugger method then.
Thank you. This and VEH helped. Although I don't have a clue as to what exactly VEH and kernelmode from the options are.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sun Oct 15, 2017 9:08 am    Post subject: Reply with quote

GoreGrindGeek wrote:
What exactly do you mean by "module" in this context?
Executable images: .exe files or .dll files.

GoreGrindGeek wrote:
Tried. The only returns are call instructions, not cmp...
The first byte of any call instruction is different from the first byte of any cmp instruction. Are you right clicking the results in the found list (the left listview in the main window) and selecting "Disassemble this memory region"?

GoreGrindGeek wrote:
Thank you. This and VEH helped. Although I don't have a clue as to what exactly VEH and kernelmode from the options are.
They're different methods by which CE handles breakpoints. The windows debugger is the "official" way of doing things, but it's easily detected. If the windows debugger doesn't work, use VEH. If VEH doesn't work, use the kernelmode debugger. If that doesn't work, you probably shouldn't be trying to debug that software.
_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
GoreGrindGeek
Newbie cheater
Reputation: 0

Joined: 30 Apr 2017
Posts: 11

PostPosted: Sun Oct 15, 2017 8:03 pm    Post subject: Reply with quote

ParkourPenguin wrote:
The first byte of any call instruction is different from the first byte of any cmp instruction. Are you right clicking the results in the found list (the left listview in the main window) and selecting "Disassemble this memory region"?
My mistake. I was selecting "Browse this memory region" instead.
I've searched for every pattern I could think of again, up to "83 B? ?? ?? ?? 00 00", but I couldn't find any similar patches of code. But at least I understand now what I'm doing and why you've suggested what you've suggested, that's a huge improvement. I think I've also become better at translating bytes to instructions and offsets. Thank you!

If I can find player health and I know its offset from the root of the player structure, is there a way for me to stop code execution if one of the registers contains the address to the player structure? That would help me find a new injection point, because I have no idea what the previous one was and how the original author located it.
I'd like to know if there are any generalised ways of finding injection points as well if that's not too much to ask.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 138

Joined: 06 Jul 2014
Posts: 4275

PostPosted: Sun Oct 15, 2017 8:51 pm    Post subject: Reply with quote

GoreGrindGeek wrote:
If I can find player health and I know its offset from the root of the player structure, is there a way for me to stop code execution if one of the registers contains the address to the player structure?

If you right click the memory record in the address list and select "Find out what instructions access this address", you should see instructions that have something like "[reg+offset]". The register in the square brackets is usually the base address of the structure and the offset should be how far away the value is located from the start of the structure.

If the AA script is only getting where the structure is at and it isn't doing anything with the value itself, then you can inject at any value in the structure to get the base address. The "injection copies" section of this topic has information about doing this.

GoreGrindGeek wrote:
I'd like to know if there are any generalised ways of finding injection points as well if that's not too much to ask.

Most of the time, "Find out what instructions access this address" will lead to a suitable injection point. There are a couple problems that can come with this: the instruction may also access other addresses (sometimes easy to deal with), and the instruction may not run as often as desired (typically hard to deal with). If one of these happens, it's usually best to find a different injection point. Again, if you're just looking to find the base address of a structure, you can look at any instruction that accesses any address in that structure. You're bound to find a good injection point eventually.

_________________
I don't know where I'm going, but I'll figure it out when I get there.
Back to top
View user's profile Send private message
GoreGrindGeek
Newbie cheater
Reputation: 0

Joined: 30 Apr 2017
Posts: 11

PostPosted: Tue Oct 17, 2017 7:44 pm    Post subject: Reply with quote

ParkourPenguin wrote:
If the AA script is only getting where the structure is at and it isn't doing anything with the value itself, then you can inject at any value in the structure to get the base address. The "injection copies" section of this topic has information about doing this.
Thank you. I will read this tutorial once more then.

ParkourPenguin wrote:
Most of the time, "Find out what instructions access this address" will lead to a suitable injection point. There are a couple problems that can come with this: the instruction may also access other addresses (sometimes easy to deal with), and the instruction may not run as often as desired (typically hard to deal with). If one of these happens, it's usually best to find a different injection point. Again, if you're just looking to find the base address of a structure, you can look at any instruction that accesses any address in that structure. You're bound to find a good injection point eventually.
That answers all the questions I've had in this topic.

Thank you so much! You've been extremely helpful, and I've learnt a lot again. If I fail to achieve what I want, I will now have information to return to and read through.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

 
Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum


Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites