clean up vnrhost

This commit is contained in:
Akash Mozumdar 2018-07-17 17:01:56 -04:00
parent 803a1cd4bf
commit ae6656441b
19 changed files with 154 additions and 387 deletions

View File

@ -76,9 +76,9 @@ void ProcessWindow::AttachProcess()
{ {
DWORD pid = GetSelectedPID(); DWORD pid = GetSelectedPID();
if (InjectProcessById(pid)) if (InjectProcessById(pid))
{
RefreshThreadWithPID(pid, true); RefreshThreadWithPID(pid, true);
} else
ConsoleOutput(L"NextHooker: could not inject");
} }
void ProcessWindow::DetachProcess() void ProcessWindow::DetachProcess()

View File

@ -18,7 +18,6 @@
#include "ITH.h" #include "ITH.h"
#include "host/host.h" #include "host/host.h"
#include "host/hookman.h" #include "host/hookman.h"
#include "host/settings.h"
#include "profile/Profile.h" #include "profile/Profile.h"
#include "ProfileManager.h" #include "ProfileManager.h"
@ -30,7 +29,6 @@ extern HWND hMainWnd; // windows.cpp
extern ProfileManager* pfman; // ProfileManager.cpp extern ProfileManager* pfman; // ProfileManager.cpp
HookManager* man; HookManager* man;
Settings* setman;
LONG split_time; LONG split_time;
std::map<std::wstring, long> setting; std::map<std::wstring, long> setting;
@ -148,17 +146,15 @@ LONG WINAPI UnhandledExcept(_EXCEPTION_POINTERS *ExceptionInfo)
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow)
{ {
InitCommonControls(); InitCommonControls();
if (OpenHost()) if (StartHost())
{ {
SetUnhandledExceptionFilter(UnhandledExcept); SetUnhandledExceptionFilter(UnhandledExcept);
GetHostHookManager(&man); GetHostHookManager(&man);
GetHostSettings(&setman);
setman->splittingInterval = 200;
pfman = new ProfileManager(); pfman = new ProfileManager();
DefaultSettings(); DefaultSettings();
LoadSettings(); LoadSettings();
InitializeSettings(); InitializeSettings();
setman->splittingInterval = split_time; man->SetSplitInterval(split_time);
hIns = hInstance; hIns = hInstance;
MyRegisterClass(hIns); MyRegisterClass(hIns);
InitInstance(hIns, FALSE, &window); InitInstance(hIns, FALSE, &window);

View File

@ -23,7 +23,6 @@
#include "vnrhook/include/const.h" #include "vnrhook/include/const.h"
#include "version.h" #include "version.h"
#include "ProfileManager.h" #include "ProfileManager.h"
#include "host/settings.h"
#include "profile/Profile.h" #include "profile/Profile.h"
#include "TextBuffer.h" #include "TextBuffer.h"
#include "profile/misc.h" #include "profile/misc.h"
@ -44,7 +43,6 @@ ProcessWindow* pswnd;
TextBuffer* texts; TextBuffer* texts;
extern ProfileManager* pfman; // ProfileManager.cpp extern ProfileManager* pfman; // ProfileManager.cpp
extern HookManager* man; // main.cpp extern HookManager* man; // main.cpp
extern Settings* setman; // main.cpp
#define COMMENT_BUFFER_LENGTH 512 #define COMMENT_BUFFER_LENGTH 512
static WCHAR comment_buffer[COMMENT_BUFFER_LENGTH]; static WCHAR comment_buffer[COMMENT_BUFFER_LENGTH];
@ -108,7 +106,7 @@ BOOL CALLBACK OptionDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
GetWindowText(GetDlgItem(hDlg, IDC_EDIT1), str, 0x80); GetWindowText(GetDlgItem(hDlg, IDC_EDIT1), str, 0x80);
DWORD st = std::stoul(str); DWORD st = std::stoul(str);
split_time = st > 100 ? st : 100; split_time = st > 100 ? st : 100;
setman->splittingInterval = split_time; man->SetSplitInterval(split_time);
} }
case IDCANCEL: case IDCANCEL:
EndDialog(hDlg, 0); EndDialog(hDlg, 0);
@ -602,7 +600,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
man->RegisterProcessDetachCallback(RemoveProcessList); man->RegisterProcessDetachCallback(RemoveProcessList);
//man->RegisterProcessNewHookCallback(RefreshProfileOnNewHook); Artikash 5/30/2018 TODO: Finish implementing this. //man->RegisterProcessNewHookCallback(RefreshProfileOnNewHook); Artikash 5/30/2018 TODO: Finish implementing this.
man->RegisterAddRemoveLinkCallback(AddRemoveLink); man->RegisterAddRemoveLinkCallback(AddRemoveLink);
StartHost(); OpenHost();
{ {
static const WCHAR program_name[] = L"NextHooker beta v"; static const WCHAR program_name[] = L"NextHooker beta v";
//static const WCHAR program_version[] = L"3.0"; //static const WCHAR program_version[] = L"3.0";

View File

@ -67,6 +67,15 @@ DWORD IthGetMemoryRange(LPCVOID mem, DWORD *base, DWORD *size)
return (info.Type&PAGE_NOACCESS) == 0; return (info.Type&PAGE_NOACCESS) == 0;
} }
inline DWORD GetHash(LPSTR str)
{
DWORD hash = 0;
//for (; *str; str++)
while (*str)
hash = ((hash >> 7) | (hash << 25)) + *str++;
return hash;
}
//Query module export table. Return function address if found. //Query module export table. Return function address if found.
//Similar to GetProcAddress //Similar to GetProcAddress
DWORD GetExportAddress(DWORD hModule,DWORD hash) DWORD GetExportAddress(DWORD hModule,DWORD hash)

View File

@ -21,13 +21,4 @@ DWORD GetExportAddress(DWORD hModule,DWORD hash);
extern BYTE LeadByteTable[]; extern BYTE LeadByteTable[];
inline DWORD GetHash(LPSTR str)
{
DWORD hash = 0;
//for (; *str; str++)
while (*str)
hash = ((hash>>7) | (hash<<25)) + *str++;
return hash;
}
// EOF // EOF

View File

@ -11,7 +11,6 @@ set(vnrhost_src
hookman.h hookman.h
host.h host.h
host_p.h host_p.h
settings.h
textthread.h textthread.h
textthread_p.h textthread_p.h
hookman.cc hookman.cc

View File

@ -5,10 +5,6 @@
// The first header file that are included by all source files. // The first header file that are included by all source files.
#define IHF // for dll import #define IHF // for dll import
//#include "ith/dllconfig.h" #define DLLEXPORT __declspec(dllexport)
#define IHFAPI __stdcall
#ifdef IHF
# define IHFSERVICE __declspec(dllexport)
#endif
// EOF // EOF

View File

@ -12,88 +12,27 @@
#include "vnrhook/include/const.h" #include "vnrhook/include/const.h"
#include "vnrhook/include/defs.h" #include "vnrhook/include/defs.h"
#include "vnrhook/include/types.h" #include "vnrhook/include/types.h"
#include "ithsys/ithsys.h"
#include <stdio.h> #include <stdio.h>
//#include <emmintrin.h> //#include <emmintrin.h>
#include "profile/Profile.h" #include "profile/Profile.h"
#include "profile/pugixml.h" #include "profile/pugixml.h"
#include "profile/misc.h" #include "profile/misc.h"
#define DEBUG "vnrhost/hookman.cc"
namespace { // unnamed
//enum { MAX_ENTRY = 0x40 };
#define HM_LOCK CriticalSectionLocker d_locker(hmcs) // Synchronized scope for accessing private data #define HM_LOCK CriticalSectionLocker d_locker(hmcs) // Synchronized scope for accessing private data
} // unnamed namespace
HookManager *man; // jichi 9/22/2013: initialized in main
//BitMap* pid_map;
DWORD clipboard_flag,
split_time,
repeat_count,
global_filter,
cyclic_remove;
DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max)
{
if (!pid)
return 0;
DWORD len = 0;
max--; //for '\0' magic marker.
//if (pid == 0) {
// len = wcslen(HookNameInitTable[0]);
// if (len >= max)
// len = max;
// memcpy(str, HookNameInitTable[0], len << 1);
// str[len] = 0;
// return len;
//}
//::man->LockProcessHookman(pid);
ProcessRecord *pr = ::man->GetProcessRecord(pid);
if (!pr)
return 0;
WaitForSingleObject(pr->hookman_mutex, 0);
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();
if (len >= max)
len = max;
ReadProcessMemory(pr->process_handle, hks[i].Name(), str, len, &len);
if (str[len - 1] == 0)
len--;
else
str[len] = 0;
break;
}
ReleaseMutex(pr->hookman_mutex);
//::man->UnlockProcessHookman(pid);
return len;
}
//Class member of HookManger
HookManager::HookManager() : HookManager::HookManager() :
// jichi 9/21/2013: Zero memory current(nullptr),
//CRITICAL_SECTION hmcs; create(nullptr),
current(nullptr) remove(nullptr),
, create(nullptr) reset(nullptr),
, remove(nullptr) attach(nullptr),
, reset(nullptr) detach(nullptr),
, attach(nullptr) hook(nullptr),
, detach(nullptr) new_thread_number(0),
, hook(nullptr) threadTable(),
, new_thread_number(0) processRecordsByIds()
, threadTable()
, processRecordsByIds()
{ {
TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++); TextThread* consoleTextThread = threadTable[{0, -1UL, -1UL, -1UL}] = new TextThread({ 0, -1UL, -1UL, -1UL }, new_thread_number++, splitDelay);
consoleTextThread->Status() |= USING_UNICODE; consoleTextThread->Status() |= USING_UNICODE;
SetCurrent(consoleTextThread); SetCurrent(consoleTextThread);
@ -102,17 +41,7 @@ HookManager::HookManager() :
HookManager::~HookManager() HookManager::~HookManager()
{ {
// Artikash 5/31/2018: This is called when the program terminates, so Windows should automatically free all these resources.....right? DeleteCriticalSection(&hmcs);
//LeaveCriticalSection(&hmcs);
//LARGE_INTEGER timeout={-1000*1000,-1};
//IthBreak();
//NtWaitForSingleObject(destroy_event, 0, 0);
//CloseHandle(destroy_event);
//CloseHandle(cmd_pipes[0]);
//CloseHandle(recv_threads[0]);
//delete thread_table;
//delete head.key;
//DeleteCriticalSection(&hmcs);
} }
TextThread *HookManager::FindSingle(DWORD number) TextThread *HookManager::FindSingle(DWORD number)
@ -232,7 +161,7 @@ void HookManager::DispatchText(DWORD pid, const BYTE *text, DWORD hook, DWORD re
TextThread *it; TextThread *it;
if (!(it = threadTable[tp])) if (!(it = threadTable[tp]))
{ {
it = threadTable[tp] = new TextThread(tp, new_thread_number++); it = threadTable[tp] = new TextThread(tp, new_thread_number++, splitDelay);
if (create) if (create)
{ {
create(it); create(it);
@ -267,15 +196,12 @@ ProcessRecord *HookManager::GetProcessRecord(DWORD pid)
return processRecordsByIds[pid]; return processRecordsByIds[pid];
} }
HANDLE HookManager::GetCommandPipe(DWORD pid) HANDLE HookManager::GetHostPipe(DWORD pid)
{ {
HM_LOCK; HM_LOCK;
return processRecordsByIds[pid] ? processRecordsByIds[pid]->hostPipe : nullptr; return processRecordsByIds[pid] ? processRecordsByIds[pid]->hostPipe : nullptr;
} }
MK_BASIC_TYPE(DWORD)
MK_BASIC_TYPE(LPVOID)
void AddHooksToProfile(Profile& pf, const ProcessRecord& pr); void AddHooksToProfile(Profile& pf, const ProcessRecord& pr);
DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread); DWORD AddThreadToProfile(Profile& pf, const ProcessRecord& pr, TextThread* thread);
void MakeHookRelative(const ProcessRecord& pr, HookParam& hp); void MakeHookRelative(const ProcessRecord& pr, HookParam& hp);

View File

@ -18,15 +18,12 @@ enum { MAX_REGISTER = 0xf };
enum { MAX_PREV_REPEAT_LENGTH = 0x20 }; enum { MAX_PREV_REPEAT_LENGTH = 0x20 };
struct ProcessRecord { struct ProcessRecord {
DWORD pid_register;
DWORD hookman_register;
DWORD module_register;
//DWORD engine_register; // jichi 10/19/2014: removed
HANDLE process_handle; HANDLE process_handle;
HANDLE hookman_mutex; HANDLE hookman_mutex;
HANDLE hookman_section; HANDLE hookman_section;
LPVOID hookman_map; LPVOID hookman_map;
HANDLE hostPipe; HANDLE hostPipe;
//std::unordered_map<DWORD, Hook> hooksByAddress;
}; };
typedef DWORD (*ProcessEventCallback)(DWORD pid); typedef DWORD (*ProcessEventCallback)(DWORD pid);
@ -39,7 +36,7 @@ struct ThreadParameterHasher
} }
}; };
class IHFSERVICE HookManager class DLLEXPORT HookManager
{ {
public: public:
HookManager(); HookManager();
@ -62,7 +59,7 @@ public:
void UnRegisterProcess(DWORD pid); void UnRegisterProcess(DWORD pid);
//void SetName(DWORD); //void SetName(DWORD);
HANDLE GetCommandPipe(DWORD pid); HANDLE GetHostPipe(DWORD pid);
ThreadEventCallback RegisterThreadCreateCallback(ThreadEventCallback cf) ThreadEventCallback RegisterThreadCreateCallback(ThreadEventCallback cf)
{ return (ThreadEventCallback)_InterlockedExchange((long*)&create,(long)cf); } { return (ThreadEventCallback)_InterlockedExchange((long*)&create,(long)cf); }
@ -82,6 +79,8 @@ public:
ProcessEventCallback RegisterProcessDetachCallback(ProcessEventCallback cf) ProcessEventCallback RegisterProcessDetachCallback(ProcessEventCallback cf)
{ return (ProcessEventCallback)_InterlockedExchange((long*)&detach,(long)cf); } { return (ProcessEventCallback)_InterlockedExchange((long*)&detach,(long)cf); }
void SetSplitInterval(unsigned int splitDelay) { this->splitDelay = splitDelay; }
void OnThreadCreate(pugi::xml_node profile_node, TextThread* thread); void OnThreadCreate(pugi::xml_node profile_node, TextThread* thread);
void GetProfile(DWORD pid, pugi::xml_node profile_node); void GetProfile(DWORD pid, pugi::xml_node profile_node);
@ -102,6 +101,8 @@ private:
WORD register_count, WORD register_count,
new_thread_number; new_thread_number;
unsigned int splitDelay;
void HookManager::AddThreadsToProfile(Profile& pf, const ProcessRecord& pr, DWORD pid); void HookManager::AddThreadsToProfile(Profile& pf, const ProcessRecord& pr, DWORD pid);
}; };

