共用方式為


驅動程式與記憶體完整性和 VBS的相容性

記憶體完整性Windows 10、Windows 11 和 Windows Server 2016 及更新版本中提供的虛擬化式安全性 (VBS) 功能。 記憶體完整性和 VBS 可改善 Windows 的威脅模型,並針對嘗試惡意探索 Windows 核心的惡意代碼提供更強大的保護。 VBS 會使用 Windows Hypervisor 來建立隔離的虛擬環境,以成為操作系統的根信任,該操作系統假設核心可能會遭到入侵。 記憶體完整性是一個重要元件,可在 VBS的隔離虛擬環境中執行核心模式程序代碼完整性,以保護和強化 Windows。 記憶體完整性也會限制可用來危害系統的核心記憶體配置,確保核心記憶體頁面只有在安全運行時間環境內傳遞程式代碼完整性檢查之後才會成為可執行檔,而且可執行檔頁面本身絕不可寫入。

注意

記憶體完整性有時稱為受 Hypervisor 保護的程式代碼完整性(HVCI)Hypervisor 強制執行的程式代碼完整性,且最初是作為 Device Guard一部分發行。 除了在組策略或 Windows 登錄中尋找記憶體完整性和 VBS 設定之外,不再使用 Device Guard。

預設會在 S 模式中的 Windows 10 全新安裝時開啟記憶體完整性,並在相容的硬體上安裝 Windows 11,如記憶體完整性啟用中所述。 在其他不符合記憶體完整性自動啟用需求的系統上,客戶可以選擇使用如何啟用記憶體完整性中所述的任何方法

應用程式相容性

雖然自 Windows 10 年度更新版 (1607) 以來,所有驅動程式的相容性一直是所有驅動程式的需求,但某些應用程式和硬體設備驅動器可能仍然不相容。 這種不相容可能會導致裝置或軟體故障,而且在罕見的情況下可能會導致開機失敗(藍色畫面)。 在啟用進程本身開啟或啟用程序期間,可能會發生這類問題。 如果您是應用程式開發人員,且想要驗證驅動程式和軟體套件是否與記憶體完整性相容,請遵循下列步驟。

我們觀察到記憶體完整性不相容的一些範例包括:

  • 使用遊戲的反作弊解決方案
  • 第三方輸入法
  • 第三方銀行密碼保護

我們努力減輕受影響的體驗,因此,如果開機關鍵驅動程式存在不相容,如果記憶體完整性保護已啟用,將會以無訊息方式關閉。 如果您遇到與其他應用程式不相容的問題,建議您先檢查特定應用程式和版本是否有更新遇到問題,再關閉記憶體完整性保護。

如何建置相容的驅動程式

由於記憶體頁和區段永遠無法寫入且可執行,因此第一個步驟是確保清楚分隔數據和程序代碼,而不會嘗試直接修改代碼頁。

  • 根據預設,選擇加入 NX
  • 針對記憶體配置使用 NX API/旗標 - NonPagedPoolNx
  • 請勿使用可寫入和可執行的區段
  • 請勿嘗試直接修改可執行的系統記憶體
  • 請勿在核心中使用動態程序代碼
  • 請勿將數據檔載入為可執行檔
  • 區段對齊必須是0x1000的倍數(PAGE_SIZE)。 例如DRIVER_ALIGNMENT=0x1000

使用最新版本的 WDKVisual Studio ,在使用預設設定時產生相容的驅動程式。

如何確認驅動程式與記憶體完整性的相容性

驗證驅動程式相容性有三個步驟:

  1. 使用驅動程式驗證器(請參閱下一節),並啟用程式代碼完整性相容性檢查。
  2. 在已啟用記憶體完整性的系統上測試驅動程式。
  3. Windows HLK 中執行 HyperVisor 程式代碼完整性整備測試

驅動程式驗證器相容性檢查

驅動程式驗證工具具有程式代碼完整性選項旗標(0x02000000),可啟用額外的檢查,以驗證與記憶體完整性的相容性。 若要從命令行啟用此功能,請使用下列命令:

verifier.exe /flags 0x02000000 /driver <driver.sys>

若要在使用驗證器 GUI 時選擇此選項,請選擇 [建立自定義設定](適用於程式代碼開發人員),選擇 [下一步 ],然後選擇 [ 程序代碼完整性檢查]。

為了成功,沒有輸出。 以下是失敗輸出的範例。

