Skip to content

Commit

Permalink
.
Browse files Browse the repository at this point in the history
  • Loading branch information
HIllya51 committed Dec 26, 2024
1 parent 0b9ccb4 commit 2a245d7
Show file tree
Hide file tree
Showing 9 changed files with 119 additions and 83 deletions.
16 changes: 12 additions & 4 deletions cpp/LunaHook/LunaHook/engine64/yuzu.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -752,6 +752,10 @@ namespace
StringReplacer(buffer, "#n", 2, " ", 1);
StringReplacer(buffer, "\n", 1, " ", 1);
}
void F010099901461A000(TextBuffer *buffer, HookParam *hp)
{
StringFilter(buffer, "#n", 2);
}
void F0100AEC013DDA000(TextBuffer *buffer, HookParam *hp)
{
auto s = buffer->strA();
Expand Down Expand Up @@ -2476,10 +2480,6 @@ namespace
// VARIABLE BARRICADE NS
{0x800e3424, {CODEC_UTF8, 0, 0, 0, F010045C0109F2000, 0x010045C0109F2000ull, "1.0.1"}}, //"System Messages + Choices"), //Also includes the names of characters,
{0x800fb080, {CODEC_UTF8, 3, 0, 0, F010045C0109F2000, 0x010045C0109F2000ull, "1.0.1"}}, // Main Text
// AMNESIA for Nintendo Switch
{0x805bba5c, {CODEC_UTF16, 2, 0, ReadTextAndLenDW, F0100A1E00BFEA000, 0x0100A1E00BFEA000ull, "1.0.1"}}, // dialogue
{0x805e9930, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100A1E00BFEA000, 0x0100A1E00BFEA000ull, "1.0.1"}}, // choice
{0x805e7fd8, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100A1E00BFEA000, 0x0100A1E00BFEA000ull, "1.0.1"}}, // name
// 蝶の毒 華の鎖
{0x80095010, {CODEC_UTF16, 1, 0, 0, F0100A1200CA3C000, 0x0100A1200CA3C000ull, "2.0.1"}}, // Main Text + Names
// Live a Live
Expand Down Expand Up @@ -2681,6 +2681,12 @@ namespace
{0x8014dc64, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100982015606000, 0x0100B5700CDFC000ull, "1.0.0"}}, // name
{0x80149b10, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100982015606000, 0x0100B5700CDFC000ull, "1.0.0"}}, // dialogue
{0x803add50, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100982015606000, 0x0100B5700CDFC000ull, "1.0.0"}}, // choice
// AMNESIA for Nintendo Switch
{0x805bba5c, {CODEC_UTF16, 2, 0, ReadTextAndLenDW, F0100A1E00BFEA000, 0x0100A1E00BFEA000ull, "1.0.1"}}, // dialogue
{0x805e9930, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100A1E00BFEA000, 0x0100A1E00BFEA000ull, "1.0.1"}}, // choice
{0x805e7fd8, {CODEC_UTF16, 1, 0, ReadTextAndLenDW, F0100A1E00BFEA000, 0x0100A1E00BFEA000ull, "1.0.1"}}, // name
// AMNESIA World for Nintendo Switch
{0x80113520, {CODEC_UTF8, 3, 0, 0, F010099901461A000, 0x010099901461A000ull, "1.0.0"}}, // text
// Natsumon! 20th Century Summer Vacation
{0x80db5d34, {CODEC_UTF16, 0, 0, 0, F0100A8401A0A8000, 0x0100A8401A0A8000ull, "1.1.0"}}, // tutorial
{0x846fa578, {CODEC_UTF16, 0, 0, 0, F0100A8401A0A8000, 0x0100A8401A0A8000ull, "1.1.0"}}, // choice
Expand Down Expand Up @@ -3575,6 +3581,8 @@ namespace
{0x81719ea0, {CODEC_UTF16, 0, 0, ReadTextAndLenDW, F01001BB01E8E2000, 0x01001BB01E8E2000ull, "1.0.0"}},
// アイキス3cute
{0x804C18C4, {CODEC_UTF8, 1, 0, 0, F0100FD4016528000, 0x0100FD4016528000ull, nullptr}}, // 1.0.0 && 1.0.2
// OZMAFIA!! VIVACE
{0x80058544, {0, 1, 0, 0, F0100509013040000, 0x01002BE0118AE000ull, nullptr}}, // 1.0.0 && 1.0.1

};
return 1;
Expand Down
22 changes: 7 additions & 15 deletions cpp/LunaHook/LunaHook/hookfinder.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include "MinHook.h"
#include "veh_hook.h"
#define DUMP_JIT_ADDR_MAP 0
namespace
{
Expand Down Expand Up @@ -258,10 +259,6 @@ void SafeSendJitVeh(hook_context *context, uintptr_t address, uint64_t em_addr,
std::unordered_map<uintptr_t, uint64_t> addresscalledtime;
bool SendJitVeh(PCONTEXT pcontext, uintptr_t address, uint64_t em_addr, JITTYPE jittype, intptr_t padding)
{
if (safeautoleaveveh)
return true;
if (recordsAvailable <= 0)
return false;
if (addresscalledtime.find(address) == addresscalledtime.end())
addresscalledtime[address] = 0;
auto tm = GetTickCount64();
Expand Down Expand Up @@ -542,9 +539,7 @@ void _SearchForHooks(SearchParam spUser)
}
else
{
safeautoleaveveh = false;

std::vector<uint64_t> successaddr;
uintptr_t minemaddr = -1, maxemaddr = 0;

ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], jitaddr2emuaddr.size());
Expand All @@ -564,25 +559,22 @@ void _SearchForHooks(SearchParam spUser)
}
fclose(f);
#endif
std::vector<newFuncType> funcs;
std::vector<void *> successaddr;
for (auto addr : jitaddr2emuaddr)
{
// ConsoleOutput("%llx => %p", addr.second.second ,addr.first);
if (addr.second.second > sp.maxAddress || addr.second.second < sp.minAddress)
continue;

// addresses.push_back(addr.first);
if (add_veh_hook((void *)addr.first, std::bind(SendJitVeh, std::placeholders::_1, addr.first, addr.second.second, addr.second.first, sp.padding)))
successaddr.push_back(addr.first);
if (successaddr.size() % 2500 == 0)
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZING], 1 + 98. * successaddr.size() / jitaddr2emuaddr.size());
funcs.push_back(std::bind(SendJitVeh, std::placeholders::_1, addr.first, addr.second.second, addr.second.first, sp.padding));
successaddr.push_back((void *)addr.first);
}
successaddr = add_veh_hook(successaddr, funcs);
ConsoleOutput(TR[HOOK_SEARCH_INITIALIZED], successaddr.size());
ConsoleOutput(TR[MAKE_GAME_PROCESS_TEXT], sp.searchTime / 1000);
Sleep(sp.searchTime);
// for(auto addr:successaddr){
// remove_veh_hook((void*)addr);
// }
safeautoleaveveh = true;
remove_veh_hook(successaddr);
}
SearchForHooks_Return();
}
Expand Down
1 change: 0 additions & 1 deletion cpp/LunaHook/LunaHook/main.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,5 @@ void jitaddrclear();

