I used DataSource
object from ..\autorun\dotnetinfo.lua
to get more convenient way (for me) to hack games that support mono features of CE (e.g. Unity).
Features:
-
mono_activate()
- replaces SymbolLookupCallback to get ability to find methods of nested mono classes (e.g. ParentClass+ChildClass:MethodOfChildClass
)
-
mono_AOBScanUnique(aob,mono_symbol)
- search for AOB withing the mono method memory region
-
mono_register(new_symbol, aob, mono_symbol, offset)
- Registers <new_symbol> for <aob> near <mono_symbol> with <offset> if needed
Requirements:
API code:
function init_DotNetInfo()
-- I didn't found a better way to access "dotnetinfo.lua" local functions
miDotNetInfoClick(getMainForm()) -- opens ".Net Info" form
df.Hide() -- hides just opened ".Net Info" form
end
--------------------------------------------------------------------------------
function mono_findClassEx(namespace, classname)
if namespace==nil then
--print("[mono_findClassEx]: Invalid parameters!" .. namespace .. "." .. classname)
else
if classname==nil then
classname=namespace
namespace=''
end
if DataSource.Domains==nil then
--print("[mono_findClassEx]: DataSource is not initialized! Open .Net Info once")
init_DotNetInfo()
end
for _, Domain in ipairs(DataSource.Domains) do
if Domain.Images == nil then
DataSource.getImages(Domain)
end
for _, Image in ipairs(Domain.Images) do
if Image.Classes == nil then
Image.Classes = {}
Image.Classes.Busy = true
DataSource.getClasses(Image)
Image.Classes.Busy = nil
end
for _, Class in ipairs(Image.Classes) do
if Class.FullName == classname then return Class.Handle end
end
end
end
end
return nil
end
--------------------------------------------------------------------------------
function mono_findMethodEx(namespace, classname, methodname)
if namespace==nil or classname==nil then
--print("[mono_findMethodEx]: Invalid parameters! " .. namespace .. "." .. classname .. ":" .. methodname)
else
if methodname==nil then
methodname=classname
classname=namespace
namespace=''
end
local class = mono_findClassEx(namespace, classname)
if class==nil or class==0 then
--print("[mono_findMethodEx]: Class not found! " .. namespace .. "." .. classname)
else
return mono_class_findMethod(class, methodname)
end
end
return nil
end
--------------------------------------------------------------------------------
function mono_symbolLookupCallbackEx(symbol)
local namespace, classname, methodname = SplitDotNetName(symbol)
if (methodname=='') or (classname=='') then
--print("[mono_symbolLookupCallbackEx]: Invalid parameters! " .. namespace .. "." .. classname .. ":" .. methodname)
else
if monopipe == nil or monopipe.IL2CPP then
--print("[mono_symbolLookupCallbackEx]: Unable to use mono features.")
else
local method = mono_findMethodEx(namespace, classname, methodname)
if method==nil or method==0 then
--print("[mono_symbolLookupCallbackEx]: Method not found! " .. namespace .. "." .. classname .. ":" .. methodname)
else
local methodaddress = mono_compile_method(method)
if methodaddress == nil or methodaddress == 0 then
--print("[mono_symbolLookupCallbackEx]: mono_compile_method error!")
else
return methodaddress
end
end
end
end
return nil
end
--------------------------------------------------------------------------------
function mono_activate()
if getOpenedProcessID()==0 then
print("[mono_activate]: No process opened!")
else
if monopipe==nil and LaunchMonoDataCollector()==0 then
print("[mono_activate]: LaunchMonoDataCollector error!")
else
if mono_SymbolLookupID~=nil then
unregisterSymbolLookupCallback(mono_SymbolLookupID)
mono_SymbolLookupID=nil
end
mono_SymbolLookupID=registerSymbolLookupCallback(mono_symbolLookupCallbackEx, slNotSymbol)
end
end
end
--------------------------------------------------------------------------------
function mono_deactivate()
if monopipe then
monopipe.OnTimeout()
end
end
--------------------------------------------------------------------------------
-- Scans the memory near <mono_symbol> for <aob> and returns it's address
function mono_AOBScanUnique(aob,mono_symbol)
local result = nil
local mono_address = mono_symbolLookupCallbackEx(mono_symbol)
if mono_address == nil then
print("[mono_AOBScanUnique]: Mono symbol not found! " .. mono_symbol)
else
local ji = mono_getJitInfo(mono_address)
local start = ji.code_start -- Method start address
local stop = start + ji.code_size -- Size of the method
local protectionFlags = "*X*C*W"
local alignmentType = fsmNotAligned
local alignmentParam = nil
local isHexadecimalInput = true
local isNotABinaryString = true
local isunicodescan = false
local iscasesensitive = false
local ms = createMemScan()
ms.firstScan(soExactValue, vtByteArray, nil, aob, nil, start, stop,
protectionFlags, alignmentType, alignmentParam,
isHexadecimalInput, isNotABinaryString, isunicodescan, iscasesensitive)
ms.waitTillDone()
local fl = createFoundList(ms)
fl.initialize()
if ms.FoundList.getCount()==0 then
print("[mono_aobscan]: AOB [" .. aob .. "] not found near " .. mono_symbol)
else
if fl.getCount()>1 then
print("[mono_aobscan]: AOB [" .. aob .. "] is not unique near " .. mono_symbol)
else
result = fl[0]
end
end
fl.deinitialize()
ms.destroy()
end
return result
end
--------------------------------------------------------------------------------
-- Registers <new_symbol> for <aob> near <mono_symbol> with <offset> if needed
function mono_register(new_symbol, aob, mono_symbol, offset)
if offset == nil then offset = 0 end
local aob_address = mono_AOBScanUnique(aob, mono_symbol)
unregisterSymbol(new_symbol)
if aob_address ~= nil then
registerSymbol(new_symbol,tonumber(aob_address,16)+offset)
end
end
--------------------------------------------------------------------------------
Example usage:
Code: Select all
OpenProcess("OxygenNotIncluded.exe")
mono_activate()
mono_register("InjectionPoint", "F3 0F 10 40 48", "StaminaMonitor+Instance:NeedsToSleep")
mono_deactivate()
Links on this topic: