Mono Script Simplifier

Upload *YOUR* gamehacking tools/helpers here
Post Reply
jgoemat
Table Makers
Table Makers
Posts: 66
Joined: Fri Jul 21, 2017 6:47 pm
Reputation: 68

Mono Script Simplifier

Post by jgoemat »

This is a fairly foolproof method for writing simple scripts for mono games. It should handle the initial code of a method changing with different values. For instance this is the start of the 'PersonController:Update' method in Raft:

Code: Select all

  push rbp
  mov rbp,rsp
  sub rsp,000009D0
  mov [rbp-28],rsi
The problem is that the '9D0' will probably change if the version of Raft changes, if you add mods, or it can just if you run it again in some games. This much code is needed for a long JMP to the code you want to inject, which has been happening to me sometimes when CE can't find memory near the method you're injecting into. The most resilient way I've found is to use readmem() in your aa script to copy the actual bytes, register a symbol, and restore them in [disable] and unregister the symbol. That's a lot of code I don't want to write for 20 methods :) I wrote some LUA to create some AA commands to make it super easy. It actually disassembles enough bytes for a long jmp and reassembles them for you to return. This should handle things like call to a relative address and rearranging code as well, but needs some love to account for things like conditional jumps since your code may be far away.

Here's a sample for Raft to give you unlimited oxygen:

Code: Select all

[enable]

alloc(newmem,$1000)

newmem:

MonoMethodInit(PersonController:Update,PersonController,PlayerStats,Stat_Oxygen,Stat)

  push rbx
  push rax
  mov rbx,[rcx+PersonController.playerStats]
  test rbx,rbx
  jz @f
  mov rbx,[rbx+PlayerStats.stat_oxygen]
  test rbx,rbx
  jz @f
  mov eax,[rbx+Stat.maxValue]
  mov [rbx+Stat.value],eax
@@:
  pop rax
  pop rbx
  jmp original_PersonController_Update

MonoMethodHook(PersonController:Update)

[disable]

MonoMethodRestore(PersonController:Update)

dealloc(newmem)
* MonoMethodInit - takes the method to hook and an optional list of types to define using GETMONOSTRUCT(). So even if offsets change, you can use 'PlayerStats.stat_oxygen' for example for the offset.
* MonoMethodHook - hooks the method to jmp to the code following MonoMethodInit
* MonoMethodRestore - restores the original bytes that were replaced by hooking the method

As you can see in the code, I do 'jmp original_PersonController_Update' to continue executing the relocated code and jumping back to after where the replaced code was. Other options are 'jmp return_PersonController_Update' which skips the relocated code, so you need to make sure you took care of what it does. Also you could just 'ret' if you don't want the method to actually execute.

The attached table has a script with LUA to create the AA commands you can drop into your own tables (or copy the lua to your table script), a sample script with the code for the unlimited oxygen, and a script with the text being what is actually generated. For example the injected code section looks like this:

Code: Select all

label(original_PersonController_Update)
ALIGN 10
original_PersonController_Update:
  push rbp
  mov rbp,rsp
  sub rsp,000009D0
  mov [rbp-28],rsi

label(return_PersonController_Update)
return_PersonController_Update:
  jmp 136FBB6000F

ALIGN 10
label(code_PersonController_Update)
code_PersonController_Update:
Followed by the code in the sample script, followed by the hook:

Code: Select all

PersonController:Update:
  jmp code_PersonController_Update
The restore section looks like this:

Code: Select all

PersonController:Update:
  db 55 48 8B EC 48 81 EC D0 09 00 00 48 89 75 D8
Attachments
MonoAAMethods.CT
(14.12 KiB) Downloaded 344 times

Post Reply

Who is online

Users browsing this forum: No registered users