void delayinsertadd(HookParam, std::string);
void delayinsertNewHook(uint64_t);
inline bool safeautoleaveveh = false;
inline bool dont_detach = false;
inline bool host_connected = false;
1 change: 0 additions & 1 deletion cpp/LunaHook/LunaHook/pchhook.h
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,6 @@
#include "embed_util.h"
#include "hijackfuns.h"

#include "veh_hook.h"
#include "engines/emujitarg.hpp"
#include "engines/mono/monoil2cpp.h"
#include "hookfinder.h"
Expand Down
13 changes: 4 additions & 9 deletions cpp/LunaHook/LunaHook/texthook.cc
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@

#include "MinHook.h"
#include "veh_hook.h"
extern WinMutex viewMutex;

// - Unnamed helpers -
Expand Down Expand Up @@ -137,13 +138,7 @@ bool TextHook::Insert(HookParam hp)
if (hp.type & DIRECT_READ)
return InsertReadCode();
if (hp.type & BREAK_POINT)
{
if (InsertBreakPoint())
return true;
if (safeautoleaveveh)
return InsertBreakPoint(); // 搜索特殊码后,不会释放,导致virtualprotect查询失败,重试。
return false;
}
return InsertBreakPoint();
return InsertHookCode();
}
uintptr_t win64find0000(uintptr_t addr)
Expand Down Expand Up @@ -453,9 +448,9 @@ bool TextHook::InsertBreakPoint()
// MH_CreateHook 64位unity/yuzu-emu经常 MH_ERROR_MEMORY_ALLOC
return add_veh_hook(location, std::bind(&TextHook::breakpointcontext, this, std::placeholders::_1));
}
bool TextHook::RemoveBreakPoint()
void TextHook::RemoveBreakPoint()
{
return remove_veh_hook(location);
remove_veh_hook(location);
}
bool TextHook::InsertHookCode()
{
Expand Down
2 changes: 1 addition & 1 deletion cpp/LunaHook/LunaHook/texthook.h
Original file line number Diff line number Diff line change
Expand Up @@ -16,14 +16,14 @@ class TextHook
bool InsertHookCode();
bool InsertReadCode();
bool InsertBreakPoint();
bool RemoveBreakPoint();
bool breakpointcontext(PCONTEXT);
void Send(uintptr_t);
void Send(hook_context*);
int GetLength(hook_context *context, uintptr_t in); // jichi 12/25/2013: Return 0 if failed
int HookStrlen(BYTE *data);
void RemoveHookCode();
void RemoveReadCode();
void RemoveBreakPoint();
bool waitfornotify(TextBuffer*, ThreadParam tp);
void parsenewlineseperator(TextBuffer*);
volatile DWORD useCount;
Expand Down
139 changes: 90 additions & 49 deletions cpp/LunaHook/LunaHook/veh_hook.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@ Version: 24-March-2008
#include <windows.h>
#include "veh_hook.h"
#include <mutex>
char int3bp[] = OPCODE_INT3;
std::mutex vehlistlock;

struct veh_node
{
void *origFunc;
Expand All @@ -19,32 +17,34 @@ struct veh_node
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)
int usecount;
bool removed;
veh_node(void *origFunc, newFuncType newFunc, void *handle, DWORD hooktype) : hooktype(hooktype), handle(handle), newFunc(newFunc), origFunc(origFunc), OldProtect(PAGE_EXECUTE_READWRITE), usecount(0), removed(false)
{
}
};

static std::map<void *, veh_node> list;

veh_node *get_veh_node(void *origFunc, int range = 0)
veh_node *get_veh_node(void *origFunc)
{
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;
if (list.find(origFunc) == list.end())
return nullptr;
return &list.at(origFunc);
}

bool add_veh_hook(void *origFunc, newFuncType newFunc, DWORD hook_type)
bool __add_veh_hook(void *origFunc, newFuncType newFunc, DWORD hook_type)
{
std::lock_guard _(vehlistlock);
// static veh_list_t* list = NULL;
DWORD oldProtect;
if (get_veh_node(origFunc))
return false;
auto hasexitst = get_veh_node(origFunc); // hookfinder不删除钩子
if (hasexitst)
{
if (!hasexitst->removed)
return false;
hasexitst->newFunc = newFunc;
hasexitst->removed = false;
return true;
}
void *handle = AddVectoredExceptionHandler(1, (PVECTORED_EXCEPTION_HANDLER)veh_dispatch);
veh_node newnode{origFunc, newFunc, handle, hook_type};

Expand All @@ -56,31 +56,75 @@ bool add_veh_hook(void *origFunc, newFuncType newFunc, DWORD hook_type)
{
return false;
}
memcpy((void *)(&newnode.origBaseByte), (const void *)origFunc, sizeof(BYTE));
memcpy((void *)origFunc, (const void *)&int3bp, sizeof(BYTE));
newnode.origBaseByte = *(BYTE *)origFunc;
*(BYTE *)origFunc = OPCODE_INT3;
VirtualProtect(origFunc, sizeof(int), newnode.OldProtect, &oldProtect);
list.emplace(std::make_pair(origFunc, newnode));
return true;
}

bool add_veh_hook(void *origFunc, newFuncType newFunc, DWORD hook_type)
{
std::lock_guard _(vehlistlock);
return __add_veh_hook(origFunc, newFunc, hook_type);
}
std::vector<void *> add_veh_hook(std::vector<void *> origFuncs, std::vector<newFuncType> newFuncs, DWORD hook_type)
{
std::lock_guard _(vehlistlock);
std::vector<void *> succ;
for (auto i = 0; i < origFuncs.size(); i++)
{
if (__add_veh_hook(origFuncs[i], newFuncs[i], hook_type))
succ.push_back(origFuncs[i]);
}
return succ;
}
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(BYTE));
*(BYTE *)node->origFunc = node->origBaseByte;
VirtualProtect(node->origFunc, sizeof(int), node->OldProtect, &_p);
}
bool remove_veh_hook(void *origFunc)
bool __remove_veh_hook(void *origFunc)
{
std::lock_guard _(vehlistlock);
veh_node *node = get_veh_node(origFunc);
if (node == NULL)
if (!node)
return true;
if (node->usecount <= 0)
{
repair_origin(node);
RemoveVectoredExceptionHandler(node->handle);
list.erase(origFunc);
return true;
}
else
{
node->removed = true;
return false;
repair_origin(node);
RemoveVectoredExceptionHandler(node->handle);
return list.erase(origFunc), true;
}
}

