flawopen.com/Teardowns/cve-2024-30051-windows-dwm-privilege-escalation
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.
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.
Desktop Window Manager (dwmcore.dll)Integer Wrap-Around / OverflowPool / Heap CorruptionSafe Integer Arithmetic (ULongAdd)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.
Um processo de malware de baixo privilégio (como o dropper QakBot) abre um canal IPC com o Desktop Window Manager.
O invasor elabora uma mensagem DirectComposition na qual a soma de offset e length ultrapassa 0xFFFFFFFF.
O dwmcore.dll sem patch calcula a soma truncada e aloca um bloco de memória de apenas 16 bytes.
O parser copia todo o payload para o bloco minúsculo, sobrescrevendo ponteiros de função vizinhos e concedendo privilégios 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;
}