Driver Verifier: Enabled for DvCi.sys, flags 0x2000000, build 16299, key o4Dbg8OVJqaBYlqWQ2QvRH

\*\*\*\*\*\*\*\*\*\*\* Verifier Detected a Code Integrity Issue \*\*\*\*\*\*\*\*\*\*\*\*

\*\* The caller 0xFFFFF8094B9852F0 specified an executable page protection 0x40.

\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*\*

\*\*\* Verifier assertion failed \*\*\*

(B)reak, (I)gnore, (W)arn only, (R)emove assert? B

測試已啟用記憶體完整性的驅動程式

雖然 Windows 預設會針對大多數系統開啟記憶體完整性,但有數個原因可能會防止這種情況發生。 若要開啟記憶體完整性,請參閱 如何開啟記憶體完整性。 然後,測試驅動程式的功能。 請務必練習驅動程式中的所有程式代碼路徑,以確保您的驅動程式不會在運行時間執行與記憶體完整性不相容的作業。

HLK 測試 (桌面與伺服器)

HLK 測試 HyperVisor 程式代碼完整性整備測試 必須通過,才能讓驅動程式獲得 Microsoft 簽署的核准。 桌面和伺服器版本都需要記憶體完整性相容驅動程式。 HLK 測試是撰寫的基本測試,以確保操作系統已正確載入並執行記憶體完整性相容驅動程式。

雖然只要通過 HLK 測試就足以讓驅動程式使用 Microsoft 簽章,但我們強烈建議使用已啟用記憶體完整性的徹底功能測試。 例如,可能會有不正確地編碼記憶體配置違反 NX 保護,導致測試不會攔截到的失敗。 驅動程式作者應該徹底測試驅動程式,同時保持記憶體完整性。

在驅動程式開發和 HLK 測試期間,可能需要停用記憶體完整性,因為它可以防止驅動程式載入。

HLK Hypervisor 程式代碼完整性整備測試是 Windows Server 保證 AQ 的一部分,而且也會在其他 HLK 測試期間啟用驅動程式驗證程式時設定啟用程式代碼完整性檢查的旗標。

常見問題集

現有驅動程式呢? 我需要重新建置這些驅動程式,讓他們能夠使用 Windows 10 嗎?

要看情況而定。 許多驅動程式已經相容。 如果使用標準設定搭配舊版 WDK 和 Visual Studio,已知問題是 INIT 區段標示為 RWX。 不過,在 Windows 10 中,W 會自動移除,因此,如果這是唯一的問題,驅動程式將會相容。

如何? 確認已啟用記憶體完整性嗎?

最簡單的方法是執行 系統資訊 應用程式 (msinfo32)。 尋找下列這一行:「虛擬化型安全性服務執行中」。 它應該回報:「Hypervisor 強制執行的程式代碼完整性」。 另外還有一個 WMI 介面可用來檢查使用管理工具,請參閱 驗證已啟用的 VBS 和記憶體完整性功能

記憶體完整性也可以在 設定 Update 和 Security Windows 安全性> 應用程式中檢查 Windows 安全性> 裝置安全性>>核心隔離詳細數據>記憶體完整性。 如需詳細資訊,請參閱 KB4096339

我是否可以從核心以程式設計方式驗證記憶體完整性,以改變驅動程序行為?

是,您可以使用 NtQuerySystemInformation: https://msdn.microsoft.com/library/windows/desktop/ms724509(v=vs.85).aspx

SYSTEM_CODEINTEGRITY_INFORMATION 結構已公開0x400值,表示記憶體完整性為開啟。

如何? 修正相容性問題?

除了重複檢查沒有 W+X 頁面,而且驅動程式區段會如上所述正確對齊,最有可能的問題是記憶體配置不正確。 下列頁面上的 MSDN 提供與所發出記憶體配置相關的程式代碼分析警告相關信息:

驅動程式警告的程式代碼分析

下列 MSDN 連結顯示一些常用的 API 範例,這些 API 會導致配置可執行記憶體,以及一些範例修正:

使用下表來解譯輸出,以判斷解決不同類型的 HVCI 不相容所需的驅動程式程式代碼變更。

