Skip to content

VAD spraying

Çok sayıda VirtualAlloc reservation'ı yaparak, ortaya çıkan Virtual Address Descriptor node'larının process address-space layout'unu tahmin edilebilir kılması; böylece attacker verisi, bir kernel/driver bug'ının dereference edeceği tahmin edilebilir adreslere yerleştirilir.

Mechanism

Her user-mode bellek reservation'ı, process başına self-balancing (AVL) bir VAD tree'deki bir Virtual Address Descriptor (_MMVAD) node'u ile tanımlanır. Kod VirtualAlloc çağırdığında, Memory Manager "creates a VAD entry immediately, but the corresponding page directory and/or page table entries are not created until a reference to the allocated memory is made" — allocation lazy'dir ve reservation ucuzdur.

Note

VAD spraying'i çalıştıran yapısal gerçek: bir reservation'ın adresi, page'lere dokunulduğunda değil, VAD node insert edildiğinde kararlaştırılır; ve Memory Manager, bilinen bir başlangıç noktası verildiğinde address range'leri deterministik olarak dağıtır. Büyük, sıralı bir reservation serisi yaparak attacker, address space'in user kısmına tahmin edilebilir bir layout dayatır. Bundan iki savunma sonucu doğar. Birincisi, kernel fault'ları bu tree'yi gezerek çözer: "the Memory Manager will consult the VAD tree … find the corresponding VAD by checking the address range of each node … the protection bits … will be examined and the PTE control bits will then be constructed." Yani attacker'ın spray'lenmiş bir range için seçtiği içerik/protection, o range'e yapılacak bir kernel dereference'in göreceği şeyin ta kendisidir. İkincisi, Windows 8'den önce "bottom-up and top-down allocations were not randomized by ASLR," yani VirtualAlloc/MapViewOfFile tahmin edilebilir adreslere düşüyordu — address-prediction spray'lerinin asıl mümkün kılıcısı (ve daha eski sistemlerde, NULL-deref bug'ları için null page'i map'lemek).

VAD spraying, pool/heap grooming'in address-layout kuzenidir: bir allocator'ın içinde object'leri düzenlemek yerine, tüm reserve edilmiş range'leri düzenler; böylece bir kernel veya driver bug'ı bir user pointer'ı okuyup/yazdığında ya da onun üzerinden jump ettiğinde, seçilen bir virtual address attacker-controlled byte'larla desteklenir.

Walkthrough

Üst düzey ve kavramsal, public Windows internals / kernel-exploitation materyalinden:

  1. Çok sayıda range reserve et. Bir hedef adresi (klasik olarak düşük, tekrar eden bir değer) kapsayan yoğun, sıralı bir VAD node kümesi oluşturmak için VirtualAlloc'u tekrar tekrar çağır.

    for i in 0..N:
        VirtualAlloc(target_base, region_size, MEM_RESERVE|MEM_COMMIT, prot)
    
  2. Seçilen adresi destekle. Kernel bug'ının dereference edeceği adresi içeren range'i commit edip controlled veriyle (bir fake object, bir function pointer ya da küçük bir payload) doldur.

  3. Kernel'in VAD'ı gezmesine izin ver. Buggy kernel path, user-controlled adresi dereference ettiğinde, bir fault attacker'ın VAD node'una karşı çözülür ve attacker'ın byte'larını/protection'ını verir.
  4. (Eski NULL-deref varyantı.) Mitigation öncesi sistemlerde, bir kernel NULL-pointer dereference'i attacker belleğine düşsün diye 0 adresini reserve et.
Neden heap değil de VAD

Heap/pool grooming, bir victim object'in hangi komşuyu aldığını kontrol eder; VAD spraying ise hangi adresin attacker verisine çözüldüğünü kontrol eder. Birbirini tamamlayıcıdırlar: bir kernel exploit'i çoğu zaman bir race kazanmak için pool'u groom'lar, ardından corrupted pointer'ın referans alacağı fake yapıyı barındırmak için VAD-backed bir user range kullanır.

Detection

  • Telemetry: tek bir process'ten gelen olağandışı hacimde NtAllocateVirtualMemory/VirtualAlloc reservation'ı, özellikle çok sayıda küçük aynı boyutlu region ya da düşük/sabit adresleri hedefleyen reservation'lar, spraying ile tutarlıdır; ETW (Microsoft-Windows-Kernel-Memory) ya da EDR üzerinden yüzeye çıkar.
  • Memory forensics: VAD tree'yi enumerate eden araçlar (örneğin Volatility vadinfo/vadtree, WinDbg !vad), çok sayıda aynı boyutta/protection'da private region ortaya çıkarır — çoğu zararsız process için bir anomali.
  • Executable user mapping'leri: bir sürü PAGE_EXECUTE_READWRITE private reservation ya da şüpheli sabit adreslerde commit'ler, yüksek değerli bir alarmdır.

Mitigation

  • Bottom-up/top-down ASLR (Windows 8+) VirtualAlloc/MapViewOfFile allocation'larının base'ini randomize eder; 64-bit'te high-entropy ASLR, bottom-up için "1 TB of variance … 24 bits of entropy" verir, böylece attacker "do[es] not have enough memory available to spray the amount that would be needed."
  • NULL-page / düşük-adres allocation'ı engellenir modern Windows'ta NULL-deref varyantı için (address space'in alttaki 64 KB'ı normal user kodu tarafından map'lenemez).
  • SMEP kernel'in user-mode page'leri çalıştırmasını engeller, HVCI/Memory Integrity + kCFG ise user-controlled koda/pointer'lara jump etmeyi veya güvenmeyi bloklar; spray'lenmiş range'den çalıştırma hedefini nötralize eder.
  • /DYNAMICBASE + /HIGHENTROPYVA'yı etkinleştir ve tahmin edilebilir adresleri yeniden getiren non-ASLR image'ları yüklemekten kaçın.

References