delete unused files and start cleaning up code

This commit is contained in:
Akash Mozumdar 2018-05-11 16:46:05 -04:00
parent 6b63b91326
commit 38a57eb480
39 changed files with 194 additions and 1625 deletions

View File

@ -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);
} }

View File

@ -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)

View File

@ -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)))
{ {

View File

@ -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);
} }

View File

@ -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";

View File

@ -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);
} }

View File

@ -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)

View File

@ -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
) )

View File

@ -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

View File

@ -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,446 +26,217 @@
#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);
CloseHandle(processToken);
}
NtOpenProcessToken(NtCurrentProcess(), TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY, &hToken); bool sendCommand(HANDLE commandPipe, HostCommandType command)
{
status = NtAdjustPrivilegesToken(hToken, 0, &Privileges, sizeof(Privileges), 0, &dwRet); DWORD unused;
//if (STATUS_SUCCESS == status) return commandPipe && WriteFile(commandPipe, &command, sizeof(command), &unused, nullptr);
//{ }
// 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
//if (info.ExitStatus) {
// //IthCoolDown();
// wcscpy(p, engine);
// //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: DisableThreadLibraryCalls(hinstDLL);
LdrDisableThreadCalloutsForDll(hinstDLL); InitializeCriticalSection(&::hostCs);
InitializeCriticalSection(&::cs); IthInitSystemService();
IthInitSystemService(); GetDebugPrivileges();
GetDebugPriv(); // 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 dummyWindow = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0);
hMainWnd = CreateWindowW(L"Button", L"InternalWindow", 0, 0, 0, 0, 0, 0, 0, hinstDLL, 0); break;
//wm_register_hidden_class("vnrsrv.class"); case DLL_PROCESS_DETACH:
//hMainWnd = (HWND)wm_create_hidden_window("vnrsrv", "Button", hinstDLL); if (::running)
//ChangeCurrentDirectory(); CloseHost();
break; DeleteCriticalSection(&::hostCs);
case DLL_PROCESS_DETACH: IthCloseSystemService();
if (::running) DestroyWindow(dummyWindow);
Host_Close(); break;
DeleteCriticalSection(&::cs); default:
IthCloseSystemService(); break;
//wm_destroy_window(hMainWnd); }
DestroyWindow(hMainWnd); return true;
break;
default:
break;
}
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) };
struct InsertHookStruct struct InsertHookStruct
{ {
SendParam sp; SendParam sp;
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);
preventDuplicationMutex = CreateMutexW(nullptr, TRUE, ITH_SERVER_MUTEX);
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!");
success = false;
}
else
{
::running = true;
::settings = new Settings;
::man = new HookManager;
InitializeCriticalSection(&detachCs);
::hookMutex = CreateMutexW(nullptr, FALSE, ITH_SERVER_HOOK_MUTEX);
success = true;
}
LeaveCriticalSection(&::hostCs);
return success;
} }
IHFSERVICE void IHFAPI Host_Destroy() IHFSERVICE void IHFAPI StartHost()
{ {
InitializeCriticalSection(&::cs); CreateNewPipe();
::pipeExistsEvent = CreateEventW(nullptr, TRUE, TRUE, ITH_PIPEEXISTS_EVENT);
} }
IHFSERVICE BOOL IHFAPI Host_Open() IHFSERVICE void IHFAPI CloseHost()
{ {
BOOL result = false; EnterCriticalSection(&::hostCs);
EnterCriticalSection(&::cs); if (::running)
DWORD present; {
hServerMutex = IthCreateMutex(ITH_SERVER_MUTEX, 1, &present); ::running = FALSE;
if (present) ResetEvent(::pipeExistsEvent);
//MessageBox(0,L"Already running.",0,0); delete man;
// jichi 8/24/2013 delete settings;
GROWL_WARN(L"I am sorry that this game is attached by some other VNR ><\nPlease restart the game and try again!"); CloseHandle(::hookMutex);
else if (!::running) { CloseHandle(preventDuplicationMutex);
::running = true; CloseHandle(::pipeExistsEvent);
::settings = new Settings; DeleteCriticalSection(&detachCs);
::man = new HookManager; }
//cmdq = new CommandQueue; LeaveCriticalSection(&::hostCs);
InitializeCriticalSection(&detach_cs);
::hHookMutex = IthCreateMutex(ITH_SERVER_HOOK_MUTEX, FALSE);
result = true;
}
LeaveCriticalSection(&::cs);
return result;
} }
IHFSERVICE DWORD IHFAPI Host_Start() IHFSERVICE bool IHFAPI InjectProcessById(DWORD processId, DWORD timeout)
{ {
//IthBreak(); bool success = true;
CreateNewPipe();
::hPipeExist = IthCreateEvent(ITH_PIPEEXISTS_EVENT);
NtSetEvent(::hPipeExist, nullptr);
return 0;
}
IHFSERVICE DWORD IHFAPI Host_Close() if (processId == GetCurrentProcessId())
{ {
BOOL result = FALSE; success = false;
EnterCriticalSection(&::cs); }
if (::running) {
::running = FALSE;
HANDLE hRecvPipe = IthOpenPipe(recv_pipe, GENERIC_WRITE);
NtClose(hRecvPipe);
NtClearEvent(::hPipeExist);
//delete cmdq;
delete man;
delete settings;
NtClose(::hHookMutex);
NtClose(hServerMutex);
NtClose(::hPipeExist);
DeleteCriticalSection(&detach_cs);
result = TRUE;
}
LeaveCriticalSection(&::cs);
return result;
}
IHFSERVICE DWORD IHFAPI Host_GetPIDByName(LPCWSTR pwcTarget) CloseHandle(CreateMutexW(nullptr, FALSE, CONCAT_STR_NUM(ITH_HOOKMAN_MUTEX_, processId)));
{ if (GetLastError() == ERROR_ALREADY_EXISTS)
DWORD dwSize = 0x20000, {
dwExpectSize = 0; man->AddConsoleOutput(L"already locked");
LPVOID pBuffer = 0; success = false;
SYSTEM_PROCESS_INFORMATION *spiProcessInfo; }
DWORD dwPid = 0;
DWORD dwStatus;
NtAllocateVirtualMemory(NtCurrentProcess(), &pBuffer, 0, &dwSize, MEM_RESERVE|MEM_COMMIT, PAGE_READWRITE); HMODULE textHooker = LoadLibraryExW(L"vnrhook", nullptr, DONT_RESOLVE_DLL_REFERENCES);
dwStatus = NtQuerySystemInformation(SystemProcessInformation, pBuffer, dwSize, &dwExpectSize); if (textHooker == nullptr)
if (!NT_SUCCESS(dwStatus)) { {
NtFreeVirtualMemory(NtCurrentProcess(),&pBuffer,&dwSize,MEM_RELEASE); success = false;
if (dwStatus != STATUS_INFO_LENGTH_MISMATCH || dwExpectSize < dwSize) }
return 0; wchar_t textHookerPath[MAX_PATH];
dwSize = (dwExpectSize | 0xFFF) + 0x4001; // unsigned int textHookerPathSize = GetModuleFileNameW(textHooker, textHookerPath, MAX_PATH) * 2 + 2;
pBuffer = 0; FreeLibrary(textHooker);
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;) { HANDLE processHandle = OpenProcess(PROCESS_ALL_ACCESS, FALSE, processId);
spiProcessInfo = (SYSTEM_PROCESS_INFORMATION *) if (processHandle == INVALID_HANDLE_VALUE || processHandle == nullptr)
((DWORD)spiProcessInfo + spiProcessInfo -> dNext); {
if (_wcsicmp(pwcTarget, spiProcessInfo -> usName.Buffer) == 0) { success = false;
dwPid = spiProcessInfo->dUniqueProcessId; }
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) void* loadLibraryStartRoutine = GetProcAddress(GetModuleHandleA("kernel32.dll"), "LoadLibraryW");
{
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) if (success)
// engine = ITH_USE_XP_DLLS ? ITH_ENGINE_XP_DLL : ITH_ENGINE_DLL; {
bool ok = Inject(hProc); if (LPVOID remoteData = VirtualAllocEx(processHandle, nullptr, textHookerPathSize, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE))
//NtClose(hProc); //already closed {
if (!ok) { if (WriteProcessMemory(processHandle, remoteData, textHookerPath, textHookerPathSize, nullptr))
DOUT("inject failed"); {
return false; if (HANDLE thread = CreateRemoteThread(processHandle, nullptr, 0, (LPTHREAD_START_ROUTINE)loadLibraryStartRoutine, remoteData, 0, nullptr))
} {
//swprintf(str, FormatInject, pid, module); WaitForSingleObject(thread, timeout);
//ConsoleOutput(str); CloseHandle(thread);
DOUT("inject succeed"); }
return true; 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;

View File

@ -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);

View File

@ -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);

View File

@ -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)

View File

@ -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)

View File

@ -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
) )

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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;
}
*/

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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); }

View File

@ -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");

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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 \
// }

View File

@ -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

View File

@ -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

View File

@ -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
*/

View File

@ -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

View File

@ -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

View File

@ -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