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 


Auto Assembly code crashes game (fstp dword pointer)

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
thenic
How do I cheat?
Reputation: 0

Joined: 13 Apr 2022
Posts: 6

PostPosted: Wed Apr 13, 2022 3:45 pm    Post subject: Auto Assembly code crashes game (fstp dword pointer) Reply with quote

Hey there,

I'm trying to hack a kids game (more than 20 years old and offline, just for nostalgic reasons for a friend of mine and myself so no doubt that it's anti-cheat free) and thanks to this forum and the Wiki examples, I thought I wrote a working code.

But I was wrong.
I found a reliable pointer for in-game fuel but I fail at Auto Assembly implementation.

Data type is float (default 25.0, needed 100.0).
My assumption was that it's enough to redirect the original line "fstp dword ptr [esi+00000198]" to a new allocation where float 100 is written to the (cleared) st(0) register and after that I can go on with overriding the value of esi+offset by using the original fstp pointer command. But the game crashes as soon as I enter the area in-game where the value is accessed.

Do you know what may cause the crash on access? Wrong memory sizes? Have absolutely no idea ...

Code:
[ENABLE]
alloc(Patch,512)
label(ReturnLoc)
define(bytes, D9 E9 98010000)
registersymbol(Patch)

Patch:
fstp st(0)
mov dword ptr [esi+00000198],(float)100.0

fstp dword ptr [esi+00000198] // ORIGINAL LINE

jmp ReturnLoc

0040F5C5:
jmp Patch
db bytes // ORIGINAL BYTES

ReturnLoc:


[DISABLE]
dealloc(Patch)

0040F5C5:
fstp dword ptr [esi+00000198]


Thanks in advance,
Nico


Last edited by thenic on Tue Apr 19, 2022 12:30 pm; edited 2 times in total
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4299

PostPosted: Wed Apr 13, 2022 4:47 pm    Post subject: Reply with quote

You're still executing the original code. This means your code injection is popping two values off the FPU stack - one more than the original code at the injection point.

Comment the original code out or remove it entirely.

_________________
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
thenic
How do I cheat?
Reputation: 0

Joined: 13 Apr 2022
Posts: 6

PostPosted: Thu Apr 14, 2022 7:57 am    Post subject: Reply with quote

Alright, thank you ParkourPenguin, I just tried it with

Code:
//fstp dword ptr [esi+00000198] // ORIGINAL LINE


but the game still crashes.

Just for my understanding:

    fstp st(0) | Writes the value of st(0) into st(0) and pops out and removes the value of st(0), so it just clears st(0)?

    mov dword ptr [esi+00000198],(float)100.0 | Writes the value "100.0" directly to the esi offset 00000198 without using the FPU st registers?


Also I will try to write the corresponding 4 byte array to esi+00000198 instead of the (float)100.0, maybe the game expects this.
Float is just my interpretation since it's a useful representation (25.0, 100.0 etc.) and because of the use of FPU/fstp.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4299

PostPosted: Thu Apr 14, 2022 11:26 am    Post subject: Reply with quote

Your understanding is correct.

Does that instruction access other addresses? Right click the original instruction in the disassembler and select "Find out what addresses this instruction accesses". If it does, see step 9 of the CE tutorial.

_________________
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
thenic
How do I cheat?
Reputation: 0

Joined: 13 Apr 2022
Posts: 6

PostPosted: Sat Apr 16, 2022 5:44 am    Post subject: Reply with quote

Thank you very much.

I still stuck at Level 9 (managed to pass until 8 without skip) but I got a working code for my problem now:

I missed the code template feature before but it is great.

Rewriting the esi+198 value isn't helpful apparently but the corresponding ebp+198 later in the code is much better to replace.

Code:

alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)

newmem:
mov [ebp+00000198],(float)100.0

originalcode:
//fld dword ptr [ebp+00000198]

exit:
jmp returnhere

"mullemeck.exe"+11AB0:
jmp newmem
nop
returnhere:


