Page 1 of 1

Request help on some code injection question

Posted: Fri Apr 18, 2025 10:31 am
by Thunter2012
Hi everyone,

I am new and learning about code injection but something I can't handle.
Please help if you have any idea.

I have a problem that I want to write a script for infinite HP on a shared code.
That is Player 1 HP & Player 2 HP using shared code.

I found a method to seperate the code logic by using cmp command.
So I write an injection to cmp the different between P1 & P2 in 2 different scripts.
When they are used seperately, it works fine. But once they used together, one of the script (or noth) may infunction.

Are there scripts can be wrote so that cheat engine can make both work but not overwrite each other when the 2 script used together?

Thank you very much.

Re: Request help on some code injection question

Posted: Fri Apr 18, 2025 11:07 am
by RTX_XXXX
if you use same opcode, you have to separate (for example hp) by some addresses in 1 script, that's different depend on game engine

for example:

Code: Select all

cmp [eax+1],1----->Player1
jne player2
mov [eax+4],#100---->injected hp
jmp return

player2:
cmp [eax+1],2----->player2
jne code
mov [eax+4],#100---->injected hp
jmp return

code:
mov [eax+4],ecx---->original opcode
jmp return

Re: Request help on some code injection question

Posted: Fri Apr 18, 2025 12:01 pm
by imjustmaxie
RTX_XXXX wrote:
Fri Apr 18, 2025 11:07 am
if you use same opcode, you have to separate (for example hp) by some addresses in 1 script, that's different depend on game engine

for example:

Code: Select all

cmp [eax+1],1----->Player1
jne player2
mov [eax+4],#100---->injected hp
jmp return

player2:
cmp [eax+1],2----->player2
jne code
mov [eax+4],#100---->injected hp
jmp return

code:
mov [eax+4],ecx---->original opcode
jmp return
I'd do the same approach, but instead of jumping everything to return, why not actually use the process control flow properly?
If I were to have both one hit kill and max health

Code: Select all

newmem:
cmp byte ptr [eax+1],1   // 1: ID for Player 1
jne @f
cmp byte ptr [flag],1		// flag that checks for max health
jne @f
mov ecx,#100
jmp code

@@:
cmp byte ptr [flag+01],1	// flag that checks for ohk
jne code
xor ecx,ecx 

code:
mov [eax+4],ecx	// original opcode
jmp return

flag:
dq 0
// 00 = Max Health
// 01 = OHK

return:
Note:
@@ is a placeholder label, @f is next label (f for forward), @b is previous label (b for backwards)

Re: Request help on some code injection question

Posted: Fri Apr 18, 2025 12:04 pm
by imjustmaxie
there's a typo in the code:
should be:

Code: Select all

cmp byte ptr [flag],1		// flag that checks for max health
jne code
since the previous code already verifies that the ID is for player, and we don't want it to kill us instead by jumping to the next label.

Sorry i post this cuz i cant edit above post.

Re: Request help on some code injection question

Posted: Fri Apr 18, 2025 12:36 pm
by RTX_XXXX
I tried to explain it in easiest way to understand, I assumed that enemy also have shared hp, also I don't prefer flag check it may some times make crash, if you wanna separate GM and 1 hit kill you need to define new addresses with cmp, like this
alloc(OHK,4)
registersymbol(OHK)

cmp [OHK],1
jne code


OHK:
dd 0

and in the separated scrip:

enable:
dd 1

disable:
dd 0

Re: Request help on some code injection question

Posted: Fri Apr 18, 2025 6:00 pm
by Send
The simplest way would be to just do the following:

Code: Select all

registersymbol(GM OHK)
label(code return GM OHK)

newmem:
cmp [GM],1 // Is GodMode enabled? 
jne @f //If not, jump to next.
cmp byte ptr [eax+1],1 //IsPlayer?
jne @f //If not, jump to next.
mov ecx,#100

@@:
cmp [OHK],1 //Is OneHitKill enabled?
jne code //If not, jump to code
cmp byte ptr [eax+1],1 //IsPlayer?
je code //If Player, jump to code.
xor ecx,ecx 
jmp code

code:
mov [eax+4],ecx
jmp return

GM:
dd 0

OHK:
dd 0

return:
Toggles in separate scripts:

Code: Select all

[ENABLE]
GM:
dd 1

{DISABLE]
GM:
dd 0

and

[ENABLE]
OHK:
dd 1

