HVCI / VBS kernel code-integrity bypass approaches¶
HVCI, SLAT-enforced W^X ile VTL 0 kernel'ında unsigned code'un execute edilmesini imkânsız kılar; bu yüzden attacker'lar shellcode yerine data-only exploitation'a ya da HVCI altında hâlâ yüklenen signed-but-vulnerable driver'lara (BYOVD) pivot eder — bu not defensive/kavramsal bir katalog kaydıdır.
Mechanism¶
Invariant: bir code page ya writable ya executable olur, ikisi birden asla değil
Virtualization-Based Security (VBS), Windows hypervisor'ını kullanarak kernel'ın kendisinin bile compromise olabileceğini varsayan izole bir root-of-trust yaratır. Bu mimari Virtual Trust Level'lara bölünür: VTL 1 secure kernel'ı (securekernel.exe) barındırır, VTL 0 ise normal Windows kernel'ıdır. Hypervisor-Protected Code Integrity (HVCI), Second Layer Address Translation (SLAT — Intel'de Extended Page Tables, EPT) üzerinden kernel memory'sine bir W^X invariant'ı dayatır.
Kilit nokta şudur: normal kernel'ın gördüğü Page Table Entry'lerin (PTE) yanında, hypervisor'ın kontrol ettiği bir Extended Page Table Entry (EPTE) katmanı vardır. EPTE, bu senaryoda root of trust'tır; permission'ını page üzerinde PTE ne derse desin zorlar. VTL 1 boot sırasında HvCallModifyVtlProtectionMask benzeri hypercall'larla EPTE protection'larını sabitler: her kernel page ya read/write ya da read/execute olur. Bir page executable yapılmadan önce code-integrity check'ini secure environment içinde geçmek zorundadır ve executable page'ler bir daha writable olamaz.
Sonuç: klasik "shellcode'u writable bir page'e yaz, sonra o page'i executable yap" akışı ölür. Attacker PTE'yi bozup page'i KRWX işaretlese bile EPTE eski permission'ı koruduğu için access violation olur. User-mode RWX code'a kernel'dan sıçrama girişimi de Mode-Based Execution Control (MBEC) / Restricted User Mode ile engellenir: kernel execute ederken tüm user-mode page'ler non-executable işaretlenir.
Walkthrough¶
Sadece kavramsal — kamuya açık writeup'a defender bakışı; weaponize edilmiş exploit yok
Boundary crossed olmadığı için, "bypass" aslında invariant'ı hiç ihlal etmeden etrafından dolaşmaktır. Connor McGarr'ın public "No Code Execution? No Problem" writeup'ı iki ana yaklaşımı ortaya koyar:
Yaklaşım 1 — Data-only / ROP (signed code'u reuse et):
- Attacker'ın elinde zaten bir arbitrary kernel read/write primitive'i var (ayrı bir bug'dan).
- Unsigned code execute edilemediği için, hedef kendi shellcode'unu çalıştırmak değil; var olan signed kernel code'unu (ntoskrnl gadget'ları, meşru API'ler) bir ROP chain hâlinde zincirlemektir. Bu "HVCI compliant" kalır.
- Kavramsal reprodüksiyon: suspended bir dummy thread yarat, onun kernel stack'ini leak et, thread'in beklediği return address'i ilk ROP gadget ile overwrite et, thread'i resume et.
- Chain,
PsGetCurrentProcessgibi meşru API'leri çağırıp token manipülasyonu gibi bir data-only hedefe ulaşır, sonra temiz şekildeZwTerminateThreadile döner. - Kernel CFG (kCFG) indirect call target'ları kısıtlar; CFG bitmap'i de SLAT ile read-only tutulduğu için exploitation ROP'a doğru itilir. Bu yaklaşımın doğal düşmanı, backward-edge control-flow'u kilitleyen kernel CET (shadow stack)'tir.
Yaklaşım 2 — BYOVD (Bring Your Own Vulnerable Driver):
- HVCI, driver'ın code integrity'sini doğrular; driver'ın functionality'sinin güvenli olup olmadığını doğrulamaz.
- Meşru şekilde imzalı ama zafiyetli bir driver (ör. arbitrary R/W IOCTL expose eden) HVCI açıkken bile yüklenir — çünkü signature geçerlidir.
- Attacker bu signed driver üzerinden kernel R/W primitive'i elde eder ve tekrar Yaklaşım 1'deki data-only manipülasyonlara döner.
- Yani HVCI, unsigned kod barajını yükseltir ama BYOVD attack surface'ini tek başına kapatmaz; onu kapatan şey vulnerable-driver blocklist'idir.
Detection¶
- VBS/HVCI durumu: Endpoint'lerde HVCI'nin gerçekten "running" olduğunu envanterle (
msinfo32→ Virtualization-based security Services Running; ya daDeviceGuardWMI class). HVCI'nin sessizce disabled olduğu host'lar anomali sayılır. - BYOVD göstergeleri: Bilinen vulnerable driver'ların (LOLDrivers/Microsoft blocklist hash'leri)
sc create/NtLoadDriverile beklenmedik path'lerden (ör.%APPDATA%) yüklenmesine alarm ver. - Suspicious kernel data manipulation: EPROCESS token değişimi,
PsCreateProcessNotifyRoutinecallback array'inin toplu sıfırlanması gibi data-only pattern'ler; bunlar code injection olmadan gerçekleştiği için memory-scan yerine davranışsal telemetri gerekir. - Thread/stack anomalileri: Suspended thread'lerin kernel stack return address'lerinin beklenmedik biçimde değişmesi, ROP-based data-only yaklaşımın izidir (ileri EDR/hypervisor agent görünürlüğü gerektirir).
- kCET/kCFG:
nt!KeIsKernelCetEnabledile kernel shadow stack durumunu kontrol et; kapalıysa ROP yaklaşımı daha uygulanabilir kalır.
Mitigation¶
- HVCI'yi UEFI lock ile etkinleştir: Memory Integrity'yi (Windows Security → Core Isolation) aç ve mümkünse UEFI lock + "Mandatory" enforcement ile config'in sessizce zayıflatılmasını önle.
- Microsoft Vulnerable Driver Blocklist / WDAC: BYOVD'nin gerçek karşılığı budur. Blocklist, driver'ı load stage'inde — HVCI code'u doğrulamadan önce — engeller. Windows 11 ve Server 2022 bunu default zorunlu kılar; eski sistemler
DriverSiPolicy.p7bile uygular. Ortama özgü custom WDAC deny policy'leriyle genişlet. - Kernel CET (shadow stack): Destekleyen donanımda etkinleştir; backward-edge ROP'u kırarak data-only reuse chain'lerini büyük ölçüde etkisizleştirir.
- Downgrade koruması: VBS binary'lerinin (secure kernel,
ci.dll) eski-vulnerable sürümlere rollback'ini önleyen revocation policy'leri uygula (bkz. VBS downgrade EoP). - Defense in depth: Least privilege ile admin token dağılımını daralt; arbitrary R/W bug'larının ortaya çıkardığı ilk primitive'i azaltmak için driver hardening ve attack-surface reduction uygula.
References¶
- Connor McGarr — Exploit Development: No Code Execution? No Problem! Living The Age of VBS, HVCI, and Kernel CFG
- Microsoft Learn — Memory Integrity and Virtualization-Based Security (VBS)
- Cisco Talos — Exploring vulnerable Windows drivers