LFH UserBlocks manipulation¶
Bir
_HEAP_USERDATA_HEADER'daki doğrulanmamış per-blockFreeEntryOffset'i corrupt et ki sonraki bir allocation seçilmiş bir adrese düşsün.
Mechanism¶
Kırılan invariant (NT Heap)
Bir _HEAP_SUBSEGMENT (UserBlocks : Ptr32 _HEAP_USERDATA_HEADER) LFH block'larının
array'ini prefix'leyen _HEAP_USERDATA_HEADER'a işaret eder. Anahtar field'lar SubSegment
back-pointer'ı ve FreeEntryOffset'tir — "_HEAP_USERDATA_HEADER'ın adresine eklendiğinde,
free etme ya da allocate etme için sonraki konuma bir pointer veren 2-byte'lık bir integer"
(sonraki block = UserBlocks + FreeEntryOffset * 0x8). Kritik olarak, her LFH block için
sonraki free offset user-writable data'nın ilk 2 byte'ında saklanır ve "chunk header'ları
allocation'larda doğrulanmaz." Geçilen sınır o güvendir.
Version scope — LFH key encoding
Bu "doğrulanmaz" framing'i Valasek'in 2010 pre-Win8 görüşüdür. Daha sonraki NT heap
build'lerinde (yaklaşık Vista SP1+/Win7; kesin uygulanan Windows build'leri burada
doğrulanmamıştır) encoded _HEAP_ENTRY / offset field'ı RtlpLFHKey ile XOR-obfuscate
edilir; dolayısıyla seçilmiş bir spesifik offset'i blind bir overwrite ile yerleştirmek
key'i leak/recover etmeyi (ya da hayatta kalan bir partial overwrite'ı) gerektirir.
Encoding-aware companion için bkz. windows-lfh-freeentryoffset-overwrite.
Walkthrough¶
Üst düzey, Valasek'in "FreeEntryOffset Overwrite" / "SubSegment Overwrite" bölümünden:
- Bucket'ı groom et ki kontrol edilebilir bir block free bir LFH block'una komşu otursun
(bkz.
lfh-bucket-grooming). - Komşu block'a overflow yap. "En az 0x9 (0xA tercih edilir) byte'lık bir overwrite ile,
NextOffset'in değerini etkileyebilir, hemen ardından yapılan bir allocation'ı etkileyebilirsin." - O size'ın sonraki bir
HeapAlloc'u attacker-chosen bir offset'e pointer döndürür (0xFFFF * 0x8'e kadar forward range), bir victim objenin üstüne taze bir allocation yerleştirir (paper victim olarak vtable'a sahip bir C++ obje array'ini groom'lar). - Taze "allocation" victim'le overlap eder; program'ın kendi write'ları sonra victim'in pointer'larını corrupt eder. (Yalnızca kavramsal.)
Segment Heap bunu kapatır
Win10 Segment Heap LFH per-block free-offset-in-userdata tasarımını kaldırır: bir block
bitmap kullanır (corrupt edilecek per-block header yoktur) ve "BlockOffsets ve LFH
subsegment header'ındaki encoded offset field'ı LFH key ve LFH subsegment adresi kullanılarak
encode edilir."
Detection¶
- LFH block metadata'sına overflow'ları yakalamak için page-heap / Application Verifier.
- Beklenen subsegment range'inin dışında adresler döndüren allocation'lar; allocator self-consistency assertion'ları.
- Taze bir allocation'ın canlı bir objeyle overlap ettiği crash imzaları.
Mitigation¶
- Segment Heap'in
BlockOffsets/ offset field'larını LFH key + subsegment adresiyle encode etmesi; LFH allocation randomization. - Komşulara sequential overflow'u durdurmak için LFH subsegment'lerinde guard page'ler.
- Isolated heap'ler; LFH
FirstAllocationOffset/BlockStrideencoding'i (Windows 8.1).