dotnetinfo utils for unity games

A general discussion area specifically for hacking, memory scan, injection, and debugging discussions.


Post Reply
User avatar
mece
Table Maker
Table Maker
Apprentice Hacker
Apprentice Hacker
Posts: 61
Joined: Sat Jul 23, 2022 9:21 am
Answers: 0
x 74
Contact:

dotnetinfo utils for unity games

Post by mece »

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:

  • Cheat Engine 7.4

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:

Last edited by mece on Tue Aug 23, 2022 2:40 pm, edited 1 time in total.

User avatar
justNOPing
Cheater
Cheater
Posts: 23
Joined: Mon Aug 08, 2022 10:02 am
Answers: 0
Location: newmem
x 15

Re: dotnetinfo utils for unity games

Post by justNOPing »

That's actually really cool but can you fix the formatting, buddy?


User avatar
mece
Table Maker
Table Maker
Apprentice Hacker
Apprentice Hacker
Posts: 61
Joined: Sat Jul 23, 2022 9:21 am
Answers: 0
x 74
Contact:

Re: dotnetinfo utils for unity games

Post by mece »

Thanks!
For now you can use the pastebin copy as an alternative:
The formatting will be fixed together with {codebox} macro.


User avatar
bbfox
Table Master
Table Master
Journeyman Hacker
Journeyman Hacker
Posts: 180
Joined: Sat Jul 23, 2022 8:59 am
Answers: 0
x 402

Re: dotnetinfo utils for unity games

Post by bbfox »

Thaks!
I tried this before. It will have document retaliation, if past data without a login. Have to register an account.


I create tables to suit my preferences. Table is free to use, but need to leave the author's name and source URL: https://opencheattables.com.
Table will not be up-to-date. Feel free to modify it, but kindly provide credit to the source.


User avatar
Seneekikaant
Table Maker
Table Maker
Apprentice Hacker
Apprentice Hacker
Posts: 88
Joined: Thu Jul 21, 2022 6:38 am
Answers: 0
Location: Australia
x 109
Contact:

Re: dotnetinfo utils for unity games

Post by Seneekikaant »

justNOPing wrote: Thu Aug 18, 2022 7:42 pm

That's actually really cool but can you fix the formatting, buddy?

A bit late to the party here, but the formatting issue was due to the bbcodes not fully implemented. I was surprised to see it was still an issue, I guess the older posts from before I got them up need to be edited and resubmitted for the formatting to take place. it looks much nicer now

A naked man fears no pickpocket


User avatar
J1327
Donor
Donor
Novice Hacker
Novice Hacker
Posts: 42
Joined: Mon Jul 25, 2022 5:00 pm
Answers: 0
Location: Baltic States
x 46

Re: dotnetinfo utils for unity games

Post by J1327 »

Finally got some time to say my experience about this:
Picking up directly, this Ex method cannot resolve some class /r methods what not Ex can.
I mean sure with Ex method app doesn’t crash and you do not need debug exceptions alike C5.
Yet…

for example from 55 images and their classes (from search form) :
Not Ex method found 200+
while this Ex method found 50+

So Ex method doesn't find most of classes and their method -- YET, again this method it is most safest approach (if you experiencing a lot of crashes during MONO info lookup...)...

So…

Edited Ex method that should found equally same as not Ex and do not cause app to crash…

Code: Select all

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 = ''
        else
            if not namespace == "" or not namespace == nil then
                classname = namespace .. "." .. classname
            end -- fixed issue when namespace is provided.
        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
                if namespace then
                    for _, Class in ipairs(Image.Classes) do -- fails here
                        -- catches first found Class if no namespace is provided for code flow.
                        -- this fixes and create new potential problem. Yet not all important classes has namespace.
                        if Class.FullName == classname or Class.Name == classname then
                            return Class.Handle
                        end
                    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

return mono_symbolLookupCallbackEx("") -- Class:method

….

Also something mixed , From .NET Info form --> Find --> Find class to Classname:method as text file (I should later merge this into my project) -- Using this Ex project in combine... (to output text file just it takes time minute or so, depending on search result count (slow at beginning)..)


local function getFormbyName(string)
    for i = 0, getFormCount() - 1 do
        local root = getForm(i)
        local root_name = root.Name
        if root_name == string then
            return root;
        end
    end
    if root_name ~= string then
        return nil
    end
end

local function local_get_mono_table() -- gets alldata
    if not process then
        return
    end
    l = mono_enumDomains()
    a = nil
    b = nil
    c = nil
    a = mono_enumAssemblies(l)
    b = {}
    -- c = {}
    for i = 1, #a do
        local s = a[i]
        local img = mono_getImageFromAssembly(s)
        tid = mono_image_enumClasses(img)

    for j = 1, #tid do
        local cID = tid[j].class
        local nID = tid[j].namespace

        local methods = mono_class_enumMethods(cID)

        for u = 1, #methods do

            local mstring
            if tid[j].namespace == "" then
                mstring = tid[j].classname .. ":" .. methods[u].name
            else
                mstring = tid[j].namespace .. "." .. tid[j].classname .. ":" .. methods[u].name
            end
            methods[u].lookupString = mstring
        end
        tid[j].methods = methods
        local fields = mono_class_enumFields(cID)
        tid[j].fields = fields
    end

    table.insert(b, {
        root = s,
        img = img,
        classes = tid
    })
end
return b -- , c
end

if not methods then
    methods = local_get_mono_table()
end
searchwin = getFormbyName("frmDotNetSearch")
if not searchwin then return error("Couldn't find Find Class .NET Info form") end
-- print(searchwin.lvResults.Items.Count) -- class count
local resultlist = createStringList()
for i = 0, searchwin.lvResults.Items.Count - 1 do
    for a = 1, #methods do

        if searchwin.lvResults.Items[i].Caption == mono_image_get_name(methods[a].img) then

            for b = 1, #methods[a].classes do
                local stringa = methods[a].classes[b].classname
                local stringb = searchwin.lvResults.Items[i].SubItems.Text:gsub("^%s*(.-)%s*$", "%1"):sub(1, -1)
                if (stringa == stringb) then
                    for c = 1, #methods[a].classes[b].methods do

                        local check = mono_symbolLookupCallbackEx(methods[a].classes[b].methods[c].lookupString)
                        if check then
                            resultlist.add(methods[a].classes[b].methods[c].lookupString)
                        end

                    end
                    break
                end

            end
            break
        end
    end
end

local sd = createSaveDialog()
sd.defaultExt = '.txt'
sd.Filter = [[Text File (*.txt)|*.txt]]
if sd.Execute() then
    resultlist.saveToFile(sd.FileName)
end
searchwin.destroy()

All this for unity mono games.

🙃
Ṯ̸͋͠H̷̻́Ē̵̦̇R̴̛̠̞̾E̷̥̗̎̾ ̷̩̽̂Ì̵̱S̵̲͘ ̷̝̝̽͆S̵̯̒T̷̩͈̃͑Î̶̯̟Ļ̴̬̈L̴̘̱̏̒ ̵̨̟̈́͠T̵͓͎͐I̶̥͈̽M̷̡̛͒E̶͙͗


Post Reply