From 9be975e15f756c7eb3fb3749f89adedcf1603710 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=81=8D=E5=85=AE=E6=83=9A=E5=85=AE?= <1173718158@qq.com> Date: Mon, 25 Nov 2024 20:41:11 +0800 Subject: [PATCH] . --- cpp/LunaHook/LunaHook/engine32/System4x.cpp | 65 ++++---- cpp/LunaHook/LunaHook/engine64/yuzu.cpp | 35 +++++ cpp/LunaHook/LunaHook/veh_hook.cpp | 156 ++++++-------------- cpp/LunaHook/LunaHook/veh_hook.h | 24 --- cpp/version.cmake | 2 +- 5 files changed, 115 insertions(+), 167 deletions(-) diff --git a/cpp/LunaHook/LunaHook/engine32/System4x.cpp b/cpp/LunaHook/LunaHook/engine32/System4x.cpp index b9aefac7..d98be948 100644 --- a/cpp/LunaHook/LunaHook/engine32/System4x.cpp +++ b/cpp/LunaHook/LunaHook/engine32/System4x.cpp @@ -855,35 +855,19 @@ static bool InsertSystem43NewHook(ULONG startAddress, ULONG stopAddress, LPCSTR 0x51, // 004eeb43 51 push ecx 0xe8 //, XX4, // 004eeb44 e8 42dc1900 call .0068c78b }; - enum - { - addr_offset = 0 - }; ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); // GROWL_DWORD(addr); if (!addr) - { - ConsoleOutput("System43+: pattern not found"); return false; - } - - // addr = *(DWORD *)(addr+1) + addr + 5; // change to hook to the actual address of function being called - HookParam hp; hp.address = addr; hp.type = NO_CONTEXT | USING_STRING | USING_SPLIT | SPLIT_INDIRECT; // hp.type = NO_CONTEXT|USING_STRING|FIXING_SPLIT; hp.split_index = 0x10; // use [[esp]+0x10] to differentiate name and thread - // Only name can be modified here, where the value of split is 0x6, and text in 0x2 - - ConsoleOutput("INSERT System43+"); - - ConsoleOutput("System43+: disable GDI hooks"); // disable hooking to TextOutA, which is cached - return NewHook(hp, hookName); } -void System43New2Filter(TextBuffer *buffer, HookParam *) +void System43aFilter(TextBuffer *buffer, HookParam *) { auto text = reinterpret_cast(buffer->buff); @@ -895,7 +879,7 @@ void System43New2Filter(TextBuffer *buffer, HookParam *) } } -bool InsertSystem43New2Hook() +bool InsertSystem43aHook() { /* @@ -910,30 +894,47 @@ bool InsertSystem43New2Hook() 0x57, // push edi 0xC6, 0x06, 0x00 // mov byte ptr [esi],00 << hook here }; - enum - { - addr_offset = sizeof(bytes) - 3 - }; - - ULONG range = min(processStopAddress - processStartAddress, MAX_REL_ADDR); - ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStartAddress + range); + ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); if (!addr) - { - ConsoleOutput("System43new: pattern not found"); return false; - } HookParam hp; - hp.address = addr + addr_offset; + hp.address = addr + sizeof(bytes) - 3; hp.offset = get_reg(regs::edx); hp.split = get_reg(regs::esp); hp.type = NO_CONTEXT | USING_STRING | USING_SPLIT; - hp.filter_fun = System43New2Filter; - ConsoleOutput("INSERT System43new"); + hp.filter_fun = System43aFilter; return NewHook(hp, "System43new"); } + +bool InsertSystem43bHook() +{ + /* + * Sample games: + * https://vndb.org/v10732 + */ + const BYTE bytes[] = { + 0x8B, 0xCE, // mov ecx,esi << hook here + 0xE8, XX4, // call Oyakorankan.exe+13D890 + 0x8B, 0x43, 0x04, // mov eax,[ebx+04] + 0x8D, 0x4C, 0x24, 0x10, // lea ecx,[esp+10] + 0x3B, 0xC8, // cmp ecx,eax + 0x73, 0x64 // jae Oyakorankan.exe+1403B2 + }; + + ULONG addr = MemDbg::findBytes(bytes, sizeof(bytes), processStartAddress, processStopAddress); + if (!addr) + return false; + HookParam hp = {}; + hp.address = addr; + hp.offset = get_reg(regs::edx); + hp.split = get_stack(12); + hp.type = USING_STRING | USING_SPLIT; + NewHook(hp, "System43b"); + return true; +} bool InsertSystem43Hook() { - if (InsertSystem43New2Hook()) + if (InsertSystem43aHook() || InsertSystem43bHook()) return true; // bool patched = Util::CheckFile(L"AliceRunPatch.dll"); bool patched = ::GetModuleHandleA("AliceRunPatch.dll"); diff --git a/cpp/LunaHook/LunaHook/engine64/yuzu.cpp b/cpp/LunaHook/LunaHook/engine64/yuzu.cpp index 87c11b52..cc294685 100644 --- a/cpp/LunaHook/LunaHook/engine64/yuzu.cpp +++ b/cpp/LunaHook/LunaHook/engine64/yuzu.cpp @@ -662,6 +662,22 @@ namespace s = std::regex_replace(s, std::regex(R"(#Color\[\d+?\])"), ""); buffer->from(s); } + void F0100CF90151E0000(TextBuffer *buffer, HookParam *hp) + { + auto ws = StringToWideString(buffer->viewA(), 932).value(); + strReplace(ws, L"^", L""); + ws = std::regex_replace(ws, std::wregex(LR"(@c\d)"), L""); + ws = std::regex_replace(ws, std::wregex(LR"(@v\(\d+\))"), L""); + buffer->from(WideStringToString(ws, 932)); + } + void F010052300F612000(TextBuffer *buffer, HookParam *hp) + { + auto s = buffer->strA(); + s = std::regex_replace(s, std::regex(R"(#r(.*?)\|(.*?)#)"), "$1"); + strReplace(s, R"(\c)", ""); + strReplace(s, R"(\n)", ""); + buffer->from(s); + } void F010001D015260000(TextBuffer *buffer, HookParam *hp) { auto s = buffer->viewA(); @@ -892,6 +908,15 @@ namespace s = std::regex_replace(s, colorRegex, L"$1"); buffer->from(s); } + void F010015600D814000(TextBuffer *buffer, HookParam *hp) + { + StringFilter(buffer, L"\\n", 2); + auto s = buffer->viewW(); + static std::wstring last; + if (last == s) + return buffer->clear(); + last = s; + } void F0100B0601852A000(TextBuffer *buffer, HookParam *hp) { auto s = buffer->viewW(); @@ -3363,6 +3388,16 @@ namespace // 猛獣たちとお姫様 for Nintendo Switch 二合一 {0x80115C70, {CODEC_UTF8, 0, 0, 0, F010001D015260000, "010035001D1B2000", "1.0.0"}}, // text {0x80115F20, {CODEC_UTF8, 0, 0, 0, F010001D015260000, "010035001D1B2000", "1.0.1"}}, // text + // BEAST Darling!-けもみみ男子と秘密の寮- + {0x80424D50, {CODEC_UTF16, 8, 0, 0, F0100B0601852A000, "010045F00BF64000", "1.0.0"}}, // text + // 恋の花咲く百花園 + {0x211464, {0, 0, 0, 0, F010052300F612000, "010052300F612000", "1.0.0"}}, // text + // 東京24区 -祈- + {0x8006F100, {0, 0, 0, 0, F0100CF90151E0000, "0100CF90151E0000", "1.0.0"}}, // text + // ディアマジ -魔法少年学科- + {0x802B1270, {CODEC_UTF16, 8, 0, 0, F010015600D814000, "010015600D814000", "1.0.0"}}, // text + {0x802B19E0, {CODEC_UTF16, 8, 0, 0, F010015600D814000, "010015600D814000", "1.0.1"}}, // text + }; return 1; }(); diff --git a/cpp/LunaHook/LunaHook/veh_hook.cpp b/cpp/LunaHook/LunaHook/veh_hook.cpp index 42a6ba0d..0bea133d 100644 --- a/cpp/LunaHook/LunaHook/veh_hook.cpp +++ b/cpp/LunaHook/LunaHook/veh_hook.cpp @@ -7,84 +7,80 @@ Version: 24-March-2008 #include #include "veh_hook.h" #include -static veh_list_t *list = NULL; -char int3bp[] = "\xCC"; +char int3bp[] = OPCODE_INT3; std::mutex vehlistlock; + +struct veh_node +{ + void *origFunc; + newFuncType newFunc; + void *handle; + DWORD hooktype; + void *baseAddr; // Address of the page in which origFunc resides. + BYTE origBaseByte; + DWORD OldProtect; + veh_node(void *origFunc, newFuncType newFunc, void *handle, DWORD hooktype) : hooktype(hooktype), handle(handle), newFunc(newFunc), origFunc(origFunc), OldProtect(PAGE_EXECUTE_READWRITE) + { + } +}; + +static std::map list; + +veh_node *get_veh_node(void *origFunc, int range = 0) +{ + for (int i = 0; i <= range; i++) + { + auto ptr = (void *)((uintptr_t)origFunc - i); + if (list.find(ptr) == list.end()) + continue; + return &list.at(ptr); + } + return nullptr; +} + bool add_veh_hook(void *origFunc, newFuncType newFunc, DWORD hook_type) { std::lock_guard _(vehlistlock); // static veh_list_t* list = NULL; DWORD oldProtect; - if (list == NULL) - list = new_veh_list(); - if (list == NULL) - return false; - if (get_veh_node(list, origFunc)) + if (get_veh_node(origFunc)) return false; void *handle = AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)veh_dispatch); - auto newnode = create_veh_node(origFunc, newFunc, handle, hook_type); - if (newnode == NULL) - return false; + veh_node newnode{origFunc, newFunc, handle, hook_type}; + // For memory hooks especially, we need to know the address of the start of the relevant page. MEMORY_BASIC_INFORMATION mem_info; VirtualQuery(origFunc, &mem_info, sizeof(MEMORY_BASIC_INFORMATION)); - newnode->baseAddr = mem_info.BaseAddress; - if (!VirtualProtect(origFunc, sizeof(int), PAGE_EXECUTE_READWRITE, &newnode->OldProtect)) + newnode.baseAddr = mem_info.BaseAddress; + if (!VirtualProtect(origFunc, sizeof(int), PAGE_EXECUTE_READWRITE, &newnode.OldProtect)) { - delete newnode; return false; } - memcpy((void *)(&newnode->origBaseByte), (const void *)origFunc, sizeof(BYTE)); + memcpy((void *)(&newnode.origBaseByte), (const void *)origFunc, sizeof(BYTE)); memcpy((void *)origFunc, (const void *)&int3bp, sizeof(BYTE)); - VirtualProtect(origFunc, sizeof(int), newnode->OldProtect, &oldProtect); - insert_veh_node(list, newnode); + VirtualProtect(origFunc, sizeof(int), newnode.OldProtect, &oldProtect); + list.emplace(std::make_pair(origFunc, newnode)); return true; } -void repair_origin(veh_node_t *node) +void repair_origin(veh_node *node) { DWORD _p; if (!VirtualProtect(node->origFunc, sizeof(int), PAGE_EXECUTE_READWRITE, &_p)) return; - memcpy((void *)node->origFunc, (const void *)(&node->origBaseByte), sizeof(char)); + memcpy((void *)node->origFunc, (const void *)(&node->origBaseByte), sizeof(BYTE)); VirtualProtect(node->origFunc, sizeof(int), node->OldProtect, &_p); } bool remove_veh_hook(void *origFunc) { std::lock_guard _(vehlistlock); - if (list == NULL) - return false; - veh_node_t *node = get_veh_node(list, origFunc); + veh_node *node = get_veh_node(origFunc); if (node == NULL) return false; repair_origin(node); RemoveVectoredExceptionHandler(node->handle); - return remove_veh_node(list, origFunc), true; + return list.erase(origFunc), true; } -void remove_veh_node(veh_list_t *list, void *origFunc) -{ - veh_node_t *searchnode = list->head; - - while (searchnode != NULL) - { - if (searchnode->origFunc == origFunc) - { - if (list->tail == searchnode) - list->tail = searchnode->last; - if (list->head == searchnode) - list->head = searchnode->next; - if (searchnode->last) - searchnode->last->next = searchnode->next; - if (searchnode->next) - searchnode->next->last = searchnode->last; - - delete (searchnode); - return; - } - searchnode = searchnode->next; - } - return; -} LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo) { @@ -98,10 +94,10 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo) if (Code == STATUS_BREAKPOINT) //&& hooktype == VEH_HK_INT3) { - veh_node_t *currnode; + veh_node *currnode; { std::lock_guard _(vehlistlock); - currnode = get_veh_node(list, Addr); + currnode = get_veh_node(Addr); } if (currnode == NULL) return EXCEPTION_CONTINUE_SEARCH; @@ -119,7 +115,7 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo) else if (Code == STATUS_SINGLE_STEP) //&& hooktype == VEH_HK_INT3) { std::lock_guard _(vehlistlock); - veh_node_t *currnode = get_veh_node(list, Addr, 0x10); + veh_node *currnode = get_veh_node(Addr, 0x10); if (currnode == NULL) return EXCEPTION_CONTINUE_SEARCH; @@ -138,64 +134,4 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo) // currnode->newFunc(ExceptionInfo->ContextRecord); // } return EXCEPTION_CONTINUE_EXECUTION; -} - -veh_list_t *new_veh_list() -{ - veh_list_t *newlist = (veh_list_t *)malloc(sizeof(veh_list_t)); - if (newlist == NULL) - return NULL; - newlist->head = NULL; - newlist->tail = NULL; - return newlist; -} -veh_node_t *create_veh_node(void *origFunc, newFuncType newFunc, void *handle, DWORD hook_type) -{ - veh_node_t *newnode = new veh_node_t; - if (newnode == NULL) - return NULL; - newnode->last = NULL; - newnode->origFunc = origFunc; - newnode->newFunc = newFunc; - newnode->handle = handle; - newnode->OldProtect = PAGE_EXECUTE_READWRITE; - newnode->next = NULL; - newnode->hooktype = hook_type; - return newnode; -} -void insert_veh_node(veh_list_t *list, veh_node_t *newnode) -{ - if (list == NULL) - return; - if (list->head == NULL) - { - list->head = newnode; - list->tail = newnode; - } - else - { - list->tail->next = newnode; - newnode->last = list->tail; - list->tail = newnode; - } -} -veh_node_t *get_veh_node(veh_list_t *list, void *origFunc, int range) -{ - veh_node_t *newnode; - veh_node_t *closestnode = NULL; - if (list == NULL) - return NULL; - newnode = list->head; - while (newnode != NULL) - { - if (((uintptr_t)origFunc - (uintptr_t)newnode->origFunc) <= range) - { - closestnode = newnode; - if (range == 0) - break; - range = ((uintptr_t)origFunc - (uintptr_t)newnode->origFunc); - } - newnode = newnode->next; - } - return closestnode; -} +} \ No newline at end of file diff --git a/cpp/LunaHook/LunaHook/veh_hook.h b/cpp/LunaHook/LunaHook/veh_hook.h index 2ff9cedf..e34c0d6f 100644 --- a/cpp/LunaHook/LunaHook/veh_hook.h +++ b/cpp/LunaHook/LunaHook/veh_hook.h @@ -21,25 +21,6 @@ Version: 24-March-2008 // typedef void (*newFuncType)(PCONTEXT); using newFuncType = std::function; -typedef struct veh_node -{ - struct veh_node *last; - struct veh_node *next; - void *origFunc; - newFuncType newFunc; - void *handle; - DWORD hooktype; - void *baseAddr; // Address of the page in which origFunc resides. - BYTE origBaseByte; - DWORD OldProtect; -} veh_node_t; - -typedef struct -{ - veh_node_t *head; - veh_node_t *tail; -} veh_list_t; - // VEH hook interface functions for creating and removing hooks. bool add_veh_hook(void *origFunc, newFuncType newFunc, DWORD hook_type = VEH_HK_INT3); bool remove_veh_hook(void *origFunc); @@ -49,10 +30,5 @@ bool remove_veh_hook(void *origFunc); LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo); // Functions used internally by the library. -veh_list_t *new_veh_list(); -veh_node_t *create_veh_node(void *origFunc, newFuncType newFunc, void *handle, DWORD hook_type); -void insert_veh_node(veh_list_t *list, veh_node_t *); -void remove_veh_node(veh_list_t *list, void *origFunc); -veh_node_t *get_veh_node(veh_list_t *list, void *origFunc, int range = 0); #endif // LIST_T_H_INCLUDED diff --git a/cpp/version.cmake b/cpp/version.cmake index 45d0641b..ba95639b 100644 --- a/cpp/version.cmake +++ b/cpp/version.cmake @@ -1,7 +1,7 @@ set(VERSION_MAJOR 6) set(VERSION_MINOR 6) -set(VERSION_PATCH 4) +set(VERSION_PATCH 5) set(VERSION_REVISION 0) set(LUNA_VERSION "{${VERSION_MAJOR},${VERSION_MINOR},${VERSION_PATCH},${VERSION_REVISION}}") add_library(VERSION_DEF INTERFACE)