ASM Code Injection - Working with Floats

TheyCallMeTim13

Wiki Monster
Talents
Fearless Donors
#1
https://wiki.cheatengine.org/index.php?title=Tutorial:CodeInjection_Floats
Code Injection - Working with Floats
This tutorial builds on the topic of Code Injection:

Let's say you have a float and some code that increases the value.
NASM:
addss [eax+10],xmm0
Note: SS is for singles and SD is for doubles. (i.e.: ADDSS or ADDSD)
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).
NASM:
addss xmm0,xmm1
//...
movss [eax+10],xmm0

Editable value
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.
CEA:
//...
alloc(someMem, 0x400)
//...
label(someSymbol)
registerSymbol(someSymbol)
//...
someMem:
  //...
  movss xmm0,[someSymbol]
  addss [eax+10],xmm0
  //...
  jmp return
  //...
  someSymbol:
    dd (float)100
//...

Adding a Multiplier
We could add an editable value like above but use MULSS to add a multiplier to the script.
CEA:
//...
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
Let's say we just can't find an ADDSS or a SUBSS, and all we have is a MOVSS.
NASM:
movss [eax+10],xmm0
We can just do some math in the script, to calculate a value for a multiplier.
CEA:
//...
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
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.
NASM:
movsd [eax+10],xmm0
So to calculate a value for a multiplier.
CEA:
//...
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
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.
NASM:
addps [eax+10],xmm0
So let's add a multiplier for this.
CEA:
//...
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
Let's say we just can't find an ADDPS or a SUBPS, and all we have is a MOVUPS or a MOVAPS.
NASM:
movups [eax+10],xmm0
We can just do some math in the script, to calculate a value for a multiplier.
CEA:
//...
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.
NASM:
movaps [eax+10],xmm0
Then we could make a script like this.
CEA:
//...
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
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.
NASM:
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.
NASM:
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.
NASM:
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.
CEA:
//...
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
 
Last edited:

SunBeam

RCE Fanatics
Talents
Fearless Donors
#2
Should also add a branch of this for playing with 16 bytes ;) Example: read/write player coordinates (Vec3):
CEA:
movups xmm0,[plCoords] // save
movups [stCoords],xmm0
movups xmm0,[newCoords]
mov [plCoords],xmm0
That makes an easy 16-bytes write on the fly, rather than doing 3/4 movss for each coordinate. As well as other specific operations: shuffling, adding, subtracting, etc. for processing ;)

Found this quite useful ;)

BR,
Sun
 

TheyCallMeTim13

Wiki Monster
Talents
Fearless Donors
#3
Should also add a branch of this for playing with 16 bytes...
Yeah, I was at first, but then wanted to talk about aligned instruction. But I don't know if it requires just memory to be aligned or the stack, testing seems just memory used but I found some stuff talking about the stack. Just been trying to find an answer, but I agree @SunBeam, I should add the unaligned instruction's for now. I mostly made this one for all the "how to add a multiplier" questions.

I did go over it a bit in the editable values tutorial, but this is where I started to want to find a good answer to the aligned question.

I'm betting you might know @SunBeam, is it just the memory or the stack that needs to be aligned for the aligned instructions?

EDIT:
And I want to add some stuff for the FPU registory.
 

SunBeam

RCE Fanatics
Talents
Fearless Donors
#4
See here or here. It's the operand, as in the memory address. Just use movups.

The other way around is to AND address so it ends in a 0. But then you wouldn't be able to dynamically use it very well if you call functions requiring alignment from your cave.

If you plan to use an address from your cave, then use one that ends in a 0. Might as well use CE's align to solve this.
 
Last edited:

TheyCallMeTim13

Wiki Monster
Talents
Fearless Donors
#5
^ So it's just the memory, I guess the stack if we access it but at that point offsets work fine.

I actually use the shit out of CE align, it just makes the assembled code look better I think; I guess that's the art part of coding.
 

TheyCallMeTim13

Wiki Monster
Talents
Fearless Donors
#7
Yeah I did the same, then found align some where and fell in love with it. The only thing I have found is if it's already aligned and you want the "CC" bytes then you have to unalign it first (i.e.: db CC).
 
Top Bottom