Skip to content

LFH UserBlocks manipulation

Bir _HEAP_USERDATA_HEADER'daki doğrulanmamış per-block FreeEntryOffset'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:

  1. Bucket'ı groom et ki kontrol edilebilir bir block free bir LFH block'una komşu otursun (bkz. lfh-bucket-grooming).
  2. 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."
  3. 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).
  4. 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 / BlockStride encoding'i (Windows 8.1).

References