diff --git a/LunaHook/engine32/cef.cpp b/LunaHook/engine32/cef.cpp index a6c8038..eb59fff 100644 --- a/LunaHook/engine32/cef.cpp +++ b/LunaHook/engine32/cef.cpp @@ -1,118 +1,130 @@ -#include"cef.h" +#include "cef.h" typedef wchar_t char16; -typedef struct _cef_string_wide_t { - wchar_t* str; +typedef struct _cef_string_wide_t +{ + wchar_t *str; size_t length; - void (*dtor)(wchar_t* str); + void (*dtor)(wchar_t *str); } cef_string_wide_t; -typedef struct _cef_string_utf8_t { - char* str; +typedef struct _cef_string_utf8_t +{ + char *str; size_t length; - void (*dtor)(char* str); + void (*dtor)(char *str); } cef_string_utf8_t; -typedef struct _cef_string_utf16_t { - char16* str; +typedef struct _cef_string_utf16_t +{ + char16 *str; size_t length; - void (*dtor)(char16* str); + void (*dtor)(char16 *str); } cef_string_utf16_t; -static void hook_cef_string_utf16_t(hook_stack* stack, HookParam *hp, uintptr_t* data, uintptr_t* split, size_t* len) +static void hook_cef_string_utf16_t(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len) { - if (auto p = (_cef_string_utf16_t*)stack->stack[1]) { + if (auto p = (_cef_string_utf16_t *)stack->stack[1]) + { *data = (DWORD)p->str; *len = p->length; // for widechar 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; + s = *(DWORD *)s; else break; if (!s) s = hp->address; - if (hp->type & USING_SPLIT) *split = s; + if (hp->type & USING_SPLIT) + *split = s; } } -static void hook_cef_string_wide_t(hook_stack* stack, HookParam *hp, uintptr_t* data, uintptr_t* split, size_t* len) +static void hook_cef_string_wide_t(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len) { - if (auto p = (_cef_string_wide_t*)stack->stack[1]) { + if (auto p = (_cef_string_wide_t *)stack->stack[1]) + { *data = (DWORD)p->str; *len = p->length; // for widechar 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; + s = *(DWORD *)s; else break; if (!s) s = hp->address; - if (hp->type & USING_SPLIT) *split = s; + if (hp->type & USING_SPLIT) + *split = s; } } -static void hook_cef_string_utf8_t(hook_stack* stack, HookParam *hp, uintptr_t* data, uintptr_t* split, size_t* len) +static void hook_cef_string_utf8_t(hook_stack *stack, HookParam *hp, uintptr_t *data, uintptr_t *split, size_t *len) { - if (auto p = (_cef_string_utf8_t*)stack->stack[1]) { + if (auto p = (_cef_string_utf8_t *)stack->stack[1]) + { *data = (DWORD)p->str; *len = p->length; // for widechar 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; + s = *(DWORD *)s; else break; if (!s) s = hp->address; - if (hp->type & USING_SPLIT) *split = s; + if (hp->type & USING_SPLIT) + *split = s; } } bool InsertlibcefHook(HMODULE module) { - if (!module)return false; + if (!module) + return false; bool ret = false; - - struct libcefFunction { // argument indices start from 0 for SpecialHookMonoString, otherwise 1 - const char* functionName; - size_t textIndex; // argument index - short lengthIndex; // argument index + struct libcefFunction + { // argument indices start from 0 for SpecialHookMonoString, otherwise 1 + const char *functionName; + size_t textIndex; // argument index + short lengthIndex; // argument index unsigned long hookType; // HookParam type - void* text_fun; // HookParam::text_fun_t - }; + void *text_fun; // HookParam::text_fun_t + }; HookParam hp; const libcefFunction funcs[] = { - {"cef_string_utf8_set",1,0,USING_STRING | CODEC_UTF8 | NO_CONTEXT,NULL}, //ok - {"cef_string_utf8_to_utf16",1,0,USING_STRING | CODEC_UTF8 | NO_CONTEXT,NULL}, - {"cef_string_utf8_to_wide",1,0,USING_STRING | CODEC_UTF8 | NO_CONTEXT,NULL}, //ok - {"cef_string_utf8_clear",0,0,USING_STRING | CODEC_UTF8 | NO_CONTEXT,hook_cef_string_utf8_t}, + {"cef_string_utf8_set", 1, 0, USING_STRING | CODEC_UTF8 | NO_CONTEXT, NULL}, // ok + {"cef_string_utf8_to_utf16", 1, 0, USING_STRING | CODEC_UTF8 | NO_CONTEXT, NULL}, + {"cef_string_utf8_to_wide", 1, 0, USING_STRING | CODEC_UTF8 | NO_CONTEXT, NULL}, // ok + {"cef_string_utf8_clear", 0, 0, USING_STRING | CODEC_UTF8 | NO_CONTEXT, hook_cef_string_utf8_t}, - {"cef_string_utf16_set",1,0,USING_STRING|CODEC_UTF16 | NO_CONTEXT,NULL}, //ok - {"cef_string_utf16_clear",0,0,USING_STRING|CODEC_UTF16,hook_cef_string_utf16_t},//ok - {"cef_string_utf16_to_utf8",1,0,USING_STRING|CODEC_UTF16 | NO_CONTEXT,NULL},//ok - {"cef_string_utf16_to_wide",1,0,USING_STRING|CODEC_UTF16 | NO_CONTEXT,NULL}, + {"cef_string_utf16_set", 1, 0, USING_STRING | CODEC_UTF16 | NO_CONTEXT, NULL}, // ok + {"cef_string_utf16_clear", 0, 0, USING_STRING | CODEC_UTF16, hook_cef_string_utf16_t}, // ok + {"cef_string_utf16_to_utf8", 1, 0, USING_STRING | CODEC_UTF16 | NO_CONTEXT, NULL}, // ok + {"cef_string_utf16_to_wide", 1, 0, USING_STRING | CODEC_UTF16 | NO_CONTEXT, NULL}, - {"cef_string_ascii_to_utf16",1,0,USING_STRING | NO_CONTEXT,NULL}, - {"cef_string_ascii_to_wide",1,0,USING_STRING | NO_CONTEXT,NULL}, + {"cef_string_ascii_to_utf16", 1, 0, USING_STRING | NO_CONTEXT, NULL}, + {"cef_string_ascii_to_wide", 1, 0, USING_STRING | NO_CONTEXT, NULL}, - {"cef_string_wide_set",1,0,USING_STRING | CODEC_UTF16 | NO_CONTEXT,NULL},//ok - {"cef_string_wide_to_utf16",1,0,USING_STRING| CODEC_UTF16 | NO_CONTEXT,NULL}, - {"cef_string_wide_to_utf8",1,0,USING_STRING | CODEC_UTF16 | NO_CONTEXT,NULL}, - {"cef_string_wide_clear",0,0,USING_STRING|CODEC_UTF16,hook_cef_string_wide_t} - }; - for (auto func : funcs) { - if (FARPROC addr = ::GetProcAddress(module, func.functionName)) { - if (addr == 0)continue; + {"cef_string_wide_set", 1, 0, USING_STRING | CODEC_UTF16 | NO_CONTEXT, NULL}, // ok + {"cef_string_wide_to_utf16", 1, 0, USING_STRING | CODEC_UTF16 | NO_CONTEXT, NULL}, + {"cef_string_wide_to_utf8", 1, 0, USING_STRING | CODEC_UTF16 | NO_CONTEXT, NULL}, + {"cef_string_wide_clear", 0, 0, USING_STRING | CODEC_UTF16, hook_cef_string_wide_t}}; + for (auto func : funcs) + { + if (FARPROC addr = ::GetProcAddress(module, func.functionName)) + { + if (addr == 0) + continue; hp.address = (DWORD)addr; - hp.type = func.hookType; + hp.type = func.hookType; hp.offset = func.textIndex * 4; hp.length_offset = func.lengthIndex * 4; hp.text_fun = (decltype(hp.text_fun))func.text_fun; ConsoleOutput("libcef: INSERT"); - ret|=NewHook(hp, func.functionName); + ret |= NewHook(hp, func.functionName); } } @@ -120,65 +132,89 @@ bool InsertlibcefHook(HMODULE module) ConsoleOutput("libcef: failed to find function address"); return ret; } -bool libcefhook(HMODULE module) { - //https://vndb.org/v12297 - //魔降ル夜ノ凜 Animation ダウンロード版 +namespace +{ + bool ceffileter(void *data, uintptr_t *size, HookParam *hp) + { + auto s = std::wstring((wchar_t *)data, *size / 2); + if (s == *(std::wstring *)(hp->user_value)) + return false; + *(std::wstring *)(hp->user_value) = s; + return true; + }; +} +bool libcefhook(HMODULE module) +{ + // https://vndb.org/v12297 + // 魔降ル夜ノ凜 Animation ダウンロード版 - if (module == 0)return false; auto [minAddress, maxAddress] = Util::QueryModuleLimits(module); - ConsoleOutput("check v8libcefhook %p %p", minAddress,maxAddress); + ConsoleOutput("check v8libcefhook %p %p", minAddress, maxAddress); const BYTE bytes[] = { 0x50, 0x51, 0x52, 0x57, - 0xff,0xd6, - 0x83,0xc4,0x10, - 0x8b,0x4d,XX, - 0x89,0xc6, - 0x31,0xe9, - 0xe8,XX4, - 0x89,0xF0, - 0x83,0xC4,0x18, + 0xff, 0xd6, + 0x83, 0xc4, 0x10, + 0x8b, 0x4d, XX, + 0x89, 0xc6, + 0x31, 0xe9, + 0xe8, XX4, + 0x89, 0xF0, + 0x83, 0xC4, 0x18, 0x5e, 0x5f, 0x5d, 0xc3 }; - auto addr = reverseFindBytes(bytes, sizeof(bytes), minAddress, maxAddress); + // 対魔忍ユキカゼ2Animation + const BYTE bytes2[] = { + 0x51, + 0x57, + 0x52, + 0x50, + 0xff, 0xd6, + 0x83, 0xc4, 0x10, + 0x8b, 0x4d, XX, + 0x89, 0xc6, + 0x31, 0xe9, + 0xe8, XX4, + 0x89, 0xF0, + 0x83, 0xC4, 0x18, + 0x5e, + 0x5f, + 0x5b, + 0x5d, + 0xc3 - HookParam hp; - hp.address = addr+6; - hp.offset=get_stack(1); - hp.filter_fun=[] (void* data, uintptr_t * size, HookParam*) { - std::wstring s = L""; - int i = 0; - for (; i < *size /2; i++) { - auto c = ((LPWSTR)data)[i]; - if (c == L'[') { - break; - } - else { - s += c; - } - } - strReplace(s,L"
",L"\n"); - static std::wstring last; - if(s==last)return false; - last=s; - return write_string_overwrite(data,size,s); }; - hp.type = USING_STRING | CODEC_UTF16|NO_CONTEXT; - ConsoleOutput("v8libcefhook %p", addr); - - return NewHook(hp, "v8libcefhook"); - + bool succ = false; + for (auto addrs : {Util::SearchMemory(bytes, sizeof(bytes), PAGE_EXECUTE_READWRITE, minAddress, maxAddress), Util::SearchMemory(bytes2, sizeof(bytes2), PAGE_EXECUTE_READWRITE, minAddress, maxAddress)}) + { + for (auto addr : addrs) + { + HookParam hp; + hp.address = addr + 4; + hp.offset = get_stack(1); + hp.filter_fun = ceffileter; + hp.newlineseperator = L"
"; + hp.length_offset = 2; + hp.type = USING_STRING | CODEC_UTF16 | NO_CONTEXT; + hp.user_value = (DWORD) new std::wstring; + succ |= NewHook(hp, "libcef"); + } + } + return succ; } -bool cef::attach_function(){ +bool cef::attach_function() +{ auto hm = GetModuleHandleW(L"libcef.dll"); - - //InsertlibcefHook(hm); - + + if (!hm) + return false; + // InsertlibcefHook(hm); + return libcefhook(hm); } \ No newline at end of file