Windows 登錄檔架構簡介

Windows 登錄檔是一個 層次結構資料庫 ,作為 Windows 作業系統的中樞神經系統,儲存作業系統、已安裝應用程式及使用者偏好設定的關鍵設定。取代早期 Windows 版本使用的過時 .INI 檔案,登錄檔提供一個 統一儲存庫 ,供系統和應用程式設定參考,Windows 在執行時期會持續存取。技術上,登錄檔採用樹狀結構,由 Key (類似目錄)和 Value (類似檔案)組成,分為數個Root Key(稱為 hives),各有不同用途。

從安全研究的角度來看,登錄檔呈現一個 複雜的攻擊面 ,具有幾個關鍵特性:它主要位於核心 Windows Kernel(ntoskrnl.exe)中,全部以記憶體不安全的 C 語言撰寫,管理敏感系統資訊,且在大多數設定下可被非特權使用者存取。

這些因素結合使得登錄檔操作成為系統最佳化和進攻性安全操作的基本技術,包括 持續性機制 權限提升 防禦規避

註冊表漏洞解密:駭客的C++攻擊手法與關鍵防禦策略 | 資訊安全新聞

登錄檔結構與技術基礎

層次組織

登錄檔的架構分為五個主要的邏輯 hives,形成其層次結構的根部:

HKEY_CLASSES_ROOT (HKCR)
檔案關聯映射和 COM 物件註冊
HKEY_CURRENT_USER (HKCU)
使用者特定設定和偏好
HKEY_LOCAL_MACHINE (HKLM)
系統範圍的設定和硬體設定
HKEY_USERS (HKU)
所有當前載入的使用者設定檔
HKEY_CURRENT_CONFIG (HKCC)
系統啟動時的硬體設定檔

每個登錄檔值以特定格式儲存資料。最常見的資料類型包括:

資料類型 描述 大小
REG_SZ 以空字元結尾的字串 可變
REG_DWORD 32位元整數 4 位元組
REG_QWORD 64位元整數 8 位元組
REG_BINARY 二進位資料 可變
REG_MULTI_SZ 以空字元結尾的字串陣列 可變

安全特性與漏洞類別

登錄檔在 Windows Kernel 中的實作暴露了多個安全研究者必須考慮的漏洞類別:

  • Hive 記憶體損壞 :修改登錄檔結構的操作可能因可變長度陣列和參考計數物件導致緩衝區溢位或釋放後使用問題。
  • 手動參考計數漏洞 :安全描述符(Security descriptor)使用 32 位元參考計數,易受整數溢位(Overflow )和下溢(Underflow)影響,可能導致釋放後使用問題(CVE-2023-28248, CVE-2024-43641)。
  • Race Condition :多執行緒存取造成同步挑戰和潛在的「雙重提取(Double fetch)」漏洞。
  • 資訊洩露 :Kernel-登錄檔互動可能將未初始化的資料洩露給使用者模式應用程式。
  • 存取控制問題 :未正確保護的 Key 允許權限提升和未授權的修改。

現代 C++ 登錄檔操作技術

登錄檔 API 的演進

早期的登錄檔操作需要複雜的 API 串連:開發者需呼叫 RegOpenKeyEx 取得 Handle,然後使用 RegQueryValueEx (返回未正確終止的字串),最後呼叫 RegCloseKey - 每一步都需要手動錯誤檢查。Windows Vista 引入 RegGetValue 顯著簡化了取值方式,自動處理 Key 生命週期管理和正確的字串終止。然而,其 C 風格的介面對開發者來說仍然複雜。

C++ 抽象模式

現代 C++ 透過更高層次的抽象,使登錄檔操作更安全且直觀。一個關鍵模式是建立基於異常的錯誤處理,取代傳統的回傳碼檢查:

  1. // Exception class for registry errors
  2. class RegistryError : public std::runtime_error {
  3. public:
  4. RegistryError(const char* message, LONG errorCode)
  5. : std::runtime_error{message}, m_errorCode{errorCode} {}
  6. LONG ErrorCode() const noexcept { return m_errorCode; }
  7. private:
  8. LONG m_errorCode;
  9. };

此異常類別為特定類型讀取函數奠定了基礎。讀取 DWORD 值展示了透過抽象實現的簡化:

  1. // Reading a DWORD value from registry
  2. DWORD RegGetDword(HKEY hKey, const std::wstring& subKey,
  3. const std::wstring& value) {
  4. DWORD data{};
  5. DWORD dataSize = sizeof(data);
  6. LONG retCode = ::RegGetValue(hKey, subKey.c_str(), value.c_str(),
  7. RRF_RT_REG_DWORD, nullptr, &data, &dataSize);
  8. if (retCode != ERROR_SUCCESS) {
  9. throw RegistryError{"Cannot read DWORD from registry.", retCode};
  10. }
  11. return data;
  12. }

