cleaning things up

This commit is contained in:
Akash Mozumdar 2018-05-20 13:11:55 -04:00
parent c7a79e6064
commit 290ef57490
12 changed files with 269 additions and 303 deletions

View File

@ -129,7 +129,7 @@ size_t IthGetCurrentModulePath(wchar_t *buf, size_t len)
HANDLE hHeap; // used in ith/common/memory.h
#endif // ITH_HAS_HEAP
DWORD current_process_id;
DWORD currentProcessId;
DWORD debug;
BYTE launch_time[0x10];
LPVOID page;
@ -238,7 +238,7 @@ public:
AcquireLock();
DWORD pid,addr,len;
if (hProc == NtCurrentProcess())
pid = ::current_process_id;
pid = ::currentProcessId;
else {
PROCESS_BASIC_INFORMATION info;
NtQueryInformationProcess(hProc, ProcessBasicInformation, &info, sizeof(info), &len);
@ -287,7 +287,7 @@ public:
DWORD pid,addr,len;
AcquireLock();
if (hProc==NtCurrentProcess())
pid = ::current_process_id;
pid = ::currentProcessId;
else {
PROCESS_BASIC_INFORMATION info;
NtQueryInformationProcess(hProc,ProcessBasicInformation,&info,sizeof(info),&len);
@ -733,7 +733,7 @@ BOOL IthInitSystemService()
mov ecx,[eax+0x20]
mov eax,[eax+0x30]
mov peb,eax
mov current_process_id,ecx
mov currentProcessId,ecx
}
debug = peb->BeingDebugged;
LowFragmentHeap = 2;

View File

@ -63,7 +63,7 @@ void CheckThreadStart();
extern HANDLE hHeap; // used in ith/common/memory.h
#endif // ITH_HAS_HEAP
extern DWORD current_process_id;
extern DWORD currentProcessId;
extern DWORD debug;
extern BYTE LeadByteTable[];
extern LPVOID page;

View File

@ -485,7 +485,7 @@ void HookManager::RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread)
else
NtClearEvent(destroy_event);
}
void HookManager::RegisterProcess(DWORD pid, DWORD hookman, DWORD module)
void HookManager::RegisterProcess(DWORD pid)
{
HM_LOCK;
wchar_t str[0x40],
@ -494,8 +494,6 @@ void HookManager::RegisterProcess(DWORD pid, DWORD hookman, DWORD module)
//ConsoleOutput("vnrhost:RegisterProcess: lock");
//EnterCriticalSection(&hmcs);
record[register_count - 1].pid_register = pid;
record[register_count - 1].hookman_register = hookman;
record[register_count - 1].module_register = module;
//record[register_count - 1].engine_register = engine;
swprintf(str, ITH_SECTION_ L"%d", pid);
HANDLE hSection = IthCreateSection(str, HOOK_SECTION_SIZE, PAGE_READONLY);

View File

@ -71,7 +71,7 @@ public:
void RemoveSingleHook(DWORD pid, DWORD addr);
void RegisterThread(TextThread*, DWORD); // private
void RegisterPipe(HANDLE text, HANDLE cmd, HANDLE thread);
void RegisterProcess(DWORD pid, DWORD hookman, DWORD module);
void RegisterProcess(DWORD pid);
void UnRegisterProcess(DWORD pid);
//void SetName(DWORD);

View File

@ -56,9 +56,9 @@ namespace
{ // unnamed
void GetDebugPrivileges()
{
{ // Artikash 5/19/2018: Is it just me or is this function 100% superfluous?
HANDLE processToken;
TOKEN_PRIVILEGES Privileges = { 1, {0x14, 0, SE_PRIVILEGE_ENABLED} };
TOKEN_PRIVILEGES Privileges = {1, {0x14, 0, SE_PRIVILEGE_ENABLED}};
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken);
AdjustTokenPrivileges(processToken, FALSE, &Privileges, 0, nullptr, nullptr);
@ -79,7 +79,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
IthInitSystemService();
GetDebugPrivileges();
// jichi 12/20/2013: Since I already have a GUI, I don't have to InitCommonControls()
//Used by timers.
// Used by timers.
InitCommonControls();
// jichi 8/24/2013: Create hidden window so that ITH can access timer and events
dummyWindow = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0);
@ -133,7 +133,6 @@ IHFSERVICE bool IHFAPI OpenHost()
IHFSERVICE void IHFAPI StartHost()
{
CreateNewPipe();
::pipeExistsEvent = CreateEventW(nullptr, TRUE, TRUE, ITH_PIPEEXISTS_EVENT);
}
IHFSERVICE void IHFAPI CloseHost()
@ -142,12 +141,10 @@ IHFSERVICE void IHFAPI CloseHost()
if (::running)
{
::running = FALSE;
ResetEvent(::pipeExistsEvent);
delete man;
delete settings;
CloseHandle(::hookMutex);
CloseHandle(preventDuplicationMutex);
CloseHandle(::pipeExistsEvent);
DeleteCriticalSection(&detachCs);
}
LeaveCriticalSection(&::hostCs);
@ -169,7 +166,7 @@ IHFSERVICE bool IHFAPI InjectProcessById(DWORD processId, DWORD timeout)
success = false;
}
HMODULE textHooker = LoadLibraryExW(L"vnrhook", nullptr, DONT_RESOLVE_DLL_REFERENCES);
HMODULE textHooker = LoadLibraryExW(ITH_DLL, nullptr, DONT_RESOLVE_DLL_REFERENCES);
if (textHooker == nullptr)
{
success = false;
@ -184,7 +181,7 @@ IHFSERVICE bool IHFAPI InjectProcessById(DWORD processId, DWORD timeout)
success = false;
}
void* loadLibraryStartRoutine = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW");
LPTHREAD_START_ROUTINE loadLibraryStartRoutine = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW");
if (success)
{
@ -192,7 +189,7 @@ IHFSERVICE bool IHFAPI InjectProcessById(DWORD processId, DWORD timeout)
{
if (WriteProcessMemory(processHandle, remoteData, textHookerPath, textHookerPathSize, nullptr))
{
if (HANDLE thread = CreateRemoteThread(processHandle, nullptr, 0, (LPTHREAD_START_ROUTINE)loadLibraryStartRoutine, remoteData, 0, nullptr))
if (HANDLE thread = CreateRemoteThread(processHandle, nullptr, 0, loadLibraryStartRoutine, remoteData, 0, nullptr))
{
WaitForSingleObject(thread, timeout);
CloseHandle(thread);
@ -247,7 +244,7 @@ IHFSERVICE void IHFAPI GetHostSettings(Settings **p)
}
}
// I don't understand the following operations, so I'm making minimal changes in cleanup -Artikash 11 May 2018
// Artikash 5/11/2018: I don't understand the following operations, so I'm making minimal changes in cleanup
IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name)
{

View File

@ -31,7 +31,7 @@ GLOBAL DWORD split_time,
global_filter;
GLOBAL CRITICAL_SECTION detachCs;
DWORD WINAPI RecvThread(LPVOID lpThreadParameter);
DWORD WINAPI TextReceiver(LPVOID lpThreadParameter);
DWORD WINAPI CmdThread(LPVOID lpThreadParameter);
DWORD GetCurrentPID();

View File

@ -9,6 +9,8 @@
#include "vnrhook/include/const.h"
#include "ithsys/ithsys.h"
#include <stdio.h>
#include "growl.h"
#include <atlbase.h>
//#include "CommandQueue.h"
//#include <QtCore/QDebug>
@ -17,57 +19,57 @@
//DWORD WINAPI UpdateWindows(LPVOID lpThreadParameter);
namespace { // unnamed
enum NamedPipeCommand {
NAMED_PIPE_DISCONNECT = 1
, NAMED_PIPE_CONNECT = 2
};
namespace
{ // unnamed
bool newline = false;
bool detach = false;
// jichi 10/27/2013
// Check if text has leading space
enum { FILTER_LIMIT = 0x20 }; // The same as the orignal ITH filter. So, I don't have to check \u3000
//enum { FILTER_LIMIT = 0x19 };
inline bool HasLeadingSpace(const BYTE *text, int len)
{
return len == 1 ? *text <= FILTER_LIMIT : // 1 byte
*(WORD*)text <= FILTER_LIMIT; // 2 bytes
}
// jichi 10/27/2013
// Check if text has leading space
enum { _filter_limit = 0x20 }; // The same as the orignal ITH filter. So, I don't have to check \u3000
//enum { _filter_limit = 0x19 };
inline bool has_leading_space(const BYTE *text, int len)
{
return len == 1 ? *text <= _filter_limit : // 1 byte
*reinterpret_cast<const WORD *>(text) <= _filter_limit; // 2 bytes
}
// jichi 9/28/2013: Skip leading garbage
// Note:
// - Modifying limit will break manual translation. The orignal one is 0x20
// - Eliminating 0x20 will break English-translated games
const BYTE *Filter(const BYTE *str, int len)
{
// jichi 9/28/2013: Skip leading garbage
// Note:
// - Modifying limit will break manual translation. The orignal one is 0x20
// - Eliminating 0x20 will break English-translated games
const BYTE* Filter(const BYTE *str, int len)
{
#ifdef ITH_DISABLE_FILTER // jichi 9/28/2013: only for debugging purpose
return str;
#endif // ITH_DISABLE_FILTER
// if (len && *str == 0x10) // jichi 9/28/2013: garbage on wine, data link escape, or ^P
// return nullptr;
//enum { limit = 0x19 };
while (true)
if (len >= 2) {
if (*(const WORD *)str <= _filter_limit) { // jichi 10/27/2013: two bytes
str += 2;
len -= 2;
} else
break;
} else if (*str <= _filter_limit) { // jichi 10/27/2013: 1 byte
str++;
len--;
} else
break;
return str;
}
} // unnamed namespace
return str;
#endif
while (true)
{
if (len >= 2)
{
if (*(WORD*)str <= FILTER_LIMIT)
{ // jichi 10/27/2013: two bytes
str += 2;
len -= 2;
}
else
{
break;
}
//WCHAR recv_pipe[] = L"\\??\\pipe\\ITH_PIPE";
//WCHAR command_pipe[] = L"\\??\\pipe\\ITH_COMMAND";
wchar_t recv_pipe[] = ITH_TEXT_PIPE;
wchar_t command_pipe[] = ITH_COMMAND_PIPE;
}
else if (*str <= FILTER_LIMIT)
{ // jichi 10/27/2013: 1 byte
str++;
len--;
}
else
{
break;
}
}
return str;
}
} // unnamed namespace
CRITICAL_SECTION detachCs; // jichi 9/27/2013: also used in main
//HANDLE hDetachEvent;
@ -75,204 +77,106 @@ extern HANDLE pipeExistsEvent;
void CreateNewPipe()
{
HANDLE hTextPipe, hCmdPipe, hThread;
HANDLE hookPipe, hostPipe, TextReceivingThread;
hTextPipe = CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 0x1000, 0x1000, MAXDWORD, NULL);
hCmdPipe = CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, 0x1000, 0x1000, MAXDWORD, NULL);
hThread = CreateThread(nullptr, 0, RecvThread, hTextPipe, 0, nullptr);
man->RegisterPipe(hTextPipe, hCmdPipe, hThread);
hookPipe = CreateNamedPipeW(ITH_TEXT_PIPE, PIPE_ACCESS_INBOUND, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE, PIPE_UNLIMITED_INSTANCES, 0x1000, 0x1000, MAXDWORD, NULL);
hostPipe = CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, 0x1000, 0x1000, MAXDWORD, NULL);
TextReceivingThread = CreateThread(nullptr, 0, TextReceiver, hookPipe, 0, nullptr);
man->RegisterPipe(hookPipe, hostPipe, TextReceivingThread);
}
void DetachFromProcess(DWORD pid)
DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
{
HANDLE hMutex = INVALID_HANDLE_VALUE,
hEvent = INVALID_HANDLE_VALUE;
//try {
IO_STATUS_BLOCK ios;
ProcessRecord *pr = man->GetProcessRecord(pid);
if (!pr)
return;
//IthBreak();
hEvent = IthCreateEvent(nullptr);
if (STATUS_PENDING == NtFsControlFile(
man->GetCmdHandleByPID(pid),
hEvent,
0,0,
&ios,
CTL_CODE(FILE_DEVICE_NAMED_PIPE, NAMED_PIPE_DISCONNECT, 0, 0),
0,0,0,0))
NtWaitForSingleObject(hEvent, 0, 0);
NtClose(hEvent);
//hEvent = INVALID_HANDLE_VALUE;
HANDLE hookPipe = (HANDLE)lpThreadParameter;
ConnectNamedPipe(hookPipe, nullptr);
WCHAR mutex[0x20];
swprintf(mutex, ITH_DETACH_MUTEX_ L"%d", pid);
hMutex = IthOpenMutex(mutex);
if (hMutex != INVALID_HANDLE_VALUE) {
NtWaitForSingleObject(hMutex, 0, 0);
NtReleaseMutant(hMutex, 0);
NtClose(hMutex);
//hMutex = INVALID_HANDLE_VALUE;
}
enum { PIPE_BUFFER_SIZE = 0x1000 };
BYTE* buffer = new BYTE[PIPE_BUFFER_SIZE];
DWORD bytesRead, processId;
//} catch (...) {
// if (hEvent != INVALID_HANDLE_VALUE)
// NtClose(hEvent);
// else if (hMutex != INVALID_HANDLE_VALUE) {
// NtWaitForSingleObject(hMutex, 0, 0);
// NtReleaseMutant(hMutex, 0);
// NtClose(hMutex);
// }
//}
// Artikash 5/20/2018: Shouldn't Windows automatically close the handles when the host process stops running?
//if (!::running) {
// NtClose(hookPipe);
// return 0;
//}
//NtSetEvent(hDetachEvent, 0);
if (::running)
NtSetEvent(pipeExistsEvent, 0);
}
ReadFile(hookPipe, &processId, sizeof(processId), &bytesRead, nullptr);
man->RegisterProcess(processId);
// jichi 9/27/2013: I don't need this
//void OutputDWORD(DWORD d)
//{
// WCHAR str[0x20];
// swprintf(str, L"%.8X", d);
// ConsoleOutput(str);
//}
// jichi 9/27/2013: why recursion?
// Artikash 5/20/2018: To create a new pipe for another process
CreateNewPipe();
DWORD WINAPI RecvThread(LPVOID lpThreadParameter)
{
HANDLE hTextPipe = (HANDLE)lpThreadParameter;
while (::running)
{
if (!ReadFile(hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr))
{
break;
}
IO_STATUS_BLOCK ios;
NtFsControlFile(hTextPipe,
0, 0, 0,
&ios,
CTL_CODE(FILE_DEVICE_NAMED_PIPE, NAMED_PIPE_CONNECT, 0, 0),
0, 0, 0, 0);
if (!::running) {
NtClose(hTextPipe);
return 0;
}
enum { DATA_OFFSET = 0xc }; // jichi 10/27/2013: Seem to be the data offset in the pipe
BYTE *buff;
if (bytesRead < DATA_OFFSET)
{
break;
}
enum { PipeBufferSize = 0x1000 };
buff = new BYTE[PipeBufferSize];
::memset(buff, 0, PipeBufferSize); // jichi 8/27/2013: zero memory, or it will crash wine on start up
union { DWORD retn; DWORD commandType; };
DWORD hook = *(DWORD *)buffer;
retn = *(DWORD *)(buffer + 4);
DWORD split = *(DWORD *)(buffer + 8);
// 10/19/2014 jichi: there are totally three words received
// See: hook/rpc/pipe.cc
// struct {
// DWORD pid;
// TextHook *man;
// DWORD module;
// //DWORD engine;
// } u;
enum { module_struct_size = 12 };
NtReadFile(hTextPipe, 0, 0, 0, &ios, buff, module_struct_size, 0, 0);
buffer[bytesRead] = 0;
buffer[bytesRead + 1] = 0;
// jichi 7/2/2015: This must be consistent with the struct declared in vnrhook/pipe.cc
DWORD pid = *(DWORD *)buff,
module = *(DWORD *)(buff + 0x8),
hookman = *(DWORD *)(buff + 0x4);
//engine = *(DWORD *)(buff + 0xc);
man->RegisterProcess(pid, hookman, module);
if (hook == HOST_NOTIFICATION)
{
switch (commandType)
{
case HOST_NOTIFICATION_NEWHOOK:
{
static long lock;
while (InterlockedExchange(&lock, 1) == 1);
man->ProcessNewHook()(processId);
lock = 0;
}
break;
case HOST_NOTIFICATION_TEXT:
USES_CONVERSION;
man->AddConsoleOutput(A2W((LPCSTR)(buffer + 8)));
break;
}
}
else
{
// 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]);
// jichi 9/27/2013: why recursion?
CreateNewPipe();
const BYTE *data = buffer + DATA_OFFSET; // th
int dataLength = bytesRead - DATA_OFFSET;
bool space = ::HasLeadingSpace(data, dataLength);
if (space)
{
const BYTE *it = ::Filter(data, dataLength);
dataLength -= it - data;
data = it;
}
man->DispatchText(processId, data, hook, retn, split, dataLength, space);
}
}
//NtClose(IthCreateThread(UpdateWindows,0));
while (::running) {
if (!NT_SUCCESS(NtReadFile(hTextPipe,
0, 0, 0,
&ios,
buff,
0xf80,
0, 0)))
break;
EnterCriticalSection(&detachCs);
enum { data_offset = 0xc }; // jichi 10/27/2013: Seem to be the data offset in the pipe
DisconnectNamedPipe(hookPipe);
DisconnectNamedPipe(man->GetCmdHandleByPID(processId));
man->UnRegisterProcess(processId);
DWORD RecvLen = ios.uInformation;
if (RecvLen < data_offset)
break;
DWORD hook = *(DWORD *)buff;
LeaveCriticalSection(&detachCs);
delete[] buffer;
union { DWORD retn; DWORD cmd_type; };
union { DWORD split; DWORD new_engine_type; };
retn = *(DWORD *)(buff + 4);
split = *(DWORD *)(buff + 8);
buff[RecvLen] = 0;
buff[RecvLen + 1] = 0;
if (hook == HOST_NOTIFICATION) {
switch (cmd_type) {
case HOST_NOTIFICATION_NEWHOOK:
{
static long lock;
while (InterlockedExchange(&lock, 1) == 1);
ProcessEventCallback new_hook = man->ProcessNewHook();
if (new_hook)
new_hook(pid);
lock = 0;
} break;
case HOST_NOTIFICATION_TEXT:
//qDebug() << ((LPCSTR)(buff + 8));
break;
}
} else {
// jichi 9/28/2013: Debug raw data
//ITH_DEBUG_DWORD9(RecvLen - 0xc,
// buff[0xc], buff[0xd], buff[0xe], buff[0xf],
// buff[0x10], buff[0x11], buff[0x12], buff[0x13]);
const BYTE *data = buff + data_offset; // th
int len = RecvLen - data_offset;
bool space = ::has_leading_space(data, len);
if (space) {
const BYTE *it = ::Filter(data, len);
len -= it - data;
data = it;
}
if (len >> 31) // jichi 10/27/2013: len is too large, which seldom happens
len = 0;
//man->DispatchText(pid, len ? data : nullptr, hook, retn, split, len, space);
man->DispatchText(pid, data, hook, retn, split, len, space);
}
}
EnterCriticalSection(&detachCs);
HANDLE hDisconnect = IthCreateEvent(nullptr);
if (STATUS_PENDING == NtFsControlFile(
hTextPipe,
hDisconnect,
0, 0,
&ios,
CTL_CODE(FILE_DEVICE_NAMED_PIPE, NAMED_PIPE_DISCONNECT, 0, 0),
0, 0, 0, 0))
NtWaitForSingleObject(hDisconnect, 0, 0);
NtClose(hDisconnect);
DetachFromProcess(pid);
man->UnRegisterProcess(pid);
//NtClearEvent(hDetachEvent);
LeaveCriticalSection(&detachCs);
delete[] buff;
if (::running)
DOUT("detached");
//if (::running) {
// swprintf((LPWSTR)buff, FormatDetach, pid);
// ConsoleOutput((LPWSTR)buff);
// NtClose(IthCreateThread(UpdateWindows, 0));
//}
return 0;
return 0;
}
// EOF

