# Root Cause Analysis — CVE-2024-30051

## Summary

| Field | Value |
|---|---|
| **CVE** | CVE-2024-30051 |
| **Binary** | dwmcore.dll (Desktop Window Manager Core Library) |
| **Component** | CCommandBuffer::Initialize — D2D shared buffer handling |
| **Bug Class** | Heap-Based Buffer Overflow (CWE-122) via Integer Division Truncation |
| **Impact** | Elevation of Privilege → SYSTEM Integrity |
| **CVSS 3.1** | 7.8 (AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H) |
| **Exploited ITW** | Yes (discovered April 2024 by Kaspersky, QiAnXin, others) |
| **Patch** | May 2024 Patch Tuesday (KB5037771 Win11 23H2) |

## Vulnerability Overview

A heap-based buffer overflow exists in `CCommandBuffer::Initialize` in dwmcore.dll
due to a size miscalculation caused by integer division truncation. The function
obtains a `buffer_size` from `CD2DSharedBuffer::GetBufferSize`, then:

1. Allocates memory using `(buffer_size / 0x90) * 0x90` — rounding DOWN
2. Copies data using the original `buffer_size` — WITHOUT rounding

When `buffer_size` is not a multiple of 0x90, the allocation is smaller than the
copy length, causing a heap overflow of up to 0x8F bytes with attacker-controlled
content. A local attacker can exploit this to achieve code execution as the DWM
user with SYSTEM integrity privileges.

## Root Cause — Integer Division Truncation

### The Vulnerable Code (pre-patch)

In `CCommandBuffer::Initialize`:

```c
// Both calls return the same value
ULONG buffer_size  = CD2DSharedBuffer::GetBufferSize(sharedBuf);
ULONG buffer_size2 = CD2DSharedBuffer::GetBufferSize(sharedBuf);

// Allocation: rounds DOWN to nearest 0x90 multiple
ULONG size_new = (buffer_size / 0x90) * 0x90;
PVOID dest = operator new(size_new);

// Copy: uses ORIGINAL size (not rounded)
memcpy(dest, src, buffer_size2);  // BUG: buffer_size2 > size_new
```

### The Math

| buffer_size | size_new = (buf/0x90)*0x90 | Overflow = buf - size_new |
|---|---|---|
| 0x90 | 0x90 | 0 (no overflow) |
| 0x91 | 0x90 | 1 byte |
| 0xFF | 0x90 | 0x6F bytes |
| 0x11F | 0x90 | 0x8F bytes |
| 0x120 | 0x120 | 0 (no overflow) |
| 0x23F | 0x1B0 | 0x8F bytes |

The maximum overflow per 0x90 block is **0x8F bytes** (143 bytes), occurring when
`buffer_size % 0x90 == 0x8F`.

### Call Flow to Reach the Vulnerable Function

```
User-mode application
  → D2D API interaction with DWM compositor
    → CPrimitiveGroup::Create / CPrimitiveGroup::CreatePrimitive
      → CCommandBuffer::Initialize *** VULNERABLE ***
        → CD2DSharedBuffer::GetBufferSize  → returns buffer_size
        → operator new((buffer_size / 0x90) * 0x90)  → UNDERSIZED ALLOCATION
        → memcpy(dest, src, buffer_size)  → HEAP OVERFLOW
```

### Attacker Control

The `buffer_size` is derived from a D2D shared buffer whose size the attacker
controls from user-mode. The content being copied (`src`) is also from the shared
buffer, giving the attacker full control over both the overflow length and data.

## Exploitation Path (ITW)

The in-the-wild exploit achieves EoP to SYSTEM integrity:

1. **Heap spray**: Allocate many D2D shared buffers in the DWM process to create
   predictable heap layout
2. **Setup adjacent objects**: Place exploitable kernel/DWM objects adjacent to the
   vulnerable allocation
3. **Trigger overflow**: Create a shared buffer with `size % 0x90 != 0` and trigger
   `CCommandBuffer::Initialize` — the memcpy overwrites adjacent heap objects
4. **Corrupt adjacent object**: Overwrite function pointers or metadata in the
   adjacent object to redirect execution
5. **Code execution**: DWM process loads attacker-crafted DLL from a controlled path,
   achieving code execution as DWM user with SYSTEM integrity

### Post-Exploitation

