 |
Cheat Engine The Official Site of Cheat Engine
|
| View previous topic :: View next topic |
| Author |
Message |
Frouk Grandmaster Cheater
Reputation: 6
Joined: 22 Jun 2021 Posts: 528
|
Posted: Sat Aug 15, 2026 1:52 am Post subject: [Mono] Retrieving class instances in C |
|
|
| Code: |
...
{$luacode refList=RSI}
local klass = mono_findClass("...")
if (klass) then
refList = #mono_class_findInstancesOfClassListOnly(nil, klass)
end
{$asm}
...
{$luacode list=RAX}
local klass = mono_findClass("...")
if (klass) then
local tbl = mono_class_findInstancesOfClassListOnly(nil, klass)
if (tbl and #tbl > 0) then
for i, v in pairs(tbl) do
writePointer(list + 0x4 + 0x8 * (i - 1), v)
end
end
end
{$asm}
...
|
Is there's an easier way to retrieve instances using C code or assembly rather than making a call through lua code? Or it would require writing a header or exports of mono to do that?(it seems to be a "yes" answer)
|
|
| Back to top |
|
 |
Dark Byte Site Admin
Reputation: 475
Joined: 09 May 2003 Posts: 25989 Location: The netherlands
|
Posted: Sat Aug 15, 2026 2:52 pm Post subject: |
|
|
it requires a memoryscan
Unity does have a helper funnction that keeps track of some class instances, but not all
_________________
Tools give you results. Knowledge gives you control.
Like my help? Join me on Patreon so i can keep helping |
|
| Back to top |
|
 |
Frouk Grandmaster Cheater
Reputation: 6
Joined: 22 Jun 2021 Posts: 528
|
Posted: Sat Aug 15, 2026 3:07 pm Post subject: |
|
|
so, either basic vtable or "klass" memory scan or using the Unity's helper function
though, I should test the Unity's helper function first and report back
|
|
| Back to top |
|
 |
Frouk Grandmaster Cheater
Reputation: 6
Joined: 22 Jun 2021 Posts: 528
|
Posted: Mon Aug 17, 2026 9:37 am Post subject: |
|
|
Okay, using Unity's helper function worked
| Code: |
void *domain = mono_domain_get();
if (!domain)
{
return;
}
void *coreMod = mono_domain_assembly_open(domain, "UnityEngine.CoreModule");
if (!coreMod)
coreMod = mono_domain_assembly_open(domain, "UnityEngine");
if (!coreMod)
{
return;
}
void *modImage = mono_assembly_get_image(coreMod);
void *unityObjClass = mono_class_from_name(modImage, "UnityEngine", "Object");
if (!unityObjClass)
{
return;
}
void *iter = 0;
void *method = 0;
void *found = 0;
while ((method = mono_class_get_methods(unityObjClass, &iter)) != 0)
{
const char *methodName = mono_method_get_name(method);
if (_stricmp(methodName, "FindObjectsOfType") == 0)
{
void *sig = mono_method_signature(method);
if (!sig)
continue;
int paramCnt = mono_signature_get_param_count(sig);
if (paramCnt == 1)
{
void *iter = 0;
void *params = mono_signature_get_params(sig, &iter);
if (params)
{
void *paramKlass = mono_type_get_class(params);
if (paramKlass)
{
const char* paramName = mono_class_get_name(paramKlass);
if (strstr(paramName, "Type"))
{
void *type = mono_signature_get_return_type(sig);
if (!type)
continue;
if (mono_type_get_type(type) == 0x1D)
{
found = method;
break;
}
}
}
}
}
}
}
if (!found)
{
return;
}
|
Took some time before I eventually got it working
|
|
| Back to top |
|
 |
Csimbi I post too much
Reputation: 98
Joined: 14 Jul 2007 Posts: 3423
|
Posted: Mon Aug 17, 2026 2:27 pm Post subject: |
|
|
Well done!
Any chance you could provide and example with the intended use?
Thanks!
|
|
| Back to top |
|
 |
Frouk Grandmaster Cheater
Reputation: 6
Joined: 22 Jun 2021 Posts: 528
|
Posted: Tue Aug 18, 2026 3:57 am Post subject: |
|
|
| Csimbi wrote: | Well done!
Any chance you could provide and example with the intended use?
Thanks! |
Yes,
| Code: |
// defined in {$C}
void *mono_findClass(const char *szAssembly, const char *namespaze, const char *name)
{
void *domain = mono_domain_get();
if (!domain)
return 0;
void *assembly = mono_domain_assembly_open(domain, szAssembly);
if (!assembly)
return 0;
void *image = mono_assembly_get_image(assembly);
if (!image)
return 0;
return mono_class_from_name(image, namespaze, name);
}
// will return the UnityEngine.Object[] type
// therefore -
// count - 0x18(x64) or 0xC(x86)
// start of array - 0x20(x64) or 0x10(x86)
void *mono_class_findEveryInstance(void *klass)
{
void *resourcesClass = mono_findClass("UnityEngine.CoreModule", "UnityEngine", "Resources");
if (!resourcesClass)
resourcesClass = mono_findClass("UnityEngine", "UnityEngine", "Resources");
void *objectClass = resourcesClass;
if (!objectClass)
{
objectClass = mono_findClass("UnityEngine.CoreModule", "UnityEngine", "Object");
if (!objectClass) // If we failed to find one in core module, we would try to find it in the unity's default module
objectClass = mono_findClass("UnityEngine", "UnityEngine", "Object");
}
if (!objectClass)
return 0;
void *iter = 0;
void *foundMethod = 0;
for (void *method = mono_class_get_methods(objectClass, &iter); method; method = mono_class_get_methods(objectClass, &iter))
{
const char *methodName = mono_method_get_name(method);
if (_stricmp(methodName, resourcesClass ? "FindObjectsOfTypeAll" : "FindObjectsOfType") == 0)
{
void *sig = mono_method_signature(method);
if (!sig)
continue;
if (mono_signature_get_param_count(sig) == 1) // one parameter
{
void *paramIter = 0;
void *params = mono_signature_get_params(sig, ¶mIter);
if (!params)
continue;
void *paramClass = mono_type_get_class(params);
if (!paramClass)
continue;
const char *paramName = mono_class_get_name(paramClass);
if (strstr(paramName, "Type"))
{
void *type = mono_signature_get_return_type(sig);
if (!type)
continue;
if (mono_type_get_type(type) == 0x1D) // 0x1D - MONO_TYPE_SZARRAY
{
foundMethod = method;
break;
}
}
}
}
}
if (foundMethod)
{
void *domain = mono_domain_get();
void *klassType = mono_class_get_type(klass);
void *objectType = mono_type_get_object(domain, klassType);
if (!objectType)
return 0;
void *exc = 0;
void *args[] = { objectType };
void *result = mono_runtime_invoke(foundMethod, 0, args, &exc);
if (!result || exc)
return 0;
return result;
}
return 0;
}
|
Simplified and turned into helper functions
| Code: |
void *klass = mono_findClass("Assembly-CSharp", "ExampleNamespace", "ExampleClass");
if (!klass)
return;
void *array = mono_class_findEveryInstance(klass);
if (!array)
return;
int count = mono_array_length(array);
for (int i = 0; i < count; i++)
{
void *item = *(void**)((uintptr_t)array + 0x20 + 0x8 * i);
// x86
// void *item = *(void**)((uintptr_t)array + 0x10 + 0x4 * i);
// item now holds the address of the object
*(int*)((uintptr_t)item + 0x30) = 100; // let's say 0x30 offset holds our health, from here we set the health to 100, offsets can be seen via .NET info or Mono lookup
}
|
|
|
| Back to top |
|
 |
Csimbi I post too much
Reputation: 98
Joined: 14 Jul 2007 Posts: 3423
|
Posted: Tue Aug 18, 2026 10:52 am Post subject: |
|
|
| Much appreciated!
|
|
| 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
|
|