|
Cheat Engine The Official Site of Cheat Engine
|
View previous topic :: View next topic |
Author |
Message |
Bardez How do I cheat? Reputation: 0
Joined: 17 Nov 2018 Posts: 4
|
Posted: Sat Nov 17, 2018 10:09 pm Post subject: Referencing Mono structures |
|
|
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 |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Sun Nov 18, 2018 8:48 am Post subject: |
|
|
>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
_________________
|
|
Back to top |
|
|
Bardez How do I cheat? Reputation: 0
Joined: 17 Nov 2018 Posts: 4
|
Posted: Sun Nov 18, 2018 12:18 pm Post subject: |
|
|
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 |
|
|
FreeER Grandmaster Cheater Supreme Reputation: 53
Joined: 09 Aug 2013 Posts: 1091
|
Posted: Sun Nov 18, 2018 7:00 pm Post subject: |
|
|
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
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
_________________
|
|
Back to top |
|
|
Bardez How do I cheat? Reputation: 0
Joined: 17 Nov 2018 Posts: 4
|
Posted: Mon Nov 19, 2018 12:00 am Post subject: |
|
|
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 |
|
|
Bardez How do I cheat? Reputation: 0
Joined: 17 Nov 2018 Posts: 4
|
Posted: Mon Nov 19, 2018 11:14 pm Post subject: |
|
|
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 |
|
|
panraven Grandmaster Cheater Reputation: 55
Joined: 01 Oct 2008 Posts: 942
|
Posted: Tue Nov 20, 2018 1:09 am Post subject: |
|
|
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 |
|
|
|
|
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
|
|