DirectComposition — Kernel Research

Тема в разделе "WASM.RESEARCH", создана пользователем galenkane, 2 июн 2026 в 06:22.

  1. galenkane

    galenkane Active Member

    Публикаций:
    4
    Регистрация:
    13 янв 2017
    Сообщения:
    475
    DirectComposition — Kernel Research via WinDbg
    Полный ресерч архитектуры DirectComposition в ядре Windows (ARM64), полученный через живое disassembly в WinDbg. Исследование проводилось на Parallels Desktop VM (Windows ARM64) с kernel debugging через кастомный windbg_agent.dll MCP.
    Архитектура: 3-Layer System
    DirectComposition — это 3-уровневая система в ядре Windows:
    Код (Text):
    1. User32.dll / DComp.dll (user-mode)
    2.         |
    3.         v
    4. win32kbase / win32kfull (session-space kernel)
    5.         |            |
    6.         v            v
    7. dxgkrnl.sys          DWM.exe (compositor process)
    8.         |
    9.         v
    10. GPU Driver DDI
    NtUserCreateDCompositionHwndTarget (win32kfull) — главный syscall для создания composition target:
    Код (Text):
    1. 1. TestWindowForCompositionTarget — валидация HWND
    2. 2. CreateSharedSystemVisualObject — alloc 0xB8 bytes, создает shared resource object
    3. 3. AttachWindowCompositionTarget — bind к HWND:
    4.    ├── EnterCrit
    5.    ├── ValidateHwnd
    6.    ├── Проверка стиля окна: (style & 0xFFFF2FFF) == 0x29D
    7.    ├── Win32HM_LockIntoThread → PsGetCurrentProcess vs IoThreadToProcess
    8.    │   └── Если не тот процесс → STATUS_ACCESS_DENIED (0xC0000022)
    9.    └── _AttachWindowCompositionTarget:
    10.        ├── W32GetUserSessionState
    11.        ├── GetProp(atom=0xA542) → CHwndTargetProp
    12.        │   └── Если нет → CWindowProp::CreateWindowProp<CHwndTargetProp>
    13.        ├── CWindowProp::SetProp
    14.        ├── CHwndTargetProp::SetSystemVisual:
    15.        │   ├── ApiSetEditionNotifyDwmForSystemVisualCreation
    16.        │   └── ObReferenceObjectByPointer(type=CompositionObject)
    17.        └── CreateVisRgnTracker (type 0 → flag 4, type 1 → flag 8)
    18. 4. CompositionObject::CreateHandle → ObOpenObjectByPointer → handle
    CompositionObject::Create (win32kbase) — создание kernel объекта:
    Код (Text):
    1. ObCreateObject(0xB0 bytes) →
    2.   W32GetCurrentWin32kSessionId → store at [obj+8] →
    3.   ZwAllocateLocallyUniqueId → LUID at [obj+0x10] →
    4.   virtual init callback →
    5.   ObInsertObject → handle
    6. Validation: CompositionObjectType (w4-1) must be <= 5 → 6 object types
    Disassembly CompositionObject::Create (win32kbase!d622c9b0):
    Код (Text):
    1. pacibsp
    2. stp  x19,x20,[sp,#-0x20]!
    3. stp  fp,lr,[sp,#-0x10]!
    4. mov  fp,sp
    5. mov  x19,x0                ; CompositionObjectType
    6. ...
    7. mov  w5,#0xB0               ; object size = 0xB0 bytes
    8. mov  x4,#0                  ; no ParseContext
    9. mov  w3,#1                  ; ObjectBody size present
    10. mov  x2,x1                  ; OBJECT_ATTRIBUTES
    11. ldr  x1,[...ObjectType]     ; CompositionObjectType ptr
    12. sxtb w0,w0                  ; sign-extend alloc type
    13. bl   nt!ObCreateObject      ; ★ create kernel object
    14. ...
    15. bl   nt!PsGetCurrentProcess
    16. bl   nt!PsGetProcessSessionId
    17. str  w0,[x8,#8]             ; store SessionId at obj+8
    18. ...
    19. add  x0,x8,#0x10            ; LUID at obj+0x10
    20. bl   nt!ZwAllocateLocallyUniqueId  ; ★ assign LUID
    21. ...
    22. bl   nt!ObInsertObject      ; ★ insert into handle table
    ShouldComposeWindow — решает, нужно ли окно композить:
    Код (Text):
    1. if ([window+0x18] == NULL || [window+0x18] == arg1):
    2.     return false
    3. if IsWindowBeingDestroyed: return false
    4. if !([window_state+0x1F] & 0x10): return false  // bit 4 = "has composition"
    5. if IsTopLevelWindow: return true
    6. if IsDesktopWindow: return true
    7. return false
    Disassembly ShouldComposeWindow (win32kfull!d6641f30):
    Код (Text):
    1. pacibsp
    2. stp  fp,lr,[sp,#-0x10]!
    3. mov  fp,sp
    4. mov  x11,x0                 ; window object
    5. ldr  x8,[x11,#0x18]         ; composition target ptr
    6. mov  w12,#0                  ; result = false
    7. cmp  x8,#0
    8. ccmpne x8,x1,#0             ; compare with expected value
    9. bne  skip                    ; if target != null && != expected → skip
    10. bl   IsWindowBeingDestroyed
    11. cbnz w0,skip                 ; being destroyed → skip
    12. ldr  x8,[x11,#0x28]         ; window internal state
    13. ldrb w8,[x8,#0x1F]          ; flags byte
    14. tbz  w8,#4,skip             ; ★ bit 4 not set → not composed → skip
    15. mov  x0,x11
    16. bl   IsTopLevelWindow
    17. cbnz w0,compose_yes
    18. mov  x0,x11
    19. bl   IsDesktopWindow
    20. cbz  w0,skip
    21. compose_yes:
    22. mov  w12,#1                  ; result = true
    23. skip:
    24. mov  w0,w12
    ComposeWindowIfNeeded — main composition pipeline:
    Код (Text):
    1. 1. IsToplevelWindowDesktopComposed?
    2.    ├── YES: ComposeWindow(type=5 if arg==0, else 0xD)
    3.    │        DirtyVisRgnTrackers
    4.    │        ReferenceDwmApiPort → get DWM LPC port
    5.    │        IncrementDWMWindowUniqueness
    6.    │        → if port exists: LPC message to DWM via nt!LpcRequestPort
    7.    │           (message size 0x3C, type 0x40000016, data 0x16)
    8.    ├── NO + IsDesktopWindow:
    9.    │   → IsWindowDesktopComposed?
    10.    │     → YES: goto ComposeWindow path
    11.    └── NO:
    12.        → IsChildWindowDpiBoundaryDesktopComposed?
    13.          → YES: goto ComposeWindow path
    14.          → NO: return error
    Disassembly ComposeWindowIfNeeded (win32kfull!d6525ac8):
    Код (Text):
    1. pacibsp
    2. stp  x19,x20,[sp,#-0x20]!
    3. ...
    4. mov  x19,x0                  ; window
    5. mov  w20,w1                  ; compose type
    6. bl   IsToplevelWindowDesktopComposed
    7. cbz  w0,check_desktop        ; not top-level composed → check desktop
    8. ...
    9. ; === Compose path ===
    10. cmp  w20,#0
    11. mov  w9,#5
    12. mov  w8,#0xD
    13. cseleq w1,w9,w8              ; type = 5 if arg==0, else 0xD
    14. mov  x0,x19
    15. bl   ComposeWindow           ; ★ compose the window
    16. mov  w21,w0
    17. mov  x0,x19
    18. bl   DirtyVisRgnTrackers     ; ★ mark visual region dirty
    19. ...
    20. bl   ReferenceDwmApiPort     ; ★ get DWM communication port
    21. ...
    22. ; === Build LPC message and send to DWM ===
    23. movi v16.16b,#0
    24. ldr  w8,[...msg_type]        ; 0x3C0014 → type 0x40000016
    25. str  w8,[sp,#0x10]
    26. mov  w8,#-0x8000
    27. strh w8,[sp,#0x14]           ; HWND handle
    28. ...
    29. bl   nt!LpcRequestPort       ; ★ send LPC message to DWM
    30. bl   nt!ObDereferenceObject  ; release port reference
    ComposeWindow — ядро composition:
    Код (Text):
    1. if (type & 1):  // compose operation
    2.     if IsDesktopWindow: session state path
    3.     check window_state[0x1F] bit 4 (composed flag)
    4.     if window_state[0x1A] & 8:  // has sprite
    5.         → UpdateWindowSpriteMonitor
    6.     if window_state[0xE8] & 2:  // already layered
    7.         → UnsetLayeredWindow(type)
    8.     else:
    9.         → AtomicExecutionCheck guard
    10.         → xxxSetLayeredWindow (make layered)
    11.         → SetLayeredWindowAttributes(alpha=0xFF)
    12.         → sets window_state[0xE8] |= 2  // mark as layered
    13.         → ReferenceDwmApiPort
    14.         → DwmAsyncChildStyleChange notification
    CSwapChainProp::SetCompositionSurfaceObj — простая функция:
    Код (Text):
    1. if ([prop+0x18] != NULL):
    2.     MicrosoftTelemetryAssertTriggeredArgsKM(assert)  // warning: already set
    3. [prop+0x18] = composition_surface_obj  // просто store указателя
    Disassembly (win32kfull!d66b6c20):
    Код (Text):
    1. pacibsp
    2. stp  x19,x20,[sp,#-0x10]!
    3. stp  fp,lr,[sp,#-0x10]!
    4. mov  fp,sp
    5. mov  x19,x0                  ; this (CSwapChainProp)
    6. ldr  x8,[x19,#0x18]          ; existing surface obj
    7. mov  x20,x1                  ; new surface obj
    8. cbz  x8,store                ; if null → ok to set
    9. ; --- Assert if already set ---
    10. adrp x8,...
    11. add  x0,x8,#0xEC0            ; assert message
    12. mov  w2,#0x5C                ; line number
    13. mov  w1,#0x20000              ; severity
    14. bl   MicrosoftTelemetryAssertTriggeredArgsKM
    15. store:
    16. str  x20,[x19,#0x18]         ; ★ store surface object pointer
    UserSetWindowedSwapChain — syscall привязки swap chain к окну:
    Код (Text):
    1. 1. EnterCrit → ValidateHwnd
    2. 2. Проверка стиля: (style & ~0xD001) - 0x29D must have no bits in 0xFFFFFFFD
    3. 3. IsWindowBeingDestroyed → reject
    4. 4. IsWindowDesktopComposed → check
    5. 5. DxgkReferenceCompositionObject(handle) → get dxgkrnl composition object
    6. 6. CWindowProp::GetProp<CSwapChainProp> → check existing
    7.    ├── No existing prop:
    8.    │   Win32AllocPoolZInit(0x28) → alloc CSwapChainProp (40 bytes)
    9.    │   init vtable (LegacyInputDispatcher::vftable+0x418+0x108)
    10.    │   CSwapChainProp::SetCompositionSurfaceObj
    11.    │   CWindowProp::SetProp → store on window
    12.    │   CreateVisRgnTracker(type=2) → tracker for DWM
    13.    └── Existing prop: update surface object
    Disassembly UserSetWindowedSwapChain (win32kfull!d66b6c68):
    Код (Text):
    1. pacibsp
    2. ...
    3. bl   EnterCrit
    4. bl   ValidateHwnd
    5. ...
    6. mov  w9,#-0xD001
    7. ldrh w8,[x8,#0x2A]           ; window style
    8. and  w8,w8,w9
    9. sub  w8,w8,#0x29D
    10. tst  w8,#0xFFFFFFFD          ; ★ style validation
    11. beq  error_exit
    12. bl   IsWindowBeingDestroyed
    13. cbnz w0,error_exit
    14. bl   IsWindowDesktopComposed
    15. ...
    16. ; --- Reference dxgkrnl composition object ---
    17. mov  w3,#1                   ; access mode
    18. mov  w2,#1
    19. mov  w1,#1
    20. mov  x0,x22                  ; handle
    21. bl   dxgkrnl!DxgkReferenceCompositionObject  ; ★ cross-module call
    22. ...
    23. ; --- Get or create CSwapChainProp ---
    24. bl   CWindowProp::GetProp<CSwapChainProp>
    25. ...
    26. cbnz x19,existing_prop       ; already exists → update
    27. ...
    28. ; --- Allocate new prop ---
    29. mov  x0,#0x28                ; 40 bytes
    30. bl   Win32AllocPoolZInit     ; alloc + zero
    31. ...
    32. ; --- Setup vtable and store ---
    33. ldr  x8,...vtable
    34. str  x8,[x19]                ; vtable
    35. stp  xzr,xzr,[x19,#8]
    36. stp  xzr,xzr,[x19,#0x18]    ; zero surface ptr
    37. bl   CSwapChainProp::SetCompositionSurfaceObj
    38. bl   CWindowProp::SetProp    ; ★ attach to window
    39. ...
    40. bl   CreateVisRgnTracker     ; ★ create DWM tracker
    CApplicationChannel::Commit — основной метод коммита:
    Код (Text):
    1. 1. Increment commit counter at [channel+0x198]
    2. 2. CMilCommandBatchParser::ValidateAndTranslateHandles (MIL batch handle translation)
    3.    └── CET check via KscpCfgCheckUserCallTargetEs
    4. 3. NotifyCommitMustBeLastForFrame (if flagged)
    5. 4. Collect batch data from [channel+0xB0] → store in pending list
    6. 5. BuildNinjaBatch:
    7.    ├── Input: pending batch + sync object
    8.    └── Output: built CMilProtocolBlock
    9. 6. SubmitBatch → send to DWM (see below)
    Disassembly CApplicationChannel::Commit (win32kbase!d6233e40):
    Код (Text):
    1. pacibsp
    2. ...
    3. mov  x19,x0                  ; this (CApplicationChannel)
    4. ldr  w26,[x19,#0x198]        ; commit counter
    5. ...
    6. add  w21,w26,#1              ; increment
    7. str  w21,[x19,#0x198]        ; store new counter
    8. ...
    9. ; === Handle validation ===
    10. ldrb w8,[x19,#0x109]         ; channel flags
    11. tbnz w8,#2,validate_handles
    12. ...
    13. validate_handles:
    14. add  x0,sp,#0x58
    15. bl   CMilCommandBatchParser::ValidateAndTranslateHandles
    16. ...
    17. ; === Notify frame ===
    18. ldrb w8,[sp,#0x10]           ; mustBeLastForFrame flag
    19. cbz  w8,check_batch
    20. mov  w1,#1
    21. mov  x0,x19
    22. bl   NotifyCommitMustBeLastForFrame
    23. ...
    24. ; === Build batch ===
    25. mov  w3,w26                  ; commit id
    26. add  x2,sp,#0x20
    27. add  x1,sp,#0x18
    28. mov  x0,x19
    29. bl   BuildNinjaBatch         ; ★ build MIL command batch
    30. ...
    31. ; === Submit batch ===
    32. ldr  x2,[sp,#0x20]           ; batch data
    33. mov  x0,x19                  ; channel
    34. and  w3,w8,#1                ; flags
    35. bl   SubmitBatch              ; ★ submit to DWM
    SubmitBatch — отправка batch в DWM:
    Код (Text):
    1. 1. Optional: KeQueryPerformanceCounter for profiling
    2. 2. KeEnterCriticalRegion
    3. 3. ExAcquireResourceSharedLite (channel lock at [channel+0x28]+0x10)
    4. 4. Check pending count > 0 at [channel+0x18]
    5. 5. Acquire connection resource lock
    6. 6. Check connection active flag at [conn+0x94]
    7. 7. ExpInterlockedPushEntrySList → push batch to SLIST at [conn+0x60]
    8.    (lock-free producer-consumer queue)
    9. 8. KeSetEvent → signal DWM via event at [conn+0x58]+8
    Disassembly SubmitBatch (win32kbase!d623b040):
    Код (Text):
    1. pacibsp
    2. ...
    3. mov  x20,x0                  ; this (CApplicationChannel)
    4. mov  x19,x1                  ; batch object
    5. mov  x23,x2                  ; batch data
    6. uxtb w8,w3                   ; profiling flag
    7. mov  x21,x4                  ; sync object
    8. ...
    9. ; === Acquire channel lock ===
    10. bl   nt!KeEnterCriticalRegion
    11. ldr  x0,[x8,...]             ; ERESOURCE at channel+0x28+0x10
    12. mov  w1,#1                   ; shared
    13. bl   nt!ExAcquireResourceSharedLite
    14. ...
    15. ; === Acquire connection lock ===
    16. ldr  x22,[x8,#0x10]          ; connection resource
    17. bl   nt!KeEnterCriticalRegion
    18. ldr  x0,[x8,...]
    19. bl   nt!ExAcquireResourceSharedLite
    20. ldr  w22,[x21,#0x94]         ; ★ connection active flag
    21. ...
    22. ; === Push to SLIST (lock-free!) ===
    23. mov  x1,x19                  ; batch entry
    24. add  x0,x21,#0x60            ; SLIST head at conn+0x60
    25. bl   nt!ExpInterlockedPushEntrySList  ; ★ atomic push
    26. ...
    27. ; === Signal DWM ===
    28. ldr  x8,[x21,#0x58]          ; event object
    29. mov  w2,#0
    30. mov  w1,#1                   ; increment
    31. ldr  x0,[x8,#8]              ; KEVENT
    32. bl   nt!KeSetEvent           ; ★ wake DWM thread
    Ключевое: Коммуникация с DWM — это lock-free SLIST (interlocked singly-linked list) + KeSetEvent. App проталкивает batch через SLIST, DWM просыпается по событию и забирает. Никаких LPC здесь — это быстрый путь. LPC используется для window composition нотификаций.
    NtCreateCompositionSurfaceHandle — syscall создания GPU composition surface:
    Код (Text):
    1. KeEnterCriticalRegion
    2. ObCreateObject(0xD8 bytes) → CompositionSurfaceObject
    3.   PsGetCurrentProcess → PsGetProcessSessionId → store at [obj+8]
    4.   ZwAllocateLocallyUniqueId → LUID at [obj+0x18]
    5.   CompositionSurfaceObject::ObjectInit(obj+0x10)
    6. ObInsertObject → return handle
    Disassembly (dxgkrnl!d2193f10):
    Код (Text):
    1. pacibsp
    2. ...
    3. mov  x19,x0                  ; OBJECT_ATTRIBUTES
    4. mov  w21,w1                  ; desired access
    5. mov  x20,x2                  ; output handle ptr
    6. ...
    7. bl   nt!KeEnterCriticalRegion
    8. ...
    9. mov  w7,#0                   ; Unknown
    10. mov  w6,#0                   ; Unknown
    11. mov  w5,#0xD8                ; ★ object body size = 0xD8 bytes (GPU surface)
    12. mov  x4,#0                   ; no ParseContext
    13. mov  w3,#1                   ; ObjectBody present
    14. mov  x2,x19                  ; OBJECT_ATTRIBUTES
    15. ldr  x1,[...ObjectType]      ; CompositionSurfaceObjectType
    16. mov  w0,#1                   ; alloc type
    17. bl   nt!ObCreateObject       ; ★ create GPU composition surface object
    18. ...
    19. bl   nt!PsGetCurrentProcess
    20. bl   nt!PsGetProcessSessionId
    21. str  w0,[x8,#8]              ; store SessionId
    22. ...
    23. add  x0,x8,#0x18             ; LUID buffer
    24. bl   nt!ZwAllocateLocallyUniqueId  ; ★ assign unique ID
    25. ...
    26. add  x2,x0,#0x10
    27. mov  x1,#0
    28. bl   CompositionSurfaceObject::ObjectInit  ; ★ init GPU surface
    29. ...
    30. bl   nt!ObInsertObject       ; ★ insert, get handle
    CompositionSurfaceObject::Create — альтернативный путь:
    Код (Text):
    1. Тот же паттерн: ObCreateObject → session ID → LUID → ObjectInit → ObInsertObject
    2. Размер объекта: 0xD8 bytes
    3. ObjectInit: stores allocation attributes, initializes GPU-side resources
    NtBindCompositionSurface — привязка surface к GPU:
    Код (Text):
    1. 1. Copy 0x520 bytes from user buffer (bind parameters) via RtlCopyFromUser
    2. 2. KeEnterCriticalRegion
    3. 3. DxgkGetWin32kImportTable → virtual call for win32k validation
    4. 4. DxgkGetSessionTokenManager → get session token
    5. 5. Virtual dispatch on token object (vtable+0x20) for validation
    6. 6. GPU driver DDI calls to bind the surface to hardware
    Disassembly NtBindCompositionSurface (dxgkrnl!d2193c20):
    Код (Text):
    1. pacibsp
    2. ...
    3. mov  x23,x0                  ; composition surface handle
    4. str  w1,[x26,#0x20]          ; bind flags
    5. stp  w1,w2,[x26,#4]          ; store params
    6. ...
    7. ; === Copy bind params from user mode ===
    8. mov  x2,#0x520               ; ★ 0x520 bytes of bind parameters
    9. mov  w1,#0
    10. bl   _memset_spec_unaligned_zva  ; zero local buffer
    11. mov  x2,#0x520
    12. mov  x1,x21                  ; user buffer
    13. bl   RtlCopyFromUser         ; ★ copy from user space
    14. ...
    15. ; === Cross-module validation ===
    16. bl   DxgkGetWin32kImportTable ; get win32k function table
    17. ldr  x8,[x0,#0x260]          ; validation function
    18. mov  x15,x8
    19. bl   nt!KscpCfgCheckUserCallTargetEs  ; CET check
    20. blr  x15                     ; ★ virtual call to win32k validator
    21. ...
    22. bl   DxgkGetSessionTokenManager  ; get token manager
    23. ...
    24. ldr  x8,[x20]                ; vtable
    25. ldr  x8,[x8,#0x20]           ; validate method
    26. mov  x15,x8
    27. bl   nt!KscpCfgCheckUserCallTargetEs
    28. blr  x15                     ; ★ token validation
    CConnection::GetDefaultConnection:
    Код (Text):
    1. Path 1: [current_process_win32k+0x100] → per-process connection
    2. Path 2: W32GetDCompSessionState+0x10 → session global connection
    3. Both guarded by ExAcquireResourceExclusiveLite + atomic ldaddal refcount
    Disassembly GetDefaultConnection (win32kbase!d6231470):
    Код (Text):
    1. ; === Path 1: per-process ===
    2. ldr  x8,[...offset_0x100]    ; per-process connection ptr
    3. cbz  x8,path2                ; null → try session path
    4. ...
    5. ldaddal w9,w8,[x8+refcount]  ; ★ atomic increment refcount
    6. ...
    7. ret
    8. ; === Path 2: session global ===
    9. path2:
    10. bl   W32GetDCompSessionState
    11. ldr  x8,[x0,#0x10]           ; session connection
    12. cbz  x8,return_null
    13. ...
    14. ldaddal w9,w8,[x8+refcount]  ; ★ atomic increment refcount
    DCompositionSessionInitialize — при создании сессии:
    Код (Text):
    1. CConnection::OnSessionCreation →
    2.   W32GetDCompSessionState →
    3.   alloc 0x218 bytes for CSynchronizationManager →
    4.   CSynchronizationManager::Initialize →
    5.   store at session_state+0x18
    Disassembly DCompositionSessionInitialize (win32kbase!d636da00):
    Код (Text):
    1. ...
    2. bl   CConnection::OnSessionCreation
    3. ...
    4. bl   W32GetDCompSessionState
    5. ...
    6. mov  x0,#0x218               ; ★ CSynchronizationManager size = 0x218 bytes
    7. bl   Win32AllocPoolZInit     ; allocate
    8. ...
    9. bl   CSynchronizationManager::Initialize
    10. str  x0,[session_state,#0x18] ; ★ store at offset 0x18
    DCompSession State Structure:
    Код (Text):
    1. offset 0x00: ??? (header)
    2. offset 0x08: ???
    3. offset 0x10: CConnection*          (session connection to DWM)
    4. offset 0x18: CSynchronizationManager*  (cross-process sync)
    5. offset 0x20: ERESOURCE              (resource lock)
    DCompositionDwmInitialize — DWM-side initialization:
    Код (Text):
    1. 1. GetDefaultConnection → CConnection
    2. 2. Acquire push lock at connection+0x150
    3. 3. Set flag at connection+0x158 (DWM initialized)
    4. 4. Optionally: EmitSetBlurredWallpaperSurface
    Disassembly (win32kbase!d636d630):
    Код (Text):
    1. ...
    2. bl   GetDefaultConnection    ; get session connection
    3. ...
    4. ; === Acquire push lock ===
    5. ldar w8,[x0,#0x158]          ; read DWM init flag
    6. cbnz w8,already_init         ; already initialized → skip
    7. ...
    8. ; acquire push lock at conn+0x150
    9. add  x1,sp,#0x8
    10. mov  w2,#1
    11. add  x0,x0,#0x150
    12. bl   RtlAcquirePushLockExclusive  ; ★ exclusive lock
    13. ...
    14. ; set flag
    15. str  w8,[x19,#0x158]         ; ★ mark DWM initialized
    16. ...
    17. bl   EmitSetBlurredWallpaperSurface  ; optional wallpaper surface
    Complete Data Flow Summary
    Код (Text):
    1. App calls DCompositionCreateDevice
    2.   → kernel: CompositionObject::Create (ObCreateObject + session+LUID)
    3.   → kernel: handle via ObOpenObjectByPointer
    4. App creates visual tree + sets target
    5.   → kernel: NtUserCreateDCompositionHwndTarget
    6.   → kernel: CHwndTargetProp (atom 0xA542) binds CompositionObject to HWND
    7.   → kernel: DWM notified via ApiSetEditionNotifyDwmForSystemVisualCreation
    8. App creates swap chain / surface
    9.   → kernel: NtCreateCompositionSurfaceHandle (dxgkrnl ObCreateObject 0xD8 bytes)
    10.   → kernel: NtBindCompositionSurface → GPU driver DDI
    11. App commits
    12.   → kernel: CApplicationChannel::Commit
    13.   → BuildNinjaBatch (MIL protocol commands)
    14.   → SubmitBatch → ExpInterlockedPushEntrySList → KeSetEvent
    15.   → DWM wakes, dequeues batch, processes visual tree
    16. Window changes
    17.   → ShouldComposeWindow (checks composed flag bit 4)
    18.   → ComposeWindowIfNeeded → ComposeWindow (layered window setup)
    19.   → LPC message to DWM via LpcRequestPort
    20. DWM composites
    21.   → Reads composition surface from dxgkrnl
    22.   → GPU renders visual tree
    23.   → Presents via CompositionSurfaceObject → independent flip
    Security Model
    • Process ownership:
      Код (Text):
      1. PsGetCurrentProcess == IoThreadToProcess(thread)
      — только процесс-владелец окна может создать composition target
    • Session isolation: SessionId записывается в каждый CompositionObject и CompositionSurfaceObject
    • Handle-based access: Все операции идут через NT object manager handles
    • CET/PAC: Все indirect calls защищены
      Код (Text):
      1. KscpCfgCheckUserCallTargetEs
      + ARM64 PAC (pacibsp/autibsp)
    Key Syscalls Map
    SyscallModulePurpose
    NtUserCreateDCompositionHwndTargetwin32kfullCreate composition target for HWND
    NtUserDestroyDCompositionHwndTargetwin32kfullDestroy composition target
    NtUserGetDCompositionHwndBitmapwin32kfullGet composition bitmap
    NtUserGetResizeDCompositionSynchronizationObjectwin32kfullResize sync object
    NtCreateCompositionSurfaceHandledxgkrnlCreate GPU composition surface
    NtBindCompositionSurfacedxgkrnlBind surface to GPU
    NtUnBindCompositionSurfacedxgkrnlUnbind surface
    NtNotifyPresentToCompositionSurfacedxgkrnlPresent frame
    NtQueryCompositionSurfaceStatisticsdxgkrnlQuery surface stats
    CompositionObject (win32kbase, 0xB0 bytes):
    Код (Text):
    1. +0x00: vtable / type info
    2. +0x08: ULONG SessionId
    3. +0x10: LUID  (Locally Unique ID)
    4. +0x18: ... (object body)
    CompositionSurfaceObject (dxgkrnl, 0xD8 bytes):
    Код (Text):
    1. +0x00: vtable / type info
    2. +0x08: ULONG SessionId
    3. +0x10: ObjectInit data
    4. +0x18: LUID (Locally Unique ID)
    CHwndTargetProp (stored via window property atom 0xA542):
    Код (Text):
    1. +0x00: vtable
    2. +0x08: ???
    3. +0x10: ???
    4. +0x18: CompositionObject*  (per-slot, indexed by target type)
    CSwapChainProp (stored via window property, 0x28 bytes):
    Код (Text):
    1. +0x00: vtable
    2. +0x08: ???
    3. +0x10: ???
    4. +0x18: CompositionSurfaceObject*  (GPU surface pointer)
    5. +0x20: ULONG flags
    CApplicationChannel:
    Код (Text):
    1. +0x00: vtable
    2. +0x18: pending batch count (atomic)
    3. +0x28: CConnection* (back-ptr to session connection)
    4. +0x30: flags byte
    5. +0x109: channel flags (validation required etc.)
    6. +0x188: CCriticalSection (batch submission lock)
    7. +0x198: ULONG commit counter
    8. +0x1D0: pre-commit callback list
    9. +0x1D8: post-commit callback list
    CConnection:
    Код (Text):
    1. +0x10: ERESOURCE (resource lock)
    2. +0x58: KEVENT* (DWM wake event, obj at [+8])
    3. +0x60: SLIST_HEADER (batch queue head)
    4. +0x94: ULONG active flag
    5. +0x150: push lock (DWM init)
    6. +0x158: ULONG DWM initialized flag
    Overlay Implications
    Для оверлеев DirectComposition дает:
    • Hardware-accelerated composition через DWM — каждый визуал — отдельный CompositionObject с собственным GPU surface
    • Independent flip — CompositionSurfaceObject позволяет GPU page flipping без GDI
    • Visual tree — parent-child отношения между визуалами, трансформации, clip regions — всё обрабатывается DWM на GPU
    • Cross-process safe — DWM процесс делает финальный composite, изолируя app от screen pixels
    • No GDI dependency — полностью минует GDI/rendering pipeline
    Исследование проведено через live kernel debugging на Windows ARM64 (Parallels Desktop VM) с использованием WinDbg MCP agent (windbg_agent.dll). Все адреса и размеры структур актуальны для данного билда Windows.