 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Profound_Darkness Newbie cheater
Reputation: 0
Joined: 21 May 2015 Posts: 23
|
Posted: Fri Jun 05, 2020 10:15 pm Post subject: Unexpected behavior trying to use a symbol in an offset |
|
|
[edit]
Updated to CE 7.1 (thankful for _MissingSetup.rar since the exe installer crashes).
The info below is still true.
[/edit]
I've encountered something a bit unexpected. The offset of a pointer in a CE table entry is using the address of a symbol rather than the value found at that address. I don't know if this is intended behavior or not. I thought I should share just in case it's unintentional.
For example lets say that I have 2 symbols, ptrStats and vOffsetStats.
ptrStats is in allocated memory at 03D20011. The value in this address is 0F27281C.
vOffsetStats is in allocated memory at 03D2008. The value in this address is 00000244.
I have a value in the cheat table with the pointer field filled with "ptrStats" which correctly gets directed to 0F27281C. In the first offset with "vOffsetStats" typed in the + is 3D2008 rather than the expected +244. This puts the final value at 12F9281C (outside of anyone's memory space) rather than the expected 0F272A60.
I've worked around this by simply copying the register's contents twice, once before and once after the instruction in the original code that applies the offset.
Using Cheat Engine version 7.0
Some of the AutoAssembler code:
| Code: |
aobGetStats:
jmp memGetStats
nop
rethere:
memGetStats:
mov [ptrStats], esi
bakGetStats:
readmem(aobGetStats, 2)
vOffsetStats:
readmem(aobGetStats+2, 4)
// copied instruction: 81 C6 440200000 - add esi,00000244
jmp rethere
ptrStats:
dd 0
|
An image of the dialog:
[img]https://ibb.co/s9yk27L[/img] |
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 155
Joined: 06 Jul 2014 Posts: 4764
|
Posted: Fri Jun 05, 2020 10:58 pm Post subject: |
|
|
Intentional.
The base address uses the address of the symbol as well. The -> means "value stored at this address". Try putting vOffsetStats in square brackets to get the value at that address. | Profound_Darkness wrote: | | I've worked around this by simply copying the register's contents twice, once before and once after the instruction in the original code that applies the offset. | Not sure what you mean by this.
Pedantic warning in that AA code snippet:
readmem in general shouldn't be used for code that's going to be executed. It's fine in this case, but the behaviour of some instructions depends on the address those instructions are located at (e.g. rip-relative addressing). Simply copying the bytes from one address to another isn't guaranteed to give you the same instruction in general.
Use reassemble to get equivalent behaviour (for executing original code), use readmem to get equivalent bytes (for backing up & restoring original code). _________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
Profound_Darkness Newbie cheater
Reputation: 0
Joined: 21 May 2015 Posts: 23
|
Posted: Sat Jun 06, 2020 6:53 pm Post subject: |
|
|
| ParkourPenguin wrote: |
Intentional.
The base address uses the address of the symbol as well. The -> means "value stored at this address". Try putting vOffsetStats in square brackets to get the value at that address.
|
<foreheadslap> I forgot about square brackets... Thanks for the reminder, worked.
| ParkourPenguin wrote: |
Not sure what you mean by this.
|
Note the added ptrStatsShifted item.
| Code: |
aobGetStats:
jmp memGetStats
nop
rethere:
memGetStats:
mov [ptrStats], esi
bakGetStats:
readmem(aobGetStats, 6)
mov [ptrStatsShifted], esi
jmp rethere
ptrStats:
dd 0
ptrStatsShifted:
dd 0
|
| ParkourPenguin wrote: |
Pedantic warning in that AA code snippet:
readmem in general shouldn't be used for code that's going to be executed.... |
Yep. This is even more important in my experience with x64 code. For one you need a full 14 contiguous bytes to pull the sort of jumps I'm used to doing in x32. To make it even harder x64 does WAY more relative operands for instructions than x32 tends to.
For myself I cut my teeth with CE using something like the following psuedo code:
| Code: |
[Enable]
...
aobInsertion:
jmp memAllocated
<0 or more nops>
rethere:
memAllocated:
<some of my code>
db <bunch of original code bytes>
jmp rethere
...
[Disable]
aobInsertion:
db <bunch of original code bytes>
...
|
Memcopy is so much easier to deal with in situations like that. Yes it can be a bit of a bad habit but with responsible use it's just so quick and I usually have AOB or asserts to prevent enable if something changes too much.
Memcopy is also handy for me where there is an absolute address operand which changes from session to session. So when I initially create the AA, using my jump over an instruction like "mov eax,[0ACFA280]" but then the next time I run the game the instruction is now "mov eax,[0A577D7C]" Still absolute but my original AA wouldn't work then. In situations like that memcopy is a one line ideal for me. Especially if that instruction example destroys what I wanted, the state of eax beforehand and I don't care one bit about the instruction after, just that it works after my code. Also situations where my insertion includes an instruction like "mov esi,[ebp-4]" where that "-4" can change between sessions. Not often but I seem to play in jit code a lot so I do see it. Really wild cases are where the instruction doesn't change (so same length of bytes) but the registers involved in the operands do... ugh.
Where things are thick with relative addresses and jumps I'll turn to Lua to relocate a call or if I'm lucky I'll borrow the space in the called function's preamble for my jump. Preambles aren't generally very dynamic (or big) so when that pops up running memcopied code it is again.
I'm often quite thankful for the pause button as well as follow/back in memory/disassembler view. Great if attaching a debugger is problematic as I can pause the game, enable and inspect my final ASM one last time to make sure I didn't screw up badly, then let it go once I'm confident. Also handy for catching relative operands that I missed and putting it all back (with disable) before a crash. |
|
| Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 155
Joined: 06 Jul 2014 Posts: 4764
|
Posted: Sat Jun 06, 2020 8:32 pm Post subject: |
|
|
| Profound_Darkness wrote: | | Memcopy is also handy for me where there is an absolute address operand which changes from session to session. | For backing up and restoring the injection point, that's fine; for executing instructions at the injection point, that's the exact wrong situation to use readmem (memcopy).
In x86, the bytes an instruction like "mov eax,[0ACFA280]" is comprised of won't change when it's located at a different address. In x64 it can change, because the concept of absolute addressing is replaced with RIP-relative addressing (at least outside the +-2GB of memory around 0). Copying the bytes via readmem (memcpy) won't give you the same instruction, and the game could crash because of that. Use reassemble instead:
| Code: | // original injection point: "add [address],64"
[ENABLE]
aobscan(foo,83 05 ?? ?? ?? ?? 64)
alloc(newmem,1024,foo)
alloc(originalBytes,7,foo)
label(return)
registersymbol(foo)
originalBytes:
readmem(foo,7)
newmem:
reassemble(foo)
// code...
jmp return
foo:
jmp newmem
nop
nop
return:
//...
[DISABLE]
foo:
readmem(originalBytes,7)
dealloc(originalBytes)
dealloc(newmem)
unregistersymbol(foo) | (you shouldn't use reassemble to backup / restore the injection point because some instructions don't have unique byte representations) _________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
| Back to top |
|
 |
Profound_Darkness Newbie cheater
Reputation: 0
Joined: 21 May 2015 Posts: 23
|
Posted: Sat Jun 06, 2020 10:32 pm Post subject: |
|
|
I'll give reassemble a try next time I'm messing with relative addresses at an insertion point. I've also bookmarked your example.
If worried about my tables promoting bad practices... I rarely publish. |
|
| Back to top |
|
 |
|
|
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
|
|