[SOLVED] Mono Features: How to create an instance of a Mono Class?

Want Cheat Engine to do something specific and no idea how to do that, ask here. (From simple scripts to full trainers and extensions)
Post Reply
User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

[SOLVED] Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

Solution
To create an instance of a Mono Class, use mono_object_new(klass) where klass is the token of the class that you want to create its instance.
For example, if you want to create an instance of class PlayerStats from namespace GameBattle:

Code: Select all

local classId = mono_findClass("GameBattle", "PlayerStats")
local instanceAddress = mono_object_new(classId) -- this function returns the address of created class's instance
I can read below for the problem that I encountered. To solve it, I use [Link] by building from the source on GitHub instead of using CE 7.5 from the latest official release. There is a problem in MonoDataCollector64.dll from CE 7.5 official release and using MonoDataCollector64.dll from CE 7.5.1 fixed my problem.
---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Problem
I am hacking a Mono game and I want to create an instance of a Mono class ParameterChanger. After researching, I learned that to create an instance of a Mono class, we have to:
  1. Allocate memory for the instance of the Mono Class
  2. Invoking the constructor method for that instance
I know how to invoke the constructor method, but I do not know how to deal with the first step. My question is, how to properly allocate memory for the instance of a Mono Class?
My attempts
  1. Do we manually allocate memory by using a Lua function like allocateMemory(size) and make sure that the size of allocated memory is exactly equal to or bigger than the total size of all fields of the Mono Class? Will this work?
  2. Can we use the function mono_object_new(kclass)? I cannot find the documentation for this Lua function in monoscript, but after researching and referencing the Mono project for embedding C/C++, it seems that this function is used to allocate memory for an instance of a Mono Class, given the id of the class.
What I experienced and confused me
  1. For the first approach, Let's say the size of an instance of Mono Class ParamterChanger is 30 bytes. I allocated more than 30 bytes and call the constructor of the class ParameterChanger on the address of allocated memory, then dissected data structure of that address to inspect the internal data, and it worked as I expected
    • But it is safe to do this?
    • Or do we have to allocate memory with a size exactly equal to the size of an instance of Mono Class?
  2. For the second approach, after launching Cheat Engine, the first time I run mono_object_new(classId) the monopipe crashes, then I have to activate mono feature again. After that, every call to mono_object_new(classId) won't crash monopipe and I obtain an address from the return value:
    • Why does it happen? How to fix it?
    • Does mono_object_new(classId) actually allocate memory with the right size for the instance of Mono Class internally? If it is not, what does this function do?
Last edited by -Pikachu- on Sun Jan 14, 2024 2:33 pm, edited 1 time in total.

Eric
Hall of Famer
Hall of Famer
Posts: 174
Joined: Thu Mar 02, 2017 11:01 pm
Reputation: 90

Re: Mono Features: How to create an instance of a Mono Class?

Post by Eric »

check out [Link]

User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

Re: Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

Eric, thank you for your answer. I read that Documentation before asking this question, and I stated what I am confused even after reading that documentation, and failures that I encountered for different approqches. I wonder if anyone has encountered this problem before and has a solution that works perfectly.

Eric
Hall of Famer
Hall of Famer
Posts: 174
Joined: Thu Mar 02, 2017 11:01 pm
Reputation: 90

Re: Mono Features: How to create an instance of a Mono Class?

Post by Eric »

about mono_object_new crashing, are you sure there's no other functions you're calling inbetween? And is the handle correct ?

easiest way to test:
in .net info select the class you're interested in and do:

Code: Select all

a=xxx.CurrentlyDisplayedClass.Handle
printf("classhandle=%x",a)
b=mono_object_new(a)
return printf("new object is: %x", b)
if this works, then likely your issue is with accessing the object afterwards
instead of using the menu to launch the dotnetdatacollector, launch it using lua:

Code: Select all

LaunchMonoDataCollector(false)
otherwise all objects referenced are up for grabs by the garbage collector

User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

Re: Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

Yes, I am sure. I followed what you guided me:

Code: Select all

a=xxx.CurrentlyDisplayedClass.Handle
printf("classhandle=%x",a)
b=mono_object_new(a)
return printf("new object is: %x", b)
The result is exactly what I experienced before. Executing the above code results in the following error in Lua engine:
terminating monoSymbolEnum due to timeout or error
Error:C:\Program Files\Cheat Engine 7.5\autorun\monoscript.lua:2966: attempt to index a nil value (global 'monopipe')
After that, I activated Mono Features again and then tried executing your code again, and weirdly, it worked. then tried executing the above code a few more times, and it still worked. So the root problem is, the first time I instantiate an object using mono_object_new(klass) since I started launching the game and attach CE to it, monoSymbolEnum will always terminate due to timeout of error and monopipe becomes nil, mono features are deactivated. Then, I have to activate mono features again. Since then, executing the code will always succeed, and I will always -obtain the address of the instantiated object without any error.

