早期有款名為 "Eureka" 的工具,能通過 Windows 安全漏洞讀取其他程序輸入框中的密碼。微軟在 Windows 2000 中修補了該漏洞,但通過 SetWindowsHookEx 注入全局鉤子,仍可在所有 32 位 Windows 系統(95/98/ME/NT/2000/XP/2003)上實現密碼提取。本文介紹 PasswordSpy 工具的實現原理、關鍵技術難點及防範方案。
SetWindowPos(hWnd, HWND_TOPMOST, ...))。WM_COPYDATA 與內存映射文件 (MMF) 結合。WH_GETMESSAGE 鉤子監聽目標進程 GetMessage/PeekMessage,捕獲密碼框內容。SetWindowsHookEx 可將鉤子安裝到特定線程或全系統。WH_GETMESSAGE 鉤子在目標線程調用 GetMessage/PeekMessage 時觸發,鉤子回調函數在目標進程上下文中執行。
難點:鉤子句柄跨進程傳遞
HHOOK 返回給安裝進程 (A),但回調在目標進程 (B) 執行。CallNextHookEx 傳遞消息,需鉤子句柄。#pragma data_seg("Shared")
HHOOK g_hHook = NULL;
#pragma data_seg()
#pragma comment(linker, "/section:Shared,rws")
缺陷: 編譯器支持不一;未來 Windows 版本可能變更共享段語義;非線程安全,多線程並發訪問無同步。
封裝 CIPC 類,使用 CreateFileMapping/MapViewOfFile 實現跨進程共享內存,CreateMutex/WaitForSingleObject 保證線程同步。
// IPC.h 關鍵定義
#define IPC_SHARED_MMF _T("{34F673E0-878F-11D5-B98A-00B0D07B8C7C}")
#define IPC_MUTEX _T("{34F673E1-878F-11D5-B98A-00B0D07B8C7C}")
class CIPC {
public:
CIPC(); virtual ~CIPC();
bool CreateIPCMMF(); // 創建 MMF
bool OpenIPCMMF(); // 打開現有 MMF
void CloseIPCMMF();
bool ReadIPCMMF(LPBYTE pBuf, DWORD& dwBufSize);
bool WriteIPCMMF(const LPBYTE pBuf, const DWORD dwBufSize);
bool Lock(); // 獲取互斥量
void Unlock(); // 釋放互斥量
protected:
HANDLE m_hFileMap;
HANDLE m_hMutex;
};
實現細節見原文 IPC.cpp,核心邏輯:首個 DWORD 存數據長度,後跟實際數據;讀寫前加鎖,操作後解鎖。
密碼框不顯示真實字符長度,而是固定長度的佔位符(如 **************),Windows NT 服務對話框即採用此策略。優點:攻擊者無法推測密碼長度,獲取到的也是假密碼。
子類化編輯框,在 WM_GETTEXT 處理中返回偽造字符串。但無法隱藏真實長度(除非同時修改 WM_GETTEXTLENGTH)。
採用系統提供的 Secure Edit Control 或第三方安全鍵盤組件,繞過標準消息循環。
Windows 鉤子是強大但雙刃劍的技術。合法場景(如輸入法、螢幕閱讀器、自動化測試)依賴鉤子;惡意軟體亦利用鉤子竊取隱私。開發者應採用「顯示偽密碼 + 截獲 WM_GETTEXT + 安全輸入控件」多層防護,並在代碼簽名、完整性校驗等方面加強防範。