mirror of
https://github.com/HIllya51/LunaHook.git
synced 2024-11-23 22:05:36 +08:00
mono
This commit is contained in:
parent
1db17d2279
commit
eed557375f
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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*);
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
@ -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);
|
||||
|
Loading…
Reference in New Issue
Block a user