forked from Public-Mirror/Textractor
delete unused files and start cleaning up code
This commit is contained in:
parent
6b63b91326
commit
38a57eb480
@ -75,9 +75,8 @@ void ProcessWindow::RefreshProcess()
|
|||||||
void ProcessWindow::AttachProcess()
|
void ProcessWindow::AttachProcess()
|
||||||
{
|
{
|
||||||
DWORD pid = GetSelectedPID();
|
DWORD pid = GetSelectedPID();
|
||||||
if (Host_InjectByPID(pid))
|
if (InjectProcessById(pid))
|
||||||
{
|
{
|
||||||
Host_HijackProcess(pid);
|
|
||||||
RefreshThreadWithPID(pid, true);
|
RefreshThreadWithPID(pid, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -85,7 +84,7 @@ void ProcessWindow::AttachProcess()
|
|||||||
void ProcessWindow::DetachProcess()
|
void ProcessWindow::DetachProcess()
|
||||||
{
|
{
|
||||||
DWORD pid = GetSelectedPID();
|
DWORD pid = GetSelectedPID();
|
||||||
if (Host_ActiveDetachProcess(pid) == 0)
|
if (DetachProcessById(pid) == 0)
|
||||||
RefreshThreadWithPID(pid, false);
|
RefreshThreadWithPID(pid, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -156,7 +156,7 @@ DWORD WINAPI InjectThread(LPVOID lpThreadParameter)
|
|||||||
Sleep(inject_delay);
|
Sleep(inject_delay);
|
||||||
if (man == NULL)
|
if (man == NULL)
|
||||||
return 0;
|
return 0;
|
||||||
DWORD status = Host_InjectByPID(pid);
|
DWORD status = InjectProcessById(pid);
|
||||||
if (!auto_insert)
|
if (!auto_insert)
|
||||||
return status;
|
return status;
|
||||||
if (status == -1)
|
if (status == -1)
|
||||||
|
@ -32,17 +32,10 @@ DWORD ProcessCommand(const std::wstring& cmd, DWORD pid)
|
|||||||
using std::regex_match;
|
using std::regex_match;
|
||||||
std::match_results<std::wstring::const_iterator> m;
|
std::match_results<std::wstring::const_iterator> m;
|
||||||
|
|
||||||
if (regex_match(cmd, m, wregex(L"/pn(.+)", wregex::icase)))
|
if (regex_match(cmd, m, wregex(L"/p(\\d+)", wregex::icase)))
|
||||||
{
|
|
||||||
pid = Host_GetPIDByName(m[1].str().c_str());
|
|
||||||
if (pid == 0)
|
|
||||||
return 0;
|
|
||||||
Host_InjectByPID(pid);
|
|
||||||
}
|
|
||||||
else if (regex_match(cmd, m, wregex(L"/p(\\d+)", wregex::icase)))
|
|
||||||
{
|
{
|
||||||
pid = std::stoul(m[1].str());
|
pid = std::stoul(m[1].str());
|
||||||
Host_InjectByPID(pid);
|
InjectProcessById(pid);
|
||||||
}
|
}
|
||||||
else if (regex_match(cmd, m, wregex(L"/h(.+)", wregex::icase)))
|
else if (regex_match(cmd, m, wregex(L"/h(.+)", wregex::icase)))
|
||||||
{
|
{
|
||||||
|
@ -246,7 +246,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
if (!IthInitSystemService())
|
if (!IthInitSystemService())
|
||||||
TerminateProcess(GetCurrentProcess(), 0);
|
TerminateProcess(GetCurrentProcess(), 0);
|
||||||
CreateMutex(NULL, TRUE, L"ITH_MAIN_RUNNING");
|
CreateMutex(NULL, TRUE, L"ITH_MAIN_RUNNING");
|
||||||
if (Host_Open())
|
if (OpenHost())
|
||||||
{
|
{
|
||||||
SetUnhandledExceptionFilter(UnhandledExcept);
|
SetUnhandledExceptionFilter(UnhandledExcept);
|
||||||
Host_GetHookManager(&man);
|
Host_GetHookManager(&man);
|
||||||
@ -280,7 +280,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
{
|
{
|
||||||
FindITH();
|
FindITH();
|
||||||
}
|
}
|
||||||
Host_Close();
|
CloseHost();
|
||||||
IthCloseSystemService();
|
IthCloseSystemService();
|
||||||
TerminateProcess(GetCurrentProcess(), 0);
|
TerminateProcess(GetCurrentProcess(), 0);
|
||||||
}
|
}
|
||||||
|
@ -753,7 +753,7 @@ LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
|
|||||||
man->RegisterProcessNewHookCallback(RefreshProfileOnNewHook);
|
man->RegisterProcessNewHookCallback(RefreshProfileOnNewHook);
|
||||||
man->RegisterAddRemoveLinkCallback(AddRemoveLink);
|
man->RegisterAddRemoveLinkCallback(AddRemoveLink);
|
||||||
man->RegisterConsoleCallback(ConsoleOutput);
|
man->RegisterConsoleCallback(ConsoleOutput);
|
||||||
Host_Start();
|
StartHost();
|
||||||
{
|
{
|
||||||
static const WCHAR program_name[] = L"Interactive Text Hooker";
|
static const WCHAR program_name[] = L"Interactive Text Hooker";
|
||||||
//static const WCHAR program_version[] = L"3.0";
|
//static const WCHAR program_version[] = L"3.0";
|
||||||
|
@ -246,7 +246,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
if (!IthInitSystemService())
|
if (!IthInitSystemService())
|
||||||
TerminateProcess(GetCurrentProcess(), 0);
|
TerminateProcess(GetCurrentProcess(), 0);
|
||||||
CreateMutex(NULL, TRUE, L"ITH_MAIN_RUNNING");
|
CreateMutex(NULL, TRUE, L"ITH_MAIN_RUNNING");
|
||||||
if (Host_Open())
|
if (OpenHost())
|
||||||
{
|
{
|
||||||
SetUnhandledExceptionFilter(UnhandledExcept);
|
SetUnhandledExceptionFilter(UnhandledExcept);
|
||||||
Host_GetHookManager(&man);
|
Host_GetHookManager(&man);
|
||||||
@ -280,7 +280,7 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine
|
|||||||
{
|
{
|
||||||
FindITH();
|
FindITH();
|
||||||
}
|
}
|
||||||
Host_Close();
|
CloseHost();
|
||||||
IthCloseSystemService();
|
IthCloseSystemService();
|
||||||
TerminateProcess(GetCurrentProcess(), 0);
|
TerminateProcess(GetCurrentProcess(), 0);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,11 @@
|
|||||||
// ccmacro.h
|
// ccmacro.h
|
||||||
// 12/9/2011 jichi
|
// 12/9/2011 jichi
|
||||||
|
|
||||||
|
#include <string>
|
||||||
|
|
||||||
|
#define CONCAT_STR_NUM(_str, _num) (std::wstring(_str) + std::to_wstring(_num)).c_str()
|
||||||
|
#define CONCAT_STR_STR(_str1, _str2) (std::wstring(_str1) + std::wstring(_str2)).c_str()
|
||||||
|
|
||||||
#define CC_UNUSED(_var) (void)(_var)
|
#define CC_UNUSED(_var) (void)(_var)
|
||||||
#define CC_NOP CC_UNUSED(0)
|
#define CC_NOP CC_UNUSED(0)
|
||||||
|
|
||||||
|
@ -19,23 +19,11 @@ set(vnrhost_src
|
|||||||
host.cc
|
host.cc
|
||||||
pipe.cc
|
pipe.cc
|
||||||
textthread.cc
|
textthread.cc
|
||||||
${PROJECT_SOURCE_DIR}/winmaker/winmaker.h
|
|
||||||
${PROJECT_SOURCE_DIR}/winmaker/winmaker.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/winmutex/winmutex.h
|
${PROJECT_SOURCE_DIR}/winmutex/winmutex.h
|
||||||
# ${PROJECT_SOURCE_DIR}/wintimer/wintimer.h
|
# ${PROJECT_SOURCE_DIR}/wintimer/wintimer.h
|
||||||
# ${PROJECT_SOURCE_DIR}/wintimer/wintimer.cc
|
# ${PROJECT_SOURCE_DIR}/wintimer/wintimer.cc
|
||||||
# ${PROJECT_SOURCE_DIR}/wintimer/wintimerbase.cc
|
# ${PROJECT_SOURCE_DIR}/wintimer/wintimerbase.cc
|
||||||
# ${PROJECT_SOURCE_DIR}/wintimer/wintimerbase.h
|
# ${PROJECT_SOURCE_DIR}/wintimer/wintimerbase.h
|
||||||
${PROJECT_SOURCE_DIR}/windbg/windbg.h
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/windbg_p.h
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/inject.h
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/inject.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/hijack.h
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/hijack.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/util.h
|
|
||||||
# ${PROJECT_SOURCE_DIR}/windbg/util.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/unload.h
|
|
||||||
${PROJECT_SOURCE_DIR}/windbg/unload.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/sakurakit/skdebug.h
|
${PROJECT_SOURCE_DIR}/sakurakit/skdebug.h
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -9,8 +9,6 @@
|
|||||||
#define IHFAPI __stdcall
|
#define IHFAPI __stdcall
|
||||||
#ifdef IHF
|
#ifdef IHF
|
||||||
# define IHFSERVICE __declspec(dllexport)
|
# define IHFSERVICE __declspec(dllexport)
|
||||||
#else
|
|
||||||
# define IHFSERVICE __declspec(dllimport)
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// EOF
|
// EOF
|
||||||
|
@ -16,8 +16,6 @@
|
|||||||
#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 "ithsys/ithsys.h"
|
||||||
#include "windbg/inject.h"
|
|
||||||
#include "winmaker/winmaker.h"
|
|
||||||
#include "ccutil/ccmacro.h"
|
#include "ccutil/ccmacro.h"
|
||||||
#include <commctrl.h>
|
#include <commctrl.h>
|
||||||
|
|
||||||
@ -28,234 +26,76 @@
|
|||||||
#define DEBUG "vnrhost/host.cc"
|
#define DEBUG "vnrhost/host.cc"
|
||||||
#include "sakurakit/skdebug.h"
|
#include "sakurakit/skdebug.h"
|
||||||
|
|
||||||
namespace { // unnamed
|
namespace
|
||||||
|
{ // unnamed
|
||||||
|
|
||||||
//enum { HOOK_TIMEOUT = -50000000 }; // in nanoseconds = 5 seconds
|
//enum { HOOK_TIMEOUT = -50000000 }; // in nanoseconds = 5 seconds
|
||||||
|
|
||||||
CRITICAL_SECTION cs;
|
CRITICAL_SECTION hostCs;
|
||||||
//WCHAR exist[] = ITH_PIPEEXISTS_EVENT;
|
//WCHAR exist[] = ITH_PIPEEXISTS_EVENT;
|
||||||
//WCHAR mutex[] = L"ITH_RUNNING";
|
//WCHAR mutex[] = L"ITH_RUNNING";
|
||||||
//WCHAR EngineName[] = ITH_ENGINE_DLL;
|
//WCHAR EngineName[] = ITH_ENGINE_DLL;
|
||||||
//WCHAR EngineNameXp[] = ITH_ENGINE_XP_DLL;
|
//WCHAR EngineNameXp[] = ITH_ENGINE_XP_DLL;
|
||||||
//WCHAR DllName[] = ITH_CLIENT_DLL;
|
//WCHAR DllName[] = ITH_CLIENT_DLL;
|
||||||
//WCHAR DllNameXp[] = ITH_CLIENT_XP_DLL;
|
//WCHAR DllNameXp[] = ITH_CLIENT_XP_DLL;
|
||||||
HANDLE hServerMutex; // jichi 9/28/2013: used to guard pipe
|
HANDLE preventDuplicationMutex; // jichi 9/28/2013: used to guard pipe
|
||||||
HANDLE hHookMutex; // jichi 9/28/2013: used to guard hook modification
|
HANDLE hookMutex; // jichi 9/28/2013: used to guard hook modification
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
//extern LPWSTR current_dir;
|
//extern LPWSTR current_dir;
|
||||||
extern CRITICAL_SECTION detach_cs;
|
extern CRITICAL_SECTION detachCs;
|
||||||
|
|
||||||
Settings *settings;
|
Settings *settings;
|
||||||
HWND hMainWnd;
|
HWND dummyWindow;
|
||||||
HANDLE hPipeExist;
|
HANDLE pipeExistsEvent;
|
||||||
BOOL running;
|
BOOL running;
|
||||||
|
|
||||||
#define ITH_SYNC_HOOK IthMutexLocker locker(::hHookMutex)
|
#define ITH_SYNC_HOOK IthMutexLocker locker(::hookMutex)
|
||||||
|
|
||||||
namespace { // unnamed
|
namespace
|
||||||
|
{ // unnamed
|
||||||
|
|
||||||
void GetDebugPriv()
|
void GetDebugPrivileges()
|
||||||
{
|
{
|
||||||
HANDLE hToken;
|
HANDLE processToken;
|
||||||
DWORD dwRet;
|
TOKEN_PRIVILEGES Privileges = { 1, {0x14, 0, SE_PRIVILEGE_ENABLED} };
|
||||||
NTSTATUS status;
|
|
||||||
|
|
||||||
TOKEN_PRIVILEGES Privileges = {1,{0x14,0,SE_PRIVILEGE_ENABLED}};
|
OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &processToken);
|
||||||
|
AdjustTokenPrivileges(processToken, FALSE, &Privileges, 0, nullptr, nullptr);
|
||||||
NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken);
|
CloseHandle(processToken);
|
||||||
|
|
||||||
status = NtAdjustPrivilegesToken(hToken, 0, &Privileges, sizeof(Privileges), 0, &dwRet);
|
|
||||||
//if (STATUS_SUCCESS == status)
|
|
||||||
//{
|
|
||||||
// admin = 1;
|
|
||||||
//}
|
|
||||||
//else
|
|
||||||
//{
|
|
||||||
// WCHAR buffer[0x10];
|
|
||||||
// swprintf(buffer, L"%.8X",status);
|
|
||||||
// MessageBox(0, NotAdmin, buffer, 0);
|
|
||||||
//}
|
|
||||||
NtClose(hToken);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool sendCommand(HANDLE hCmd, HostCommandType cmd)
|
|
||||||
{
|
|
||||||
IO_STATUS_BLOCK ios;
|
|
||||||
//SendParam sp = {};
|
|
||||||
//sp.type = cmd;
|
|
||||||
DWORD data = cmd;
|
|
||||||
return hCmd && NT_SUCCESS(NtWriteFile(hCmd, 0,0,0, &ios, &data, sizeof(data), 0,0));
|
|
||||||
}
|
|
||||||
|
|
||||||
// jichi 9/22/2013: Change current directory to the same as main module path
|
|
||||||
// Otherwise NtFile* would not work for files with relative paths.
|
|
||||||
//BOOL ChangeCurrentDirectory()
|
|
||||||
//{
|
|
||||||
// if (const wchar_t *path = GetMainModulePath()) // path to VNR's python exe
|
|
||||||
// if (const wchar_t *base = wcsrchr(path, L'\\')) {
|
|
||||||
// size_t len = base - path;
|
|
||||||
// if (len < MAX_PATH) {
|
|
||||||
// wchar_t buf[MAX_PATH];
|
|
||||||
// wcsncpy(buf, path, len);
|
|
||||||
// buf[len] = 0;
|
|
||||||
// return SetCurrentDirectoryW(buf);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return FALSE;
|
|
||||||
//}
|
|
||||||
|
|
||||||
#if 0
|
|
||||||
bool injectUsingWin32Api(LPCWSTR path, HANDLE hProc)
|
|
||||||
{ return WinDbg::injectDllW(path, 0, hProc); }
|
|
||||||
|
|
||||||
bool ejectUsingWin32Api(HANDLE hModule, HANDLE hProc)
|
|
||||||
{ return WinDbg::ejectDll(hModule, hProc); }
|
|
||||||
|
|
||||||
// The original inject logic in ITH
|
|
||||||
bool injectUsingNTApi(LPCWSTR path, HANDLE hProc)
|
|
||||||
{
|
|
||||||
LPVOID lpvAllocAddr = 0;
|
|
||||||
DWORD dwWrite = 0x1000; //, len = 0;
|
|
||||||
//if (IthIsWine())
|
|
||||||
// lpvAllocAddr = VirtualAllocEx(hProc, nullptr, dwWrite, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
//else
|
|
||||||
NtAllocateVirtualMemory(hProc, &lpvAllocAddr, 0, &dwWrite, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
if (!lpvAllocAddr)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
CheckThreadStart();
|
|
||||||
|
|
||||||
//Copy module path into address space of target process.
|
|
||||||
//if (IthIsWine())
|
|
||||||
// WriteProcessMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);
|
|
||||||
//else
|
|
||||||
NtWriteVirtualMemory(hProc, lpvAllocAddr, (LPVOID)path, MAX_PATH << 1, &dwWrite);
|
|
||||||
HANDLE hTH = IthCreateThread(LoadLibraryW, (DWORD)lpvAllocAddr, hProc);
|
|
||||||
if (hTH == 0 || hTH == INVALID_HANDLE_VALUE) {
|
|
||||||
DOUT("ERROR: failed to create remote cli thread");
|
|
||||||
//ConsoleOutput(ErrorRemoteThread);
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
// jichi 9/28/2013: no wait as it will not blocked
|
|
||||||
NtWaitForSingleObject(hTH, 0, nullptr);
|
|
||||||
THREAD_BASIC_INFORMATION info;
|
|
||||||
NtQueryInformationThread(hTH, ThreadBasicInformation, &info, sizeof(info), &dwWrite);
|
|
||||||
NtClose(hTH);
|
|
||||||
|
|
||||||
// jichi 10/19/2014: Disable inject the second dll
|
bool sendCommand(HANDLE commandPipe, HostCommandType command)
|
||||||
//if (info.ExitStatus) {
|
{
|
||||||
// //IthCoolDown();
|
DWORD unused;
|
||||||
// wcscpy(p, engine);
|
return commandPipe && WriteFile(commandPipe, &command, sizeof(command), &unused, nullptr);
|
||||||
// //if (IthIsWine())
|
}
|
||||||
// // WriteProcessMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);
|
|
||||||
// //else
|
|
||||||
// NtWriteVirtualMemory(hProc, lpvAllocAddr, path, MAX_PATH << 1, &dwWrite);
|
|
||||||
// hTH = IthCreateThread(LoadLibraryW, (DWORD)lpvAllocAddr, hProc);
|
|
||||||
// if (hTH == 0 || hTH == INVALID_HANDLE_VALUE) {
|
|
||||||
// //ConsoleOutput(ErrorRemoteThread);
|
|
||||||
// ConsoleOutput("vnrhost:inject: ERROR: failed to create remote eng thread");
|
|
||||||
// return error;
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// // jichi 9/28/2013: no wait as it will not blocked
|
|
||||||
// NtWaitForSingleObject(hTH, 0, nullptr);
|
|
||||||
// NtClose(hTH);
|
|
||||||
//}
|
|
||||||
|
|
||||||
dwWrite = 0;
|
|
||||||
//if (IthIsWine())
|
|
||||||
// VirtualFreeEx(hProc, lpvAllocAddr, dwWrite, MEM_RELEASE);
|
|
||||||
//else
|
|
||||||
NtFreeVirtualMemory(hProc, &lpvAllocAddr, &dwWrite, MEM_RELEASE);
|
|
||||||
return info.ExitStatus != -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ejectUsingNTApi(HANDLE hModule, HANDLE hProc)
|
|
||||||
{
|
|
||||||
//IthCoolDown();
|
|
||||||
//#ifdef ITH_WINE // Nt series crash on wine
|
|
||||||
// hThread = IthCreateThread(FreeLibrary, engine, hProc);
|
|
||||||
//#else
|
|
||||||
HANDLE hThread = IthCreateThread(LdrUnloadDll, module, hProc);
|
|
||||||
//#endif // ITH_WINE
|
|
||||||
if (hThread == 0 || hThread == INVALID_HANDLE_VALUE)
|
|
||||||
return false;
|
|
||||||
// jichi 10/22/2013: Timeout might crash vnrsrv
|
|
||||||
//NtWaitForSingleObject(hThread, 0, (PLARGE_INTEGER)&timeout);
|
|
||||||
NtWaitForSingleObject(hThread, 0, nullptr);
|
|
||||||
//man->UnlockHookman();
|
|
||||||
THREAD_BASIC_INFORMATION info;
|
|
||||||
NtQueryInformationThread(hThread, ThreadBasicInformation, &info, sizeof(info), 0);
|
|
||||||
NtClose(hThread);
|
|
||||||
NtSetEvent(hPipeExist, 0);
|
|
||||||
FreeThreadStart(hProc);
|
|
||||||
return info.ExitStatus;
|
|
||||||
}
|
|
||||||
#endif // 0
|
|
||||||
|
|
||||||
bool Inject(HANDLE hProc)
|
|
||||||
{
|
|
||||||
//LPWSTR dllname = (IthIsWindowsXp() && !IthIsWine()) ? DllNameXp : DllName;
|
|
||||||
//LPCWSTR dllname = ITH_USE_XP_DLLS ? ITH_DLL_XP : ITH_DLL;
|
|
||||||
//LPCWSTR dllname = ITH_DLL;
|
|
||||||
//if (!IthCheckFile(dllname))
|
|
||||||
// return error;
|
|
||||||
wchar_t path[MAX_PATH];
|
|
||||||
size_t len = IthGetCurrentModulePath(path, MAX_PATH);
|
|
||||||
if (!len)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
wchar_t *p;
|
|
||||||
for (p = path + len; *p != L'\\'; p--);
|
|
||||||
p++; // ending with L"\\"
|
|
||||||
|
|
||||||
//LPCWSTR mp = GetMainModulePath();
|
|
||||||
//len = wcslen(mp);
|
|
||||||
//memcpy(path, mp, len << 1);
|
|
||||||
//memset(path + len, 0, (MAX_PATH - len) << 1);
|
|
||||||
//LPWSTR p;
|
|
||||||
//for (p = path + len; *p != L'\\'; p--); // Always a \ after drive letter.
|
|
||||||
//p++;
|
|
||||||
::wcscpy(p, ITH_DLL);
|
|
||||||
|
|
||||||
return WinDbg::injectDllW(path, 0, hProc);
|
|
||||||
//if (IthIsWindowsXp()) // && !IthIsWine())
|
|
||||||
// return injectUsingWin32Api(path, hProc);
|
|
||||||
//else
|
|
||||||
// return injectUsingNTApi(path, hProc);
|
|
||||||
}
|
|
||||||
|
|
||||||
} // unnamed namespace
|
} // unnamed namespace
|
||||||
|
|
||||||
void CreateNewPipe();
|
void CreateNewPipe();
|
||||||
|
|
||||||
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID unused)
|
||||||
{
|
{
|
||||||
CC_UNUSED(lpvReserved);
|
|
||||||
switch (fdwReason)
|
switch (fdwReason)
|
||||||
{
|
{
|
||||||
case DLL_PROCESS_ATTACH:
|
case DLL_PROCESS_ATTACH:
|
||||||
LdrDisableThreadCalloutsForDll(hinstDLL);
|
DisableThreadLibraryCalls(hinstDLL);
|
||||||
InitializeCriticalSection(&::cs);
|
InitializeCriticalSection(&::hostCs);
|
||||||
IthInitSystemService();
|
IthInitSystemService();
|
||||||
GetDebugPriv();
|
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.
|
||||||
InitCommonControls();
|
InitCommonControls();
|
||||||
// jichi 8/24/2013: Create hidden window so that ITH can access timer and events
|
// jichi 8/24/2013: Create hidden window so that ITH can access timer and events
|
||||||
hMainWnd = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0);
|
dummyWindow = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0);
|
||||||
//wm_register_hidden_class("vnrsrv.class");
|
|
||||||
//hMainWnd = (HWND)wm_create_hidden_window("vnrsrv", "Button", hinstDLL);
|
|
||||||
//ChangeCurrentDirectory();
|
|
||||||
break;
|
break;
|
||||||
case DLL_PROCESS_DETACH:
|
case DLL_PROCESS_DETACH:
|
||||||
if (::running)
|
if (::running)
|
||||||
Host_Close();
|
CloseHost();
|
||||||
DeleteCriticalSection(&::cs);
|
DeleteCriticalSection(&::hostCs);
|
||||||
IthCloseSystemService();
|
IthCloseSystemService();
|
||||||
//wm_destroy_window(hMainWnd);
|
DestroyWindow(dummyWindow);
|
||||||
DestroyWindow(hMainWnd);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -263,20 +103,6 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
HANDLE IthOpenPipe(LPWSTR name, ACCESS_MASK direction)
|
|
||||||
{
|
|
||||||
UNICODE_STRING us;
|
|
||||||
RtlInitUnicodeString(&us, name);
|
|
||||||
SECURITY_DESCRIPTOR sd = {1};
|
|
||||||
OBJECT_ATTRIBUTES oa = {sizeof(oa), 0, &us, OBJ_CASE_INSENSITIVE, &sd, 0};
|
|
||||||
HANDLE hFile;
|
|
||||||
IO_STATUS_BLOCK isb;
|
|
||||||
if (NT_SUCCESS(NtCreateFile(&hFile, direction, &oa, &isb, 0, 0, FILE_SHARE_READ, FILE_OPEN, 0, 0, 0)))
|
|
||||||
return hFile;
|
|
||||||
else
|
|
||||||
return INVALID_HANDLE_VALUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
enum { IHS_SIZE = 0x80 };
|
enum { IHS_SIZE = 0x80 };
|
||||||
enum { IHS_BUFF_SIZE = IHS_SIZE - sizeof(HookParam) };
|
enum { IHS_BUFF_SIZE = IHS_SIZE - sizeof(HookParam) };
|
||||||
|
|
||||||
@ -286,188 +112,131 @@ struct InsertHookStruct
|
|||||||
BYTE name_buffer[IHS_SIZE];
|
BYTE name_buffer[IHS_SIZE];
|
||||||
};
|
};
|
||||||
|
|
||||||
IHFSERVICE void IHFAPI Host_Init()
|
IHFSERVICE bool IHFAPI OpenHost()
|
||||||
{
|
{
|
||||||
InitializeCriticalSection(&::cs);
|
bool success;
|
||||||
GetDebugPriv();
|
EnterCriticalSection(&::hostCs);
|
||||||
}
|
|
||||||
|
|
||||||
IHFSERVICE void IHFAPI Host_Destroy()
|
preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX);
|
||||||
{
|
if (GetLastError() == ERROR_ALREADY_EXISTS || ::running)
|
||||||
InitializeCriticalSection(&::cs);
|
{
|
||||||
}
|
|
||||||
|
|
||||||
IHFSERVICE BOOL IHFAPI Host_Open()
|
|
||||||
{
|
|
||||||
BOOL result = false;
|
|
||||||
EnterCriticalSection(&::cs);
|
|
||||||
DWORD present;
|
|
||||||
hServerMutex = IthCreateMutex(ITH_SERVER_MUTEX, 1, &present);
|
|
||||||
if (present)
|
|
||||||
//MessageBox(0,L"Already running.",0,0);
|
|
||||||
// jichi 8/24/2013
|
|
||||||
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!");
|
||||||
else if (!::running) {
|
success = false;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
::running = true;
|
::running = true;
|
||||||
::settings = new Settings;
|
::settings = new Settings;
|
||||||
::man = new HookManager;
|
::man = new HookManager;
|
||||||
//cmdq = new CommandQueue;
|
InitializeCriticalSection(&detachCs);
|
||||||
InitializeCriticalSection(&detach_cs);
|
::hookMutex = CreateMutexW(nullptr, FALSE, ITH_SERVER_HOOK_MUTEX);
|
||||||
|
success = true;
|
||||||
::hHookMutex = IthCreateMutex(ITH_SERVER_HOOK_MUTEX, FALSE);
|
|
||||||
result = true;
|
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&::cs);
|
LeaveCriticalSection(&::hostCs);
|
||||||
return result;
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
IHFSERVICE DWORD IHFAPI Host_Start()
|
IHFSERVICE void IHFAPI StartHost()
|
||||||
{
|
{
|
||||||
//IthBreak();
|
|
||||||
CreateNewPipe();
|
CreateNewPipe();
|
||||||
::hPipeExist = IthCreateEvent(ITH_PIPEEXISTS_EVENT);
|
::pipeExistsEvent = CreateEventW(nullptr, TRUE, TRUE, ITH_PIPEEXISTS_EVENT);
|
||||||
NtSetEvent(::hPipeExist, nullptr);
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IHFSERVICE DWORD IHFAPI Host_Close()
|
IHFSERVICE void IHFAPI CloseHost()
|
||||||
{
|
{
|
||||||
BOOL result = FALSE;
|
EnterCriticalSection(&::hostCs);
|
||||||
EnterCriticalSection(&::cs);
|
if (::running)
|
||||||
if (::running) {
|
{
|
||||||
::running = FALSE;
|
::running = FALSE;
|
||||||
HANDLE hRecvPipe = IthOpenPipe(recv_pipe, GENERIC_WRITE);
|
ResetEvent(::pipeExistsEvent);
|
||||||
NtClose(hRecvPipe);
|
|
||||||
NtClearEvent(::hPipeExist);
|
|
||||||
//delete cmdq;
|
|
||||||
delete man;
|
delete man;
|
||||||
delete settings;
|
delete settings;
|
||||||
NtClose(::hHookMutex);
|
CloseHandle(::hookMutex);
|
||||||
NtClose(hServerMutex);
|
CloseHandle(preventDuplicationMutex);
|
||||||
NtClose(::hPipeExist);
|
CloseHandle(::pipeExistsEvent);
|
||||||
DeleteCriticalSection(&detach_cs);
|
DeleteCriticalSection(&detachCs);
|
||||||
result = TRUE;
|
|
||||||
}
|
}
|
||||||
LeaveCriticalSection(&::cs);
|
LeaveCriticalSection(&::hostCs);
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
IHFSERVICE DWORD IHFAPI Host_GetPIDByName(LPCWSTR pwcTarget)
|
IHFSERVICE bool IHFAPI InjectProcessById(DWORD processId, DWORD timeout)
|
||||||
{
|
{
|
||||||
DWORD dwSize = 0x20000,
|
bool success = true;
|
||||||
dwExpectSize = 0;
|
|
||||||
LPVOID pBuffer = 0;
|
|
||||||
SYSTEM_PROCESS_INFORMATION *spiProcessInfo;
|
|
||||||
DWORD dwPid = 0;
|
|
||||||
DWORD dwStatus;
|
|
||||||
|
|
||||||
NtAllocateVirtualMemory(NtCurrentProcess(), &pBuffer, 0, &dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
if (processId == GetCurrentProcessId())
|
||||||
dwStatus = NtQuerySystemInformation(SystemProcessInformation, pBuffer, dwSize, &dwExpectSize);
|
{
|
||||||
if (!NT_SUCCESS(dwStatus)) {
|
success = false;
|
||||||
NtFreeVirtualMemory(NtCurrentProcess(),&pBuffer,&dwSize,MEM_RELEASE);
|
|
||||||
if (dwStatus != STATUS_INFO_LENGTH_MISMATCH || dwExpectSize < dwSize)
|
|
||||||
return 0;
|
|
||||||
dwSize = (dwExpectSize | 0xFFF) + 0x4001; //
|
|
||||||
pBuffer = 0;
|
|
||||||
NtAllocateVirtualMemory(NtCurrentProcess(), &pBuffer, 0, &dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE);
|
|
||||||
dwStatus = NtQuerySystemInformation(SystemProcessInformation, pBuffer, dwSize, &dwExpectSize);
|
|
||||||
if (!NT_SUCCESS(dwStatus)) goto _end;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (spiProcessInfo = (SYSTEM_PROCESS_INFORMATION *)pBuffer; spiProcessInfo->dNext;) {
|
CloseHandle(CreateMutexW(nullptr, FALSE, CONCAT_STR_NUM(ITH_HOOKMAN_MUTEX_, processId)));
|
||||||
spiProcessInfo = (SYSTEM_PROCESS_INFORMATION *)
|
if (GetLastError() == ERROR_ALREADY_EXISTS)
|
||||||
((DWORD)spiProcessInfo + spiProcessInfo -> dNext);
|
{
|
||||||
if (_wcsicmp(pwcTarget, spiProcessInfo -> usName.Buffer) == 0) {
|
man->AddConsoleOutput(L"already locked");
|
||||||
dwPid = spiProcessInfo->dUniqueProcessId;
|
success = false;
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!dwPid)
|
|
||||||
DOUT("pid not found");
|
|
||||||
//if (dwPid == 0) ConsoleOutput(ErrorNoProcess);
|
|
||||||
_end:
|
|
||||||
NtFreeVirtualMemory(NtCurrentProcess(),&pBuffer,&dwSize,MEM_RELEASE);
|
|
||||||
return dwPid;
|
|
||||||
}
|
|
||||||
|
|
||||||
IHFSERVICE bool IHFAPI Host_InjectByPID(DWORD pid)
|
|
||||||
{
|
|
||||||
WCHAR str[0x80];
|
|
||||||
if (!::running)
|
|
||||||
return 0;
|
|
||||||
if (pid == current_process_id) {
|
|
||||||
//ConsoleOutput(SelfAttach);
|
|
||||||
DOUT("refuse to inject myself");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (man->GetProcessRecord(pid)) {
|
|
||||||
//ConsoleOutput(AlreadyAttach);
|
|
||||||
DOUT("already attached");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
swprintf(str, ITH_HOOKMAN_MUTEX_ L"%d", pid);
|
|
||||||
DWORD s;
|
|
||||||
NtClose(IthCreateMutex(str, 0, &s));
|
|
||||||
if (s) {
|
|
||||||
DOUT("already locked");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
CLIENT_ID id;
|
|
||||||
OBJECT_ATTRIBUTES oa = {};
|
|
||||||
HANDLE hProc;
|
|
||||||
id.UniqueProcess = pid;
|
|
||||||
id.UniqueThread = 0;
|
|
||||||
oa.uLength = sizeof(oa);
|
|
||||||
if (!NT_SUCCESS(NtOpenProcess(&hProc,
|
|
||||||
PROCESS_QUERY_INFORMATION|
|
|
||||||
PROCESS_CREATE_THREAD|
|
|
||||||
PROCESS_VM_OPERATION|
|
|
||||||
PROCESS_VM_READ|
|
|
||||||
PROCESS_VM_WRITE,
|
|
||||||
&oa, &id))) {
|
|
||||||
//ConsoleOutput(ErrorOpenProcess);
|
|
||||||
DOUT("failed to open process");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//if (!engine)
|
HMODULE textHooker = LoadLibraryExW(L"vnrhook", nullptr, DONT_RESOLVE_DLL_REFERENCES);
|
||||||
// engine = ITH_USE_XP_DLLS ? ITH_ENGINE_XP_DLL : ITH_ENGINE_DLL;
|
if (textHooker == nullptr)
|
||||||
bool ok = Inject(hProc);
|
{
|
||||||
//NtClose(hProc); //already closed
|
success = false;
|
||||||
if (!ok) {
|
|
||||||
DOUT("inject failed");
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
//swprintf(str, FormatInject, pid, module);
|
wchar_t textHookerPath[MAX_PATH];
|
||||||
//ConsoleOutput(str);
|
unsigned int textHookerPathSize = GetModuleFileNameW(textHooker, textHookerPath, MAX_PATH) * 2 + 2;
|
||||||
DOUT("inject succeed");
|
FreeLibrary(textHooker);
|
||||||
return true;
|
|
||||||
|
HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
|
||||||
|
if (processHandle == INVALID_HANDLE_VALUE || processHandle == nullptr)
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void* loadLibraryStartRoutine = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW");
|
||||||
|
|
||||||
|
if (success)
|
||||||
|
{
|
||||||
|
if (LPVOID remoteData = VirtualAllocEx(processHandle, nullptr, textHookerPathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
|
||||||
|
{
|
||||||
|
if (WriteProcessMemory(processHandle, remoteData, textHookerPath, textHookerPathSize, nullptr))
|
||||||
|
{
|
||||||
|
if (HANDLE thread = CreateRemoteThread(processHandle, nullptr, 0, (LPTHREAD_START_ROUTINE)loadLibraryStartRoutine, remoteData, 0, nullptr))
|
||||||
|
{
|
||||||
|
WaitForSingleObject(thread, timeout);
|
||||||
|
CloseHandle(thread);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
VirtualFreeEx(processHandle, remoteData, textHookerPathSize, MEM_RELEASE);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!success)
|
||||||
|
{
|
||||||
|
man->AddConsoleOutput(L"error: could not inject");
|
||||||
|
}
|
||||||
|
|
||||||
|
CloseHandle(processHandle);
|
||||||
|
return success;
|
||||||
}
|
}
|
||||||
|
|
||||||
// jichi 7/16/2014: Test if process is valid before creating remote threads
|
// jichi 7/16/2014: Test if process is valid before creating remote threads
|
||||||
// See: http://msdn.microsoft.com/en-us/library/ms687032.aspx
|
// See: http://msdn.microsoft.com/en-us/library/ms687032.aspx
|
||||||
static bool isProcessTerminated(HANDLE hProc)
|
static bool isProcessTerminated(HANDLE processHandle)
|
||||||
{ return WAIT_OBJECT_0 == ::WaitForSingleObject(hProc, 0); }
|
{
|
||||||
//static bool isProcessRunning(HANDLE hProc)
|
return WAIT_OBJECT_0 == ::WaitForSingleObject(processHandle, 0);
|
||||||
//{ return WAIT_TIMEOUT == ::WaitForSingleObject(hProc, 0); }
|
}
|
||||||
|
|
||||||
// jichi 7/16/2014: Test if process is valid before creating remote threads
|
IHFSERVICE bool IHFAPI DetachProcessById(DWORD pid) // Todo: clean this up
|
||||||
//static bool isProcessRunning(DWORD pid)
|
|
||||||
//{
|
|
||||||
// bool ret = false;
|
|
||||||
// HANDLE hProc = ::OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, pid);
|
|
||||||
// if (hProc) {
|
|
||||||
// DWORD status;
|
|
||||||
// if (::GetExitCodeProcess(hProc, &status)) {
|
|
||||||
// ret = status == STILL_ACTIVE;
|
|
||||||
// ::CloseHandle(hProc);
|
|
||||||
// } else
|
|
||||||
// ret = true;
|
|
||||||
// }
|
|
||||||
// return ret;
|
|
||||||
//}
|
|
||||||
|
|
||||||
IHFSERVICE bool IHFAPI Host_ActiveDetachProcess(DWORD pid)
|
|
||||||
{
|
{
|
||||||
ITH_SYNC_HOOK;
|
ITH_SYNC_HOOK;
|
||||||
|
|
||||||
@ -543,13 +312,6 @@ IHFSERVICE bool IHFAPI Host_GetSettings(Settings **p)
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
IHFSERVICE bool IHFAPI Host_HijackProcess(DWORD pid)
|
|
||||||
{
|
|
||||||
//ITH_SYNC_HOOK;
|
|
||||||
HANDLE hCmd = man->GetCmdHandleByPID(pid);
|
|
||||||
return hCmd && sendCommand(hCmd, HOST_COMMAND_HIJACK_PROCESS);
|
|
||||||
}
|
|
||||||
|
|
||||||
IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name)
|
IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name)
|
||||||
{
|
{
|
||||||
ITH_SYNC_HOOK;
|
ITH_SYNC_HOOK;
|
||||||
|
@ -14,14 +14,14 @@ struct HookParam;
|
|||||||
IHFSERVICE void IHFAPI Host_Init();
|
IHFSERVICE void IHFAPI Host_Init();
|
||||||
IHFSERVICE void IHFAPI Host_Destroy();
|
IHFSERVICE void IHFAPI Host_Destroy();
|
||||||
|
|
||||||
IHFSERVICE DWORD IHFAPI Host_Start();
|
IHFSERVICE void IHFAPI StartHost();
|
||||||
IHFSERVICE BOOL IHFAPI Host_Open();
|
IHFSERVICE bool IHFAPI OpenHost();
|
||||||
IHFSERVICE DWORD IHFAPI Host_Close();
|
IHFSERVICE void IHFAPI CloseHost();
|
||||||
IHFSERVICE DWORD IHFAPI Host_GetHookManager(HookManager **hookman);
|
IHFSERVICE DWORD IHFAPI Host_GetHookManager(HookManager **hookman);
|
||||||
IHFSERVICE bool IHFAPI Host_GetSettings(Settings **settings);
|
IHFSERVICE bool IHFAPI Host_GetSettings(Settings **settings);
|
||||||
IHFSERVICE DWORD IHFAPI Host_GetPIDByName(LPCWSTR pwcTarget);
|
IHFSERVICE DWORD IHFAPI Host_GetPIDByName(LPCWSTR pwcTarget);
|
||||||
IHFSERVICE bool IHFAPI Host_InjectByPID(DWORD pid);
|
IHFSERVICE bool IHFAPI InjectProcessById(DWORD pid, DWORD timeout = 5000);
|
||||||
IHFSERVICE bool IHFAPI Host_ActiveDetachProcess(DWORD pid);
|
IHFSERVICE bool IHFAPI DetachProcessById(DWORD pid);
|
||||||
IHFSERVICE bool IHFAPI Host_HijackProcess(DWORD pid);
|
IHFSERVICE bool IHFAPI Host_HijackProcess(DWORD pid);
|
||||||
IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name = nullptr);
|
IHFSERVICE DWORD IHFAPI Host_InsertHook(DWORD pid, HookParam *hp, LPCSTR name = nullptr);
|
||||||
IHFSERVICE DWORD IHFAPI Host_ModifyHook(DWORD pid, HookParam *hp);
|
IHFSERVICE DWORD IHFAPI Host_ModifyHook(DWORD pid, HookParam *hp);
|
||||||
|
@ -3,6 +3,7 @@
|
|||||||
// 8/24/2013 jichi
|
// 8/24/2013 jichi
|
||||||
// Branch IHF/main.h, rev 111
|
// Branch IHF/main.h, rev 111
|
||||||
#include <windows.h>
|
#include <windows.h>
|
||||||
|
#include <tlhelp32.h>
|
||||||
|
|
||||||
#define GLOBAL extern
|
#define GLOBAL extern
|
||||||
#define SHIFT_JIS 0x3A4
|
#define SHIFT_JIS 0x3A4
|
||||||
@ -23,12 +24,12 @@ GLOBAL HookManager *man;
|
|||||||
GLOBAL SettingManager *setman;
|
GLOBAL SettingManager *setman;
|
||||||
GLOBAL WCHAR recv_pipe[];
|
GLOBAL WCHAR recv_pipe[];
|
||||||
GLOBAL WCHAR command[];
|
GLOBAL WCHAR command[];
|
||||||
GLOBAL HANDLE hPipeExist;
|
GLOBAL HANDLE pipeExistsEvent;
|
||||||
GLOBAL DWORD split_time,
|
GLOBAL DWORD split_time,
|
||||||
cyclic_remove,
|
cyclic_remove,
|
||||||
clipboard_flag,
|
clipboard_flag,
|
||||||
global_filter;
|
global_filter;
|
||||||
GLOBAL CRITICAL_SECTION detach_cs;
|
GLOBAL CRITICAL_SECTION detachCs;
|
||||||
|
|
||||||
DWORD WINAPI RecvThread(LPVOID lpThreadParameter);
|
DWORD WINAPI RecvThread(LPVOID lpThreadParameter);
|
||||||
DWORD WINAPI CmdThread(LPVOID lpThreadParameter);
|
DWORD WINAPI CmdThread(LPVOID lpThreadParameter);
|
||||||
|
@ -69,9 +69,9 @@ const BYTE *Filter(const BYTE *str, int len)
|
|||||||
wchar_t recv_pipe[] = ITH_TEXT_PIPE;
|
wchar_t recv_pipe[] = ITH_TEXT_PIPE;
|
||||||
wchar_t command_pipe[] = ITH_COMMAND_PIPE;
|
wchar_t command_pipe[] = ITH_COMMAND_PIPE;
|
||||||
|
|
||||||
CRITICAL_SECTION detach_cs; // jichi 9/27/2013: also used in main
|
CRITICAL_SECTION detachCs; // jichi 9/27/2013: also used in main
|
||||||
//HANDLE hDetachEvent;
|
//HANDLE hDetachEvent;
|
||||||
extern HANDLE hPipeExist;
|
extern HANDLE pipeExistsEvent;
|
||||||
|
|
||||||
void CreateNewPipe()
|
void CreateNewPipe()
|
||||||
{
|
{
|
||||||
@ -176,7 +176,7 @@ void DetachFromProcess(DWORD pid)
|
|||||||
|
|
||||||
//NtSetEvent(hDetachEvent, 0);
|
//NtSetEvent(hDetachEvent, 0);
|
||||||
if (::running)
|
if (::running)
|
||||||
NtSetEvent(hPipeExist, 0);
|
NtSetEvent(pipeExistsEvent, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
// jichi 9/27/2013: I don't need this
|
// jichi 9/27/2013: I don't need this
|
||||||
@ -291,7 +291,7 @@ DWORD WINAPI RecvThread(LPVOID lpThreadParameter)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
EnterCriticalSection(&detach_cs);
|
EnterCriticalSection(&detachCs);
|
||||||
|
|
||||||
HANDLE hDisconnect = IthCreateEvent(nullptr);
|
HANDLE hDisconnect = IthCreateEvent(nullptr);
|
||||||
|
|
||||||
@ -310,7 +310,7 @@ DWORD WINAPI RecvThread(LPVOID lpThreadParameter)
|
|||||||
|
|
||||||
//NtClearEvent(hDetachEvent);
|
//NtClearEvent(hDetachEvent);
|
||||||
|
|
||||||
LeaveCriticalSection(&detach_cs);
|
LeaveCriticalSection(&detachCs);
|
||||||
delete[] buff;
|
delete[] buff;
|
||||||
|
|
||||||
if (::running)
|
if (::running)
|
||||||
|
@ -31,7 +31,7 @@ static DWORD MIN_REDETECT = 0x80;
|
|||||||
DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr,DWORD max);
|
DWORD GetHookName(LPSTR str, DWORD pid, DWORD hook_addr,DWORD max);
|
||||||
|
|
||||||
extern Settings *settings;
|
extern Settings *settings;
|
||||||
extern HWND hMainWnd;
|
extern HWND dummyWindow;
|
||||||
void CALLBACK NewLineBuff(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
void CALLBACK NewLineBuff(HWND hwnd, UINT uMsg, UINT_PTR idEvent, DWORD dwTime)
|
||||||
{
|
{
|
||||||
KillTimer(hwnd,idEvent);
|
KillTimer(hwnd,idEvent);
|
||||||
@ -103,7 +103,7 @@ TextThread::TextThread(DWORD id, DWORD hook, DWORD retn, DWORD spl, WORD num) :
|
|||||||
}
|
}
|
||||||
TextThread::~TextThread()
|
TextThread::~TextThread()
|
||||||
{
|
{
|
||||||
//KillTimer(hMainWnd,timer);
|
//KillTimer(dummyWindow,timer);
|
||||||
RepeatCountNode *t = head,
|
RepeatCountNode *t = head,
|
||||||
*tt;
|
*tt;
|
||||||
while (t) {
|
while (t) {
|
||||||
@ -744,9 +744,9 @@ void TextThread::SetNewLineTimer()
|
|||||||
{
|
{
|
||||||
if (thread_number == 0)
|
if (thread_number == 0)
|
||||||
// jichi 10/27/2013: Not used
|
// jichi 10/27/2013: Not used
|
||||||
timer = 0; //SetTimer(hMainWnd,(UINT_PTR)this, settings->splittingInterval, NewLineConsole);
|
timer = 0; //SetTimer(dummyWindow,(UINT_PTR)this, settings->splittingInterval, NewLineConsole);
|
||||||
else
|
else
|
||||||
timer = SetTimer(hMainWnd, (UINT_PTR)this, settings->splittingInterval, NewLineBuff);
|
timer = SetTimer(dummyWindow, (UINT_PTR)this, settings->splittingInterval, NewLineBuff);
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD TextThread::GetThreadString(LPSTR str, DWORD max)
|
DWORD TextThread::GetThreadString(LPSTR str, DWORD max)
|
||||||
|
@ -59,13 +59,8 @@ set(vnrhook_src
|
|||||||
${PROJECT_SOURCE_DIR}/memdbg/memsearch.h
|
${PROJECT_SOURCE_DIR}/memdbg/memsearch.h
|
||||||
${PROJECT_SOURCE_DIR}/ntinspect/ntinspect.cc
|
${PROJECT_SOURCE_DIR}/ntinspect/ntinspect.cc
|
||||||
${PROJECT_SOURCE_DIR}/ntinspect/ntinspect.h
|
${PROJECT_SOURCE_DIR}/ntinspect/ntinspect.h
|
||||||
${PROJECT_SOURCE_DIR}/winkey/winkey.h
|
|
||||||
${PROJECT_SOURCE_DIR}/winversion/winversion.cc
|
${PROJECT_SOURCE_DIR}/winversion/winversion.cc
|
||||||
${PROJECT_SOURCE_DIR}/winversion/winversion.h
|
${PROJECT_SOURCE_DIR}/winversion/winversion.h
|
||||||
${PROJECT_SOURCE_DIR}/winseh/winseh.h
|
|
||||||
${PROJECT_SOURCE_DIR}/winseh/winseh.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/winseh/winseh_safe.cc
|
|
||||||
${PROJECT_SOURCE_DIR}/winseh/safeseh.asm
|
|
||||||
${PROJECT_SOURCE_DIR}/mono/monoobject.h
|
${PROJECT_SOURCE_DIR}/mono/monoobject.h
|
||||||
${PROJECT_SOURCE_DIR}/mono/monotype.h
|
${PROJECT_SOURCE_DIR}/mono/monotype.h
|
||||||
)
|
)
|
||||||
|
@ -15,7 +15,6 @@
|
|||||||
#include "src/main.h"
|
#include "src/main.h"
|
||||||
#include "include/const.h"
|
#include "include/const.h"
|
||||||
#include "ithsys/ithsys.h"
|
#include "ithsys/ithsys.h"
|
||||||
#include "winkey/winkey.h"
|
|
||||||
#include "disasm/disasm.h"
|
#include "disasm/disasm.h"
|
||||||
//#include "winseh/winseh.h"
|
//#include "winseh/winseh.h"
|
||||||
|
|
||||||
|
@ -1,89 +0,0 @@
|
|||||||
// hijack.cc
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
#include "windbg/hijack.h"
|
|
||||||
#include "windbg/windbg_p.h"
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning (disable:4996) // C4996: use POSIX function (stricmp)
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
//#define DEBUG "winsec"
|
|
||||||
#include "sakurakit/skdebug.h"
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
// - Inline Hook -
|
|
||||||
// See: http://asdf.wkeya.com/code/apihook6.html
|
|
||||||
PVOID overrideFunctionA(HMODULE stealFrom, LPCSTR oldFunctionModule, LPCSTR functionName, LPCVOID newFunction)
|
|
||||||
{
|
|
||||||
if (!stealFrom)
|
|
||||||
return nullptr;
|
|
||||||
//HMODULE oldModule = GetModuleHandleA(oldFunctionModule);
|
|
||||||
//if (!oldModule)
|
|
||||||
// return nullptr;
|
|
||||||
//void *originalAddress = GetProcAddress(oldModule, functionName);
|
|
||||||
LPVOID originalAddress = details::getModuleFunctionAddressA(functionName, oldFunctionModule);
|
|
||||||
if (!originalAddress)
|
|
||||||
return nullptr;
|
|
||||||
IMAGE_DOS_HEADER *dosHeader = reinterpret_cast<IMAGE_DOS_HEADER *>(stealFrom);
|
|
||||||
char *base = reinterpret_cast<char *>(stealFrom);
|
|
||||||
if (::IsBadReadPtr(dosHeader, sizeof(IMAGE_DOS_HEADER)) || dosHeader->e_magic != IMAGE_DOS_SIGNATURE)
|
|
||||||
return nullptr;
|
|
||||||
IMAGE_NT_HEADERS *ntHeader =
|
|
||||||
reinterpret_cast<IMAGE_NT_HEADERS* >(base + dosHeader->e_lfanew);
|
|
||||||
if (::IsBadReadPtr(ntHeader, sizeof(IMAGE_NT_HEADERS)) || ntHeader->Signature != IMAGE_NT_SIGNATURE)
|
|
||||||
return nullptr;
|
|
||||||
if (!ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress)
|
|
||||||
return nullptr;
|
|
||||||
// See: http://msdn.microsoft.com/en-us/magazine/cc301808.aspx
|
|
||||||
IMAGE_IMPORT_DESCRIPTOR *import =
|
|
||||||
reinterpret_cast<IMAGE_IMPORT_DESCRIPTOR *>(base + ntHeader->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT].VirtualAddress);
|
|
||||||
|
|
||||||
// scan memory
|
|
||||||
// TODO: add a maximum loop counter here!
|
|
||||||
while (import->Name) {
|
|
||||||
char *name = base + import->Name;
|
|
||||||
if (!::stricmp(name, oldFunctionModule))
|
|
||||||
break;
|
|
||||||
import++;
|
|
||||||
}
|
|
||||||
if (!import->Name)
|
|
||||||
return nullptr;
|
|
||||||
IMAGE_THUNK_DATA *thunk = reinterpret_cast<IMAGE_THUNK_DATA *>(base + import->FirstThunk);
|
|
||||||
while (thunk->u1.Function) {
|
|
||||||
if ((ULONG_PTR)thunk->u1.Function == (ULONG_PTR)originalAddress) {
|
|
||||||
ULONG_PTR *addr = reinterpret_cast<ULONG_PTR *>(&thunk->u1.Function);
|
|
||||||
|
|
||||||
// See: http://asdf.wkeya.com/code/apihook6.html
|
|
||||||
// Inline hook mechanism:
|
|
||||||
//
|
|
||||||
// LPVOID InlineHook3( PUINT8 mem, DWORD dwLen, PUINT8 pfOld, PUINT8 pfNew )
|
|
||||||
// {
|
|
||||||
// DWORD dwOldProtect;
|
|
||||||
// VirtualProtect( ( PUINT8 )( pfOld ), dwLen, PAGE_READWRITE, &dwOldProtect );
|
|
||||||
// // 関数のエントリーから指定したbyte数をメモリの前方にコピー
|
|
||||||
// // メモリの数byte後方からオリジナルへのジャンプを作成
|
|
||||||
// // 指定の関数アドレスから5byteをフックへのjmp命令に書き換え
|
|
||||||
// VirtualProtect( ( PUINT8 )( pfOld ), dwLen, dwOldProtect, &dwOldProtect );
|
|
||||||
// return ( PVOID )mem;
|
|
||||||
// }
|
|
||||||
|
|
||||||
MEMORY_BASIC_INFORMATION mbi;
|
|
||||||
if (::VirtualQuery((LPVOID)addr, &mbi, sizeof(mbi)) == sizeof(mbi)) {
|
|
||||||
DWORD dwOldProtect;
|
|
||||||
if (::VirtualProtect(mbi.BaseAddress, ((ULONG_PTR)addr + 8)-(ULONG_PTR)mbi.BaseAddress, PAGE_EXECUTE_READWRITE, &dwOldProtect)) {
|
|
||||||
*addr = (ULONG_PTR)newFunction;
|
|
||||||
::VirtualProtect(mbi.BaseAddress, ((ULONG_PTR)addr + 8)-(ULONG_PTR)mbi.BaseAddress, dwOldProtect, &dwOldProtect);
|
|
||||||
return originalAddress;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
thunk++;
|
|
||||||
}
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,25 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// hijack.h
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
|
|
||||||
#include "windbg/windbg.h"
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Replace the named function entry with the new one.
|
|
||||||
* @param stealFrom instance of target module
|
|
||||||
* @param oldFunctionModule TODO
|
|
||||||
* @param functionName name of the target function
|
|
||||||
* @return the orignal address if succeed, else nullptr
|
|
||||||
*
|
|
||||||
* See: http://www.codeproject.com/KB/DLL/DLL_Injection_tutorial.aspx
|
|
||||||
*/
|
|
||||||
PVOID overrideFunctionA(_In_ HMODULE stealFrom, _In_ LPCSTR oldFunctionModule,
|
|
||||||
_In_ LPCSTR functionName, _In_ LPCVOID newFunction);
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,167 +0,0 @@
|
|||||||
// inject.cc
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
#include "windbg/inject.h"
|
|
||||||
#include "windbg/windbg_p.h"
|
|
||||||
#include <cwchar> // for wcslen
|
|
||||||
|
|
||||||
//#define DEBUG "windbg::inject"
|
|
||||||
#include "sakurakit/skdebug.h"
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
// - Remote Injection -
|
|
||||||
|
|
||||||
BOOL InjectFunction1(LPCVOID addr, LPCVOID data, SIZE_T dataSize, DWORD pid, HANDLE hProcess, INT timeout)
|
|
||||||
{
|
|
||||||
DOUT("enter: pid =" << pid);
|
|
||||||
if (hProcess == INVALID_HANDLE_VALUE && pid) {
|
|
||||||
hProcess = ::OpenProcess(PROCESS_INJECT_ACCESS, FALSE, pid);
|
|
||||||
// TODO: Privilege elevation is not implemented. See: skwinsec.py.
|
|
||||||
//if (!hProcess) {
|
|
||||||
// priv = SkProcessElevator('SeDebugPrivilege')
|
|
||||||
// if not priv.isEmpty():
|
|
||||||
// handle = win32api.OpenProcess(PROCESS_INJECT_ACCESS, 0, pid)
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
if (hProcess == INVALID_HANDLE_VALUE) {
|
|
||||||
DOUT("exit: error: failed to get process handle");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ret = FALSE;
|
|
||||||
if (LPVOID remoteData = ::VirtualAllocEx(hProcess, nullptr, dataSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE)) {
|
|
||||||
if (::WriteProcessMemory(hProcess, remoteData, data, dataSize, nullptr))
|
|
||||||
if (HANDLE hThread = ::CreateRemoteThread(
|
|
||||||
hProcess,
|
|
||||||
nullptr, 0,
|
|
||||||
reinterpret_cast<LPTHREAD_START_ROUTINE>(addr),
|
|
||||||
remoteData,
|
|
||||||
0, nullptr)) {
|
|
||||||
::WaitForSingleObject(hThread, timeout);
|
|
||||||
::CloseHandle(hThread);
|
|
||||||
ret = TRUE;
|
|
||||||
}
|
|
||||||
::VirtualFreeEx(hProcess, remoteData, dataSize, MEM_RELEASE);
|
|
||||||
}
|
|
||||||
::CloseHandle(hProcess);
|
|
||||||
DOUT("exit: ret =" << ret);
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL injectDllW(LPCWSTR dllPath, DWORD pid, HANDLE hProcess, INT timeout)
|
|
||||||
{
|
|
||||||
DOUT("enter: pid =" << pid);
|
|
||||||
LPCVOID fun = details::getModuleFunctionAddressA("LoadLibraryW", "kernel32.dll");
|
|
||||||
if (!fun) {
|
|
||||||
DOUT("exit error: cannot find function");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
LPCVOID data = dllPath;
|
|
||||||
SIZE_T dataSize = ::wcslen(dllPath) * 2 + 2; // L'\0'
|
|
||||||
BOOL ok = InjectFunction1(fun, data, dataSize, pid, hProcess, timeout);
|
|
||||||
DOUT("exit: ret =" << ok);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
BOOL ejectDll(HANDLE hDll, DWORD pid, HANDLE hProcess, INT timeout)
|
|
||||||
{
|
|
||||||
DOUT("enter: pid =" << pid);
|
|
||||||
LPCVOID fun = details::getModuleFunctionAddressA("FreeLibrary", "kernel32.dll");
|
|
||||||
if (!fun) {
|
|
||||||
DOUT("exit error: cannot find function");
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
LPCVOID data = &hDll;
|
|
||||||
SIZE_T dataSize = sizeof(hDll);
|
|
||||||
BOOL ok = InjectFunction1(fun, data, dataSize, pid, hProcess, timeout);
|
|
||||||
DOUT("exit: ret =" << ok);
|
|
||||||
return ok;
|
|
||||||
}
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
||||||
|
|
||||||
/*
|
|
||||||
enum { CREATE_THREAD_ACCESS = (PROCESS_CREATE_THREAD |
|
|
||||||
PROCESS_QUERY_INFORMATION |
|
|
||||||
PROCESS_VM_OPERATION |
|
|
||||||
PROCESS_VM_WRITE |
|
|
||||||
PROCESS_VM_READ ) };
|
|
||||||
|
|
||||||
|
|
||||||
int InjectDll(HANDLE hProcess, HINSTANCE hInst) {
|
|
||||||
HANDLE hThread;
|
|
||||||
|
|
||||||
wchar_t dllFile[2*MAX_PATH];
|
|
||||||
if (GetModuleFileNameW(hInst, dllFile, sizeof(dllFile)/2) > sizeof(dllFile)/2) return 0;
|
|
||||||
|
|
||||||
void *loadLibraryW = GetProcAddress(GetModuleHandleW(L"kernel32.dll"), "LoadLibraryW");
|
|
||||||
if (!loadLibraryW) return 0;
|
|
||||||
|
|
||||||
wchar_t *name;
|
|
||||||
if (!(name = wcsrchr(dllFile, '\\'))) return 0;
|
|
||||||
name ++;
|
|
||||||
wcscpy(name, DLL_NAME);
|
|
||||||
if (GetFileAttributes(dllFile) == INVALID_FILE_ATTRIBUTES) return 0;
|
|
||||||
|
|
||||||
size_t len = sizeof(wchar_t)*(1+wcslen(dllFile));
|
|
||||||
void *remoteString = (LPVOID)VirtualAllocEx(hProcess,
|
|
||||||
NULL,
|
|
||||||
len,
|
|
||||||
MEM_RESERVE|MEM_COMMIT,
|
|
||||||
PAGE_READWRITE
|
|
||||||
);
|
|
||||||
if (remoteString) {
|
|
||||||
if (WriteProcessMemory(hProcess, (LPVOID)remoteString, dllFile, len, NULL)) {
|
|
||||||
if (hThread = CreateRemoteThread(hProcess, 0, 0, (LPTHREAD_START_ROUTINE)loadLibraryW, (LPVOID)remoteString, 0,0)) {
|
|
||||||
WaitForSingleObject(hThread, 3000);
|
|
||||||
CloseHandle(hThread);
|
|
||||||
VirtualFreeEx(hProcess, remoteString, len, MEM_FREE);
|
|
||||||
// Make sure it's injected before resuming.
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
VirtualFreeEx(hProcess, remoteString, len, MEM_FREE);
|
|
||||||
}
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int getPriv(const char * name) {
|
|
||||||
HANDLE hToken;
|
|
||||||
LUID seValue;
|
|
||||||
TOKEN_PRIVILEGES tkp;
|
|
||||||
|
|
||||||
if (!LookupPrivilegeValueA(NULL, name, &seValue) ||
|
|
||||||
!OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken)) {
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
tkp.PrivilegeCount = 1;
|
|
||||||
tkp.Privileges[0].Luid = seValue;
|
|
||||||
tkp.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
|
|
||||||
|
|
||||||
int res = AdjustTokenPrivileges(hToken, 0, &tkp, sizeof(tkp), NULL, NULL);
|
|
||||||
|
|
||||||
CloseHandle(hToken);
|
|
||||||
return res;
|
|
||||||
}
|
|
||||||
|
|
||||||
inline int getDebugPriv() {
|
|
||||||
return getPriv("SeDebugPrivilege");
|
|
||||||
}
|
|
||||||
|
|
||||||
int InjectIntoProcess(int pid) {
|
|
||||||
HANDLE hProcess = OpenProcess(CREATE_THREAD_ACCESS, 0, pid);
|
|
||||||
if (hProcess == 0) {
|
|
||||||
getDebugPriv();
|
|
||||||
hProcess = OpenProcess(CREATE_THREAD_ACCESS, 0, pid);
|
|
||||||
if (!hProcess) return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int out = InjectDll(hProcess);
|
|
||||||
|
|
||||||
CloseHandle(hProcess);
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
*/
|
|
@ -1,56 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// inject.h
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
|
|
||||||
#include "windbg/windbg.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
enum { PROCESS_INJECT_ACCESS = PROCESS_CREATE_THREAD|PROCESS_QUERY_INFORMATION|PROCESS_VM_OPERATION|PROCESS_VM_WRITE|PROCESS_VM_READ };
|
|
||||||
enum { INJECT_TIMEOUT = 3000 }; // wait at most 3 seconds for creating remote threads
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Inject function with 1 argument
|
|
||||||
* Either pid or the process handle should be specified
|
|
||||||
* @param addr LONG function memory address
|
|
||||||
* @param arg LPVOID arg1 data
|
|
||||||
* @param argSize int arg1 data size
|
|
||||||
* @param pid process id
|
|
||||||
* @param hProcess process handle
|
|
||||||
* @param timeout msec
|
|
||||||
* @return BOOL
|
|
||||||
*/
|
|
||||||
BOOL injectFunction1(_In_ LPCVOID addr, _In_ LPCVOID arg, _In_ SIZE_T argSize,
|
|
||||||
_In_ DWORD pid = 0, _In_ HANDLE hProcess = INVALID_HANDLE_VALUE,
|
|
||||||
_In_ INT timeout = INJECT_TIMEOUT);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Either pid or the process handle should be specified
|
|
||||||
* @param dllpath ABSOLUTE path to dll
|
|
||||||
* @param pid process id
|
|
||||||
* @param hProcess process handle
|
|
||||||
* @param timeout msec
|
|
||||||
* @return BOOL
|
|
||||||
*/
|
|
||||||
BOOL injectDllW(_In_ LPCWSTR dllPath,
|
|
||||||
_In_ DWORD pid = 0, _In_ HANDLE hProcess = INVALID_HANDLE_VALUE,
|
|
||||||
_In_ INT timeout = INJECT_TIMEOUT);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Either pid or the process handle should be specified
|
|
||||||
* @param hDll dll module handle
|
|
||||||
* @param pid process id
|
|
||||||
* @param hProcess process handle
|
|
||||||
* @param timeout msec
|
|
||||||
* @return BOOL
|
|
||||||
*/
|
|
||||||
BOOL ejectDll(_In_ HANDLE hDll,
|
|
||||||
_In_ DWORD pid = 0, _In_ HANDLE hProcess = INVALID_HANDLE_VALUE,
|
|
||||||
_In_ INT timeout = INJECT_TIMEOUT);
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,22 +0,0 @@
|
|||||||
// unload.cc
|
|
||||||
// 5/2/2014 jichi
|
|
||||||
#include "windbg/unload.h"
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
EXTERN_C IMAGE_DOS_HEADER __ImageBase;
|
|
||||||
// See: http://stackoverflow.com/questions/3410130/dll-unloading-itself
|
|
||||||
BOOL unloadCurrentModule()
|
|
||||||
{
|
|
||||||
auto fun = ::FreeLibrary;
|
|
||||||
//auto fun = ::LdrUnloadDll;
|
|
||||||
if (HANDLE h = ::CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)fun, &__ImageBase, 0, NULL)) {
|
|
||||||
::CloseHandle(h);
|
|
||||||
return TRUE;
|
|
||||||
}
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,19 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// unload.h
|
|
||||||
// 5/2/2014 jichi
|
|
||||||
|
|
||||||
#include "windbg/windbg.h"
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Unload current injected DLL.
|
|
||||||
* @return BOOL
|
|
||||||
*/
|
|
||||||
BOOL unloadCurrentModule();
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,61 +0,0 @@
|
|||||||
// windbg/util.cc
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
#include "windbg/util.h"
|
|
||||||
#include <tlhelp32.h>
|
|
||||||
#include <boost/foreach.hpp>
|
|
||||||
#include <list>
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class ThreadsSuspenderPrivate
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::list<HANDLE> threads;
|
|
||||||
};
|
|
||||||
|
|
||||||
ThreadsSuspender::ThreadsSuspender(bool autoSuspend)
|
|
||||||
: d_(new D)
|
|
||||||
{ if (autoSuspend) suspend(); }
|
|
||||||
|
|
||||||
ThreadsSuspender::~ThreadsSuspender()
|
|
||||||
{
|
|
||||||
resume();
|
|
||||||
delete d_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadsSuspender::suspend()
|
|
||||||
{
|
|
||||||
HANDLE hSnap = ::CreateToolhelp32Snapshot(TH32CS_SNAPTHREAD, 0);
|
|
||||||
if (hSnap == INVALID_HANDLE_VALUE)
|
|
||||||
return;
|
|
||||||
THREADENTRY32 entry;
|
|
||||||
entry.dwSize = sizeof(entry);
|
|
||||||
DWORD pid = ::GetCurrentProcessId();
|
|
||||||
DWORD tid = ::GetCurrentThreadId();
|
|
||||||
if (::Thread32First(hSnap, &entry))
|
|
||||||
do if (entry.dwSize >= 4 * sizeof(DWORD) && entry.th32OwnerProcessID == pid && entry.th32ThreadID != tid) {
|
|
||||||
if (HANDLE hThread = ::OpenThread(THREAD_SUSPEND_RESUME, 0, entry.th32ThreadID)) {
|
|
||||||
if (::SuspendThread(hThread) != DWORD(-1))
|
|
||||||
d_->threads.push_back(hThread);
|
|
||||||
else
|
|
||||||
::CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
entry.dwSize = sizeof(entry);
|
|
||||||
} while (::Thread32Next(hSnap, &entry));
|
|
||||||
::CloseHandle(hSnap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ThreadsSuspender::resume()
|
|
||||||
{
|
|
||||||
if (!d_->threads.empty()) {
|
|
||||||
BOOST_FOREACH (HANDLE hThread, d_->threads) {
|
|
||||||
::ResumeThread(hThread);
|
|
||||||
::CloseHandle(hThread);
|
|
||||||
}
|
|
||||||
d_->threads.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,34 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// windbg/util.h
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
|
|
||||||
#include "windbg/windbg.h"
|
|
||||||
#include "sakurakit/skglobal.h"
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
class ThreadsSuspenderPrivate;
|
|
||||||
/**
|
|
||||||
* When created, automatically suspends all threads in the current process.
|
|
||||||
* When destroyed, resume suspended threads.
|
|
||||||
*/
|
|
||||||
class ThreadsSuspender
|
|
||||||
{
|
|
||||||
SK_CLASS(ThreadsSuspender)
|
|
||||||
SK_DISABLE_COPY(ThreadsSuspender)
|
|
||||||
SK_DECLARE_PRIVATE(ThreadsSuspenderPrivate)
|
|
||||||
|
|
||||||
public:
|
|
||||||
explicit ThreadsSuspender(bool autoSuspend = true);
|
|
||||||
~ThreadsSuspender();
|
|
||||||
|
|
||||||
void resume(); ///< Manually resume all threads
|
|
||||||
void suspend(); ///< Manually suspend all threads
|
|
||||||
};
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,16 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// windbg.h
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
|
|
||||||
#ifndef WINDBG_BEGIN_NAMESPACE
|
|
||||||
# define WINDBG_BEGIN_NAMESPACE namespace WinDbg {
|
|
||||||
#endif
|
|
||||||
#ifndef WINDBG_END_NAMESPACE
|
|
||||||
# define WINDBG_END_NAMESPACE } // namespace WinDbg
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,24 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// windbg_p.h
|
|
||||||
// 1/27/2013 jichi
|
|
||||||
|
|
||||||
#include "windbg/windbg.h"
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
WINDBG_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
namespace details { // unnamed
|
|
||||||
|
|
||||||
/// Return the address of func in module.
|
|
||||||
inline FARPROC getModuleFunctionAddressA(LPCSTR func, LPCSTR module = nullptr)
|
|
||||||
{ return ::GetProcAddress(::GetModuleHandleA(module), func); }
|
|
||||||
|
|
||||||
inline FARPROC getModuleFunctionAddressW(LPCSTR func, LPCWSTR module = nullptr)
|
|
||||||
{ return ::GetProcAddress(::GetModuleHandleW(module), func); }
|
|
||||||
|
|
||||||
} // unamed namespace details
|
|
||||||
|
|
||||||
WINDBG_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,32 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// winkey.h
|
|
||||||
// 7/21/2011
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
#ifndef WINKEY_BEGIN_NAMESPACE
|
|
||||||
# define WINKEY_BEGIN_NAMESPACE namespace WinKey {
|
|
||||||
#endif
|
|
||||||
#ifndef WINKEY_END_NAMESPACE
|
|
||||||
# define WINKEY_END_NAMESPACE } // namespace WinKey
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
WINKEY_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
inline bool isKeyPressed(int vk) { return ::GetKeyState(vk) & 0xf0; }
|
|
||||||
inline bool isKeyToggled(int vk) { return ::GetKeyState(vk) & 0x0f; }
|
|
||||||
|
|
||||||
inline bool isKeyReturnPressed() { return isKeyPressed(VK_RETURN); }
|
|
||||||
inline bool isKeyControlPressed() { return isKeyPressed(VK_CONTROL); }
|
|
||||||
inline bool isKeyShiftPressed() { return isKeyPressed(VK_SHIFT); }
|
|
||||||
inline bool isKeyAltPressed() { return isKeyPressed(VK_MENU); }
|
|
||||||
//inline bool sKeyCapslockToggled() { return isKeyToggled(VK_CAPITAL); }
|
|
||||||
inline bool isKeyWinPressed() { return isKeyPressed(VK_LWIN) || isKeyPressed(VK_RWIN); }
|
|
||||||
|
|
||||||
inline bool isMouseLeftButtonPressed() { return isKeyPressed(VK_LBUTTON); }
|
|
||||||
inline bool isMouseMiddleButtonPressed() { return isKeyPressed(VK_MBUTTON); }
|
|
||||||
inline bool isMouseRightButtonPressed() { return isKeyPressed(VK_RBUTTON); }
|
|
||||||
|
|
||||||
WINKEY_END_NAMESPACE
|
|
@ -1,46 +0,0 @@
|
|||||||
// winmaker.cc
|
|
||||||
// 2/1/2013 jichi
|
|
||||||
|
|
||||||
#include "winmaker/winmaker.h"
|
|
||||||
#include <windows.h>
|
|
||||||
//#include <commctrl.h>
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning (disable:4800) // C4800: forcing value to bool
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
// See: http://www.codeguru.com/cpp/w-p/dll/tips/article.php/c3635/Tip-Detecting-a-HMODULEHINSTANCE-Handle-Within-the-Module-Youre-Running-In.htm
|
|
||||||
extern "C" IMAGE_DOS_HEADER __ImageBase;
|
|
||||||
namespace { // unnamed
|
|
||||||
inline HMODULE _get_module() { return reinterpret_cast<HMODULE>(&__ImageBase); }
|
|
||||||
} // unnamed
|
|
||||||
|
|
||||||
bool wm_register_hidden_class(LPCWSTR className)
|
|
||||||
{
|
|
||||||
WNDCLASSEX wx = {};
|
|
||||||
wx.cbSize = sizeof(wx);
|
|
||||||
wx.lpfnWndProc = ::DefWindowProc;
|
|
||||||
wx.hInstance = ::GetModuleHandle(nullptr);
|
|
||||||
wx.lpszClassName = className;
|
|
||||||
return ::RegisterClassEx(&wx);
|
|
||||||
}
|
|
||||||
|
|
||||||
wm_window_t wm_create_hidden_window(LPCWSTR windowName, LPCWSTR className, wm_module_t dllHandle)
|
|
||||||
{
|
|
||||||
//return ::CreateWindowExA(0, className, windowName, 0, 0, 0, 0, 0, HWND_MESSAGE, nullptr, dllHandle, nullptr);
|
|
||||||
HINSTANCE module = reinterpret_cast<HINSTANCE>(dllHandle);
|
|
||||||
if (!module)
|
|
||||||
module = _get_module();
|
|
||||||
return ::CreateWindowEx(0, className, windowName, 0, 0, 0, 0, 0, 0, NULL, module, NULL);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool wm_destroy_window(wm_window_t hwnd)
|
|
||||||
{ return ::DestroyWindow(reinterpret_cast<HWND>(hwnd)); }
|
|
||||||
|
|
||||||
|
|
||||||
// EOF
|
|
||||||
//
|
|
||||||
//void wm_init() { ::InitCommonControls(); }
|
|
||||||
//void wm_destroy() {}
|
|
||||||
//bool wm_destroy_window() { return ::DestroyWindow(hwnd); }
|
|
||||||
|
|
@ -1,23 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// winmaker.h
|
|
||||||
// 2/1/2013 jichi
|
|
||||||
|
|
||||||
#include <windows.h>
|
|
||||||
typedef void *wm_window_t; // HWMD
|
|
||||||
typedef void *wm_module_t; // HMODULE
|
|
||||||
|
|
||||||
bool wm_register_hidden_class(LPCWSTR className = L"hidden_class");
|
|
||||||
|
|
||||||
wm_window_t wm_create_hidden_window(
|
|
||||||
LPCWSTR windowName = L"hidden_window",
|
|
||||||
LPCWSTR className = L"Button", // bust be one of the common control widgets
|
|
||||||
wm_module_t dllHandle = nullptr);
|
|
||||||
|
|
||||||
bool wm_destroy_window(wm_window_t hwnd);
|
|
||||||
|
|
||||||
// EOF
|
|
||||||
|
|
||||||
//#ifdef QT_CORE_LIB
|
|
||||||
//#include <QtGui/qwindowdefs.h>
|
|
||||||
//WId wm_create_hidden_window(const char *className = "Button", const char *windowName = "hidden_window");
|
|
@ -1,26 +0,0 @@
|
|||||||
# Makefile
|
|
||||||
# 12/13/2013 jichi
|
|
||||||
# This file is for Windows only.
|
|
||||||
# Compile SAFESEH table from the ASM file.
|
|
||||||
# See: http://stackoverflow.com/questions/19722308/exception-handler-not-called-in-c
|
|
||||||
# See: http://stackoverflow.com/questions/12019689/custom-seh-handler-with-safeseh
|
|
||||||
# See: http://msdn.microsoft.com/en-us/library/16aexws6.aspx
|
|
||||||
|
|
||||||
BUILDDIR = ../../../build
|
|
||||||
OBJ = $(BUILDDIR)/safeseh.obj
|
|
||||||
|
|
||||||
ML = ml
|
|
||||||
CFLAGS =
|
|
||||||
|
|
||||||
.PHONY: all compile clean
|
|
||||||
|
|
||||||
all: compile
|
|
||||||
|
|
||||||
compile: $(OBJ)
|
|
||||||
|
|
||||||
$(OBJ): safeseh.asm
|
|
||||||
$(ML) $(CFLAGS) -Fo $@ -c -safeseh $^
|
|
||||||
|
|
||||||
clean:
|
|
||||||
|
|
||||||
# EOF
|
|
@ -1,21 +0,0 @@
|
|||||||
; safeseh.asm
|
|
||||||
; 12/13/2013 jichi
|
|
||||||
; see: http://stackoverflow.com/questions/12019689/custom-seh-handler-with-safeseh
|
|
||||||
; see: http://code.metager.de/source/xref/WebKit/Source/WebCore/platform/win/makesafeseh.asm
|
|
||||||
; see: http://jpassing.com/2008/05/20/fun-with-low-level-seh/
|
|
||||||
.386
|
|
||||||
.model flat, stdcall
|
|
||||||
option casemap :none
|
|
||||||
|
|
||||||
; The symbol name can be found out using: dumpbin /symbols winseh.obj
|
|
||||||
extern _seh_handler:near ; defined in winseh.cc
|
|
||||||
|
|
||||||
_seh_asm_handler proto
|
|
||||||
.safeseh _seh_asm_handler
|
|
||||||
|
|
||||||
.code
|
|
||||||
_seh_asm_handler proc
|
|
||||||
jmp _seh_handler
|
|
||||||
_seh_asm_handler endp
|
|
||||||
|
|
||||||
end
|
|
@ -1,52 +0,0 @@
|
|||||||
// winseh.cc
|
|
||||||
// 12/13/2013 jichi
|
|
||||||
|
|
||||||
#include "winseh/winseh.h"
|
|
||||||
#include "ntdll/ntdll.h"
|
|
||||||
//#include <cstdio>
|
|
||||||
|
|
||||||
// - Define global variables -
|
|
||||||
|
|
||||||
seh_dword_t seh_esp[seh_capacity],
|
|
||||||
seh_eip[seh_capacity],
|
|
||||||
seh_eh[seh_capacity];
|
|
||||||
seh_dword_t seh_count;
|
|
||||||
|
|
||||||
// - Exception handlers -
|
|
||||||
|
|
||||||
// VC 2013: http://msdn.microsoft.com/en-us/library/b6sf5kbd.aspx
|
|
||||||
// typedef EXCEPTION_DISPOSITION (*PEXCEPTION_ROUTINE) (
|
|
||||||
// _In_ PEXCEPTION_RECORD ExceptionRecord,
|
|
||||||
// _In_ ULONG64 EstablisherFrame,
|
|
||||||
// _Inout_ PCONTEXT ContextRecord,
|
|
||||||
// _Inout_ PDISPATCHER_CONTEXT DispatcherContext
|
|
||||||
// );
|
|
||||||
//
|
|
||||||
// winnt.h: http://www.codemachine.com/downloads/win81/ntdef.h
|
|
||||||
// typedef
|
|
||||||
// __drv_sameIRQL
|
|
||||||
// __drv_functionClass(EXCEPTION_ROUTINE)
|
|
||||||
// EXCEPTION_DISPOSITION
|
|
||||||
// NTAPI
|
|
||||||
// EXCEPTION_ROUTINE (
|
|
||||||
// _Inout_ struct _EXCEPTION_RECORD *ExceptionRecord,
|
|
||||||
// _In_ PVOID EstablisherFrame,
|
|
||||||
// _In_ struct _CONTEXT *ContextRecord,
|
|
||||||
// _In_ PVOID DispatcherContext
|
|
||||||
// );
|
|
||||||
extern "C" EXCEPTION_DISPOSITION _seh_handler( // extern C is needed to avoid name hashing in C++
|
|
||||||
_In_ PEXCEPTION_RECORD ExceptionRecord,
|
|
||||||
_In_ PVOID EstablisherFrame, // do not work if I use ULONG64
|
|
||||||
_Inout_ PCONTEXT ContextRecord,
|
|
||||||
_In_ PVOID DispatcherContext) // PDISPATCHER_CONTEXT is not declared in windows.h, use PVOID instead
|
|
||||||
{
|
|
||||||
//assert(::seh_count > 0);
|
|
||||||
ContextRecord->Esp = ::seh_esp[::seh_count - 1];
|
|
||||||
ContextRecord->Eip = ::seh_eip[::seh_count - 1];
|
|
||||||
//printf("seh_handler:%i,%x,%x\n", ::seh_count, ContextRecord->Esp, ContextRecord->Eip);
|
|
||||||
return ::seh_eh[::seh_count - 1] ?
|
|
||||||
reinterpret_cast<PEXCEPTION_ROUTINE>(::seh_eh[::seh_count - 1])(ExceptionRecord, EstablisherFrame, ContextRecord, DispatcherContext) :
|
|
||||||
ExceptionContinueExecution;
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,154 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// winseh.h
|
|
||||||
// 12/13/2013 jichi
|
|
||||||
// See: http://code.metager.de/source/xref/WebKit/Source/WebCore/platform/win/makesafeseh.asm
|
|
||||||
// See: http://jpassing.com/2008/05/20/fun-with-low-level-seh/
|
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
|
||||||
# pragma warning (disable:4733) // C4733: Inline asm assigning to 'FS:0' : handler not registered as safe handler
|
|
||||||
#endif // _MSC_VER
|
|
||||||
|
|
||||||
#define SEH_RAISE (*(int*)0 = 0) // raise C000005, for debugging only
|
|
||||||
|
|
||||||
// Maximum number of nested SEH
|
|
||||||
// Default nested function count is 100, see: http://stackoverflow.com/questions/8656089/solution-for-fatal-error-maximum-function-nesting-level-of-100-reached-abor
|
|
||||||
#ifndef SEH_CAPACITY
|
|
||||||
# define SEH_CAPACITY 100
|
|
||||||
#endif // SEH_CAPACITY
|
|
||||||
|
|
||||||
enum { seh_capacity = SEH_CAPACITY };
|
|
||||||
|
|
||||||
typedef unsigned long seh_dword_t; // DWORD in <windows.h>
|
|
||||||
|
|
||||||
// 12/13/2013 jichi
|
|
||||||
// The list implementation is not thread-safe
|
|
||||||
extern seh_dword_t
|
|
||||||
seh_count // current number of exception handlers
|
|
||||||
, seh_handler // extern PEXCEPTION_ROUTINE seh_handler;
|
|
||||||
, seh_esp[seh_capacity] // LPVOID, current stack
|
|
||||||
, seh_eip[seh_capacity] // LPVOID, current IP address
|
|
||||||
, seh_eh[seh_capacity] // EXCEPTION_ROUTINE, current exception handler function address
|
|
||||||
;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Push SEH handler
|
|
||||||
* @param _label exception recover label which should be the same as seh_pop_
|
|
||||||
* @param _eh EXCEPTION_ROUTINE or 0
|
|
||||||
* @param _r1 scalar register name, such as eax
|
|
||||||
* @param _r2 counter register name, such as ecx
|
|
||||||
*
|
|
||||||
* Note: __asm prefix is needed to allow inlining macro
|
|
||||||
* I didn't pushad and popad which seems to be not needed
|
|
||||||
*
|
|
||||||
* For SEH, see:
|
|
||||||
* http://www.codeproject.com/Articles/82701/Win32-Exceptions-OS-Level-Point-of-View
|
|
||||||
* http://sploitfun.blogspot.com/2012/08/seh-exploit-part1.html
|
|
||||||
* http://sploitfun.blogspot.com/2012/08/seh-exploit-part2.html
|
|
||||||
*
|
|
||||||
* fs:0x0 on Windows is the pointer to ExceptionList
|
|
||||||
* http://stackoverflow.com/questions/4657661/what-lies-at-fs0x0-on-windows
|
|
||||||
*
|
|
||||||
* EPB and ESP
|
|
||||||
* http://stackoverflow.com/questions/1395591/what-is-exactly-the-base-pointer-and-stack-pointer-to-what-do-they-point
|
|
||||||
*
|
|
||||||
* TODO: get sizeof dword instead of hardcode 4
|
|
||||||
*/
|
|
||||||
#define seh_push_(_label, _eh, _r1, _r2) \
|
|
||||||
{ \
|
|
||||||
__asm mov _r1, _eh /* move new handler address */ \
|
|
||||||
__asm mov _r2, seh_count /* get current seh counter */ \
|
|
||||||
__asm mov dword ptr seh_eh[_r2*4], _r1 /* set recover exception hander */ \
|
|
||||||
__asm mov _r1, _label /* move jump label address */ \
|
|
||||||
__asm mov dword ptr seh_eip[_r2*4], _r1 /* set recover eip as the jump label */ \
|
|
||||||
__asm push seh_handler /* push new safe seh handler */ \
|
|
||||||
__asm push fs:[0] /* push old fs:0 */ \
|
|
||||||
__asm mov dword ptr seh_esp[_r2*4], esp /* safe current stack address */ \
|
|
||||||
__asm mov fs:[0], esp /* change fs:0 to the current stack */ \
|
|
||||||
__asm inc seh_count /* increase number of seh */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Restore old SEH handler
|
|
||||||
* @param _label exception recover label which should be the same as seh_push_
|
|
||||||
*/
|
|
||||||
#define seh_pop_(_label) \
|
|
||||||
{ \
|
|
||||||
__asm _label: /* the exception recover label */ \
|
|
||||||
__asm pop dword ptr fs:[0] /* restore old fs:0 */ \
|
|
||||||
__asm add esp, 4 /* pop seh_handler */ \
|
|
||||||
__asm dec seh_count /* decrease number of seh */ \
|
|
||||||
}
|
|
||||||
|
|
||||||
// Define seh_exit as the shared exit label
|
|
||||||
#define seh_pop() seh_pop_(seh_exit)
|
|
||||||
#define seh_push() seh_push_(seh_exit, 0, eax, ecx) // use ecx as counter better than ebx
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @param _eh EXCEPTION_ROUTINE or 0
|
|
||||||
*/
|
|
||||||
#define seh_push_eh(_eh) seh_push_(seh_exit, _eh, eax, ecx)
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the code block with SEH handler
|
|
||||||
* @param* any code block. The colon for the last expression is optional.
|
|
||||||
*/
|
|
||||||
#define seh_with(...) \
|
|
||||||
{ \
|
|
||||||
seh_push() \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
; /* allow __VA_ARGS__ to be an expression */ \
|
|
||||||
seh_pop() \
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Wrap the code block with SEH handler
|
|
||||||
* @param _eh EXCEPTION_ROUTINE or 0
|
|
||||||
* @param* any code block. The colon for the last expression is optional.
|
|
||||||
*/
|
|
||||||
#define seh_with_eh(_eh, ...) \
|
|
||||||
{ \
|
|
||||||
seh_push_eh(_eh) \
|
|
||||||
__VA_ARGS__ \
|
|
||||||
; /* allow __VA_ARGS__ to be an expression */ \
|
|
||||||
seh_pop() \
|
|
||||||
}
|
|
||||||
|
|
||||||
// EOF
|
|
||||||
|
|
||||||
//#define seh_push_front() \
|
|
||||||
// { \
|
|
||||||
// __asm mov eax, seh_exit \
|
|
||||||
// __asm mov seh_eip, eax \
|
|
||||||
// __asm push seh_handler \
|
|
||||||
// __asm push fs:[0] \
|
|
||||||
// __asm mov seh_esp, esp \
|
|
||||||
// __asm mov fs:[0], esp \
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//#define seh_pop_front() \
|
|
||||||
// { \
|
|
||||||
// __asm seh_exit: \
|
|
||||||
// __asm mov eax, [esp] \
|
|
||||||
// __asm mov fs:[0], eax \
|
|
||||||
// __asm add esp, 8 \
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//#define seh_push_back() \
|
|
||||||
// { \
|
|
||||||
// __asm mov eax, seh_exit \
|
|
||||||
// __asm mov ecx, seh_capacity - 1 \
|
|
||||||
// __asm mov DWORD PTR seh_eip[ecx*4], eax \
|
|
||||||
// __asm push seh_handler \
|
|
||||||
// __asm push fs:[0] \
|
|
||||||
// __asm mov DWORD PTR seh_esp[ecx*4], esp \
|
|
||||||
// __asm mov fs:[0], esp \
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
//#define seh_pop_back() \
|
|
||||||
// { \
|
|
||||||
// __asm seh_exit: \
|
|
||||||
// __asm mov eax, [esp] \
|
|
||||||
// __asm mov fs:[0], eax \
|
|
||||||
// __asm add esp, 8 \
|
|
||||||
// }
|
|
@ -1,10 +0,0 @@
|
|||||||
// winseh_safe.cc
|
|
||||||
// 12/13/2013 jichi
|
|
||||||
// See: http://stackoverflow.com/questions/12019689/custom-seh-handler-with-safeseh
|
|
||||||
|
|
||||||
#include "winseh/winseh.h"
|
|
||||||
|
|
||||||
extern "C" int __stdcall _seh_asm_handler();
|
|
||||||
seh_dword_t seh_handler = reinterpret_cast<seh_dword_t>(_seh_asm_handler);
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,11 +0,0 @@
|
|||||||
// winseh_unsafe.cc
|
|
||||||
// 12/13/2013 jichi
|
|
||||||
// See: http://stackoverflow.com/questions/19722308/exception-handler-not-called-in-c
|
|
||||||
|
|
||||||
#include "winseh/winseh.h"
|
|
||||||
#include <windows.h>
|
|
||||||
|
|
||||||
extern "C" EXCEPTION_DISPOSITION _seh_handler(PEXCEPTION_RECORD, PVOID, PCONTEXT, PVOID);
|
|
||||||
seh_dword_t seh_handler = reinterpret_cast<seh_dword_t>(_seh_handler);
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,49 +0,0 @@
|
|||||||
// wintimer.cc
|
|
||||||
// 6/6/2012 jichi
|
|
||||||
|
|
||||||
#include "wintimer/wintimer.h"
|
|
||||||
|
|
||||||
//#define DEBUG "wintimer.cc"
|
|
||||||
#include "sakurakit/skdebug.h"
|
|
||||||
#include <windows.h>
|
|
||||||
WINTIMER_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
void WinTimer::singleShot(int msecs, const function_type &f, WId parent)
|
|
||||||
{
|
|
||||||
Self *t = new Self(parent);
|
|
||||||
t->setInterval(msecs);
|
|
||||||
t->setSingleShot(true);
|
|
||||||
t->setFunction([=] { // Copy function f instead of pass by reference.
|
|
||||||
f();
|
|
||||||
delete t;
|
|
||||||
});
|
|
||||||
t->start();
|
|
||||||
}
|
|
||||||
|
|
||||||
WINTIMER_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
||||||
|
|
||||||
/*
|
|
||||||
// - Single shot -
|
|
||||||
|
|
||||||
namespace { // unnamed
|
|
||||||
|
|
||||||
class apply_delete
|
|
||||||
{
|
|
||||||
typedef WinTimer::function_type function_type;
|
|
||||||
function_type f_;
|
|
||||||
WinTimer *t_;
|
|
||||||
public:
|
|
||||||
apply_delete(const function_type &f, WinTimer *t)
|
|
||||||
: f_(f), t_(t) { Q_ASSERT(t); }
|
|
||||||
|
|
||||||
void operator()()
|
|
||||||
{
|
|
||||||
f_();
|
|
||||||
delete t_;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
} // unnamed namespace
|
|
||||||
*/
|
|
@ -1,93 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// wintimer.h
|
|
||||||
// 6/6/2012 jichi
|
|
||||||
//
|
|
||||||
// A light-weighted native windows timer as a replacement of QTimer from Qt.
|
|
||||||
// Implementation is based on Windows Messaging. A visible parent hwnd is required.
|
|
||||||
//
|
|
||||||
// This timer is critical where QTimer or event loop are not available, or need to
|
|
||||||
// warp to different event loop. Some usage cases follow:
|
|
||||||
// - Used by texthook as a replacement of QTimer in non-QThread
|
|
||||||
// - Used by qapplicationloader to implement pseudo event loop
|
|
||||||
// - Used by winhook to synchronize with window event loop across threads
|
|
||||||
|
|
||||||
#include "wintimer/wintimerbase.h"
|
|
||||||
#include <boost/bind.hpp>
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief A light-weighted native windows timer as a replacement of QTimer.
|
|
||||||
*
|
|
||||||
* Needed when in a thread where event loop is not accessible.
|
|
||||||
* Implemented using extensive inlining over pimp, so that the entire class
|
|
||||||
* could be put on the stack without heap.
|
|
||||||
*
|
|
||||||
* Each timer requires an valid visible window's handle to synchronize with.
|
|
||||||
* Either specify the window handle with the parent window or a global window.
|
|
||||||
*/
|
|
||||||
class WinTimer : protected WinTimerBase
|
|
||||||
{
|
|
||||||
SK_EXTEND_CLASS(WinTimer, WinTimerBase)
|
|
||||||
SK_DISABLE_COPY(WinTimer)
|
|
||||||
|
|
||||||
// - Construction -
|
|
||||||
public:
|
|
||||||
//typedef std::function<void ()> function_type;
|
|
||||||
using Base::function_type; ///< std::function<void ()>
|
|
||||||
|
|
||||||
/// Default parent window of all timers.
|
|
||||||
static WId globalWindow() { return Base::globalWindow; }
|
|
||||||
static void setGlobalWindow(WId winId) { Base::globalWindow = winId; }
|
|
||||||
|
|
||||||
//static WId createHiddenWindow();
|
|
||||||
|
|
||||||
public:
|
|
||||||
/// Construct a timer with the parent window handle.
|
|
||||||
explicit WinTimer(WId parentWindow = 0) { setParentWindow(parentWindow); }
|
|
||||||
|
|
||||||
static void singleShot(int msecs, const function_type &f, WId parent = 0);
|
|
||||||
|
|
||||||
// - Properties -
|
|
||||||
public:
|
|
||||||
using Base::isActive;
|
|
||||||
using Base::isSingleShot;
|
|
||||||
|
|
||||||
void setSingleShot(bool t) { Base::singleShot = t; }
|
|
||||||
|
|
||||||
//bool isEmpty() const { return Base::function.empty(); }
|
|
||||||
|
|
||||||
WId parentWindow() const { return Base::parentWindow; }
|
|
||||||
void setParentWindow(WId winId) { Base::parentWindow = winId ? winId : Base::globalWindow; }
|
|
||||||
|
|
||||||
int interval() const { return Base::interval; }
|
|
||||||
void setInterval(int msecs) { Base::interval = msecs; }
|
|
||||||
|
|
||||||
/// Timeout callback when trigger.
|
|
||||||
void setFunction(const function_type &f) { Base::function = f; }
|
|
||||||
|
|
||||||
/// @overload Set callback to a class method
|
|
||||||
template <typename Class, typename Member>
|
|
||||||
void setMethod(Class *obj, Member mfunc)
|
|
||||||
{ setFunction(boost::bind(mfunc, obj)); }
|
|
||||||
|
|
||||||
/// @overload Set callback to a const class method
|
|
||||||
template <typename Class, typename Member>
|
|
||||||
void setMethod(const Class *obj, Member mfunc)
|
|
||||||
{ setFunction(boost::bind(mfunc, obj)); }
|
|
||||||
|
|
||||||
// - Actions -
|
|
||||||
public:
|
|
||||||
/// Start TimerProc
|
|
||||||
using Base::start;
|
|
||||||
|
|
||||||
/// Stop TimerProc
|
|
||||||
using Base::stop;
|
|
||||||
|
|
||||||
/// Reset interval and start TimerProc
|
|
||||||
void start(int interval) { setInterval(interval); start(); }
|
|
||||||
|
|
||||||
/// Invoke the callback. This function is the callback of the underlying TimerProc
|
|
||||||
using Base::trigger;
|
|
||||||
};
|
|
||||||
|
|
||||||
WINTIMER_END_NAMESPACE
|
|
@ -1,73 +0,0 @@
|
|||||||
// wintimerbase.cc
|
|
||||||
// 6/6/2012 jichi
|
|
||||||
|
|
||||||
#include "wintimer/wintimerbase.h"
|
|
||||||
#ifdef QT_CORE_LIB
|
|
||||||
# include <qt_windows.h>
|
|
||||||
#else
|
|
||||||
# include <windows.h>
|
|
||||||
#endif // QT_CORE_LIB
|
|
||||||
#include "ccutil/ccmacro.h"
|
|
||||||
|
|
||||||
//#define DEBUG "wintimerbase.cc"
|
|
||||||
#include "sakurakit/skdebug.h"
|
|
||||||
|
|
||||||
static VOID CALLBACK WinTimerProc(
|
|
||||||
HWND hwnd, // ウィンドウのハンドル
|
|
||||||
UINT uMsg, // WM_TIMER メッセージ
|
|
||||||
UINT_PTR idEvent, // Timer ID
|
|
||||||
DWORD dwTime // 現在のシステム時刻
|
|
||||||
)
|
|
||||||
{
|
|
||||||
Q_UNUSED(hwnd)
|
|
||||||
Q_UNUSED(dwTime)
|
|
||||||
Q_UNUSED(uMsg)
|
|
||||||
Q_ASSERT(idEvent);
|
|
||||||
if (CC_UNLIKELY(!idEvent))
|
|
||||||
return;
|
|
||||||
DOUT("enter");
|
|
||||||
WinTimerBase *t = reinterpret_cast<WinTimerBase *>(idEvent);
|
|
||||||
|
|
||||||
if (t->isSingleShot() && t->isActive())
|
|
||||||
t->stop();
|
|
||||||
t->trigger();
|
|
||||||
DOUT("leave");
|
|
||||||
}
|
|
||||||
|
|
||||||
WINTIMER_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
// - Construction -
|
|
||||||
|
|
||||||
WId WinTimerBase::globalWindow;
|
|
||||||
|
|
||||||
//WId WinTimer::createHiddenWindow()
|
|
||||||
//{
|
|
||||||
// DOUT("enter: warning: hidden window used");
|
|
||||||
// QWidget *w = new QWidget;
|
|
||||||
// w->resize(QSize());
|
|
||||||
// w->show();
|
|
||||||
// DOUT("leave");
|
|
||||||
// return w->winId();
|
|
||||||
//}
|
|
||||||
|
|
||||||
// - Timer -
|
|
||||||
|
|
||||||
void WinTimerBase::start()
|
|
||||||
{
|
|
||||||
DOUT("enter: active =" << active << ", interval =" << interval);
|
|
||||||
active = true;
|
|
||||||
::SetTimer(parentWindow, reinterpret_cast<UINT_PTR>(this), interval, WinTimerProc);
|
|
||||||
DOUT("leave");
|
|
||||||
}
|
|
||||||
|
|
||||||
void WinTimerBase::stop()
|
|
||||||
{
|
|
||||||
DOUT("enter: active =" << active);
|
|
||||||
active = false;
|
|
||||||
::KillTimer(parentWindow, reinterpret_cast<UINT_PTR>(this));
|
|
||||||
DOUT("leave");
|
|
||||||
}
|
|
||||||
|
|
||||||
WINTIMER_END_NAMESPACE
|
|
||||||
|
|
||||||
// EOF
|
|
@ -1,68 +0,0 @@
|
|||||||
#pragma once
|
|
||||||
|
|
||||||
// wintimerbase.h
|
|
||||||
// 6/6/2012 jichi
|
|
||||||
//
|
|
||||||
// Internal header for wintimer base class.
|
|
||||||
|
|
||||||
#include "sakurakit/skglobal.h"
|
|
||||||
#include <functional>
|
|
||||||
|
|
||||||
#ifdef QT_CORE_LIB
|
|
||||||
# include <QtGui/qwindowdefs.h>
|
|
||||||
#else
|
|
||||||
# include <windows.h>
|
|
||||||
#endif // QT_CORE_LIB
|
|
||||||
|
|
||||||
#ifndef WINTIMER_BEGIN_NAMESPACE
|
|
||||||
# define WINTIMER_BEGIN_NAMESPACE
|
|
||||||
#endif
|
|
||||||
#ifndef WINTIMER_END_NAMESPACE
|
|
||||||
# define WINTIMER_END_NAMESPACE
|
|
||||||
#endif
|
|
||||||
|
|
||||||
WINTIMER_BEGIN_NAMESPACE
|
|
||||||
|
|
||||||
/// Internal base class for WinTimer
|
|
||||||
class WinTimerBase
|
|
||||||
{
|
|
||||||
SK_CLASS(WinTimerBase)
|
|
||||||
SK_DISABLE_COPY(WinTimerBase)
|
|
||||||
|
|
||||||
// - Types -
|
|
||||||
public:
|
|
||||||
typedef std::function<void ()> function_type;
|
|
||||||
#ifndef QT_CORE_LIB
|
|
||||||
typedef HWND WId;
|
|
||||||
#endif // QT_CORE_LIB
|
|
||||||
|
|
||||||
// - Methods -
|
|
||||||
public:
|
|
||||||
/// Construct a timer with the parent window handle.
|
|
||||||
WinTimerBase()
|
|
||||||
: parentWindow(0), // use 0 instead of nullptr to be consistent with Qt5
|
|
||||||
interval(0), singleShot(false), active(false) {}
|
|
||||||
|
|
||||||
bool isSingleShot() const { return singleShot; }
|
|
||||||
bool isActive() const { return active; }
|
|
||||||
|
|
||||||
/// Start TimerProc
|
|
||||||
void start();
|
|
||||||
/// Stop TimerProc
|
|
||||||
void stop();
|
|
||||||
/// Invoke the callback. This function is the callback of the underlying TimerProc
|
|
||||||
void trigger() { function(); }
|
|
||||||
|
|
||||||
// - Fields -
|
|
||||||
protected:
|
|
||||||
static WId globalWindow;
|
|
||||||
|
|
||||||
WId parentWindow;
|
|
||||||
int interval;
|
|
||||||
bool singleShot;
|
|
||||||
bool active;
|
|
||||||
function_type function;
|
|
||||||
|
|
||||||
};
|
|
||||||
|
|
||||||
WINTIMER_END_NAMESPACE
|
|
Loading…
x
Reference in New Issue
Block a user