#include "def_il2cpp.hpp" namespace { Il2CppClass *get_il2cppclass1(const char *assemblyName, const char *namespaze, const char *klassName, bool strict) { auto il2cpp_domain = (SafeFptr(il2cpp_domain_get))(); if (!il2cpp_domain) return NULL; void *assembly = 0; do { assembly = (SafeFptr(il2cpp_domain_assembly_open))(il2cpp_domain, assemblyName); if (!assembly) break; auto image = (SafeFptr(il2cpp_assembly_get_image))(assembly); if (!image) break; auto klass = (SafeFptr(il2cpp_class_from_name))(image, namespaze, klassName); if (klass) return klass; } while (0); if (strict) return NULL; int _ = 0; size_t sz = 0; auto assemblies = (SafeFptr(il2cpp_domain_get_assemblies))(il2cpp_domain, &sz); if (assemblies) for (auto i = 0; i < sz; i++, assemblies++) { auto image = (SafeFptr(il2cpp_assembly_get_image))(*assemblies); if (!image) continue; auto cls = (SafeFptr(il2cpp_class_from_name))(image, namespaze, klassName); if (cls) return cls; } return NULL; } void foreach_func(Il2CppClass *klass, void *userData) { auto st = (std::vector *)userData; st->push_back(klass); } std::vector get_il2cppclass2(const char *namespaze, const char *klassName) { std::vector maybes; std::vector klasses; (SafeFptr(il2cpp_class_for_each))(foreach_func, &klasses); for (auto klass : klasses) { auto classname = (SafeFptr(il2cpp_class_get_name))(klass); if (!classname) continue; if (strcmp(classname, klassName) != 0) continue; maybes.push_back(klass); auto namespacename = (SafeFptr(il2cpp_class_get_namespace))(klass); if (!namespacename) continue; if (strlen(namespaze) && (strcmp(namespacename, namespaze) == 0)) { return {klass}; } } return maybes; } struct AutoThread { void *thread = NULL; AutoThread() { auto il2cpp_domain = (SafeFptr(il2cpp_domain_get))(); if (!il2cpp_domain) return; thread = (SafeFptr(il2cpp_thread_attach))(il2cpp_domain); } ~AutoThread() { if (!thread) return; (SafeFptr(il2cpp_thread_detach))(thread); } }; void tryprintimage(Il2CppClass *klass) { auto image = (SafeFptr(il2cpp_class_get_image))(klass); if (!image) return; auto imagen = (SafeFptr(il2cpp_image_get_name))(image); auto names = (SafeFptr(il2cpp_class_get_namespace))(klass); if (imagen && names) ConsoleOutput("%s:%s", imagen, names); } uintptr_t getmethodofklass(Il2CppClass *klass, const char *name, int argsCount) { if (!klass) return NULL; auto ret = (SafeFptr(il2cpp_class_get_method_from_name))(klass, name, argsCount); if (!ret) return NULL; tryprintimage(klass); return ret->methodPointer; } } void il2cppfunctions::init(HMODULE game_module) { RESOLVE_IMPORT(il2cpp_string_new_utf16); RESOLVE_IMPORT(il2cpp_string_chars); RESOLVE_IMPORT(il2cpp_string_length); RESOLVE_IMPORT(il2cpp_image_get_name); RESOLVE_IMPORT(il2cpp_class_get_image); RESOLVE_IMPORT(il2cpp_string_new_utf16); RESOLVE_IMPORT(il2cpp_string_new); RESOLVE_IMPORT(il2cpp_domain_get); RESOLVE_IMPORT(il2cpp_domain_assembly_open); RESOLVE_IMPORT(il2cpp_assembly_get_image); RESOLVE_IMPORT(il2cpp_class_from_name); RESOLVE_IMPORT(il2cpp_class_get_methods); RESOLVE_IMPORT(il2cpp_class_get_method_from_name); RESOLVE_IMPORT(il2cpp_method_get_param); RESOLVE_IMPORT(il2cpp_object_new); RESOLVE_IMPORT(il2cpp_resolve_icall); RESOLVE_IMPORT(il2cpp_array_new); RESOLVE_IMPORT(il2cpp_thread_attach); RESOLVE_IMPORT(il2cpp_thread_detach); RESOLVE_IMPORT(il2cpp_class_get_field_from_name); RESOLVE_IMPORT(il2cpp_class_is_assignable_from); RESOLVE_IMPORT(il2cpp_class_for_each); RESOLVE_IMPORT(il2cpp_class_get_nested_types); RESOLVE_IMPORT(il2cpp_class_get_type); RESOLVE_IMPORT(il2cpp_type_get_object); RESOLVE_IMPORT(il2cpp_gchandle_new); RESOLVE_IMPORT(il2cpp_gchandle_free); RESOLVE_IMPORT(il2cpp_gchandle_get_target); RESOLVE_IMPORT(il2cpp_class_from_type); RESOLVE_IMPORT(il2cpp_runtime_class_init); RESOLVE_IMPORT(il2cpp_runtime_invoke); RESOLVE_IMPORT(il2cpp_class_get_name); RESOLVE_IMPORT(il2cpp_class_get_namespace); RESOLVE_IMPORT(il2cpp_domain_get_assemblies); } uintptr_t il2cppfunctions::get_method_pointer(const char *assemblyName, const char *namespaze, const char *klassName, const char *name, int argsCount, bool strict) { auto thread = AutoThread(); if (!thread.thread) return NULL; auto klass = get_il2cppclass1(assemblyName, namespaze, klassName, strict); // 正向查询,assemblyName可以为空 if (klass) return getmethodofklass(klass, name, argsCount); if (strict) return NULL; auto klasses = get_il2cppclass2(namespaze, klassName); // 反向查询,namespace可以为空 for (auto klass : klasses) { auto method = getmethodofklass(klass, name, argsCount); if (method) return method; } return NULL; } std::optional il2cppfunctions::get_string(void *ptr) { auto str = reinterpret_cast(ptr); if (!str) return {}; auto wc = (SafeFptr(il2cpp_string_chars))(str); auto len = (SafeFptr(il2cpp_string_length))(str); if (!(wc && len)) return {}; return std::wstring_view(wc, len); } void *il2cppfunctions::create_string(std::wstring_view ws) { return (SafeFptr(il2cpp_string_new_utf16))(ws.data(), ws.length()); }