From fb56457cdb29b96046b87b5c77feb9d32dbdf478 Mon Sep 17 00:00:00 2001 From: Akash Mozumdar Date: Fri, 1 Jun 2018 02:36:51 -0400 Subject: [PATCH] finish rewriting hookman, still some cleanup to do --- vnr/texthook/host/hookman.cc | 273 +++++++++------------------------ vnr/texthook/host/hookman.h | 8 +- vnr/texthook/host/host.cc | 6 +- vnr/texthook/host/host_p.h | 2 +- vnr/texthook/host/pipe.cc | 33 ++-- vnr/texthook/host/textthread.h | 1 - 6 files changed, 97 insertions(+), 226 deletions(-) diff --git a/vnr/texthook/host/hookman.cc b/vnr/texthook/host/hookman.cc index 2c61a96..1dc2460 100644 --- a/vnr/texthook/host/hookman.cc +++ b/vnr/texthook/host/hookman.cc @@ -60,7 +60,7 @@ DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max) if (!pr) return 0; NtWaitForSingleObject(pr->hookman_mutex, 0, 0); - Hook *hks = (Hook *)pr->hookman_map; + const Hook *hks = (const Hook *)pr->hookman_map; for (int i = 0; i < MAX_HOOK; i++) if (hks[i].Address() == hook_addr) { len = hks[i].NameLength(); @@ -175,36 +175,9 @@ HookManager::HookManager() : , threadTable() , processRecordsByIds() { - // jichi 9/21/2013: zero memory - ::memset(record, 0, sizeof(record)); - ::memset(text_pipes, 0, sizeof(text_pipes)); - ::memset(cmd_pipes, 0, sizeof(cmd_pipes)); - ::memset(recv_threads, 0, sizeof(recv_threads)); - - head.key = new ThreadParameter; - head.key->pid = 0; - head.key->hook = -1; - head.key->retn = -1; - head.key->spl = -1; - head.data = 0; - thread_table = new ThreadTable; // jichi 9/26/2013: zero memory in ThreadTable - TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread(0, -1, -1, -1, threadTable.size()); consoleTextThread->Status() |= USING_UNICODE; SetCurrent(consoleTextThread); - - TextThread *entry = new TextThread(0, -1,-1,-1, new_thread_number++); // jichi 9/26/2013: zero memory in TextThread - thread_table->SetThread(0, entry); - SetCurrent(entry); - entry->Status() |= USING_UNICODE; - //texts->SetUnicode(true); - //entry->AddToCombo(); - //entry->ComboSelectCurrent(); - - //if (background==0) entry->AddToStore((BYTE*)BackgroundMsg,wcslen(BackgroundMsg)<<1,0,1); - - //InitializeCriticalSection(&hmcs); - destroy_event = IthCreateEvent(0, 0, 0); } HookManager::~HookManager() @@ -307,127 +280,73 @@ void HookManager::RemoveProcessContext(DWORD pid) void HookManager::RegisterThread(TextThread* it, DWORD num) { thread_table->SetThread(num, it); } -void HookManager::RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread) -{ - text_pipes[register_count] = text; - cmd_pipes[register_count] = cmd; - recv_threads[register_count] = thread; - register_count++; - if (register_count == 1) - NtSetEvent(destroy_event, 0); - else - NtClearEvent(destroy_event); -} -void HookManager::RegisterProcess(DWORD pid) +void HookManager::RegisterProcess(DWORD pid, HANDLE hostPipe) { HM_LOCK; wchar_t str[0x40], path[MAX_PATH]; - //pid_map->Set(pid>>2); - //ConsoleOutput("vnrhost:RegisterProcess: lock"); - //EnterCriticalSection(&hmcs); - record[register_count - 1].pid_register = pid; - //record[register_count - 1].engine_register = engine; - swprintf(str, ITH_SECTION_ L"%d", pid); - HANDLE hSection = IthCreateSection(str, HOOK_SECTION_SIZE, PAGE_READONLY); - LPVOID map = nullptr; - //DWORD map_size = 0x1000; - DWORD map_size = HOOK_SECTION_SIZE / 2; // jichi 1/16/2015: Changed to half to hook section size - //if (::ith_has_section) - NtMapViewOfSection(hSection, NtCurrentProcess(), - &map, 0, map_size, 0, &map_size, ViewUnmap, 0, - PAGE_READONLY); - record[register_count - 1].hookman_section = hSection; - record[register_count - 1].hookman_map = map; + ProcessRecord* record = processRecordsByIds[pid] = new ProcessRecord; + record->hostPipe = hostPipe; + record->hookman_section = OpenFileMappingW(FILE_MAP_READ, FALSE, (std::wstring(ITH_SECTION_) + std::to_wstring(pid)).c_str()); + record->hookman_map = MapViewOfFile(record->hookman_section, FILE_MAP_READ, 0, 0, HOOK_SECTION_SIZE / 2); // jichi 1/16/2015: Changed to half to hook section size + record->process_handle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid); + record->hookman_mutex = OpenMutexW(MUTEX_ALL_ACCESS, FALSE, (std::wstring(ITH_HOOKMAN_MUTEX_) + std::to_wstring(pid)).c_str()); + //if (NT_SUCCESS(NtOpenProcess(&hProc, + // PROCESS_QUERY_INFORMATION| + // PROCESS_CREATE_THREAD| + // PROCESS_VM_READ| + // PROCESS_VM_WRITE| + // PROCESS_VM_OPERATION, + // &oa,&id))) - HANDLE hProc; - CLIENT_ID id; - id.UniqueProcess = pid; - id.UniqueThread = 0; - OBJECT_ATTRIBUTES oa = {}; - oa.uLength = sizeof(oa); - if (NT_SUCCESS(NtOpenProcess(&hProc, - PROCESS_QUERY_INFORMATION| - PROCESS_CREATE_THREAD| - PROCESS_VM_READ| - PROCESS_VM_WRITE| - PROCESS_VM_OPERATION, - &oa,&id))) - record[register_count - 1].process_handle = hProc; - else { - DOUT("failed to open process"); - //::man->AddConsoleOutput(ErrorOpenProcess); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RegisterProcess: unlock"); - return; - } - - // jichi 9/27/2013: The hook man should be consistent with the one defined in vnrcli - //Hook *h = (Hook *)map; - //for (int i = 0; i < MAX_HOOK; i++) - // if (!h[i].hook_name) - // break; - // else { - // const Hook &hi = h[i]; - // wchar_t buffer[1000]; - // DWORD len = hi.NameLength(); - // NtReadVirtualMemory(hProc, hi.hook_name, buffer, len << 1, &len); - // buffer[len] = 0; - // ITH_MSG(buffer); - // } - - swprintf(str, ITH_HOOKMAN_MUTEX_ L"%d", pid); - record[register_count - 1].hookman_mutex = IthOpenMutex(str); - current_pid = pid; if (attach) attach(pid); - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:RegisterProcess: unlock"); + } void HookManager::UnRegisterProcess(DWORD pid) { - HM_LOCK; - //ConsoleOutput("vnrhost:UnRegisterProcess: lock"); - //EnterCriticalSection(&hmcs); + //HM_LOCK; + ////ConsoleOutput("vnrhost:UnRegisterProcess: lock"); + ////EnterCriticalSection(&hmcs); - int i; - for (i = 0; i < MAX_REGISTER; i++) - if(record[i].pid_register == pid) - break; + //int i; + //for (i = 0; i < MAX_REGISTER; i++) + // if(record[i].pid_register == pid) + // break; - if (i < MAX_REGISTER) { - NtClose(text_pipes[i]); - NtClose(cmd_pipes[i]); - NtClose(recv_threads[i]); - NtClose(record[i].hookman_mutex); + //if (i < MAX_REGISTER) { + // NtClose(text_pipes[i]); + // NtClose(cmd_pipes[i]); + // NtClose(recv_threads[i]); + CloseHandle(processRecordsByIds[pid]->hookman_mutex); - //if (::ith_has_section) - NtUnmapViewOfSection(NtCurrentProcess(), record[i].hookman_map); - //else - // delete[] record[i].hookman_map; + // //if (::ith_has_section) + // NtUnmapViewOfSection(NtCurrentProcess(), record[i].hookman_map); + // //else + // // delete[] record[i].hookman_map; - NtClose(record[i].process_handle); - NtClose(record[i].hookman_section); + // NtClose(record[i].process_handle); + // NtClose(record[i].hookman_section); - for (; i < MAX_REGISTER; i++) { - record[i] = record[i+1]; - text_pipes[i] = text_pipes[i+1]; - cmd_pipes[i] = cmd_pipes[i+1]; - recv_threads[i] = recv_threads[i+1]; - if (text_pipes[i] == 0) - break; - } - register_count--; - if (current_pid == pid) - current_pid = register_count ? record[0].pid_register : 0; + // for (; i < MAX_REGISTER; i++) { + // record[i] = record[i+1]; + // text_pipes[i] = text_pipes[i+1]; + // cmd_pipes[i] = cmd_pipes[i+1]; + // recv_threads[i] = recv_threads[i+1]; + // if (text_pipes[i] == 0) + // break; + // } + // register_count--; + // if (current_pid == pid) + // current_pid = register_count ? record[0].pid_register : 0; RemoveProcessContext(pid); - } - //pid_map->Clear(pid>>2); + //} + ////pid_map->Clear(pid>>2); - if (register_count == 1) - NtSetEvent(destroy_event, 0); + //if (register_count == 1) + // NtSetEvent(destroy_event, 0); //LeaveCriticalSection(&hmcs); //ConsoleOutput("vnrhost:UnRegisterProcess: unlock"); if (detach) @@ -469,43 +388,23 @@ void HookManager::DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD re //ConsoleOutput("vnrhost:DispatchText: lock"); //EnterCriticalSection(&hmcs); TextThread *it; - //`try { - if (TreeNode *in = Search(&tp)) { - DWORD number = in->data; - it = thread_table->FindThread(number); - } else if (IsFull()) { // jichi 1/16/2015: Skip adding threads when full - static bool once = true; // output only once - if (once) { - once = false; - DOUT("so many new threads, skip"); - } - return; - } else { // New thread - Insert(&tp, new_thread_number); - it = new TextThread(pid, hook, retn, spl, new_thread_number); - RegisterThread(it, new_thread_number); - DOUT("found new thread"); - char entstr[0x200]; - it->GetEntryString(entstr); - DOUT(entstr); - while (thread_table->FindThread(++new_thread_number)); - if (create) - create(it); - } - if (it) - it->AddText(text, len, false, space); // jichi 10/27/2013: new line is false - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:DispatchText: unlock"); - //} catch (...) { - // // ignored - //} + if (!(it = threadTable[tp])) + { + it = threadTable[tp] = new TextThread(pid, hook, retn, spl, threadTable.size()); + if (create) + { + create(it); + } + } + it->AddText(text, len, false, space); } void HookManager::AddConsoleOutput(LPCWSTR text) { - if (text) { - int len = wcslen(text) << 1; - TextThread *console = thread_table->FindThread(0); + if (text) + { + int len = wcslen(text) * 2; + TextThread *console = threadTable[{0, -1UL, -1UL, -1UL}]; //EnterCriticalSection(&hmcs); console->AddText((BYTE*)text,len,false,true); console->AddText((BYTE*)L"\r\n",4,false,true); @@ -513,25 +412,6 @@ void HookManager::AddConsoleOutput(LPCWSTR text) } } -void HookManager::ClearText(DWORD pid, DWORD hook, DWORD retn, DWORD spl) -{ - HM_LOCK; - //bool flag=false; - //ConsoleOutput("vnrhost:ClearText: lock"); - //EnterCriticalSection(&hmcs); - ThreadParameter tp = {pid, hook, retn, spl}; - if (TreeNode *in = Search(&tp)) - if (TextThread *it = thread_table->FindThread(in->data)) { - it->Reset(); - //SetCurrent(it); - if (reset) - reset(it); - //it->ResetEditText(); - } - - //LeaveCriticalSection(&hmcs); - //ConsoleOutput("vnrhost:ClearText: unlock"); -} void HookManager::ClearCurrent() { HM_LOCK; @@ -551,9 +431,10 @@ void HookManager::ResetRepeatStatus() HM_LOCK; //ConsoleOutput("vnrhost:ResetRepeatStatus: lock"); //EnterCriticalSection(&hmcs); - for (int i = 1; i < thread_table->Used(); i++) - if (TextThread *it = thread_table->FindThread(i)) - it->ResetRepeatStatus(); + for (auto i : threadTable) + { + i.second->ResetRepeatStatus(); + } //LeaveCriticalSection(&hmcs); //ConsoleOutput("vnrhost:ResetRepeatStatus: unlock"); @@ -576,23 +457,17 @@ ProcessRecord *HookManager::GetProcessRecord(DWORD pid) { HM_LOCK; //EnterCriticalSection(&hmcs); - for (int i = 0; i < MAX_REGISTER; i++) - if (record[i].pid_register == pid) - return record + i; - return nullptr; + return processRecordsByIds[pid]; //ProcessRecord *pr = i < MAX_REGISTER ? record + i : nullptr; //LeaveCriticalSection(&hmcs); //return pr; } -HANDLE HookManager::GetCmdHandleByPID(DWORD pid) +HANDLE HookManager::GetHostPipeByPID(DWORD pid) { HM_LOCK; //EnterCriticalSection(&hmcs); - for (int i = 0; i < MAX_REGISTER; i++) - if (record[i].pid_register == pid) - return cmd_pipes[i]; - return nullptr; + return processRecordsByIds[pid] ? processRecordsByIds[pid]->hostPipe : nullptr; //HANDLE h = i < MAX_REGISTER ? cmd_pipes[i] : 0; //LeaveCriticalSection(&hmcs); //return h; @@ -610,8 +485,6 @@ MK_BASIC_TYPE(LPVOID) // return hash; //} -HANDLE GetCmdHandleByPID(DWORD pid) { return ::man->GetCmdHandleByPID(pid); } - //void AddLink(WORD from, WORD to) { ::man->AddLink(from, to); } // jichi 9/27/2013: Unparse to hook parameters /H code @@ -749,7 +622,7 @@ void HookManager::AddThreadsToProfile(Profile& pf, const ProcessRecord& pr, DWOR if (tt == NULL || tt->GetThreadParameter()->pid != pid) continue; //if (tt->Status() & CURRENT_SELECT || tt->Link() || tt->GetComment()) - if (tt->Status() & CURRENT_SELECT || tt->Link()) + if (tt->Status() & CURRENT_SELECT) AddThreadToProfile(pf, pr, tt); } } @@ -769,12 +642,6 @@ DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* threa WORD iw = thread_profile_index & 0xFFFF; if (thread->Status() & CURRENT_SELECT) pf.SelectedIndex() = iw; - if (thread->Link()) - { - WORD to_index = AddThreadToProfile(pf, pr, thread->Link()) & 0xFFFF; - if (iw >= 0) - pf.AddLink(link_ptr(new LinkProfile(iw, to_index))); - } } return thread_profile_index; // in case more than one thread links to the same thread } diff --git a/vnr/texthook/host/hookman.h b/vnr/texthook/host/hookman.h index 5e5a388..36129a7 100644 --- a/vnr/texthook/host/hookman.h +++ b/vnr/texthook/host/hookman.h @@ -26,6 +26,7 @@ struct ProcessRecord { HANDLE hookman_mutex; HANDLE hookman_section; LPVOID hookman_map; + HANDLE hostPipe; }; class ThreadTable : public MyVector @@ -68,17 +69,14 @@ public: // jichi 10/27/2013: Add const; add space. void DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD retn, DWORD split, int len, bool space); - - void ClearText(DWORD pid, DWORD hook, DWORD retn, DWORD split); // private void RemoveProcessContext(DWORD pid); // private void RemoveSingleHook(DWORD pid, DWORD addr); void RegisterThread(TextThread*, DWORD); // private - void RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread); - void RegisterProcess(DWORD pid); + void RegisterProcess(DWORD pid, HANDLE hostPipe); void UnRegisterProcess(DWORD pid); //void SetName(DWORD); - HANDLE GetCmdHandleByPID(DWORD pid); + HANDLE GetHostPipeByPID(DWORD pid); ConsoleCallback RegisterConsoleCallback(ConsoleCallback cf) { return (ConsoleCallback)_InterlockedExchange((long*)&console,(long)cf); } diff --git a/vnr/texthook/host/host.cc b/vnr/texthook/host/host.cc index d947705..b663356 100644 --- a/vnr/texthook/host/host.cc +++ b/vnr/texthook/host/host.cc @@ -213,7 +213,7 @@ IHFSERVICE bool IHFAPI DetachProcessById(DWORD processId) { ITH_SYNC_HOOK; DWORD command = HOST_COMMAND_DETACH; - return WriteFile(man->GetCmdHandleByPID(processId), &command, sizeof(command), nullptr, nullptr); + return WriteFile(man->GetHostPipeByPID(processId), &command, sizeof(command), nullptr, nullptr); } IHFSERVICE void IHFAPI GetHostHookManager(HookManager** hookman) @@ -238,7 +238,7 @@ IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name) { ITH_SYNC_HOOK; - HANDLE hCmd = man->GetCmdHandleByPID(pid); + HANDLE hCmd = man->GetHostPipeByPID(pid); if (hCmd == 0) return -1; @@ -269,7 +269,7 @@ IHFSERVICE DWORD IHFAPI Host_RemoveHook(DWORD pid, DWORD addr) ITH_SYNC_HOOK; HANDLE hRemoved,hCmd; - hCmd = GetCmdHandleByPID(pid); + hCmd = man->GetHostPipeByPID(pid); if (hCmd == 0) return -1; hRemoved = CreateEventW(nullptr, TRUE, FALSE, ITH_REMOVEHOOK_EVENT); diff --git a/vnr/texthook/host/host_p.h b/vnr/texthook/host/host_p.h index 1c16159..896497c 100644 --- a/vnr/texthook/host/host_p.h +++ b/vnr/texthook/host/host_p.h @@ -36,7 +36,7 @@ DWORD WINAPI CmdThread(LPVOID lpThreadParameter); DWORD GetCurrentPID(); //DWORD GetProcessIDByPath(LPWSTR str); -HANDLE GetCmdHandleByPID(DWORD pid); +HANDLE GetHostPipeByPID(DWORD pid); //DWORD Inject(HANDLE hProc); //DWORD InjectByPID(DWORD pid); //DWORD PIDByName(LPWSTR target); diff --git a/vnr/texthook/host/pipe.cc b/vnr/texthook/host/pipe.cc index d2f5d8e..9204dab 100644 --- a/vnr/texthook/host/pipe.cc +++ b/vnr/texthook/host/pipe.cc @@ -74,20 +74,26 @@ CRITICAL_SECTION detachCs; // jichi 9/27/2013: also used in main //HANDLE hDetachEvent; extern HANDLE pipeExistsEvent; +struct Pipes +{ + HANDLE hookPipe; + HANDLE hostPipe; +}; + void CreateNewPipe() { - HANDLE hookPipe, hostPipe, TextReceivingThread; - - hookPipe = CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL); - hostPipe = CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL); - TextReceivingThread = CreateThread(nullptr, 0, TextReceiver, hookPipe, 0, nullptr); - man->RegisterPipe(hookPipe, hostPipe, TextReceivingThread); + CreateThread(nullptr, 0, TextReceiver, new Pipes + { + CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL), + CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL) + }, + 0, nullptr); } DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) { - HANDLE hookPipe = (HANDLE)lpThreadParameter; - ConnectNamedPipe(hookPipe, nullptr); + Pipes* pipes = (Pipes*)lpThreadParameter; + ConnectNamedPipe(pipes->hookPipe, nullptr); BYTE* buffer = new BYTE[PIPE_BUFFER_SIZE]; DWORD bytesRead, processId; @@ -98,8 +104,8 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) // return 0; //} - ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr); - man->RegisterProcess(processId); + ReadFile(pipes->hookPipe, &processId, sizeof(processId), &bytesRead, nullptr); + man->RegisterProcess(processId, pipes->hostPipe); // jichi 9/27/2013: why recursion? // Artikash 5/20/2018: To create a new pipe for another process @@ -107,7 +113,7 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) while (::running) { - if (!ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) + if (!ReadFile(pipes->hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) { break; } @@ -161,12 +167,13 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) EnterCriticalSection(&detachCs); - DisconnectNamedPipe(hookPipe); - DisconnectNamedPipe(man->GetCmdHandleByPID(processId)); + DisconnectNamedPipe(pipes->hookPipe); + DisconnectNamedPipe(pipes->hostPipe); man->UnRegisterProcess(processId); LeaveCriticalSection(&detachCs); delete[] buffer; + delete pipes; return 0; } diff --git a/vnr/texthook/host/textthread.h b/vnr/texthook/host/textthread.h index ef4c2ee..a2160bb 100644 --- a/vnr/texthook/host/textthread.h +++ b/vnr/texthook/host/textthread.h @@ -48,7 +48,6 @@ public: //virtual void SetComment(LPWSTR); //virtual void ExportTextToFile(LPWSTR filename); - virtual bool CheckCycle(TextThread *start); virtual DWORD GetThreadString(LPSTR str, DWORD max); virtual DWORD GetEntryString(LPSTR str, DWORD max = 0x200);