Code Injection - Working with Floats

From Cheat Engine
Jump to navigation Jump to search


This tutorial builds on the topic of Code Injection:


Let's say you have a float and some code that increases the value.

addss [eax+10],xmm0
Note: SS is for singles and SD is for doubles.

What if what writes to the value is only a MOVSS. Try to find a spot above the write instruction that has an ADDSS (or a SUBSS depending on what you want to do).

addss xmm0,xmm1
//...
movss [eax+10],xmm0


Editable value[edit]

We could use a label, giving it some memory. And optionally register it so the label can be used on the table as an address.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  movss xmm0,[someSymbol]
  addss [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dd (float)100
//...


Adding a Multiplier[edit]

We could add an editable value like above but use MULSS to add a multiplier to the script.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  mulss xmm0,[someSymbol]
  addss [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dd (float)100
//...


Calculate a value for a Multiplier[edit]

Let's say we just can't find an ADDSS or a SUBSS, and all we have is a MOVSS.

movss [eax+10],xmm0

We can just do some math in the script, to calculate a value for a multiplier.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  subss xmm0,[eax+10]
  mulss xmm0,[someSymbol]
  addss xmm0,[eax+10]
  movss [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dd (float)10
//...


Working with doubles[edit]

Let's say the game use doubles, we can use ADDSD, SUBSD, MULSD, and MOVSD instead. We just need to also make our scripts value a double.

movsd [eax+10],xmm0

So to calculate a value for a multiplier.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  subsd xmm0,[eax+10]
  mulsd xmm0,[someSymbol]
  addsd xmm0,[eax+10]
  movsd [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dq (double)10
//...


Working with packed instructions[edit]

Some times (especially with vectors) you'll see packed instructions, like MOVAPS, MOVUPS, ADDPS, SUBPS, MULPS. These type of instructions work on 16 bytes at a time.

So let's say you have some code accessing the player coordinate deltas, and it's using packed instructions.

addps [eax+10],xmm0

So let's add a multiplier for this.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  mulps xmm0,[someSymbol]
  addps [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dd (float)1.75
    dd (float)1.75
    dd (float)1.25
    dd (float)1
//...


Calculate a value for packed instruction[edit]

Let's say we just can't find an ADDPS or a SUBPS, and all we have is a MOVUPS or a MOVAPS.

movups [eax+10],xmm0

We can just do some math in the script, to calculate a value for a multiplier.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  subps xmm0,[eax+10]
  mulps xmm0,[someSymbol]
  addps xmm0,[eax+10]
  movups [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dd (float)1.75
    dd (float)1.75
    dd (float)1.25
    dd (float)1
//...

We could use the align command and then be able to use aligned instructions. So if the injection point looks like this.

movups [eax+10],xmm0

Then we could make a script like this.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  subps xmm0,[eax+10]
  mulps xmm0,[someSymbol]
  addps xmm0,[eax+10]
  movaps [eax+10],xmm0
  //...
  jmp return
  //...
  align 10 CC
  someSymbol:
    dd (float)1.75
    dd (float)1.75
    dd (float)1.25
    dd (float)1
//...


Working with the FPU registry[edit]

Some times you'll find some opcode that uses the FPU registry. These include FLD, FMUL, FADD, FSUB, FST, FSTP.

So with singles it might look like this.

fld dword ptr [ebp+20]
fmul dword ptr [ebp+40]
fadd dword ptr [eax+10]
fstp dword ptr [eax+10]

And if it was with doubles it might look like this.

fld qword ptr [ebp+20]
fmul qword ptr [ebp+40]
fadd qword ptr [eax+10]
fstp qword ptr [eax+10]

So say we have some opcode that decreases health that looks like this.

fld dword ptr [eax+10]
fsub dword ptr [ebp+20]
fstp dword ptr [eax+10]

So the add a multiplier to this we could make a script like this.

//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  fld dword ptr [ebp+20]
  fmul dword ptr [someSymbol]
  fld dword ptr [eax+10]
  fsub st(0),st(1)
  fstp dword ptr [eax+10]
  fstp st(0)
  //...
  jmp return
  //...
  someSymbol:
    dd (float)0.25
//...


See Also[edit]