2024-02-07 20:59:24 +08:00
|
|
|
|
|
2024-05-09 07:23:06 +08:00
|
|
|
|
#include"monostringapis.h"
|
2024-02-07 20:59:24 +08:00
|
|
|
|
namespace {
|
2024-05-09 07:23:06 +08:00
|
|
|
|
|
2024-03-20 19:29:38 +08:00
|
|
|
|
void mscorlib_system_string_InternalSubString_hook_fun(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
|
|
|
|
{
|
2024-03-20 23:20:17 +08:00
|
|
|
|
uintptr_t offset=stack->ARG1;
|
|
|
|
|
uintptr_t startIndex=stack->ARG2;
|
|
|
|
|
uintptr_t length=stack->ARG3;
|
2024-03-20 19:29:38 +08:00
|
|
|
|
|
|
|
|
|
MonoString* string = (MonoString*)offset;
|
|
|
|
|
if(string==0)return;
|
|
|
|
|
*data = (uintptr_t)(startIndex+string->chars);
|
|
|
|
|
if(wcslen((wchar_t*)*data)<length)return;
|
|
|
|
|
*len = length * 2;
|
|
|
|
|
|
2024-02-07 20:59:24 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/** jichi 12/26/2014 Mono
|
|
|
|
|
* Sample game: [141226] ハ<EFBFBD>レ<EFBFBD>めいと
|
|
|
|
|
*/
|
|
|
|
|
void SpecialHookMonoString(hook_stack* stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t*len)
|
|
|
|
|
{
|
2024-05-10 00:51:41 +08:00
|
|
|
|
commonsolvemonostring(stack->ARG1,data,len);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
|
|
|
|
|
#ifndef _WIN64
|
|
|
|
|
auto s = stack->ecx;
|
|
|
|
|
for (int i = 0; i < 0x10; i++) // traverse pointers until a non-readable address is met
|
|
|
|
|
if (s && !::IsBadReadPtr((LPCVOID)s, sizeof(DWORD)))
|
|
|
|
|
s = *(DWORD *)s;
|
|
|
|
|
else
|
|
|
|
|
break;
|
|
|
|
|
if (!s)
|
|
|
|
|
s = hp->address;
|
|
|
|
|
if (hp->type & USING_SPLIT) *split = s;
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 07:23:06 +08:00
|
|
|
|
}
|
|
|
|
|
namespace {
|
|
|
|
|
bool monodllhook(HMODULE module) {
|
|
|
|
|
HookParam hp;
|
|
|
|
|
const MonoFunction funcs[] = { MONO_FUNCTIONS_INITIALIZER };
|
|
|
|
|
for (auto func : funcs) {
|
|
|
|
|
if (FARPROC addr = GetProcAddress(module, func.functionName)) {
|
|
|
|
|
hp.address =(uintptr_t) addr;
|
|
|
|
|
hp.type =USING_STRING| func.hookType;
|
|
|
|
|
hp.filter_fun =all_ascii_Filter;
|
|
|
|
|
hp.offset = func.textIndex * 4;
|
|
|
|
|
hp.length_offset = func.lengthIndex * 4;
|
|
|
|
|
hp.text_fun = (decltype(hp.text_fun))func.text_fun;
|
|
|
|
|
ConsoleOutput("Mono: INSERT");
|
|
|
|
|
NewHook(hp, func.functionName);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
}
|
2024-05-09 07:23:06 +08:00
|
|
|
|
}
|
2024-02-07 20:59:24 +08:00
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2024-05-09 07:23:06 +08:00
|
|
|
|
namespace monocommon{
|
2024-02-07 20:59:24 +08:00
|
|
|
|
|
|
|
|
|
bool monodllhook(HMODULE module) {
|
|
|
|
|
HookParam hp;
|
|
|
|
|
const MonoFunction funcs[] = { MONO_FUNCTIONS_INITIALIZER };
|
|
|
|
|
for (auto func : funcs) {
|
|
|
|
|
if (FARPROC addr = GetProcAddress(module, func.functionName)) {
|
|
|
|
|
hp.address =(uintptr_t) addr;
|
|
|
|
|
hp.type =USING_STRING| func.hookType;
|
|
|
|
|
hp.filter_fun =all_ascii_Filter;
|
|
|
|
|
hp.offset = func.textIndex * 4;
|
|
|
|
|
hp.length_offset = func.lengthIndex * 4;
|
|
|
|
|
hp.text_fun = (decltype(hp.text_fun))func.text_fun;
|
2024-05-09 07:23:06 +08:00
|
|
|
|
NewHook(hp, func.functionName);
|
2024-02-07 20:59:24 +08:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
}
|
2024-05-09 07:23:06 +08:00
|
|
|
|
struct functioninfo{
|
|
|
|
|
const char* assemblyName;const char* namespaze;
|
|
|
|
|
const char* klassName; const char* name;int argsCount;
|
2024-05-14 10:51:19 +08:00
|
|
|
|
int argidx;void* text_fun=nullptr;bool Embed=false;bool isstring=true;
|
2024-05-09 07:23:06 +08:00
|
|
|
|
std::string hookname(){
|
|
|
|
|
char tmp[1024];
|
|
|
|
|
sprintf(tmp,"%s:%s",klassName,name);
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
|
|
|
|
std::string info(){
|
|
|
|
|
char tmp[1024];
|
|
|
|
|
sprintf(tmp,"%s:%s:%s:%s:%d",assemblyName,namespaze,klassName,name,argsCount);
|
|
|
|
|
return tmp;
|
|
|
|
|
}
|
2024-05-14 10:51:19 +08:00
|
|
|
|
};
|
2024-05-09 07:23:06 +08:00
|
|
|
|
bool NewHook_check(uintptr_t addr,functioninfo&hook){
|
|
|
|
|
|
|
|
|
|
HookParam hp;
|
|
|
|
|
hp.address = addr;
|
|
|
|
|
hp.argidx=hook.argidx;
|
|
|
|
|
hp.text_fun =(decltype(hp.text_fun))hook.text_fun;
|
2024-05-14 10:51:19 +08:00
|
|
|
|
if(hook.isstring){
|
|
|
|
|
hp.type = USING_STRING | CODEC_UTF16|FULL_STRING;
|
2024-05-10 02:11:33 +08:00
|
|
|
|
if(!hp.text_fun)hp.type|=SPECIAL_JIT_STRING;
|
2024-05-14 10:51:19 +08:00
|
|
|
|
}
|
|
|
|
|
else{
|
|
|
|
|
hp.type = USING_CHAR | CODEC_UTF16;
|
|
|
|
|
}
|
2024-05-09 07:23:06 +08:00
|
|
|
|
hp.jittype=JITTYPE::UNITY;
|
|
|
|
|
strcpy(hp.unityfunctioninfo,hook.info().c_str());
|
|
|
|
|
if(hook.Embed)
|
|
|
|
|
hp.type|=EMBED_ABLE|EMBED_BEFORE_SIMPLE;
|
|
|
|
|
auto succ=NewHook(hp,hook.hookname().c_str());
|
|
|
|
|
#ifdef _WIN64
|
|
|
|
|
if(!succ){
|
|
|
|
|
hp.type|=BREAK_POINT;
|
|
|
|
|
succ|=NewHook(hp,hook.hookname().c_str());
|
|
|
|
|
}
|
|
|
|
|
#endif
|
|
|
|
|
return succ;
|
|
|
|
|
}
|
|
|
|
|
std::vector<functioninfo>commonhooks{
|
2024-05-14 10:51:19 +08:00
|
|
|
|
{"mscorlib","System","String","ToCharArray",0,1},
|
|
|
|
|
{"mscorlib","System","String","Replace",2,1},
|
|
|
|
|
{"mscorlib","System","String","ToString",0,1},
|
|
|
|
|
{"mscorlib","System","String","IndexOf",1,1},
|
|
|
|
|
{"mscorlib","System","String","Substring",2,1},
|
|
|
|
|
{"mscorlib","System","String","op_Inequality",2,1},
|
|
|
|
|
{"mscorlib","System","String","InternalSubString",2,99999,mscorlib_system_string_InternalSubString_hook_fun},
|
2024-05-09 07:23:06 +08:00
|
|
|
|
|
|
|
|
|
{"Unity.TextMeshPro","TMPro","TMP_Text","set_text",1,2,nullptr,true},
|
2024-05-14 10:32:10 +08:00
|
|
|
|
{"Unity.TextMeshPro","TMPro","TextMeshPro","set_text",1,2,nullptr,true},
|
2024-05-09 07:23:06 +08:00
|
|
|
|
{"UnityEngine.UI","UnityEngine.UI","Text","set_text",1,2,nullptr,true},
|
|
|
|
|
{"UnityEngine.UIElementsModule","UnityEngine.UIElements","TextElement","set_text",1,2,nullptr,true},
|
|
|
|
|
{"UnityEngine.UIElementsModule","UnityEngine.UIElements","TextField","set_value",1,2,nullptr,true},
|
|
|
|
|
{"UnityEngine.TextRenderingModule","UnityEngine","GUIText","set_text",1,2,nullptr,true},
|
|
|
|
|
{"UnityEngine.TextRenderingModule","UnityEngine","TextMesh","set_text",1,2,nullptr,true},
|
2024-05-09 18:58:07 +08:00
|
|
|
|
{"UGUI","","UILabel","set_text",1,2,nullptr,true},
|
2024-05-09 07:23:06 +08:00
|
|
|
|
};
|
2024-05-14 10:32:10 +08:00
|
|
|
|
std::vector<functioninfo>extrahooks{
|
|
|
|
|
//https://vndb.org/r37234 && https://vndb.org/r37235
|
|
|
|
|
//Higurashi When They Cry Hou - Ch.2 Watanagashi && Higurashi When They Cry Hou - Ch.3 Tatarigoroshi
|
|
|
|
|
{"Assembly-CSharp","Assets.Scripts.Core.TextWindow","TextController","SetText",4,3,nullptr,true},
|
2024-05-14 10:51:19 +08:00
|
|
|
|
//逆転裁判123 成歩堂セレクション
|
|
|
|
|
{"Assembly-CSharp","","MessageText","Append",1,2,nullptr,false,false},
|
2024-05-14 10:32:10 +08:00
|
|
|
|
};
|
2024-05-09 14:22:19 +08:00
|
|
|
|
bool hook_mono_il2cpp(){
|
2024-02-07 20:59:24 +08:00
|
|
|
|
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);
|
2024-05-09 14:22:19 +08:00
|
|
|
|
load_mono_functions_from_dll(module);
|
|
|
|
|
il2cpp_symbols::init(module);
|
|
|
|
|
bool succ=false;
|
|
|
|
|
for(auto hook:commonhooks){
|
|
|
|
|
auto addr=tryfindmonoil2cpp(hook.assemblyName,hook.namespaze,hook.klassName,hook.name,hook.argsCount);
|
|
|
|
|
if(!addr)continue;
|
|
|
|
|
succ|=NewHook_check(addr,hook);
|
|
|
|
|
}
|
2024-05-14 10:32:10 +08:00
|
|
|
|
for(auto hook:extrahooks){
|
|
|
|
|
auto addr=tryfindmonoil2cpp(hook.assemblyName,hook.namespaze,hook.klassName,hook.name,hook.argsCount,true);
|
|
|
|
|
if(!addr)continue;
|
|
|
|
|
succ|=NewHook_check(addr,hook);
|
|
|
|
|
}
|
2024-05-09 14:22:19 +08:00
|
|
|
|
if(succ||b2)return true;
|
2024-02-07 20:59:24 +08:00
|
|
|
|
}
|
|
|
|
|
return false;
|
|
|
|
|
}
|
|
|
|
|
}
|