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

● CVE-2024-30051 · CVSS 9.8 · Kritisch
Sicherheitsforschung · FlawOpen

CVE-2024-30051: Analyse des Heap-Buffer-Overflows in Windows DWM Core Library

Wie eine ungeprüfte 32-Bit-Ganzzahladition in dwmcore.dll es lokaler Schadsoftware ermöglichte, eine unterdimensionierte Heap-Zuweisung auszulösen, Speicher zu korrumpieren und SYSTEM-Rechte zu erlangen.

💡 Einfache Erklärung (ELI5)

Stellen Sie sich vor, ein Paketdienst gibt Ihnen eine Schachtel für 10 Gegenstände, weil Sie '5 Gegenstände plus 5 Gegenstände' angemeldet haben. Sie übergeben jedoch so gigantische Zahlen, dass der Computer-Zähler überläuft und wieder bei Null beginnt: Der Computer kalkuliert '4 Milliarden plus 10 Gegenstände gleich 10 Gegenstände'. Er stellt eine Mini-Schachtel bereit, Sie stopfen 4 Milliarden Gegenstände hinein, die das gesamte Lager überfluten, sodass Sie die Kontrolle über das Gebäude übernehmen.

Kernkonzepte & Begriffe

Desktop Window Manager (dwmcore.dll)
Zentrales Windows-Subsystem, das für die visuelle Fensterkomposition, das DirectComposition-Rendering und die Desktop-Grafik zuständig ist.
Integer Wrap-Around / Overflow
In der vorzeichenlosen 32-Bit-Arithmetik springt 0xFFFFFFFF + 1 auf 0 zurück. Erfolgt dies vor der Heap-Zuweisung, entsteht ein winziger Puffer.
Pool / Heap Corruption
Schreiben von Daten über die Grenzen eines Heap-Blocks hinaus in benachbarte Allokator-Strukturen, was eine lokale Rechteausweitung auf NT AUTHORITY\SYSTEM erlaubt.
Safe Integer Arithmetic (ULongAdd)
Sichere Arithmetik-Bibliothek von Microsoft, die vor Rückgabe der Summe prüft, ob eine Addition überläuft.

Ursachenanalyse

Die Schwachstelle resultiert aus einem ungeprüften 32-Bit-Ganzzahlüberlauf in dwmcore.dll!CInteraction::ProcessInputArray, bei dem offset + count überläuft, ein 16-Byte-Heap-Puffer reserviert wird und memcpy benachbarten Speicher überschreibt.

Schritt-für-Schritt Angriffsablauf

Step 1

1. Lokale Malware-Ausführung

Ein Prozess mit niedrigen Rechten (z. B. ein QakBot-Dropper) initiiert einen IPC-Kanal zum Desktop Window Manager.

Step 2

2. Erstellung des übergroßen Befehls

Der Angreifer konstruiert eine DirectComposition-Nachricht, bei der die Summe aus offset und length gezielt 0xFFFFFFFF übersteigt.

Step 3

3. Unterdimensionierte Heap-Allokation

Die ungepatchte dwmcore.dll berechnet die überlaufene Summe und allokiert einen winzigen 16-Byte-Puffer statt mehrerer Megabyte.

Step 4

4. Lineares Überschreiben und SYSTEM-Eskalation

Der Parser kopiert die gesamten Nutzdaten in den Mini-Puffer, überschreibt benachbarte Funktionszeiger und erlangt SYSTEM-Rechte.

Quellcode: Verwundbar vs. Sicher

✕ VERWUNDBARE IMPLEMENTIERUNG
// 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;
}
✓ GEHÄRTETER SICHERHEITS-PATCH
// 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;
}

Checkliste für Engineering & Systemsicherheit