diff --git a/GUI/mainwindow.cpp b/GUI/mainwindow.cpp index 21115bc..839c097 100644 --- a/GUI/mainwindow.cpp +++ b/GUI/mainwindow.cpp @@ -2,7 +2,6 @@ #include "ui_mainwindow.h" #include "extensions.h" #include "misc.h" -#include "../vnrhook/include/const.h" #include #include #include @@ -78,9 +77,9 @@ void MainWindow::AddThread(TextThread* thread) { ttCombo->addItem( TextThreadString(thread) + - QString::fromStdWString(Host::GetHookName(thread->GetThreadParameter().pid, thread->GetThreadParameter().hook)) + + QString::fromStdWString(Host::GetHookName(thread->GetThreadParam().pid, thread->GetThreadParam().hook)) + " (" + - GenerateCode(Host::GetHookParam(thread->GetThreadParameter()), thread->GetThreadParameter().pid) + + GenerateCode(Host::GetHookParam(thread->GetThreadParam()), thread->GetThreadParam().pid) + ")" ); thread->RegisterOutputCallBack([&](TextThread* thread, std::wstring output) @@ -116,7 +115,7 @@ void MainWindow::ThreadOutput(TextThread* thread, QString output) QString MainWindow::TextThreadString(TextThread* thread) { - ThreadParameter tp = thread->GetThreadParameter(); + ThreadParam tp = thread->GetThreadParam(); return QString("%1:%2:%3:%4: ").arg( QString::number(tp.pid), QString::number(tp.hook, 16), @@ -125,7 +124,7 @@ QString MainWindow::TextThreadString(TextThread* thread) ).toUpper(); } -ThreadParameter MainWindow::ParseTextThreadString(QString textThreadString) +ThreadParam MainWindow::ParseTextThreadString(QString textThreadString) { QStringList threadParam = textThreadString.split(":"); return { threadParam[0].toUInt(), threadParam[1].toULongLong(nullptr, 16), threadParam[2].toULongLong(nullptr, 16), threadParam[3].toULongLong(nullptr, 16) }; @@ -149,9 +148,9 @@ std::unordered_map MainWindow::GetInfoForExtensions(TextThread { { "current select", (int)ttCombo->currentText().startsWith(TextThreadString(thread)) }, { "text number", 0 }, - { "process id", thread->GetThreadParameter().pid }, - { "hook address", (int)thread->GetThreadParameter().hook }, - { "hook address (upper 32 bits)", (int)(thread->GetThreadParameter().hook >> 32) } + { "process id", thread->GetThreadParam().pid }, + { "hook address", (int)thread->GetThreadParam().hook }, + { "hook address (upper 32 bits)", (int)(thread->GetThreadParam().hook >> 32) } }; } @@ -161,7 +160,7 @@ QVector MainWindow::GetAllHooks(DWORD processId) QVector hooks; for (int i = 0; i < ttCombo->count(); ++i) { - ThreadParameter tp = ParseTextThreadString(ttCombo->itemText(i)); + ThreadParam tp = ParseTextThreadString(ttCombo->itemText(i)); if (tp.pid == processId && !addresses.contains(tp.hook)) { addresses.insert(tp.hook); diff --git a/GUI/mainwindow.h b/GUI/mainwindow.h index d349313..bd0f31d 100644 --- a/GUI/mainwindow.h +++ b/GUI/mainwindow.h @@ -44,7 +44,7 @@ private slots: private: QString TextThreadString(TextThread* thread); - ThreadParameter ParseTextThreadString(QString textThreadString); + ThreadParam ParseTextThreadString(QString textThreadString); DWORD GetSelectedProcessId(); void ReloadExtensions(); std::unordered_map GetInfoForExtensions(TextThread* thread); diff --git a/GUI/misc.cpp b/GUI/misc.cpp index 36d3f67..4ae9358 100644 --- a/GUI/misc.cpp +++ b/GUI/misc.cpp @@ -1,5 +1,5 @@ #include "misc.h" -#include "../vnrhook/include/const.h" +#include "const.h" #include #include diff --git a/GUI/misc.h b/GUI/misc.h index de2a13b..103ed10 100644 --- a/GUI/misc.h +++ b/GUI/misc.h @@ -2,7 +2,7 @@ #define MISC_H #include "qtcommon.h" -#include "../host/host.h" +#include "pipe.h" QString GetFullModuleName(DWORD processId, HMODULE module = NULL); QString GetModuleName(DWORD processId, HMODULE module = NULL); diff --git a/host/CMakeLists.txt b/host/CMakeLists.txt index 378a45e..b863d03 100644 --- a/host/CMakeLists.txt +++ b/host/CMakeLists.txt @@ -1,8 +1,4 @@ set(vnrhost_src - host.h - pipe.h - textthread.h - winmutex.h host.cc pipe.cc textthread.cc diff --git a/host/host.cc b/host/host.cc index 9fcac40..68e6574 100644 --- a/host/host.cc +++ b/host/host.cc @@ -4,21 +4,33 @@ #include "host.h" #include "pipe.h" -#include "winmutex.h" -#include "../vnrhook/include/const.h" -#include "../vnrhook/include/defs.h" -#include "../vnrhook/include/types.h" +#include "const.h" +#include "defs.h" +#include "../vnrhook/hijack/texthook.h" - -struct ThreadParameterHasher +struct ProcessRecord { - size_t operator()(const ThreadParameter& tp) const - { - return std::hash<__int64>()(tp.pid << 6) + std::hash<__int64>()(tp.hook) + std::hash<__int64>()(tp.retn) + std::hash<__int64>()(tp.spl); - } + HANDLE processHandle; + HANDLE sectionMutex; + HANDLE section; + LPVOID sectionMap; + HANDLE hostPipe; }; -std::unordered_map textThreadsByParams; +// Artikash 5/31/2018: required for unordered_map to work with struct key +template <> struct std::hash { size_t operator()(const ThreadParam& tp) const { return std::hash<__int64>()((tp.pid + tp.hook) ^ (tp.retn + tp.spl)); } }; +bool operator==(const ThreadParam& one, const ThreadParam& two) { return memcmp(&one, &two, sizeof(ThreadParam)) == 0; } + +// Artikash 7/20/2018: similar to std::lock guard but use Winapi objects for cross process comms +class MutexLocker +{ + HANDLE mutex; +public: + MutexLocker(HANDLE mutex) : mutex(mutex) { WaitForSingleObject(mutex, 0); } + ~MutexLocker() { if (mutex != INVALID_HANDLE_VALUE && mutex != nullptr) ReleaseMutex(mutex); } +}; + +std::unordered_map textThreadsByParams; std::unordered_map processRecordsByIds; std::recursive_mutex hostMutex; @@ -28,7 +40,7 @@ ProcessEventCallback OnAttach, OnDetach; DWORD DUMMY[100]; -ThreadParameter CONSOLE{ 0, -1UL, -1UL, -1UL }; +ThreadParam CONSOLE{ 0, -1ULL, -1ULL, -1ULL }; #define HOST_LOCK std::lock_guard hostLocker(hostMutex) // Synchronized scope for accessing private data @@ -38,7 +50,7 @@ namespace Host { OnAttach = onAttach; OnDetach = onDetach; OnCreate = onCreate; OnRemove = onRemove; OnCreate(textThreadsByParams[CONSOLE] = new TextThread(CONSOLE, USING_UNICODE)); - CreateNewPipe(); + CreatePipe(); } DLLEXPORT void Close() @@ -102,25 +114,20 @@ namespace Host DLLEXPORT bool DetachProcess(DWORD processId) { - DWORD command = HOST_COMMAND_DETACH; + int command = HOST_COMMAND_DETACH; return WriteFile(processRecordsByIds[processId].hostPipe, &command, sizeof(command), DUMMY, nullptr); } DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name) { - BYTE buffer[PIPE_BUFFER_SIZE] = {}; - *(DWORD*)buffer = HOST_COMMAND_NEW_HOOK; - *(HookParam*)(buffer + sizeof(DWORD)) = hp; - if (name.size()) strcpy((char*)buffer + sizeof(DWORD) + sizeof(HookParam), name.c_str()); - return WriteFile(processRecordsByIds[pid].hostPipe, buffer, sizeof(DWORD) + sizeof(HookParam) + name.size(), DUMMY, nullptr); + auto info = InsertHookCmd(hp, name); + return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr); } DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr) { - BYTE buffer[sizeof(DWORD) * 2] = {}; - *(DWORD*)buffer = HOST_COMMAND_REMOVE_HOOK; - *(DWORD*)(buffer + sizeof(DWORD)) = addr; - return WriteFile(processRecordsByIds[pid].hostPipe, buffer, sizeof(DWORD) * 2, DUMMY, nullptr); + auto info = RemoveHookCmd(addr); + return WriteFile(processRecordsByIds[pid].hostPipe, &info, sizeof(info), DUMMY, nullptr); } DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr) @@ -130,14 +137,14 @@ namespace Host ProcessRecord pr = processRecordsByIds[pid]; if (pr.sectionMap == nullptr) return ret; MutexLocker locker(pr.sectionMutex); - const Hook* hooks = (const Hook*)pr.sectionMap; + const TextHook* hooks = (const TextHook*)pr.sectionMap; for (int i = 0; i < MAX_HOOK; ++i) if ((DWORD)hooks[i].Address() == addr) ret = hooks[i].hp; return ret; } - DLLEXPORT HookParam GetHookParam(ThreadParameter tp) { return GetHookParam(tp.pid, tp.hook); } + DLLEXPORT HookParam GetHookParam(ThreadParam tp) { return GetHookParam(tp.pid, tp.hook); } DLLEXPORT std::wstring GetHookName(DWORD pid, DWORD addr) { @@ -147,7 +154,7 @@ namespace Host ProcessRecord pr = processRecordsByIds[pid]; if (pr.sectionMap == nullptr) return L""; MutexLocker locker(pr.sectionMutex); - const Hook* hooks = (const Hook*)pr.sectionMap; + const TextHook* hooks = (const TextHook*)pr.sectionMap; for (int i = 0; i < MAX_HOOK; ++i) if ((DWORD)hooks[i].Address() == addr) { @@ -158,7 +165,7 @@ namespace Host return std::wstring(A2W(buffer.c_str())); } - DLLEXPORT TextThread* GetThread(ThreadParameter tp) + DLLEXPORT TextThread* GetThread(ThreadParam tp) { HOST_LOCK; return textThreadsByParams[tp]; @@ -171,7 +178,7 @@ namespace Host } } -void DispatchText(ThreadParameter tp, const BYTE* text, int len) +void DispatchText(ThreadParam tp, const BYTE* text, int len) { if (!text || len <= 0) return; HOST_LOCK; @@ -181,10 +188,10 @@ void DispatchText(ThreadParameter tp, const BYTE* text, int len) it->AddText(text, len); } -void RemoveThreads(bool(*RemoveIf)(ThreadParameter, ThreadParameter), ThreadParameter cmp) +void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp) { HOST_LOCK; - std::vector removedThreads; + std::vector removedThreads; for (auto i : textThreadsByParams) if (RemoveIf(i.first, cmp)) { diff --git a/host/host.h b/host/host.h index b51a51b..8113447 100644 --- a/host/host.h +++ b/host/host.h @@ -6,19 +6,9 @@ #include "common.h" #include "textthread.h" -#include "../vnrhook/include/types.h" #define DLLEXPORT __declspec(dllexport) -struct ProcessRecord -{ - HANDLE processHandle; - HANDLE sectionMutex; - HANDLE section; - LPVOID sectionMap; - HANDLE hostPipe; -}; - typedef std::function ProcessEventCallback; typedef std::function ThreadEventCallback; @@ -32,15 +22,15 @@ namespace Host DLLEXPORT bool InsertHook(DWORD pid, HookParam hp, std::string name = ""); DLLEXPORT bool RemoveHook(DWORD pid, DWORD addr); DLLEXPORT HookParam GetHookParam(DWORD pid, DWORD addr); - DLLEXPORT HookParam GetHookParam(ThreadParameter tp); + DLLEXPORT HookParam GetHookParam(ThreadParam tp); DLLEXPORT std::wstring GetHookName(DWORD pid, DWORD addr); - DLLEXPORT TextThread* GetThread(ThreadParameter tp); + DLLEXPORT TextThread* GetThread(ThreadParam tp); DLLEXPORT void AddConsoleOutput(std::wstring text); } -void DispatchText(ThreadParameter tp, const BYTE *text, int len); -void RemoveThreads(bool(*RemoveIf)(ThreadParameter, ThreadParameter), ThreadParameter cmp); +void DispatchText(ThreadParam tp, const BYTE *text, int len); +void RemoveThreads(bool(*RemoveIf)(ThreadParam, ThreadParam), ThreadParam cmp); void RegisterProcess(DWORD pid, HANDLE hostPipe); void UnregisterProcess(DWORD pid); diff --git a/host/pipe.cc b/host/pipe.cc index 8223058..acc809e 100644 --- a/host/pipe.cc +++ b/host/pipe.cc @@ -4,10 +4,10 @@ #include "pipe.h" #include "host.h" -#include "../vnrhook/include/defs.h" -#include "../vnrhook/include/const.h" +#include "defs.h" +#include "const.h" -void CreateNewPipe() +void CreatePipe() { std::thread([]() { @@ -17,7 +17,7 @@ void CreateNewPipe() // jichi 9/27/2013: why recursion? // Artikash 5/20/2018: Easy way to create a new pipe for another process - CreateNewPipe(); + CreatePipe(); BYTE buffer[PIPE_BUFFER_SIZE + 1] = {}; DWORD bytesRead, processId; @@ -25,35 +25,30 @@ void CreateNewPipe() RegisterProcess(processId, hostPipe); while (ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) - { - buffer[bytesRead] = 0; - buffer[bytesRead + 1] = 0; - - if (*(DWORD*)buffer == HOST_NOTIFICATION) - switch (*(DWORD*)(buffer + sizeof(DWORD))) // Artikash 7/17/2018: Notification type - { - case HOST_NOTIFICATION_NEWHOOK: // Artikash 7/18/2018: Useless for now, but could be used to implement smth later - break; - case HOST_NOTIFICATION_RMVHOOK: - RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; }, - { processId, *(DWORD*)(buffer + sizeof(DWORD) * 2) }); // Address - break; - case HOST_NOTIFICATION_TEXT: - USES_CONVERSION; - Host::AddConsoleOutput(A2W((LPCSTR)(buffer + sizeof(DWORD) * 2))); // Text - break; - } - else DispatchText( - { - processId, - *(DWORD*)buffer, // Hook address - *(DWORD*)(buffer + sizeof(DWORD)), // Return address - *(DWORD*)(buffer + sizeof(DWORD) * 2) // Split - }, - buffer + HEADER_SIZE, // Data - bytesRead - HEADER_SIZE // Data size - ); - } + switch (*(int*)buffer) + { + //case HOST_NOTIFICATION_NEWHOOK: // Artikash 7/18/2018: Useless for now, but could be used to implement smth later + //break; + case HOST_NOTIFICATION_RMVHOOK: + { + auto info = *(HookRemovedNotif*)buffer; + RemoveThreads([](auto one, auto two) { return one.pid == two.pid && one.hook == two.hook; }, { processId, info.address }); + } + break; + case HOST_NOTIFICATION_TEXT: + { + auto info = *(ConsoleOutputNotif*)buffer; + USES_CONVERSION; + Host::AddConsoleOutput(A2W(info.message)); + } + break; + default: + { + ThreadParam tp = *(ThreadParam*)buffer; + DispatchText(tp, buffer + sizeof(tp), bytesRead - sizeof(tp)); + } + break; + } DisconnectNamedPipe(hookPipe); DisconnectNamedPipe(hostPipe); diff --git a/host/pipe.h b/host/pipe.h deleted file mode 100644 index cb0dee5..0000000 --- a/host/pipe.h +++ /dev/null @@ -1,10 +0,0 @@ -#pragma once - -// pipe.h -// 7/19/2018 Artikash - -#include "common.h" - -void CreateNewPipe(); - -// EOF \ No newline at end of file diff --git a/host/textthread.cc b/host/textthread.cc index 9499c79..227a32a 100644 --- a/host/textthread.cc +++ b/host/textthread.cc @@ -1,16 +1,13 @@ // textthread.cc // 8/24/2013 jichi // Branch IHF/TextThread.cpp, rev 133 -#ifdef _MSC_VER -# pragma warning (disable:4100) // C4100: unreference formal parameter -#endif // _MSC_VER #include "textthread.h" -#include "../vnrhook/include/const.h" +#include "const.h" #define TT_LOCK std::lock_guard ttLocker(ttMutex) // Synchronized scope for accessing private data -TextThread::TextThread(ThreadParameter tp, DWORD status) : +TextThread::TextThread(ThreadParam tp, DWORD status) : deletionEvent(CreateEventW(nullptr, FALSE, FALSE, NULL)), flushThread([&]() { while (WaitForSingleObject(deletionEvent, 100), Flush()); }), timestamp(GetTickCount()), diff --git a/host/textthread.h b/host/textthread.h index a6d4a78..a4737e0 100644 --- a/host/textthread.h +++ b/host/textthread.h @@ -5,34 +5,18 @@ // Branch: ITH/TextThread.h, rev 120 #include "common.h" +#include "pipe.h" -struct ThreadParameter -{ - DWORD pid; // jichi: 5/11/2014: The process ID - unsigned __int64 hook; // Artikash 6/6/2018: The insertion address of the hook - unsigned __int64 retn; // jichi 5/11/2014: The return address of the hook - unsigned __int64 spl; // jichi 5/11/2014: the processed split value of the hook paramete - - // Artikash 5/31/2018: required for unordered_map to work with struct key - friend bool operator==(const ThreadParameter& one, const ThreadParameter& two) - { - return one.pid == two.pid && one.hook == two.hook && one.retn == two.retn && one.spl == two.spl; - } -}; - -class TextThread; -typedef std::function ThreadOutputCallback; - -//extern DWORD split_time,repeat_count,global_filter,cyclic_remove; class TextThread { + typedef std::function ThreadOutputCallback; public: - TextThread(ThreadParameter tp, DWORD status); + TextThread(ThreadParam tp, DWORD status); virtual ~TextThread(); virtual std::wstring GetStore(); - ThreadParameter GetThreadParameter() { return tp; } + ThreadParam GetThreadParam() { return tp; } void RegisterOutputCallBack(ThreadOutputCallback cb) { Output = cb; } @@ -50,7 +34,7 @@ private: DWORD timestamp; ThreadOutputCallback Output; - ThreadParameter tp; + ThreadParam tp; DWORD status; }; diff --git a/host/winmutex.h b/host/winmutex.h deleted file mode 100644 index 1cb43d9..0000000 --- a/host/winmutex.h +++ /dev/null @@ -1,18 +0,0 @@ -#pragma once -// winmutex.h -// 12/11/2011 jichi - -#include -#include "common.h" - -// Artikash 7/20/2018: similar to std::lock guard but use Winapi objects for cross process comms - -class MutexLocker -{ - HANDLE mutex; -public: - MutexLocker(HANDLE mutex) : mutex(mutex) { WaitForSingleObject(mutex, 0); } - ~MutexLocker() { if (mutex != INVALID_HANDLE_VALUE && mutex != nullptr) ReleaseMutex(mutex); } -}; - -// EOF diff --git a/include/common.h b/include/common.h index 655a44a..360cf5d 100644 --- a/include/common.h +++ b/include/common.h @@ -8,4 +8,4 @@ #include #include #include -#include \ No newline at end of file +#include diff --git a/include/const.h b/include/const.h new file mode 100644 index 0000000..b6b70ba --- /dev/null +++ b/include/const.h @@ -0,0 +1,64 @@ +#pragma once + +// vnrhook/const.h +// 8/23/2013 jichi +// Branch: ITH/common.h, rev 128 + +enum { MESSAGE_SIZE = 500, PIPE_BUFFER_SIZE = 0x1000 }; + +// jichi 375/2014: Add offset of pusha/pushad +// http://faydoc.tripod.com/cpu/pushad.htm +// http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial +// +// Warning: The offset in ITH has -4 offset comparing to pusha and AGTH +enum pusha_off +{ + pusha_eax_off = -0x4, + pusha_ecx_off = -0x8, + pusha_edx_off = -0xc, + pusha_ebx_off = -0x10, + pusha_esp_off = -0x14, + pusha_ebp_off = -0x18, + pusha_esi_off = -0x1c, + pusha_edi_off = -0x20, + pusha_off = -0x24 // pushad offset +}; + +enum HostCommandType +{ + HOST_COMMAND = -1, // null type + HOST_COMMAND_NEW_HOOK = 0, + HOST_COMMAND_REMOVE_HOOK = 1, + HOST_COMMAND_MODIFY_HOOK = 2, + HOST_COMMAND_HIJACK_PROCESS = 3, + HOST_COMMAND_DETACH = 4 +}; + +enum HostNotificationType +{ + HOST_NOTIFICATION = -1, // null type + HOST_NOTIFICATION_TEXT = 0, + HOST_NOTIFICATION_NEWHOOK = 1, + HOST_NOTIFICATION_RMVHOOK = 2 +}; + +enum HookParamType : unsigned long +{ + USING_STRING = 0x1, // type(data) is char* or wchar_t* and has length + USING_UNICODE = 0x2, // type(data) is wchar_t or wchar_t* + BIG_ENDIAN = 0x4, // type(data) is char + DATA_INDIRECT = 0x8, + USING_SPLIT = 0x10, // aware of split time? + SPLIT_INDIRECT = 0x20, + MODULE_OFFSET = 0x40, // do hash module, and the address is relative to module + //FUNCTION_OFFSET = 0x80, // do hash function, and the address is relative to funccion + USING_UTF8 = 0x100, + NO_CONTEXT = 0x400, + HOOK_EMPTY = 0x800, + FIXING_SPLIT = 0x1000, + DIRECT_READ = 0x2000, // /R read code instead of classic /H hook code + HOOK_ENGINE = 0x4000, + HOOK_ADDITIONAL = 0x8000 +}; + +enum { FIXED_SPLIT_VALUE = 0x10001 }; // 6/1/2014: Fixed split value for hok parameter. Fuse all threads, and prevent floating diff --git a/vnrhook/include/defs.h b/include/defs.h similarity index 56% rename from vnrhook/include/defs.h rename to include/defs.h index 1795e70..40e3491 100644 --- a/vnrhook/include/defs.h +++ b/include/defs.h @@ -3,16 +3,6 @@ // vnrhook/defs.h // 8/23/2013 jichi -// DLL files - -//#define ITH_SERVER_DLL L"vnrsrv.dll" -//#define ITH_CLIENT_DLL L"vnrcli.dll" -//#define ITH_CLIENT_XP_DLL L"vnrclixp.dll" -////#define ITH_CLIENT_UX_DLL L"vnrcliux.dll" -//#define ITH_ENGINE_DLL L"vnreng.dll" -//#define ITH_ENGINE_XP_DLL L"vnrengxp.dll" -//#define ITH_ENGINE_UX_DLL L"vnrengux.dll" - #define ITH_DLL L"vnrhook.dll" // Pipes diff --git a/include/pipe.h b/include/pipe.h new file mode 100644 index 0000000..6eb9751 --- /dev/null +++ b/include/pipe.h @@ -0,0 +1,70 @@ +#pragma once + +#include "common.h" +#include "const.h" + +void CreatePipe(); + +// jichi 3/7/2014: Add guessed comment +struct HookParam +{ + // jichi 8/24/2013: For special hooks. + typedef void(*text_fun_t)(DWORD esp, HookParam *hp, BYTE index, DWORD *data, DWORD *split, DWORD *len); + typedef bool(*filter_fun_t)(LPVOID str, DWORD *len, HookParam *hp, BYTE index); // jichi 10/24/2014: Add filter function. Return true if skip the text + typedef bool(*hook_fun_t)(DWORD esp, HookParam *hp); // jichi 10/24/2014: Add generic hook function, return false if stop execution. + + unsigned __int64 address; // absolute or relative address + short offset, // offset of the data in the memory + index, // deref_offset1 + split, // offset of the split character + split_index; // deref_offset2 + DWORD module; // hash of the module + DWORD type; // flags + WORD length_offset; // index of the string length + DWORD user_value; // 7/20/2014: jichi additional parameters for PSP games + + text_fun_t text_fun; + filter_fun_t filter_fun; + hook_fun_t hook_fun; + + BYTE hook_len, // ? + recover_len; // ? + HANDLE readerHandle; // Artikash 8/4/2018: handle for reader thread +}; + +struct ThreadParam // From hook +{ + DWORD pid; // jichi: 5/11/2014: The process ID + unsigned __int64 hook; // Artikash 6/6/2018: The insertion address of the hook + unsigned __int64 retn; // jichi 5/11/2014: The return address of the hook + unsigned __int64 spl; // jichi 5/11/2014: the processed split value of the hook paramete +}; + +struct InsertHookCmd // From host +{ + InsertHookCmd(HookParam hp, std::string name = "") : hp(hp) { strncpy(this->name, name.c_str(), 500); }; + int command = HOST_COMMAND_NEW_HOOK; + HookParam hp; + char name[MESSAGE_SIZE] = {}; +}; + +struct RemoveHookCmd // From host +{ + RemoveHookCmd(unsigned __int64 address) : address(address) {}; + int command = HOST_COMMAND_REMOVE_HOOK; + unsigned __int64 address; +}; + +struct ConsoleOutputNotif // From hook +{ + ConsoleOutputNotif(std::string message = "") { strncpy(this->message, message.c_str(), 500); }; + int command = HOST_NOTIFICATION_TEXT; + char message[MESSAGE_SIZE] = {}; +}; + +struct HookRemovedNotif // From hook +{ + HookRemovedNotif(unsigned __int64 address) : address(address) {}; + int command = HOST_NOTIFICATION_RMVHOOK; + unsigned __int64 address; +}; diff --git a/vnrhook/CMakeLists.txt b/vnrhook/CMakeLists.txt index f2e3deb..796ccd9 100644 --- a/vnrhook/CMakeLists.txt +++ b/vnrhook/CMakeLists.txt @@ -2,50 +2,27 @@ include_directories(.) if("${CMAKE_SIZEOF_VOID_P}" STREQUAL "8") set(vnrhook_src - include/const.h - include/defs.h - include/types.h - src/main.cc - src/main.h - src/pipe.cc - src/util/ithsys/ithsys.cc - src/hijack/texthook.cc + main.cc + pipe.cc + util/ithsys/ithsys.cc + hijack/texthook.cc ) else() set(vnrhook_src - include/const.h - include/defs.h - include/types.h - src/except.h - src/main.cc - src/main.h - src/pipe.cc - src/engine/engine.cc - src/engine/engine.h - src/engine/hookdefs.h - src/engine/match.cc - src/engine/match.h - src/engine/pchooks.cc - src/engine/pchooks.h - src/engine/mono/funcinfo.h - src/engine/mono/types.h - src/engine/ppsspp/funcinfo.h - src/hijack/texthook.cc - src/hijack/texthook.h - src/util/growl.h - src/util/util.cc - src/util/util.h - src/util/ithsys/ithsys.cc - src/util/disasm/disasm.cc - src/util/memdbg/memdbg.h - src/util/memdbg/memsearch.cc - src/util/memdbg/memsearch.h - src/util/mono/monoobject.h - src/util/mono/monotype.h + main.cc + pipe.cc + engine/engine.cc + engine/match.cc + engine/pchooks.cc + hijack/texthook.cc + util/util.cc + util/ithsys/ithsys.cc + util/disasm/disasm.cc + util/memdbg/memsearch.cc ) endif() -include_directories(src/util) +include_directories(util) add_library(vnrhook SHARED ${vnrhook_src}) diff --git a/vnrhook/src/engine/engine.cc b/vnrhook/engine/engine.cc similarity index 99% rename from vnrhook/src/engine/engine.cc rename to vnrhook/engine/engine.cc index cb1f652..7594fed 100644 --- a/vnrhook/src/engine/engine.cc +++ b/vnrhook/engine/engine.cc @@ -7,21 +7,21 @@ # pragma warning (disable:4819) #endif // _MSC_VER -#include "src/engine/engine.h" +#include "engine/engine.h" #include "ntdll/ntdll.h" -#include "src/engine/match.h" -#include "src/engine/hookdefs.h" -#include "src/util/util.h" -#include "src/main.h" -#include "src/engine/mono/funcinfo.h" -#include "src/engine/ppsspp/funcinfo.h" -#include "src/except.h" +#include "engine/match.h" +#include "util/util.h" +#include "main.h" +#include "engine/mono/funcinfo.h" +#include "engine/ppsspp/funcinfo.h" +#include "except.h" #include "ithsys/ithsys.h" #include "memdbg/memsearch.h" #include "disasm/disasm.h" #include "cpputil/cppcstring.h" #include "mono/monoobject.h" #include "growl.h" +#include "const.h" //#include #include #include @@ -38,50 +38,6 @@ enum { VNR_TEXT_CAPACITY = 1500 }; // estimated max number of bytes allowed in VNR, slightly larger than VNR's text limit (1000) -#ifdef DEBUG -# include "src/util/growl.h" -//# include "uniquemap.h" -//# include "uniquemap.cc" -namespace { // unnamed debug functions -// jichi 12/17/2013: Copied from int TextHook::GetLength(DWORD base, DWORD in) -int GetHookDataLength(const HookParam &hp, DWORD base, DWORD in) -{ - if (CC_UNLIKELY(!base)) - return 0; - int len; - switch (hp.length_offset) { - default: // jichi 12/26/2013: I should not put this default branch to the end - len = *((int *)base + hp.length_offset); - if (len >= 0) { - if (hp.type & USING_UNICODE) - len <<= 1; - break; - } - else if (len != -1) - break; - //len == -1 then continue to case 0. - case 0: - if (hp.type & USING_UNICODE) - len = wcslen((LPCWSTR)in) << 1; - else - len = strlen((LPCSTR)in); - break; - case 1: - if (hp.type & USING_UNICODE) - len = 2; - else { - if (hp.type & BIG_ENDIAN) - in >>= 8; - len = LeadByteTable[in&0xff]; //Slightly faster than IsDBCSLeadByte - } - break; - } - // jichi 12/25/2013: This function originally return -1 if failed - //return len; - return max(0, len); -} -} // unnamed -#endif // DEBUG namespace { // unnamed helpers diff --git a/vnrhook/src/engine/engine.h b/vnrhook/engine/engine.h similarity index 100% rename from vnrhook/src/engine/engine.h rename to vnrhook/engine/engine.h diff --git a/vnrhook/src/engine/match.cc b/vnrhook/engine/match.cc similarity index 99% rename from vnrhook/src/engine/match.cc rename to vnrhook/engine/match.cc index 2881a4a..b1ce028 100644 --- a/vnrhook/src/engine/match.cc +++ b/vnrhook/engine/match.cc @@ -7,13 +7,13 @@ //# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler #endif // _MSC_VER -#include "src/engine/match.h" -#include "src/engine/engine.h" -#include "src/engine/pchooks.h" -#include "src/util/growl.h" -#include "src/util/util.h" -#include "src/main.h" -#include "src/except.h" +#include "engine/match.h" +#include "engine/engine.h" +#include "engine/pchooks.h" +#include "util/growl.h" +#include "util/util.h" +#include "main.h" +#include "except.h" #include "ithsys/ithsys.h" //#define ConsoleOutput(...) (void)0 // jichi 8/18/2013: I don't need ConsoleOutput diff --git a/vnrhook/src/engine/match.h b/vnrhook/engine/match.h similarity index 100% rename from vnrhook/src/engine/match.h rename to vnrhook/engine/match.h diff --git a/vnrhook/src/engine/mono/funcinfo.h b/vnrhook/engine/mono/funcinfo.h similarity index 100% rename from vnrhook/src/engine/mono/funcinfo.h rename to vnrhook/engine/mono/funcinfo.h diff --git a/vnrhook/src/engine/mono/types.h b/vnrhook/engine/mono/types.h similarity index 100% rename from vnrhook/src/engine/mono/types.h rename to vnrhook/engine/mono/types.h diff --git a/vnrhook/src/engine/pchooks.cc b/vnrhook/engine/pchooks.cc similarity index 99% rename from vnrhook/src/engine/pchooks.cc rename to vnrhook/engine/pchooks.cc index d3c8372..7ea8365 100644 --- a/vnrhook/src/engine/pchooks.cc +++ b/vnrhook/engine/pchooks.cc @@ -1,8 +1,8 @@ // pchooks.cc // 8/1/2014 jichi -#include "src/engine/pchooks.h" -#include "src/main.h" +#include "engine/pchooks.h" +#include "main.h" //#include #define DEBUG "vnrcli" diff --git a/vnrhook/src/engine/pchooks.h b/vnrhook/engine/pchooks.h similarity index 100% rename from vnrhook/src/engine/pchooks.h rename to vnrhook/engine/pchooks.h diff --git a/vnrhook/src/engine/ppsspp/funcinfo.h b/vnrhook/engine/ppsspp/funcinfo.h similarity index 100% rename from vnrhook/src/engine/ppsspp/funcinfo.h rename to vnrhook/engine/ppsspp/funcinfo.h diff --git a/vnrhook/src/hijack/texthook.cc b/vnrhook/hijack/texthook.cc similarity index 94% rename from vnrhook/src/hijack/texthook.cc rename to vnrhook/hijack/texthook.cc index bac78a9..ad5725c 100644 --- a/vnrhook/src/hijack/texthook.cc +++ b/vnrhook/hijack/texthook.cc @@ -9,11 +9,11 @@ //# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler #endif // _MSC_VER -#include "src/hijack/texthook.h" -#include "src/engine/match.h" -#include "src/except.h" -#include "src/main.h" -#include "include/const.h" +#include "hijack/texthook.h" +#include "engine/match.h" +#include "except.h" +#include "main.h" +#include "const.h" #include "ithsys/ithsys.h" #include "disasm/disasm.h" //#include "winseh/winseh.h" @@ -293,9 +293,8 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn) } dwCount = GetLength(dwDataBase, dwDataIn); } - // jichi 12/25/2013: validate data size - if (dwCount == 0 || dwCount > PIPE_BUFFER_SIZE - HEADER_SIZE) + if (dwCount == 0 || dwCount > PIPE_BUFFER_SIZE - sizeof(ThreadParam)) return 0; if (hp.length_offset == 1) { @@ -304,27 +303,27 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn) dwDataIn = _byteswap_ushort(dwDataIn & 0xffff); if (dwCount == 1) dwDataIn &= 0xff; - *(WORD *)(pbData + HEADER_SIZE) = dwDataIn & 0xffff; + *(WORD *)(pbData + sizeof(ThreadParam)) = dwDataIn & 0xffff; } else - ::memcpy(pbData + HEADER_SIZE, (void *)dwDataIn, dwCount); + ::memcpy(pbData + sizeof(ThreadParam), (void *)dwDataIn, dwCount); // jichi 10/14/2014: Add filter function - if (hp.filter_fun && !hp.filter_fun(pbData + HEADER_SIZE, &dwCount, &hp, 0) || dwCount <= 0) { + if (hp.filter_fun && !hp.filter_fun(pbData + sizeof(ThreadParam), &dwCount, &hp, 0) || dwCount <= 0) { return 0; } - *(DWORD *)pbData = dwAddr; if (dwType & (NO_CONTEXT|FIXING_SPLIT)) dwRetn = 0; + *(ThreadParam*)pbData = { GetCurrentProcessId(), dwAddr, dwRetn, dwSplit }; *((DWORD *)pbData + 1) = dwRetn; *((DWORD *)pbData + 2) = dwSplit; if (dwCount) { DWORD unused; //CliLockPipe(); - WriteFile(::hookPipe, pbData, dwCount + HEADER_SIZE, &unused, nullptr); + WriteFile(::hookPipe, pbData, dwCount + sizeof(ThreadParam), &unused, nullptr); //CliUnlockPipe(); } return 0; @@ -454,7 +453,7 @@ DWORD WINAPI ReaderThread(LPVOID threadParam) while (true) { Sleep(500); - if (memcmp(buffer + HEADER_SIZE, currentAddress, dataLen) == 0) + if (memcmp(buffer + sizeof(ThreadParam), currentAddress, dataLen) == 0) { changeCount = 0; continue; @@ -471,12 +470,10 @@ DWORD WINAPI ReaderThread(LPVOID threadParam) else dataLen = strlen(currentAddress); - *(DWORD*)buffer = hook->hp.address; - *(DWORD*)(buffer + 4) = 0; - *(DWORD*)(buffer + 8) = 0; - memcpy(buffer + HEADER_SIZE, currentAddress, dataLen); + *(ThreadParam*)buffer = { GetCurrentProcessId(), hook->hp.address, 0, 0 }; + memcpy(buffer + sizeof(ThreadParam), currentAddress, dataLen); DWORD unused; - WriteFile(::hookPipe, buffer, dataLen + HEADER_SIZE, &unused, nullptr); + WriteFile(::hookPipe, buffer, dataLen + sizeof(ThreadParam), &unused, nullptr); } hook->ClearHook(); return 0; diff --git a/vnrhook/hijack/texthook.h b/vnrhook/hijack/texthook.h new file mode 100644 index 0000000..bd5d3d2 --- /dev/null +++ b/vnrhook/hijack/texthook.h @@ -0,0 +1,63 @@ +#pragma once + +// texthook.h +// 8/24/2013 jichi +// Branch: IHF_DLL/IHF_CLIENT.h, rev 133 +// +// 8/24/2013 TODO: +// - Clean up this file +// - Reduce global variables. Use namespaces or singleton classes instead. +#include "common.h" +#include "pipe.h" + +extern int currentHook; +extern DWORD trigger; + +// jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor +// interprocedure communication, where constructor/destructor will NOT work. +class TextHook +{ + int InsertHookCode(); + int InsertReadCode(); + int UnsafeInsertHookCode(); + DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn); + int RemoveHookCode(); + int RemoveReadCode(); + int SetHookName(LPCSTR name); +public: + LPSTR hook_name; + int name_length; + BYTE recover[0x68 - sizeof(HookParam)]; + BYTE original[0x10]; + HookParam hp; + + unsigned __int64 Address() const { return hp.address; } + DWORD Type() const { return hp.type; } + WORD Length() const { return hp.hook_len; } + LPSTR Name() const { return hook_name; } + int NameLength() const { return name_length; } + int InsertHook(); + int InitHook(const HookParam &hp, LPCSTR name = 0, WORD set_flag = 0); + DWORD Send(DWORD dwDataBase, DWORD dwRetn); + int ClearHook(); + int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed +}; + +// jichi 1/16/2015: Though called max hook, it means max number of text threads +enum { MAX_HOOK = 64 }; +enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(TextHook) * 2, HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) }; + +extern TextHook *hookman, +*current_available; + +extern bool running, +live; + +extern HANDLE hookPipe, +hmMutex; + +DWORD WINAPI PipeManager(LPVOID unused); + +enum : int { yes = 0, no = 1 }; + +// EOF diff --git a/vnrhook/include/const.h b/vnrhook/include/const.h deleted file mode 100644 index 6aeb203..0000000 --- a/vnrhook/include/const.h +++ /dev/null @@ -1,89 +0,0 @@ -#pragma once -#include "types.h" - -// vnrhook/const.h -// 8/23/2013 jichi -// Branch: ITH/common.h, rev 128 - -// jichi 1/16/2015: Though called max hook, it means max number of text threads -enum { MAX_HOOK = 64 }; // must be larger than HOOK_FUN_COUNT - -//enum { HOOK_SECTION_SIZE = 0x2000 }; // default ITH value -// jichi 1/16/2015: Change to a very large number to prevent crash -//enum { MAX_HOOK = 0x100 }; // must be larger than HookFunCount -enum { HOOK_SECTION_SIZE = MAX_HOOK * sizeof(Hook) * 2 }; // default ITH value is 0x2000 for 32 hook (0x100 per hook) - -// jichi 375/2014: Add offset of pusha/pushad -// http://faydoc.tripod.com/cpu/pushad.htm -// http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial -// -// Warning: The offset in ITH has -4 offset comparing to pusha and AGTH -enum pusha_off { - pusha_eax_off = -0x4 - , pusha_ecx_off = -0x8 - , pusha_edx_off = -0xc - , pusha_ebx_off = -0x10 - , pusha_esp_off = -0x14 - , pusha_ebp_off = -0x18 - , pusha_esi_off = -0x1c - , pusha_edi_off = -0x20 - , pusha_off = -0x24 // pushad offset -}; - -enum HostCommandType { - HOST_COMMAND = -1 // null type - , HOST_COMMAND_NEW_HOOK = 0 - , HOST_COMMAND_REMOVE_HOOK = 1 - , HOST_COMMAND_MODIFY_HOOK = 2 - , HOST_COMMAND_HIJACK_PROCESS = 3 - , HOST_COMMAND_DETACH = 4 -}; - -enum HostNotificationType { - HOST_NOTIFICATION = -1 // null type - , HOST_NOTIFICATION_TEXT = 0 - , HOST_NOTIFICATION_NEWHOOK = 1 - , HOST_NOTIFICATION_RMVHOOK = 2 -}; - -// jichi 9/8/2013: The meaning are guessed -// Values must be within DWORD -// Unused values are as follows: -// - 0x100 -enum HookParamType : unsigned long { - USING_STRING = 0x1 // type(data) is char* or wchar_t* and has length - , USING_UNICODE = 0x2 // type(data) is wchar_t or wchar_t* - , BIG_ENDIAN = 0x4 // type(data) is char - , DATA_INDIRECT = 0x8 - , USING_SPLIT = 0x10 // aware of split time? - , SPLIT_INDIRECT = 0x20 - , MODULE_OFFSET = 0x40 // do hash module, and the address is relative to module - //, FUNCTION_OFFSET = 0x80 // do hash function, and the address is relative to funccion - , USING_UTF8 = 0x100 - //, STRING_LAST_CHAR = 0x200 - , NO_CONTEXT = 0x400 - , HOOK_EMPTY = 0x800 - , FIXING_SPLIT = 0x1000 - , DIRECT_READ = 0x2000 // /R read code instead of classic /H hook code - //, HOOK_AUXILIARY = 0x2000 // jichi 12/13/2013: None of known hooks are auxiliary - //, RELATIVE_SPLIT = 0x2000 // Artikash 8/3/2018: does nothing - , HOOK_ENGINE = 0x4000 - , HOOK_ADDITIONAL = 0x8000 -}; - -// 6/1/2014: Fixed split value for hok parameter -// Fuse all threads, and prevent floating -enum { FIXED_SPLIT_VALUE = 0x10001 }; - -enum { PIPE_BUFFER_SIZE = 0x1000}; - -// jichi 12/25/2013: Header in each message sent to vnrsrv -// There are totally three elements -// - 0x0 dwAddr hook address -// - 0x4 dwRetn return address -// - 0x8 dwSplit split value -#define HEADER_SIZE sizeof(DWORD) * 3 - -#define TIMEOUT 5000 // 5 seconds - -// EOF diff --git a/vnrhook/include/types.h b/vnrhook/include/types.h deleted file mode 100644 index a6a1304..0000000 --- a/vnrhook/include/types.h +++ /dev/null @@ -1,66 +0,0 @@ -#pragma once - -// vnrhook/types.h -// 8/23/2013 jichi -// Branch: ITH/common.h, rev 128 - -#include // needed for windef types - - /** jichi 3/7/2014: Add guessed comment - * - * DWORD addr absolute or relative address - * DWORD split esp offset of the split character - * - * http://faydoc.tripod.com/cpu/pushad.htm - * http://agth.wikia.com/wiki/Cheat_Engine_AGTH_Tutorial - * The order is the same as pushd - * EAX, ECX, EDX, EBX, ESP (original value), EBP, ESI, and EDI (if the current operand-size attribute is 32) and AX, CX, DX, BX, SP - * Negative values of 'data_offset' and 'sub_offset' refer to registers:-4 for EAX, -8 for ECX, -C for EDX, -10 for EBX, -14 for ESP, -18 for EBP, -1C for ESI, -20 for EDI - */ -struct HookParam { - // jichi 8/24/2013: For special hooks. - typedef void (*text_fun_t)(DWORD esp, HookParam *hp, BYTE index, DWORD *data, DWORD *split, DWORD *len); - - // jichi 10/24/2014: Add filter function. Return true if skip the text - typedef bool (*filter_fun_t)(LPVOID str, DWORD *len, HookParam *hp, BYTE index); - - // jichi 10/24/2014: Add generic hook function, return false if stop execution. - typedef bool (*hook_fun_t)(DWORD esp, HookParam *hp); - - unsigned __int64 address; // absolute or relative address - short offset, // offset of the data in the memory - index, - split, // offset of the split character - split_index; - - DWORD module; // hash of the module - text_fun_t text_fun; - filter_fun_t filter_fun; - hook_fun_t hook_fun; - DWORD type; // flags - WORD length_offset; // index of the string length - BYTE hook_len, // ? - recover_len; // ? - - // 7/20/2014: jichi additional parameters for PSP games - DWORD user_value; - - // Artikash 8/4/2018: handle for reader thread - HANDLE readerHandle; -}; - -struct Hook { // size: 0x80 - HookParam hp; - LPSTR hook_name; - int name_length; - BYTE recover[0x68 - sizeof(HookParam)]; - BYTE original[0x10]; - - unsigned __int64 Address() const { return hp.address; } - DWORD Type() const { return hp.type; } - WORD Length() const { return hp.hook_len; } - LPSTR Name() const { return hook_name; } - int NameLength() const { return name_length; } -}; - -// EOF diff --git a/vnrhook/main.cc b/vnrhook/main.cc new file mode 100644 index 0000000..d60b8ad --- /dev/null +++ b/vnrhook/main.cc @@ -0,0 +1,128 @@ +// main.cc +// 8/24/2013 jichi +// Branch: ITH_DLL/main.cpp, rev 128 +// 8/24/2013 TODO: Clean up this file + +#ifdef _MSC_VER +# pragma warning (disable:4100) // C4100: unreference formal parameter +//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler +#endif // _MSC_VER + +#include "main.h" +#include "defs.h" +#include "engine/engine.h" +#include "engine/match.h" +#include "hijack/texthook.h" +#include "util/growl.h" + +// Global variables + +// jichi 6/3/2014: memory range of the current module +DWORD processStartAddress, +processStopAddress; + +WCHAR hm_section[0x100]; +HANDLE hSection; +bool running; +int currentHook = 0, +user_hook_count = 0; +DWORD trigger = 0; +HANDLE +hFile, +hMutex, +hmMutex; + +BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused) +{ + switch (fdwReason) + { + case DLL_PROCESS_ATTACH: + { + ::hmMutex = CreateMutexW(nullptr, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(GetCurrentProcessId())).c_str()); + if (GetLastError() == ERROR_ALREADY_EXISTS) return FALSE; + DisableThreadLibraryCalls(hModule); + + // jichi 9/25/2013: Interprocedural communication with vnrsrv. + hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE, 0, HOOK_SECTION_SIZE, (ITH_SECTION_ + std::to_wstring(GetCurrentProcessId())).c_str()); + ::hookman = (TextHook*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE); + + ::processStartAddress = ::processStopAddress = (DWORD)GetModuleHandleW(nullptr); + + MEMORY_BASIC_INFORMATION info; + do + { + VirtualQuery((void*)::processStopAddress, &info, sizeof(info)); + ::processStopAddress = (DWORD)info.BaseAddress + info.RegionSize; + } while (info.Protect > PAGE_NOACCESS); + processStopAddress -= info.RegionSize; + + ::running = true; + ::current_available = ::hookman; + + CreatePipe(); + } + break; + case DLL_PROCESS_DETACH: + { + ::running = false; + + for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++) man->ClearHook(); + //if (ith_has_section) + UnmapViewOfFile(::hookman); + + CloseHandle(::hookPipe); + CloseHandle(hSection); + CloseHandle(hMutex); + CloseHandle(hmMutex); + //} ITH_EXCEPT {} + } + break; + } + return TRUE; +} + +//extern "C" { +DWORD NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag) +{ + std::string name = lpname; + int current = ::current_available - ::hookman; + if (current < MAX_HOOK) { + //flag &= 0xffff; + //if ((flag & HOOK_AUXILIARY) == 0) + flag |= HOOK_ADDITIONAL; + if (name[0] == '\0') + { + name = "UserHook" + std::to_string(user_hook_count++); + } + + ConsoleOutput(("vnrcli:NewHook: try inserting hook: " + name).c_str()); + + // jichi 7/13/2014: This function would raise when too many hooks added + ::hookman[current].InitHook(hp, name.c_str(), flag & 0xffff); + + if (::hookman[current].InsertHook() == 0) { + ConsoleOutput(("vnrcli:NewHook: inserted hook: " + name).c_str()); + NotifyHookInsert(hp, name.c_str()); + } + else + ConsoleOutput("vnrcli:NewHook:WARNING: failed to insert hook"); + } + return 0; +} +DWORD RemoveHook(DWORD addr) +{ + for (int i = 0; i < MAX_HOOK; i++) + if (::hookman[i].Address() == addr) { + ::hookman[i].ClearHook(); + return 0; + } + return 0; +} + +DWORD SwitchTrigger(DWORD t) +{ + trigger = t; + return 0; +} + +// EOF \ No newline at end of file diff --git a/vnrhook/src/main.h b/vnrhook/main.h similarity index 92% rename from vnrhook/src/main.h rename to vnrhook/main.h index 4cce4e0..7593de5 100644 --- a/vnrhook/src/main.h +++ b/vnrhook/main.h @@ -4,8 +4,8 @@ // 8/23/2013 jichi // Branch: ITH/IHF_DLL.h, rev 66 -#include "include/const.h" -#include "include/types.h" +#include "common.h" +#include "pipe.h" void ConsoleOutput(LPCSTR text); // jichi 12/25/2013: Used to return length of sent text void NotifyHookInsert(HookParam hp, LPCSTR name); diff --git a/vnrhook/pipe.cc b/vnrhook/pipe.cc new file mode 100644 index 0000000..73d1e2c --- /dev/null +++ b/vnrhook/pipe.cc @@ -0,0 +1,116 @@ +// pipe.cc +// 8/24/2013 jichi +// Branch: ITH_DLL/pipe.cpp, rev 66 +// 8/24/2013 TODO: Clean up this file + +#ifdef _MSC_VER +# pragma warning (disable:4100) // C4100: unreference formal parameter +#endif // _MSC_VER + +#include "pipe.h" +#include "main.h" +#include "hijack/texthook.h" +#include "engine/match.h" +#include "defs.h" +#include "const.h" +#include "growl.h" + +HANDLE hookPipe; + +DWORD DUMMY[100]; + +void CreatePipe() +{ + std::thread([]() + { + enum { STANDARD_WAIT = 50 }; + while (::running) + { + DWORD count = 0; + BYTE buffer[PIPE_BUFFER_SIZE] = {}; + HANDLE hostPipe = ::hookPipe = INVALID_HANDLE_VALUE, + pipeAcquisitionMutex = CreateMutexW(nullptr, TRUE, ITH_GRANTPIPE_MUTEX); + + while (::hookPipe == INVALID_HANDLE_VALUE || hostPipe == INVALID_HANDLE_VALUE) + { + if (::hookPipe == INVALID_HANDLE_VALUE) + { + ::hookPipe = CreateFileW(ITH_TEXT_PIPE, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + } + if (hostPipe == INVALID_HANDLE_VALUE) + { + hostPipe = CreateFileW(ITH_COMMAND_PIPE, GENERIC_READ | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); + DWORD mode = PIPE_READMODE_MESSAGE; + SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL); + } + Sleep(STANDARD_WAIT); + } + + *(DWORD*)buffer = GetCurrentProcessId(); + WriteFile(::hookPipe, buffer, sizeof(DWORD), &count, nullptr); + + ReleaseMutex(pipeAcquisitionMutex); + CloseHandle(pipeAcquisitionMutex); + + ConsoleOutput("vnrcli:WaitForPipe: pipe connected"); +#ifdef _WIN64 + ConsoleOutput("Hooks don't work on x64, only read codes work. Engine disabled."); +#else + Engine::Hijack(); +#endif + + while (::running && ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE, &count, nullptr)) + switch (*(int*)buffer) + { + case HOST_COMMAND_NEW_HOOK: + { + auto info = *(InsertHookCmd*)buffer; + NewHook(info.hp, info.name); + } + break; + case HOST_COMMAND_REMOVE_HOOK: + { + auto info = *(RemoveHookCmd*)buffer; + for (int i = 0; i < MAX_HOOK; ++i) + if (::hookman[i].Address() == info.address) + ::hookman[i].ClearHook(); + } + break; + case HOST_COMMAND_DETACH: + { + ::running = false; + } + break; + } + + CloseHandle(hostPipe); + } + FreeLibraryAndExitThread(GetModuleHandleW(ITH_DLL), 0); + }).detach(); +} + +void ConsoleOutput(LPCSTR text) +{ + auto info = ConsoleOutputNotif(text); + WriteFile(::hookPipe, &info, strlen(text) + sizeof(info), DUMMY, nullptr); +} + +void NotifyHookInsert(HookParam hp, LPCSTR name) +{ + //BYTE buffer[PIPE_BUFFER_SIZE]; + //*(DWORD*)buffer = HOST_NOTIFICATION; + //*(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_NEWHOOK; + //*(HookParam*)(buffer + sizeof(DWORD) * 2) = hp; + //strcpy((char*)buffer + sizeof(DWORD) * 2 + sizeof(HookParam), name); + //DWORD unused; + //WriteFile(::hookPipe, buffer, strlen(name) + sizeof(DWORD) * 2 + sizeof(HookParam), &unused, nullptr); + //return; +} + +void NotifyHookRemove(DWORD addr) +{ + auto info = HookRemovedNotif(addr); + WriteFile(::hookPipe, &info, sizeof(info), DUMMY, nullptr); +} + +// EOF diff --git a/vnrhook/src/engine/hookdefs.h b/vnrhook/src/engine/hookdefs.h deleted file mode 100644 index f429a2d..0000000 --- a/vnrhook/src/engine/hookdefs.h +++ /dev/null @@ -1,12 +0,0 @@ -#pragma once - -// engine/hookdefs.h -// 7/20/2014 jichi - -// For HookParam user flags -enum HookParamFlag : unsigned long { - HPF_Null = 0 // never used - , HPF_IgnoreSameAddress = 1 // ignore the last same text address -}; - -// EOF diff --git a/vnrhook/src/hijack/texthook.h b/vnrhook/src/hijack/texthook.h deleted file mode 100644 index 4bb319e..0000000 --- a/vnrhook/src/hijack/texthook.h +++ /dev/null @@ -1,78 +0,0 @@ -#pragma once - -// texthook.h -// 8/24/2013 jichi -// Branch: IHF_DLL/IHF_CLIENT.h, rev 133 -// -// 8/24/2013 TODO: -// - Clean up this file -// - Reduce global variables. Use namespaces or singleton classes instead. -#include -#include -#include "include/types.h" -#include - -extern int currentHook; -extern WCHAR dll_mutex[]; -//extern WCHAR dll_name[]; -extern DWORD trigger; -//extern DWORD current_process_id; - -// jichi 6/3/2014: Get memory range of the current module -extern DWORD processStartAddress, - processStopAddress; - -void InitFilterTable(); - -// jichi 9/25/2013: This class will be used by NtMapViewOfSectionfor -// interprocedure communication, where constructor/destructor will NOT work. -class TextHook : public Hook -{ - int InsertHookCode(); - int InsertReadCode(); - int UnsafeInsertHookCode(); - DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn); - int RemoveHookCode(); - int RemoveReadCode(); - int SetHookName(LPCSTR name); -public: - int InsertHook(); - int InitHook(const HookParam &hp, LPCSTR name = 0, WORD set_flag = 0); - DWORD Send(DWORD dwDataBase, DWORD dwRetn); - int ClearHook(); - int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed -}; - -extern TextHook *hookman, - *current_available; - -//void InitDefaultHook(); - -struct FilterRange { DWORD lower, upper; }; -extern FilterRange *filter; - -extern bool running, - live; - -extern HANDLE hookPipe, - hmMutex; - -DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter); -DWORD WINAPI CommandPipe(LPVOID lpThreadParameter); -DWORD WINAPI PipeManager(LPVOID unused); - -//void RequestRefreshProfile(); - -//typedef DWORD (*InsertHookFun)(DWORD); -//typedef DWORD (*IdentifyEngineFun)(); -//typedef DWORD (*InsertDynamicHookFun)(LPVOID addr, DWORD frame, DWORD stack); -//extern IdentifyEngineFun IdentifyEngine; -//extern InsertDynamicHookFun InsertDynamicHook; - -// jichi 9/28/2013: Protect pipeline in wine -void CliLockPipe(); -void CliUnlockPipe(); - -enum : int { yes = 0, no = 1 }; - -// EOF diff --git a/vnrhook/src/main.cc b/vnrhook/src/main.cc deleted file mode 100644 index 37786a1..0000000 --- a/vnrhook/src/main.cc +++ /dev/null @@ -1,175 +0,0 @@ -// main.cc -// 8/24/2013 jichi -// Branch: ITH_DLL/main.cpp, rev 128 -// 8/24/2013 TODO: Clean up this file - -#ifdef _MSC_VER -# pragma warning (disable:4100) // C4100: unreference formal parameter -//# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler -#endif // _MSC_VER - -#include "src/main.h" -#include "src/engine/engine.h" -#include "src/engine/match.h" -#include "src/hijack/texthook.h" -#include "src/util/growl.h" -#include "src/except.h" -#include "include/const.h" -#include "include/defs.h" -#include "ithsys/ithsys.h" -#include "util/util.h" -#include // for swprintf -//#include "ntinspect/ntinspect.h" -//#include "winseh/winseh.h" -//#include -//#include "md5.h" -//#include -//#include - -// Global variables - -// jichi 6/3/2014: memory range of the current module -DWORD processStartAddress, - processStopAddress; - -enum { HOOK_BUFFER_SIZE = MAX_HOOK * sizeof(TextHook) }; - -WCHAR hm_section[0x100]; -HANDLE hSection; -bool running; -int currentHook = 0, - user_hook_count = 0; -DWORD trigger = 0; -HANDLE - hFile, - hMutex, - hmMutex; -HMODULE currentModule; -//DWORD current_process_id; -extern DWORD enter_count; -//extern LPWSTR current_dir; -extern DWORD engine_type; - -BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused) -{ - static HANDLE pipeThread; - - - switch (fdwReason) { - case DLL_PROCESS_ATTACH: - { - static bool attached_ = false; - if (attached_) // already attached - { - return TRUE; - } - attached_ = true; - - DisableThreadLibraryCalls(hModule); - - swprintf(hm_section, ITH_SECTION_ L"%d", GetCurrentProcessId()); - - // jichi 9/25/2013: Interprocedural communication with vnrsrv. - hSection = CreateFileMappingW(INVALID_HANDLE_VALUE, nullptr, PAGE_EXECUTE_READWRITE, 0, HOOK_SECTION_SIZE, hm_section); - ::hookman = (TextHook*)MapViewOfFile(hSection, FILE_MAP_ALL_ACCESS | FILE_MAP_EXECUTE, 0, 0, HOOK_BUFFER_SIZE); - - ::processStartAddress = ::processStopAddress = (DWORD)GetModuleHandleW(nullptr); - -#ifndef _WIN64 - MEMORY_BASIC_INFORMATION info; - do - { - VirtualQuery((void*)::processStopAddress, &info, sizeof(info)); - ::processStopAddress = (DWORD)info.BaseAddress + info.RegionSize; - } while (info.Protect > PAGE_NOACCESS); - processStopAddress -= info.RegionSize; -#endif - - { - wchar_t hm_mutex[0x100]; - swprintf(hm_mutex, ITH_HOOKMAN_MUTEX_ L"%d", GetCurrentProcessId()); - ::hmMutex = CreateMutexW(nullptr, FALSE, hm_mutex); - if (GetLastError() == ERROR_ALREADY_EXISTS) - return FALSE; - } - - ::running = true; - ::current_available = ::hookman; - ::currentModule = hModule; - - pipeThread = CreateThread(nullptr, 0, PipeManager, 0, 0, nullptr); - } break; - case DLL_PROCESS_DETACH: - { - static bool detached_ = false; - if (detached_) // already detached - return TRUE; - detached_ = true; - - // jichi 10/2/2103: Cannot use __try in functions that require object unwinding - //ITH_TRY { - ::running = false; - - if (pipeThread) { - WaitForSingleObject(pipeThread, TIMEOUT); - CloseHandle(pipeThread); - } - - for (TextHook *man = ::hookman; man < ::hookman + MAX_HOOK; man++) - man->ClearHook(); - //if (ith_has_section) - UnmapViewOfFile(::hookman); - - CloseHandle(hSection); - CloseHandle(hMutex); - CloseHandle(hmMutex); - //} ITH_EXCEPT {} - } break; - } - return TRUE; -} - -//extern "C" { -DWORD NewHook(const HookParam &hp, LPCSTR lpname, DWORD flag) -{ - std::string name = lpname; - int current = ::current_available - ::hookman; - if (current < MAX_HOOK) { - //flag &= 0xffff; - //if ((flag & HOOK_AUXILIARY) == 0) - flag |= HOOK_ADDITIONAL; - if (name[0] == '\0') - { - name = "UserHook" + std::to_string(user_hook_count++); - } - - ConsoleOutput(("vnrcli:NewHook: try inserting hook: " + name).c_str()); - - // jichi 7/13/2014: This function would raise when too many hooks added - ::hookman[current].InitHook(hp, name.c_str(), flag & 0xffff); - - if (::hookman[current].InsertHook() == 0) { - ConsoleOutput(("vnrcli:NewHook: inserted hook: " + name).c_str()); - NotifyHookInsert(hp, name.c_str()); - } else - ConsoleOutput("vnrcli:NewHook:WARNING: failed to insert hook"); - } - return 0; -} -DWORD RemoveHook(DWORD addr) -{ - for (int i = 0; i < MAX_HOOK; i++) - if (::hookman[i].Address ()== addr) { - ::hookman[i].ClearHook(); - return 0; - } - return 0; -} - -DWORD SwitchTrigger(DWORD t) -{ - trigger = t; - return 0; -} - -// EOF \ No newline at end of file diff --git a/vnrhook/src/pipe.cc b/vnrhook/src/pipe.cc deleted file mode 100644 index 8818336..0000000 --- a/vnrhook/src/pipe.cc +++ /dev/null @@ -1,138 +0,0 @@ -// pipe.cc -// 8/24/2013 jichi -// Branch: ITH_DLL/pipe.cpp, rev 66 -// 8/24/2013 TODO: Clean up this file - -#ifdef _MSC_VER -# pragma warning (disable:4100) // C4100: unreference formal parameter -#endif // _MSC_VER - -#include "src/hijack/texthook.h" -#include "src/engine/match.h" -#include "src/util/util.h" -#include "src/main.h" -#include "include/defs.h" -#include "src/util/growl.h" -#include "ithsys/ithsys.h" -#include // for swprintf - -HANDLE hookPipe; -extern HMODULE currentModule; - -DWORD WINAPI PipeManager(LPVOID unused) -{ - enum { STANDARD_WAIT = 50 }; - while (::running) - { - DWORD count; - BYTE buffer[PIPE_BUFFER_SIZE]; - HANDLE hostPipe = ::hookPipe = INVALID_HANDLE_VALUE, - pipeAcquisitionMutex = CreateMutexW(nullptr, TRUE, ITH_GRANTPIPE_MUTEX); - - while (::hookPipe == INVALID_HANDLE_VALUE || hostPipe == INVALID_HANDLE_VALUE) - { - if (::hookPipe == INVALID_HANDLE_VALUE) - { - ::hookPipe = CreateFileW(ITH_TEXT_PIPE, GENERIC_WRITE, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - } - if (hostPipe == INVALID_HANDLE_VALUE) - { - hostPipe = CreateFileW(ITH_COMMAND_PIPE, GENERIC_READ | FILE_WRITE_ATTRIBUTES, FILE_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr); - DWORD mode = PIPE_READMODE_MESSAGE; - SetNamedPipeHandleState(hostPipe, &mode, NULL, NULL); - } - Sleep(STANDARD_WAIT); - } - - *(DWORD*)buffer = GetCurrentProcessId(); - WriteFile(::hookPipe, buffer, sizeof(DWORD), &count, nullptr); - - ReleaseMutex(pipeAcquisitionMutex); - CloseHandle(pipeAcquisitionMutex); - - ConsoleOutput("vnrcli:WaitForPipe: pipe connected"); -#ifdef _WIN64 - ConsoleOutput("Hooks don't work on x64, only read codes work. Engine disabled."); -#else - Engine::Hijack(); -#endif - - while (::running) - { - if (!ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE / 2, &count, nullptr)) // Artikash 5/21/2018: why / 2? wchar_t? - { - break; - } - DWORD command = *(DWORD*)buffer; - switch (command) - { - case HOST_COMMAND_NEW_HOOK: - buffer[count] = 0; - NewHook(*(HookParam *)(buffer + sizeof(DWORD)), // Hook parameter - (LPSTR)(buffer + 4 + sizeof(HookParam)), // Hook name - 0 - ); - break; - case HOST_COMMAND_REMOVE_HOOK: - { - TextHook *in = hookman; - for (int i = 0; i < currentHook; in++) - { - if (in->Address()) i++; - if (in->Address() == *(DWORD *)(buffer + sizeof(DWORD))) // Hook address - { - break; - } - } - if (in->Address()) - { - in->ClearHook(); - } - } - break; - case HOST_COMMAND_DETACH: - ::running = false; - break; - } - } - CloseHandle(::hookPipe); - CloseHandle(hostPipe); - } - FreeLibraryAndExitThread(::currentModule, 0); - return 0; -} - -void ConsoleOutput(LPCSTR text) -{ - BYTE buffer[PIPE_BUFFER_SIZE]; - *(DWORD*)buffer = HOST_NOTIFICATION; - *(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_TEXT; - strcpy((char*)buffer + sizeof(DWORD) * 2, text); - DWORD unused; - WriteFile(::hookPipe, buffer, strlen(text) + sizeof(DWORD) * 2, &unused, nullptr); -} - -void NotifyHookInsert(HookParam hp, LPCSTR name) -{ - BYTE buffer[PIPE_BUFFER_SIZE]; - *(DWORD*)buffer = HOST_NOTIFICATION; - *(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_NEWHOOK; - *(HookParam*)(buffer + sizeof(DWORD) * 2) = hp; - strcpy((char*)buffer + sizeof(DWORD) * 2 + sizeof(HookParam), name); - DWORD unused; - WriteFile(::hookPipe, buffer, strlen(name) + sizeof(DWORD) * 2 + sizeof(HookParam), &unused, nullptr); - return; -} - -void NotifyHookRemove(DWORD addr) -{ - BYTE buffer[sizeof(DWORD) * 3]; - *(DWORD*)buffer = HOST_NOTIFICATION; - *(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_RMVHOOK; - *(DWORD*)(buffer + sizeof(DWORD) * 2) = addr; - DWORD unused; - WriteFile(::hookPipe, buffer, sizeof(DWORD) * 3, &unused, nullptr); - return; -} - -// EOF diff --git a/vnrhook/src/util/cpputil/cppcstring.h b/vnrhook/util/cpputil/cppcstring.h similarity index 100% rename from vnrhook/src/util/cpputil/cppcstring.h rename to vnrhook/util/cpputil/cppcstring.h diff --git a/vnrhook/src/util/disasm/disasm.cc b/vnrhook/util/disasm/disasm.cc similarity index 100% rename from vnrhook/src/util/disasm/disasm.cc rename to vnrhook/util/disasm/disasm.cc diff --git a/vnrhook/src/util/disasm/disasm.h b/vnrhook/util/disasm/disasm.h similarity index 100% rename from vnrhook/src/util/disasm/disasm.h rename to vnrhook/util/disasm/disasm.h diff --git a/vnrhook/src/except.h b/vnrhook/util/except.h similarity index 100% rename from vnrhook/src/except.h rename to vnrhook/util/except.h diff --git a/vnrhook/src/util/growl.h b/vnrhook/util/growl.h similarity index 100% rename from vnrhook/src/util/growl.h rename to vnrhook/util/growl.h diff --git a/vnrhook/src/util/ithsys/ithsys.cc b/vnrhook/util/ithsys/ithsys.cc similarity index 100% rename from vnrhook/src/util/ithsys/ithsys.cc rename to vnrhook/util/ithsys/ithsys.cc diff --git a/vnrhook/src/util/ithsys/ithsys.h b/vnrhook/util/ithsys/ithsys.h similarity index 100% rename from vnrhook/src/util/ithsys/ithsys.h rename to vnrhook/util/ithsys/ithsys.h diff --git a/vnrhook/src/util/memdbg/memdbg.h b/vnrhook/util/memdbg/memdbg.h similarity index 100% rename from vnrhook/src/util/memdbg/memdbg.h rename to vnrhook/util/memdbg/memdbg.h diff --git a/vnrhook/src/util/memdbg/memsearch.cc b/vnrhook/util/memdbg/memsearch.cc similarity index 100% rename from vnrhook/src/util/memdbg/memsearch.cc rename to vnrhook/util/memdbg/memsearch.cc diff --git a/vnrhook/src/util/memdbg/memsearch.h b/vnrhook/util/memdbg/memsearch.h similarity index 100% rename from vnrhook/src/util/memdbg/memsearch.h rename to vnrhook/util/memdbg/memsearch.h diff --git a/vnrhook/src/util/mono/monoobject.h b/vnrhook/util/mono/monoobject.h similarity index 100% rename from vnrhook/src/util/mono/monoobject.h rename to vnrhook/util/mono/monoobject.h diff --git a/vnrhook/src/util/mono/monotype.h b/vnrhook/util/mono/monotype.h similarity index 100% rename from vnrhook/src/util/mono/monotype.h rename to vnrhook/util/mono/monotype.h diff --git a/vnrhook/src/util/ntdll/ntdll.h b/vnrhook/util/ntdll/ntdll.h similarity index 100% rename from vnrhook/src/util/ntdll/ntdll.h rename to vnrhook/util/ntdll/ntdll.h diff --git a/vnrhook/src/util/util.cc b/vnrhook/util/util.cc similarity index 99% rename from vnrhook/src/util/util.cc rename to vnrhook/util/util.cc index 3c8c2de..5a499f9 100644 --- a/vnrhook/src/util/util.cc +++ b/vnrhook/util/util.cc @@ -3,7 +3,7 @@ // Branch: ITH_Engine/engine.cpp, revision 133 // See: http://ja.wikipedia.org/wiki/プロジェクト:美少女ゲーム系/ゲームエンジン -#include "src/util/util.h" +#include "util/util.h" #include "ithsys/ithsys.h" namespace { // unnamed diff --git a/vnrhook/src/util/util.h b/vnrhook/util/util.h similarity index 100% rename from vnrhook/src/util/util.h rename to vnrhook/util/util.h