first commit
This commit is contained in:
commit
7dd9dd689e
40 changed files with 4100 additions and 0 deletions
436
Core/il2cpp/Api/Il2CppApi.cpp
Normal file
436
Core/il2cpp/Api/Il2CppApi.cpp
Normal file
|
|
@ -0,0 +1,436 @@
|
|||
#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);
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue