NtQuerySystemInformation kernel-address disclosure¶
NtQuerySystemInformation'ın bir dizi information class'ı (SystemModuleInformation,SystemHandleInformation,SystemBigPoolInformation,SystemExtendedHandleInformation) yıllarca medium-IL caller'lara ham kernel pointer'ları döndürdü ve tek bir syscall ile kASLR'ı çökertti;ExIsRestrictedCallerbunu önce below-Medium caller'lar için, sonra da 24H2'deSeDebugPrivilegeyoksa herkes için kapattı.
Mechanism¶
NtQuerySystemInformation (dahili ExpQuerySystemInformation) bir "SYSTEM_INFORMATION_CLASS" alır ve o class'a karşılık gelen kernel bookkeeping yapısını user buffer'a kopyalar. Sorun, bu yapıların birçoğunun tasarımı gereği ham kernel virtual address taşımasıdır: SystemModuleInformation her yüklü modülün DllBase'ini, SystemHandleInformation / SystemExtendedHandleInformation her object'in kernel Object pointer'ını, SystemBigPoolInformation ise her big-pool allocation'ının VirtualAddress'ini içerir. Bir syscall, ntoskrnl ve driver base'lerini plus canlı pool/object adreslerini user mode'a yankılıyordu.
Note
Buradaki invariant bir memory-safety bug'ı değil, bir policy eksikliğidir: kernel, diagnostic amaçlı tutulan pointer'ları trust boundary'yi düşünmeden geri veriyordu. kASLR'ın tüm değeri "attacker base'i bilmiyor" varsayımına dayanır; bu class'lar o varsayımı sıfır effort'la yıkar — heap groom, race ya da OOB read gerekmez. Çünkü leak'in kaynağı bir zafiyet değil, dokümante edilmiş bir API'nin niyetlenmiş çıktısıdır; savunma da bu yüzden bir patch değil, caller'a göre alanları zero'lama politikasıdır.
Windows 8.1 bu boşluğu ExIsRestrictedCaller ile daraltmaya başladı: fonksiyon, integrity level'ı Medium'un altında olan (Low / Untrusted / AppContainer — yani sandbox'lı IE, Chrome, Reader) caller'lar için TRUE döner ve çağıran kod (örn. ExpQueryModuleInformation) address alanlarını 0 yazar. Ama Medium IL ve üzeri "unrestricted" sayıldığından, sandbox'sız bir local process için leak yıllarca canlı kaldı.
Walkthrough¶
Public PoC'lerin (sam-b/windows_kernel_address_leaks) izlediği high-level mantık:
// 1. Boyutu öğrenmek için sıfır buffer'la çağır (STATUS_INFO_LENGTH_MISMATCH).
ULONG len = 0;
NtQuerySystemInformation(SystemModuleInformation, NULL, 0, &len);
// 2. Buffer ayır ve tekrar sorgula.
auto* mods = (RTL_PROCESS_MODULES*)malloc(len);
NtQuerySystemInformation(SystemModuleInformation, mods, len, &len);
// 3. mods->Modules[i].ImageBase => ntoskrnl.exe / driver kernel base'i.
// (Medium IL'de dolu; below-Medium'da 0'lanmış gelir.)
Kavramsal adımlar:
- Class seçimi. Image base için
SystemModuleInformation; belirli bir object'in (ör. hedef process token'ı) kernel adresi içinSystemHandleInformation/SystemExtendedHandleInformation; pool grooming hedefi içinSystemBigPoolInformation. - İki-geçişli sorgu. Önce length'i öğren, sonra buffer'ı doldur — klasik
NtQuerySystemInformationidiom'u. - Pointer çıkarımı. İlgili struct field'ından (
ImageBase/Object/VirtualAddress) kernel address'i oku. - kASLR çözümü. Leak edilen base bir sonraki write/execute primitive'inin hedef offset'lerini hesaplamak için kullanılır — leak burada exploit chain'in "recon" evresidir, silah değil.
Neden bu kadar cazipti
Tek başına bir memory-corruption bug'ı çoğu zaman sadece bir R/W primitive verir ama nereye yazacağını bilmen için bir base gerekir. Bu class'lar o base'i syscall maliyetiyle sağladığı için, medium-IL LPE exploit'leri (browser sandbox'tan sonra veya doğrudan local) bir OOB-read info-leak yazmak yerine buradan besleniyordu.
Warning
Leak edilen değerler canlı runtime adresleridir; sabit değil. Yani telemetri açısından "bilinen kötü bir sabit" aramak işe yaramaz — sinyal, class'ın kullanımının kendisidir.
Detection¶
- ETW
THREATINTsensor'u. Windows 11 23H2+ çekirdeği,NtQuerySystemInformation(veNtSystemDebugControl) çağrılarında kernel-address sızdıran class'lar içinTHREATINT_PROCESS_SYSCALL_USAGEevent'ini üretir. Event yalnızca non-admin user-mode caller için ve her class başına process başına bir kez fire eder; bu, EDR için düşük-gürültülü bir "bu process kASLR recon yapıyor" sinyalidir. - Behavioral anomali. Meşru bir uygulamanın
SystemModuleInformation+SystemHandleInformation+SystemBigPoolInformationgibi bir dizi leak-y class'ı arka arkaya sorgulaması nadirdir; özellikle ardından bir driver open / write-primitive davranışı gelirse chain habercisidir. - Non-admin big-pool sorgusu.
SystemBigPoolInformation/SystemExtendedHandleInformationgibi çoğunlukla debugger/diagnostic tooling'e ait class'ların medium-IL, non-SeDebug bir process'ten gelmesi telemetride flag'lenmelidir. - Guard/CFG bağlamı. Leak'i takip eden indirect-call veya SMEP/CFG ihlali, host-based exploit-guard log'larında ikinci bir korelasyon noktasıdır.
Mitigation¶
- 24H2 kernel-address restriction. Windows 11 / Windows Server 2022 24H2 ile,
Feature_RestrictKernelAddressLeaksetkinken bu class'lar artık Medium IL için de adres alanlarını0'lar; tek istisnaSeDebugPrivilege'in enable edilmiş olmasıdır (SeSinglePrivilegeCheck(SeDebugPrivilege, ...)), ki bu default'ta yalnızca admin process'lerde bulunur. Böylece sandbox'sız medium-IL leak yolu kapanır. - Below-Medium çoktan kapalı. Windows 8.1'den beri
ExIsRestrictedCallerLow/Untrusted/AppContainer caller'lar için alanları zero'lar — browser/document sandbox'ları için leak zaten yıllardır ölüydü. - Least privilege. Servisleri gereksiz
SeDebugPrivilegeolmadan çalıştırmak, 24H2 gate'inin bypass edilmesini engeller. - Defense-in-depth. kCFG / HVCI, sızan bir pointer downstream'de indirect-call hijack'e dönüşse bile hedef kümesini daraltır; leak'i tümüyle önlemese de exploit değerini düşürür.
References¶
- Winsider / windows-internals.com — KASLR Leaks Restriction (ExIsRestrictedCaller, RestrictKernelAddressLeaks, 24H2)
- Winsider / windows-internals.com — An End to KASLR Bypasses? (THREATINT_PROCESS_SYSCALL_USAGE ETW event)
- Alex Ionescu — KASLR Bypass Mitigations in Windows 8.1 (ExIsRestrictedCaller, restricted classes)
- hackyboiz — Bypassing Windows Kernel Mitigations Part0: Deep Dive into KASLR Leaks Restriction
- sam-b/windows_kernel_address_leaks — public PoCs for leaking kernel pointers from user mode