dumpcs-dumper/Core/il2cpp/Api/Il2CppApi.cpp
2026-01-05 23:50:53 +03:00

436 lines
13 KiB
C++

#include "pch.h"
#include "Il2CppOffsets.h"
#include "Il2CppApi.h"
#include <libloaderapi.h>
#include <cstdio>
#include <cstdint>
#include <cstddef>
// Type and reflection API implementations
char* Il2CppApi::TypeGetName(const Il2CppType* type) {
auto func = RemoteFuncCall<char*, const Il2CppType*>(
il2CppOffsets::Class::il2cpp_type_get_name
);
return func(type);
}
// Type system API implementations
Il2CppClass* Il2CppApi::GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index) {
auto func = RemoteFuncCall<Il2CppClass*, TypeDefinitionIndex>(
il2CppOffsets::GetTypeInfoFromTypeDefinitionIndex
);
return func(index);
}
const char* Il2CppApi::ClassGetNamespace(Il2CppClass* klass) {
auto func = RemoteFuncCall<const char*, Il2CppClass*>(
il2CppOffsets::Class::il2cpp_class_get_namespace
);
return func(klass);
}
const char* Il2CppApi::ClassGetName(Il2CppClass* klass) {
auto func = RemoteFuncCall<const char*, Il2CppClass*>(
il2CppOffsets::Class::il2cpp_class_get_name
);
return func(klass);
}
bool Il2CppApi::ClassIsEnum(const Il2CppClass* klass) {
auto func = RemoteFuncCall<bool, const Il2CppClass*>(
il2CppOffsets::Class::il2cpp_class_is_enum
);
auto result = func(klass) != 0;
return result;
}
bool Il2CppApi::ClassIsValueType(const Il2CppClass* klass) {
auto func = RemoteFuncCall<bool, const Il2CppClass*>(
il2CppOffsets::Type::class_is_valuetype
);
return func(klass);
}
int Il2CppApi::ClassGetFlags(const Il2CppClass* klass) {
auto func = RemoteFuncCall<bool, const Il2CppClass*>(
il2CppOffsets::Class::il2cpp_class_get_flags
);
return func(klass);
}
Il2CppClass* Il2CppApi::ClassGetParent(Il2CppClass* klass) {
auto func = RemoteFuncCall<Il2CppClass*, Il2CppClass*>(
il2CppOffsets::Class::il2cpp_class_get_parent
);
return func(klass);
}
const Il2CppType* Il2CppApi::ClassGetType(Il2CppClass* klass) {
auto func = RemoteFuncCall<const Il2CppType*, Il2CppClass*>(
il2CppOffsets::Class::il2cpp_class_get_type
);
return func(klass);
}
Il2CppClass* Il2CppApi::ClassFromName(const Il2CppImage* image, const char* namespaze, const char* name) {
auto func = RemoteFuncCall<Il2CppClass*, const Il2CppImage*, const char*, const char*>(
il2CppOffsets::Class::il2cpp_class_from_name
);
return func(image, namespaze, name);
}
bool Il2CppApi::ClassInit(Il2CppClass* klass) {
auto func = RemoteFuncCall<bool, Il2CppClass*>(
il2CppOffsets::RuntimeStuff::il2cpp_vm_class_init
);
return func(klass);
}
// Method API implementations
const uint8_t* Il2CppApi::ClassGetMethods(Il2CppClass* klass, void* iter) {
auto func = RemoteFuncCall<const uint8_t*, Il2CppClass*, void*>(
il2CppOffsets::Class::il2cpp_class_get_methods
);
return func(klass, iter);
}
const char* Il2CppApi::MethodGetName(const uint8_t* MethodPtr) {
auto func = RemoteFuncCall<const char*, const uint8_t*>(
il2CppOffsets::Methods::il2cpp_method_get_name
);
return func(MethodPtr);
}
const Il2CppType* Il2CppApi::MethodGetReturnType(const uint8_t* method) {
auto func = RemoteFuncCall<const Il2CppType*, const uint8_t*>(
il2CppOffsets::Methods::il2cpp_method_get_return_type
);
return func(method);
}
const uint32_t Il2CppApi::MethodGetParamCount(const uint8_t* method) {
auto func = RemoteFuncCall<const uint32_t, const uint8_t*>(
il2CppOffsets::Methods::il2cpp_method_get_param_count
);
return func(method);
}
const Il2CppType* Il2CppApi::MethodGetParam(const uint8_t* method, uint32_t index) {
auto func = RemoteFuncCall<const Il2CppType*, const uint8_t*, uint32_t>(
il2CppOffsets::Methods::il2cpp_method_get_param
);
return func(method, index);
}
const char* Il2CppApi::MethodGetParamName(const uint8_t* method, uint32_t index) {
auto func = RemoteFuncCall<const char*, const uint8_t*, uint32_t>(
il2CppOffsets::Methods::il2cpp_method_get_param_name
);
return func(method, index);
}
const uintptr_t* Il2CppApi::ClassGetMethodFromName(Il2CppClass* klass, const char* name, int argsCount) {
auto func = RemoteFuncCall<uintptr_t*, Il2CppClass*, const char*, int>(
il2CppOffsets::Class::il2cpp_class_get_method_from_name
);
ClassInit(klass);
return func(klass, name, argsCount);
}
std::string Il2CppApi::GetMethodModifier(uint32_t flags) {
std::stringstream Modifiers;
auto access = flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK;
switch (access) {
case METHOD_ATTRIBUTE_PRIVATE: Modifiers << "private "; break;
case METHOD_ATTRIBUTE_PUBLIC: Modifiers << "public "; break;
case METHOD_ATTRIBUTE_FAMILY: Modifiers << "protected "; break;
case METHOD_ATTRIBUTE_ASSEM:
case METHOD_ATTRIBUTE_FAM_AND_ASSEM: Modifiers << "internal "; break;
case METHOD_ATTRIBUTE_FAM_OR_ASSEM: Modifiers << "protected internal "; break;
}
if (flags & METHOD_ATTRIBUTE_STATIC) Modifiers << "static ";
if (flags & METHOD_ATTRIBUTE_ABSTRACT) {
Modifiers << "abstract ";
if ((flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_REUSE_SLOT) {
Modifiers << "override ";
}
}
else if (flags & METHOD_ATTRIBUTE_FINAL) {
if ((flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_REUSE_SLOT) {
Modifiers << "sealed override ";
}
}
else if (flags & METHOD_ATTRIBUTE_VIRTUAL) {
if ((flags & METHOD_ATTRIBUTE_VTABLE_LAYOUT_MASK) == METHOD_ATTRIBUTE_NEW_SLOT) {
Modifiers << "virtual ";
}
else {
Modifiers << "override ";
}
}
if (flags & METHOD_ATTRIBUTE_PINVOKE_IMPL) Modifiers << "extern ";
return Modifiers.str();
}
// Field API implementations
uintptr_t* Il2CppApi::ClassGetFields(Il2CppClass* klass, void** iter) {
auto func = RemoteFuncCall<uintptr_t*, Il2CppClass*, void**>(
il2CppOffsets::Class::il2cpp_class_get_fields
);
ClassInit(klass);
return func(klass, iter);
}
int Il2CppApi::FieldGetFlags(uintptr_t* field) {
auto func = RemoteFuncCall<int, uintptr_t*>(
il2CppOffsets::Field::il2cpp_field_get_flags
);
return func(field);
}
const Il2CppType* Il2CppApi::FieldGetType(uintptr_t* field) {
auto func = RemoteFuncCall<const Il2CppType*, uintptr_t*>(
il2CppOffsets::Field::il2cpp_field_get_type
);
return func(field);
}
const char* Il2CppApi::FieldGetName(uintptr_t* field) {
auto func = RemoteFuncCall<const char*, uintptr_t*>(
il2CppOffsets::Field::il2cpp_field_get_name
);
return func(field);
}
void Il2CppApi::FieldStaticGetValue(uintptr_t* field, void* value) {
auto func = RemoteFuncCall<void, uintptr_t*, void*>(
il2CppOffsets::Field::il2cpp_field_static_get_value
);
func(field, value);
}
size_t Il2CppApi::FieldStaticGetValue(uintptr_t* field) {
size_t out = 0;
FieldStaticGetValue(
field,
&out
);
return out;
}
bool Il2CppApi::FieldIsInstance(uintptr_t* field) {
int flags = Il2CppApi::FieldGetFlags(field);
return (flags & FIELD_ATTRIBUTE_STATIC) == 0;
}
size_t Il2CppApi::FieldGetOffset(uintptr_t* field) {
auto func = RemoteFuncCall<size_t, uintptr_t*>(
il2CppOffsets::Field::il2cpp_field_get_offset
);
return func(field);
}
uint32_t Il2CppApi::FieldGetToken(uintptr_t* field) {
auto func = RemoteFuncCall<uint32_t, uintptr_t*>(
il2CppOffsets::Field::il2cpp_field_get_token
);
return func(field);
}
// Generic type API implementations
const size_t* Il2CppApi::ClassGetInterfaces(const uint8_t* klass, size_t& count) {
const uint64_t count_ptr = *reinterpret_cast<const uint64_t*>(klass + 24);
count = static_cast<size_t>(*reinterpret_cast<const uint8_t*>(count_ptr + 67LL)) ^ 0x9BLL;
const size_t* interfaces = *reinterpret_cast<const size_t* const*>(klass + 16);
return interfaces ? interfaces : nullptr;
}
const Il2CppGenericContainer* Il2CppApi::GenericClassGetGenericContainer(const Il2CppGenericClass* generic_class) {
if (!generic_class) return nullptr;
return generic_class->genericContainer;
}
const Il2CppGenericClass* Il2CppApi::ClassGetGenericClass(const Il2CppClass* klass) {
if (!klass) return nullptr;
return klass->generic_class;
}
uint32_t Il2CppApi::ClassGetGenericArgCount(const Il2CppClass* klass) {
auto generic_class = ClassGetGenericClass(klass);
if (!generic_class) return 0;
auto generic_container = GenericClassGetGenericContainer(generic_class);
if (!generic_container) return 0;
return generic_container->type_argc;
}
const void* Il2CppApi::ClassGetGenericArgType(const Il2CppClass* klass, uint64_t index) {
if (!klass) return nullptr;
const Il2CppGenericClass* generic_class = klass->generic_class;
if (!generic_class) return nullptr;
const Il2CppGenericContainer* generic_container = generic_class->genericContainer;
if (!generic_container) return nullptr;
const void** argv = generic_container->type_argv;
if (!argv) return nullptr;
return argv[index];
}
bool Il2CppApi::ClassIsGeneric(const Il2CppClass* klass) {
if (!klass) return false;
const Il2CppGenericClass* generic_class = klass->generic_class;
if (!generic_class) return false;
return generic_class->genericContainer != nullptr;
}
Il2CppClass* Il2CppApi::FromIl2CppType(const Il2CppType* type) {
auto func = RemoteFuncCall<Il2CppClass*, const Il2CppType*>(
il2CppOffsets::Class::FromIl2CppType
);
return func(type);
}
// Runtime API implementations
const uintptr_t* Il2CppApi::RuntimeClassInit() {
auto func = RemoteFuncCall<const uintptr_t*>(
il2CppOffsets::RuntimeStuff::il2cpp_runtime_class_init
);
return func();
}
Il2CppObject* Il2CppApi::MethodInvoke(const uintptr_t* method, void* obj, void** params) { //under the hood this is il2cpp_runtime_invoke
Il2CppException* exception = nullptr;
auto func = RemoteFuncCall<Il2CppObject*, const uintptr_t*, void*, void**, Il2CppException**>(
il2CppOffsets::RuntimeStuff::il2cpp_runtime_invoke
);
return func(method, obj, params, &exception);
}
Il2CppDomain* Il2CppApi::DomainGet() {
auto func = RemoteFuncCall<Il2CppDomain*>(
il2CppOffsets::Domain::il2cpp_domain_get
);
return func();
}
Il2CppAssembly** Il2CppApi::DomainGetAssemblies(size_t* size) {
uintptr_t assemblies_array = il2CppOffsets::gIBaseAddress + 0x43B5138;
uintptr_t* asm_start_ptr = *reinterpret_cast<uintptr_t**>(assemblies_array);
uintptr_t* asm_end_ptr = *reinterpret_cast<uintptr_t**>(assemblies_array + sizeof(uintptr_t));
*size = (reinterpret_cast<uintptr_t>(asm_end_ptr) - reinterpret_cast<uintptr_t>(asm_start_ptr)) / sizeof(uintptr_t);
return reinterpret_cast<Il2CppAssembly**>(asm_start_ptr);
}
const Il2CppAssembly* Il2CppApi::DomainAssemblyOpen(const char* name)
{
// RCX = Il2CppDomain*, RDX = const char*
auto func = RemoteFuncCall<const Il2CppAssembly*,
Il2CppDomain*,
const char*>(
il2CppOffsets::Domain::il2cpp_domain_assembly_open
);
Il2CppDomain* domain = DomainGet();
return func(domain, name);
}
const Il2CppImage* Il2CppApi::AssemblyGetImage(const Il2CppAssembly* assembly) {
auto func = RemoteFuncCall<const Il2CppImage*, const Il2CppAssembly*>(
il2CppOffsets::Domain::il2cpp_assembly_get_image
);
return func(assembly);
}
Il2CppClass* Il2CppApi::ObjectGetClass(Il2CppObject* obj)
{
return obj->klass;
}
const void* Il2CppApi::ObjectUnbox(Il2CppObject* obj) {
return reinterpret_cast<void*>(reinterpret_cast<uint8_t*>(obj) + sizeof(Il2CppObject));
}
Il2CppArray* Il2CppApi::ArrayNew(Il2CppClass* elementTypeInfo, il2cpp_array_size_t length) {
auto func = RemoteFuncCall<Il2CppArray*, Il2CppClass*, il2cpp_array_size_t>(
il2CppOffsets::RuntimeStuff::il2cpp_vm_array_new
);
return func(elementTypeInfo, length);
}
Il2CppObject* Il2CppApi::ObjectNew(Il2CppClass* klass) {
auto func = RemoteFuncCall<Il2CppObject*, Il2CppClass*>(
il2CppOffsets::RuntimeStuff::il2cpp_object_new
);
ClassInit(klass);
return func(klass);
}
void Il2CppApi::GCDisable() {
auto func = RemoteFuncCall<void>(
il2CppOffsets::GC::il2cpp_gc_disable
);
return func();
}
Il2CppThread* Il2CppApi::ThreadAttach(Il2CppDomain* domain) {
auto func = RemoteFuncCall<Il2CppThread*, Il2CppDomain*>(
il2CppOffsets::RuntimeStuff::il2cpp_thread_attach
);
return func(domain);
}
const char* Il2CppApi::AssemblyGetName(const Il2CppAssembly* assembly) {
auto baseAddress = reinterpret_cast<const uint8_t*>(assembly);
uint64_t* encryptedPtr = reinterpret_cast<uint64_t*>(const_cast<uint8_t*>(baseAddress) + 0x18LL);
uint64_t ptrObfuscated = *encryptedPtr;
uint64_t realPtr = ptrObfuscated - 0x6E24B24F7558EC86LL;
return reinterpret_cast<const char*>(realPtr);
}
uint32_t Il2CppApi::ImageGetClassCount(const Il2CppImage* image)
{
uint8_t* base = reinterpret_cast<uint8_t*>(const_cast<Il2CppImage*>(image));
uint32_t rawValue = *reinterpret_cast<uint32_t*>(base + 16);
uint32_t value = rawValue ^ 0x183E6E00u;
return value;
}
Il2CppClass* Il2CppApi::ImageGetClass(const Il2CppImage* image, size_t index) {
uint8_t* base = reinterpret_cast<uint8_t*>(const_cast<Il2CppImage*>(image));
uint32_t rawValue = *reinterpret_cast<uint32_t*>(base + 48);
int value = rawValue - 1579693933;
return Il2CppApi::GetTypeInfoFromTypeDefinitionIndex(value + index);
}