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 


Referencing Mono structures

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

Joined: 17 Nov 2018
Posts: 4

PostPosted: Sat Nov 17, 2018 10:09 pm    Post subject: Referencing Mono structures Reply with quote

I'm somewhat new to Lua scripting inside of Cheat Engine. I am trying to use Mono features inside of CE scripts to load structure definition(s) and then inside the same script be able to reference that found structure definition.

i.e.:

Code:
{$lua}
monoAA_GETMONOSTRUCT("Player")


I have tried many variants on the above, such as

Code:
{$lua}
return monoAA_GETMONOSTRUCT("Player")



Code:
{$lua}
local temp = monoAA_GETMONOSTRUCT("Player")
print(1 + temp.Field)


Code:
{$lua}
return monoAA_GETMONOSTRUCT("Player")
{$asm}

{$lua}
print(1 + Player.Field)


... you likely get the idea. I can verify that Player is found because if I search in the interactive Lua Engine window, I get a result of the found Player struct.

I just... don't understand how I am supposed to reference the struct and its offsets inside of the same Lua script.

Any help?

If I am going about this all wrong, please tell me. All I really want to do is:
Code:
FindSpecificMonoClassesAndRegisterThemSomehow()
AddFieldsForClassesFoundToTheAddressList()
Back to top
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Sun Nov 18, 2018 8:48 am    Post subject: Reply with quote

>AddFieldsForClassesFoundToTheAddressList()

Well, monoAA_GETMONOSTRUCT just provides offsets from the base of the struct for the fields that you could use eg. mov [rbx+PLAYER.health], #100. For actual addresses you have to first find all of the instances of that struct/class so that you can add the offsets to the base address. Look into mono_class_findInstancesOfClassListOnly(domain, klass) note that this essentially just does a scan for the vtable pointer and returns anything it finds assuming it's an actual instance.

So, scan, maybe try and verify somehow, add to addresslist or whatever.





With my extension here you can essentially just call a function and it'll create all the memory records for you, though since it's designed for the user/hacker to quickly generate them from CE feel free to yank out just the necessary functions and give credit rather than require people use an extension they don't otherwise need.

For Streets of Rogue I made a script like this that the user can run to update the struct in case of a game update (since the struct offsets are used in the addresses rather than hardcoded):
Code:
{$lua}
[ENABLE]
if syntaxcheck then return end
error('HEY DO YOU REALLY WANT THIS?') -- must remove/comment in order to run
local player = getAddressSafe('player') -- get player instance address from player symbol or whatever user overwrites
if not player or player == 0 then error('I need a player address!') end
local realaddress, classaddress, classname=mono_object_findRealStartOfObject(player)
if not realaddress or not classaddress then error("Invalid player address!") end

local ags = getStructure(7)
assert(ags.Name == 'Agent','Hey thats the wrong struct!')

for i=s.Count-1,0,-1 do
  s.Element[i].destroy()
end
--(structToAddTo, monoklass, recursive, includeStaticFields, structmap, makeglobal)
local newags = monoform_exportStructInternal(ags, classaddress, true, false, {}, false)
[DISABLE]

Basically it takes an address of an instance of the object (so you need to find at least one real instance to update), deletes everything in the old structure (id hardcoded as 7 in this case with a basic name check for safety) then calls some mono functions to get the class and export mono's struct definition into the global struct that everything was just deleted from. It could probably just use findClass rather than taking an instance address but... that's not what I did back when I made it lol

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
Bardez
How do I cheat?
Reputation: 0

Joined: 17 Nov 2018
Posts: 4

PostPosted: Sun Nov 18, 2018 12:18 pm    Post subject: Reply with quote

Perhaps I'm missing something, but I have absolutely zero interest in writing assembler, nor referencing addresses in assembler.

Using `mono_class_findInstancesOfClassListOnly` I have addresses, and I would love to test them... not referencing any constant values. That is why I would like to load the structure definition dynamically, to insulate from patches changing data, offsets, etc.

So, presuming that I have an address or list thereof in memory that appear to be valid, active objects in memory (and not waiting for the garbage collector to dispose of them), I'd like to actually be able to make those tests to see what instance is valid and what is not.

My problem is being able to access the offsets of known, named fields in the valid, returned structure definition. Because inside of Lua, I do not seem to be able to access the found/generated definition. And I don't really want to use assembler.
Back to top
View user's profile Send private message
FreeER
Grandmaster Cheater Supreme
Reputation: 53

Joined: 09 Aug 2013
Posts: 1091

PostPosted: Sun Nov 18, 2018 7:00 pm    Post subject: Reply with quote

Quote:
I have absolutely zero interest in writing assembler, nor referencing addresses in assembler

Well "CE scripts" leaves it open so I didn't want to assume that was the case Smile

monoAA_GETMONOSTRUCT is designed to return a string that when run as AA code will define a struct accessible in that AA script as struct.element as the offset for use in assembly

Quote:
I would like to load the structure definition dynamically

