Skip to content

Windows LFH FreeEntryOffset overwrite

Win8 öncesi bir LFH block'unun içindeki encoded FreeEntryOffset "next free" cursor'ını overwrite ederek, o bucket'tan yapılan bir sonraki allocation'ı attacker'ın seçtiği, üst üste binen bir slot'a yönlendirmek.

Mechanism

Bozulan invariant

Windows 8 öncesi LFH'de, her block'un encoded _HEAP_ENTRY'si bir FreeEntryOffset taşır — block başına "next free" cursor. Allocator sonraki chunk'ı UserBlocks + FreeEntryOffset * granularity olarak türetir; defter tutma subsegment _INTERLOCK_SEQ'tedir. Invariant, bu free cursor'ın allocator'a özel ve güvenilir olmasıdır.

Küçük header'ı aşıp bitişik bir block'un encoded _HEAP_ENTRY'sine ulaşan linear bir overflow, FreeEntryOffset'i yeniden yazar; böylece o bucket'tan yapılan sonraki allocation attacker'ın seçtiği bir slot'a yönlendirilir ve overlapping chunks / controlled placement üretir. _HEAP_ENTRY, heap başına RtlpLFHKey ile XOR-obfuscate edilmiştir; (yalnızca crash etmek yerine) belirli bir offset yerleştirmek için attacker key/keystream'i leak etmeli ya da sağ kalan kısmi bir overwrite'a güvenmelidir.

Walkthrough

Kavramsal reproduction (bkz. Valasek'in LFH analizi):

  1. Bucket için LFH aktivasyonunu zorla (bkz. LFH bucket grooming).
  2. Overflow kaynağını victim block'un hemen önüne yerleştirmek için free/realloc yap.
  3. Encoding'i kurtar (RtlpLFHKey'i ya da bilinen bir encoded header'ı leak et) ki istenen bir offset doğru şekilde yeniden encode olsun.
  4. Victim'in encoded _HEAP_ENTRY'sini overflow et ki decode edilmiş next-free offset seçilen bir slot'u göstersin:

    Temsili mantık (çalışan bir exploit değil)
    // next = UserBlocks + FreeEntryOffset * granularity
    encoded_entry.FreeEntryOffset = encode(chosen_slot, RtlpLFHKey);
    
  5. Bucket'tan geri al ve read/write ya da type confusion için overlap'e farklı tipte bir object spray'le.

Detection

  • PageHeap / Application Verifier overflow'u yakalar (not: bunları etkinleştirmek gerçek LFH'yi devre dışı bırakır, yani bu yalnızca test zamanı sinyalidir).
  • Terminate-on-corruption altında bir decode-checksum hatasından gelen STATUS_HEAP_CORRUPTION (0xC0000374).
  • RtlpLowFragHeapAllocFromContext / RtlpLogHeapFailure içinde WER/EDR fault'ları.
  • Bir crash'in hemen öncesinde bir grup same-size allocation (grooming) artı size-class free/realloc çalkalanması.

Mitigation

  • _HEAP_ENTRY / LFH encoding + header checksum — blind bir overwrite decode'u geçemez.
  • Windows 8 redesign'ı artık FreeEntryOffset kullanmaz: block seçimi, randomize edilmiş allocation order, BlockZones integrity check'leri ve UserBlocks arasında guard page'lerle bitmap-tabanlıdır.
  • HeapEnableTerminationOnCorruption; Windows 10+'da Segment Heap front end'i.

References