字串取出因資料長度可變而需要額外複雜性。推薦的模式涉及 雙重 API 呼叫 - 首先確定緩衝區大小,然後取出實際值:

  1. // Reading a string value from registry
  2. std::wstring RegGetString(HKEY hKey, const std::wstring& subKey,
  3. const std::wstring& value) {
  4. DWORD dataSize{};
  5. LONG retCode = ::RegGetValue(hKey, subKey.c_str(), value.c_str(),
  6. RRF_RT_REG_SZ, nullptr, nullptr, &dataSize);
  7. if (retCode != ERROR_SUCCESS) {
  8. throw RegistryError{"Cannot read string from registry.", retCode};
  9. }
  10. std::wstring buffer;
  11. buffer.resize(dataSize / sizeof(wchar_t));
  12. retCode = ::RegGetValue(hKey, subKey.c_str(), value.c_str(),
  13. RRF_RT_REG_SZ, nullptr, &buffer[0], &dataSize);
  14. if (retCode != ERROR_SUCCESS) {
  15. throw RegistryError{"Cannot read string from registry.", retCode};
  16. }
  17. buffer.resize((dataSize - 1) / sizeof(wchar_t)); // Remove NUL terminator
  18. return buffer;
  19. }

登錄檔修改模式

除了讀取值外,C++ 程式經常需要建立或修改Registry key。以下模式展示了使用 RegCreateKeyEx RegSetValueEx 進行穩健的鍵建立和值設定:

  1. // Creating and setting registry values
  2. void setRegistryKeyValue(HKEY hKey, const std::string& subKey,
  3. const std::string& valueName, const std::string& data) {
  4. HKEY key;
  5. DWORD disposition;
  6. LONG result = RegCreateKeyEx(hKey, subKey.c_str(), 0, NULL,
  7. REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL,
  8. &key, &disposition);
  9. if (result == ERROR_SUCCESS) {
  10. result = RegSetValueEx(key, valueName.c_str(), 0, REG_SZ,
  11. (const BYTE*)data.c_str(), data.size() + 1);
  12. if (result != ERROR_SUCCESS) {
  13. std::cerr << "Error setting value: " << result << std::endl;
  14. }
  15. RegCloseKey(key);
  16. } else {
  17. std::cerr << "Error creating key: " << result << std::endl;
  18. }
  19. }

REG_OPTION_NON_VOLATILE 標誌確保 Key 在重啟後持續存在,而 KEY_SET_VALUE 指定遵循 最小權限原則 的最低必要存取權限。

安全影響與攻擊向量

持續性機制

基於登錄檔的持續性因其可靠性和低可見性仍是主要的攻擊向量:

  • Run/RunOnce 鍵 :惡意軟體常針對 HKCU\Software\Microsoft\Windows\CurrentVersion\Run HKLM\...\Run 實現使用者或系統級別的持續性。RunOnce 變體在執行後自動移除進入點(Entry),減少鑑識 Artifact。
  • 服務修改 :攻擊者針對 HKLM\System\CurrentControlSet\Services 建立或修改服務進入點,以 SYSTEM 權限執行。此技術符合 MITRE ATT&CK 技術 T1547.001
  • 檔案關聯劫持 :修改 HKCR Subkey允許攻擊者在使用者開啟常見檔案類型時執行惡意程式碼。

防禦規避與權限提升

登錄檔操作啟用了複雜的規避技術:

  • 安全工具停用 :修改 HKLM\SOFTWARE\Policies\Microsoft\Windows Defender 或在 HKLM\...\Policies\System 下設定 DisableTaskMgr=1 可停用關鍵安全監控。
  • UAC 繞過 :在 HKCU\...\Policies\System 中設定 EnableLUA=0 可有效停用使用者帳戶控制保護。
  • 環境變數操作 :更改 HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders 中的 shell 資料夾促進路徑攔截攻擊(MITRE ATT&CK T1574.007 )。

檢測挑戰

相較於基於檔案的技術,登錄檔攻擊呈現獨特的檢測難度:

  • 低可見性 :傳統檔案監控解決方案通常忽略登錄檔修改,特別是使用 Native API 時。
  • 合法混合 :惡意變更與合法系統修改混合,透過基於簽章的工具難以識別。
  • 最少鑑識 Artifact :揮發性登錄檔修改留下有限的痕跡,特別是使用基於交易的操作在失敗時 Roll back。

防禦策略與最佳實務

監控與檢測

進階登錄檔監控需要多層次方法:

  • Sysmon 設定 :部署系統監控器,設定記錄敏感鍵的修改,特別是 Registry Key => Run 和服務設定。例如事件 ID 12(RegistryEvent)和 13(RegistryValueSet)提供關鍵稽核功能。
  • 即時登錄檔稽核 :透過群組原則啟用 Windows native auditing( 電腦設定 > 原則 > Windows 設定 > 安全性設定 > 進階稽核原則設定 > 稽核原則 > 物件存取 > 稽核登錄檔 )以產生事件 4657 來記錄登錄檔修改。
  • 定期基準比較 :使用像 Regshot 這樣的工具捕捉登錄檔快照,檢測時間間隔內的未授權修改。
  • EDR 整合 :設定端點檢測解決方案以標記可疑的登錄檔寫入模式,特別是未簽署程序對安全相關鍵的修改。

