#include "pch.h" #include "Il2CppOffsets.h" #include "Il2CppApi.h" #include #include #include #include // Type and reflection API implementations char* Il2CppApi::TypeGetName(const Il2CppType* type) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_type_get_name ); return func(type); } // Type system API implementations Il2CppClass* Il2CppApi::GetTypeInfoFromTypeDefinitionIndex(TypeDefinitionIndex index) { auto func = RemoteFuncCall( il2CppOffsets::GetTypeInfoFromTypeDefinitionIndex ); return func(index); } const char* Il2CppApi::ClassGetNamespace(Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_get_namespace ); return func(klass); } const char* Il2CppApi::ClassGetName(Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_get_name ); return func(klass); } bool Il2CppApi::ClassIsEnum(const Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_is_enum ); auto result = func(klass) != 0; return result; } bool Il2CppApi::ClassIsValueType(const Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Type::class_is_valuetype ); return func(klass); } int Il2CppApi::ClassGetFlags(const Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_get_flags ); return func(klass); } Il2CppClass* Il2CppApi::ClassGetParent(Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_get_parent ); return func(klass); } const Il2CppType* Il2CppApi::ClassGetType(Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_get_type ); return func(klass); } Il2CppClass* Il2CppApi::ClassFromName(const Il2CppImage* image, const char* namespaze, const char* name) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_from_name ); return func(image, namespaze, name); } bool Il2CppApi::ClassInit(Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::RuntimeStuff::il2cpp_vm_class_init ); return func(klass); } // Method API implementations const uint8_t* Il2CppApi::ClassGetMethods(Il2CppClass* klass, void* iter) { auto func = RemoteFuncCall( il2CppOffsets::Class::il2cpp_class_get_methods ); return func(klass, iter); } const char* Il2CppApi::MethodGetName(const uint8_t* MethodPtr) { auto func = RemoteFuncCall( il2CppOffsets::Methods::il2cpp_method_get_name ); return func(MethodPtr); } const Il2CppType* Il2CppApi::MethodGetReturnType(const uint8_t* method) { auto func = RemoteFuncCall( il2CppOffsets::Methods::il2cpp_method_get_return_type ); return func(method); } const uint32_t Il2CppApi::MethodGetParamCount(const uint8_t* method) { auto func = RemoteFuncCall( il2CppOffsets::Methods::il2cpp_method_get_param_count ); return func(method); } const Il2CppType* Il2CppApi::MethodGetParam(const uint8_t* method, uint32_t index) { auto func = RemoteFuncCall( il2CppOffsets::Methods::il2cpp_method_get_param ); return func(method, index); } const char* Il2CppApi::MethodGetParamName(const uint8_t* method, uint32_t index) { auto func = RemoteFuncCall( 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( 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( il2CppOffsets::Class::il2cpp_class_get_fields ); ClassInit(klass); return func(klass, iter); } int Il2CppApi::FieldGetFlags(uintptr_t* field) { auto func = RemoteFuncCall( il2CppOffsets::Field::il2cpp_field_get_flags ); return func(field); } const Il2CppType* Il2CppApi::FieldGetType(uintptr_t* field) { auto func = RemoteFuncCall( il2CppOffsets::Field::il2cpp_field_get_type ); return func(field); } const char* Il2CppApi::FieldGetName(uintptr_t* field) { auto func = RemoteFuncCall( il2CppOffsets::Field::il2cpp_field_get_name ); return func(field); } void Il2CppApi::FieldStaticGetValue(uintptr_t* field, void* value) { auto func = RemoteFuncCall( 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( il2CppOffsets::Field::il2cpp_field_get_offset ); return func(field); } uint32_t Il2CppApi::FieldGetToken(uintptr_t* field) { auto func = RemoteFuncCall( 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(klass + 24); count = static_cast(*reinterpret_cast(count_ptr + 67LL)) ^ 0x9BLL; const size_t* interfaces = *reinterpret_cast(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( il2CppOffsets::Class::FromIl2CppType ); return func(type); } // Runtime API implementations const uintptr_t* Il2CppApi::RuntimeClassInit() { auto func = RemoteFuncCall( 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( il2CppOffsets::RuntimeStuff::il2cpp_runtime_invoke ); return func(method, obj, params, &exception); } Il2CppDomain* Il2CppApi::DomainGet() { auto func = RemoteFuncCall( 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(assemblies_array); uintptr_t* asm_end_ptr = *reinterpret_cast(assemblies_array + sizeof(uintptr_t)); *size = (reinterpret_cast(asm_end_ptr) - reinterpret_cast(asm_start_ptr)) / sizeof(uintptr_t); return reinterpret_cast(asm_start_ptr); } const Il2CppAssembly* Il2CppApi::DomainAssemblyOpen(const char* name) { // RCX = Il2CppDomain*, RDX = const char* auto func = RemoteFuncCall( il2CppOffsets::Domain::il2cpp_domain_assembly_open ); Il2CppDomain* domain = DomainGet(); return func(domain, name); } const Il2CppImage* Il2CppApi::AssemblyGetImage(const Il2CppAssembly* assembly) { auto func = RemoteFuncCall( 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(reinterpret_cast(obj) + sizeof(Il2CppObject)); } Il2CppArray* Il2CppApi::ArrayNew(Il2CppClass* elementTypeInfo, il2cpp_array_size_t length) { auto func = RemoteFuncCall( il2CppOffsets::RuntimeStuff::il2cpp_vm_array_new ); return func(elementTypeInfo, length); } Il2CppObject* Il2CppApi::ObjectNew(Il2CppClass* klass) { auto func = RemoteFuncCall( il2CppOffsets::RuntimeStuff::il2cpp_object_new ); ClassInit(klass); return func(klass); } void Il2CppApi::GCDisable() { auto func = RemoteFuncCall( il2CppOffsets::GC::il2cpp_gc_disable ); return func(); } Il2CppThread* Il2CppApi::ThreadAttach(Il2CppDomain* domain) { auto func = RemoteFuncCall( il2CppOffsets::RuntimeStuff::il2cpp_thread_attach ); return func(domain); } const char* Il2CppApi::AssemblyGetName(const Il2CppAssembly* assembly) { auto baseAddress = reinterpret_cast(assembly); uint64_t* encryptedPtr = reinterpret_cast(const_cast(baseAddress) + 0x18LL); uint64_t ptrObfuscated = *encryptedPtr; uint64_t realPtr = ptrObfuscated - 0x6E24B24F7558EC86LL; return reinterpret_cast(realPtr); } uint32_t Il2CppApi::ImageGetClassCount(const Il2CppImage* image) { uint8_t* base = reinterpret_cast(const_cast(image)); uint32_t rawValue = *reinterpret_cast(base + 16); uint32_t value = rawValue ^ 0x183E6E00u; return value; } Il2CppClass* Il2CppApi::ImageGetClass(const Il2CppImage* image, size_t index) { uint8_t* base = reinterpret_cast(const_cast(image)); uint32_t rawValue = *reinterpret_cast(base + 48); int value = rawValue - 1579693933; return Il2CppApi::GetTypeInfoFromTypeDefinitionIndex(value + index); }