Skip to content

GDI Palette object arbitrary R/W primitive (pFirstColor/cEntries)

Bozuk bir Windows kernel GDI PALETTE objesinin, dokümante edilmiş Get/SetPaletteEntries API'leri aracılığıyla tek bir write-where bug'ını kararlı bir arbitrary kernel read/write'a nasıl dönüştürdüğünün kavramsal kataloğu.

Mechanism

Kırılan invariant

Bir GDI PALETTE (kernel'da _XEPALOBJ), color table'ı attacker açısından iki alanla tanımlanan pool-backed bir objedir: pFirstColor (entry array'ine bir pointer) ve cEntries (entry sayısı). Dokümante edilmiş user-mode API'leri GetPaletteEntries / SetPaletteEntries (ve AnimatePalette) tam olarak user mode adına color data'yı kernel objesinin içine ve dışına kopyalamak için vardır.

Security boundary aşılır çünkü o trusted copy routine'leri körü körüne objenin kendi pFirstColor/cEntries'ine güvenir. Ayrı bir kernel write-where bug'ı pFirstColor'ı arbitrary kernel memory'ye işaret edecek şekilde bozarsa (ya da cEntries'i şişirerek in-bounds görünen index'lerin sonun ötesini okumasını sağlarsa), aynı yetkilendirilmiş user→kernel kopyası artık attacker'ın nişanladığı yere okur ya da yazar. Code execution gerekmez: primitive tamamen bozuk bir data pointer artı meşru API çağrılarından kurulur.

Walkthrough

Üst-seviye, public research'ten (SensePost, HITB 2018):

  1. Bir write primitive seed'le. Bir pool overflow / write-where bug'ı, bitişik bir PALETTE'in pFirstColor'ını ya da cEntries'ini bozmak için kullanılır.
  2. Manager + worker pattern'i. Reliability için bir manager palette, ikinci bir worker palette'in pFirstColor'ını overwrite etmekte kullanılır. Manager ardından worker'ı talep üzerine herhangi bir kernel adresine yeniden nişanlar.
  3. Read/write. GetPaletteEntries(worker, ...) nişanlanan adresteki kernel memory'yi okur; SetPaletteEntries(worker, ...) onu yazar. 2. adımı tekrarlamak bunu tekrarlanabilir bir arbitrary R/W yapar.
  4. Escalate. Tipik olarak EPROCESS'i leak/lokalize etmek ve SYSTEM token'ını çalmak için kullanılır (bkz. eprocess-token-stealing).
Kavramsal şekil

corrupt(worker.pFirstColor = TARGET); GetPaletteEntries(worker) -> *TARGET

Detection

  • Çok sayıda palette/bitmap oluşturup ardından sıkı Set/GetPaletteEntries döngüleri issue eden process'ler, özellikle low-integrity / sandboxed bir process'ten.
  • PALETTE/SURFACE'a referans veren win32k/win32kbase pool-corruption bugcheck'leri.
  • GDI obje churn'ünün ardından local privilege-escalation davranışı (token swap).
  • Tarihsel KASLR öncülü: PEB'den GdiSharedHandleTable okumaları.

Mitigation

  • GDI Type Isolation (Windows 10 1709+) SURFACE/Bitmap header'larını attacker'ın erişebildiği data buffer'larından ayırarak Bitmap-as-target tekniğini zorlaştırır; ancak bu mitigation SURFOBJ/Bitmap header'ları için tasarlanmıştı ve palette corruption path'ini kırmaz — araştırmacıları geriye kalan bir vektör olarak PALETTE nesnelerine yönlendiren şey tam da budur. Çıtayı yükseltir, sınıfı kapatmaz (bkz. win32k-type-isolation-mitigation).
  • User-mode GdiSharedHandleTable kernel-address leak'inin kaldırılması (1607).
  • Kernel pool integrity hardening, SMAP ve (Win11) kernel CFG.
  • Corruption'ı seed'leyen upstream write-where bug'ını ortadan kaldır.

References