This commit is contained in:
恍兮惚兮 2024-05-09 14:22:19 +08:00
parent 1db17d2279
commit eed557375f
8 changed files with 170 additions and 123 deletions

View File

@ -48,9 +48,9 @@ bool monodll() {
bool mono::attach_function() {
bool il2=monocommon::il2cpp();
bool common=monocommon::hook_mono_il2cpp();
bool bmonobdwgc=monobdwgc();
bool bmonodll=monodll();
bool mono=monocommon::hook_mono();
return il2||bmonobdwgc||bmonodll||mono;
return common||bmonobdwgc||bmonodll;
}

View File

@ -77,8 +77,7 @@ _BYTE *__fastcall sub_18005B290(
}
}
bool mono::attach_function(){
bool il2=monocommon::il2cpp();
bool common=monocommon::hook_mono_il2cpp();
bool bmonobdwgc=monobdwgc();
bool mono=monocommon::hook_mono();
return il2||bmonobdwgc||mono;
return common||bmonobdwgc;
}

View File

@ -401,3 +401,6 @@ typedef void (*mono_profiler_install_jit_end_t)(MonoProfileJitResult end);
typedef void (*mono_profiler_install_exception_t)(MonoProfileExceptionFunc throw_callback, MonoProfileMethodFunc exc_method_leave, MonoProfileExceptionClauseFunc clause_callback);
typedef void (*mono_profiler_install_thread_t)(MonoProfileThreadFunc start, MonoProfileThreadFunc end);
typedef uint64_t* (*mono_compile_method_t)(uintptr_t);
typedef void*(*mono_image_get_table_info_t)(void*,uint32_t);
typedef int (*mono_table_info_get_rows_t)(void*);

View File

