CE Mono Features

Section's for general approaches on hacking various options in games. No online-related discussions/posts OR warez!
Post Reply
TimFun13
Expert Cheater
Expert Cheater
Posts: 1354
Joined: Fri Mar 03, 2017 12:31 am
Reputation: 6

CE Mono Features

Post by TimFun13 »

[Link]

CE Mono Features

So what are the Cheat Engine mono features? What is Mono? [Link] is a free and open-source project. Created to build an ECMA (European Computer Manufacturers Association) standard-compliant .NET Framework compatible set of tools. Including a C# compiler and a Common Language Runtime with just-in-time (JIT) compilation. Side Note: The logo of Mono is a stylized monkey's face, mono being Spanish for monkey. The Cheat Engine Mono feature are basically tools to help in Mono games. They can offer a different way to create and/or use cheats.



Let's setup infinite health in a Mono game. I'll be using [Link].



Attaching to the process

So if you attach to a Mono game then Cheat Engine initializes the Mono features and there will be a new Mono menu item in the Cheat Engine main form. But you'll notice if you use [Link] in some Lua script, the Mono menu item doesn't show up. With Mono we want to us [Link] to open the process or use [Link] to initialize the Mono features. The main thing to note is it takes a process ID (number), not a process name (string). Then we just need to use [Link] to activate the Mono features, it needs to be called after attaching to the process (after the Mono features are initialized).

Code: Select all

--[============================================================[
 Process : Cuphead.exe
 Game Version : 5.6.2.10718
 CE Version : 6.7
]============================================================]--
PROCESS_NAME = 'Cuphead.exe'
GAME_TITLE = 'Cuphead'
-- GAME_VERSION = '5.6.2.10718'
local autoAttachTimerInterval = 100
local autoAttachTimerTicks = 0
local autoAttachTimerTickMax = 5000
local autoAttachTimer = nil
local function autoAttachTimer_tick(timer)
 if autoAttachTimerTickMax > 0 and autoAttachTimerTicks >= autoAttachTimerTickMax then
 timer.destroy()
 end
 if getProcessIDFromProcessName(PROCESS_NAME) ~= nil then
 timer.destroy()
 --openProcess(PROCESS_NAME)
 mono_OpenProcess(getProcessIDFromProcessName(PROCESS_NAME))
 local InjectedMono = LaunchMonoDataCollector()
 if InjectedMono and InjectedMono ~= 0 then
 print(string.format('Mono Features Enabled: %X', InjectedMono))
 end
 end
 autoAttachTimerTicks = autoAttachTimerTicks + 1
end
autoAttachTimer = createTimer(MainForm)
autoAttachTimer.Interval = autoAttachTimerInterval
autoAttachTimer.OnTimer = autoAttachTimer_tick
Or We could just use an Auto Assembler script and nest other scripts under it, and we would only need to check for process and initialize the Mono features.

Code: Select all

[ENABLE]
{$lua}
if syntaxcheck then return end
if process and readInteger(process) ~= 0 then
 mono_initialize()
 LaunchMonoDataCollector()
else
 local msg = 'No process detected.'
 print(msg)
 error(msg)
end
{$asm}
[DISABLE]


Working with Mono in scripts

So let's say we already found health with traditional value scanning. If you have the Mono features enabled and setup an injection script then you will see addresses like this [ICODE]PlayerStatsManager:TakeDamage+ABC[/ICODE] instead of just a game plus offset address.

[Link]



So if we setup a script we can use the Mono address to make if more robust to deal with game updates better.

Code: Select all

{$STRICT}
define(bytes,89 47 60)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
assert(PlayerStatsManager:TakeDamage+8A, bytes)
PlayerStatsManager:TakeDamage+8A:
 nop
 nop
 nop
////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
PlayerStatsManager:TakeDamage+8A:
 db bytes
 // mov [edi+60],eax
But if we try to enable this script before the player takes damage, then you will find it won't enable. So let's fix that.



So fist we need to understand why scripts using Mono addresses don't enable before some given action. Well in short, Mono uses a [Link] compiler. [Link] compilation (a.k.a.: dynamic translation or run-time compilation), involves compilation during execution of a program (at run time) rather than prior to execution. So to get the game to JIT (compile) the code we need to preform some action, for the above code we have to take damage. So how do we JIT the code, we can use [Link] with [Link] in the scripts.



JIT the method

You can JIT a method in the [Link] by right clicking on a selected method.

[Link]



This will JIT the method and open the memory viewer at the methods start.

[Link]



Scripted JITting

Or we can setup a script to JIT the method.

Code: Select all

{$STRICT}
define(bytes,89 47 60)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
{$lua}
if syntaxcheck then return end
if LaunchMonoDataCollector() ~= 0 then
 local mId = mono_findMethod('Assembly-CSharp', 'PlayerStatsManager', 'TakeDamage')
 --local mId = mono_findMethod('', 'PlayerStatsManager', 'TakeDamage') ---- This also works
 mono_compile_method(mId)
end
{$asm}

assert(PlayerStatsManager:TakeDamage+8A, bytes)
PlayerStatsManager:TakeDamage+8A:
 nop
 nop
 nop

////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
PlayerStatsManager:TakeDamage+8A:
 db bytes
 // mov [edi+60],eax
With this we can just enable the script after the Mono features have been enabled.





Make method only return

We could also try to just make the method return with out doing any thing.

[Link]

[Link]

Code: Select all

{$STRICT}
define(bytes,55)
////
//// ------------------------------ ENABLE ------------------------------
[ENABLE]
{$lua}
if syntaxcheck then return end
if LaunchMonoDataCollector() ~= 0 then
 local mId = mono_findMethod('Assembly-CSharp', 'PlayerStatsManager', 'TakeDamage')
 --local mId = mono_findMethod('', 'PlayerStatsManager', 'TakeDamage') ---- This also works
 mono_compile_method(mId)
end
{$asm}

assert(PlayerStatsManager:TakeDamage, bytes)
PlayerStatsManager:TakeDamage:
 ret

////
//// ------------------------------ DISABLE ------------------------------
[DISABLE]
PlayerStatsManager:TakeDamage:
 db bytes
 // push ebp


Finding the Namespace

We can use [Link] with [Link] in the Lua Engine to get the Namespace.

Code: Select all

local mID = mono_getJitInfo(getAddress('PlayerStatsManager:TakeDamage')).method
local cID = mono_method_getClass(mID)
print('Namespace: ', '"' .. mono_class_getNamespace(cID) .. '"')
But this returns an empty Namespace, and it turns out [Link] will tend to work with an empty Namespace. Note: Most stuff in Mono games will be in the Assembly-CSharp Namespace.

See also
  • [Link]
  • [Link]
  • [Link]
  • [Link]
    • [Link]
  • [Link]

Post Reply

Who is online

Users browsing this forum: No registered users