refactor and start using pipe instead of section to get hook info

This commit is contained in:
Akash Mozumdar 2018-07-17 19:18:36 -04:00
parent ae6656441b
commit ffbb081bcc
13 changed files with 86 additions and 116 deletions

View File

@ -363,23 +363,8 @@ bool GetHookParam(DWORD pid, DWORD hook_addr, HookParam& hp)
{
if (!pid)
return false;
ProcessRecord *pr = ::man->GetProcessRecord(pid);
if (!pr)
return false;
bool result = false;
WaitForSingleObject(pr->hookman_mutex, 0);
const Hook *hks = (Hook *)pr->hookman_map;
for (int i = 0; i < MAX_HOOK; i++)
{
if (hks[i].Address() == hook_addr)
{
hp = hks[i].hp;
result = true;
break;
}
}
ReleaseMutex(pr->hookman_mutex);
return result;
hp = man->GetHook(pid, hook_addr).hp;
return true;
}
std::wstring GetEntryString(TextThread& thread)
@ -506,7 +491,7 @@ bool IsUnicodeHook(const ProcessRecord& pr, DWORD hook)
{
bool res = false;
WaitForSingleObject(pr.hookman_mutex, 0);
auto hooks = (const Hook*)pr.hookman_map;
auto hooks = (const OldHook*)pr.hookman_map;
for (DWORD i = 0; i < MAX_HOOK; i++)
{
if (hooks[i].Address() == hook)

View File

@ -257,7 +257,7 @@ std::wstring GetHookNameByAddress(const ProcessRecord& pr, DWORD hook_address)
{
std::wstring hook_name;
WaitForSingleObject(pr.hookman_mutex, 0);
auto hooks = (const Hook*)pr.hookman_map;
auto hooks = (const OldHook*)pr.hookman_map;
for (int i = 0; i < MAX_HOOK; ++i)
{
auto& hook = hooks[i];

View File

@ -29,10 +29,10 @@ HookManager::HookManager() :
detach(nullptr),
hook(nullptr),
new_thread_number(0),
threadTable(),
textThreadsByParams(),
processRecordsByIds()
{
TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++, splitDelay);
TextThread* consoleTextThread = textThreadsByParams[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++, splitDelay);
consoleTextThread->Status() |= USING_UNICODE;
SetCurrent(consoleTextThread);
@ -46,7 +46,7 @@ HookManager::~HookManager()
TextThread *HookManager::FindSingle(DWORD number)
{
for (auto i : threadTable)
for (auto i : textThreadsByParams)
{
if (i.second->Number() == number)
{
@ -77,7 +77,7 @@ void HookManager::RemoveSingleHook(DWORD pid, DWORD addr)
{
HM_LOCK;
std::vector<ThreadParameter> removedThreads;
for (auto i : threadTable)
for (auto i : textThreadsByParams)
{
if (i.second->PID() == pid && i.second->Addr() == addr)
{
@ -91,7 +91,7 @@ void HookManager::RemoveSingleHook(DWORD pid, DWORD addr)
}
for (auto i : removedThreads)
{
threadTable.erase(i);
textThreadsByParams.erase(i);
}
SelectCurrent(0);
}
@ -100,7 +100,7 @@ void HookManager::RemoveProcessContext(DWORD pid)
{
HM_LOCK;
std::vector<ThreadParameter> removedThreads;
for (auto i : threadTable)
for (auto i : textThreadsByParams)
{
if (i.second->PID() == pid)
{
@ -114,7 +114,7 @@ void HookManager::RemoveProcessContext(DWORD pid)
}
for (auto i : removedThreads)
{
threadTable.erase(i);
textThreadsByParams.erase(i);
}
SelectCurrent(0);
}
@ -159,9 +159,9 @@ void HookManager::DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD re
HM_LOCK;
ThreadParameter tp = {pid, hook, retn, spl};
TextThread *it;
if (!(it = threadTable[tp]))
if (!(it = textThreadsByParams[tp]))
{
it = threadTable[tp] = new TextThread(tp, new_thread_number++, splitDelay);
it = textThreadsByParams[tp] = new TextThread(tp, new_thread_number++, splitDelay);
if (create)
{
create(it);
@ -175,7 +175,7 @@ void HookManager::AddConsoleOutput(LPCWSTR text)
if (text)
{
int len = wcslen(text) * 2;
TextThread *console = threadTable[{0, -1UL, -1UL, -1UL}];
TextThread *console = textThreadsByParams[{0, -1UL, -1UL, -1UL}];
console->AddSentence(std::wstring(text));
}
}
@ -202,6 +202,18 @@ HANDLE HookManager::GetHostPipe(DWORD pid)
return processRecordsByIds[pid] ? processRecordsByIds[pid]->hostPipe : nullptr;
}
Hook HookManager::GetHook(DWORD processId, DWORD addr)
{
HM_LOCK;
return hooksByAddresses[{ processId, addr, 0, 0}];
}
void HookManager::SetHook(DWORD processId, DWORD addr, Hook hook)
{
HM_LOCK;
hooksByAddresses[{ processId, addr, 0, 0}] = hook;
}
void AddHooksToProfile(Profile& pf, const ProcessRecord& pr);
DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread);
void MakeHookRelative(const ProcessRecord& pr, HookParam& hp);
@ -220,7 +232,7 @@ void HookManager::GetProfile(DWORD pid, pugi::xml_node profile_node)
void AddHooksToProfile(Profile& pf, const ProcessRecord& pr)
{
WaitForSingleObject(pr.hookman_mutex, 0);
auto hooks = (const Hook*)pr.hookman_map;
auto hooks = (const OldHook*)pr.hookman_map;
for (DWORD i = 0; i < MAX_HOOK; ++i)
{
if (hooks[i].Address() == 0)

View File

@ -8,6 +8,8 @@
#include "host/textthread.h"
#include "winmutex/winmutex.h"
#include <unordered_map>
#include <string>
#include "vnrhook/include/types.h"
namespace pugi {
class xml_node;
@ -23,7 +25,12 @@ struct ProcessRecord {
HANDLE hookman_section;
LPVOID hookman_map;
HANDLE hostPipe;
//std::unordered_map<DWORD, Hook> hooksByAddress;
};
struct Hook
{
HookParam hp;
std::wstring name;
};
typedef DWORD (*ProcessEventCallback)(DWORD pid);
@ -41,11 +48,10 @@ class DLLEXPORT HookManager
public:
HookManager();
~HookManager();
// jichi 12/26/2013: remove virtual modifiers
TextThread *FindSingle(DWORD number);
ProcessRecord *GetProcessRecord(DWORD pid);
//void LockHookman();
//void UnlockHookman();
Hook GetHook(DWORD processId, DWORD addr);
void SetHook(DWORD processId, DWORD addr, Hook hook);
void ClearCurrent();
void SelectCurrent(DWORD num);
void SetCurrent(TextThread *it);
@ -85,7 +91,8 @@ public:
void GetProfile(DWORD pid, pugi::xml_node profile_node);
private:
std::unordered_map<ThreadParameter, TextThread*, ThreadParameterHasher> threadTable;
std::unordered_map<ThreadParameter, TextThread*, ThreadParameterHasher> textThreadsByParams;
std::unordered_map<ThreadParameter, Hook, ThreadParameterHasher> hooksByAddresses; // Artikash 7/17/2018: retn and spl should always be zero when accessing this!
std::unordered_map<DWORD, ProcessRecord*> processRecordsByIds;
CRITICAL_SECTION hmcs;

View File

@ -68,7 +68,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
DLLEXPORT bool StartHost()
{
preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX);
if (GetLastError() == ERROR_ALREADY_EXISTS || ::running)
{
@ -101,7 +100,6 @@ DLLEXPORT void CloseHost()
DLLEXPORT bool InjectProcessById(DWORD processId, DWORD timeout)
{
if (processId == GetCurrentProcessId())
{
return false;
@ -158,11 +156,11 @@ DLLEXPORT DWORD InsertHook(DWORD pid, const HookParam *hp, std::string name)
BYTE buffer[PIPE_BUFFER_SIZE] = {};
*(DWORD*)buffer = HOST_COMMAND_NEW_HOOK;
memcpy(buffer + 4, hp, sizeof(HookParam));
if (name.size()) strcpy((char*)buffer + 4 + sizeof(HookParam), name.c_str());
*(HookParam*)(buffer + sizeof(DWORD)) = *hp;
if (name.size()) strcpy((char*)buffer + sizeof(DWORD) + sizeof(HookParam), name.c_str());
DWORD unused;
WriteFile(commandPipe, buffer, 4 + sizeof(HookParam) + name.size(), &unused, nullptr);
WriteFile(commandPipe, buffer, sizeof(DWORD) + sizeof(HookParam) + name.size(), &unused, nullptr);
return 0;
}
@ -173,12 +171,12 @@ DLLEXPORT DWORD RemoveHook(DWORD pid, DWORD addr)
return -1;
HANDLE hookRemovalEvent = CreateEventW(nullptr, TRUE, FALSE, ITH_REMOVEHOOK_EVENT);
BYTE buffer[8];
BYTE buffer[sizeof(DWORD) * 2] = {};
*(DWORD*)buffer = HOST_COMMAND_REMOVE_HOOK;
*(DWORD*)(buffer + 4) = addr;
*(DWORD*)(buffer + sizeof(DWORD)) = addr;
DWORD unused;
WriteFile(commandPipe, buffer, 8, &unused, nullptr);
WriteFile(commandPipe, buffer, sizeof(DWORD) * 2, &unused, nullptr);
WaitForSingleObject(hookRemovalEvent, 1000);
CloseHandle(hookRemovalEvent);
man->RemoveSingleHook(pid, addr);

View File

@ -61,32 +61,37 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
if (*(DWORD*)buffer == HOST_NOTIFICATION)
{
USES_CONVERSION;
switch (*(DWORD*)(buffer + 4)) // Artikash 7/17/2018: Notification type
{
case HOST_NOTIFICATION_NEWHOOK:
man->SetHook(processId,
((HookParam*)(buffer + sizeof(DWORD) * 2))->address,
{
break;
*(HookParam*)(buffer + sizeof(DWORD) * 2), // Hook address
std::wstring(A2W(
(const char*)buffer + sizeof(DWORD) * 2 + sizeof(HookParam) // Hook name
))
}
);
break;
case HOST_NOTIFICATION_TEXT:
USES_CONVERSION;
man->AddConsoleOutput(A2W((LPCSTR)(buffer + 8)));
man->AddConsoleOutput(A2W((LPCSTR)(buffer + sizeof(DWORD) * 2))); // Text
break;
}
}
else
{
DWORD hook = *(DWORD*)buffer;
DWORD retn = *(DWORD*)(buffer + 4);
DWORD split = *(DWORD*)(buffer + 8);
// jichi 9/28/2013: Debug raw data
//ITH_DEBUG_DWORD9(RecvLen - 0xc,
// buffer[0xc], buffer[0xd], buffer[0xe], buffer[0xf],
// buffer[0x10], buffer[0x11], buffer[0x12], buffer[0x13]);
const BYTE *data = buffer + HEADER_SIZE; // th
int dataLength = bytesRead - HEADER_SIZE;
man->DispatchText(processId, data, hook, retn, split, dataLength);
man->DispatchText(processId, buffer + HEADER_SIZE,
*(DWORD*)buffer, // Hook address
*(DWORD*)(buffer + sizeof(DWORD)), // Return address
*(DWORD*)(buffer + sizeof(DWORD) * 2), // Split
bytesRead - HEADER_SIZE
);
}
}

View File

@ -39,7 +39,7 @@ DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max)
if (!pr)
return 0;
WaitForSingleObject(pr->hookman_mutex, 0);
const Hook *hks = (const Hook *)pr->hookman_map;
const OldHook *hks = (const OldHook *)pr->hookman_map;
for (int i = 0; i < MAX_HOOK; i++)
if (hks[i].Address() == hook_addr) {
len = hks[i].NameLength();

View File

@ -253,7 +253,7 @@ enum {
// - 0x0 dwAddr hook address
// - 0x4 dwRetn return address
// - 0x8 dwSplit split value
#define HEADER_SIZE 0xc
#define HEADER_SIZE sizeof(DWORD) * 3
#define TIMEOUT 5000 // 5 seconds

View File

@ -74,7 +74,7 @@ struct SendParam {
HookParam hp;
};
struct Hook { // size: 0x80
struct OldHook { // size: 0x80
HookParam hp;
LPSTR hook_name;
int name_length;

View File

@ -339,8 +339,6 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
BYTE *pbData,
pbSmallBuff[SMALL_BUFF_SIZE];
DWORD dwType = hp.type;
if (!::live) // the pipe thread is busy
return 0;
//if ((dwType & NO_CONTEXT) == 0 && HookFilter(dwRetn))
// return 0;
@ -730,26 +728,6 @@ int TextHook::ClearHook()
return err;
}
int TextHook::ModifyHook(const HookParam &hp)
{
//WCHAR name[0x40];
DWORD len = 0;
if (hook_name)
len = ::strlen(hook_name);
LPSTR name = 0;
if (len) {
name = new char[len + 1];
//ITH_MEMSET_HEAP(name, 0, sizeof(wchar_t) * (len + 1)); // jichi 9/26/2013: zero memory
strcpy(name, hook_name);
}
ClearHook();
InitHook(hp, name);
InsertHook();
if (name)
delete[] name;
return 0;
}
int TextHook::RecoverHook()
{
if (hp.address) {

View File

@ -26,7 +26,7 @@ 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
class TextHook : public OldHook
{
int UnsafeInsertHookCode();
DWORD UnsafeSend(DWORD dwDataBase, DWORD dwRetn);
@ -40,7 +40,6 @@ public:
int RecoverHook();
int RemoveHook();
int ClearHook();
int ModifyHook(const HookParam&);
int SetHookName(LPCSTR name);
int GetLength(DWORD base, DWORD in); // jichi 12/25/2013: Return 0 if failed
void CoolDown(); // jichi 9/28/2013: flush instruction cache on wine

View File

@ -41,8 +41,7 @@ FilterRange *filter = _filter;
WCHAR hm_section[0x100];
HANDLE hSection;
bool running,
live = false;
bool running;
int currentHook = 0,
user_hook_count = 0;
DWORD trigger = 0;
@ -121,7 +120,6 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID unused)
// jichi 10/2/2103: Cannot use __try in functions that require object unwinding
//ITH_TRY {
::running = false;
::live = false;
Engine::terminate();

View File

@ -56,13 +56,11 @@ DWORD WINAPI PipeManager(LPVOID unused)
ReleaseMutex(pipeAcquisitionMutex);
CloseHandle(pipeAcquisitionMutex);
::live = true;
Engine::hijack();
ConsoleOutput("vnrcli:WaitForPipe: pipe connected");
while (::running)
{
Sleep(STANDARD_WAIT);
if (!ReadFile(hostPipe, buffer, PIPE_BUFFER_SIZE / 2, &count, nullptr)) // Artikash 5/21/2018: why / 2? wchar_t?
{
break;
@ -72,18 +70,20 @@ DWORD WINAPI PipeManager(LPVOID unused)
{
case HOST_COMMAND_NEW_HOOK:
buffer[count] = 0;
NewHook(*(HookParam *)(buffer + 4), (LPSTR)(buffer + 4 + sizeof(HookParam)), 0);
NewHook(*(HookParam *)(buffer + sizeof(DWORD)), // Hook parameter
(LPSTR)(buffer + 4 + sizeof(HookParam)), // Hook name
0
);
break;
case HOST_COMMAND_REMOVE_HOOK:
{
DWORD removalAddress = *(DWORD *)(buffer + 4);
HANDLE hookRemovalEvent = OpenEventW(SYNCHRONIZE | EVENT_MODIFY_STATE, FALSE, ITH_REMOVEHOOK_EVENT);
TextHook *in = hookman;
for (int i = 0; i < currentHook; in++)
{
if (in->Address()) i++;
if (in->Address() == removalAddress)
if (in->Address() == *(DWORD *)(buffer + sizeof(DWORD))) // Hook address
{
break;
}
@ -102,8 +102,9 @@ DWORD WINAPI PipeManager(LPVOID unused)
break;
}
}
CloseHandle(::hookPipe);
CloseHandle(hostPipe);
::live = false;
for (int i = 0, count = 0; count < ::currentHook; i++)
{
if (hookman[i].RemoveHook())
@ -111,44 +112,31 @@ DWORD WINAPI PipeManager(LPVOID unused)
count++;
}
}
CloseHandle(::hookPipe);
CloseHandle(hostPipe);
}
FreeLibraryAndExitThread(::currentModule, 0);
return 0;
}
void ConsoleOutput(LPCSTR text)
{ // jichi 12/25/2013: Rewrite the implementation
if (!::live)
{
return;
}
DWORD textSize = strlen(text) + 1;
DWORD dataSize = textSize + 8;
BYTE *buffer = new BYTE[dataSize];
*(DWORD*)buffer = HOST_NOTIFICATION; //cmd
*(DWORD*)(buffer + 4) = HOST_NOTIFICATION_TEXT; //console
memcpy(buffer + 8, text, textSize);
DWORD unused;
WriteFile(::hookPipe, buffer, dataSize, &unused, nullptr);
}
// Artikash 7/3/2018: TODO: Finish using this in vnrhost instead of section to deliver hook name
void NotifyHookInsert(HookParam hp, LPCSTR name)
{
if (!::live)
{
return;
}
BYTE buffer[PIPE_BUFFER_SIZE];
*(DWORD*)buffer = HOST_NOTIFICATION;
*(DWORD*)(buffer + 4) = HOST_NOTIFICATION_NEWHOOK;
*(HookParam*)(buffer + 8) = hp;
strcpy((char*)buffer + 8 + sizeof(HookParam), name);
*(DWORD*)(buffer + sizeof(DWORD)) = HOST_NOTIFICATION_TEXT;
strcpy((char*)buffer + sizeof(DWORD) * 2, text);
DWORD unused;
WriteFile(::hookPipe, buffer, strlen(name) + 8 + sizeof(HookParam), &unused, nullptr);
WriteFile(::hookPipe, buffer, strlen(text) + sizeof(DWORD) * 2, &unused, nullptr);
}
// Artikash 7/3/2018: TODO: Finish using this in vnrhost instead of section to deliver hook info
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;
}