The DWM user has SYSTEM integrity level but is NOT in the Administrators group,
so some operations are restricted. However, SYSTEM integrity grants significant
privileges including access to most system resources.

## Patch Analysis

The patch in `CCommandBuffer::Initialize` (dwmcore.dll 10.0.22621.3593) adds:

```c
// Post-patch: use rounded size for BOTH allocation and copy
ULONG buffer_size = CD2DSharedBuffer::GetBufferSize(sharedBuf);
ULONG size_rounded = (buffer_size / 0x90) * 0x90;

// Validate size
if (size_rounded == 0 || size_rounded > MAX_ALLOWED) {
    return E_INVALIDARG;
}

PVOID dest = operator new(size_rounded);
memcpy(dest, src, size_rounded);  // FIXED: uses rounded size for copy too
```

The patched version adds significant validation blocks (visible in BinDiff as many
new basic blocks) to ensure the allocation size and copy size match.

## Reachability

- **Attack vector**: Local — requires code execution on the target
- **Privileges required**: Low — any user can interact with DWM
- **User interaction**: None
- **Attack surface**:
  - D2D API calls that interact with DWM shared buffers
  - Any application can trigger DWM compositor operations
  - DWM is always running on desktop Windows systems

## Detection

### YARA — Vulnerable dwmcore.dll

```yara
rule CVE_2024_30051_Vulnerable_DWMCore
{
    meta:
        description = "Detects pre-patch dwmcore.dll with size mismatch in CCommandBuffer::Initialize"
        cve         = "CVE-2024-30051"
        author      = "OnlyFm252"

    strings:
        $func = "CCommandBuffer::Initialize"
        $class = "CD2DSharedBuffer"

    condition:
        uint16(0) == 0x5A4D and
        filesize > 2MB and filesize < 10MB and
        $func and $class
}
```

### Sigma — DWM Process Crash or Suspicious DLL Load

```yaml
title: CVE-2024-30051 DWM Exploitation Indicators
id: f8a9b0c1-d2e3-4567-f012-345678abcdef
status: experimental
description: >
    Detects potential exploitation of CVE-2024-30051 via DWM process crash
    or suspicious DLL loading in dwm.exe context.
author: OnlyFm252
date: 2026/07/26
references:
    - https://www.coresecurity.com/core-labs/articles/windows-dwm-core-library-elevation-privilege-vulnerability-cve-2024-30051
    - https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-30051
logsource:
    product: windows
    category: image_load
detection:
    selection_dwm:
        Image|endswith: '\dwm.exe'
    filter_known:
        ImageLoaded|startswith:
            - 'C:\Windows\System32\'
            - 'C:\Windows\WinSxS\'
    condition: selection_dwm and not filter_known
level: high
tags:
    - attack.privilege_escalation
    - attack.t1068
    - cve.2024.30051
```

### Sysmon Configuration

```xml
<Sysmon schemaversion="4.90">
  <EventFiltering>
    <!-- Event 7: Detect non-system DLL loads in dwm.exe -->
    <ImageLoad onmatch="include">
      <Image condition="end with">\dwm.exe</Image>
    </ImageLoad>

    <!-- Event 1: Detect processes spawned by dwm.exe (post-exploit) -->
    <ProcessCreate onmatch="include">
      <ParentImage condition="end with">\dwm.exe</ParentImage>
    </ProcessCreate>

    <!-- Event 10: Detect process access to dwm.exe (heap spray injection) -->
    <ProcessAccess onmatch="include">
      <TargetImage condition="end with">\dwm.exe</TargetImage>
      <GrantedAccess condition="is">0x1F0FFF</GrantedAccess>
    </ProcessAccess>
  </EventFiltering>
</Sysmon>
```

## References

- [Core Security — Windows DWM Core Library EoP CVE-2024-30051](https://www.coresecurity.com/core-labs/articles/windows-dwm-core-library-elevation-privilege-vulnerability-cve-2024-30051)
- [Fortra — CVE-2024-30051 PoC](https://github.com/fortra/CVE-2024-30051)
- [MSRC Advisory — CVE-2024-30051](https://msrc.microsoft.com/update-guide/vulnerability/CVE-2024-30051)
- [Kaspersky — QakBot Targets DWM Zero-Day](https://securelist.com/cve-2024-30051/)
- [SnapAttack — Hunting CVE-2024-30051](https://blog.snapattack.com/hunting-cve-2024-30051)
