flawopen.com/Teardowns/cve-2024-30051-windows-dwm-privilege-escalation

● CVE-2024-30051 · CVSS 9.8 · Критический
Исследования · FlawOpen

CVE-2024-30051: Разбор переполнения кучи в Windows DWM Core Library

Как непроверенное 32-битное сложение целых чисел в dwmcore.dll позволяло локальному вредоносному ПО выделять буфер кучи заниженного размера, повреждать память и повышать привилегии до SYSTEM.

💡 Простыми словами (ELI5)

Представьте складской сервис, который выдает вам коробку на 10 мест, потому что вы сказали 'у меня 5 предметов плюс еще 5'. Но вы передаете такие огромные числа, что счетчик сбрасывается обратно в ноль: компьютер считает, что '4 миллиарда плюс 10 предметов равно 10 предметам'. Выделяется крошечная коробка, в нее загружают 4 миллиарда предметов, они загромождают весь склад и позволяют захватить здание.

Ключевые понятия и термины

Desktop Window Manager (dwmcore.dll)
Ключевая подсистема Windows, отвечающая за компоновку окон, рендеринг DirectComposition и графику рабочего стола.
Integer Wrap-Around / Overflow
В 32-битном беззнаковом сложении 0xFFFFFFFF + 1 превращается в 0. При расчете размера буфера это приводит к выделению памяти меньшего объема, чем требуется.
Pool / Heap Corruption
Запись данных за пределы блока кучи в соседние структуры аллокатора, приводящая к локальному повышению привилегий до NT AUTHORITY\SYSTEM.
Safe Integer Arithmetic (ULongAdd)
Безопасная математическая функция Microsoft, проверяющая переполнение перед возвратом суммы.

Анализ первопричины

Уязвимость заключается в целочисленном переполнении в dwmcore.dll!CInteraction::ProcessInputArray: сложение offset + count переполняет 32-битный предел, вызывая выделение маленького буфера и последующее повреждение памяти через memcpy.

Пошаговый сценарий атаки

Step 1

1. Запуск непривилегированного процесса

Низкопривилегированный вредоносный процесс (например, дроппер QakBot) инициирует сессию IPC с процессом Desktop Window Manager.

Step 2

2. Создание вредоносной команды

Атакующий формирует сообщение DirectComposition, в котором сумма offset и length превышает 0xFFFFFFFF.

Step 3

3. Выделение буфера заниженного размера

Непропатченная dwmcore.dll вычисляет переполненную сумму и выделяет буфер размером всего 16 байт.

Step 4

4. Перезапись памяти и получение прав SYSTEM

Парсер копирует весь массив байтов в крошечный блок кучи, перезаписывая указатели и получая права SYSTEM.

Исходный код: Уязвимый vs Защищённый вариант

✕ УЯЗВИМАЯ РЕАЛИЗАЦИЯ
// 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;
}

Чек-лист по защите системы для инженеров