[DISABLE]
OHK:
dd 0
No need to allocate memory for toggles.

Re: Request help on some code injection question

Posted: Sat Apr 19, 2025 7:41 am
by Thunter2012
Thank you very much to all of you,

I learn a lot. All of the suggestion are useful in my situation.

Send wrote:
Fri Apr 18, 2025 6:00 pm
The simplest way would be to just do the following:

Code: Select all

registersymbol(GM OHK)
label(code return GM OHK)

newmem:
cmp [GM],1 // Is GodMode enabled? 
jne @f //If not, jump to next.
cmp byte ptr [eax+1],1 //IsPlayer?
jne @f //If not, jump to next.
mov ecx,#100

@@:
cmp [OHK],1 //Is OneHitKill enabled?
jne code //If not, jump to code
cmp byte ptr [eax+1],1 //IsPlayer?
je code //If Player, jump to code.
xor ecx,ecx 
jmp code

code:
mov [eax+4],ecx
jmp return

GM:
dd 0

OHK:
dd 0

return:
Toggles in separate scripts:

Code: Select all

[ENABLE]
GM:
dd 1

{DISABLE]
GM:
dd 0

and

[ENABLE]
OHK:
dd 1

[DISABLE]
OHK:
dd 0
No need to allocate memory for toggles.
Hi Send,

