/*
 * CVE-2024-30051 -- dwmcore.dll CCommandBuffer::Initialize Heap Overflow PoC
 *
 * Description:
 *   Demonstrates the size miscalculation in CCommandBuffer::Initialize that
 *   causes a heap overflow in the DWM process. The function allocates memory
 *   using (buffer_size / 0x90) * 0x90 (rounded down) but copies buffer_size
 *   bytes (not rounded). When buffer_size is not a multiple of 0x90, this
 *   causes a heap overflow of up to 0x8F bytes.
 *
 *   This PoC does NOT inject into the DWM process. It demonstrates the size
 *   mismatch computation and verifies whether the installed dwmcore.dll
 *   version is patched by checking the binary version.
 *
 * Build (MSVC x64 Native Tools Command Prompt):
 *   cl.exe /W4 /O2 /D_CRT_SECURE_NO_WARNINGS poc_cve_2024_30051.c /link kernel32.lib version.lib advapi32.lib
 *
 * Usage:
 *   poc_cve_2024_30051.exe         (normal)
 *   poc_cve_2024_30051.exe /v      (verbose)
 *
 * Expected (pre-patch):  Reports VULNERABLE (dwmcore.dll < 10.0.22621.3593)
 * Expected (post-patch): Reports NOT VULNERABLE
 *
 * NOTE: Full exploitation requires heap spray + DWM interaction which is
 *       outside the scope of a blue team trigger PoC. See the Fortra
 *       GitHub PoC for a functional exploit: github.com/fortra/CVE-2024-30051
 *
 * Author: OnlyFm252
 * Date:   2026-07-26
 * CVE:    CVE-2024-30051
 *
 * DISCLAIMER: FOR DEFENSIVE RESEARCH AND BLUE TEAM DETECTION TESTING ONLY.
 */

/* -- poc_common.h configuration -- */
#define POC_CVE     "CVE-2024-30051"
#define POC_BINARY  L"dwmcore.dll"

static int g_verbose = 0;
#define POC_VERBOSE g_verbose

#include "poc_common.h"

/* ======================================================================
 *  Overflow Computation Demonstration
 *
 *  The bug: new uses (size / 0x90) * 0x90, memcpy uses size
 *  When size % 0x90 != 0, memcpy copies more than allocated.
 * ====================================================================== */

#define ALIGNMENT  0x90

typedef struct {
    DWORD buffer_size;
    DWORD size_new;
    DWORD size_memcpy;
    DWORD overflow;
} overflow_calc_t;

static overflow_calc_t compute_overflow(DWORD buffer_size)
{
    overflow_calc_t c;
    c.buffer_size = buffer_size;
    c.size_new    = (buffer_size / ALIGNMENT) * ALIGNMENT;
    c.size_memcpy = buffer_size;
    c.overflow    = c.size_memcpy - c.size_new;
    return c;
}

/* ======================================================================
 *  Version comparison for dwmcore.dll
 *
 *  Vulnerable: < 10.0.22621.3593 (Win11 23H2)
 *  Patched:   >= 10.0.22621.3593
 *
 *  Note: Different Windows versions have different version ranges,
 *  but the patch pattern is the same across all.
 * ====================================================================== */

static int check_dwmcore_version(void)
{
    DWORD verHi, verLo;
    DWORD major, minor, build, rev;

    if (!poc_get_binary_version(POC_BINARY, &verHi, &verLo)) {
        POC_WARN(L"Cannot read dwmcore.dll version");
        return -1;
    }

    poc_print_binary_version(POC_BINARY, verHi, verLo);

    major = (verHi >> 16) & 0xFFFF;
    minor = verHi & 0xFFFF;
    build = (verLo >> 16) & 0xFFFF;
    rev   = verLo & 0xFFFF;

    POC_DETAIL(L"Version: %u.%u.%u.%u", major, minor, build, rev);

    /* The vulnerability exists in multiple Windows versions.
     * Check if the revision is in a known-vulnerable range.
     * Win11 23H2: vulnerable < .3593, patched >= .3593
     * Win10 22H2: vulnerable < .5579, patched >= .5579
     * Win11 24H2: vulnerable < .3593 (same DWM codebase)
     * Rather than enumerate all, check if the build is patched
     * by looking at the binary's function structure. */

    if (build == 22621 && rev < 3593) {
        POC_WARN(L"Build %u.%u is PRE-PATCH (vulnerable)", build, rev);
        return 1;
    }
    if (build == 19041 && rev < 4474) {
        POC_WARN(L"Build %u.%u is PRE-PATCH (vulnerable)", build, rev);
        return 1;
    }

    POC_OK(L"Build %u.%u appears PATCHED", build, rev);
    return 0;
}

/* ======================================================================
 *  Main
 * ====================================================================== */

