jgoemat Master Cheater Reputation: 23 Joined: 25 Sep 2011 Posts: 264
|
Posted: Mon Aug 04, 2025 5:29 pm Post subject: MonoHelper |
|
|
Sorry I don't have time to create a tutorial or video or update a lot of things, but I have a 'MonoHelper' project that you might be interested in. Here's the link that has some info: https://fearlessrevolution.com/viewtopic.php?t=11415
But if you want to use it, I recommend downloading one of my recent tables and checking it out as I've updated the script recently. I condensed it into a single table entry that runs the LUA. What it does is pre-process a single mono dll, defaulting to 'Assembly-CSharp' which is most often used. Then it adds a 'Search' button in the Mono menu when connected to a game. It filters classes, properties, and methods as you type. Here's a recent one for 'Rock Crusher' demo which is free if you want to see how the scripts it creates work and try it out: https://fearlessrevolution.com/search.php?author_id=7314&sr=posts - if you right-click on the script and go to "group config' and uncheck 'hide all children when deactivated' then delete all the children you can copy it to your own table.
Usually I start just by using Mono->Search and looking for classes like 'Player', 'Ship', 'Manager', 'Entity', etc. It's a good thing when you find something with an 'Update()' method. That means it is usually called every frame. I usually start by finding something like that and in the class window I right-click on the method and select 'Create Debug Entry'. That'll create a table entry you can enable to hook that method. That table entry has children that show the last value of RCX when it was called (pointer to that class instance), how many times it was called, and all the parameter values passed the last time it was called. I'll usually copy that value and load it into the structure dissectory (CTRL+M for memory viewer, then CTRL+D for structure dissector) and let it generate the structure to see what I'm working with. Then I can just add instructions to try out something to cheat and I have a working script.
For example in the Rock Crusher I have a cheat to not consume fuel. I just searched for 'fuel' and found the FuelManager class and ConsumeFuel method by searching for which seemed like what I wanted. I just double-clicked to open the class and right-clicked on that method to create a debug entery and added some code. I added `GETMONOSTRUCT(FuelManager)` which sets up the field names with offsets for the script, and three instructions to set the current fuel to max and zero out xmm1 which is the parameter for how much fuel to consume, the rest was generated.
Code: | define(hook,"SR.Run.Combat.FuelManager:Consume")
define(bytes,55 48 8B EC 48)
[enable]
assert(hook, bytes)
alloc(newmem,$1000, hook)
label(pFuelManager_Consume)
{
RCX: FuelManager (this)
XMM1: single amount
R8: SR.Run.Combat.FuelConsumptionSource source
Returns (RAX) System.Void
}
GETMONOSTRUCT(FuelManager)
newmem:
// increment counter, store instance and parameters (could be off for static method?)
push rbp
mov rbp,rsp
push rax
mov [pFuelManager_Consume], rcx
inc dword ptr [pFuelManager_Consume+8]
movss [pFuelManager_Consume+10], XMM1 // amount
mov [pFuelManager_Consume+18], R8 // source
mov eax,[rcx+maxFuel]
mov [rcx+currentFuel],eax // set current fuel to max
xorps xmm1,xmm1 // zero out amount
pop rax
pop rbp
// original code
// push rbp
// mov rbp,rsp
// sub rsp,00000080
readmem(hook,11)
jmp hook+B
align 10
pFuelManager_Consume:
dq 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
hook:
jmp newmem
registersymbol(pFuelManager_Consume)
[disable]
hook:
db bytes
unregistersymbol(pFuelManager_Consume)
dealloc(newmem)
|
You should also check out this post: https://forum.cheatengine.org/viewtopic.php?t=623200 - You can actually write C# now and have it compiled as part of your scripts. It's a bit complicated, but I found a pretty simple method `CraftingWindowUI.CheckCraftable()`. I created a class of my own in my own namespace 'MyGuild' here to replace that method, using a static class and static method with 'this CraftingWindowUI' as the first parameter. Then I just hooked the method and jumped to my replacement which added 'ui.CraftButton.interactable = true' to make it always interactable.
Code: | {$lua}
if syntaxcheck then return end
local references, core = dotnetpatch_getAllReferences()
local code = [[namespace MyGuild
{
public static class CraftingWindowExtensions
{
public static void CheckCraftable(this CraftingWindowUI ui)
{
ui.CraftButton.interactable = true;
ui.CraftPrompt.UpdateUI();
}
}
}
]]
local assemblyPath = compileCS(code, references, core)
mono_loadAssemblyFromFile(assemblyPath)
{$asm} |
|
|