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 


modifying assembly instructions?

 
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
wayden
Cheater
Reputation: 0

Joined: 09 Dec 2020
Posts: 27

PostPosted: Thu Jul 06, 2023 11:45 pm    Post subject: modifying assembly instructions? Reply with quote

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
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4700

PostPosted: Thu Jul 06, 2023 11:58 pm    Post subject: Reply with quote

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:
Code:
code here

_________________
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
wayden
Cheater
Reputation: 0

Joined: 09 Dec 2020
Posts: 27

PostPosted: Fri Jul 07, 2023 11:12 am    Post subject: Reply with quote

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
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4700

PostPosted: Fri Jul 07, 2023 7:45 pm    Post subject: Reply with quote

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
View user's profile Send private message
wayden
Cheater
Reputation: 0

Joined: 09 Dec 2020
Posts: 27

PostPosted: Fri Jul 07, 2023 9:44 pm    Post subject: Reply with quote

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
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4700

PostPosted: Fri Jul 07, 2023 10:27 pm    Post subject: Reply with quote

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
View user's profile Send private message
wayden
Cheater
Reputation: 0

Joined: 09 Dec 2020
Posts: 27

PostPosted: Sat Jul 08, 2023 1:14 am    Post subject: Reply with quote

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
View user's profile Send private message
ParkourPenguin
I post too much
Reputation: 152

Joined: 06 Jul 2014
Posts: 4700

PostPosted: Sat Jul 08, 2023 9:49 am    Post subject: This post has 1 review(s) Reply with quote

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
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking 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