警告 解決方法
執行集區類型 呼叫端指定了可執行的集區類型。 呼叫要求可執行記憶體的記憶體配置函式。 請確定所有集區類型都包含非可執行的 NX 旗標。
執行頁面保護 呼叫端指定了可執行的頁面保護。 指定「無執行」頁面保護遮罩。
執行頁面對應 呼叫端指定了可執行的記憶體描述元清單 (MDL) 對應。 請確定使用的遮罩包含 MdlMappingNoExecute。 如需詳細資訊,請參閱 MmGetSystemAddressForMdl 保管庫
Execute-Write 區段 映像包含可執行檔和可寫入區段。
區段對齊失敗 影像包含未對齊頁面的區段。 區段對齊必須是0x1000的倍數(PAGE_SIZE)。 例如DRIVER_ALIGNMENT=0x1000
不支援的 Relocs 在 Windows 10 版本 1507 到版本 1607 中,由於使用位址空間配置隨機化 (ASLR),位址對齊和記憶體重新配置可能會發生問題。 操作系統需要重新放置連結器將預設基位址設定為 ASLR 指派的實際位置的位址。 此重新配置無法跨越頁面界限。 例如,請考慮從頁面中位移0x3FFC開始的64位位址值。 其位址值會重疊至位移0x0003的下一頁。 Windows 10 版本 1703 之前不支援這種類型的重疊重新置放。

當全域結構類型變數初始化表達式具有另一個全域的錯位指標時,就會發生這種狀況,如此一來,連結器就無法移動變數,以避免分流重新配置。 鏈接器會嘗試移動變數,但在某些情況下,它可能無法執行此動作,例如,使用大型錯位結構或大量錯誤結構陣列。 適當時,應該使用 /Gy (COMDAT) 選項組合模組,讓連結器盡可能對齊模組程序代碼。

#include <pshpack1.h>

typedef struct _BAD_STRUCT {
      USHORT Value;
      CONST CHAR *String;
} BAD_STRUCT, * PBAD_STRUCT;

#include <poppack.h>

#define BAD_INITIALIZER0 { 0, "BAD_STRING" },
#define BAD_INITIALIZER1 \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0      \
      BAD_INITIALIZER0

#define BAD_INITIALIZER2 \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1      \
      BAD_INITIALIZER1

#define BAD_INITIALIZER3 \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2      \
      BAD_INITIALIZER2

#define BAD_INITIALIZER4 \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3      \
      BAD_INITIALIZER3

BAD_STRUCT MayHaveStraddleRelocations[4096] = { // as a global variable
      BAD_INITIALIZER4
};

還有其他情況涉及使用組合器程序代碼,此問題也可能發生。

可執行檔區段中的 IAT 匯入位址表 (IAT), 不應該是記憶體的可執行區段。

當 IAT 位於記憶體的唯讀和執行區段中時,就會發生此問題。 這表示 OS 將無法寫入 IAT,以設定參考 DLL 所在位置的正確位址。

其中一個可能發生這種情況的方法是在程式碼連結中使用 /MERGE (合併區段) 選項。 例如,如果 .rdata (只讀初始化的數據) 與 .text 數據合併 (可執行程式代碼),IAT 可能會最終出現在記憶體的可執行檔區段中。

哪些 API 可能會受到影響?