which is why I gave a code example I'd actually used in a table (for myself but still) to do that with monoform_exportStructInternal, while the example code used a global struct because memory records in the address list needed to use it, you could just create a new one only used by code get the offsets from it. Though I don't think it has a way to get an element by name... so you'd have to iterate through the elements and check the name. Or perhaps if monoform_exportStructInternal was passed true for the last/makeglobal parameter then you could use getAddress('structname.elementname') and just let CE handling getting it that way.


I haven't played around with structs too much so there's a lot I don't know, just gave some info and example code that I could.

if you print the result of monoAA_GETMONOSTRUCT you can see something like
Code:
struct Flockie
vtable: resb 64
myFlock:  resb 4
battlingWith:  resb 4
colli:  resb 4
allyLibrary:  resb 4
posFromCenterOfFlock:  resb 8
ends
but that won't be available to lua even when returned, though I suppose you could parse it into a table if you wished,some further playing with the code from monoscript.lua gives
Code:
function getFields(param)
  -- simplified 'classname' or 'namespace:classname' input
  -- obviously you could just change the code to pass findClass's result
  local namespace,classname = param:match('(%w+):?(%w*)')
  if not classname or classname == '' then namespace, classname = '', namespace end
  local class=mono_findClass(namespace, classname)
  local fields=mono_class_enumFields(class)
  local result = {}
  for _, field in ipairs(fields) do
    result[field.name] = field.offset
  end
  return result
end
Though at a glance this won't give any fields from parent classes, I think the previously given example for monoform_exportStructInternal can be simplified to
Code:
function getFields(klass)
  local struct = monoform_exportStructInternal(createStructure(''), klass,
    true --[[recursive]], false --[[not static]], {'some struct map thing'}, false --[[not global]])
  local fields = {}
  for i=0, struct.Count-1 do
    local e = struct.getElement(i)
    fields[e.name] = e.offset
  end
  return fields
end


not really sure how to actually verify the results from mono_class_findInstancesOfClassListOnly however, though the most basic would be to check that a few known pointers aren't 0 I guess /shrug

_________________
https://github.com/FreeER/ has a few CE related repos
Back to top
View user's profile Send private message
Bardez
How do I cheat?
Reputation: 0

Joined: 17 Nov 2018
Posts: 4

PostPosted: Mon Nov 19, 2018 12:00 am    Post subject: Reply with quote

FreeER wrote:
but that won't be available to lua even when returned


I think that this is exactly what I am/was missing.

FreeER wrote:
monoAA_GETMONOSTRUCT is designed to return a string that when run as AA code will define a struct accessible in that AA script as struct.element as the offset for use in assembly


Sumbitch. I totally see that, now. The string is generated assembler code and defines the struct in assembler. Thus, it is presumably compiled and ran with all of the return statements I have seen referencing the method. I suppose, then, that the answer to my original question is that `monoAA_GETMONOSTRUCT` only ever registers the structure, fields, and offsets into assembler code sections, and never into Lua sections. Similarly, the structure definition if captured in a local variable inside of a Lua section of code --even when it prints reasonable output as proof that it was captured-- doesn't exactly contain the field offsets which one could easily parse and package into an array/dictionary/set/etc.

I will take a look at your `getFields` definition, as that was the other path I was starting to follow, before the structure definitions jumped out at me.
Back to top
View user's profile Send private message
Bardez
How do I cheat?
Reputation: 0

Joined: 17 Nov 2018
Posts: 4

PostPosted: Mon Nov 19, 2018 11:14 pm    Post subject: Reply with quote

For what it is worth, I ended up going with the following:


Code:
--function to return a table of fields and their offsets for the specified class name
--params:
--    namespace: namespace of the class to get a structure definition for
--    className: name of the class to get a structure definition for
function GetFields(namespace, className)
   local classId = mono_findClass(namespace, className)
   local struct = monoform_exportStructInternal(createStructure(''), classId,
      true --[[recursive]], false --[[not static]], {'some struct map thing'}, false --[[not global]])

   local fields = {}
   for i=0, struct.Count-1 do
      local e = struct.getElement(i)
      fields[e.name] = e.offset
   end
   return fields
end


Something to beware of, dear readers whom seek The Wisdom of the Ancients (xkcd reference -- I can't post URLs yet), is that .NET has some weird names to be wary of. Auto-Properties are great for developers, but they leave some weird names in the intermediate language:

Code:
<GameId>k__BackingField   312
<Money>k__BackingField   360


Literally, "<GameId>k__BackingField" and "<Money>k__BackingField" are field names, and you should probably reference the field table with
Code:
fields["<GameId>k__BackingField"]
rather than attempt to use
Code:
fields.<GameId>k__BackingField
Back to top
View user's profile Send private message
panraven
Grandmaster Cheater
Reputation: 55

Joined: 01 Oct 2008
Posts: 942

PostPosted: Tue Nov 20, 2018 1:09 am    Post subject: Reply with quote

Without worrying name crash, this may remove the burden of "backing field" or alike.
Code:

...
      local e = struct.getElement(i)
      local e_name = e.name
      e_name = e_name:match"<([_%w]+)>" or e_name
      fields[e_name] = e.offset
...

_________________
- Retarded.
Back to top
View user's profile Send private message
Display posts from previous:   
Post new topic   Reply to topic    Cheat Engine Forum Index -> Cheat Engine Lua Scripting 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