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 


Strange 1 byte too short address in AA asm... ?

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

Joined: 21 May 2015
Posts: 23

PostPosted: Fri Aug 20, 2021 3:31 pm    Post subject: Strange 1 byte too short address in AA asm... ? Reply with quote

So the target process is 64 bit and my intention is to read an address from register into memory to act as a base pointer, pretty bog standard... I'm sure I'm doing something wrong/missing something but I don't quite know what. I don't play with 64 bit targets much. At least things work more or less as expected when I do.

It's acting like AA is writing the address portion 1 byte too short but I'd expect a lot of other cheat tables to be broken if that were generally the case. I haven't played with this for long so I"m hoping someone might be able to point me in an apt direction for further exploration.

This occurs on version 7.1 and 7.3 of CE btw.

What I start with (pre-auto assembler)
Code:

movzx eax,byte ptr [rdx+2C]
ret
int 3
int 3
...
int 3


relevant AA code:
Code:

alloc(memBasePtr, 8)
aobscanmodule(aobBasePtr...)
label(ptrBase)
registersymbol(ptrBase)

aobBasePtr+4:
mov [ptrBase],rdx
ret

memBasePtr:
ptrBase:
dq 0


What I get in memory view after activating the item
Code:

movzx eax,byte ptr [rdx+2C]
mov [C35A0000],rdx
int 3
...
int 3


the newly added code in byte form:
48 89 14 25 00 00 5A C3
a ret being C3 looks interesting.

As a test lets try dropping the ret, obviously nonfunctional code but see what gets assembled.

for mov [ptrBase],rdx I get the bytes: 48 89 14 25 00005ACC
I would expect the address to be 00005A03, in both cases

This strangeness shows up if I do an LEA instruction, ie
lea rax,[ptrBase]
results in the same address being 1 byte shorter than expected, 'eating' a byte from the next instruction. If that's the only change the final byte of the instruction will be CC just like in the MOV instruction.

For now I'm using the following obviously not quite right code to get the address 'proper'

Code:

aobBasePtr+4:
mov [ptrBase],rdx
db 03
ret


results in:
Code:

movzx eax,byte ptr [rdx+2C]
mov [ptrBase],rdx
ret


for completion of demonstration...
Code:

mov [ptrBase],rdx
nop //byte code 90
ret


resulting opcodes:
Code:

movzx eax,byte ptr [rdx+2C]
mov [905A0000],rdx
ret


lea rax,[ptrBase]
becomes
lea rax,[CC5A0000]
bytes
48 8D 04 25 00 00 5A CC
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4717

PostPosted: Fri Aug 20, 2021 4:19 pm    Post subject: Reply with quote

I can't replicate it.

Could you provide a minimal working example with the CE tutorial (Tutorial-x86_64.exe)? If not, at least provide the entire AA script and not just the parts you think are important. (redact the game name- e.g. use "game.exe")

One possible problem I see is that you're not passing the third argument to alloc, which means memBasePtr might not be allocated close enough to the injection point to use RIP-relative addressing.

edit: just noticed your CE is choosing to assemble that with modR/M and SIB bytes 14 25 (Disp32), while mine is assembling it with just 15 (RIP+Disp32). Might be some edge case error in there somewhere. Is that vanilla CE, or did you do something weird (e.g. custom binutils)?

_________________
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
Profound_Darkness
Newbie cheater
Reputation: 0

Joined: 21 May 2015
Posts: 23

PostPosted: Fri Aug 20, 2021 8:46 pm    Post subject: Reply with quote

Before coming back here I tried ... as it happens what you suggested with tutorial (64 bit) and things were compiled as expected. I've got a lot of blindspots, particularly with 64 bit so didn't consider that 3rd argument to alloc.

I didn't do anything odd, to my fuzzy memory, in 7.1 but I compiled 7.3 rather than from pre-built binaries.

my entire AA script including remarks, most of them are to do alternate assembles to see what happens.
Code:

[Enable]
alloc(memBasePtr, 8)
aobscanmodule(aobBasePtr, game.exe, 0F B6 42 2C C3 CC CC CC CC CC CC CC CC CC CC)
//only need first 5 bytes to ID
registersymbol(aobBasePtr)

label(ptrBase)
registersymbol(ptrBase)

aobBasePtr+4:
//lea eax,[ptrBase]
//mov [rax],rdx
//movzx eax,byte ptr[rdx+2C]
mov [ptrBase],rdx
//db 03 // bad fix
ret
//db 0F B6 42 2C C3

memBasePtr:
ptrBase:
dq 0 //64 bit register so pointer might be longer than double

[Disable]
aobBasePtr:
db 0F B6 42 2C C3
db CC CC CC CC CC CC CC CC CC CC

unregistersymbol(aobBasePtr)
unregistersymbol(ptrBase)

dealloc(memBasePtr)


result:
Code:

aobBasePtr - 0FB6 42 2C            - movzx eax,byte ptr [rdx+2C]
game.exe+7DFBB4- 48 89 14 25 00005CC3  - mov [C35C0000],rdx
game.exe+7DFBBC- CC                    - int 3


Now I've tried out the tweak you mentioned, the 3rd argument of alloc. That appears to have helped...

AA
Code:

[Enable]
//alloc(memBasePtr, 8)
aobscanmodule(aobBasePtr, game.exe, 0F B6 42 2C C3 CC CC CC CC CC CC CC CC CC CC)
//only need first 5 bytes to ID
alloc(memBasePtr, 8, aobBasePtr)
registersymbol(aobBasePtr)

label(ptrBase)
registersymbol(ptrBase)