下列未保留供系統使用的 API 清單可能會受到影響:

   
API 名稱 描述
ExAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff544501(v=vs.85).aspx
ExAllocatePoolWithQuota https://msdn.microsoft.com/library/windows/hardware/ff544506(v=vs.85).aspx
ExAllocatePoolWithQuotaTag https://msdn.microsoft.com/library/windows/hardware/ff544513(v=vs.85).aspx
ExAllocatePoolWithTag https://msdn.microsoft.com/library/windows/hardware/ff544520(v=vs.85).aspx
ExAllocatePoolWithTagPriority https://msdn.microsoft.com/library/windows/hardware/ff544523(v=vs.85).aspx
ExInitializeNPagedLookasideList https://msdn.microsoft.com/library/windows/hardware/ff545301(v=vs.85).aspx
ExInitializeLookasideListEx https://msdn.microsoft.com/library/windows/hardware/ff545298(v=vs.85).aspx
MmAllocateContiguousMemory https://msdn.microsoft.com/library/windows/hardware/ff554460(v=vs.85).aspx
MmAllocateContiguousMemorySpecifyCache https://msdn.microsoft.com/library/windows/hardware/ff554464(v=vs.85).aspx
MmAllocateContiguousMemorySpecifyCacheNode https://msdn.microsoft.com/library/windows/hardware/ff554464(v=vs.85).aspx
MmAllocateContiguousNodeMemory https://msdn.microsoft.com/library/windows/hardware/jj602795(v=vs.85).aspx
MmCopyMemory https://msdn.microsoft.com/library/windows/hardware/dn342884(v=vs.85).aspx
MmMapIoSpace https://msdn.microsoft.com/library/windows/hardware/ff554618(v=vs.85).aspx
MmMapLockedPages https://msdn.microsoft.com/library/windows/hardware/ff554622(v=vs.85).aspx
MmMapLockedPagesSpecifyCache https://msdn.microsoft.com/library/windows/hardware/ff554629(v=vs.85).aspx
MmProtectMdlSystemAddress https://msdn.microsoft.com/library/windows/hardware/ff554670(v=vs.85).aspx
ZwAllocateVirtualMemory https://msdn.microsoft.com/library/windows/hardware/ff566416(v=vs.85).aspx
ZwCreateSection https://msdn.microsoft.com/library/windows/hardware/ff566428(v=vs.85).aspx
ZwMapViewOfSection https://msdn.microsoft.com/library/windows/hardware/ff566481(v=vs.85).aspx
NtCreateSection https://msdn.microsoft.com/library/windows/hardware/ff556473(v=vs.85).aspx
NtMapViewOfSection https://msdn.microsoft.com/library/windows/hardware/ff556551(v=vs.85).aspx
StorPortGetDataInBufferSystemAddress https://msdn.microsoft.com/library/windows/hardware/jj553720(v=vs.85).aspx
StorPortGetSystemAddress https://msdn.microsoft.com/library/windows/hardware/ff567100(v=vs.85).aspx
DxgkCbMapMemory https://msdn.microsoft.com/library/windows/hardware/ff559533(v=vs.85).aspx
IMiniportDMus::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536701(v=vs.85).aspx
FltAllocatePoolAlignedWithTag https://msdn.microsoft.com/library/windows/hardware/ff541762(v=vs.85).aspx
FltAllocateContext https://msdn.microsoft.com/library/windows/hardware/ff541710(v=vs.85).aspx
ChangerClassAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff551402(v=vs.85).aspx
IMiniportMidi::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536710(v=vs.85).aspx
IMiniportWaveCyclic::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536723(v=vs.85).aspx
IPortWavePci::NewMasterDmaChannel https://msdn.microsoft.com/library/windows/hardware/ff536916(v=vs.85).aspx
IMiniportWavePci::NewStream https://msdn.microsoft.com/library/windows/hardware/ff536735(v=vs.85).aspx
PcNewDmaChannel https://msdn.microsoft.com/library/windows/hardware/ff537712(v=vs.85).aspx
PcNewResourceList https://msdn.microsoft.com/library/windows/hardware/ff537717(v=vs.85).aspx
PcNewResourceSublist https://msdn.microsoft.com/library/windows/hardware/ff537718(v=vs.85).aspx
VideoPortAllocatePool https://msdn.microsoft.com/library/windows/hardware/ff570180(v=vs.85).aspx
ClfsCreateMarshallingArea https://msdn.microsoft.com/library/windows/hardware/ff541520(v=vs.85).aspx
WdfLookasideListCreate https://msdn.microsoft.com/library/windows/hardware/ff548694(v=vs.85).aspx
WdfMemoryCreate https://msdn.microsoft.com/library/windows/hardware/ff548706(v=vs.85).aspx
WdfDeviceAllocAndQueryProperty https://msdn.microsoft.com/library/windows/hardware/ff545882(v=vs.85).aspx
WdfDeviceAllocAndQueryPropertyEx https://msdn.microsoft.com/library/windows/hardware/dn265599(v=vs.85).aspx
WdfFdoInitAllocAndQueryProperty https://msdn.microsoft.com/library/windows/hardware/ff547239(v=vs.85).aspx
WdfFdoInitAllocAndQueryPropertyEx https://msdn.microsoft.com/library/windows/hardware/dn265612(v=vs.85).aspx
WdfIoTargetAllocAndQueryTargetProperty https://msdn.microsoft.com/library/windows/hardware/ff548585(v=vs.85).aspx
WdfRegistryQueryMemory https://msdn.microsoft.com/library/windows/hardware/ff549920(v=vs.85).aspx
NdisAllocateMemory https://msdn.microsoft.com/library/windows/hardware/ff550762(v=vs.85).aspx