flawopen.com/Teardowns/cve-2024-30051-windows-dwm-privilege-escalation
Как непроверенное 32-битное сложение целых чисел в dwmcore.dll позволяло локальному вредоносному ПО выделять буфер кучи заниженного размера, повреждать память и повышать привилегии до SYSTEM.
Представьте складской сервис, который выдает вам коробку на 10 мест, потому что вы сказали 'у меня 5 предметов плюс еще 5'. Но вы передаете такие огромные числа, что счетчик сбрасывается обратно в ноль: компьютер считает, что '4 миллиарда плюс 10 предметов равно 10 предметам'. Выделяется крошечная коробка, в нее загружают 4 миллиарда предметов, они загромождают весь склад и позволяют захватить здание.
Desktop Window Manager (dwmcore.dll)Integer Wrap-Around / OverflowPool / Heap CorruptionSafe Integer Arithmetic (ULongAdd)Уязвимость заключается в целочисленном переполнении в dwmcore.dll!CInteraction::ProcessInputArray: сложение offset + count переполняет 32-битный предел, вызывая выделение маленького буфера и последующее повреждение памяти через memcpy.
Низкопривилегированный вредоносный процесс (например, дроппер QakBot) инициирует сессию IPC с процессом Desktop Window Manager.
Атакующий формирует сообщение DirectComposition, в котором сумма offset и length превышает 0xFFFFFFFF.
Непропатченная dwmcore.dll вычисляет переполненную сумму и выделяет буфер размером всего 16 байт.
Парсер копирует весь массив байтов в крошечный блок кучи, перезаписывая указатели и получая права SYSTEM.
// 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;
}