Hunting Windows Desktop Window Manager Bugs
Zhang WangJunjie (Security Researcher · Hillstone Networks), YiSheng He (Hillstone Networks), Wenyue Li (Senior Security Researcher · Hillstone Networks)
HITBSecConf2023 - Amsterdam · Day 1 · Track 1
Overview
This talk, "Hunting Windows Desktop Window Manager Bugs," presented by Zhang WangJunjie, Wenyue Li, and YiSheng He from Hillstone Networks, delves into the vast and often overlooked attack surface within the Windows Desktop Window Manager (DWM) and its underlying DirectComposition user-mode component. The speakers provide a comprehensive analysis of the DWM architecture, the interaction between user-mode applications and the kernel, and the types of vulnerabilities that can arise from this complex interplay.

Key moments
- 2:00 DirectComposition architecture and DWM components
- 3:00 DWM command submission via kernel syscalls
- 20:00 DWM's large attack surface and fuzzing methodology
- 28:00 CVE-2022-2196: Shared memory arbitrary address access
- 34:00 Type confusion leading to out-of-bounds write
- 38:00 Use-After-Free in DWM's publisher/subscriber model
- 42:00 Heap buffer overflow and future DWM research
Hunting Windows Desktop Window Manager Bugs
Speakers: Zhang WangJunjie (Security Researcher, Hillstone Networks); YiSheng He (Hillstone Networks); Wenyue Li (Senior Security Researcher, Hillstone Networks)
Conference: HITB Amsterdam
YouTube: https://www.youtube.com/watch?v=4_ExouTXe10
Overview
This talk, "Hunting Windows Desktop Window Manager Bugs," presented by Zhang WangJunjie, Wenyue Li, and YiSheng He from Hillstone Networks, delves into the vast and often overlooked attack surface within the Windows Desktop Window Manager (DWM) and its underlying DirectComposition user-mode component. The speakers provide a comprehensive analysis of the DWM architecture, the interaction between user-mode applications and the kernel, and the types of vulnerabilities that can arise from this complex interplay.
The research highlights DWM's critical role in rendering the Windows user interface and its elevated privileges, running at the System Integrity Level. This makes DWM a prime target for privilege escalation attacks, particularly from sandboxed, low-privileged processes like those found in app containers. The presentation details several novel vulnerabilities discovered through both fuzzing and code auditing, including arbitrary address dereferences, out-of-bounds accesses, type confusions, use-after-frees (UAFs), and heap buffer overflows. The insights shared are crucial for security researchers and defenders seeking to understand and mitigate risks within core Windows display components.
Background
▶ Watch: DirectComposition architecture and DWM components (2:00)
DirectComposition is a fundamental Windows component designed to enable high-performance bitmap composition, facilitating rich visual effects, animations, and transitions within the user interface. Developers leverage the DirectComposition API to create dynamic and visually engaging applications. The architecture is split into two primary domains: user-mode and kernel-mode.
In user-mode, applications interact with the DirectComposition API, which in turn calls Wing32kbase.sys via Wing32u.dll export functions. These kernel-mode system calls generate commands that are stored in a shared section of memory. The DWM process, running in user-mode, then retrieves and processes these commands, orchestrating the final rendering operations. The bulk of command processing within the DWM process is handled by DWM Core.dll. An ALPC port also exists to handle requests from the user in the kernel.
Key system calls that orchestrate this interaction include:
NTDCompositionCreateChannel: Initiates a channel, creating a kernel object handle and allocating a shared buffer for commands. The size of this shared section can be customized.NTDCompositionProcessChannelBatchBuffer: Used to create various commands, such as creating or releasing resource objects, setting reference objects, or modifying integer/floating-point attributes. These commands are stored in the previously mapped shared section.NTDCompositionCommitChannel: Submits all generated commands to the DWM process for execution.
Objects within DirectComposition, both in the kernel and DWM Core.dll, possess virtual tables with distinct functions, such as GetType and IsOfType for object verification, and SetReferenceProperty or SetIntegerProperty for attribute manipulation. A SetRemotionFlagObject function is particularly notable as it's invoked when the DWM process restarts, allowing the kernel to recalculate and restore the state of previously created objects, ensuring continuity after unexpected crashes. Object handles are managed through a handle table, which maps numerical handles to object pointers, simplifying subsequent command references.
Key Findings
▶ Watch: DWM's large attack surface and fuzzing methodology (20:00)
The research revealed that the DirectComposition component presents an exceptionally large and complex attack surface, making it ripe for vulnerability discovery. The speakers identified two primary areas of interest:
- Kernel-State Driver (win32kbase.sys): This module exposes a vast number of object internal functions. A direct search for "DirectComposition" in a function panel reveals approximately 2163 functions, indicating an extensive surface area for potential kernel-mode vulnerabilities.
- User-Mode DWM Process (DWM Core.dll): The DWM process includes a large switch-case branch within
CComposition::ProcessChannelBatchBufferthat dispatches commands. In the Windows 21H1 version, there are roughly 0x282 distinct commands, leading to nearly 700 branch functions responsible for processing these commands. Each of these branches represents a potential point of failure or security flaw.
Crucially, the DWM process operates at the System Integrity Level. This elevated privilege status means that vulnerabilities found within DWM can be exploited by low-privileged, sandboxed processes (e.g., those running in an App Container) to achieve privilege escalation. The system calls involved in DWM interaction are often not filtered by sandboxes, allowing attackers to directly target DWM.
The team employed a fuzzing approach, modifying the open-source ciscollar tool (similar to syzkaller) to target DirectComposition. Their fuzzer focused on collecting code coverage for the win32kbase kernel driver. By adding NTDCompositionCommitChannel at the end of each generated program, they ensured commands were submitted to DWM, allowing them to monitor for DWM process crashes. Despite the fuzzer's relative simplicity (lacking DWM user-mode coverage collection), it successfully uncovered several vulnerabilities, including a surprising type confusion issue. The talk detailed five distinct vulnerabilities, highlighting the effectiveness of their methodology.
Technical Deep Dive
▶ Watch: CVE-2022-2196: Shared memory arbitrary address access (28:00)
The speakers detailed several critical vulnerabilities, demonstrating common pitfalls in complex component development:
1. Arbitrary Address Dereference / Use-After-Free (CVE-2022-2196)
This vulnerability stems from DWM Core.dll's handling of data from shared memory. The process involves:
- Shared Memory Acquisition: DWM Core.dll obtains a pointer to shared memory via
NTDCompositionCreateAndBindSharedSection. This syscall creates a kernel section object usingZWCreateSection, attaches it to the DWM process, and allocates a handle. DWM Core then usesCSharedSection::ResolveAllocationto get the actual shared memory address. - Lack of Validation: The pointer obtained from shared memory is used without any validation. It's directly copied into an object, and its reference count is incremented.
- Race Condition: A critical problem arises because DWM Core.dll clears the shared memory content using
memsetafter obtaining the address. If a large shared memory region is created (e.g., 0x2000 bytes), thememsetoperation takes longer. This extended execution window allows for a race condition. - Exploitation: An attacker can create a large shared memory section. Simultaneously, a separate thread can repeatedly write a malicious data pointer (e.g., an invalid address) into this shared memory after DWM has obtained its address but before the
memsetcompletes. WhenNTDCompositionCommitChannelis called, the DWM process will eventually attempt to dereference this invalid pointer, leading to an arbitrary address violation and a crash in the object's destructor function (ReadValueFromCache).
2. Out-of-Bounds Access in Keyframe Data Processing
This vulnerability also resides in shared memory handling, specifically within the CComposition::ProcessSetKeyframeData function.
- Unchecked Index: The function directly extracts an object index from the shared memory.
- Direct Object Access: Without any bounds checks on this index, DWM then directly retrieves an object from an array using this potentially malicious index.
- Reference Count Increment: The reference count of the retrieved (potentially out-of-bounds) object is then incremented.
- Impact: This leads to an out-of-bounds read or write access, causing a process crash. The crash stack shows the issue occurring after
CComposition::ProcessSetKeyframeDatais invoked, with the buffer index entirely controllable by the attacker.
3. Type Confusion (CResourceTable::GetResourceWithoutType)
This is a significant vulnerability arising from insufficient type validation.
- Two Resource Retrieval Functions: DWM Core.dll has two primary functions for obtaining resource objects:
CResourceTable::GetResourceandCResourceTable::GetResourceWithoutType. - Lack of Type Checking:
GetResourceperforms type validation (checking if the object type matches a specified parameter), returning zero if types differ. However,GetResourceWithoutTypedoes not perform any type checks. - Exploitation: If
IsOfTypeis not called immediately afterGetResourceWithoutTypeto manually verify the object's type, a type confusion can occur. The talk demonstrated a scenario where aCBaseExpressionobject is mistakenly treated as aCManipulationobject. This leads to DWM creating a weak reference pointer to the unchecked object, setting it to an expression object, and releasing the old object. This process can be repeated. - Arbitrary Write: The confused object is eventually passed to
CScene::InjectManipulation, which still does not check the object type. DWM then attempts to write controllable values at specific offsets (e.g., 0x256, 0x268, and 0x300) within this object. If the actual size of the confused object is less than these offsets, it results in an out-of-bounds write, allowing an attacker to overwrite data in adjacent memory regions (e.g., overwriting a pointer with0x41414141), leading to a DWM process crash.
4. Use-After-Free (UAF) in CProxyGeometry::ProcessSetViewbox
This UAF vulnerability is related to the publisher-subscriber model supported by DWM.
- Unchecked Registration: The
CProxyGeometry::ProcessSetViewboxfunction usesGetResourceWithoutTypeto obtain aCViewboxobject provided by the user and registers it as a subscriber toCProxyGeometry. Critically, this function lacks re-entry detection, allowing multipleCViewboxobjects to be registered as subscribers. - Publisher/Subscriber Model: When a property of the
CProxyGeometryobject changes, it notifies all its registered subscriberCViewboxobjects by calling theirEndNotificationOnChangefunction. - Exploitation Steps:
- Create
CProxyGeometryand an initialCViewboxobject, binding them. Commit viaNTDCompositionCommitChannel. - Loop: Create a large number of additional
CViewboxobjects (e.g., 0x1000), binding them all to theCProxyGeometryobject. Commit channel. This registers manyCViewboxobjects as subscribers. - Release the
CViewboxobjects created by the kernel. These objects are now freed. - Create a new
CViewboxobject and bind it toCProxyGeometry. Commit channel. - When
ProcessSetViewboxis called, it attempts to notify all previously registeredCViewboxobjects, including those that have been freed in step 3. This triggers a Use-After-Free.
- Heap Spray for Control: To gain control over the freed memory, the
CInteractionTracker::ProcessSetInteractionModifierAnimationfunction can be used. This function allows allocating arbitrary-sized memory with fully controlled content, enabling an attacker to occupy the freedCViewboxobjects and control the UAF primitive.
5. Heap Buffer Overflow in CInjectionAnimation::ProcessSetInjectionData
This vulnerability is a classic heap buffer overflow due to an allocation/copy size mismatch.
- Size Calculation Mismatch: In
CInjectionAnimation::ProcessSetInjectionData, the function calculates ablock_sizebased on a user-providedbuffer_size. It then allocates memory usingblock_size * 0x84. However, when copying data from the shared memory to this newly allocated buffer usingmemcpy, it uses the originalbuffer_size. - Vulnerable Scenario: If the
buffer_sizeprovided by the user is not a multiple of0x84(e.g., 0x83 bytes), theblock_sizecalculation can result in a smaller-than-expected allocation, or even a zero-sized allocation (ifbuffer_size<0x84,block_sizemight be 0). - Exploitation: For example, if
buffer_sizeis0x83,block_sizemight be calculated as0. This would lead to a 0-byte allocation. However,memcpystill attempts to copy0x83bytes, resulting in a heap buffer overflow. - Impact: An attacker can provide a
buffer_sizeof0x83and set the content of the shared memory to controlled data (e.g.,0x41414141). This will overwrite a pointer in an adjacent object, causing a DWM process crash and providing a strong primitive for exploitation.
Demo / Proof of Concept
▶ Watch: Use-After-Free in DWM's publisher/subscriber model (38:00)
While the talk did not feature a live demo, the speakers meticulously walked through the Proof of Concept (POC) steps for several of the identified vulnerabilities, particularly the Heap Buffer Overflow and the UAF issue.
For the Heap Buffer Overflow (CInjectionAnimation::ProcessSetInjectionData), the POC involved:
- Creating
CInjectionAnimationandCSharedSectionMarshallobjects. - Establishing shared memory between them, filling it with controlled data (e.g.,
0x41414141). - Sending a
SetIntegerPropertycommand to set the buffer size to0x83. - Sending a
SetReferencePropertycommand to bind the shared section to theCInjectionAnimationobject. - Calling
NTDCompositionCommitChannelto submit the commands, leading to a visible DWM process crash with the overwritten pointer.
The speakers noted that the object types and property values might differ across Windows versions (e.g., the POC was based on Windows 11 21H2), requiring adaptation for other environments. The detailed steps provided for the UAF (creating 0x1000 objects, releasing, then re-triggering) and Type Confusion (forcing CBaseExpression to be treated as CManipulation) also serve as comprehensive POC descriptions, outlining the precise sequence of NTDComposition syscalls required to trigger each bug.
Defensive Implications
▶ Watch: Heap buffer overflow and future DWM research (42:00)
The findings presented in this talk offer several critical defensive implications for both developers and security practitioners:
- Strict Input Validation: Developers of components interacting with shared memory must implement rigorous validation for all data read from these regions, especially pointers, sizes, and indices. Assumptions about data integrity from shared sections are dangerous.
- Robust Type Checking: The prevalence of type confusion issues, particularly when using functions like
GetResourceWithoutType, underscores the need for explicit type validation immediately after object retrieval. Every object should be verified against its expected type before any operations are performed. - Careful Reference Counting and Object Lifecycle Management: Vulnerabilities like UAF highlight the importance of correct reference counting and ensuring objects are not accessed after they have been freed. Mechanisms for re-entry detection in object registration processes are crucial to prevent double-frees or UAFs.
- Secure Memory Allocation and Copying: The heap buffer overflow demonstrates the classic danger of mismatched allocation and copy sizes. Developers must meticulously ensure that
memcpyoperations do not exceed the bounds of allocated buffers, especially when sizes are derived from user input or complex calculations. - Regular Patching and Updates: For end-users and system administrators, the most direct defense is to keep Windows operating systems fully updated. Patches for these types of vulnerabilities are regularly released by Microsoft and are essential to mitigate known attack vectors.
- Enhanced Sandbox Filtering: While DWM interaction is often unfiltered, security architects should consider if additional filtering or stricter policies could be applied to DWM-related system calls from low-privileged processes, potentially reducing the attack surface for privilege escalation.
- Continued Research and Auditing: The DWM component remains a large and active area of development, with new features constantly being added. The speakers explicitly mentioned that the ALPC processing code within DWM has not been fully reviewed, indicating further attack surface. Continuous security auditing and fuzzing efforts are necessary to uncover new vulnerabilities.
Key Takeaways
- The Windows Desktop Window Manager (DWM) and its DirectComposition component represent a massive and complex attack surface, encompassing both kernel-mode (win32kbase.sys with ~2163 functions) and user-mode (DWM Core.dll with ~700 command processing branches) code.
- DWM runs at the System Integrity Level, making it a high-value target for privilege escalation from low-privileged sandboxed processes, as its interaction syscalls are often unfiltered.
- Shared memory handling is a common source of critical vulnerabilities, including arbitrary address dereferences, race conditions, and out-of-bounds accesses, due to insufficient validation and synchronization.
- Lack of strict type validation, particularly with functions like
CResourceTable::GetResourceWithoutType, directly leads to severe type confusion vulnerabilities that can be leveraged for arbitrary memory writes and process crashes. - Improper object lifecycle management, including issues with reference counting and re-entry detection during object registration, is a root cause for Use-After-Free (UAF) vulnerabilities.
- Even relatively simple fuzzing techniques, such as modifying
ciscollarto targetwin32kbaseand monitor DWM crashes, can be highly effective in uncovering significant vulnerabilities in complex, continuously updated components like DWM.
About the Speaker(s)
Zhang WangJunjie is a Security Researcher at Hillstone Networks. His primary research focus is Windows vulnerability research, covering both user-mode and kernel-mode components. He has been recognized as a Microsoft Most Valuable Security Researcher (MVS) in both 2020 and 2022.
Wenyue Li is a Senior Security Researcher at Hillstone Networks. His expertise lies in mobile security, operating system vulnerabilities, and Advanced Persistent Threat (APT) analysis.
YiSheng He is the leader of the security team at Hillstone Networks. His main research areas include AIoT and web security. He is also an enthusiastic participant in CTF (Capture The Flag) competitions. Unfortunately, he was unable to attend the conference in person.
Reviews
Dr. Zero (Offensive Security Researcher) — STRONG ACCEPT
Solid bug-hunting talk that delivers five real vulnerabilities in DWM/DirectComposition with clear root-cause analysis. Not groundbreaking technique-wise—race conditions, type confusion, UAFs are familiar primitives—but the target selection is smart and the attack surface enumeration alone is useful. Good craft, not revolutionary.
Heather Calloway (CISO) — SOLID
Competent Windows internals research that documents real privilege escalation paths from sandboxed processes via DWM. The five CVEs are legitimate, but this is specialized offensive research—useful for teams with Windows kernel visibility, not a strategic priority for most security programs.