Skip to content

tagWND.cbWndExtra arbitrary write primitive

Bir window'un tagWND.cbWndExtra'sını ("extra bytes" length'i) corrupt et, böylece SetWindowLongPtr object'in ötesine, kernel desktop heap'ine yazsın; sınırlı bir window field'ını controlled bir relative/arbitrary write'a çevirerek (CVE-2021-1732'nin çekirdeği).

Mechanism

Note

Her window object'i (tagWND), class-tanımlı bir blok extra bytes taşıyabilir; length tagWND.cbWndExtra'da yaşar ve veri, kernel'in cbWndExtra'ya karşı bounds-check ettiği, caller'ın seçtiği bir offset'te SetWindowLongPtr/GetWindowLongPtr ile erişilebilir. Korunan invariant şudur: offset, object'in kendi extra-bytes bölgesinin içinde kalır. CVE-2021-1732 bunu, bir user-mode callback sırasında bir flag'i field'dan desync ederek kırar. win32kfull!xxxCreateWindowEx, xxxClientAllocWindowClassExtraBytes üzerinden user mode'a callback yaptığında, attacker window'u bir console window'a çevirmek için NtUserConsoleControl'ı çağırır — bu da bir flag set eder (örn. dwExtraFlag'te 0x800), böylece pExtraBytes bir user-mode pointer yerine bir kernel desktop heap offset olarak yorumlanır — ve ardından NtCallbackReturn, flag set kalırken extra-bytes field'ına düşen bir attacker değeri döndürür. Sonuç: cbWndExtra (ya da offset mekanizması) artık attacker-etkili'dir ve sonraki bir SetWindowLongPtr, victim object'in ötesindeki kernel desktop-heap belleğine yazar.

Bu, bir state-desync win32k callback bug'ından desktop heap üzerinde generic bir write-what-where'e giden köprüdür; orada komşu tagWND object'leri hassas biçimde yerleştirilebilir.

Walkthrough

Public CVE-2021-1732 analizlerinden (Unit 42, iamelli0t) kavramsal yeniden üretim. Yalnızca mantıksal adımlar ve fragment seviyesi:

  1. Desktop heap'i groom et, böylece bir victim window'un extra bytes'ı, field'larını kontrol etmek istediğin bir manager window'un bitişiğinde dursun.
  2. Alloc callback'ini hook et: xxxClientAllocWindowClassExtraBytes CreateWindowEx sırasında senin kodunu callback edecek şekilde register ol.
  3. Flag vs. field'ı desync et: callback içinde console flag'ini set etmek için NtUserConsoleControl'ı çağır, sonra arbitrary bir değer NtCallbackReturn et — kernel onu extra-bytes field'ına yazar ama flag'i temizlemez.
xxxCreateWindowEx
  -> xxxClientAllocWindowClassExtraBytes  (user-mode callback)
       NtUserConsoleControl(...)   // flag now says "offset is kernel heap"
       NtCallbackReturn(value)     // value lands in tagWND, flag still set
  <- kernel resumes with desynced state
  1. Write penceresini büyüt: cbWndExtra etkin olarak oversized iken, victim üzerinde SetWindowLongPtr bitişik window'un tagWND'sine yazar (örn. onun cbWndExtra'sını overwrite eder), bir relative write verir ve bu sonra arbitrary write'a pivot edilir.
Bir arbitrary read ile eşleştirme

Exploit'ler genelde controlled bir window'un extra bytes'ında fake bir spmenu (menu) forge eder ve GetMenuBarInfo'yu çağırır; bu da kernel'in fake menu'yü dereference edip veri döndürmesine neden olur — write'ı tamamlayan bir arbitrary read. Farklı bir object'ten kurulu benzer bir read/write eşleştirmesi için bkz. GDI bitmap arbitrary R/W primitive.

Altta yatan kusur bir win32k user-mode callback abuse state desync'idir; yakından ilişkili offset confusion, win32k consolecontrol offset confusion içinde görülür.

Detection

  • Class-extra-bytes alloc callback'ini hook eden ve non-console, low-integrity bir context'ten CreateWindowEx sırasında NtUserConsoleControl'ı çağıran bir process, güçlü bir davranışsal sinyaldir.
  • Bir window'un declare ettiği cbWndExtra'da veya ötesinde anormal SetWindowLongPtr offset'leri.
  • Cross-object tagWND write'larını yakalayan Driver Verifier / desktop-heap consistency check'leri; corrupt komşu cbWndExtra ile win32kfull window-field path'lerindeki bugcheck'ler.

Mitigation

  • Patch: Microsoft, xxxCreateWindowEx'teki flag/field desync'ini düzeltti; CVE-2021-1732 update'inin (ve ilgili CVE-2022-21882 regression fix'inin) kurulu olduğundan emin ol.
  • Type isolation: win32k type isolation, window object'lerini dedicated pool'lara ayırır ve adjacency grooming'i engeller. Bkz. win32k type isolation mitigation.
  • Surface azaltma: sandbox'lı process'ler için win32k syscall filtering, çağrı surface'ini kaldırır; KASLR/kCFG post-primitive maliyeti artırır.

References