Thanks and have a nice easter weekend,

Nico
Back to top
View user's profile Send private message
thenic
How do I cheat?
Reputation: 0

Joined: 13 Apr 2022
Posts: 6

PostPosted: Tue Apr 19, 2022 12:41 pm    Post subject: Reply with quote

Hello once again, my last goal is to multiply the flight speed by a predefined value (e. g. 2).

I already found the pointer and I found an opcode where I think I can inject the operation without being ignored or crashing the game:

Code:
1002B574 - D8 4B 60  - fmul dword ptr [ebx+60]
1002B577 - D9 5C 24 1C  - fstp dword ptr [esp+1C]
1002B57B - D8 4B 64  - fmul dword ptr [ebx+64] <<
1002B57E - 89 08  - mov [eax],ecx
1002B580 - 8B 4C 24 1C  - mov ecx,[esp+1C]

EAX=00A4D584
EBX=00A4D4C8
ECX=C0CD5F84
EDX=00A4D53C
ESI=0019FB70
EDI=0019FBC8
ESP=0019FB40
EBP=00A4D4C8
EIP=1002B57E


Storing the mulitplier like 2 as st(0) and using "fmul" for multiplying may work in my imagination.
But how can I store (float)2 to the FPU stack and push it to st(0) for making use of the value in the next operation (fmul dword ptr [ebx+64])?

I have to use a new temporary memory address, right?
Or may something like this help:
Code:

    fld    qword [a]   ;load a into st0
    fmul   st0, st0    ;st0 = a * a = a^2


(from Wikibooks > X86_Assembly/Floating_Point)

Code:
newmem:
fld dword [2] // the multiplier
fmul dword ptr [ebx+64]

originalcode:
//fmul dword ptr [ebx+64]
//mov [eax],ecx

crashes the game.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4299

PostPosted: Tue Apr 19, 2022 1:06 pm    Post subject: Reply with quote

thenic wrote:
Code:
fld dword [2]
In this instruction, 2 is an address, not a value. You can't load an arbitrary immediate onto the fpu stack. You have to load it from memory.
For example, if the value you want to multiply is already loaded on the top of the FPU stack, do this:
Code:
...
label(multiplier)

newmem:
  fmul qword ptr[multiplier]
  //...

align 8 CC
multiplier:
  dq (double)2.0

...

_________________
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
thenic
How do I cheat?
Reputation: 0

Joined: 13 Apr 2022
Posts: 6

PostPosted: Wed Apr 20, 2022 12:55 pm    Post subject: Reply with quote

Thanks, yes, already thought that [3] can't reference a value but must name an address to get it's value from.

The game crashes again when I operate this code.
Then I alternated it a bit but it still crashes.

Code:
alloc(newmem,2048)
label(returnhere)
label(originalcode)
label(exit)
label(multiplier)

newmem:
fmul dword ptr [multiplier]

originalcode:
//fld dword ptr [ebx+64]
//mov [eax],ecx

align 8 CC
multiplier:
  dd (float)2

exit:
jmp returnhere

"Cc.dll"+2B57B:
jmp newmem
returnhere:


What does the "align 8 CC" mean? If I understand the CE Auto Assembler:align page correctly, it reserves a memory area for the qword to save?

Also - can I monitor some addresse's values while running the game?
I'd like to know what is ebx+64 but when I take the EBX register address via 'More information' as seen in the tutorial and "add manualy" with offset 64, I only get a value that doesn't change during the game.

Even if I enforce a value change with "mov [ebx+64],(float)5" using AA (which affects the game and my pointer value quite well).
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4299

PostPosted: Wed Apr 20, 2022 1:44 pm    Post subject: Reply with quote

The original code isn't being executed. This leaves the fpu stack imbalanced as the original code was pushing a value on it but you don't. Also that mov instruction was probably doing something important.
Are you sure that fld instruction was part of the original code? From your previous post it looks like it should've been `fmul dword ptr [ebx+64]`.

