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

● CVE-2024-30051 · CVSS 9.8 · Crítica
Pesquisa · FlawOpen

CVE-2024-30051: Análise técnica de overflow de heap no Windows DWM Core Library

Como uma soma de inteiros de 32 bits sem validação no dwmcore.dll permitiu que malwares locais causassem alocações insuficientes de heap, corrompessem a memória e escalassem para privilégios SYSTEM.

💡 Explicação em Linguagem Simples (ELI5)

Imagine que uma transportadora lhe dê uma caixa minúscula para 10 itens porque você disse 'tenho 5 itens mais 5 itens'. Mas você envia números tão gigantescos que o cálculo do computador estoura o limite de 32 bits e volta para zero: o computador entende que '4 bilhões mais 10 itens é igual a 10 itens'. Ele cria uma caixa minúscula, você empurra 4 bilhões de pacotes e eles transbordam pelo armazém inteiro, permitindo que você assuma o controle da instalação.

Conceitos Centrais e Termos

Desktop Window Manager (dwmcore.dll)
Subsistema essencial do Windows responsável pela composição visual de janelas, renderização DirectComposition e gráficos do sistema.
Integer Wrap-Around / Overflow
Na aritmética de 32 bits sem sinal, 0xFFFFFFFF + 1 retorna a 0. Se calculado antes de alocar heap, um buffer muito menor é criado.
Pool / Heap Corruption
Gravação de dados além do limite de um bloco de heap em estruturas vizinhas do alocador, possibilitando a escalada local para NT AUTHORITY\SYSTEM.
Safe Integer Arithmetic (ULongAdd)
Biblioteca de aritmética segura da Microsoft que valida se uma adição estoura o limite antes de retornar a soma.

Análise de Causa Raiz

A vulnerabilidade decorre de um estouro de inteiro de 32 bits na função CInteraction::ProcessInputArray de dwmcore.dll, onde a soma offset + count ultrapassa 0xFFFFFFFF, gerando um buffer de 16 bytes que sofre overflow com memcpy.

Fluxo de Ataque Passo a Paso

Step 1

1. Execução inicial do processo local

Um processo de malware de baixo privilégio (como o dropper QakBot) abre um canal IPC com o Desktop Window Manager.

Step 2

2. Criação do comando de tamanho excessivo

O invasor elabora uma mensagem DirectComposition na qual a soma de offset e length ultrapassa 0xFFFFFFFF.

Step 3

3. Alocação de heap insuficiente

O dwmcore.dll sem patch calcula a soma truncada e aloca um bloco de memória de apenas 16 bytes.

Step 4

4. Sobrescrita de memória e escalada a SYSTEM

O parser copia todo o payload para o bloco minúsculo, sobrescrevendo ponteiros de função vizinhos e concedendo privilégios SYSTEM.

Código-Fonte: Vulnerável vs. Seguro

✕ IMPLEMENTAÇÃO VULNERÁVEL
// 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;
}
✓ PATCH SEGURO E ROBUSTO
// 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;
}

Lista de Verificação de Segurança para Engenharia