View File

@ -10,34 +10,20 @@
//#include "customfilter.h" //#include "customfilter.h"
#include "growl.h" #include "growl.h"
#include "host.h" #include "host.h"
#include "host_p.h"
#include "settings.h"
#include "vnrhook/include/const.h" #include "vnrhook/include/const.h"
#include "vnrhook/include/defs.h" #include "vnrhook/include/defs.h"
#include "vnrhook/include/types.h" #include "vnrhook/include/types.h"
#include "ithsys/ithsys.h"
#include <commctrl.h> #include <commctrl.h>
#include <string> #include <string>
#include "extensions/Extensions.h" #include "extensions/Extensions.h"
#define DEBUG "vnrhost/host.cc" #define DEBUG "vnrhost/host.cc"
namespace HANDLE preventDuplicationMutex;
{ // unnamed
CRITICAL_SECTION hostCs; HookManager* man;
HANDLE preventDuplicationMutex; // jichi 9/28/2013: used to guard pipe
HANDLE hookMutex; // jichi 9/28/2013: used to guard hook modification
} // unnamed namespace
//extern LPWSTR current_dir;
extern CRITICAL_SECTION detachCs;
Settings *settings;
HWND dummyWindow; HWND dummyWindow;
BOOL running; bool running;
#define ITH_SYNC_HOOK MutexLocker locker(::hookMutex)
namespace namespace
{ // unnamed { // unnamed
@ -62,7 +48,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
{ {
case DLL_PROCESS_ATTACH: case DLL_PROCESS_ATTACH:
DisableThreadLibraryCalls(hinstDLL); DisableThreadLibraryCalls(hinstDLL);
InitializeCriticalSection(&::hostCs);
GetDebugPrivileges(); GetDebugPrivileges();
// jichi 12/20/2013: Since I already have a GUI, I don't have to InitCommonControls() // jichi 12/20/2013: Since I already have a GUI, I don't have to InitCommonControls()
// Used by timers. // Used by timers.
@ -73,7 +58,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
case DLL_PROCESS_DETACH: case DLL_PROCESS_DETACH:
if (::running) if (::running)
CloseHost(); CloseHost();
DeleteCriticalSection(&::hostCs);
DestroyWindow(dummyWindow); DestroyWindow(dummyWindow);
break; break;
default: default:
@ -82,129 +66,83 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
return true; return true;
} }
IHFSERVICE bool IHFAPI OpenHost() DLLEXPORT bool StartHost()
{ {
bool success;
EnterCriticalSection(&::hostCs);
preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX); preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX);
if (GetLastError() == ERROR_ALREADY_EXISTS || ::running) if (GetLastError() == ERROR_ALREADY_EXISTS || ::running)
{ {
GROWL_WARN(L"I am sorry that this game is attached by some other VNR ><\nPlease restart the game and try again!"); GROWL_WARN(L"I am sorry that this game is attached by some other VNR ><\nPlease restart the game and try again!");
success = false; return false;
} }
else else
{ {
LoadExtensions(); LoadExtensions();
::running = true; ::running = true;
::settings = new Settings;
::man = new HookManager; ::man = new HookManager;
InitializeCriticalSection(&detachCs); return true;
::hookMutex = CreateMutexW(nullptr, FALSE, ITH_SERVER_HOOK_MUTEX);
success = true;
} }
LeaveCriticalSection(&::hostCs);
return success;
} }
IHFSERVICE void IHFAPI StartHost() DLLEXPORT void OpenHost()
{ {
CreateNewPipe(); CreateNewPipe();
} }
IHFSERVICE void IHFAPI CloseHost() DLLEXPORT void CloseHost()
{ {
EnterCriticalSection(&::hostCs);
if (::running) if (::running)
{ {
::running = false; ::running = false;
delete man; delete man;
delete settings;
CloseHandle(::hookMutex);
CloseHandle(preventDuplicationMutex); CloseHandle(preventDuplicationMutex);
DeleteCriticalSection(&detachCs);
} }
LeaveCriticalSection(&::hostCs);
} }
IHFSERVICE bool IHFAPI InjectProcessById(DWORD processId, DWORD timeout) DLLEXPORT bool InjectProcessById(DWORD processId, DWORD timeout)
{ {
bool success = true;
if (processId == GetCurrentProcessId()) if (processId == GetCurrentProcessId())
{ {
success = false; return false;
} }
CloseHandle(CreateMutexW(nullptr, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId)).c_str())); CloseHandle(CreateMutexW(nullptr, FALSE, (ITH_HOOKMAN_MUTEX_ + std::to_wstring(processId)).c_str()));
if (GetLastError() == ERROR_ALREADY_EXISTS) if (GetLastError() == ERROR_ALREADY_EXISTS)
{ {
man->AddConsoleOutput(L"already locked"); man->AddConsoleOutput(L"already locked");
success = false; return false;
} }
HMODULE textHooker = LoadLibraryExW(ITH_DLL, nullptr, DONT_RESOLVE_DLL_REFERENCES); HMODULE textHooker = LoadLibraryExW(ITH_DLL, nullptr, DONT_RESOLVE_DLL_REFERENCES);
if (textHooker == nullptr)
{
success = false;
}
wchar_t textHookerPath[MAX_PATH]; wchar_t textHookerPath[MAX_PATH];
unsigned int textHookerPathSize = GetModuleFileNameW(textHooker, textHookerPath, MAX_PATH) * 2 + 2; unsigned int textHookerPathSize = GetModuleFileNameW(textHooker, textHookerPath, MAX_PATH) * 2 + 2;
FreeLibrary(textHooker); FreeLibrary(textHooker);
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId); if (HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId))
if (processHandle == INVALID_HANDLE_VALUE || processHandle == nullptr)
{
success = false;
}
LPTHREAD_START_ROUTINE loadLibraryStartRoutine = (LPTHREAD_START_ROUTINE)GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW");
if (success)
{
if (LPVOID remoteData = VirtualAllocEx(processHandle, nullptr, textHookerPathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE)) if (LPVOID remoteData = VirtualAllocEx(processHandle, nullptr, textHookerPathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
{
if (WriteProcessMemory(processHandle, remoteData, textHookerPath, textHookerPathSize, nullptr)) if (WriteProcessMemory(processHandle, remoteData, textHookerPath, textHookerPathSize, nullptr))
{ if (HANDLE thread = CreateRemoteThread(processHandle, nullptr, 0, (LPTHREAD_START_ROUTINE)LoadLibraryW, remoteData, 0, nullptr))
if (HANDLE thread = CreateRemoteThread(processHandle, nullptr, 0, loadLibraryStartRoutine, remoteData, 0, nullptr))
{ {
WaitForSingleObject(thread, timeout); WaitForSingleObject(thread, timeout);
CloseHandle(thread); CloseHandle(thread);
VirtualFreeEx(processHandle, remoteData, textHookerPathSize, MEM_RELEASE);
CloseHandle(processHandle);
return true;
} }
else
{
success = false;
}
}
else
{
success = false;
}
VirtualFreeEx(processHandle, remoteData, textHookerPathSize, MEM_RELEASE);
}
else
{
success = false;
}
}
if (!success) man->AddConsoleOutput(L"couldn't inject dll");
{ return false;
man->AddConsoleOutput(L"error: could not inject");
}
CloseHandle(processHandle);
return success;
} }
IHFSERVICE bool IHFAPI DetachProcessById(DWORD processId) DLLEXPORT bool DetachProcessById(DWORD processId)
{ {
DWORD command = HOST_COMMAND_DETACH; DWORD command = HOST_COMMAND_DETACH;
DWORD unused; DWORD unused;
return WriteFile(man->GetCommandPipe(processId), &command, sizeof(command), &unused, nullptr); return WriteFile(man->GetHostPipe(processId), &command, sizeof(command), &unused, nullptr);
} }
IHFSERVICE void IHFAPI GetHostHookManager(HookManager** hookman) DLLEXPORT void GetHostHookManager(HookManager** hookman)
{ {
if (::running) if (::running)
{ {
@ -212,17 +150,9 @@ IHFSERVICE void IHFAPI GetHostHookManager(HookManager** hookman)
} }
} }
IHFSERVICE void IHFAPI GetHostSettings(Settings **p) DLLEXPORT DWORD InsertHook(DWORD pid, const HookParam *hp, std::string name)
{ {
if (::running) HANDLE commandPipe = man->GetHostPipe(pid);
{
*p = settings;
}
}
IHFSERVICE DWORD IHFAPI InsertHook(DWORD pid, const HookParam *hp, std::string name)
{
HANDLE commandPipe = man->GetCommandPipe(pid);
if (commandPipe == nullptr) if (commandPipe == nullptr)
return -1; return -1;
@ -236,9 +166,9 @@ IHFSERVICE DWORD IHFAPI InsertHook(DWORD pid, const HookParam *hp, std::string n
return 0; return 0;
} }
IHFSERVICE DWORD IHFAPI RemoveHook(DWORD pid, DWORD addr) DLLEXPORT DWORD RemoveHook(DWORD pid, DWORD addr)
{ {
HANDLE commandPipe = man->GetCommandPipe(pid); HANDLE commandPipe = man->GetHostPipe(pid);
if (commandPipe == nullptr) if (commandPipe == nullptr)
return -1; return -1;

View File

@ -9,26 +9,15 @@
#include "host/hookman.h" #include "host/hookman.h"
#include <string> #include <string>
struct Settings;
struct HookParam; struct HookParam;
IHFSERVICE void IHFAPI Host_Init(); DLLEXPORT void OpenHost();
IHFSERVICE void IHFAPI Host_Destroy(); DLLEXPORT bool StartHost();
DLLEXPORT void CloseHost();
IHFSERVICE void IHFAPI StartHost(); DLLEXPORT void GetHostHookManager(HookManager **hookman);
IHFSERVICE bool IHFAPI OpenHost(); DLLEXPORT bool InjectProcessById(DWORD pid, DWORD timeout = 5000);
IHFSERVICE void IHFAPI CloseHost(); DLLEXPORT bool DetachProcessById(DWORD pid);
IHFSERVICE void IHFAPI GetHostHookManager(HookManager **hookman); DLLEXPORT DWORD InsertHook(DWORD pid, const HookParam *hp, std::string name = "");
IHFSERVICE void IHFAPI GetHostSettings(Settings **settings); DLLEXPORT DWORD RemoveHook(DWORD pid, DWORD addr);
IHFSERVICE DWORD IHFAPI Host_GetPIDByName(LPCWSTR pwcTarget);
IHFSERVICE bool IHFAPI InjectProcessById(DWORD pid, DWORD timeout = 5000);
IHFSERVICE bool IHFAPI DetachProcessById(DWORD pid);
IHFSERVICE bool IHFAPI Host_HijackProcess(DWORD pid);
IHFSERVICE DWORD IHFAPI InsertHook(DWORD pid, const HookParam *hp, std::string name = "");
IHFSERVICE DWORD IHFAPI Host_ModifyHook(DWORD pid, HookParam *hp);
IHFSERVICE DWORD IHFAPI RemoveHook(DWORD pid, DWORD addr);
IHFSERVICE DWORD IHFAPI Host_AddLink(DWORD from, DWORD to);
IHFSERVICE DWORD IHFAPI Host_UnLink(DWORD from);
IHFSERVICE DWORD IHFAPI Host_UnLinkAll(DWORD from);
// EOF // EOF

View File

@ -1,45 +0,0 @@
#pragma once
// host_p.h
// 8/24/2013 jichi
// Branch IHF/main.h, rev 111
#include <windows.h>
#include <tlhelp32.h>
#define GLOBAL extern
#define SHIFT_JIS 0x3A4
class HookManager;
//class CommandQueue;
class SettingManager;
class TextHook;
//class BitMap;
//class CustomFilterMultiByte;
//class CustomFilterUnicode;
//#define TextHook Hook
GLOBAL BOOL running;
//GLOBAL BitMap *pid_map;
//GLOBAL CustomFilterMultiByte *mb_filter;
//GLOBAL CustomFilterUnicode *uni_filter;
GLOBAL HookManager *man;
//GLOBAL CommandQueue *cmdq;
GLOBAL SettingManager *setman;
GLOBAL WCHAR recv_pipe[];
GLOBAL WCHAR command[];
GLOBAL HANDLE pipeExistsEvent;
GLOBAL DWORD split_time,
cyclic_remove,
clipboard_flag,
global_filter;
GLOBAL CRITICAL_SECTION detachCs;
DWORD WINAPI TextReceiver(LPVOID lpThreadParameter);
DWORD WINAPI CmdThread(LPVOID lpThreadParameter);
DWORD GetCurrentPID();
//DWORD GetProcessIDByPath(LPWSTR str);
HANDLE GetCommandPipe(DWORD pid);
//DWORD Inject(HANDLE hProc);
//DWORD InjectByPID(DWORD pid);
//DWORD PIDByName(LPWSTR target);
//DWORD Hash(LPCWSTR module, int length=-1);
// EOF

View File

@ -3,22 +3,15 @@
// Branch IHF/pipe.cpp, rev 93 // Branch IHF/pipe.cpp, rev 93
// 8/24/2013 TODO: Clean up this file // 8/24/2013 TODO: Clean up this file
#include "host_p.h" #include "host.h"
#include "hookman.h" #include "hookman.h"
#include "vnrhook/include/defs.h" #include "vnrhook/include/defs.h"
#include "vnrhook/include/const.h" #include "vnrhook/include/const.h"
#include "ithsys/ithsys.h"
#include <stdio.h> #include <stdio.h>
#include "growl.h" #include "growl.h"
#include <atlbase.h> #include <atlbase.h>
//#include "CommandQueue.h"
//#include <QtCore/QDebug>
#define DEBUG "vnrhost/pipe.cc" extern HookManager* man;
CRITICAL_SECTION detachCs; // jichi 9/27/2013: also used in main
//HANDLE hDetachEvent;
extern HANDLE pipeExistsEvent;
struct Pipes struct Pipes
{ {
@ -26,14 +19,16 @@ struct Pipes
HANDLE hostPipe; HANDLE hostPipe;
}; };
DWORD WINAPI TextReceiver(LPVOID lpThreadParameter);
void CreateNewPipe() void CreateNewPipe()
{ {
CreateThread(nullptr, 0, TextReceiver, new Pipes CloseHandle(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_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) CreateNamedPipeW(ITH_COMMAND_PIPE, PIPE_ACCESS_OUTBOUND, 0, PIPE_UNLIMITED_INSTANCES, PIPE_BUFFER_SIZE, PIPE_BUFFER_SIZE, MAXDWORD, NULL)
}, },
0, nullptr); 0, nullptr));
} }
DWORD WINAPI TextReceiver(LPVOID lpThreadParameter) DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
@ -57,34 +52,22 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
// Artikash 5/20/2018: To create a new pipe for another process // Artikash 5/20/2018: To create a new pipe for another process
CreateNewPipe(); CreateNewPipe();
while (::running) while (true)
{ {
if (!ReadFile(pipes->hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) if (!ReadFile(pipes->hookPipe, buffer, PIPE_BUFFER_SIZE, &bytesRead, nullptr)) break;
{
break;
}
enum { DATA_OFFSET = 0xc }; // jichi 10/27/2013: Seem to be the data offset in the pipe
if (bytesRead < DATA_OFFSET)
{
break;
}
union { DWORD retn; DWORD commandType; };
DWORD hook = *(DWORD *)buffer;
retn = *(DWORD *)(buffer + 4);
DWORD split = *(DWORD *)(buffer + 8);
buffer[bytesRead] = 0; buffer[bytesRead] = 0;
buffer[bytesRead + 1] = 0; buffer[bytesRead + 1] = 0;
if (hook == HOST_NOTIFICATION) if (*(DWORD*)buffer == HOST_NOTIFICATION)
{ {
switch (commandType) switch (*(DWORD*)(buffer + 4)) // Artikash 7/17/2018: Notification type
{ {
case HOST_NOTIFICATION_NEWHOOK: // Artikash 5/30/2018: Useless for now, but could be handy to implement something later case HOST_NOTIFICATION_NEWHOOK:
{
break; break;
}
case HOST_NOTIFICATION_TEXT: case HOST_NOTIFICATION_TEXT:
USES_CONVERSION; USES_CONVERSION;
man->AddConsoleOutput(A2W((LPCSTR)(buffer + 8))); man->AddConsoleOutput(A2W((LPCSTR)(buffer + 8)));
@ -93,24 +76,26 @@ DWORD WINAPI TextReceiver(LPVOID lpThreadParameter)
} }
else else
{ {
DWORD hook = *(DWORD*)buffer;
DWORD retn = *(DWORD*)(buffer + 4);
DWORD split = *(DWORD*)(buffer + 8);
// jichi 9/28/2013: Debug raw data // jichi 9/28/2013: Debug raw data
//ITH_DEBUG_DWORD9(RecvLen - 0xc, //ITH_DEBUG_DWORD9(RecvLen - 0xc,
// buffer[0xc], buffer[0xd], buffer[0xe], buffer[0xf], // buffer[0xc], buffer[0xd], buffer[0xe], buffer[0xf],
// buffer[0x10], buffer[0x11], buffer[0x12], buffer[0x13]); // buffer[0x10], buffer[0x11], buffer[0x12], buffer[0x13]);
const BYTE *data = buffer + DATA_OFFSET; // th const BYTE *data = buffer + HEADER_SIZE; // th
int dataLength = bytesRead - DATA_OFFSET; int dataLength = bytesRead - HEADER_SIZE;
man->DispatchText(processId, data, hook, retn, split, dataLength); man->DispatchText(processId, data, hook, retn, split, dataLength);
} }
} }
EnterCriticalSection(&detachCs);
DisconnectNamedPipe(pipes->hookPipe); DisconnectNamedPipe(pipes->hookPipe);
DisconnectNamedPipe(pipes->hostPipe); DisconnectNamedPipe(pipes->hostPipe);
man->UnRegisterProcess(processId); man->UnRegisterProcess(processId);
CloseHandle(pipes->hookPipe);
CloseHandle(pipes->hostPipe);
LeaveCriticalSection(&detachCs);
delete pipes; delete pipes;
return 0; return 0;

View File

@ -1,17 +0,0 @@
#pragma once
// settings.h
// 8/24/2013 jichi
struct Settings {
//bool debug; // whether output debug messages using pipes
int splittingInterval;// time to split text into sentences
bool clipboardFlag;
Settings() : splittingInterval(200),
clipboardFlag(false)
{}
};
// EOF

View File

@ -7,41 +7,66 @@
# pragma warning (disable:4100) // C4100: unreference formal parameter # pragma warning (disable:4100) // C4100: unreference formal parameter
#endif // _MSC_VER #endif // _MSC_VER
#include "settings.h" #include "host.h"
#include "textthread.h" #include "textthread.h"
//#include "wintimer/wintimer.h" //#include "wintimer/wintimer.h"
#include "vnrhook/include/const.h" #include "vnrhook/include/const.h"
#include "ithsys/ithsys.h" #include "vnrhook/include/types.h"
#include <stdio.h> #include <stdio.h>
#include "extensions/Extensions.h" #include "extensions/Extensions.h"
MK_BASIC_TYPE(BYTE) extern HookManager* man;
MK_BASIC_TYPE(ThreadParameter)
static DWORD MIN_DETECT = 0x20; DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr, DWORD max)
static DWORD MIN_REDETECT = 0x80; {
//#define MIN_DETECT 0x20 if (!pid)
//#define MIN_REDETECT 0x80 return 0;
#ifndef CURRENT_SELECT
# define CURRENT_SELECT 0x1000
#endif
#ifndef REPEAT_NUMBER_DECIDED
# define REPEAT_NUMBER_DECIDED 0x2000
#endif
DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr,DWORD max); DWORD len = 0;
max--; //for '\0' magic marker.
//if (pid == 0) {
// len = wcslen(HookNameInitTable[0]);
// if (len >= max)
// len = max;
// memcpy(str, HookNameInitTable[0], len << 1);
// str[len] = 0;
// return len;
//}
//::man->LockProcessHookman(pid);
ProcessRecord *pr = ::man->GetProcessRecord(pid);
if (!pr)
return 0;
WaitForSingleObject(pr->hookman_mutex, 0);
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();
if (len >= max)
len = max;
ReadProcessMemory(pr->process_handle, hks[i].Name(), str, len, &len);
if (str[len - 1] == 0)
len--;
else
str[len] = 0;
break;
}
ReleaseMutex(pr->hookman_mutex);
//::man->UnlockProcessHookman(pid);
return len;
}
extern Settings *settings;
extern HWND dummyWindow; extern HWND dummyWindow;
TextThread::TextThread(ThreadParameter tp, WORD num) : TextThread::TextThread(ThreadParameter tp, unsigned int threadNumber, unsigned int splitDelay) :
//,tp thread_number(threadNumber),
thread_number(num) splitDelay(splitDelay),
, output(nullptr) output(nullptr),
//, comment(nullptr) status(0),
, status(0) tp(tp),
, tp(tp) sentenceBuffer()
, sentenceBuffer()
{ {
} }
@ -77,7 +102,7 @@ void TextThread::AddSentence(std::wstring sentence)
void TextThread::AddText(const BYTE *con, int len) void TextThread::AddText(const BYTE *con, int len)
{ {
sentenceBuffer.insert(sentenceBuffer.end(), con, con+len); sentenceBuffer.insert(sentenceBuffer.end(), con, con+len);
SetTimer(dummyWindow, (UINT_PTR)this, settings->splittingInterval, SetTimer(dummyWindow, (UINT_PTR)this, splitDelay,
[](HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime) [](HWND hWnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
{ {
KillTimer(hWnd, idEvent); KillTimer(hWnd, idEvent);

View File

@ -23,13 +23,6 @@ struct ThreadParameter {
}; };
#define CURRENT_SELECT 0x1000 #define CURRENT_SELECT 0x1000
#define REPEAT_NUMBER_DECIDED 0x2000
#define BUFF_NEWLINE 0x4000
#define CYCLIC_REPEAT 0x8000
#define COUNT_PER_FOWARD 0x200
#define REPEAT_DETECT 0x10000
#define REPEAT_SUPPRESS 0x20000
#define REPEAT_NEWLINE 0x40000
class TextThread; class TextThread;
typedef DWORD (* ThreadOutputFilterCallback)(TextThread *,const BYTE *, DWORD, DWORD); typedef DWORD (* ThreadOutputFilterCallback)(TextThread *,const BYTE *, DWORD, DWORD);
@ -40,7 +33,7 @@ typedef DWORD (* ThreadEventCallback)(TextThread *);
class TextThread : public MyVector<BYTE, 0x200> class TextThread : public MyVector<BYTE, 0x200>
{ {
public: public:
TextThread(ThreadParameter tp, WORD num); TextThread(ThreadParameter tp, unsigned int threadNumber, unsigned int splitDelay);
virtual void GetEntryString(LPSTR buffer, DWORD max); virtual void GetEntryString(LPSTR buffer, DWORD max);
@ -64,10 +57,10 @@ public:
private: private:
ThreadParameter tp; ThreadParameter tp;
ThreadOutputFilterCallback output;
std::vector<char> sentenceBuffer; std::vector<char> sentenceBuffer;
unsigned int thread_number; unsigned int thread_number;
ThreadOutputFilterCallback output; unsigned int splitDelay;
DWORD status; DWORD status;
}; };

View File

@ -5,15 +5,6 @@
#include <windows.h> #include <windows.h>
template <typename T>
void Release(const T &p) { delete p; }
// Prevent memory release.
// Used when T is basic types and will be automatically released (on stack).
#define MK_BASIC_TYPE(T) \
template<> \
void Release<T>(const T &p) {}
template<class T, int default_size> template<class T, int default_size>
class MyVector class MyVector
{ {
@ -42,7 +33,7 @@ protected:
{ {
EnterCriticalSection(&cs_store); EnterCriticalSection(&cs_store);
for (int i = 0; i < used; i++) { for (int i = 0; i < used; i++) {
Release<T>(storage[i]); //Release<T>(storage[i]);
storage[i] = T(); storage[i] = T();
} }
used = 0; used = 0;
@ -52,7 +43,7 @@ protected:
{ {
if (index>=used) if (index>=used)
return; return;
Release<T>(storage[index]); //Release<T>(storage[index]);
for (int i = index; i < used; i++) for (int i = index; i < used; i++)
storage[i] = storage[i+1]; storage[i] = storage[i+1];
used--; used--;

View File

@ -248,6 +248,13 @@ enum {
, IHF_FILTER_CAPACITY = IHF_FILTER_COUNT + 1 // one more than the dll count , IHF_FILTER_CAPACITY = IHF_FILTER_COUNT + 1 // one more than the dll count
}; };
// jichi 12/25/2013: Header in each message sent to vnrsrv
// There are totally three elements
// - 0x0 dwAddr hook address
// - 0x4 dwRetn return address
// - 0x8 dwSplit split value
#define HEADER_SIZE 0xc
#define TIMEOUT 5000 // 5 seconds #define TIMEOUT 5000 // 5 seconds
// EOF // EOF

View File

@ -12,13 +12,6 @@
#include "include/types.h" #include "include/types.h"
#include <windows.h> #include <windows.h>
// jichi 12/25/2013: Header in each message sent to vnrsrv
// There are totally three elements
// - 0x0 dwAddr hook address
// - 0x4 dwRetn return address
// - 0x8 dwSplit split value
#define HEADER_SIZE 0xc
extern int currentHook; extern int currentHook;
extern WCHAR dll_mutex[]; extern WCHAR dll_mutex[];
//extern WCHAR dll_name[]; //extern WCHAR dll_name[];