void remove_veh_hook(void *origFunc)
{
// 仅会在手动移除时被调用
while (true)
{
std::lock_guard _(vehlistlock);
if (__remove_veh_hook(origFunc))
break;
}
}
void remove_veh_hook(std::vector<void *> origFuncs)
{
std::lock_guard _(vehlistlock);
for (auto origFunc : origFuncs)
{
// hookfinder时,usecount有时会无法归零(例如JIT重新写code),所以仅尝试一次即可
__remove_veh_hook(origFunc);
}
}
thread_local veh_node *lastnode;
LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo)
{

Expand All @@ -92,37 +136,34 @@ LONG CALLBACK veh_dispatch(PEXCEPTION_POINTERS ExceptionInfo)
return EXCEPTION_CONTINUE_SEARCH;
// Try to find the node associated with the address of the current exception, continue searching for handlers if not found;

std::lock_guard _(vehlistlock);
if (Code == STATUS_BREAKPOINT) //&& hooktype == VEH_HK_INT3)
{
veh_node *currnode;
{
std::lock_guard _(vehlistlock);
currnode = get_veh_node(Addr);
}
if (currnode == NULL)
veh_node *currnode = get_veh_node(Addr);
if (!currnode)
return EXCEPTION_CONTINUE_SEARCH;

if (currnode->newFunc(ExceptionInfo->ContextRecord))
lastnode = currnode;
repair_origin(currnode);
if (!currnode->removed)
{
repair_origin(currnode);
ExceptionInfo->ContextRecord->EFlags |= 0x100;
}
else
{
remove_veh_hook(Addr);
currnode->usecount += 1;
if (currnode->newFunc(ExceptionInfo->ContextRecord))
ExceptionInfo->ContextRecord->EFlags |= 0x100;
}
}
else if (Code == STATUS_SINGLE_STEP) //&& hooktype == VEH_HK_INT3)
{
std::lock_guard _(vehlistlock);
veh_node *currnode = get_veh_node(Addr, 0x10);
if (currnode == NULL)
if (!lastnode)
return EXCEPTION_CONTINUE_SEARCH;

VirtualProtect(Addr, sizeof(int), PAGE_EXECUTE_READWRITE, &currnode->OldProtect);
memcpy((void *)currnode->origFunc, (const void *)&int3bp, sizeof(BYTE));
VirtualProtect(Addr, sizeof(int), currnode->OldProtect, &oldProtect);
ExceptionInfo->ContextRecord->EFlags &= ~0x00000100; // Remove TRACE from EFLAGS
if (!lastnode->removed)
{
VirtualProtect(Addr, sizeof(int), PAGE_EXECUTE_READWRITE, &lastnode->OldProtect);
*(BYTE *)lastnode->origFunc = OPCODE_INT3;
VirtualProtect(Addr, sizeof(int), lastnode->OldProtect, &oldProtect);
ExceptionInfo->ContextRecord->EFlags &= ~0x00000100; // Remove TRACE from EFLAGS
}
lastnode->usecount -= 1;
lastnode = nullptr;
}
// else if (Code == STATUS_SINGLE_STEP && hooktype == VEH_HK_HW)
// {
Expand Down
6 changes: 4 additions & 2 deletions cpp/LunaHook/LunaHook/veh_hook.h
Original file line number Diff line number Diff line change
Expand Up @@ -15,15 +15,17 @@ Version: 24-March-2008
#define VEH_HK_HW 2
// -

#define OPCODE_INT3 "\xCC"
#define OPCODE_INT3 '\xCC'

// typedef void (*pfvoid)();
// typedef void (*newFuncType)(PCONTEXT);
using newFuncType = std::function<bool(PCONTEXT)>;

// 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);
std::vector<void *> add_veh_hook(std::vector<void *>origFuncs, std::vector<newFuncType> newFuncs, DWORD hook_type = VEH_HK_INT3);
void remove_veh_hook(void *origFunc);
void remove_veh_hook(std::vector<void *>origFuncs);

// The VEH dispathing function is called by Windows every time an exception is encountered.
// the function dispatches calls to the correct inctercept function.
Expand Down
Loading

0 comments on commit 2a245d7

Please sign in to comment.