Skip to content

Pool Feng Shui (kernel pool grooming)

Windows kernel pool'unu aynı boyutta çok sayıda allocation spray'leyip seçici şekilde free'leyerek deterministik biçimde şekillendirmek; böylece bir vulnerable object, seçilen bir victim object'in hemen yanına düşer ve güvenilmez bir overflow/UAF, öngörülebilir bir corruption'a dönüşür.

Mechanism

Note

Kernel pool, size'a göre ayrılmış bir allocator'dır: belli bir yuvarlanmış boyuttaki istekler aynı free/lookaside yapılarından karşılanır, dolayısıyla aynı boyuttaki allocation'lar pool meşgulken contiguous (ardışık) yerleşme eğilimindedir. Attacker bu determinizmi kullanır. Önce çok sayıda aynı boyutta, attacker kontrolündeki object'i spray'leyerek pool'un free bölgeleri tüketilir ve yeni allocation'lar sıkışık şekilde paketlenir. Ardından hole punching — her N'inci sprayl'enen object'i free'lemek — tam olarak bir object genişliğinde öngörülebilir boşluklar yaratır. Sonraki vulnerable buffer allocation'ı bilinen bir hole'a düşer ve seçilen victim object'in hemen arkasında oturmasını garanti eder.

Teknik tek başına bir bug exploit'lemez; randomness'ı ortadan kaldırır ki ayrı bir primitive (linear pool overflow, off-by-one veya use-after-free reclamation) corruption'ı işe yarayan bir target'a güvenilir şekilde isabet etsin — örneğin TypeIndex/callback pointer'ı ya da gömülü length alanı yönlendirilebilen bir object header. Modern build'lerde per-CPU Low Fragmentation Heap (kLFH / segment pool) layout matematiğini değiştirir, bu yüzden grooming, LFH bucket'larını ve subsegment davranışını hesaba katmalıdır.

Walkthrough

Klasik HEVD pool-overflow alıştırması (rootkits.xyz / FuzzySecurity), non-paged pool içinde CreateEventA Event object'lerini spray'ler. Event object'leri küçük, sabit boyutlu, tamamen attacker tarafından allocate edilen ve CloseHandle ile istendiğinde free'lenen object'lerdir — ideal grooming dolgusu.

Step 1 — Pool'u doldurup yoğunlaştırmak için spray.

# Allocate two large arrays of identically-sized Event objects (NonPagedPool)
spray_event1 = []
for i in range(10000):
    spray_event1.append(kernel32.CreateEventA(None, False, False, None))

spray_event2 = []
for i in range(5000):
    spray_event2.append(kernel32.CreateEventA(None, False, False, None))

Step 2 — Hole punch (düzenli bir pattern'i free'le) ile tek-object'lik boşluklar yarat.

# Free a strided pattern from the second array to open predictable holes
for i in range(0, len(spray_event2), 16):
    for j in range(0, 8, 1):
        kernel32.CloseHandle(spray_event2[i + j])

Step 3 — Vulnerable buffer'ı bir hole içine allocate et.

Vulnerable allocation (burada kcaH tag'li 0x1f8-byte'lık bir buffer) artık hayatta kalan Event object'lerinin tam yanına düşer. Buradan yapılan linear bir overflow, komşu object'in POOL_HEADER'ını ve object gövdesini ezer — groom, komşunun rastgele pool verisi değil bir Event olmasını garanti eder.

Grooming sonrası adjacency (kavramsal !pool görünümü)
ffffd00`2a1c0000  size:  0x200  Used  tag: kcaH  <-- vulnerable buffer (overflow source)
ffffd00`2a1c0200  size:  0x040  Used  tag: Even  <-- victim Event (corruption target)
ffffd00`2a1c0240  size:  0x040  Used  tag: Even
...

Warning

Spray sayıları, hole stride'ı ve chunk boyutları build'e ve sistem yüküne bağlıdır. Aşırı spray pool'u tüketip bugcheck'e yol açabilir; yetersiz spray ise layout'u gürültülü bırakır. Güvenilir groom'lar bu değerleri her target için ampirik olarak ayarlar ve Windows 10/11'de kLFH bucketing'ini hesaba katar.

Detection

  • Low-privilege bir process'in kısa bir patlama içinde on binlerce kernel object'i (Event'ler, named pipe'lar, reserve object'ler) oluşturup ardından strided bir pattern'le toplu free'lemesi anormal bir grooming signature'ıdır.
  • CloseProcedure/callback'e kadar hayatta kalan ve non-canonical ya da user-range bir pointer taşıyan pool corruption'ı güçlü bir post-exploitation göstergesidir.

Mitigation

  • kLFH randomization (Windows 10 19H1+) per-bucket allocation randomness getirir ve deterministik adjacency'yi bozar.
  • Pool header integrity check'leri ve PoolQuota / safe-unlinking, free sırasında bozulmuş POOL_HEADER alanlarını tespit eder.
  • Hassas object'lerin type-isolation'ı ve dedicated pool'lar, işe yarar komşu victim arzını azaltır.

See also: hevd-pool-buffer-overflow-scenario, non-paged-pool-overflow-exploitation, low-fragmentation-heap-grooming, named-pipe-non-paged-pool-grooming, pool-lookaside-list-confusion.

References