更新紀錄(僅初版,2026年08月22日 發布)
- 初次發布
引用本文(DOI(已登錄存檔): 10.5281/zenodo.22176891)
以下 DOI 指向先前登錄的存檔,內容可能與目前正文不同。引用目前正文時,請使用本頁網址。
Go Komura(2026)。〈Windows 虛擬化的深層(第 2 回)── 連核心也讀不到的記憶體:VBS、HVCI 與 Credential Guard 的運作方式〉。小村軟體有限公司。 https://comcomponent.com/zh-TW/blog/windows-virtualization-internals-vbs-hvci-credential-guard/
- DOI(已登錄存檔)
- 10.5281/zenodo.22176891
- DOI(上次登錄版本)
- 10.5281/zenodo.22176892
連系統管理員權限和核心都讀不到的秘密,Windows 究竟放在哪裡? 第 2 回就從這個問題出發,來看 VBS、HVCI 與 Credential Guard 的運作方式。
在以往的 Windows 上,攻擊者以系統管理員身分載入核心驅動程式、傾印 LSASS 處理程序的記憶體,就能偷走密碼雜湊與 Kerberos 票證,再拿它們橫向移動到別的機器。
在 Credential Guard 正在執行的 Windows 11 上,受保護的網域認證資料雜湊不會放在一般核心找得到的地方。在符合 Enterprise、Education 等授權需求與硬體需求的裝置上,從 22H2 起這項保護預設啟用。1 需求與實際的執行狀態是兩回事,所以並不代表「沒有在執行時的風險」就此消失。
第 1 回看到的是主機 Windows 執行在 Hypervisor 之上的根分割區裡這個結構。本文要追的,是在同一個分割區內部再畫出的另一條界線。
「Windows 虛擬化的深層」全 3 回
同一個 Windows Hypervisor,依基礎 → 安全性的隔離 → 輕量虛擬機的應用這個順序來看。
| 回 | 核心提問 |
|---|---|
| 第 1 回:Hypervisor 與分割區 | 主機 Windows 究竟在哪裡執行 |
| 第 2 回:VBS、HVCI 與 Credential Guard(本文) | 連核心也讀不到的秘密放在哪裡 |
| 第 3 回:WSL2、Windows Sandbox 與容器 | 維持隔離的同時,為什麼還能做得這麼輕 |
本文的前提
| 項目 | 內容 |
|---|---|
| 目標讀者 | 想弄清楚核心隔離、記憶體完整性與 Credential Guard 究竟是什麼的開發者與維運人員 |
| 前提環境 | x64 的 Windows 10/11 或現行的 Windows Server。關於 ring 與 SLAT 的說明以 x64 為前提,Arm64 用的是例外等級等另一套機制 |
| 前提知識 | 第 1 回的分割區與 SLAT 概念 |
| 難度與範圍 | 中階。不是設定手冊,而是解說安全性功能的結構 |
本文的讀法
| 想知道的事 | 要讀的章節 |
|---|---|
| 為什麼需要比核心更強的隔離,以及怎麼做到 | 第 2 節:傳統模型的極限 → 第 3 節:VSM、VTL 與 SLAT |
| HVCI 與 Credential Guard 各自保護什麼 | 第 4 節:程式碼完整性 → 第 5 節:認證資料與保護範圍 |
| 怎麼把設定畫面和實際執行狀態分開來讀 | 第 6 節:確認方式 → 第 7 節:誤讀 |
1. 先講結論
Windows 多加了 VTL(虛擬信任等級)這一條特權的軸,並把秘密放在 VTL1。在 VTL0 執行的一般核心讀不到 VTL1 的記憶體。守住這條界線的不是核心自己,而是握著 SLAT 轉譯表的 Hypervisor。
這就是以虛擬化為基礎的安全性(VBS)的骨架。VBS 用 Hypervisor 做出隔離環境,把安全性功能收在裡面。它的設計前提是:就算核心被攻陷,隔離環境依然安全。2
flowchart TB
accTitle: VBS 做出的兩個世界
accDescr: 同一個分割區裡有 VTL0 與 VTL1,VTL0 中是一般核心與應用程式,VTL1 中是安全核心與被隔離的安全性功能,界線由 Hypervisor 守住
subgraph vtl0 ["VTL0(一般的世界)"]
apps["應用程式(ring 3)"]
ntk["NT 核心與驅動程式(ring 0)"]
end
subgraph vtl1 ["VTL1(被隔離的世界)"]
ium["被隔離的安全性功能"]
sk["安全核心"]
end
hv["Hypervisor(用 SLAT 強制界線)"] --- vtl0
hv --- vtl1
ntk -.->|無法讀取| ium
圖1:一個 Windows 裡存在兩個世界,VTL0 的核心無法存取 VTL1 的記憶體。
重點在於,這並不是「另外開了一台虛擬機」。VTL0 與 VTL1 位在同一個分割區、同一個 Windows 的內部。以下就依序來看這個切分是怎麼做到的。
圖中實線表示始終成立的關係,虛線表示附帶條件的關係(成立條件寫在詳細頁面中各關係的說明中)。關係的完整清單(共 22 條,附依據與可信度)以及主要概念的定義,彙整在知識地圖詳細頁面(日文)。資料:JSON-LD / Turtle
2. ring 模型的極限 ── 守的一方和被守的一方站在同一個高度
以往 Windows 的安全性,蓋在 ring(特權等級)這道階梯之上。使用者模式(ring 3)由核心模式(ring 0)守護。那麼 ring 0 由誰來守──沒有人守得了。因為 ring 0 就是最高特權。
這個結構有兩個根本上的弱點。
- 核心並不是鐵板一塊。 ring 0 上執行的不只有 Windows 本體,還有大量第三方驅動程式。其中任何一個有漏洞,攻擊者就能拿到 ring 0 的程式碼執行權。
- 從 ring 0 什麼都看得見。 像 LSASS 這種使用者模式處理程序再怎麼自保,對掌握核心的攻擊者而言記憶體都是隨便讀的。因為保護屬性與分頁表本來就由核心自己管理。
flowchart TB
accTitle: 傳統 ring 模型下認證資料被竊取的路徑
accDescr: 透過有漏洞的驅動程式拿下 ring 0 的攻擊者,可以用核心的全部權限讀取 LSASS 處理程序的記憶體,取得密碼雜湊
mal["攻擊者的程式碼"] -->|利用有漏洞的驅動程式| r0["拿下 ring 0"]
r0 --> readall["能讀取全部實體記憶體"]
readall --> lsass["從 LSASS 的記憶體取得雜湊"]
lsass --> lateral["用來橫向移動到別的機器"]
圖2:守的一方(核心)和被守的一方(秘密)站在同一個高度,所以 ring 0 一失守就全盤皆輸,這是根本的弱點。
也就是說,需要的是「比 ring 0 更高的位置」。第 1 回裡,這個位置已經登場過了。Hypervisor 以高於核心的特權執行,並在很早的階段獨佔 CPU 的記憶體存取權限控制(SLAT)。Hypervisor 守住的隔離區域,面對來自 ring 0(supervisor 模式)的作業系統軟體的存取同樣受保護。3
3. VSM 與 VTL ── 替特權再加一條軸
本節依提供隔離的功能群(VSM)→ 隔離的等級(VTL)→ 強制界線的機制(SLAT)→ 在裡面執行的程式碼這個順序整理。名字相似,但並不是同一樣東西。
3.1. 虛擬信任等級(VTL)
提供這種隔離的 Hypervisor 功能群,稱為 VSM(虛擬安全模式)。VSM 是 Device Guard、Credential Guard、虛擬 TPM 等的基礎。3
VSM 的核心概念是 VTL(Virtual Trust Level:虛擬信任等級)。重點如下。3
- VTL 是分層的,編號越大特權越高。VTL0 最低,VTL1 的特權高於 VTL0。
- 架構上定義了最多 16 個等級,但目前實作的是 VTL0 與 VTL1 這兩個。
- 每個 VTL 各自擁有獨立的記憶體存取保護。這些保護由 Hypervisor 針對分割區的實體位址空間管理,因此分割區內的系統軟體無法變更。
- 虛擬處理器在每個 VTL 上各自擁有暫存器狀態與中斷機制,低 VTL 窺看不到高 VTL 的狀態。
flowchart TB
accTitle: 構成 VTL 隔離的三項獨立
accDescr: 每個 VTL 的記憶體存取保護、虛擬處理器的暫存器狀態與中斷機制都各自獨立,低 VTL 碰不到高 VTL 的任何一項
vtl["每個 VTL 各自獨立的東西"] --> m1["記憶體存取保護"]
vtl --> m2["虛擬處理器的暫存器狀態"]
vtl --> m3["中斷機制"]
m1 -.-> rule["低 VTL 碰不到高 VTL"]
m2 -.-> rule
m3 -.-> rule
圖3:不只是記憶體,連 CPU 的狀態與中斷都做成另一個世界,才是不留窺孔的三件組。
如果說 ring(0 與 3)是切分「作業系統與應用程式」的軸,那麼 VTL 就是切分「一般世界與隔離世界」的第二條軸。兩條軸彼此正交,VTL1 內部同樣有核心模式與使用者模式。
flowchart TB
accTitle: ring 與 VTL 兩條軸做出的四個區域
accDescr: ring 這條軸切分核心模式與使用者模式,VTL 這條軸切分一般世界與隔離世界,組合起來形成一般應用程式、NT 核心、IUM 的 Trustlet、安全核心這四個區域
subgraph ax0 ["VTL0(一般世界)"]
a0["ring 3:一般應用程式"]
k0["ring 0:NT 核心與驅動程式"]
end
subgraph ax1 ["VTL1(隔離世界)"]
a1["ring 3:IUM(Trustlet)"]
k1["ring 0:安全核心"]
end
a0 --- k0
a1 --- k1
k0 ~~~ a1
圖4:特權的軸變成兩條,「是不是核心」和「是不是隔離世界」成了兩個不同的提問。
3.2. 界線的實體是 SLAT
第 1 回講過,把客體實體位址(GPA)對應到實際 RAM(SPA)的第二層轉譯表──SLAT──握在 Hypervisor 手上。VSM 用的正是這個性質。VTL 的隔離,是利用 Hyper-V Hypervisor 與 SLAT 做出來的。4
當 VTL1 宣告「這塊記憶體不給 VTL0 看」時,Hypervisor 就會從 VTL0 用的轉譯表中拿掉對該分頁的存取權限。此後就算 VTL0 的核心去碰那個位址,也會在 CPU 的位址轉譯階段被拒絕。核心怎麼改自己的分頁表都是白費。
因為分頁表(GVA→GPA)雖然屬於核心,但再往後的轉譯(GPA→SPA)以及最終的存取權限,屬於 Hypervisor。
flowchart TB
accTitle: 從 VTL0 存取 VTL1 記憶體被拒絕的流程
accDescr: VTL0 的核心想讀 VTL1 的記憶體時,就算通過了自己的分頁表,也會被 SLAT 的存取保護拒絕,控制權轉到 Hypervisor
try["VTL0 的核心試圖讀取 VTL1 的分頁"] --> pt["核心自己的分頁表可以通過"]
pt --> slat{"SLAT 的存取保護允許嗎?"}
slat -->|沒有允許| deny["Hypervisor 介入並拒絕存取"]
slat -->|有允許| ok["一般的記憶體存取"]
deny -.-> point["由核心改不動的一層來守護"]
圖5:防壁位在核心之外,而 SLAT 的保護無法被分割區內的軟體變更。
記憶體系列第 1 回寫過「VAD、PTE 與保護屬性決定存取能否通過」。在 VBS 環境中可以這樣整理:全部通過之後,還有 SLAT 這道關卡在等著。
3.3. 安全核心與 IUM
在 VTL1 中執行的不是一般的 NT 核心,而是一個稱為安全核心的小核心。VTL1 的使用者模式稱為 IUM(Isolated User Mode:隔離使用者模式),在裡面執行的程式稱為 Trustlet(受信任的處理程序)。4
Trustlet 並不像一般處理程序那樣什麼都能做。大多數系統呼叫會封送處理到 VTL0 那一側的 NT 核心,委託它處理。4 VTL1 不是「什麼都能做的上位世界」,而是被刻意做得很小的保管秘密的金庫。能帶進庫內的程式碼越少,攻擊面就越小。
flowchart TB
accTitle: Trustlet 的系統呼叫流程
accDescr: VTL1 的 Trustlet 不自己處理大多數系統呼叫,而是封送處理給 VTL0 的 NT 核心,只接收結果,藉此把 VTL1 維持得很小
tl["Trustlet(VTL1 的 IUM)"] --> sc{"需要系統呼叫"}
sc -->|多數情況| mar["委託給 VTL0 的 NT 核心"]
mar --> res["只接收結果"]
res -.-> small["VTL1 那側維持得小,攻擊面隨之減少"]
圖6:金庫不自備設備,雜事一律往外委託,只專心守住秘密。
4. HVCI ── 在金庫裡驗證核心的程式碼完整性
關於 HVCI 要抓住兩點:驗證在哪裡進行,以及驗證之後允許記憶體做什麼。以下依序來看它的保護,以及對驅動程式相容性的影響。
4.1. 驗證的到底是什麼
蓋在 VBS 之上的代表性功能,第一個是記憶體完整性──HVCI(由 Hypervisor 保護的程式碼完整性)。Windows 有一套程式碼完整性機制,會在啟動前檢查核心模式的驅動程式與二進位檔,不讓未簽署或不受信任的東西載入。HVCI 把這項驗證放進 VBS 的隔離環境中執行。2
把驗證邏輯本身搬到 VTL1 的理由,正是第 2 節講的那個弱點。驗證程式碼若在 VTL0 的核心裡,掌握核心的攻擊者就能把驗證抽換掉。放在 VTL1,抽換的手就伸不過來了。
flowchart TB
accTitle: 驗證程式碼放在哪裡造成的差別
accDescr: 驗證程式碼若在 VTL0 的核心裡,核心一被拿下就會失效,若在 VTL1 則連拿下核心的攻擊者也伸不到手,驗證得以保住
atk["拿下核心的攻擊者"] --> q{"程式碼完整性的驗證在哪裡?"}
q -->|"VTL0 的核心裡(傳統)"| bad["驗證邏輯可以被抽換"]
q -->|"VTL1 的隔離環境(HVCI)"| good["抽換的手伸不過來"]
bad --> res1["未簽署的程式碼可能在核心裡執行"]
good --> res2["核心被攻陷之後驗證依然有效"]
圖7:不要把關卡設在有可能被攻破的那一側裡面──驗證邏輯的這次搬家,就是 HVCI 的本質。
4.2. 可執行分頁的規則
HVCI 的效果不只停在「啟動時的檢查」,它也對核心記憶體的配置施加限制。5
- 核心的分頁要先通過程式碼完整性驗證才會變成可執行。
- 可執行的分頁不會同時可寫(也就是所謂的 W^X)。
這兩條湊齊之後,就算用緩衝區溢位之類的漏洞改寫了核心記憶體,也無法把改寫的內容送去執行。因為可執行的分頁改不動,而改得動的分頁不能執行。5 執行許可最終的依據在 SLAT 那側的執行權限,而這是 VTL0 的核心動不了的。
flowchart TB
accTitle: HVCI 環境中核心分頁變成可執行的過程
accDescr: 驅動程式的載入要求在 VBS 的隔離環境中接受程式碼完整性驗證,通過就允許成為可執行且不可寫的分頁,沒通過則被擋下並記入 CodeIntegrity 記錄檔
load["核心程式碼的載入與執行要求"] --> verify{"在隔離環境中做程式碼完整性驗證"}
verify -->|通過| exec["允許為可執行分頁(不可寫)"]
verify -->|沒通過| block["載入被擋下"]
block --> log["記入 CodeIntegrity Operational 記錄檔(事件識別碼 3087)"]
exec -.-> wx["可寫的分頁仍然不可執行"]
圖8:不讓執行與寫入並存的這條規則,其驗證在 VTL1 那側進行,VTL0 的核心推翻不了。
順著攻擊者的視角走一遍,就能看清這條規則是怎麼發揮作用的。
flowchart TB
accTitle: HVCI 環境中程式碼注入失敗的流程
accDescr: 就算用漏洞改寫了核心記憶體,寫得進去的分頁不可執行,而可執行的分頁本來就改不動,因此注入的程式碼無法送去執行
inj["試圖用漏洞在核心記憶體裡動手腳"] --> which{"要下手的是哪一種分頁?"}
which -->|可寫的分頁| wok["改寫會成功"]
which -->|可執行的分頁| xfail["根本改寫不了"]
wok --> nx["但那個分頁不可執行"]
nx --> dead["注入的程式碼無法送去執行"]
xfail --> dead
圖9:從哪個入口進去都是死路一條──讓可寫的分頁和可跑的分頁不相交,意義就在這裡。
4.3. 驅動程式相容性這個代價
這條規則會和舊設計的驅動程式衝突。在執行時改寫自己的程式碼、沒有簽署、要求同時可執行又可寫的記憶體──這樣的驅動程式在 HVCI 環境中載入不了。
被擋下這件事,可以在事件檢視器的 Applications and Services Logs\Microsoft\Windows\CodeIntegrity\Operational(有代表性的是事件識別碼 3087)中確認。6
「一啟用記憶體完整性周邊裝置就不能用」這類麻煩,多數情況下真身就是它。處理的正途是更新到支援 HVCI 的驅動程式版本,而關掉記憶體完整性等於把這層保護整個交出去,應該視為最後手段。
如果你是從驅動程式開發那一側參與這類驗證,也可以參考篩選器驅動程式的文章(「Windows 的迷你篩選器驅動程式」)。
flowchart TB
accTitle: 記憶體完整性導致周邊裝置不能用時的釐清方式
accDescr: 用 CodeIntegrity Operational 記錄檔找出被擋下的驅動程式,正途是更新到支援 HVCI 的版本,沒有對應版本就向廠商提出要求,關閉功能是不做成長期設定的最後手段
sym["啟用記憶體完整性後裝置不能用"] --> log2["用 CodeIntegrity 記錄檔找出擋下的來源"]
log2 --> upd{"有支援 HVCI 的驅動程式版本嗎?"}
upd -->|有| fix2["更新後維持啟用並解決"]
upd -->|沒有| ask2["向廠商要求提供對應版本"]
ask2 -.-> temp["關閉是不做成長期設定的最後手段"]
圖10:最先該看的不是設定畫面而是記錄檔,擋下的元凶由事件識別碼 3087 告訴你。
5. Credential Guard ── 雜湊在 LSAIso 裡面
HVCI 守的是核心的程式碼完整性,而 Credential Guard 守的是認證資料。把受理驗證的窗口和秘密的保管位置分開來想,結構與守備範圍就串起來了。
5.1. LSASS 與 LSAIso
蓋在 VBS 之上的第二個代表性功能,就是開頭那個謎題的答案:Credential Guard。
以往的 Windows 把 NTLM 雜湊與 Kerberos 的各種票證放在 LSA 處理程序(lsass.exe)的記憶體裡。啟用 Credential Guard 之後,其中受保護的秘密──網域認證資料的 NTLM 雜湊、Kerberos 的 TGT(票證授權票證)等──的保管,就移交給 LSAIso.exe──執行在 VTL1 的 IUM 中的 Trustlet。7
- lsass.exe(VTL0)照舊作為驗證處理的窗口運作。
- 秘密的實體由 LSAIso.exe(VTL1)持有,VTL0 存取不到。
- 兩者透過 RPC(遠端程序呼叫)通訊。
- LSAIso 完全不承載裝置驅動程式,只收容必要的最小限度的已簽署二進位檔。簽署由 VBS 信任的憑證驗證。7
flowchart TB
accTitle: 啟用 Credential Guard 時認證資料的擺放方式
accDescr: VTL0 的 lsass 作為驗證窗口用 RPC 與 VTL1 的 LSAIso 通訊,受保護的網域認證資料雜湊與 TGT 的實體由 LSAIso 持有,因此在 VTL0 拿到系統管理員權限的攻擊者傾印 lsass 也得不到實體
subgraph v0 ["VTL0"]
lsassP["lsass.exe(驗證的窗口)"]
att["攻擊者(系統管理員權限)"]
end
subgraph v1 ["VTL1"]
iso["LSAIso.exe(秘密的保險庫)"]
end
lsassP <-->|RPC| iso
att -->|記憶體傾印| lsassP
att -.->|搆不到| iso
圖11:窗口和保險庫被分開了,所以就算傾印 lsass,受保護的網域認證資料雜湊的實體也已經不在那裡。
預設啟用的條件
從 Windows 11 版本 22H2 起,在符合授權需求(Enterprise E3/E5、Education A3/A5)與硬體需求的裝置上,VBS 與 Credential Guard 預設啟用。在 Pro 等版本上 Credential Guard 不會自動啟用(也有例外,例如過去在符合資格的授權下啟用過的機器被降級的情況)。1
這種認證資料的保護並不是什麼額外產品的話題,而是對應版本的現行 Windows 的標準狀態。
flowchart TB
accTitle: 從登入到驗證的認證資料流動
accDescr: 登入之後秘密的實體保管在 VTL1 的 LSAIso 裡,每當需要驗證時 VTL0 的 lsass 用 RPC 委託運算,受保護的長期秘密本身不會回傳,只有驗證處理的結果回到 VTL0
signin["使用者登入"] --> front["lsass 作為窗口處理"]
front --> store["秘密的實體保管到 LSAIso"]
auth["之後的驗證要求"] --> front
front -->|用 RPC 委託運算| store
store -->|回傳處理結果(不回傳秘密)| front
圖12:受保護的長期秘密本身不會離開金庫,回到 VTL0 的是票證等驗證處理的結果。
5.2. 準確地知道哪些不受保護
受保護的認證資料
Credential Guard 不是萬能的盾。受保護的是網域認證資料的 NTLM 雜湊、Kerberos 的 TGT(票證授權票證),以及以網域認證資料儲存的內容。
不在保護範圍內的東西
以下這些不在範圍內。8
- Kerberos 的服務票證(TGT 受保護)
- 本機帳號與 Microsoft 帳號的認證資料
- 鍵盤側錄在輸入時的竊取,以及實體攻擊
- 走 NTLMv1、MS-CHAPv2、Digest、CredSSP 這些路徑的認證資料
- 自行管理認證資料的第三方軟體內部
除了保護範圍,也要確認驗證的相容性
另外,啟用 Credential Guard 之後 NTLMv1 與 Kerberos 的未受限制委派等將不能再用,因此依賴舊式驗證的業務系統需要先確認相容性。8 不是「啟用就沒事了」,而是把守備範圍的內外摸清楚,再用別的措施補上剩下的部分──這才是實務上正確的用法。
flowchart TB
accTitle: Credential Guard 的守備範圍
accDescr: 網域的 NTLM 雜湊與 TGT、已儲存的網域認證資料受保護,而服務票證、本機帳號、鍵盤側錄、實體攻擊、應用程式自行儲存的認證資料都不在保護範圍內
scope{"那個秘密在守備範圍的哪一側?"} --> inA["網域的 NTLM 雜湊與 TGT"]
scope --> outA["服務票證或本機帳號"]
inA --> prot["由 LSAIso 保護"]
outA --> unprot["不受保護(需要別的措施)"]
unprot -.-> outB["按鍵輸入、實體攻擊、應用程式自行儲存也不在範圍內"]
圖13:守備範圍畫得很清楚,線外的部分要靠多因素驗證與應用程式那側的設計來補。
6. 用自己的眼睛確認
VBS 與各項功能的執行狀態,可以在手邊確認。要把 VBS 這個基礎的狀態,和跑在它上面的服務的狀態分開來讀。
6.1. 用 PowerShell 確認 VBS 與執行中的服務
Get-CimInstance -Namespace root/Microsoft/Windows/DeviceGuard `
-ClassName Win32_DeviceGuard |
Select-Object VirtualizationBasedSecurityStatus,
SecurityServicesConfigured,
SecurityServicesRunning
讀法如下。9
VirtualizationBasedSecurityStatus為 2,表示 VBS 已啟用且正在執行。SecurityServicesRunning中含有 1 就是 Credential Guard、含有 2 就是記憶體完整性(HVCI)正在執行。
6.2. 把 msinfo32 和設定畫面分開來讀
若要用圖形介面確認執行狀態,就看 msinfo32 的「以虛擬化為基礎的安全性」欄位(執行中的服務會列出「由 Hypervisor 強制的程式碼完整性」等)。
Windows 安全性應用程式裡「裝置安全性 > 核心隔離」下的「記憶體完整性」切換開關,映出來的是設定,在剛啟用後等待重新開機期間,或啟動時出現相容性問題、HVCI 實際上沒有在跑的期間,它也可能看起來是開著的,因此有沒有在執行要用 msinfo32 或 Win32_DeviceGuard 的 SecurityServicesRunning 來判斷。6
6.3. 不要只憑處理程序在不在就斷定它在執行
工作管理員的詳細資料索引標籤裡也有痕跡。在 VBS 執行的機器上,看得到一個叫「安全系統」(Secure System)的處理程序。LsaIso.exe 是分離 LSA 的服務被裝載在 VTL1 時才出現的處理程序,在只啟用 HVCI 的組態下通常不會出現。
不過處理程序在不在終究只是痕跡,Credential Guard 有沒有在執行,還是要用前面說的 SecurityServicesRunning(是否含有 1)來判斷。兩者都是對應著 VTL1 那個世界、從 VTL0 看得見的窗口。
flowchart TB
accTitle: VBS 相關功能的執行確認步驟
accDescr: 用 Win32_DeviceGuard 的查詢確認 VBS 有沒有在執行,再從 SecurityServicesRunning 的值判斷 Credential Guard 與 HVCI 有沒有在執行,驅動程式問題則看 CodeIntegrity 記錄檔
q0["查詢 Win32_DeviceGuard"] --> q1{"VBS 的 Status 是 2 嗎?"}
q1 -->|否| off["VBS 沒有在執行(確認需求與設定)"]
q1 -->|是| q2{"SecurityServicesRunning 的值是?"}
q2 -->|含有 1| cg["Credential Guard 執行中"]
q2 -->|含有 2| hvciR["記憶體完整性(HVCI)執行中"]
hvciR -.-> ev["驅動程式問題看 CodeIntegrity 記錄檔(3087)"]
圖14:狀態確認依 VBS 本體、其上的各項服務、出問題時的記錄檔這三個階段推進。
7. 實務上要避開的三種誤讀
7.1. 「守住系統管理員權限就夠了。VBS 是伺服器那邊的事」
Credential Guard 防的是系統管理員權限被奪走之後的災情擴大(雜湊被帶走以及橫向移動)。也就是說,VBS 是以已被入侵為前提的縱深防禦中的一層,反而在用戶端 PC 上最見效。既然在符合需求的 Windows 11 上預設啟用已是常態,那麼正確的態度就不是「跟我們無關」,而是「按它已經在跑來管理相容性」。
flowchart TB
accTitle: 入侵的階段與 VBS 發揮作用的位置
accDescr: 初期入侵由多因素驗證與教育訓練等別的措施承擔,權限提升之後的核心程式碼注入由 HVCI 擋下,受保護網域秘密的竊取與橫向移動由 Credential Guard 擋下,但保護範圍之外的秘密不在其列
s1["初期入侵(釣魚等)"] --> s2["權限提升"]
s2 --> s3["對核心注入程式碼"]
s3 --> s4["受保護網域秘密的竊取與橫向移動"]
s1 -.-> d1["由 MFA、教育訓練、EDR 承擔"]
s3 -.-> d2["HVCI 在這裡擋下"]
s4 -.-> d3["Credential Guard 擋下(僅限保護對象)"]
圖15:VBS 不是「不讓人進來」的技術,而是守在不同階段的「進來了也別讓他贏」的技術。
7.2. 「記憶體完整性一出問題,關掉就好」
關掉當然一時能用,但那等於把針對核心程式碼注入的防壁整個拆掉。正途是先用 CodeIntegrity 記錄檔找出被擋下的驅動程式,再套用廠商的更新版本。就算為了驗證而暫時關閉,也建議不要把它固定成長期設定。
7.3. 「有了 Credential Guard 密碼就不會被偷」
這是把守備範圍混為一談的過度自信。服務票證、本機帳號、按鍵輸入本身、應用程式自行儲存的認證資料都不在範圍內。8 面對釣魚與鍵盤側錄需要別的措施(多因素驗證、Windows Hello、重新檢視應用程式那側的認證資料管理)。
8. 總結
- VBS 用 Hypervisor 做出隔離環境,在核心可能被攻陷的前提下守護安全性功能。2
- 隔離的單位是 VTL,目前實作了 VTL0(一般世界)與 VTL1(安全核心與 IUM)這兩個等級。3
- 界線的實體是 SLAT 的記憶體存取保護,分割區內的軟體──包含核心──都無法變更。3
- HVCI 在隔離環境中做程式碼完整性驗證,強制「驗證通過前不可執行」「可執行的分頁不可寫」。5 代價是需要管理驅動程式相容性。6
- Credential Guard 把網域認證資料的 NTLM 雜湊與 TGT 隔離到 VTL1 的 LSAIso。從 Windows 11 22H2 起,在符合授權需求(Enterprise、Education)與硬體需求的裝置上預設啟用(請與執行狀態的確認一起使用)。71
- 執行狀態可以用
Win32_DeviceGuard的 SecurityServicesRunning(1=Credential Guard、2=HVCI)確認。9
接下來是第 3 回「幾秒就能啟動的虛擬機 ── WSL2、Windows Sandbox 與容器」。
到這裡為止,我們都是從「隔離有多強」這一側看虛擬化。最終回反過來,從「有多輕」這一側,追一追捨掉完整虛擬機重量的輕量虛擬機們究竟在哪裡省了工。
相關文章
- Windows 虛擬化的深層(第 1 回)── 你的 Windows 究竟在哪裡執行:Hypervisor 與分割區
- Windows 記憶體的深層(第 1 回)── 虛擬位址變成實體 RAM 的瞬間:分頁錯誤的來龍去脈
- Windows 的迷你篩選器驅動程式
- Windows 的錯誤碼體系 ── Win32、HRESULT 與 NTSTATUS
相關諮詢領域
小村軟體有限公司承接 Windows 應用程式與安全性功能的相容性調查、驅動程式引起的問題分析,以及公司內部 PC 環境的技術驗證。
參考連結
-
Microsoft Learn, Credential Guard overview. 關於從 Windows 11 版本 22H2 起,在符合授權需求與硬體、軟體需求且未被明確停用的裝置上 Credential Guard 預設啟用;符合資格的版本與授權是 Enterprise(E3/E5)與 Education(A3/A5),Pro 不在範圍內;以及 Pro 上曾在符合資格的授權下啟用過的機器,在降級之後仍可能屬於預設啟用的對象。 ↩ ↩2 ↩3
-
Microsoft Learn, Virtualization-based Security (VBS). 關於 VBS 用硬體虛擬化與 Windows Hypervisor 做出隔離環境,並在核心可能被攻陷的前提下把它當成作業系統的信任起點;記憶體完整性在該隔離環境中執行核心模式的程式碼完整性驗證;以及 SLAT 是 VBS 的必要條件。 ↩ ↩2 ↩3
-
Microsoft Learn, Virtual Secure Mode. 關於 VSM 是 Device Guard、Credential Guard、虛擬 TPM 等的基礎;對隔離區域的存取只經由 Hypervisor 控制,即使面對 ring 0 的作業系統軟體也受保護;VTL 是分層的,最多 16 個等級中實作了 2 個;以及每個 VTL 的記憶體存取保護無法被分割區內的系統軟體變更。 ↩ ↩2 ↩3 ↩4 ↩5
-
Microsoft Learn, Isolated User Mode (IUM) Processes. 關於 VSM 利用 Hyper-V Hypervisor 與 SLAT 做出 VTL;安全核心與 IUM 在 VTL1 中執行;Trustlet 把系統呼叫封送處理給 VTL0 的核心;以及 LSAIso 在 VTL1 中執行並經由 RPC 與 lsass 通訊。 ↩ ↩2 ↩3
-
Microsoft Learn, Memory integrity and virtualization-based security. 關於記憶體完整性(HVCI)在隔離環境中執行程式碼完整性驗證,以及核心記憶體分頁只有在通過驗證之後才變成可執行、可執行分頁不會變成可寫。 ↩ ↩2 ↩3
-
Microsoft Learn, Memory integrity and VBS enablement. 關於在相容硬體上全新安裝 Windows 11 時記憶體完整性預設啟用;在 msinfo32 與 Windows 安全性應用程式中確認狀態;以及可以用 CodeIntegrity Operational 記錄檔的事件識別碼 3087 確認被擋下的驅動程式。 ↩ ↩2 ↩3
-
Microsoft Learn, How Credential Guard works. 關於啟用 Credential Guard 時 LSA 與分離 LSA 處理程序(LSAIso.exe)通訊來保管秘密;保管的資料受 VBS 保護,作業系統的其餘部分無法存取;以及分離 LSA 處理程序不承載裝置驅動程式,只收容通過簽署驗證的最小限度二進位檔。 ↩ ↩2 ↩3
-
Microsoft Learn, Credential Guard protection limits. 關於服務票證、本機帳號、鍵盤側錄、實體攻擊等不在 Credential Guard 的保護範圍內;TGT 受保護而服務票證不受保護;以及啟用之後 NTLMv1 與未受限制的委派將不能使用。 ↩ ↩2 ↩3
-
Microsoft Learn, Enable virtualization-based protection of code integrity. 關於用 Win32_DeviceGuard 類別確認 VBS 與記憶體完整性狀態的方式,以及 SecurityServicesRunning 各個值的意義(1 是 Credential Guard,2 是記憶體完整性)。 ↩ ↩2
相關文章
共用相同標籤的最新文章。能以相近的主題延伸理解。
關掉記憶體完整性(HVCI)會變快嗎 ── 意義、步驟與判斷
Windows 安全性中「核心隔離」裡的記憶體完整性(HVCI)到底在做什麼,關掉它真的會變快嗎。本文面向入門讀者,整理可能變快的條件與不會變的條件、關閉的步驟與復原方法、如何確認真的關掉了,以及什麼情況下可以關。
Windows 虛擬化的深層(第 3 回)── 幾秒就啟動的虛擬機器:WSL2、Windows Sandbox 與容器為何這麼輕
WSL2 與 Windows Sandbox 為何幾秒就能啟動、又這麼輕?本文從動態基礎映像、直接對應、記憶體的動態調配,一路講到 Hyper-V 隔離容器的運作方式。
Windows 虛擬化的深層(第 1 回)── 你的 Windows 究竟跑在哪裡:Hypervisor 與分割區
啟用 Hyper-V 之後,主機 Windows 本身會以根分割區的身分跑在 Hypervisor 之上。本文從 VT-x、SLAT、VMBus 的職責講起,說清虛擬化的底層基礎。
具名管道實務 ── 從設計到安全,看懂 Windows 行程間通訊的標準做法
以實務角度說明 Windows 行程間通訊的標準做法——具名管道。依據一手資料整理位元組模式與訊息模式的取捨、同時接受多個用戶端的伺服器結構、ACL 與模擬的安全設計,以及 .NET 的具名管道串流。
Windows 服務的帳戶選定 ── LocalSystem、虛擬帳戶與 gMSA 的取捨
您是否一直讓 Windows 服務以 LocalSystem 執行?本文以判斷表比較 LocalService、NetworkService、虛擬帳戶、網域使用者與 gMSA 的權限與網路身分,說明如何以最小權限維運的選擇方式。
相關主題
與本文相近的主題頁面。以本文為起點,可進一步連到相關服務與其他文章。
Windows 技術主題
彙整 KomuraSoft LLC 關於 Windows 開發、故障調查與既有資產活用文章的主題中心。
常見問題
整理諮詢這個主題時常見的問題。
- VBS(以虛擬化為基礎的安全性)和核心隔離是同一件事嗎?
- 嚴格來說是兩件事。VBS 是用 Hypervisor 做出隔離環境的基礎技術,而 Windows 安全性應用程式裡的「核心隔離」,是把建立在 VBS 之上的多項保護收在一起的畫面名稱。其中的代表是「記憶體完整性」,指的就是 HVCI(由 Hypervisor 保護的程式碼完整性)。各項服務的執行狀態要用查詢 Win32_DeviceGuard 來確認,而不是看畫面顯示。
- VTL1 的記憶體,用系統管理員權限或核心驅動程式真的讀不到嗎?
- 讀不到。每個 VTL 的記憶體存取保護由 Hypervisor 針對分割區的實體位址空間管理,分割區內執行的軟體無法變更。即使是在核心(ring 0)執行的程式碼,也不允許從 VTL0 存取 VTL1 的記憶體。
- 為什麼啟用記憶體完整性(HVCI)之後驅動程式會不能用?
- 在 HVCI 環境中,核心的分頁要先通過完整性驗證才會變成可執行,而且不允許寫入可執行分頁。未簽署的驅動程式,以及會改寫可執行記憶體的舊設計驅動程式,無法符合這項限制,載入會被擋下。被擋下的紀錄可以在 CodeIntegrity Operational 記錄檔(事件識別碼 3087 等)中確認。
- Credential Guard 保護什麼,不保護什麼?
- 它在隔離環境中保護網域認證資料的 NTLM 密碼雜湊、Kerberos 的 TGT,以及應用程式以網域認證資料儲存的內容。另一方面,Kerberos 的服務票證、本機帳號與 Microsoft 帳號的認證資料、鍵盤側錄在輸入時的竊取以及實體攻擊,都不在保護範圍內。
- 要在哪裡確認 VBS 有沒有在執行?
- 看 msinfo32 的「以虛擬化為基礎的安全性」欄位,或用 PowerShell 查詢 root/Microsoft/Windows/DeviceGuard 命名空間的 Win32_DeviceGuard 類別。若 SecurityServicesRunning 含有 1,表示 Credential Guard 正在執行;含有 2 則表示記憶體完整性(HVCI)正在執行。