refactor and start using pipe instead of section to get hook info
This commit is contained in:
parent
ae6656441b
commit
ffbb081bcc
@ -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)
|
||||
|
@ -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];
|
||||
|
@ -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)
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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,
|
||||
{
|
||||
*(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
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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
|
||||
|
||||
|
@ -74,7 +74,7 @@ struct SendParam {
|
||||
HookParam hp;
|
||||
};
|
||||
|
||||
struct Hook { // size: 0x80
|
||||
struct OldHook { // size: 0x80
|
||||
HookParam hp;
|
||||
LPSTR hook_name;
|
||||
int name_length;
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
|
@ -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();
|
||||
|
||||
|
@ -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);
|
||||
{
|
||||
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, dataSize, &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 name
|
||||
// Artikash 7/3/2018: TODO: Finish using this in vnrhost instead of section to deliver hook info
|
||||
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_NEWHOOK;
|
||||
*(HookParam*)(buffer + sizeof(DWORD) * 2) = hp;
|
||||
strcpy((char*)buffer + sizeof(DWORD) * 2 + sizeof(HookParam), name);
|
||||
DWORD unused;
|
||||
WriteFile(::hookPipe, buffer, strlen(name) + 8 + sizeof(HookParam), &unused, nullptr);
|
||||
WriteFile(::hookPipe, buffer, strlen(name) + sizeof(DWORD) * 2 + sizeof(HookParam), &unused, nullptr);
|
||||
return;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user