
Detailed technical analysis and proof-of-concept exploit for CVE-2024-30051, a heap-based buffer overflow in the Windows DWM Core Library enabling local privilege escalation to Integrity System level.
In this blog post, I will explain a vulnerability in the Microsoft Windows DWM Core library that I analyzed when the exploit for Core Impact was being developed. Allows an unprivileged attacker to execute code as a DWM user with Integrity System privileges (CVE-2024-30051).
Since there were not enough public information at the time to develop the exploit, I had to reverse a lot, so here I will show how to reverse the KB5037771 patch for Windows 23H2 using IDA PRO, I will use BINDIFF to perform binary diffing between dwmcore.dll version 10.0.22621.3447 and version 10.0.22621.3593, will show how the heap overflow is produced, and then will exploit it by elevating privileges, finally will create a functional PoC.
Index:
[Windows DWM Core Library Elevation of Privilege Vulnerability (CVE-2024-30051) 1](#windows-dwm-core-library-elevation-of-privilege-vulnerability-cve-2024-30051)
[Vulnerability details: 2](#vulnerability-details)
[Diffing to find the bug: 3](#diffing-to-find-the-bug)
[Analysis of the PoC exploiting CVE-2024-30051: 8](#analysis-of-the-poc-exploiting-cve-2024-30051)
[1)Initialization 8](#initialization)
[2)Hooking 8](#hooking)
[3)Creating the window 16](#creating-the-window)
[4)Create Device 16](#create-device)
[5) Create Factory 22](#create-factory)
[6) Create Device Context 28](#create-a-device-context)
[7)Create Composition Device 29](#create-a-composition-device)
[8)Calling hook3 function 31](#calling-dcompositioncreatedevice-function)
[9)Creating target for HWND 32](#creating-a-target-for-handle-hwnd)
[10)Creating Surface 33](#creating-surface)
[11)Calling BeginDraw, EndDraw, and CreateVisual. 34](#calling-begindraw-enddraw-and-createvisual)
[11)Calling Visual SetContent 36](#calling-visual-setcontent)
[12)Release objects 38](#release-objects)
[13)Commit Composition Device 38](#commit-composition-device)
[14)Calling hook2 39](#calling-hook2)
[15)Calling hook 39](#remember-that-the-vulnerable-function-can-be-reached-using-some-methods-of-the-cprimitivegroup-class.-at-this-point-it-creates-a-heap-then-hook2-captures-and-saves-the-corresponding-heaphandle.)
[16)Calling hook4 41](#calling-the-function-hook4)
[17)Performing Heap Spray 49](#performing-heap-spray)
[18)Modifying the base chunk previous to send. 51](#modifying-the-base-chunk-before-send)
[19)Debugging the process DWM 52](#debugging-the-dwm-process)
[20)Elevating Privileges to Integrity System level 62](#elevating-privileges-to-integrity-system-level)
Windows DWM Core Library Elevation of Privilege Vulnerability CVE-2024-30051
Released: May 14, 2024
Assigning CNA: Microsoft CVE-2024-30051
Impact: Elevation of Privilege
Max Severity: Important
Weakness:
CWE-122: Heap-based Buffer Overflow
CVSS: 3.1 7.8 / 7.2
The vulnerability exists due to a size miscalculation error in an integer division within the main Windows DWM library called dwmcore.dll. A local user can cause a buffer overflow on the heap in the CCommandBuffer::Initialize method in dwmcore.dll and can execute arbitrary code with the DWM user with Integrity System Privileges. The exploit will perform a Heap Spray in the DWM process to prepare the memory and finally produces a Heap Overflow in dwmcore.dll which will be triggered by releasing certain parts of the heap spray.
Once the exploit is successful, the DWM process will load our crafted DLL that executes our code or our executable (in our case a CMD) as the DWM user which has Integrity System Privileges.

Let’s walk through this vulnerability and see how it allows us to run as a DWM user with Integrity Level SYSTEM. Note that since this is not a user belonging to the Administrator group it has some privilege restrictions.
The patch for Windows 11 23H2 can be downloaded from:
https://www.catalog.update.microsoft.com/Search.aspx?q=KB5037771
windows11.0-kb5037771-x64_19a3f100fb8437d059d7ee2b879fe8e48a1bae42.msu
The vulnerable version of dwmcore.dll is: 10.0.22621.3447
The patched version of dwmcore.dll is: 10.0.22621.3593
Analyzing the changed functions, it’s clear the patched version of CCommandBuffer::Initialize has a lot of blocks added, making it look quite different to the unpatched version.

After statically reversing that function, there are two calls to CD2DSharedBuffer::GetBufferSize.
The first call gets the size to allocate in the new and the second call gets the same size for the memcpy.

Everything initially seems correct. However, before the allocation, it performs some operations with the size.

It gets buffer_size and buffer_size2 by calling the same CD2DSharedBuffer::GetBufferSize function, returning both the same value. But in the new it performs a pre-operation, an integer division of the buffer_size by 0x90 and then multiplying by 0x90, whereas in the memcpy it uses the returned buffer_size2 without operating on it.
With these operations, I found that the size finally used in the new and in the memcpy can be different.
buffer_size = buffer_size2 (sizes returned)
size_new= buffer_size/0x90 x 0x90
size_memcpy=buffer_size2
For example, if buffer_size is 0x91
buffer_size = buffer_size2=0x91
size_new= buffer_size/0x90 x 0x90 =0x90
size_memcpy= buffer_size2= 0x91
This example proves that there is a heap overflow. It’s copying more bytes than allocated, and the size is controllable.
For example, if buffer_size is 0x23f as they used in the POC.
buffer_size = buffer_size2=0x23F
size_new= buffer_size/0x90 x 0x90 =0x1b0
size_memcpy== buffer_size2=0x23f
With the vulnerable function analyzed, I wanted to see how to reach the vulnerable function CCommandBuffer::Initialize. This is where things start to get complicated.