# Patch diff to SYSTEM

Use-after-free in Windows DWM's CSynchronousSuperWetInk destructor skips RemoveSource when LookupMode is changed, leaving a dangling pointer that yields SYSTEM code execution.

- Payout: Research
- Severity: high
- Program: Windows DWM
- Credited: Joe Desimone
- Disclosed: 2026-03-06
- Write-up quality: 10/10
- Original: https://www.elastic.co/security-labs/blog/patch-diff-to-system
- Library page: https://bugbountylibrary.com/r/blog%3Aelastic-co-security-labs-blog-patch-diff-to-system
- Tags: domain:desktop impact:privesc impact:rce kind:research platform:threat-intel sev:high tech:windows technique:chained technique:incomplete-fix technique:source-review vuln:memory-corruption vuln:privilege-escalation

**Target:** dwmcore.dll (Desktop Window Manager) via DirectComposition batch buffer
**Root cause:** Destructor ~CSynchronousSuperWetInk only calls CSuperWetInkManager::RemoveSource when IsSuperWetCompatible() returns true; changing LookupMode from 2 to 0 before release makes it return false, so the object is freed while still referenced in localStrokesVector.
**Steps:**
1. Create D3D11 device with BGRA support and swap chain; init DirectComposition via `DCompositionCreateDevice`.
2. Query `IDCompositionInkTrailDevice` and call `CreateDelegatedInkTrailForSwapChain()` to allocate CSynchronousSuperWetInk (type 0xa8).
3. Inject batch buffer: `CMD_CREATE_RESOURCE` (0x02) type 0xa5 CSuperWetInkVisual; `CMD_SET_REFERENCE` (0x10) propId 0x34 to link ink source; `CMD_SET_PROPERTY` (0x0B) propId 10 LookupMode=2; link to handles 1/2.
4. Present frames and commit to register pointer in CSuperWetInkManager::localStrokesVector.
5. Inject `CMD_SET_PROPERTY` propId 10 to set LookupMode=0.
6. Disconnect refs via `CMD_SET_REFERENCE` refHandle=0 and release IDCompositionDelegatedInkTrail; destructor skips RemoveSource, leaving dangling pointer.
7. Spray 288-byte CRegionGeometry RECT buffer via `CMD_SET_BUFFER_PROPERTY` (0x0F) propId 5 with 18 RECTs to reclaim freed slot with fake vtable.
8. Present frames to trigger DirtyActiveInk dereference of dangling pointer → `[[spray]+0x50]` call.
9. Chain __fnINSTRING (KCT) → FixupCallbackPointers → CStdAsyncStubBuffer2_Disconnect → VirtualProtect RWX → shellcode WinExec.
**How found:** Patch-diffed January 2026 Patch Tuesday dwmcore.dll using Ghidra BSim vectors and Opus 4.5, which flagged ~CSynchronousSuperWetInk and IsSuperWetCompatible as heavily modified; reading the destructor revealed the conditional RemoveSource and the LookupMode gate.
**Exploitation:** Low-priv user triggers UAF via DirectComposition batch buffer commands; reclaims freed 0x120 allocation with a 288-byte RECT spray containing a fake vtable pointing at KCT[fnINSTRING]-0x50. __fnINSTRING's FixupCallbackPointers converts embedded relative offsets to absolute using the buffer base, eliminating the need for a heap leak. It dispatches CStdAsyncStubBuffer2_Disconnect, whose two vtable calls first invoke VirtualProtect to mark the spray page RWX (and update CFG bitmap), then jump to inline shellcode calling WinExec("cmd.exe"). Shellcode defuses the vtable and does `add rsp,0xB8` to return cleanly to DWM's composition loop. DWM runs at System integrity, yielding SYSTEM.
**Escalation:** DWM process runs as DWM user with System integrity; code execution inside DWM escalates from low-priv user to SYSTEM. A separate DWM-to-SYSTEM path was developed but withheld.
**Insight:** When a destructor's cleanup is gated on a mutable object field (LookupMode), look for a state transition between registration and destruction that flips the gate — here CMD_SET_PROPERTY to 0 before CMD_RELEASE_RESOURCE. Also: KCT entries in the PEB are CFG-valid and readable, and __fnINSTRING's FixupCallbackPointers gives a leakless relative-to-absolute primitive for fake vtables.