Here is a minimal example to reproduce my problem:
  1. Open the game, launch CE, and attach CE to that game
  2. Activate Mono Features (either doing manually via Mono menu, or using LaunchMonoDataCollector()), I tried both approaches, and they all produced the same result
  3. Activate the following code in Lua engine:

    Code: Select all

    return mono_object_new(mono_findClass("", "ParameterChanger"))
  4. I got the following error:
    terminating monoSymbolEnum due to timeout or error
    Error:C:\Program Files\Cheat Engine 7.5\autorun\monoscript.lua:2966: attempt to index a nil value (global 'monopipe')
  5. Activate the Mono features again
  6. Run the above code again
  7. Now it works, each time I activate the code, a new address will be printed in the Lua engine

Eric
Hall of Famer
Hall of Famer
Posts: 174
Joined: Thu Mar 02, 2017 11:01 pm
Reputation: 90

Re: Mono Features: How to create an instance of a Mono Class?

Post by Eric »

ok, so it's not normal mono but il2cpp. Likely it's taking more time due to the symbol enum still being done

try adding this code first:

Code: Select all

local timeout=getTickCount()+60000 --1 minute, just making sure you're not freezing forever (adjust if needed)

while monoSymbolList.FullyLoaded==false and getTickCount()<timeout do
  if inMainThread() then
    synchronize(100)
  else
    sleep(100)
  end
end

if getTickCount()>=timeout then
  print("timed out. Got to wait longer")
  return
end
(if you don't intend to use methodnames as addresses you can also disable the symbolllist enum)

User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

Re: Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

Yes, this is an IL2CPP game, not a normal Mono.
I think this is not a problem due to Symbol Enum still being done, because after I activate Mono features, I always wait until Mono Symbol Enum is fully loaded (i.e.: waiting for the progress bar at the bottom of CE main form to be completed) before actually running the code in Lua Engine. I also tried applying your guidance, but sadly, the same error still occurred. Other mono functions are still working properly, I only encounter this error when using mono_object_new. The same error happens when I try creating an instance of a class via Mono Dissector GUI. I read the underlying implementation of that feature in [Link], and internally it also uses mono_object_new to create an instance of a class.
I don't know if this also happens for other games, or if it is only specific to my game:
The first time mono_object_new is called, an error will always occur and cause Mono Features to be deactivated, but we just need to activate Mono Features again and it will work flawlessly.

Eric
Hall of Famer
Hall of Famer
Posts: 174
Joined: Thu Mar 02, 2017 11:01 pm
Reputation: 90

Re: Mono Features: How to create an instance of a Mono Class?

Post by Eric »

it could be it's this game or an il2cpp issue. But have you tried that code I posted and did it ever not timeout?

And how long does it take between the first mono_object_new and the error?

User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

Re: Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

I tried the code that you posted and it did not ever timeout. As I emphasized before, after activating Mono Features, I always wait until MonoSymbolEnum is fully loaded before actually executing my code in Lua Engine. The error occurs immediately after mono_object_new is executed. The video below demonstrates my problem:
(The video was recorded after I launched the game and attached CE to it)

User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

Re: [SOLVED] Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

Hello Eric, I managed to solve my problem by replacing MonoDataCollector64.dll and monoscript.lua in CE 7.5 latest release with the same files from CE 7.5.1 on GitHub. So I think there is a problem with MonoDataCollector64.dll in C.E 7.5 latest release when I attempt to create an instance of a class using mono_object_new(klass). I am very grateful that you spent time to guiding and helping me.

I want to ask you for clarification about the part where you said:
Instead of using the menu to launch the dotnetdatacollector, launch it using lua:

Code: Select all

LaunchMonoDataCollector(false)
otherwise, all objects referenced are up for grabs by the garbage collector
When we instantiate a class using mono_object_new(klass), as I understand, internally, no variable references the instance created by this instance. So does it mean that at some point, this instance will be collected by the garbage collector?
  • If this is the case, how can I solve this problem? As far as I understand what you said, this problem does occur and using LaunchMonoDataCollector() will fix the problem?
  • If it is not, then how can I free the memory storage of that instance when I no longer need it?

Eric
Hall of Famer
Hall of Famer
Posts: 174
Joined: Thu Mar 02, 2017 11:01 pm
Reputation: 90

Re: [SOLVED] Mono Features: How to create an instance of a Mono Class?

Post by Eric »

It is possible it gets garbage collected yes. The default behavior is that for each command the mono data collector .net thread attaches, does something, and then detaches. Detaching will release all objects assigned to that thread, including created objects

It's possible that between two instruction calls the object could get garbage collected unless as mentioned loading mono using LaunchMonoDataCollector(false) which makes it not detach.
As for freeing the memory, you could reconnect mono again which causes the old thread to detach and terminate making the object free for the taking for the garbage collector

User avatar
-Pikachu-
Noobzor
Noobzor
Posts: 7
Joined: Sun Dec 31, 2023 8:04 am
Reputation: 0

Re: [SOLVED] Mono Features: How to create an instance of a Mono Class?

Post by -Pikachu- »

Super!!!! I completely understand it now. Thank you a lot again, Eric :D

Post Reply

Who is online

Users browsing this forum: No registered users