Textractor_test/texthook/main.cc

198 lines
5.9 KiB
C++
Raw Normal View History

2018-08-23 23:53:23 +08:00
// main.cc
// 8/24/2013 jichi
// Branch: ITH_DLL/main.cpp, rev 128
// 8/24/2013 TODO: Clean up this file
#include "main.h"
#include "defs.h"
#include "engine/match.h"
2018-11-11 12:29:12 +08:00
#include "texthook.h"
2019-06-02 14:09:17 +08:00
#include "hookfinder.h"
2019-01-04 06:52:16 +08:00
#include "util.h"
2018-08-23 23:53:23 +08:00
2019-02-28 00:33:17 +08:00
extern const char* PIPE_CONNECTED;
extern const char* INSERTING_HOOK;
extern const char* REMOVING_HOOK;
extern const char* HOOK_FAILED;
extern const char* TOO_MANY_HOOKS;
2019-06-02 14:09:17 +08:00
extern const char* STARTING_SEARCH;
2019-02-28 00:33:17 +08:00
extern const char* NOT_ENOUGH_TEXT;
extern const char* COULD_NOT_FIND;
WinMutex viewMutex;
2018-08-25 00:50:20 +08:00
2018-11-11 13:34:42 +08:00
namespace
{
2018-12-02 04:52:52 +08:00
AutoHandle<> hookPipe = INVALID_HANDLE_VALUE, mappedFile = INVALID_HANDLE_VALUE;
TextHook (*hooks)[MAX_HOOK];
2018-11-11 13:34:42 +08:00
bool running;
2018-12-02 04:52:52 +08:00
int currentHook = 0;
2018-11-11 13:34:42 +08:00
}
2018-11-11 12:29:12 +08:00
DWORD WINAPI Pipe(LPVOID)
{
while (running)
{
DWORD count = 0;
BYTE buffer[PIPE_BUFFER_SIZE] = {};
2018-12-02 04:52:52 +08:00
AutoHandle<> hostPipe = INVALID_HANDLE_VALUE;
hookPipe = INVALID_HANDLE_VALUE;
2018-11-11 12:29:12 +08:00
while (!hostPipe || !hookPipe)
2018-11-11 12:29:12 +08:00
{
WinMutex connectionMutex(CONNECTING_MUTEX, &allAccess);
std::scoped_lock lock(connectionMutex);
WaitForSingleObject(AutoHandle<>(CreateEventW(&allAccess, FALSE, FALSE, PIPE_AVAILABLE_EVENT)), INFINITE);
hostPipe = CreateFileW(HOST_PIPE, GENERIC_READ | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
hookPipe = CreateFileW(HOOK_PIPE, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
2018-11-11 12:29:12 +08:00
}
DWORD mode = PIPE_READMODE_MESSAGE;
SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL);
2018-11-11 12:29:12 +08:00
*(DWORD*)buffer = GetCurrentProcessId();
WriteFile(hookPipe, buffer, sizeof(DWORD), &count, nullptr);
2018-11-11 13:34:42 +08:00
ConsoleOutput(PIPE_CONNECTED);
2018-11-11 12:29:12 +08:00
Engine::Hijack();
while (running && ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE, &count, nullptr))
switch (*(HostCommandType*)buffer)
{
case HOST_COMMAND_NEW_HOOK:
{
auto info = *(InsertHookCmd*)buffer;
2018-12-02 04:52:52 +08:00
NewHook(info.hp, "UserHook", 0);
2018-11-11 12:29:12 +08:00
}
break;
2019-06-02 14:09:17 +08:00
case HOST_COMMAND_FIND_HOOK:
{
auto info = *(FindHookCmd*)buffer;
SearchForHooks(info.sp);
}
break;
2018-11-11 12:29:12 +08:00
case HOST_COMMAND_DETACH:
{
running = false;
}
break;
}
}
2018-12-02 04:52:52 +08:00
hookPipe = INVALID_HANDLE_VALUE;
for (auto& hook : *hooks) if (hook.address) hook.Clear();
2018-11-11 12:29:12 +08:00
FreeLibraryAndExitThread(GetModuleHandleW(ITH_DLL), 0);
return 0;
}
void TextOutput(ThreadParam tp, BYTE* text, int len)
{
if (len < 0) return;
2019-01-10 11:35:01 +08:00
if (len > PIPE_BUFFER_SIZE - sizeof(tp)) len = PIPE_BUFFER_SIZE - sizeof(tp);
2018-11-11 12:29:12 +08:00
BYTE buffer[PIPE_BUFFER_SIZE] = {};
*(ThreadParam*)buffer = tp;
2019-01-10 11:35:01 +08:00
memcpy(buffer + sizeof(tp), text, len);
2019-06-04 05:58:30 +08:00
WriteFile(hookPipe, buffer, sizeof(tp) + len, DUMMY, nullptr);
2018-11-11 12:29:12 +08:00
}
2018-12-02 04:52:52 +08:00
void ConsoleOutput(LPCSTR text, ...)
2018-11-11 12:29:12 +08:00
{
2018-12-02 04:52:52 +08:00
ConsoleOutputNotif buffer;
va_list args;
va_start(args, text);
2019-06-02 14:09:17 +08:00
vsnprintf(buffer.message, MESSAGE_SIZE, text, args);
2019-06-04 05:58:30 +08:00
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
2019-06-02 14:09:17 +08:00
}
void NotifyHookFound(uint64_t addr, int offset, wchar_t* text)
{
HookParam hp = {};
hp.offset = offset;
hp.type = USING_UNICODE | USING_STRING;
hp.address = addr;
HookFoundNotif buffer(hp, text);
2019-06-04 05:58:30 +08:00
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
2018-11-11 12:29:12 +08:00
}
2019-02-28 00:33:17 +08:00
void NotifyHookRemove(uint64_t addr, LPCSTR name)
2018-11-11 12:29:12 +08:00
{
2019-02-28 00:33:17 +08:00
if (name) ConsoleOutput(REMOVING_HOOK, name);
2018-11-11 12:29:12 +08:00
HookRemovedNotif buffer(addr);
2019-06-04 05:58:30 +08:00
WriteFile(hookPipe, &buffer, sizeof(buffer), DUMMY, nullptr);
2018-11-11 12:29:12 +08:00
}
2018-09-21 10:42:15 +08:00
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID)
2018-08-23 23:53:23 +08:00
{
switch (fdwReason)
{
case DLL_PROCESS_ATTACH:
{
viewMutex = WinMutex(ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId()), &allAccess);
2018-08-23 23:53:23 +08:00
if (GetLastError() == ERROR_ALREADY_EXISTS) return FALSE;
DisableThreadLibraryCalls(hModule);
// jichi 9/25/2013: Interprocedural communication with vnrsrv.
mappedFile = CreateFileMappingW(INVALID_HANDLE_VALUE, &allAccess, PAGE_EXECUTE_READWRITE, 0, HOOK_SECTION_SIZE, (ITH_SECTION_ + std::to_wstring(GetCurrentProcessId())).c_str());
hooks = (TextHook(*)[MAX_HOOK])MapViewOfFile(mappedFile, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE);
2018-11-11 12:29:12 +08:00
memset(hooks, 0, HOOK_BUFFER_SIZE);
2018-08-23 23:53:23 +08:00
2018-08-26 03:45:25 +08:00
MH_Initialize();
2018-11-11 12:29:12 +08:00
running = true;
2018-08-23 23:53:23 +08:00
CloseHandle(CreateThread(nullptr, 0, Pipe, nullptr, 0, nullptr)); // Using std::thread here = deadlock
2018-08-23 23:53:23 +08:00
}
break;
case DLL_PROCESS_DETACH:
{
2018-11-11 12:29:12 +08:00
running = false;
UnmapViewOfFile(hooks);
2018-11-11 13:34:42 +08:00
MH_Uninitialize();
2018-08-23 23:53:23 +08:00
}
break;
}
return TRUE;
}
2018-11-11 12:29:12 +08:00
void NewHook(HookParam hp, LPCSTR lpname, DWORD flag)
2018-08-23 23:53:23 +08:00
{
2019-01-04 06:52:16 +08:00
if (hp.type & READ_SEARCH)
{
2019-01-05 16:46:13 +08:00
bool found = false;
2019-01-04 06:52:16 +08:00
char utf8Text[MAX_MODULE_SIZE * 4] = {};
WideCharToMultiByte(CP_UTF8, 0, hp.text, MAX_MODULE_SIZE, utf8Text, MAX_MODULE_SIZE * 4, nullptr, nullptr);
char codepageText[MAX_MODULE_SIZE * 4] = {};
2019-01-05 16:46:13 +08:00
WideCharToMultiByte(hp.codepage, 0, hp.text, MAX_MODULE_SIZE, codepageText, MAX_MODULE_SIZE * 4, nullptr, nullptr);
2019-01-04 06:52:16 +08:00
if (strlen(utf8Text) < 8 || strlen(codepageText) < 8 || wcslen(hp.text) < 4) return ConsoleOutput(NOT_ENOUGH_TEXT);
2019-06-02 14:09:17 +08:00
ConsoleOutput(STARTING_SEARCH);
2019-01-04 06:52:16 +08:00
for (auto[addrs, type] : Array<std::tuple<std::vector<uint64_t>, HookParamType>>{
{ Util::SearchMemory(utf8Text, strlen(utf8Text), PAGE_READWRITE), USING_UTF8 },
{ Util::SearchMemory(codepageText, strlen(codepageText), PAGE_READWRITE), USING_STRING },
2019-01-04 06:52:16 +08:00
{ Util::SearchMemory(hp.text, wcslen(hp.text) * 2, PAGE_READWRITE), USING_UNICODE }
})
for (auto addr : addrs)
{
2019-01-05 16:46:13 +08:00
if (abs((long long)(utf8Text - addr)) < 20000) continue; // don't add read code if text is on this thread's stack
found = true;
2019-01-04 06:52:16 +08:00
HookParam h = {};
h.type = DIRECT_READ | type;
h.address = addr;
h.codepage = hp.codepage;
NewHook(h, lpname, 0);
}
2019-01-05 16:46:13 +08:00
if (!found) ConsoleOutput(COULD_NOT_FIND);
2019-01-04 06:52:16 +08:00
}
else
{
if (++currentHook >= MAX_HOOK) return ConsoleOutput(TOO_MANY_HOOKS);
if (lpname && *lpname) strncpy_s(hp.name, lpname, HOOK_NAME_SIZE - 1);
2019-01-04 06:52:16 +08:00
ConsoleOutput(INSERTING_HOOK, hp.name);
2019-02-16 13:24:36 +08:00
if (hp.address) RemoveHook(hp.address, 0);
if (!(*hooks)[currentHook].Insert(hp, flag)) ConsoleOutput(HOOK_FAILED);
2019-01-04 06:52:16 +08:00
}
2018-08-23 23:53:23 +08:00
}
2018-08-26 03:45:25 +08:00
2018-12-02 04:52:52 +08:00
void RemoveHook(uint64_t addr, int maxOffset)
2018-08-23 23:53:23 +08:00
{
for (auto& hook : *hooks) if (abs((long long)(hook.address - addr)) <= maxOffset) return hook.Clear();
2018-08-23 23:53:23 +08:00
}
2018-12-21 23:10:51 +08:00
// EOF