強化與存取控制

主動登錄檔強化顯著減少攻擊面:

  • 最小權限原則 :使用群組原則限制敏感 hives 的寫入權限。Service registry key 應僅由 SYSTEM 和管理員修改。
  • 應用程式控制原則 :實作白名單解決方案以防止未授權的可執行檔修改 Registry key,儘管研究者已展示繞過技術。
  • Critical key 保護 :監控並警示高價值目標的變更,包括:
HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
HKLM\SYSTEM\CurrentControlSet\Services\*
HKCU\Environment
HKLM\Software\Policies\Microsoft\Windows Defender
HKLM\SYSTEM\CurrentControlSet\Control\Terminal Server\fDenyTSConnections

新興保護技術

創新方法正在解決登錄檔安全限制:

  • 執行時期加密 :研究展示透過 hook 登錄檔 API 來透明加密/解密敏感值,使用 DPAPI 管理的金鑰,防止即使具有登錄檔存取權的認證採集。
  • 登錄檔虛擬化沙箱 :實驗性解決方案將登錄檔修改隔離在使用者特定的容器中,限制橫向移動影響。
  • 機器學習異常檢測 :登錄檔存取模式的行為分析可識別基於簽章的工具遺漏的可疑活動。

結論與未來研究方向

透過 C++ 程式進行 Windows 登錄檔操作代表一種 雙重用途能力 ,對系統管理和進攻性安全均有重大影響。登錄檔 API 的技術深度實現了從合法設定管理到隱形攻擊者持續性機制的複雜操作。現代 C++ 抽象簡化了登錄檔互動,同時引入了關於 API 信任邊界和異常安全的新安全考量。

未來研究的重要領域包括開發 跨平台登錄檔稽核框架 以規範不同環境的遙測資料、增強 執行時期加密性能 以最小化操作影響,以及建立 標準化行為剖繪 以提升異常檢測的準確性。此外,研究 交易式登錄檔操作 可能產生防止不一致狀態漏洞(Inconsistent state vulnerability)的新方法。

隨著 Windows 不斷發展,儘管出現了像 Windows Runtime 設定系統這樣的替代方案,登錄檔仍是一個關鍵系統組件。其層次結構和程式化存取確保了對攻擊者和防禦者的持續相關性。持續技術檢查登錄檔內部、操作技術和防禦對策對於在日益複雜的威脅環境中維持系統安全至關重要。

參考資料

  1. Windows Registry Manipulation Techniques
  2. Windows Registry Manipulation via C Program
  3. Researchers Use C++ to Modify Windows Registry for System Configuration
  4. Microsoft Documentation: Windows Registry
  5. MITRE ATT&CK: Modify Registry
  6. Registry Key Security and Access Rights
  7. Use Modern C++ to Access the Windows Registry
  8. Windows Registry attacks: Knowledge is the best defense
  9. Unlocking the Windows Registry: A Hidden Goldmine for Cyber Threat Detection

關鍵技術概念

  • 登錄檔 Hive 結構
  • 資料類型與儲存
  • Win32 登錄檔 API
  • C++ 登錄檔抽象
  • 存取控制列表
  • 登錄檔虛擬化
  • 持續性機制
  • 安全描述符
  • 登錄檔交易
  • 防禦規避技術

關鍵登錄檔路徑

  • 開機設定: HKLM\SYSTEM\CurrentControlSet
  • 啟動程式: HKLM\SOFTWARE\Microsoft\Windows\CurrentVersion\Run
  • 檔案關聯: HKCR\.ext
  • 使用者設定: HKCU\Environment
  • 系統原則: HKLM\SOFTWARE\Policies
  • 服務設定: HKLM\SYSTEM\CurrentControlSet\Services
  • 安全性設定: HKLM\SOFTWARE\Policies\Microsoft\Windows Defender

最佳實務

  • 始終檢查登錄檔函數的回傳碼
  • 使用適當的登錄檔資料類型
  • 限制僅在必要情況下進行寫入操作
  • 實作備份/還原機制
  • 遵循最小權限原則
  • 盡可能優先使用 HKCU 而非 HKLM
  • 正確處理 32/64 位元登錄檔視圖
  • 為關鍵鍵啟用登錄檔稽核
  • 使用 Sysmon 進行進階監控
  • 為敏感值實作執行時期加密

MITRE ATT&CK 技術

  • T1112:修改登錄檔
  • T1547.001:登錄檔執行鍵/啟動資料夾
  • T1574.007:透過登錄檔進行路徑攔截
  • T1012:查詢登錄檔
  • T1059.003:Windows 命令殼層
  • T1562.001:停用或修改工具
Copyright © 2025 版權所有 翊天科技有限公司