You're storing data in the middle of code you're trying to execute. This will almost certainly crash the game.

The align pseudoinstruction inserts as many bytes as is necessary to put the next address at a certain alignment.
Code:
align 8 CC
multiplier:
  dq (double)2.0
This makes sure the multiplier label is assigned to an address divisible by 8.
This isn't strictly necessary in most cases: most instructions in x86 / x86-64 architectures that address memory don't require strict alignment, but you should have it anyway. A typical example is when an unaligned value crosses a cache line boundary.

If you insist on only storing a float, you'd only need 4 byte alignment. You still shouldn't store it in the middle of code you're trying to execute: it's data, not code.
Also, if you're not going to use aobscans, use the assert from the full injection template.
Code:
assert(...)

alloc(newmem,2048)
label(returnhere)
label(multiplier)

newmem:
  fmul dword ptr [multiplier]
  mov [eax],ecx
  jmp returnhere

align 8 CC
multiplier:
  dd (float)2

"Cc.dll"+2B57B:
  jmp newmem
returnhere:

Search for "injection copy" if you want to get an address accessed by an instruction.

_________________
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
thenic
How do I cheat?
Reputation: 0

Joined: 13 Apr 2022
Posts: 6

PostPosted: Wed Apr 20, 2022 3:04 pm    Post subject: Reply with quote

Thank your for your patience, much appreciated. It's a steep learning curve and huge respect for everyone who has (that much of) a clue of assembler code. Assembler was always sth like "the supreme power" of computer programming for me.

