This commit is contained in:
恍兮惚兮 2024-11-25 20:41:11 +08:00
parent 239b8231f3
commit 9be975e15f
5 changed files with 115 additions and 167 deletions

View File

@ -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<LPSTR>(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");

View File

@ -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;
}();

View File

@ -7,84 +7,80 @@ Version: 24-March-2008
#include <windows.h>
#include "veh_hook.h"
#include <mutex>
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<void *, veh_node> 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;
}
}

View File

@ -21,25 +21,6 @@ Version: 24-March-2008
// typedef void (*newFuncType)(PCONTEXT);
using newFuncType = std::function<bool(PCONTEXT)>;
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

View File

@ -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)