My script want to trigger P1 & P2 infinite health toegther & seperately, your code seem to be the best solution in my case.
My code is written as something like this (by using CE's code injection template as I am a newbie)

Code: Select all


[ENABLE]
alloc(newmem,2048,"GGST-Win64-Shipping.exe"+C68DFE) 
label(returnhere)
label(originalcode)
label(exit)

newmem:
cmp byte ptr [rdi+4C],0 //to compare player 1 or not, player 1 is 0 while player 2 is 1
mov [rdi+00001220],#420 //if player 1, then write 420 to the health
je exit

originalcode:
mov [rdi+00001220],esi

exit:
jmp returnhere

"GGST-Win64-Shipping.exe"+C68DFE:
jmp newmem
nop
returnhere:

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"GGST-Win64-Shipping.exe"+C68DFE:
db 89 B7 20 12 00 00
//mov [rdi+00001220],esi
if I want to be able trigger both P1 & P2's cheat, should I write the code as below?

Code: Select all


[ENABLE]
//code from here to '[DISABLE]' will be used to enable the cheat
registersymbol(Player1health)
registersymbol(Player2health)
alloc(newmem,2048,"GGST-Win64-Shipping.exe"+C68DFE) 
label(returnhere)
label(originalcode)
label(exit)

newmem:
cmp [Player1health],1 // Don't sure if this is right or not as I only want to infinite health
jne @f //If not, jump to next.
cmp byte ptr [rdi+4C],0 //IsPlayer 1?, 0 for player 1
jne @f //If not, jump to next.
mov [rdi+00001220],#420

@@:
cmp [Player2health],1 // same as player above, not sure if it is right or not
jne @f //If not, jump to next.
cmp byte ptr [rdi+4C],1 //IsPlayer 2?, 1 for player 2
jne @f //If not, jump to next.
mov [rdi+00001220],#420

jmp originalcode

originalcode:
mov [rdi+00001220],esi

exit:
jmp returnhere

Player1health:
dd 0

Player2health:
dd 0

"GGST-Win64-Shipping.exe"+C68DFE:
jmp newmem
nop
returnhere:

[DISABLE]
//code from here till the end of the code will be used to disable the cheat
dealloc(newmem)
"GGST-Win64-Shipping.exe"+C68DFE:
db 89 B7 20 12 00 00
//mov [rdi+00001220],esi
And I should wrtie a seperate script as below

Script A

Code: Select all

[ENABLE]
Player1health:
dd 1

{DISABLE]
Player1health:
dd 0

Script B

Code: Select all

[ENABLE]
Player2health:
dd 1

{DISABLE]
player2health:
dd 0

Please help me if I make something wrong. Thank you very much again to you all.

Re: Request help on some code injection question

Posted: Sat Apr 19, 2025 8:09 am
by Send
Thunter2012 wrote:
Sat Apr 19, 2025 7:41 am
///
I suggest using AOB instead of code injection. Seeing as Guilty Gear Strive (info I got from the address in your code) is still being updated, that address will no longer work after an update. If you use AOB instead of code injection and offsets haven't changed, the script will work.

Re: Request help on some code injection question

Posted: Sat Apr 19, 2025 8:46 am
by Rhark
I wouldn't write:

Code: Select all

mov [rdi+00001220],#420
Because it'll be overwritten by the value of ESI.

Instead just write this:

Code: Select all

mov esi,#420

Re: Request help on some code injection question

Posted: Sun Apr 20, 2025 4:50 am
by Thunter2012
Thank you to you all again.

Finally I make a work script with what I want.
Below is the script I wrote, it work properly.
But when the script is deactivated, it cannot activate again until I close and re-open CE again.
Do I missed something in the script? Please help and thanks again.

Code: Select all

[ENABLE]

aobscanmodule(INJECT,GGST-Win64-Shipping.exe,89 B7 20 12 00 00) // should be unique
alloc(newmem,$1000,INJECT)

registersymbol(Player1health)
registersymbol(Player2health)
label(code)
label(return)

newmem:

cmp [Player1health],1 // Don't sure if this is right or not as I only want to infinite health
jne @f //If not, jump to next.
cmp byte ptr [rdi+4C],0 //IsPlayer 1?, 0 for player 1
jne @f //If not, jump to next.
mov esi,#420

@@:
cmp [Player2health],1 // same as player above, not sure if it is right or not
jne @f //If not, jump to next.
cmp byte ptr [rdi+4C],1 //IsPlayer 2?, 1 for player 2
jne @f //If not, jump to next.
mov esi,#420

jmp code

code:
  mov [rdi+00001220],esi
  jmp return

Player1health:
dd 0

Player2health:
dd 0

INJECT:
  jmp newmem
  nop
return:
registersymbol(INJECT)

[DISABLE]

INJECT:
  db 89 B7 20 12 00 00

unregistersymbol(INJECT)
dealloc(newmem)


Re: Request help on some code injection question

Posted: Sun Apr 20, 2025 12:32 pm
by AlexS
(Google Translate)

To understand the reason, in the disassembler window, go to the instruction on which your script is being implemented and check whether the code is being restored correctly after deactivating the script.

Apparently, you have several scripts in the table.
When you create a new script, the program offers you the name of the injection point "INJECT". Always change this name to something unique. For example, "INJECT1", "INJECT2", "INJECT 3", etc.. You can choose any name, but only so that the names of the injection point do not match in different scripts.
Also note that different scripts cannot use the same injection point (sometimes they can, but only if you know exactly what you are doing). Therefore, if you have, for example, two scripts in the table using the same injection point, then you can activate only the first or only the second script, but not both scripts at the same time.

Re: Request help on some code injection question

Posted: Sun Apr 20, 2025 8:05 pm
by Send
Thunter2012 wrote:
Sun Apr 20, 2025 4:50 am
///
The symbols used (Player1health and Player2health) to toggle aren't unregistered.

Code: Select all

unregistersymbol(*)
dealloc(*)

Re: Request help on some code injection question

Posted: Mon Apr 21, 2025 11:00 am
by Thunter2012
Send wrote:
Sun Apr 20, 2025 8:05 pm
Thunter2012 wrote:
Sun Apr 20, 2025 4:50 am
///
The symbols used (Player1health and Player2health) to toggle aren't unregistered.

Code: Select all

unregistersymbol(*)
dealloc(*)
Thank you very much.
The script is finally work and no problem found.
I still need experts to point out the mistakes and omissions of a novice like me.
Thank you again.

Re: Request help on some code injection question

Posted: Mon Apr 21, 2025 11:03 am
by Thunter2012
AlexS wrote:
Sun Apr 20, 2025 12:32 pm
(Google Translate)

To understand the reason, in the disassembler window, go to the instruction on which your script is being implemented and check whether the code is being restored correctly after deactivating the script.

Apparently, you have several scripts in the table.
When you create a new script, the program offers you the name of the injection point "INJECT". Always change this name to something unique. For example, "INJECT1", "INJECT2", "INJECT 3", etc.. You can choose any name, but only so that the names of the injection point do not match in different scripts.
Also note that different scripts cannot use the same injection point (sometimes they can, but only if you know exactly what you are doing). Therefore, if you have, for example, two scripts in the table using the same injection point, then you can activate only the first or only the second script, but not both scripts at the same time.
Thank you very much.
This is what i missed so that the script isn't work properly.
I learn a lots.