aobBasePtr+4:
//lea eax,[ptrBase]
//mov [rax],rdx
//movzx eax,byte ptr[rdx+2C]
mov [ptrBase],rdx
//db 03 // bad fix
ret
//db 0F B6 42 2C C3

memBasePtr:
ptrBase:
dq 0 //64 bit register so pointer might be longer than double

[Disable]
aobBasePtr:
db 0F B6 42 2C C3
db CC CC CC CC CC CC CC CC CC CC

unregistersymbol(aobBasePtr)
unregistersymbol(ptrBase)

dealloc(memBasePtr)


result:
Code:

aobBasePtr - 0FB6 42 2C            - movzx eax,byte ptr [rdx+2C]
game.exe+7DFBB4- 48 89 15 450481FF     - mov [ptrBase],rdx
game.exe+7DFBBB- C3                    - ret
game.exe+7DFBBC- CC                    - int 3


I'll poke around some in a bit, see if I can force a long distance alloc in the tutorial and see what happens with mov/lea with that.

Thanks.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4717

PostPosted: Fri Aug 20, 2021 9:24 pm    Post subject: Reply with quote

I think there's some buggy edge case behaviour going on with this. What address is the module game.exe loaded at, and what address is ptrBase?
You can execute this in the Lua engine after you enable the script:
Code:
print(('game.exe: %08X'):format(getAddress('game.exe')))
print(('ptrBase: %08X'):format(getAddress('ptrBase')))


Directly addressing a memory location like [ptrBase] is complicated in a 64-bit process because you can't simply use a 64-bit memory displacement (in most cases). Either you can use RIP-relative addressing if the target address is within +-2GB of the next instruction (i.e. modR/M byte 15) or you can use a direct 32-bit displacement from 0 if the address is within the first 4GB of the virtual address space (i.e. modR/M byte 14, SIB byte 25). Maybe there's a scenario where CE thinks it can use RIP-relative addressing but assembles the instruction using a 32-bit displacement anyway (and use 1 more byte than it thought it needed to).

_________________
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
Profound_Darkness
Newbie cheater
Reputation: 0

Joined: 21 May 2015
Posts: 23

PostPosted: Sat Aug 21, 2021 2:04 pm    Post subject: Reply with quote

game.exe: 13F530000
ptrBase: 03440000
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4717

PostPosted: Sat Aug 21, 2021 3:23 pm    Post subject: Reply with quote

I still can't replicate it under similar conditions (CE 7.2). No idea why that's happening for you.

I'm glad using the 3rd parameter to alloc solved this issue.

_________________
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
Profound_Darkness
Newbie cheater
Reputation: 0

Joined: 21 May 2015
Posts: 23

PostPosted: Sat Aug 21, 2021 7:51 pm    Post subject: Reply with quote

So I managed to sit down and try making something similar to the game but for the tutorial and it broke there too.

So here is my AA script. It's got some extra bits to backup/restore some code but I wanted to keep the core test concept clean so two different allocations.
Code:

[Enable]
alloc(memTest, 8, 1000)
label(ptrTest)
registersymbol(ptrTest)
alloc(memBak, 20)
label(bakTest)
registersymbol(bakTest)

define(tutBase, Tutorial-x86_64.exe+2B92)
registersymbol(tutBase)

tutBase:
mov [ptrTest], rdx
nop

memTest:
ptrTest:
dq 0

memBak:
bakTest:
readmem(tutBase, 20)

[Disable]
unregistersymbol(ptrTest)

dealloc(memTest)

tutBase:
readmem(bakTest, 20)

unregistersymbol(bakTest)
unregistersymbol(tutBase)

dealloc(memBak)


the resulting bytes/code:
Code:

tutBase - 48 89 14 25 00001B90  - mov [901B0000],rdx


note the lack of nop in the result... or more accurately that the nop is 'eaten' in the MOV's address.

Tutorial-x86_64.exe: 100000000
ptrTest: 031B0000

Switched to CE 7.2 with the following results:
Code:

tutBase - 48 89 14 25 00000C90  - mov [900C0000],rdx


Tutorial-x86_64.exe: 100000000
ptrTest: 030C0000

The section of the tutorial code I'm altering is quite arbitrary. it just so happens the offset in tutorial was where memory view opened to after attaching to tutorial the first time.

Unless any other ideas pop up for something I should try/report on I'll likely put further poking at this on the back burner. I mean the particular case we're looking at here mostly only came up because I wasn't doing things quite right anyway.

Thanks again.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4717

PostPosted: Sat Aug 21, 2021 9:09 pm    Post subject: Reply with quote

I can replicate it now with that example.

Directly addressing a memory location that may not have been allocated within 2GB (by not using the 3rd alloc parameter) is pretty much undefined behaviour anyway, so I'm not too concerned about this bug either.

You've done plenty- that minimal working example is all that's needed to identify the bug. All that's left is for someone to sift through CE's source and find it. There may be more important things to do in the meantime though.

Thank you for your help.

_________________
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
Dark Byte
Site Admin
Reputation: 471

Joined: 09 May 2003
Posts: 25830
Location: The netherlands

PostPosted: Sun Aug 22, 2021 12:44 am    Post subject: Reply with quote

if you put
Code:

memTest:
ptrTest:
dq 0


before tutbase: it'll work

at the time of assembling it doesn't know what the address will be so it will allocate memory and fill it in when known. But the allocated size is too snall because of this very rare construction that a range above 2gb within the 0 to 2GB range bas a solution thatbis bigger than the others

of course, fixing that may mess up lots if existing scripts, so it's best to go with enforced 3th alloc parameter

_________________
Do not ask me about online cheats. I don't know any and wont help finding them.

Like my help? Join me on Patreon so i can keep helping
Back to top
View user's profile Send private message MSN Messenger
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine 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