Cheat Engine Forum Index Cheat Engine
The Official Site of Cheat Engine
 FAQFAQ   SearchSearch   MemberlistMemberlist   UsergroupsUsergroups   RegisterRegister 
 ProfileProfile   Log in to check your private messagesLog in to check your private messages   Log inLog in 

Q: How to use Mono to get offsets

Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking
View previous topic :: View next topic  
Author Message
How do I cheat?
Reputation: 0

Joined: 02 May 2017
Posts: 6

PostPosted: Wed Jan 31, 2018 11:45 pm    Post subject: Q: How to use Mono to get offsets Reply with quote

What I Would Like To Know
Explain to me like I'm five. Full context examples. I have minimal CE/Lua experience.

I want to use mono dissect features to find offsets to member variables in a class. Alignment shifts with game updates, but the variable names stay the same. Mono features display the offset next to the name, so obviously the information is there and I just don't know how to use it. I'd like to use a technique that eliminates the typewriter monkey work I'm doing (manually retargetting all offsets every game update, like an idiot).

Also, if such a technique exists, I'd like an example on how to use it on multiple classes together (e.g. class A contains ptr var to class B which has member var I want, I need to get offsets for both A and B and use them in the same table entry)

Some Background
My knowledge of CE is limited to manual scanning & AA AOB func injection. So I've been using some simple AOBscan stuff to get base addresses of class instances I care about. I end up with a big table all based on one address with manually entered offsets to arrive at the member variables (and other classes) I care about. The issue is that it's entirely manual. If the game updates, it can shift all of my offsets by 4 bytes, and then I spent a bunch of time pressing arrows and increment all the offsets in my table.

Mono dissected classes show "offset: variable name" for members within the class. So clearly the information is there... I just don't know how to get and use it programmatically.
Back to top
View user's profile Send private message
Grandmaster Cheater
Reputation: 27

Joined: 01 Oct 2008
Posts: 676

PostPosted: Thu Feb 01, 2018 4:58 am    Post subject: Reply with quote

May check ce dir autorun/monoscript.lua function mono_class_enumFields,
previous version accept one input parameter of the monoclass (which expected to be a number see later),
recent versionn add 2nd parameter to also collect all parent's (and recursively grandparents) fields.

The result is a table t of the form:

t[1] = {
  name = 'health',
  offset = 0x120,
  type = <vtType for use with CE memroy record>,
  flags = < number as bit fields ? >,
  isStatic = false <true of false>,
  isConst = <true of false>,
  ... some other fields
t[2] = {
  name = 'mana',
  offset = 0x140,
  isStatic = false,
t[40] = {
  name = 'EntityList',
  offset = 0x10,
  isStatic = true,

-- you refer the table field like
local t = mono_class_enumFields(class)
for i=1,#t do
  print(string.format("%3d(th) fileds - name: %s offset at 0x%X",i, t[i].name, t[i].offset))

Note that the order of the entries is not sort by offsets, and it include both static fields and instance fields (or may be some other thing) which may need to separated using the flag/isStatic/isConst properties (there is example code on how in monoscript.lua ) .

Also in some obfuscated assembly, they can have same 'name' (but different monotype) for different entries, which make following suggestion not possible.

This raw table may not easily use in AA or other lua script.
Usually we only need the name and its associated offset.
We can construct another table like this :

  instanceTable = {
  health = 0x120,
  man = 0x140,
  staticTable = {
  EntityList = 0x10

Since CE 6.7, we can refer simple Lua expression (in lua global context) in AA prefix a '$', so if above instanceTable is made before hand and set as a global variable, we should be write something like :

  lea  rax, [rcx + $]

However the AA in some line (probably during parsing assembler instruction ) convert the letter following 1st word after '$' (instanceTable here) into upper case, ie. it see $ as lua expression $instanceTable.HEALTH.
But sometime you can use $ without the upper case conversion.
For this I added a field on following implementation to refer the upper case field.


Now about the input parameter 'class', it is expected as a number, if we want to refer the class by name, we need some conversion.

A class-name may include 2 part, namespace and the class name alone.
Note that there is other format, eg. nested class, we only consider simple class that can be determined by namespace and class name.

CE Symbol list for mono process include this format:
namespace:classname (if namespace present)
classname (if namespace is Default)
or just
but some mono function expect like
namespace.classname (':' is replaced as '.')
or they are input as separated parameter.

One way to convert the named class (in string ) to the class number is using
mono_findClass(namespace, classname)

The following is a quick function to obtain the instance table of a named class:

function monoGetFields(class, namespace)
  if not readInteger'mono_domain_get' or LaunchMonoDataCollector()==0 then
    return nil,"can't attach mono"
  if type(class)=='string' then
    if class:find':' then namespace,class = class:match"([^:]+):([^:]+)"end
    if class then class = mono_findClass(namespace or '', class)end
  if type(class)~='number' or class==0 then
    return nil,'class not known '..tostring(class)
  local ok,fs = pcall(mono_class_enumFields, class, true) -- easity cause error?
  if not ok then return nil,tostring(fs)end
  local inst, static = {__={}},{__={}} -- the tables we want
  for i=1,#fs do
    local e, name, offset = fs[i], fs[i].name, fs[i].offset
    if not e.isConst then
      if e.isStatic then
        static.__[name:upper()] = offset -- work around for AA upper case conversion
        inst.__[name:upper()] = offset -- work around for AA upper case conversion
  return inst, static

For the AA upper case conversion:
if this not work

  lea  rax, [rcx + $]


  lea  rax, [rcx + $]
// internally see instanceTable.__.HEALTH

A sample script (Creeper World 3 ):

-- must be global variables
crcI, crcS = monoGetFields'SevenZip:CRC'


luacall(print('from luacall:',crcS.Table, crcI._value))


lea  rax,[rcx+$crcS.__.Table]
lea  rax,[rcx+$crcI.__._value]
//lea  rax,[rcx+$crcI._value] // not work due to AA upper conversion
dq $crcS.Table, $crcI._value, Symbol /// but in some case it do work


Sorry if it is incomprehension due to age, I seemingly often speak nonsense here for viewers of any age anyway~

- Retarded.
Back to top
View user's profile Send private message
How do I cheat?
Reputation: 0

Joined: 02 May 2017
Posts: 6

PostPosted: Fri Feb 02, 2018 7:08 am    Post subject: Reply with quote


I've learned a lot from this. Regarding both CE and Lua itself. Your code and example was a big help. I admit that it was confusing at first, but I understand now (through trial and error of my own ignorance). I'll continue to experiment.

This was a very useful explanation. Thank you!
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> General Gamehacking All times are GMT - 6 Hours
Page 1 of 1

Jump to:  
You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot vote in polls in this forum
You cannot attach files in this forum
You can download files in this forum

Powered by phpBB © 2001, 2005 phpBB Group

CE Wiki   IRC (#CEF)   Twitter
Third party websites