 |
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
wayden Cheater
Reputation: 0
Joined: 09 Dec 2020 Posts: 27
|
Posted: Thu Jul 06, 2023 11:45 pm Post subject: modifying assembly instructions? |
|
|
Hi,
I got a little question about code injection and how to modify specific instruction
So im modding Hell is others and after using mono dissector i got to a method that call an other one :
xor edx,edx
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything
the thing is i wanted to call this method with her boolean parameter set to 1
so i manualy did this:
mov dl,01
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything
and it worked perfectly but when i tried to use the autoassemble and Aob injection template wich look like this :
aobscanmodule(SeeEverythings,GameAssembly.dll,33 D2 48 8B CB E8 4C
EE FF FF) // should be unique
alloc(newmem,$1000)
...
mov dl,01
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything
jmp return
SeeEverythings:
jmp newmem
...
the game just crash, im gonna try to just modify the SeeEverythings: part to put it the modified operation directly
because i don't think i really need to alloc newmem since i don't create anything but perhaps im making mistake.
i wanted to know if their is others way more adapted for this kind of problem?
PS: modifying the SeeEvryhting: part directly worked , but i wonder why doing it the normal way by allocating new mem and just jmp to it didn't worked ?
is it possible that the alocated memory where i was doing the call from was too far away from the method i called ?
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4700
|
Posted: Thu Jul 06, 2023 11:58 pm Post subject: |
|
|
If there's enough room in the injection point to do what I want, I typically do it there and delete all the alloc stuff. You have to be careful about the number of bytes you overwrite in the original code: it's easy to screw things up and crash the game. Pause the process if necessary (mono stuff stops working while it's paused, that's fine).
I don't know why the typical alloc code injection isn't working for you. Perhaps you injected at the wrong instruction? Post the full script, along with the comment at the bottom showing instructions around the injection point. This comment is included in the "AOB Injection" and "Full Injection" templates.
PS: this forum has code labels:
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
wayden Cheater
Reputation: 0
Joined: 09 Dec 2020 Posts: 27
|
Posted: Fri Jul 07, 2023 11:12 am Post subject: |
|
|
Thanks for your answer ! Here is the full script :
Code: |
{ Game : Hell Is Others
Version:
Date : 2023-07-07
Author : wayden
This script does blah blah blah
}
[ENABLE]
aobscanmodule(SeeEverythings,GameAssembly.dll,33 D2 48 8B CB E8 4C EE FF FF) // should be unique
alloc(newmem,$1000)
label(code)
label(return)
newmem:
code:
SeeEverythings:
mov dl,01
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything
return:
registersymbol(SeeEverythings)
[DISABLE]
SeeEverythings:
db 33 D2 48 8B CB E8 4C EE FF FF
unregistersymbol(SeeEverythings)
dealloc(newmem)
{
// ORIGINAL CODE - INJECTION POINT: GameAssembly.dll+63AC9A
GameAssembly.dll+63AC6F: 48 8B 49 08 - mov rcx,[rcx+08]
GameAssembly.dll+63AC73: 48 85 C9 - test rcx,rcx
GameAssembly.dll+63AC76: 0F 84 6B 02 00 00 - je GameAssembly.dll+63AEE7
GameAssembly.dll+63AC7C: 48 8B 49 20 - mov rcx,[rcx+20]
GameAssembly.dll+63AC80: 48 8D 54 24 30 - lea rdx,[rsp+30]
GameAssembly.dll+63AC85: 45 33 C0 - xor r8d,r8d
GameAssembly.dll+63AC88: F2 0F 11 74 24 30 - movsd [rsp+30],xmm6
GameAssembly.dll+63AC8E: 89 6C 24 38 - mov [rsp+38],ebp
GameAssembly.dll+63AC92: E8 C9 51 F2 FF - call CameraManager.WarpCameraPosition
GameAssembly.dll+63AC97: 45 33 C0 - xor r8d,r8d
// ---------- INJECTING HERE ----------
GameAssembly.dll+63AC9A: 33 D2 - xor edx,edx
// ---------- DONE INJECTING ----------
GameAssembly.dll+63AC9C: 48 8B CB - mov rcx,rbx
GameAssembly.dll+63AC9F: E8 4C EE FF FF - call PlayerCharacter.EnableSeeEverything
GameAssembly.dll+63ACA4: 48 8B 05 6D 2C B1 02 - mov rax,[GameAssembly.dll+314D918]
GameAssembly.dll+63ACAB: 48 8B 88 B8 00 00 00 - mov rcx,[rax+000000B8]
GameAssembly.dll+63ACB2: C6 01 00 - mov byte ptr [rcx],00
GameAssembly.dll+63ACB5: 48 8B 05 34 66 B3 02 - mov rax,[GameAssembly.dll+31712F0]
GameAssembly.dll+63ACBC: 48 8B 88 B8 00 00 00 - mov rcx,[rax+000000B8]
GameAssembly.dll+63ACC3: 48 8B 49 08 - mov rcx,[rcx+08]
GameAssembly.dll+63ACC7: 48 85 C9 - test rcx,rcx
GameAssembly.dll+63ACCA: 0F 84 17 02 00 00 - je GameAssembly.dll+63AEE7
} |
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4700
|
Posted: Fri Jul 07, 2023 7:45 pm Post subject: |
|
|
Are you sure that script you just posted isn't working? It should be fine. Maybe CE isn't assembling the call instruction correctly (e.g. far call over that 5-byte call), or maybe the upper 3 bytes of edx matter. (modifying `dl` doesn't modify the other parts of `edx`)
There's no reason to overwrite those other 2 instructions, and most other lines can be deleted.
Code: | ...
[ENABLE]
aobscanmodule(SeeEverythings,GameAssembly.dll,33 D2 48 8B CB E8 4C EE FF FF)
SeeEverythings:
mov dl,01
registersymbol(SeeEverythings)
[DISABLE]
SeeEverythings:
db 33 D2
unregistersymbol(SeeEverythings)
{
...
} |
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
wayden Cheater
Reputation: 0
Joined: 09 Dec 2020 Posts: 27
|
Posted: Fri Jul 07, 2023 9:44 pm Post subject: |
|
|
Ah yes it's the working one where i don't do any jump to newmem and doesn't call from it.
the one that wasn't working looked like that :
Code: |
[ENABLE]
aobscanmodule(SeeEverythings,GameAssembly.dll,33 D2 48 8B CB E8 4C EE FF FF) // should be unique
alloc(newmem,$1000)
label(code)
label(return)
newmem:
code:
mov dl,01
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything
SeeEverythings:
jmp newmem
return:
registersymbol(SeeEverythings)
[DISABLE]
SeeEverythings:
db 33 D2 48 8B CB E8 4C EE FF FF
unregistersymbol(SeeEverythings)
dealloc(newmem)
|
with the exact same comments
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4700
|
Posted: Fri Jul 07, 2023 10:27 pm Post subject: |
|
|
The problem with that script is that `PlayerCharacter.EnableSeeEverything` is being called twice: once in your code injection with the correct arguments, and once again in the original code with undefined arguments.
`jmp newmem` takes up 5 bytes here... or, at least, it should if `alloc` was using the third parameter:
Code: | aobscanmodule(SeeEverythings,GameAssembly.dll,33 D2 48 8B CB E8 4C EE FF FF) // should be unique
alloc(newmem,$1000,SeeEverythings) // third parameter is very important
... | Without that third parameter, the `jmp` might take up 14 bytes, which would certainly crash the process.
Anyway, those 5 bytes taken up by `jmp newmem` overwrite two instructions: `xor edx,edx` and `mov rcx,rbx`. The third instruction, `call PlayerCharacter.EnableSeeEverything`, isn't overwritten. It gets executed immediately after `jmp return`... which your script seems to be missing as well.
Code: | code:
mov dl,01
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything
jmp return // jump back to the original code from your code injection
SeeEverythings:
jmp newmem // jump from original code to your code injection
return: | This missing instruction would crash the process too.
Anyway again, while the first call is fine, the second call is not because it doesn't have the correct arguments. `rcx` and `rdx` need to be set to the correct values; otherwise, the game could crash. Remove one of the calls to fix this: the one in your code injection is easiest.
The other two problems can be fixed by using the AOBScan template. If you want to make changes to the code CE generates for you, make sure you understand why the parts you change were there in the first place.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
wayden Cheater
Reputation: 0
Joined: 09 Dec 2020 Posts: 27
|
Posted: Sat Jul 08, 2023 1:14 am Post subject: |
|
|
aight i think i get it, i had the "same" problem on an other script :
Code: |
{ Game : HellIsOthers_launcher.exe
Version:
Date : 2023-07-08
Author : wayden
This script does blah blah blah
}
[ENABLE]
aobscanmodule(ItemMultiply,EOSSDK-Win64-Shipping.dll,29 41 08 48 8B 1D DB 69 1D 02) // should be unique
alloc(newmem,$1000,ItemMultiply)
alloc(CurrentItem,4)
registerSymbol(CurrentItem)
registerSymbol(newmem)
label(return)
CurrentItem:
dd 0
newmem:
mov [CurrentItem],rcx
add [rcx+08],eax
mov rbx,[GameAssembly.dll+1562A88]
jmp return
ItemMultiply:
jmp newmem
nop
nop
nop
nop
nop
return:
registersymbol(ItemMultiply)
/*--------------------------------------------*/
aobscanmodule(Itemmultiply2,EOSSDK-Win64-Shipping.dll,29 41 08 48 8B 44 24 30) // should be unique
Itemmultiply2:
add [rcx+08],eax
registersymbol(Itemmultiply2)
[DISABLE]
Itemmultiply2:
db 29 41 08
unregistersymbol(Itemmultiply2)
ItemMultiply:
db 29 41 08 48 8B 1D DB 69 1D 02
unregistersymbol(ItemMultiply)
unregistersymbol(newmem)
unregistersymbol(CurrentItem)
dealloc(newmem)
dealloc(CurrentItem)
|
so i added 5 nop to replace the second overwritten instruction and added it into the "code:" section and i didn't forgot the jmp return and it finally worked, Thanks a lot!
i let the other script without a "code:" section it's simpler to just overwrite 1 instruction than alloc registersymbol label jmp and jmp back dealloc
btw how can i know that rcx and rdx are used as arguments (in EnableSeeEverythings) ? for me it was only edx since the function takes only one bool arg and modifying edx to 01 was enought ?
|
|
Back to top |
|
 |
ParkourPenguin I post too much
Reputation: 152
Joined: 06 Jul 2014 Posts: 4700
|
Posted: Sat Jul 08, 2023 9:49 am Post subject: |
|
|
wayden wrote: | btw how can i know that rcx and rdx are used as arguments (in EnableSeeEverythings) ? for me it was only edx since the function takes only one bool arg and modifying edx to 01 was enought ? |
That comes down to calling conventions.
Windows x64 calling conventions dictate, among other things, that `rcx` and `rdx` are the first and second parameters to a function, respectively.
If you're looking at source code and only see one parameter, there's probably an implicit "this" parameter specifying the object being acted on. `rcx` is the "this" parameter (i.e. which player character to act on), and `edx` is the value passed to the function:
Code: | xor edx,edx
mov rcx,rbx
call PlayerCharacter.EnableSeeEverything | Here, `mov rcx,rbx` is setting up a parameter.
`rcx` is a caller-saved register, meaning the caller is responsible for saving it (if needed) and the function `PlayerCharacter.EnableSeeEverything` is free to overwrite it without backing it up. The only purpose that `mov` instruction could reasonably have immediately before a `call` is to set up a parameter.
More information:
https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions
However, I've seen modules and JIT runtimes somewhat ignore windows conventions and use some weird intra-module ABIs. This isn't guaranteed to be accurate in general.
_________________
I don't know where I'm going, but I'll figure it out when I get there. |
|
Back to top |
|
 |
|
|
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
|
|