How an unchecked 32-bit integer addition in dwmcore.dll allowed local malware to trigger an undersized heap allocation, corrupt memory, and escalate to SYSTEM privileges.
Imagine a shipping company gives you a small box that holds 10 items because you told them 'I have 5 items plus 5 items'. But you cleverly pass numbers so big that the computer's simple addition wraps around back to zero—telling the computer '4 billion plus 10 items equals 10 items'. The computer prepares a tiny box, you shove in 4 billion items, and it spills all over the warehouse floor, letting you take control of the entire facility.
A low-privileged local malware process (e.g. QakBot dropper) initializes an IPC channel with the Desktop Window Manager.
The attacker crafts a direct composition drawing message where commandHeader.offset + commandHeader.length deliberately wraps past 0xFFFFFFFF.
The unpatched dwmcore.dll computes the wrapped sum, allocating a 64-byte heap chunk instead of several megabytes.
The message parser copies the entire payload into the tiny heap chunk, overwriting adjacent function pointers to achieve full system privileges.
Delivered in clean, readable high-level source code (no raw assembly or binary diffs).
// VULNERABLE: Decompiled C logic from dwmcore.dll before May 2024 patch
HRESULT CInteraction::ProcessInputArray(BYTE* pBuffer, ULONG offset, ULONG count) {
// CRITICAL ROOT CAUSE:
// Raw addition wraps around 32-bit integer boundaries!
// If offset = 0xFFFFFFF0 and count = 0x20:
// 0xFFFFFFF0 + 0x20 = 0x00000010 (16 bytes!)
ULONG totalAllocationSize = offset + count;
// Allocates a tiny 16-byte heap buffer!
BYTE* pDestArray = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, totalAllocationSize);
if (!pDestArray) {
return E_OUTOFMEMORY;
}
// Copies original oversized byte count, overflowing heap chunks!
memcpy(pDestArray + offset, pBuffer, count);
return S_OK;
}
// SECURE: Decompiled C logic from dwmcore.dll after Patch Tuesday
#include <intsafe.h>
HRESULT CInteraction::ProcessInputArray(BYTE* pBuffer, ULONG offset, ULONG count) {
ULONG totalAllocationSize = 0;
// 1. Enforce safe integer arithmetic check
// Returns INTSAFE_E_ARITHMETIC_OVERFLOW if sum exceeds ULONG_MAX
if (FAILED(ULongAdd(offset, count, &totalAllocationSize))) {
return E_INVALIDARG;
}
// 2. Validate upper bound threshold limits
if (totalAllocationSize > MAX_ALLOWED_INPUT_SIZE) {
return E_INVALIDARG;
}
BYTE* pDestArray = (BYTE*)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, totalAllocationSize);
if (!pDestArray) {
return E_OUTOFMEMORY;
}
memcpy(pDestArray + offset, pBuffer, count);
return S_OK;
}