Skip to content

Windows LFH BlockStride / FirstAllocationOffset Corruption

LFH'nin bir sonraki allocation adresini hesaplamak için kullandığı subsegment geometry alanlarını corrupt ederek, allocator'ın attacker tarafından kaydırılmış, out-of-bounds bir pointer döndürmesini sağlamak.

Mechanism

Bozulan invariant

Low Fragmentation Heap, same-size istekleri bir _HEAP_SUBSEGMENT tarafından tanımlanan bir UserBlocks region'ından (_HEAP_USERDATA_HEADER) karşılar. LFH saklanmış bir pointer'ı çekmek yerine, sonraki block'u hesaplar:

next = UserBlocks_base + FirstAllocationOffset + BlockStride * index

Invariant, FirstAllocationOffset ve BlockStride'ın region'ı dürüstçe sınırlamasıdır. Subsegment metadata'sına bu alanlardan birini değiştiren linear bir overflow, bu çarp-ve-topla işleminin out-of-bounds / attacker tarafından kaydırılmış bir pointer döndürmesini sağlar; program da bunun içine write yapar — free-list unlink'i gerektirmeyen controlled bir write.

Heap başına RtlpLFHKey önemlidir: subsegment back-pointer'ları (ve Windows 8.1+'da geometry alanlarının kendisi) XOR-encoded'dur, dolayısıyla key olmadan yapılan blind bir overwrite, kullanılabilir bir offset üretmek yerine consistency check'i geçemez.

Walkthrough

Kavramsal reproduction (bkz. Rapid7 ve Valasek public yazıları):

  1. Bucket için LFH'yi aktive etmek üzere yeterince same-size allocation (~18) yap (bkz. LFH bucket grooming).
  2. Subsegment metadata'sına bitişik overflow edilebilir bir chunk groom et (bkz. LFH UserBlocks manipulation).
  3. FirstAllocationOffset / BlockStride'ı overflow et:

    Temsili mantık (çalışan bir exploit değil)
    overflow_into(&subseg.BlockStride, value);   // poison the stride
    // next = base + FirstAllocationOffset + BlockStride * index  -> OOB
    
  4. Bir block daha iste — allocator kaydırılmış pointer'ı döndürür.

  5. Bitişik bir object'in vtable'ına / function pointer'ına düşmek için onun üzerinden write yap.

Sertleştirilmiş build'lerde bu, encoded alanları forge etmek ve allocation-order randomization'ını yenmek için ek olarak bir info leak gerektirir.

Detection

  • Full PageHeap (gflags /p /enable img /full) overflow noktasında fault verir.
  • Metadata hataları STATUS_HEAP_CORRUPTION / FAST_FAIL_HEAP_METADATA_CORRUPTION (kernel bugcheck 0x13A) yükseltir.
  • WinDbg !heap / dt _HEAP_SUBSEGMENT, chunk'ı sınırlamayan bir stride/offset gösterir.
  • ntdll LFH routine'lerindeki heap fast-fail'lerinde EDR/WER kümelenmesi; izlenen herhangi bir segment'in dışında döndürülen allocation'lar.

Mitigation

  • Windows 8.1+, FirstAllocationOffset ve BlockStride'ı encode eder.
  • Windows 8+ LFH allocation-order randomization'ı deterministik indexing'i kırar (Rapid7, offset tahmin edilebilirliğinin Win7'de ~%97,8'den Win10'da ~%6'ya düştüğünü ölçtü).
  • Random RtlpLFHKey + encoded back-pointer'lar; büyük allocation'larda/ subsegment'lerde guard page'ler.
  • HeapEnableTerminationOnCorruption (modern process'ler için varsayılan); birçok system process için 19H1 Segment Heap.

References