Credit
Ari Sohandri Putra is a software developer with over a decade of experience, specializing in low-level programming and hardware-related systems. He is also the founder of ARIMetic. Much of his work focuses on exploring how software interacts with hardware, leading him to develop tools like HardMon, HeatMon for temperature monitoring, and uBattery for analyzing the health and behavior of laptop and UPS batteries.
He is passionate about building practical tools that help users better understand and manage their devices, especially in areas like performance and hardware monitoring.
Find Ari at: CodeNomaden (Personal Blog)
uDiscMounter - Driver Architecture
1. Introduction
uDiscMounter is a virtual drive system that allows a disk image (such as ISO) to be mounted as if it were a real physical CD/DVD device.
Unlike a normal application, the core functionality relies on a kernel-mode driver, which integrates directly with the Windows storage stack. This driver makes the operating system believe that a real storage device exists, even though all data actually comes from a file.
2. High-Level Architecture
The system is split into two main layers:
[ User Mode ]
---------------------------------
uDiscMounter Application
|
| IOCTL (DeviceIoControl)
v
[ Kernel Mode ]
---------------------------------
uDiscMounter Driver
|
v
Windows Storage Stack
(File System → Class Driver → SCSI)
Key Idea
The driver emulates a CD-ROM device, and translates:
Disk Request (LBA-based)
↓
File Offset (inside ISO file)
3. Windows Storage Stack Integration
When a file is accessed from the mounted drive, the request flows through several layers:
Application (Read File)
↓
File System (CDFS / UDF)
↓
Class Driver (cdrom.sys)
↓
SCSI Request (SRB + CDB)
↓
uDiscMounter Driver
↓
ISO File (on disk)
4. SCSI Emulation Concept
Windows communicates with storage devices using SCSI commands.
Example: READ(10) command
CDB Structure:
---------------------------------
Byte 0 : Operation Code (0x28)
Byte 2-5: LBA (Logical Block Address)
Byte 7-8: Transfer Length
Your driver receives this and must respond as if it were real hardware.
5. Core Translation Logic
This is the heart of the system:
LBA (sector index)
↓
Offset = LBA * SectorSize (2048 for ISO)
↓
Read from ISO file
↓
Return data to OS
6. Driver Initialization (C++)
#include <ntddk.h>
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{
UNREFERENCED_PARAMETER(RegistryPath);
DriverObject->MajorFunction[IRP_MJ_CREATE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DispatchCreateClose;
DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = DispatchDeviceControl;
DriverObject->MajorFunction[IRP_MJ_SCSI] = DispatchScsi;
DriverObject->DriverUnload = DriverUnload;
IoCreateDevice(
DriverObject,
0,
L"\\Device\\uDiscMounter",
FILE_DEVICE_CD_ROM,
0,
FALSE,
&g_DeviceObject
);
return STATUS_SUCCESS;
}
7. Mounting an Image
When the user mounts an ISO:
NTSTATUS OpenImageFile(PCWSTR path)
{
OBJECT_ATTRIBUTES attr;
IO_STATUS_BLOCK io;
UNICODE_STRING uPath;
RtlInitUnicodeString(&uPath, path);
InitializeObjectAttributes(
&attr,
&uPath,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
NULL
);
return ZwCreateFile(
&g_ImageHandle,
GENERIC_READ,
&attr,
&io,
NULL,
FILE_ATTRIBUTE_NORMAL,
FILE_SHARE_READ,
FILE_OPEN,
FILE_NON_DIRECTORY_FILE,
NULL,
0
);
}
8. Handling SCSI Requests
This is where the driver behaves like a real device.
NTSTATUS DispatchScsi(PDEVICE_OBJECT DeviceObject, PIRP Irp)
{
PIO_STACK_LOCATION stack = IoGetCurrentIrpStackLocation(Irp);
PSCSI_REQUEST_BLOCK srb = (PSCSI_REQUEST_BLOCK)stack->Parameters.Scsi.Srb;
UCHAR op = srb->Cdb[0];
switch (op)
{
case SCSIOP_READ:
{
ULONG lba =
(srb->Cdb[2] << 24) |
(srb->Cdb[3] << 16) |
(srb->Cdb[4] << 8) |
(srb->Cdb[5]);
ULONG sectors =
(srb->Cdb[7] << 8) |
(srb->Cdb[8]);
LARGE_INTEGER offset;
offset.QuadPart = (LONGLONG)lba * 2048;
IO_STATUS_BLOCK io;
ZwReadFile(
g_ImageHandle,
NULL,
NULL,
NULL,
&io,
srb->DataBuffer,
sectors * 2048,
&offset,
NULL
);
srb->SrbStatus = SRB_STATUS_SUCCESS;
Irp->IoStatus.Status = STATUS_SUCCESS;
break;
}
default:
srb->SrbStatus = SRB_STATUS_INVALID_REQUEST;
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
break;
}
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
9. Low-Level (Assembly Perspective)
At the lowest level, the operation becomes:
; Convert LBA to file offset
mov rax, rcx ; rcx = LBA
imul rax, 2048 ; sector size
; Call ZwReadFile using offset
mov rcx, g_ImageHandle
call ZwReadFile
10. Unmount Process
When the drive is removed:
- Close ISO file (ZwClose)
- Remove symbolic link
- Delete device object
- Driver releases memory
11. Key Technical Characteristics
Runs in kernel mode
Emulates a SCSI CD-ROM device
Uses file-backed storage (ISO)
Translates LBA → file offset
Typically read-only
Integrates into Windows storage stack
12. Conclusion
uDiscMounter works by bridging two worlds:
The OS expects a hardware storage device
The driver provides a software-backed illusion
By implementing SCSI command handling and translating requests into file operations, the system achieves a seamless virtual drive experience.
|