Skip to content

Windows Heap Safe Unlinking Bypass

Klasik "write-4" unlink primitive'i — bir free chunk'ın Flink/Blink'ini forge ederek coalesce/unlink'in bir write-what-where vermesini sağlamak — ve Microsoft'un safe-unlink consistency check'ini yenen teknikler.

Mechanism

Bozulan invariant

Bir free chunk bir doubly-linked free list'ten kaldırıldığında (bitişik free block'ların coalescing'i sırasında ya da bir list'ten allocation sırasında), klasik RtlpUnlinkFreeBlock tarzı işlem ders kitabı unlink'ini çalıştırır:

Blink->Flink = Flink;   //  *(Blink + 0) = Flink
Flink->Blink = Blink;   //  *(Flink + 4) = Blink

Flink/Blink attacker-controlled olduğunda bu klasik write-4 / write-what-where'dir. Invariant: unlink, bir node'un komşularının ona geri işaret ettiğine güvenir.

Safe Unlinking (XP SP2, sertleştirilmiş Windows 7/8), write'ları yapmadan önce Flink->Blink == entry && Blink->Flink == entry doğrulamasını ekler — list segment'inin kendi içinde tutarlı olmasını ister. Bypass'lar, bu check'in yalnızca unlink edilen tek chunk'ı doğrulaması gerçeğini sömürür.

Walkthrough

Public Litchfield ve McDonald & Valasek materyalinden alınan kavramsal reproduction. Aşağıdaki 1-3 adımı yalnızca pre-SP2 basit unlink saldırısını (classic heap, bugün tamamen mitigate edilmiş) tarihsel bağlam olarak gösterir; safe-unlink check'ini asıl yenen teknikler için aşağıdaki Bypassing the Check bölümüne bakın:

  1. Bir free chunk'ın header'ını overflow et ki Flink ≈ &target ve Blink = &value olsun (bkz. heap buffer overflow).
  2. Unlink'i tetikle — o chunk'ı allocate et ya da free sırasında bir komşuyla coalesce et (bkz. nt-heap unlink ve heap-entry unlink).
  3. Unlink, attacker değerini target'a yazar.

Platform notu

Buradaki mekanizma Windows NT heap'e özgüdür (Flink/Blink, RtlpUnlinkFreeBlock). glibc'deki unsafe unlink (fd/bk, FD->bk == P && BK->fd == P) yalnızca kavramsal analog olarak referanslanır; offset'ler ve safe-unlink check'i platforma özgüdür. Windows'a özgü ayrıntı için nt-heap unlink ve heap-entry unlink.

Bypassing the Check

Safe-unlink consistency check'ini yenen üç kavramsal yaklaşım:

  • Self-referential çift forge et: zaten kontrol ettiğin bellekte kendi içinde tutarlı bir Flink/Blink çifti oluştur; sahte pointer'lar gerçekten birbirini ve entry'yi gösterir, böylece Flink->Blink == Blink->Flink == entry tutar ve check geçilir.
  • Check'siz bir path'e saldır: doğrulamayı tümüyle atlayan bir kod path'ini hedefle, örneğin FreeList[0] insert splice'ı ya da lookaside list pop'u.
  • Non-terminating detection'ı suistimal et: XP SP2'de erken unsafe-unlink tespiti process'i sonlandırmaz; corrupt ama kullanılabilir bir heap bırakır.

Detection

  • RtlpUnlinkFreeBlock / RtlpCoalesceFreeBlocks içinde AV'ler; 0xC0000374 heap-corruption bugcheck'leri.
  • PageHeap altında double-free / coalesce anomalileri.
  • EDR, bir function pointer'a, SEH chain'ine ya da _PEB->FastPebLock'a düşen bir write-what-where'i işaretler.
  • !heap -v doğrulamasında görünen eşleşmeyen Flink->Blink / Blink->Flink.

Mitigation

  • Safe Unlinking (XP SP2; encoded header'larla sertleştirilmiş Windows 7/8, böylece pointer'ların kendisi kolayca forge edilemez).
  • Heap header cookie / XOR encoding (Vista+) forge maliyetini artırır.
  • HeapEnableTerminationOnCorruption — tespit edilen bir tutarsızlıkta devam etmek yerine dur (bkz. validate heap integrity).
  • Windows 10 Segment Heap, encoded header'lar ve guard page'lerle farklı bir metadata layout'u kullanır.

References