@ -28,10 +28,7 @@ il2cpp_runtime_invoke_t il2cpp_runtime_invoke;
il2cpp_class_get_name_t il2cpp_class_get_name;
il2cpp_class_get_namespace_t il2cpp_class_get_namespace;
il2cpp_domain_get_assemblies_t il2cpp_domain_get_assemblies;
char* il2cpp_array_addr_with_size(void* array, int32_t size, uintptr_t idx)
{
return ((char*)array) + kIl2CppSizeOfArray + size * idx;
}
namespace il2cpp_symbols
{
@ -72,10 +69,7 @@ namespace il2cpp_symbols
Il2CppClass* get_il2cppclass1(const char* assemblyName, const char* namespaze,
const char* klassName)
{
if(!(il2cpp_thread_attach&&il2cpp_domain_get&&il2cpp_assembly_get_image&&il2cpp_class_from_name))return NULL;
auto il2cpp_domain=il2cpp_domain_get();
if (!il2cpp_domain) return NULL;
il2cpp_thread_attach(il2cpp_domain);
if(!(il2cpp_assembly_get_image&&il2cpp_class_from_name))return NULL;
void* assembly=0;
if(il2cpp_domain_assembly_open){
do{
@ -101,41 +95,67 @@ namespace il2cpp_symbols
return NULL;
}
struct callbackstruct{
const char* classname;
const char* namespacename;
Il2CppClass* klass;
};
void foreach_func(Il2CppClass* klass, void* userData){
auto st=(callbackstruct*)userData;
auto classname = il2cpp_class_get_name(klass);
auto namespacename=il2cpp_class_get_namespace(klass);
if(strcmp(classname,st->classname)==0&&strcmp(namespacename,st->namespacename)==0)
st->klass=klass;
auto st=(std::vector<Il2CppClass*>*)userData;
st->push_back(klass);
}
Il2CppClass* get_il2cppclass2(const char* namespaze,
std::vector<Il2CppClass*> get_il2cppclass2(const char* namespaze,
const char* klassName)
{
if(!(il2cpp_class_for_each&&il2cpp_class_get_name&&il2cpp_class_get_namespace))return NULL;
callbackstruct st;
st.klass=NULL;
st.classname=klassName;
st.namespacename=namespaze;
il2cpp_class_for_each(foreach_func,&st);
if(!(il2cpp_class_for_each&&il2cpp_class_get_name))return {};
std::vector<Il2CppClass*>maybes;
std::vector<Il2CppClass*>klasses;
il2cpp_class_for_each(foreach_func,&klasses);
return st.klass;
for(auto klass:klasses){
auto classname = il2cpp_class_get_name(klass);
if(strcmp(classname,klassName)!=0)continue;
maybes.push_back(klass);
if(il2cpp_class_get_namespace){
auto namespacename=il2cpp_class_get_namespace(klass);
if(strcmp(namespacename,namespaze)==0){
return {klass};
}
}
}
return maybes;
}
struct AuthThread{
void*thread=NULL;
AuthThread(){
if(!(il2cpp_thread_attach&&il2cpp_domain_get))return;
auto il2cpp_domain=il2cpp_domain_get();
if (!il2cpp_domain) return;
thread= il2cpp_thread_attach(il2cpp_domain);
}
~AuthThread(){
if(!thread)return;
if(!il2cpp_thread_detach)return;
il2cpp_thread_detach(thread);
}
};
uintptr_t getmethodofklass(Il2CppClass* klass,const char* name, int argsCount){
if(!(il2cpp_class_get_method_from_name))return NULL;
if(!klass)return NULL;
auto ret = il2cpp_class_get_method_from_name(klass, name, argsCount);
if(!ret)return NULL;
return ret->methodPointer;
}
uintptr_t get_method_pointer(const char* assemblyName, const char* namespaze,
const char* klassName, const char* name, int argsCount)
{
if(!il2cpp_class_get_method_from_name)return NULL;
auto klass=get_il2cppclass1(assemblyName,namespaze,klassName);
if (!klass)
klass=get_il2cppclass2(namespaze,klassName);
if (!klass)
return NULL;
auto ret = il2cpp_class_get_method_from_name(klass, name, argsCount);
if (ret) return ret->methodPointer;
auto thread=AuthThread();
if(!thread.thread)return NULL;
auto klass=get_il2cppclass1(assemblyName,namespaze,klassName);//正向查询assemblyName可以为空
if(klass)
return getmethodofklass(klass,name,argsCount);
auto klasses=get_il2cppclass2(namespaze,klassName);//反向查询namespace可以为空
for(auto klass:klasses){
auto method= getmethodofklass(klass,name,argsCount);
if(method)return method;
}
return NULL;
}
}

View File

@ -230,9 +230,12 @@ mono_profiler_install_allocation_t mono_profiler_install_allocation = nullptr;
mono_profiler_install_jit_end_t mono_profiler_install_jit_end = nullptr;
mono_profiler_install_exception_t mono_profiler_install_exception = nullptr;
mono_profiler_install_thread_t mono_profiler_install_thread = nullptr;
mono_image_get_table_info_t mono_image_get_table_info=nullptr;
mono_table_info_get_rows_t mono_table_info_get_rows=nullptr;
void load_mono_functions_from_dll(HMODULE dll)
{
mono_table_info_get_rows=(mono_table_info_get_rows_t)(GetProcAddress(dll, "mono_table_info_get_rows"));
mono_image_get_table_info=(mono_image_get_table_info_t)(GetProcAddress(dll, "mono_image_get_table_info"));
mono_compile_method=(mono_compile_method_t)(GetProcAddress(dll, "mono_compile_method"));
mono_thread_suspend_all_other_threads = (mono_thread_suspend_all_other_threads_t)(GetProcAddress(dll, "mono_thread_suspend_all_other_threads"));
mono_thread_pool_cleanup = (mono_thread_pool_cleanup_t)(GetProcAddress(dll, "mono_thread_pool_cleanup"));
@ -464,65 +467,97 @@ void load_mono_functions_from_dll(HMODULE dll)
mono_profiler_install_exception = (mono_profiler_install_exception_t)(GetProcAddress(dll, "mono_profiler_install_exception"));
mono_profiler_install_thread = (mono_profiler_install_thread_t)(GetProcAddress(dll, "mono_profiler_install_thread"));
}
struct callbackstruct{
const char* _dll;
const char* _namespace;
const char* _class;
bool goodmatch;
MonoImage* Image;
MonoClass* klass;
};
static void MonoCallBack(void* assembly, void* userData) {
namespace{
void MonoCallBack(void* assembly, void* userData) {
auto Image=mono_assembly_get_image((MonoAssembly*)assembly);
if(!Image)return;
auto st=reinterpret_cast<callbackstruct*>(userData);
if(st->goodmatch)return;
auto st=reinterpret_cast<std::vector<MonoImage*>*>(userData);
st->push_back(Image);
}
std::vector<MonoImage*>mono_loop_images(){
if(!(mono_assembly_get_image&&mono_assembly_foreach))return {};
std::vector<MonoImage*>images;
mono_assembly_foreach(MonoCallBack,(void*)&images);
return images;
}
MonoClass* mono_findklassby_ass_namespace(std::vector<MonoImage*>& images,const char *_dll, const char *_namespace,const char *_class){
if(!(mono_class_from_name))return NULL;
MonoClass* maybe=NULL;
for(auto Image:images){
auto tmp=mono_class_from_name(Image, _namespace,_class);
if(tmp){
maybe=tmp;
if(mono_image_get_name){
auto name=mono_image_get_name(Image);
if(strcmp(st->_dll,name)==0){
st->Image=Image;
st->goodmatch=true;
st->klass=mono_class_from_name(Image, st->_namespace,st->_class);
return;
if(name&&(strcmp(_dll,name)==0))return tmp;
}
}
}
return maybe;
}
std::vector<MonoClass*> mono_findklassby_class(std::vector<MonoImage*>& images,const char *_namespace,const char *_class){
if(!(mono_image_get_table_info&&mono_table_info_get_rows&&mono_class_get&&mono_class_get_name))return {};
if(!st->klass)
std::vector<MonoClass*>maybes;
for(auto image:images){
auto _1=mono_image_get_table_info((void*)image,MONO_TABLE_TYPEDEF);
auto tdefcount=mono_table_info_get_rows(_1);
for (int i = 0; i < tdefcount; i++)
{
auto mono_class=mono_class_from_name(Image,st->_namespace,st->_class);
if(mono_class)
st->klass=mono_class;
auto klass = (MonoClass*)mono_class_get(image, MONO_TOKEN_TYPE_DEF | i+1);
auto name=mono_class_get_name(klass);
if(strcmp(name,_class)!=0)continue;
maybes.push_back(klass);
if(mono_class_get_namespace){
auto namespacename=mono_class_get_namespace(klass);
if(strcmp(namespacename,_namespace)==0){
return {klass};
}
}
}
}
return maybes;
}
MonoThread* tryattach(){
}
// Function to invoke a dll method in a mono application
uintptr_t getmonofunctionptr(const char *_dll, const char *_namespace, const char *_class, const char *_method, int paramCount) {
if(!(mono_thread_attach&&mono_class_from_name&&mono_class_get_method_from_name&&mono_assembly_foreach&&mono_get_root_domain&&mono_compile_method))return NULL;
mono_thread_attach(mono_get_root_domain());
callbackstruct st;
st.Image=NULL;
st.klass=NULL;
st._dll=_dll;
st._namespace=_namespace;
st._class=_class;
st.goodmatch=false;
mono_assembly_foreach(MonoCallBack,(void*)&st);
#if 0
MonoDomain* domain = mono_get_root_domain();
if(!domain)return NULL;
//Opening a custom assembly in the domain.
MonoAssembly* domainassembly = mono_domain_assembly_open(domain, _dll);
if(!domainassembly)return NULL;
//Getting the assembly's Image(Binary image, essentially a file-module).
MonoImage* Image = mono_assembly_get_image(domainassembly);
#endif
auto pClass=st.klass;
if(!pClass)return NULL;
//Declaring the method, that attaches our assembly to the game. (Class, MethodName, Parameters)
MonoMethod* MonoClassMethod = mono_class_get_method_from_name(pClass, _method, paramCount);
uintptr_t getmethodofklass(MonoClass* klass,const char* name, int argsCount){
if(!(mono_class_get_method_from_name&&mono_compile_method))return NULL;
if(!klass)return NULL;
MonoMethod* MonoClassMethod = mono_class_get_method_from_name(klass, name, argsCount);
if(!MonoClassMethod)return NULL;
return (uintptr_t)mono_compile_method((uintptr_t)MonoClassMethod);
}
struct AuthThread{
MonoThread *thread=NULL;
AuthThread(){
if(!(mono_get_root_domain&&mono_thread_attach))return ;
auto _root=mono_get_root_domain();
if(!_root)return ;
thread= mono_thread_attach(_root);
}
~AuthThread(){
if(!thread)return;
if(!mono_thread_detach)return;
mono_thread_detach(thread);
}
};
}
uintptr_t getmonofunctionptr(const char *_dll, const char *_namespace, const char *_class, const char *_method, int paramCount) {
auto thread=AuthThread();
if(!thread.thread)return NULL;
auto images=mono_loop_images();
auto pClass=mono_findklassby_ass_namespace(images,_dll,_namespace,_class);//dll可以为空
if(pClass)
return getmethodofklass(pClass,_method,paramCount);
auto klasses=mono_findklassby_class(images,_namespace,_class);//namespace可以为空
for(auto klass:klasses){
auto method= getmethodofklass(klass,_method,paramCount);
if(method)return method;
}
return NULL;
}

View File

@ -133,35 +133,19 @@ namespace monocommon{
{"UnityEngine.TextRenderingModule","UnityEngine","TextMesh","set_text",1,2,nullptr,true},
};
bool il2cpp() {
HMODULE module = GetModuleHandleW(L"GameAssembly.dll");
if (module == 0)return false;
bool hook_mono_il2cpp(){
for (const wchar_t* monoName : { L"mono.dll", L"mono-2.0-bdwgc.dll",L"GameAssembly.dll" })
if (HMODULE module = GetModuleHandleW(monoName)) {
bool b2=monodllhook(module);
load_mono_functions_from_dll(module);
il2cpp_symbols::init(module);
bool succ=false;
for(auto hook:commonhooks){
auto addr=il2cpp_symbols::get_method_pointer(hook.assemblyName,hook.namespaze,hook.klassName,hook.name,hook.argsCount);
//ConsoleOutput("%s %p",hook.name,addr-(uintptr_t)module);
auto addr=tryfindmonoil2cpp(hook.assemblyName,hook.namespaze,hook.klassName,hook.name,hook.argsCount);
if(!addr)continue;
succ|=NewHook_check(addr,hook);
}
return succ;
}
bool InsertMonoHooksByAssembly(HMODULE module){
load_mono_functions_from_dll(module);
bool succ=false;
for(auto hook:commonhooks){
auto addr=getmonofunctionptr(hook.assemblyName,hook.namespaze,hook.klassName,hook.name,hook.argsCount);
if(!addr)continue;
succ|=NewHook_check(addr,hook);
}
return succ;
}
bool hook_mono(){
for (const wchar_t* monoName : { L"mono.dll", L"mono-2.0-bdwgc.dll",L"GameAssembly.dll" })
if (HMODULE module = GetModuleHandleW(monoName)) {
bool b1=InsertMonoHooksByAssembly(module);
bool b2=monodllhook(module);
if(b1||b2)return true;
if(succ||b2)return true;
}
return false;
}

View File

@ -33,3 +33,10 @@ namespace il2cpp_symbols
void load_mono_functions_from_dll(HMODULE dll);
uintptr_t getmonofunctionptr(const char *_dll, const char *_namespace, const char *_class, const char *_method, int paramCount);
inline uintptr_t tryfindmonoil2cpp(const char *_dll, const char *_namespace, const char *_class, const char *_method, int paramCoun){
auto addr=il2cpp_symbols::get_method_pointer(_dll,_namespace,_class,_method,paramCoun);
if(addr)return addr;
return getmonofunctionptr(_dll,_namespace,_class,_method,paramCoun);
}

View File

@ -207,9 +207,8 @@ bool NewHook(HookParam hp, LPCSTR name){
return NewHook_1(hp,name);
if(hp.jittype==JITTYPE::UNITY){
auto spls=strSplit(hp.unityfunctioninfo,":");
hp.address = il2cpp_symbols::get_method_pointer(spls[0].c_str(),spls[1].c_str() ,spls[2].c_str(),spls[3].c_str(),std::stoi(spls[4]));
if(!hp.address)
hp.address=getmonofunctionptr(spls[0].c_str(),spls[1].c_str() ,spls[2].c_str(),spls[3].c_str(),std::stoi(spls[4]));
hp.address = tryfindmonoil2cpp(spls[0].c_str(),spls[1].c_str() ,spls[2].c_str(),spls[3].c_str(),std::stoi(spls[4]));
if(!hp.address)
return false;
return NewHook_1(hp,name);