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 


Injection change crashes no matter what I try (SOPFFO)

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

Joined: 07 Mar 2018
Posts: 7

PostPosted: Sat Apr 30, 2022 9:05 pm    Post subject: Injection change crashes no matter what I try (SOPFFO) Reply with quote

I'm new to injection, so please don't be too harsh on me in responses for overlooking something silly.

I am playing Stranger of Paradise: Final Fantasy Origin, and I want to make an injection script that makes it so my Lightbringer (LB) buff doesn't decrease. Obviously I can just lock it, but each time it's cast the game uses a different memory address. So I thought I'd just locate the pointer, but there's some weird switch-a-roos the pointer undergoes each time before it gets to the buff timer countdown and locking it seems to do nothing. When the buff gets to 0, the pointer switches to another address (that's fine). When I cast it again, the pointer shows the correct time for an instant, then the pointer changes a handful of times to random numbers before coming back to the real timer. It's weird. Unlocking and locking each time works, but that's a little annoying.

So here's where I'm at.

Code:

SOPFFO.exe+2F75D8 - F3 0F10 4B 34         - movss xmm1,[rbx+34]
SOPFFO.exe+2F75DD - F3 0F5C C8            - subss xmm1,xmm0
SOPFFO.exe+2F75E1 - F3 0F10 43 38         - movss xmm0,[rbx+38]
SOPFFO.exe+2F75E6 - 0F2F C8               - comiss xmm1,xmm0
SOPFFO.exe+2F75E9 - F3 0F11 4B 34         - movss [rbx+34],xmm1


The line I'm directed toward that writes to the countdown timer is +2F75E9. So I saw that +2F75D8 loads the current buff time remaining, then xmm0 on line +2F75DD is always 1 and subtracts 1 from the buff time remaining. Then +2F75E9 moves that new value into the remaining time.

I first tried injecting at +2F75E9 the following, directly setting the xmm1 register to 900 using a user-created variable:
Code:

alloc(newmem,2048,"SOPFFO.exe"+2F75E9)
label(returnhere)
label(originalcode)
label(exit)
label(lbmax)

newmem:
movss xmm1,[lbmax]

lbmax:
dd 900

originalcode:
movss [rbx+34],xmm1

exit:
jmp returnhere

"SOPFFO.exe"+2F75E9:
jmp newmem
returnhere:


If LB isn't active, toggling the script on and off works and doesn't do anything (duh). If LB is active and I activate the script -- instant crash.

So I tried another. I tried going up to +2F75D8 and injecting the following, changing it so the -1 actually just performed -0 each time:
Code:

alloc(newmem,2048,"SOPFFO.exe"+2F75DD)
label(returnhere)
label(originalcode)
label(exit)
label(subzero)

newmem:
subss xmm1,[subzero]
movss xmm0,[rbx+38]

subzero:
dd 0

originalcode:
//subss xmm1,xmm0
//movss xmm0,[rbx+38]

exit:
jmp returnhere

"SOPFFO.exe"+2F75DD:
jmp newmem
nop 4
returnhere:


But alas, the same outcome.

Am I just a moron and don't know what I'm doing? Thanks.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 155

Joined: 06 Jul 2014
Posts: 4771

PostPosted: Sat Apr 30, 2022 10:06 pm    Post subject: Reply with quote

In both examples, you have data (i.e. lbmax and subzero respectively) in the middle of code you're trying to execute. I gave a brief example of how this turns code to junk here:
https://forum.cheatengine.org/viewtopic.php?p=5778471#5778471

Also, `dd 900` is the 4-byte integer 900, not a float. It's nice if the data is aligned too.

This is what your first script should look like:
Code:
alloc(newmem,2048,"SOPFFO.exe"+2F75E9)
label(returnhere)
label(lbmax)

newmem:
  movss xmm1,[lbmax]
  movss [rbx+34],xmm1
  jmp returnhere

align 4 CC
lbmax:
  dd (float)900.0

"SOPFFO.exe"+2F75E9:
  jmp newmem
returnhere:
This script might still have a problem since it didn't affect the comiss instruction before it.

Personally, I'd replace `subss xmm1,xmm0` with nops:
Code:
define(address,"SOPFFO.exe"+2F75DD)
define(bytes,F3 0F 5C C8)

[ENABLE]
assert(address,bytes)

address:
  nop 4

[DISABLE]

address:
  db bytes
  // subss xmm1,xmm0

{
// ORIGINAL CODE - INJECTION POINT: SOPFFO.exe+2F75DD

SOPFFO.exe+2F75D8 - F3 0F10 4B 34         - movss xmm1,[rbx+34]
// ---------- NOP HERE ----------
SOPFFO.exe+2F75DD - F3 0F5C C8            - subss xmm1,xmm0
// ---------- DONE NOP ----------
SOPFFO.exe+2F75E1 - F3 0F10 43 38         - movss xmm0,[rbx+38]
SOPFFO.exe+2F75E6 - 0F2F C8               - comiss xmm1,xmm0
SOPFFO.exe+2F75E9 - F3 0F11 4B 34         - movss [rbx+34],xmm1
}

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

Joined: 07 Mar 2018
Posts: 7

PostPosted: Sun May 01, 2022 10:09 am    Post subject: Reply with quote

ParkourPenguin wrote:

Also, `dd 900` is the 4-byte integer 900, not a float. It's nice if the data is aligned too.


Your code works great! I will add that "900" and "900.0" are interpreted the same in this case because -- although the game has the variable as a FLOAT, the value is always an integer (I know, it's weird...). So that's why I just did a DD w/o (float). I've noticed a lot of variables in this game where they use floats unnecessarily.

But maybe you're right that I should use a float just to not screw anything up I may not be seeing....

However, I'm not sure what your "align 4 CC" line does. All I did was move my "lbmax: dd 900" line down lower to after the "JMP RETURNHERE" and it works fine as well.

So having all the extra stuff you put in DOES work, but so does my version being a little more minimalist.

So, being new to injection here, what is the difference then between yours and mine?

Here is the complete code I have that works 100% perfectly:

Code:

alloc(newmem,2048,"SOPFFO.exe"+2F75E9)
label(returnhere)
label(lbmax)
label(originalcode)
label(exit)

newmem:
movss xmm1,[lbmax]

originalcode:
movss [rbx+34],xmm1

exit:
jmp returnhere

lbmax:
dd 900

"SOPFFO.exe"+2F75E9:
jmp newmem
returnhere:
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 155

Joined: 06 Jul 2014
Posts: 4771

PostPosted: Sun May 01, 2022 11:48 am    Post subject: Reply with quote

jplumb wrote:
although the game has the variable as a FLOAT, the value is always an integer
You misunderstand. Floats and integers are two completely different data types. Example C code:
Code:
#include <stdio.h>

union Data {
   float f;     // float
   unsigned u;  // integer
};

int main(int argc, char** argv) {
   union Data data;
   data.f = 900.f;

   printf("data.f: %g (float)\n", data.f);
   printf("data.u: 0x%08X (integer)\n", data.u);

   return 0;
}


/* Output:
 *
 * data.f: 900 (float)
 * data.u: 0x44610000 (integer)
 */
The float 900 is the 4-byte integer 0x44610000.
In your case, the 4-byte integer 0x900 (yes integers are in hex by default) is the float 3.22859e-42.
See IEEE-754 for more information.

jplumb wrote:
However, I'm not sure what your "align 4 CC" line does.
It aligns the data. It's not terribly important in x86 / x86-64 architectures- most instructions can access unaligned data. It's just that CPUs prefer to access aligned data. e.g. CPUs don't like memory accesses that cross a cache line boundary.
The overwhelming majority of values that exist are aligned. In most programming languages, it's undefined behaviour, if not impossible, to access unaligned data. CE's fast scan feature takes advantage of this.
Personally, I align data just to make me feel better. It's not like I'll ever notice a speed difference between code injections that do and do not align data.

Code differences:
  • Uses the actual float 900, not the float 3.22859e-42
  • The data is aligned. This isn't really of much practical importance
  • No useless labels. I don't like clutter
  • Instructions are indented a little. Indented code is more readable to me (align is an exception as it applies to the label more than anything else)

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

Joined: 07 Mar 2018
Posts: 7

PostPosted: Sun May 01, 2022 8:27 pm    Post subject: Reply with quote

ParkourPenguin wrote:
jplumb wrote:
although the game has the variable as a FLOAT, the value is always an integer
You misunderstand. Floats and integers are two completely different data types.


What I am saying is that "dd 900" works as intended because of how it's used. It sets the value to 900.0. I don't have to add the ".0" to the end or even say "(float)" before I'm assuming because I'm throwing it in a double-precision register (xmm1).

I may not fully understand all of the reasons for everything, but I can tell you that it set the value properly without needing any additional info.

Maybe I'm just not following what you're saying. If so, then maybe one day it'll dawn on me.
Back to top
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 155

Joined: 06 Jul 2014
Posts: 4771

PostPosted: Sun May 01, 2022 10:00 pm    Post subject: Reply with quote

jplumb wrote:
What I am saying is that "dd 900" works as intended because of how it's used. It sets the value to 900.0. I don't have to add the ".0" to the end or even say "(float)" before I'm assuming because I'm throwing it in a double-precision register (xmm1).

I don't know why you think what you're doing works as you intend, but it doesn't. You're wrong. I don't know how I can be any more direct.
I'm looking at CE's source right now and I can tell you there's no magic that will automatically interpret the 900 in `dd 900` as anything but a hexadecimal 4-byte integer.

Attach CE to any process (e.g. the tutorial), add this script to the table, and run it:
Code:
[ENABLE]
globalalloc(foo,4096)
label(source)
label(result)

registersymbol(source)
registersymbol(result)

createthread(foo)

foo:
  movss xmm0,[source]
  movss [result],xmm0
  ret

foo+100:
source:
  dd 900
result:
  dd 0

{$lua}
if syntaxcheck then return end
createTimer(500, function()
  local src, res = getAddressSafe'source', getAddressSafe'result'
  if src and res then
    print(('source (int): 0x%X'):format(readInteger(src)))
    print(('result (int): 0x%X'):format(readInteger(res)))
    print(('source (float): %g'):format(readFloat(src)))
    print(('result (float): %g'):format(readFloat(res)))
  end
end)

--[[ Output:
source (int): 0x900
result (int): 0x900
source (float): 3.22859e-42
result (float): 3.22859e-42
--]]
{$asm}

[DISABLE]

unregistersymbol(source)
unregistersymbol(result)
You'll see `dd 900` results in the integer 0x900 (as a float: 3.22859e-42).

If you really want to assert it works the way you think it works, provide an example. Assumptions, especially from someone new to something, aren't worth much.


Also, "float" is short for "single-precision floating point number", "double" is short for "double-precision floating point number", and xmm1 is a 128-bit register that can store 4 floats or 2 doubles.

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

Joined: 07 Mar 2018
Posts: 7

PostPosted: Mon May 02, 2022 7:51 am    Post subject: Reply with quote

ParkourPenguin wrote:

I don't know why you think what you're doing works as you intend, but it doesn't. You're wrong. I don't know how I can be any more direct.
I'm looking at CE's source right now and I can tell you there's no magic that will automatically interpret the 900 in `dd 900` as anything but a hexadecimal 4-byte integer.


I have to come confess that you are correct. I don't know what I had typed in my code last night that was "working" but "900" clearly doesn't work this morning. I apologize for disputing what you were saying, and I appreciate your help in learning this.
Back to top
View user's profile Send private message
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