Oh I get it, an unaligned value may get split into two cache lines (if it's coincidentally at "the end" of the first) and this should be avoided.

You mean storing the multiplier using an operation during the jump isn't clean and it's better to store it before and just reference to it when the specific opcode (that I need/want to manipulate) gets executed? This sounds reasonable to me.

Okay and injection copy looks like I have to mov the base address ([ebx]) right before it gets used/written by the code into a newly allocated memory address that I can monitor (with offset attached). Also I won't remove the original operation. Will have a try asap.

I used the 'full injection' template now but now my code doesn't have any impact.
I will investigate!

(Yes, I messed up the fsp/fmul line in my previous post - sorry for that!)

Code:

define(address,"Cc.dll"+2B57B)
define(bytes,D8 4B 64 89 08)

[ENABLE]


assert(address,bytes)
alloc(newmem,$1000)

label(code)
label(return)

newmem:
  fmul dword ptr [multiplier]
  mov [eax],ecx
  jmp return

align 8 CC
multiplier:
  dd (float)2

code:
  fmul dword ptr [ebx+64]
  mov [eax],ecx
  jmp return

address:
  jmp newmem
return:

[DISABLE]

address:
  db bytes
  // fmul dword ptr [ebx+64]
  // mov [eax],ecx

dealloc(newmem)

{
// ORIGINAL CODE - INJECTION POINT: Cc.CcRigidBody::Derive+AB

Cc.CcRigidBody::Derive+82: 8D 74 24 30              - lea esi,[esp+30]
Cc.CcRigidBody::Derive+86: 8D BC 24 88 00 00 00     - lea edi,[esp+00000088]
Cc.CcRigidBody::Derive+8D: C7 44 24 10 03 00 00 00  - mov [esp+10],00000003
Cc.CcRigidBody::Derive+95: D9 C0                    - fld st(0)
Cc.CcRigidBody::Derive+97: D8 4B 5C                 - fmul dword ptr [ebx+5C]
Cc.CcRigidBody::Derive+9A: D9 5C 24 18              - fstp dword ptr [esp+18]
Cc.CcRigidBody::Derive+9E: 8B 4C 24 18              - mov ecx,[esp+18]
Cc.CcRigidBody::Derive+A2: D9 C0                    - fld st(0)
Cc.CcRigidBody::Derive+A4: D8 4B 60                 - fmul dword ptr [ebx+60]
Cc.CcRigidBody::Derive+A7: D9 5C 24 1C              - fstp dword ptr [esp+1C]
// ---------- INJECTING HERE ----------
Cc.CcRigidBody::Derive+AB: D8 4B 64                 - fmul dword ptr [ebx+64]
// ---------- DONE INJECTING  ----------
Cc.CcRigidBody::Derive+AE: 89 08                    - mov [eax],ecx
Cc.CcRigidBody::Derive+B0: 8B 4C 24 1C              - mov ecx,[esp+1C]
Cc.CcRigidBody::Derive+B4: 89 48 04                 - mov [eax+04],ecx
Cc.CcRigidBody::Derive+B7: D9 5C 24 20              - fstp dword ptr [esp+20]
Cc.CcRigidBody::Derive+BB: 8B 4C 24 20              - mov ecx,[esp+20]
Cc.CcRigidBody::Derive+BF: 89 48 08                 - mov [eax+08],ecx
Cc.CcRigidBody::Derive+C2: 8B 02                    - mov eax,[edx]
Cc.CcRigidBody::Derive+C4: 8B 4A 0C                 - mov ecx,[edx+0C]
Cc.CcRigidBody::Derive+C7: 89 44 24 30              - mov [esp+30],eax
Cc.CcRigidBody::Derive+CB: 8B 42 18                 - mov eax,[edx+18]
}
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 140

Joined: 06 Jul 2014
Posts: 4299

PostPosted: Wed Apr 20, 2022 3:49 pm    Post subject: Reply with quote

thenic wrote:
You mean storing the multiplier using an operation during the jump isn't clean and it's better to store it before and just reference to it when the specific opcode (that I need/want to manipulate) gets executed?
I don't know what you mean by that.
The multiplier gets stored when the AA script gets executed- not when one of the game's threads executes the assembly code.
Code:
multiplier:
  dd (float)2
"multiplier" is just a label- its only purpose is so that you can more easily refer to the address that label is located at.
The `dd` pseudoinstruction writes a doubleword (in this case a float) into memory. In general, the data being written by `dd` isn't code a CPU thread can execute- it's just data.

Example:
Code:
globalalloc(foo,4096)
label(multiplier)

foo:
// code
  fmul dword ptr [multiplier]

// data
align 4 CC
multiplier:
  dd (float)2

// back to code
  jmp foo+800

{
assembles to:
foo   - D8 0D 08009502 - fmul dword ptr [foo+8]
foo+6 - CC             - int 3
foo+7 - CC             - int 3
foo+8 - 00 00          - add [eax],al
foo+A - 00 40 E9       - add [eax-17],al
foo+D - EF             - out dx,eax
foo+E - 07             - pop es
foo+F - 00 00          - add [eax],al
...
}
This script assembles to stuff that looks like garbage because there is garbage in the middle of the code: the float 2.

thenic wrote:
Okay and injection copy looks like I have to mov the base address ([ebx]) right before it gets used/written by the code...
before or after isn't important since ebx isn't being modified.
This would only matter if the register you want to save is also being modified. e.g.:
Code:
mov esi,[esi]
To save the address being accessed here, you would have to save it before that instruction.

thenic wrote:
Also I won't remove the original operation.
It's fine to leave out the fmul instruction since you're replacing that with your own fmul. The mov instruction you should leave alone because you don't know what that does.
Your code looks fine, except that I'd remove the code label:
Code:
...
label(code)  // remove this
...
code:                      // remove these 4 lines
  fmul dword ptr [ebx+64]  // ^
  mov [eax],ecx            // ^
  jmp return               // ^
...

If it's still crashing, I guess you could try writing your multiplier to memory and see what happens:
Code:
...
newmem:
  push ecx
  mov ecx,[multiplier]
  mov [ebx+64],ecx
  pop ecx

  fmul dword ptr [ebx+64]
  mov [eax],ecx
  jmp return
...
Does the instruction `fmul dword ptr [ebx+64]` access more addresses than you intended? That's another reason why it could crash.
_________________
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
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