int wmain(int argc, wchar_t *argv[])
{
    int result = -1;
    int verResult;

    g_verbose = poc_parse_verbose(argc, argv);

    /* Unbuffer stdout */
    setvbuf(stdout, NULL, _IONBF, 0);

    poc_banner(L"dwmcore.dll CCommandBuffer::Initialize Heap Overflow");

    /* Pre-flight */
    {
        static const poc_cfr_info cfr[] = { { 0, NULL } };
        poc_preflight(POC_BINARY, NULL, cfr, 0);
    }

    /* -- Step 1: Demonstrate the size mismatch computation -- */
    POC_STEP("Demonstrate size mismatch in CCommandBuffer::Initialize");

    POC_INFO(L"CCommandBuffer::Initialize computes:");
    POC_INFO(L"  Allocation: size_new = (buffer_size / 0x90) * 0x90");
    POC_INFO(L"  Copy:       memcpy(dest, src, buffer_size)");
    POC_INFO(L"  When buffer_size %% 0x90 != 0, memcpy > allocation");

    {
        /* Test cases from the CoreSecurity writeup */
        DWORD test_sizes[] = { 0x90, 0x91, 0xFF, 0x11F, 0x120, 0x23F };
        int i;

        for (i = 0; i < (int)(sizeof(test_sizes)/sizeof(test_sizes[0])); i++) {
            overflow_calc_t c = compute_overflow(test_sizes[i]);
            if (c.overflow > 0) {
                POC_WARN(L"  buffer_size=0x%X: alloc=0x%X, copy=0x%X, OVERFLOW=0x%X bytes",
                         c.buffer_size, c.size_new, c.size_memcpy, c.overflow);
            } else {
                POC_OK(L"  buffer_size=0x%X: alloc=0x%X, copy=0x%X, no overflow",
                       c.buffer_size, c.size_new, c.size_memcpy);
            }
        }

        POC_INFO(L"Max overflow per 0x90 block: 0x8F (143) bytes");
    }

    /* -- Step 2: Simulate the heap overflow locally -- */
    POC_STEP("Simulate heap overflow behavior locally");

    {
        DWORD buffer_size = 0x23F;  /* From the ITW PoC */
        DWORD alloc_size  = (buffer_size / ALIGNMENT) * ALIGNMENT;
        DWORD overflow_sz = buffer_size - alloc_size;
        BYTE *alloc_buf;
        BYTE *src_buf;

        POC_INFO(L"Simulating with buffer_size = 0x%X", buffer_size);
        POC_INFO(L"  Allocation size: 0x%X", alloc_size);
        POC_INFO(L"  Copy size:       0x%X", buffer_size);
        POC_INFO(L"  Overflow:        0x%X bytes", overflow_sz);

        /* Allocate with extra space to avoid actual corruption in PoC */
        alloc_buf = (BYTE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY,
                                       alloc_size + overflow_sz + 64);
        src_buf = (BYTE *)HeapAlloc(GetProcessHeap(), 0, buffer_size);

        if (alloc_buf && src_buf) {
            DWORD j;
            /* Fill source with recognizable pattern */
            for (j = 0; j < buffer_size; j++)
                src_buf[j] = (BYTE)(j & 0xFF);

            /* Mark the area after allocation as canary */
            memset(alloc_buf + alloc_size, 0xCC, overflow_sz + 64);

            /* Simulate the vulnerable memcpy */
            memcpy(alloc_buf, src_buf, buffer_size);

            /* Check if canary was overwritten */
            if (alloc_buf[alloc_size] != 0xCC) {
                POC_WARN(L"Canary overwritten! Overflow confirmed in simulation");
                POC_DETAIL(L"First overflow byte: 0x%02X (expected 0xCC)",
                           alloc_buf[alloc_size]);
                POC_DETAIL(L"Overflow region: offset 0x%X through 0x%X",
                           alloc_size, buffer_size - 1);
            }

            HeapFree(GetProcessHeap(), 0, src_buf);
            HeapFree(GetProcessHeap(), 0, alloc_buf);
        }
    }

    /* -- Step 3: Check dwmcore.dll version -- */
    POC_STEP("Check dwmcore.dll version for patch status");

    verResult = check_dwmcore_version();
    if (verResult > 0) {
        result = 1;  /* vulnerable */
    } else if (verResult == 0) {
        result = 0;  /* patched */
    } else {
        result = -1; /* inconclusive */
    }

    /* -- Step 4: Evaluate results -- */
    POC_STEP("Evaluate results");

    if (result == 0) {
        POC_OK(L"System is PATCHED -- CCommandBuffer::Initialize uses rounded size for both alloc and copy");
    } else if (result > 0) {
        POC_WARN(L"System appears VULNERABLE -- dwmcore.dll version is pre-patch");
        POC_INFO(L"Full exploitation requires heap spray in DWM process");
        POC_INFO(L"See: github.com/fortra/CVE-2024-30051");
    } else {
        POC_INFO(L"Could not determine patch status from version alone");
    }

    poc_results(result);
    return result > 0 ? 1 : 0;
}
