Skip to content
Suzu
2 min read

【Windows Internal】SetWindowsHookEx 與 DLL 注入

SetWindowsHookEx 與 DLL 注入

Series
5 posts
View the complete series →
On this page

【Windows Internal】SetWindowsHookEx 與 DLL 注入

SetWindowsHookEx是 Windows 的訊息攔截機制,

設了一個 global hook 之後,系統會為了讓你的 CallBack Function 可以在別的 Process 裡面執行,

會把 Hook DLL inject 到每個收訊息的 Process,而且是合法的

組成&應用

Windows 上的程式之間都用訊息溝通(像是滑鼠點了、鍵盤按了這樣),

每個有視窗的 Process 都有訊息 Queue,

SetWindowsHookEx 讓你可以登記一個竊聽器,之後 Process 收訊息前都要經過你的處理函式

定義:

HHOOK SetWindowsHookExW(
  int       idHook,      // 鉤子類型,例如 WH_CALLWNDPROC
  HOOKPROC  lpfn,        // CallBack Function Pointer
  HINSTANCE hmod,        // CallBack Function 所在的 DLL 模組
  DWORD     dwThreadId   // 0 = 全域(桌面所有 Threads)
);

CallBack Function 必須要在目標 Process 的上下文裡面執行,

所以系統會把 hmod 指定的 DLL map 進目標 Process 的 Address Space,

->可以當成是 合法的 DLL 注入管道 (但目標 IL 還是要 <= Hook IL)

實作例子

// 設 Global Hook
bool SetupHook() {
	if (g_hook) { return true; }
	OutputDebugStringA("Setting up Windows hook.");
	g_hook = SetWindowsHookExW(WH_CALLWNDPROC, HookWndProc, g_instance, 0);
	return g_hook != nullptr;
}

// CallBack Function:在 Injected 目標 Process 的上下文裡執行
static LRESULT CALLBACK HookWndProc(_In_ int nCode, _In_ WPARAM wParam, _In_ LPARAM lParam)
{
	if (!g_spawned)
	{
		g_spawned = true;
		if (IsElevated() && _wcsicmp(GetModuleName().c_str(), L"cleanmgr.exe") == 0)
		{
			OutputDebugStringA("Creating privileged command prompt\n");
			...
			WCHAR cmdline[] = L"cmd.exe";
			BOOL result = CreateProcess(nullptr, cmdline, nullptr, nullptr, FALSE,
				CREATE_NEW_CONSOLE, nullptr, nullptr, &start_info, &proc_info);
		}
	}
	return CallNextHookEx(nullptr, nCode, wParam, lParam);  // 交棒給下一個 Hook
}

CallBack 結尾呼叫 CallNextHookEx 把訊息交棒給 Hook Chain 的下一個 Handler,

這樣就不會攔截、修改,

Hook 會比較穩定,也不容易把目標 Process 弄掛

Share this page