在 Windows NT 系列作業系統中,獲取登入使用者密碼一直是安全研究的重要課題。本文將深入探討三種主要技術路線,並著重分析在 Windows Server 2003 環境下,如何透過 LSASS 進程記憶體提取明文密碼的可行性與挑戰。
透過 Hook 住 Winlogon 關鍵函數,攔截登入過程中的憑證資料。網路上存在如 WinLogonHijack 等專案,但此類方法僅對本地登入有效,無法捕獲遠端桌面(Terminal Services)登入的憑證。
GINA (Graphical Identification and Authentication) 是 Winlogon 呼叫的驗證元件。透過替換或攔截 GINA DLL 中的特定函數,可記錄所有登入類型(本地與遠端)的密碼,穩定性較高。然而,Windows XP/2003 引入了新的 Winlogon 函數,導致現有的 GINA 後門程式因缺少匯出函數而失效。
早期在 NT 4.0/2000 中,工具如 findpass 可直接從 Winlogon 進程記憶體的固定位址讀取帳號、域名與明文密碼。但在 XP/2003 中,Winlogon 不再以固定模式儲存憑證,此法失效。
雖然 Winlogon 不再保存明文,但 LSASS (Local Security Authority Subsystem Service) 進程在處理認證時必須使用明文密碼。微軟未對 LSASS 記憶體中的密碼加密(理由是加密仍需可逆解密,不如直接明文存放效率高),因此登入使用者的明文密碼確實存在於 LSASS 進程記憶體中。
LogonUser() API 以已知帳號密碼模擬登入,搜尋該已知密碼在記憶體中的位置,推測其他密碼的大致儲存區域(密碼通常儲存在相鄰記憶體區塊)。以下測試程式採用基礎特徵搜尋法:在 LSASS 記憶體中尋找字串 "LocalSystem Remote Procedure Call",該字串後方常緊鄰 Unicode 格式的密碼資料。成功率受限於上述困難,但在「管理員僅本地/終端登入一次且未鎖定工作站」的場景下成功率較高。
//********************************************************************************
// Version: V1.0
// Coder: WinEggDrop
// Date Release: 12/15/2004
// Purpose: Demonstrate Searching Logon User Password On 2003 Box
// Test Platform: Windows Server 2003
// Compiled On: VC++ 6.0
//********************************************************************************
#include
#include
#include
#include
#define BaseAddress 0x002b5000
char Password[MAX_PATH] = {0};
// 函式原型宣告
BOOL FindPassword(DWORD PID);
int Search(char *Buffer, const UINT nSize);
DWORD GetLsassPID();
BOOL Is2003();
int main() {
DWORD PID = 0;
printf("Windows 2003 Password Viewer V1.0 By WinEggDrop\n\n");
if (!Is2003()) {
printf("This program only runs on Windows 2003.\n");
return -1;
}
PID = GetLsassPID();
if (PID == 0) return -1;
FindPassword(PID);
return 0;
}
// 搜尋記憶體緩衝區,嘗試定位密碼
int Search(char *Buffer, const UINT nSize) {
// ... 手動搜尋 "LocalSystem Remote Procedure Call" 特徵字串 ...
// ... 找到後解析後續 Unicode 字串為密碼 ...
return -1; // 簡化示意
}
DWORD GetLsassPID() {
// 使用 Toolhelp32 快照遍歷進程,找到 lsass.exe 的 PID
return 0; // 簡化示意
}
BOOL FindPassword(DWORD PID) {
// OpenProcess -> ReadProcessMemory -> Search -> 輸出結果
return TRUE;
}
BOOL Is2003() {
OSVERSIONINFOEX osvi = {0};
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX);
GetVersionEx((OSVERSIONINFO*)&osvi);
return (osvi.dwMajorVersion == 5 && osvi.dwMinorVersion == 2);
}
三種方法中,GINA 攔截法最穩定安全;Winlogon Hook 影響系統穩定;LSASS 記憶體搜尋準確率低。防禦面建議:啟用「安全登入」(Ctrl+Alt+Del)、部署防毒軟體監控異常記憶體讀取、限制服務安裝權限、定期修補系統漏洞。
Windows 2000 Server 入侵偵測實戰技巧:IIS 日誌分析、Unicode 攻擊識別、命令列快速過濾
Windows 2000 磁碟碎片整理完整指南:碎片類型、分析時機、執行流程與 MFT/分頁檔案優化
Longhorn 4051 深度體驗(一):安裝需求、硬體規格、新介面架構、側邊欄與 IE 革新
Windows Server 2008 Active Directory 改進:唯讀網域控制站 (RODC) 完整架構與部署指南
Windows Server 2003 建立開機磁碟片完整教學:有/無 2003 環境雙重情境、SCSI/IDE 開機參數配置
Windows Server 2003 運行 Sysprep 時套用自訂使用者設定
Windows 2000 Outlook Express 聯絡人與通訊錄管理:建立、群組、LDAP、vCard、匯入匯出、列印
Windows Server 2008 終端服務深度增強:Gateway、RemoteApp、Web Access 全方位解析