View File

@ -234,7 +234,7 @@ DWORD GetModuleBase()
// *(DWORD*)buffer=-1;
// *(DWORD*)(buffer+4)=1;
// IO_STATUS_BLOCK ios;
// NtWriteFile(hPipe,0,0,0,&ios,buffer,0x10,0,0);
// NtWriteFile(hookPipe,0,0,0,&ios,buffer,0x10,0,0);
// }
//}
@ -488,9 +488,9 @@ DWORD TextHook::UnsafeSend(DWORD dwDataBase, DWORD dwRetn)
IthCoolDown(); // jichi 9/28/2013: cool down to prevent parallelization in wine
//CliLockPipe();
if (STATUS_PENDING == NtWriteFile(::hPipe, 0, 0, 0, &ios, pbData, dwCount + HEADER_SIZE, 0, 0)) {
NtWaitForSingleObject(::hPipe, 0, 0);
NtFlushBuffersFile(::hPipe, &ios);
if (STATUS_PENDING == NtWriteFile(::hookPipe, 0, 0, 0, &ios, pbData, dwCount + HEADER_SIZE, 0, 0)) {
NtWaitForSingleObject(::hookPipe, 0, 0);
NtFlushBuffersFile(::hookPipe, &ios);
}
//CliUnlockPipe();
}
@ -550,7 +550,7 @@ int TextHook::UnsafeInsertHookCode()
if (base)
hp.address += base;
else {
current_hook--;
currentHook--;
ConsoleOutput("vnrcli:UnsafeInsertHookCode: FAILED: function not found in the export table");
return no;
}
@ -561,7 +561,7 @@ int TextHook::UnsafeInsertHookCode()
hp.type &= ~(MODULE_OFFSET | FUNCTION_OFFSET);
}
else {
current_hook--;
currentHook--;
ConsoleOutput("vnrcli:UnsafeInsertHookCode: FAILED: module not present");
return no;
}
@ -569,7 +569,7 @@ int TextHook::UnsafeInsertHookCode()
{
TextHook *it = hookman;
for (int i = 0; (i < current_hook) && it; it++) { // Check if there is a collision.
for (int i = 0; (i < currentHook) && it; it++) { // Check if there is a collision.
if (it->Address())
i++;
//it = hookman + i;
@ -640,7 +640,7 @@ int TextHook::UnsafeInsertHookCode()
//Check if the new hook range conflict with existing ones. Clear older if conflict.
{
TextHook *it = hookman;
for (int i = 0; i < current_hook; it++) {
for (int i = 0; i < currentHook; it++) {
if (it->Address())
i++;
if (it == this)
@ -686,7 +686,7 @@ int TextHook::InitHook(LPVOID addr, DWORD data, DWORD data_ind,
hp.hook_len = 0;
hp.module = 0;
hp.length_offset = len_off & 0xffff;
current_hook++;
currentHook++;
if (current_available >= this)
for (current_available = this + 1; current_available->Address(); current_available++);
IthReleaseMutex(hmMutex);
@ -701,7 +701,7 @@ int TextHook::InitHook(const HookParam &h, LPCSTR name, WORD set_flag)
if (name && name != hook_name) {
SetHookName(name);
}
current_hook++;
currentHook++;
current_available = this+1;
while (current_available->Address())
current_available++;
@ -742,7 +742,7 @@ int TextHook::ClearHook()
memset(this, 0, sizeof(TextHook)); // jichi 11/30/2013: This is the original code of ITH
//if (current_available>this)
// current_available = this;
current_hook--;
currentHook--;
IthReleaseMutex(hmMutex);
return err;
}

View File

@ -19,11 +19,11 @@
// - 0x8 dwSplit split value
#define HEADER_SIZE 0xc
extern int current_hook;
extern int currentHook;
extern WCHAR dll_mutex[];
//extern WCHAR dll_name[];
extern DWORD trigger;
//extern DWORD current_process_id;
//extern DWORD currentProcessId;
// jichi 6/3/2014: Get memory range of the current module
extern DWORD processStartAddress,
@ -77,11 +77,12 @@ extern FilterRange *filter;
extern bool running,
live;
extern HANDLE hPipe,
extern HANDLE hookPipe,
hmMutex;
DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter);
DWORD WINAPI CommandPipe(LPVOID lpThreadParameter);
DWORD WINAPI PipeManager(LPVOID unused);
//void RequestRefreshProfile();

View File

@ -62,14 +62,14 @@ HINSTANCE hDLL;
HANDLE hSection;
bool running,
live = false;
int current_hook = 0,
int currentHook = 0,
user_hook_count = 0;
DWORD trigger = 0;
HANDLE
hFile,
hMutex,
hmMutex;
//DWORD current_process_id;
//DWORD currentProcessId;
extern DWORD enter_count;
//extern LPWSTR current_dir;
extern DWORD engine_type;
@ -133,7 +133,7 @@ void RequestRefreshProfile()
*(DWORD *)(buffer + 8) = 0;
IO_STATUS_BLOCK ios;
CliLockPipe();
NtWriteFile(hPipe, 0, 0, 0, &ios, buffer, HEADER_SIZE, 0, 0);
NtWriteFile(hookPipe, 0, 0, 0, &ios, buffer, HEADER_SIZE, 0, 0);
CliUnlockPipe();
}
}
@ -156,7 +156,7 @@ DWORD GetFunctionAddr(const char *name, DWORD *addr, DWORD *base, DWORD *size, L
BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
{
static HANDLE hSendThread,
static HANDLE pipeThread,
hCmdThread;
CC_UNUSED(lpReserved);
@ -189,7 +189,7 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
// No longer checking if SystemService fails, which could happen on non-Japanese OS
IthInitSystemService();
swprintf(hm_section, ITH_SECTION_ L"%d", current_process_id);
swprintf(hm_section, ITH_SECTION_ L"%d", currentProcessId);
// jichi 9/25/2013: Interprocedural communication with vnrsrv.
hSection = IthCreateSection(hm_section, HOOK_SECTION_SIZE, PAGE_EXECUTE_READWRITE);
@ -211,12 +211,12 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
{
wchar_t hm_mutex[0x100];
swprintf(hm_mutex, ITH_HOOKMAN_MUTEX_ L"%d", current_process_id);
swprintf(hm_mutex, ITH_HOOKMAN_MUTEX_ L"%d", currentProcessId);
::hmMutex = IthCreateMutex(hm_mutex, FALSE);
}
{
wchar_t dll_mutex[0x100];
swprintf(dll_mutex, ITH_PROCESS_MUTEX_ L"%d", current_process_id);
swprintf(dll_mutex, ITH_PROCESS_MUTEX_ L"%d", currentProcessId);
DWORD exists;
::hMutex = IthCreateMutex(dll_mutex, TRUE, &exists); // jichi 9/18/2013: own is true, make sure the injected dll is singleton
if (exists)
@ -231,8 +231,7 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
AddAllModules();
InitFilterTable();
hSendThread = IthCreateThread(WaitForPipe, 0);
hCmdThread = IthCreateThread(CommandPipe, 0);
pipeThread = IthCreateThread(PipeManager, 0);
} break;
case DLL_PROCESS_DETACH:
{
@ -250,9 +249,9 @@ BOOL WINAPI DllMain(HINSTANCE hModule, DWORD fdwReason, LPVOID lpReserved)
Engine::terminate();
if (hSendThread) {
NtWaitForSingleObject(hSendThread, 0, (PLARGE_INTEGER)&timeout);
NtClose(hSendThread);
if (pipeThread) {
NtWaitForSingleObject(pipeThread, 0, (PLARGE_INTEGER)&timeout);
NtClose(pipeThread);
}
if (hCmdThread) {

View File

@ -12,7 +12,7 @@
#include "src/util/util.h"
#include "src/main.h"
#include "include/defs.h"
//#include "src/util/growl.h"
#include "src/util/growl.h"
#include "ithsys/ithsys.h"
#include "ccutil/ccmacro.h"
#include <cstdio> // for swprintf
@ -34,7 +34,7 @@ LARGE_INTEGER sleep_time = {-20*10000, -1};
DWORD engine_type;
DWORD module_base;
HANDLE hPipe,
HANDLE hookPipe,
hCommand,
hDetach; //,hLose;
//InsertHookFun InsertHook;
@ -71,20 +71,88 @@ HANDLE IthOpenPipe(LPWSTR name, ACCESS_MASK direction)
return INVALID_HANDLE_VALUE;
}
DWORD WINAPI PipeManager(LPVOID unused)
{
enum { STANDARD_WAIT = 1000 };
while (::running)
{
DWORD count;
BYTE* buffer = new BYTE[0x1000];
HANDLE hostPipe = ::hookPipe = INVALID_HANDLE_VALUE,
pipeAcquisitionMutex = CreateMutexW(nullptr, TRUE, ITH_GRANTPIPE_MUTEX);
while (::hookPipe == INVALID_HANDLE_VALUE || hostPipe == INVALID_HANDLE_VALUE)
{
Sleep(STANDARD_WAIT);
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_SHARE_READ, nullptr, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, nullptr);
}
}
WriteFile(::hookPipe, &::currentProcessId, sizeof(::currentProcessId), &count, nullptr);
for (int i = 0, count = 0; count < ::currentHook; i++)
{
if (hookman[i].RecoverHook()) // jichi 9/27/2013: This is the place where built-in hooks like TextOutA are inserted
{
count++;
}
}
ReleaseMutex(pipeAcquisitionMutex);
CloseHandle(pipeAcquisitionMutex);
::live = true;
Engine::hijack();
ConsoleOutput("vnrcli:WaitForPipe: pipe connected");
while (::running)
{
Sleep(STANDARD_WAIT);
if (!ReadFile(hostPipe, buffer, 0x800, &count, nullptr))
{
break;
}
DWORD command = *(DWORD*)buffer;
switch (command)
{
case HOST_COMMAND_NEW_HOOK:
buffer[count] = 0;
NewHook(*(HookParam *)(buffer + 4), (LPSTR)(buffer + 4 + sizeof(HookParam)), 0);
break;
case HOST_COMMAND_DETACH:
::running = false;
break;
}
}
::live = false;
for (int i = 0, count = 0; count < ::currentHook; i++)
{
if (hookman[i].RemoveHook())
{
count++;
}
}
CloseHandle(::hookPipe);
CloseHandle(hostPipe);
}
Util::unloadCurrentModule();
return 0;
}
DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter) // Dynamically detect ITH main module status.
{
CC_UNUSED(lpThreadParameter);
// jichi 7/2/2015:This must be consistent with the struct declared in vnrhost/pipe.cc
struct {
DWORD pid;
DWORD module;
TextHook *man;
//DWORD engine;
} u;
//swprintf(engine_event,L"ITH_ENGINE_%d",current_process_id);
swprintf(::detach_mutex, ITH_DETACH_MUTEX_ L"%d", current_process_id);
//swprintf(lose_event,L"ITH_LOSEPIPE_%d",current_process_id);
//swprintf(engine_event,L"ITH_ENGINE_%d",currentProcessId);
swprintf(::detach_mutex, ITH_DETACH_MUTEX_ L"%d", currentProcessId);
//swprintf(lose_event,L"ITH_LOSEPIPE_%d",currentProcessId);
//hEngine=IthCreateEvent(engine_event);
//NtWaitForSingleObject(hEngine,0,0);
//NtClose(hEngine);
@ -93,35 +161,33 @@ DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter) // Dynamically detect ITH mai
// NtDelayExecution(0, &wait_time);
//LoadEngine(L"ITH_Engine.dll");
u.module = module_base;
u.pid = current_process_id;
u.man = hookman;
//u.engine = engine_base; // jichi 10/19/2014: disable the second dll
HANDLE hPipeExist = IthOpenEvent(ITH_PIPEEXISTS_EVENT);
IO_STATUS_BLOCK ios;
//hLose=IthCreateEvent(lose_event,0,0);
if (hPipeExist != INVALID_HANDLE_VALUE)
while (::running) {
::hPipe = INVALID_HANDLE_VALUE;
::hookPipe = INVALID_HANDLE_VALUE;
hCommand = INVALID_HANDLE_VALUE;
while (NtWaitForSingleObject(hPipeExist, 0, &wait_time) == WAIT_TIMEOUT)
if (!::running)
goto _release;
GROWL_MSG(L"Pipe connected");
HANDLE hMutex = IthCreateMutex(ITH_GRANTPIPE_MUTEX, 0);
NtWaitForSingleObject(hMutex, 0, 0);
while (::hPipe == INVALID_HANDLE_VALUE||
while (::hookPipe == INVALID_HANDLE_VALUE||
hCommand == INVALID_HANDLE_VALUE) {
NtDelayExecution(0, &sleep_time);
if (::hPipe == INVALID_HANDLE_VALUE)
::hPipe = IthOpenPipe(recv_pipe, GENERIC_WRITE);
if (::hookPipe == INVALID_HANDLE_VALUE)
::hookPipe = IthOpenPipe(recv_pipe, GENERIC_WRITE);
if (hCommand == INVALID_HANDLE_VALUE)
hCommand = IthOpenPipe(command, GENERIC_READ);
}
//NtClearEvent(hLose);
CliLockPipe();
NtWriteFile(::hPipe, 0, 0, 0, &ios, &u, sizeof(u), 0, 0);
NtWriteFile(::hookPipe, 0, 0, 0, &ios, &::currentProcessId, sizeof(::currentProcessId), 0, 0);
CliUnlockPipe();
for (int i = 0, count = 0; count < ::current_hook; i++)
for (int i = 0, count = 0; count < ::currentHook; i++)
if (hookman[i].RecoverHook()) // jichi 9/27/2013: This is the place where built-in hooks like TextOutA are inserted
count++;
//ConsoleOutput(dll_name);
@ -141,19 +207,19 @@ DWORD WINAPI WaitForPipe(LPVOID lpThreadParameter) // Dynamically detect ITH mai
NtDelayExecution(0, &sleep_time);
::live = false;
for (int i = 0, count = 0; count < ::current_hook; i++)
for (int i = 0, count = 0; count < ::currentHook; i++)
if (hookman[i].RemoveHook())
count++;
if (!::running) {
IthCoolDown(); // jichi 9/28/2013: Use cooldown instead of lock pipe to prevent from hanging on exit
//CliLockPipe();
//NtWriteFile(::hPipe, 0, 0, 0, &ios, man, 4, 0, 0);
NtWriteFile(::hPipe, 0, 0, 0, &ios, hookman, 4, 0, 0);
//NtWriteFile(::hookPipe, 0, 0, 0, &ios, man, 4, 0, 0);
NtWriteFile(::hookPipe, 0, 0, 0, &ios, hookman, 4, 0, 0);
//CliUnlockPipe();
IthReleaseMutex(::hDetach);
}
NtClose(::hDetach);
NtClose(::hPipe);
NtClose(::hookPipe);
}
_release:
//NtClose(hLose);
@ -211,7 +277,7 @@ DWORD WINAPI CommandPipe(LPVOID lpThreadParameter)
HANDLE hRemoved = IthOpenEvent(ITH_REMOVEHOOK_EVENT);
TextHook *in = hookman;
for (int i = 0; i < current_hook; in++) {
for (int i = 0; i < currentHook; in++) {
if (in->Address()) i++;
if (in->Address() == rm_addr) break;
}
@ -226,7 +292,7 @@ DWORD WINAPI CommandPipe(LPVOID lpThreadParameter)
DWORD rm_addr = *(DWORD *)(buff + 4);
HANDLE hModify = IthOpenEvent(ITH_MODIFYHOOK_EVENT);
TextHook *in = hookman;
for (int i = 0; i < current_hook; in++) {
for (int i = 0; i < currentHook; in++) {
if (in->Address())
i++;
if (in->Address() == rm_addr)
@ -270,7 +336,7 @@ void ConsoleOutput(LPCSTR text)
memcpy(data + 8, text, text_size);
IO_STATUS_BLOCK ios;
NtWriteFile(hPipe, 0, 0, 0, &ios, data, data_size, 0, 0);
NtWriteFile(hookPipe, 0, 0, 0, &ios, data, data_size, 0, 0);
if (data != buf)
delete[] data;
}
@ -279,7 +345,7 @@ void ConsoleOutput(LPCSTR text)
// BYTE buffer[0x80];
// BYTE *buff;
// len = wcslen(str) << 1;
// t = swprintf((LPWSTR)(buffer + 8),L"%d: ",current_process_id) << 1;
// t = swprintf((LPWSTR)(buffer + 8),L"%d: ",currentProcessId) << 1;
// sum = len + t + 8;
// if (sum > 0x80) {
// buff = new BYTE[sum];
@ -292,7 +358,7 @@ void ConsoleOutput(LPCSTR text)
// *(DWORD *)(buff + 4) = HOST_NOTIFICATION_TEXT; //console
// memcpy(buff + t + 8, str, len);
// IO_STATUS_BLOCK ios;
// NtWriteFile(hPipe,0,0,0,&ios,buff,sum,0,0);
// NtWriteFile(hookPipe,0,0,0,&ios,buff,sum,0,0);
// if (buff != buffer)
// delete[] buff;
// return len;
@ -343,7 +409,7 @@ DWORD NotifyHookInsert(DWORD addr)
*(DWORD *)(buffer + 0xc) = 0;
IO_STATUS_BLOCK ios;
CliLockPipe();
NtWriteFile(hPipe,0,0,0,&ios,buffer,0x10,0,0);
NtWriteFile(hookPipe,0,0,0,&ios,buffer,0x10,0,0);
CliUnlockPipe();
}
return 0;

View File

@ -304,6 +304,7 @@ termin:
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
// See: http://stackoverflow.com/questions/3410130/dll-unloading-itself
// TODO: This doesn't always work. Fix it.
bool Util::unloadCurrentModule()
{
auto fun = ::FreeLibrary;