finish rewriting hookman, still some cleanup to do

This commit is contained in:
Akash Mozumdar 2018-06-01 02:36:51 -04:00
parent aaf33094d1
commit fb56457cdb
6 changed files with 97 additions and 226 deletions

View File

@ -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<ThreadParameter *,DWORD> *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 (!(it = threadTable[tp]))
{
it = threadTable[tp] = new TextThread(pid, hook, retn, spl, threadTable.size());
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
//}
}
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<ThreadParameter *, DWORD> *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
}

View File

@ -26,6 +26,7 @@ struct ProcessRecord {
HANDLE hookman_mutex;
HANDLE hookman_section;
LPVOID hookman_map;
HANDLE hostPipe;
};
class ThreadTable : public MyVector<TextThread *, 0x40>
@ -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); }

View File

@ -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);

View File

@ -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);

View File

@ -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;
}

View File

@ -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);