Skip to content

Segment Heap

Modern Windows 10+ native heap'i (birçok system/Store/Edge process'i için default, win32 app'leri için opt-in); bir page-range tree üzerine LFH, Variable Size ve backend allocator'larından inşa edilmiştir.

Mechanism

Segment Heap, Windows 10'da tanıtılan native user-mode heap implementasyonudur. Legacy NT Heap ile yan yana var olur ve process başına seçilir: Windows app'leri (UWP/Store) ve belirli system process'leri için default'tur, Microsoft Edge için etkindir ve executable başına toggle edilebilir.

Bu not vs. sibling

Bu sayfa allocator'ın yapısını/internals'ını (LFH/VS/backend dispatch, page-range tree'leri) belgeler — bir saldırı değil. Bu yapı üzerine kurulu somut corruption tekniği (VS _HEAP_VS_CHUNK_HEADER coalesce forge) için bkz. Segment Heap exploitation.

Note

Savunucunun ihtiyaç duyduğu yapısal gerçek: tek bir _SEGMENT_HEAP front-end'i, her isteği yalnızca AllocSize'a göre üç internal allocator'dan birine dispatch eder ve üçü de page'lerini, NtAllocateVirtualMemory() ile reserve/commit eden tek bir backend'den çeker. Bu deterministik size-to-allocator yönlendirmesi, heap'i groomable kılan şeydir: allocation boyutlarını seçebilen bir attacker, bir victim object'in hangi allocator'a (ve dolayısıyla hangi adjacency kurallarına) tabi olacağını seçebilir. Üç bileşen şunlardır: Low Fragmentation Heap (küçük, bucket'lanmış block'lar), Variable Size (VS) allocator ve backend/large-block allocator. Yason paper'ına göre, "Variable size (VS) allocation is used for allocations with sizes 1 to 131,072 (0x20000) bytes"; daha büyük istekler doğrudan backend'e gider ve küçük boyutlar, ilgili bucket aktive edildiğinde bir LFH bucket'ı tarafından servis edilir.

RtlpHpAllocateHeap() içindeki dispatch mantığı önce o boyut için LFH bucket'ını dener; bucket henüz aktive değilse "returns -1" yapar ve istek VS allocator'a düşer. Backend'in kendisi free alanı bir red-black tree of page ranges (FreePageRanges) ile izler ve VS/LFH subsegment'leri kendileri özel backend block'larıdır (bir VS subsegment'inin ilk page-range descriptor'ında PAGE_RANGE_FLAGS_VS_SUBSEGMENT (0x20) flag'i set'lidir).

Bu, legacy NT Heap'in FreeLists/_HEAP_ENTRY modelinden temiz bir kopuştur: Segment Heap'teki header'lar encode'ludur, free block'lar klasik doubly-linked unlink list'leri yerine tree'lerde izlenir ve LFH ile VS context'leri için metadata _SEGMENT_HEAP yapısında (LfhContext, VsContext) durur.

Walkthrough

Yüksek seviye, herkese açık Yason "Windows 10 Segment Heap Internals" white paper'ından:

  1. Heap oluşturma. RtlpHpSegHeapCreate(), NtAllocateVirtualMemory() ile bir bölge reserve eder; commit boyutu sadece _SEGMENT_HEAP yapısıdır ve onun altındaki bellek ("LFH context extension"), LFH bucket'ları aktive oldukça lazy olarak commit edilir.
  2. Allocation yönlendirme. S boyutlu bir istek RtlpHpAllocateHeap()'e girer:

    if  S <= LFH-serviceable and bucket active -> LFH
    elif S <= 0x20000                          -> VS allocator
    else                                       -> backend (large block)
    
  3. VS best-fit. RtlpHpVsContextAllocate(), VS free tree'sinde best-fit bir block arar (key = 16-byte birim sayısı + bir memory-cost word'ü); kalan kısım < 0x20 byte olmayacaksa oversized block'ları split eder.

  4. LFH aktivasyonu. Tekrarlanan aynı boyutlu istekler eşleşen LFH bucket'ını aktive eder; ondan sonra o boyutlar VS allocator yerine LFH subsegment'lerinden servis edilir — bir attacker'ın bir victim object'i seçilen bir allocator'a taşımak için kasıtlı tetikleyebileceği bir geçiş.
Bir binary için etkinleştirme/devre dışı bırakma

Paper, IFEO knob'unu belgeliyor:

HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\Image File Execution Options\(exe)
    FrontEndHeapDebugOptions = (DWORD)
    Bit 2 (0x04): Disable Segment Heap
    Bit 3 (0x08): Enable Segment Heap

Bu, hem hardening için hem de belirli bir process'in neden NT Heap yerine Segment Heap kullandığını anlamak için yararlı bir yapılandırma gerçeğidir.

Detection

  • Segment Heap kendisi bir exploit değildir; tespit, onu suistimal eden corruption'a odaklanır. Adjacency overflow'larını anında access violation'lara çevirmek için aday binary'leri PageHeap / Application Verifier (gflags) altında çalıştır.
  • Crash telemetrisi / WER: ntdll!Rtlp*Heap* rutinleri içindeki access violation'lar (encoded-header validation hataları, VS free-tree veya backend page-range tree tutarsızlıkları) metadata corruption'ın güçlü bir sinyalidir.
  • EDR/ETW: bir LFH bucket'ını inactive'den active'e iten aynı boyutlu allocation'ların anormal patlamaları ya da büyük VS/backend reservation'ları grooming ile tutarlıdır; vulnerable process ile ilişkilendir.

Mitigation

  • Windows'u güncel tut — Segment Heap hardened metadata ile gelir (encoded header'lar, tree-tabanlı free tracking, randomize LFH) ve Microsoft bu check'leri zamanla sıkılaştırır.
  • HVCI / Memory Integrity ve CFG, bir heap corruption'ı code execution'a çevirmenin maliyetini yükseltir.
  • Process başına, hardened layout'undan fayda gören binary'ler için Segment Heap, IFEO FrontEndHeapDebugOptions bit'i ile force-enable edilebilir veya test sırasında debug varyantları etkinleştirilebilir.
  • /DYNAMICBASE + /HIGHENTROPYVA ile derle ki heap base high-entropy ASLR'den faydalansın ve adres tahminlerinin değeri azalsın.

References