# Fat32VirtualDisk **Repository Path**: xcvk/Fat32VirtualDisk ## Basic Information - **Project Name**: Fat32VirtualDisk - **Description**: 适用于 Fat32 文件系统的虚拟磁盘 - **Primary Language**: C - **License**: MIT - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 0 - **Created**: 2022-05-09 - **Last Updated**: 2024-03-13 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Fat32虚拟磁盘 ## 介绍 适用于Fat32文件系统的虚拟磁盘。 ![](./Pics/%E8%99%9A%E6%8B%9F%E7%A3%81%E7%9B%98.png) ## 测试 Win10 x64 1903 ## 注册例程 ``` NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegPath) { UNREFERENCED_PARAMETER(pRegPath); pDriverObject->DriverUnload = DriverUnload; pDriverObject->DriverExtension->AddDevice = DrvAddDevice; pDriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = IrpDeviceControl; pDriverObject->MajorFunction[IRP_MJ_CREATE] = IrpCreate; pDriverObject->MajorFunction[IRP_MJ_CLOSE] = IrpClose; pDriverObject->MajorFunction[IRP_MJ_WRITE] = IrpWrite; pDriverObject->MajorFunction[IRP_MJ_READ] = IrpRead; pDriverObject->MajorFunction[IRP_MJ_PNP] = IrpPnp; return STATUS_SUCCESS; } ``` ## 为PNP管理器枚举的设备创建过滤设备对象 - 主要流程: 1. 创建设备对象和符号链接 2. 初始化设备扩展 3. 初始化Fat32的DBR 4. 附加设备 ``` NTSTATUS DrvAddDevice(IN PDRIVER_OBJECT DriverObject, IN PDEVICE_OBJECT PhysicalDeviceObject) { UNICODE_STRING usDeviceName = { 0 }; PDEVICE_OBJECT pDeviceObject = NULL; NTSTATUS ntStatus; PDEVICE_EXTENSION pDeviceExtension = NULL; BOOLEAN bCreate = FALSE; PVOID pBuff = NULL; do { // // 创建设备对象 // RtlInitUnicodeString(&usDeviceName, USTRING_DEVICE_NAME); ntStatus = IoCreateDevice(DriverObject, sizeof(DEVICE_EXTENSION), &usDeviceName, FILE_DEVICE_DISK, FILE_DEVICE_SECURE_OPEN, FALSE, &pDeviceObject); if (!NT_SUCCESS(ntStatus)) { ERRPRINT(IoCreateDevice, ntStatus); break; } pDeviceObject->Flags |= DO_DIRECT_IO; pDeviceObject->Flags |= DO_POWER_PAGABLE; // // 创建符号链接 // pDeviceExtension = (PDEVICE_EXTENSION)pDeviceObject->DeviceExtension; RtlInitUnicodeString(&pDeviceExtension->usSymbolicLink, USTRING_SYMBOL_NAME); ntStatus = IoCreateSymbolicLink(&pDeviceExtension->usSymbolicLink, &usDeviceName); if (STATUS_SUCCESS != ntStatus) { ERRPRINT(IoCreateSymbolicLink, ntStatus); break; } bCreate = TRUE; // // 初始化设备扩展 // # 保存设备对象、物理设备对象、磁盘配置 // # 初始化移除锁 // # 分配磁盘空间 // pDeviceExtension->DeviceObject = pDeviceObject; pDeviceExtension->PhysicalDeviceObject = PhysicalDeviceObject; IoInitializeRemoveLock(&pDeviceExtension->RemoveLock, TAG_REMOVELOCK, 0, 0); pDeviceExtension->DiskInfo.DiskSize = 0x40000000; pDeviceExtension->DiskInfo.RootDirEntries = 0x0; pDeviceExtension->DiskInfo.SectorsPerCluster = 8; pBuff = ExAllocatePoolWithTag(NonPagedPool, pDeviceExtension->DiskInfo.DiskSize, TAG_MEMORYDISK); if (!pBuff) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; ERRPRINT(ExAllocatePoolWithTag, ntStatus); break; } pDeviceExtension->Memory = pBuff; // // 初始化 Fat32's DBR // InitFat32Vdisk(pDeviceObject); // // 附加设备 // pDeviceExtension->NextDeviceObject = IoAttachDeviceToDeviceStack(pDeviceObject, PhysicalDeviceObject); if (!pDeviceExtension->NextDeviceObject) { ntStatus = STATUS_NO_SUCH_DEVICE; ERRPRINT(IoAttachDeviceToDeviceStack, ntStatus); break; } pDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; ntStatus = STATUS_SUCCESS; } while (FALSE); if (STATUS_SUCCESS != ntStatus) { if (pBuff) ExFreePoolWithTag(pBuff, TAG_MEMORYDISK); if (bCreate) IoDeleteSymbolicLink(&pDeviceExtension->usSymbolicLink); if (pDeviceObject) IoDeleteDevice(pDeviceObject); } return ntStatus; } ``` ## 初始化Fat32的DBR ``` static void InitFat32Vdisk(IN PDEVICE_OBJECT DeviceObject) { PDEVICE_EXTENSION pDeviceExtension = DeviceObject->DeviceExtension; PDOS_BOOT_RECORD pBoot = (PDOS_BOOT_RECORD)pDeviceExtension->Memory; PULONG FatSector; ASSERT(SIZE_PER_SECTOR == sizeof(DOS_BOOT_RECORD)); ASSERT(NULL != pDeviceExtension->Memory); RtlZeroMemory(pDeviceExtension->Memory, pDeviceExtension->DiskInfo.DiskSize); // // 初始化物理磁盘信息 // 存储容量 = 磁头数 × 柱面数 × 扇区数 × 每扇区字节数 // pDeviceExtension->DiskGeometry.BytesPerSector = SIZE_PER_SECTOR; pDeviceExtension->DiskGeometry.SectorsPerTrack = 0x3F; pDeviceExtension->DiskGeometry.TracksPerCylinder = 0xFF; pDeviceExtension->DiskGeometry.Cylinders.QuadPart = (LONGLONG)( pDeviceExtension->DiskInfo.DiskSize / pDeviceExtension->DiskGeometry.BytesPerSector / pDeviceExtension->DiskGeometry.SectorsPerTrack / pDeviceExtension->DiskGeometry.TracksPerCylinder); pDeviceExtension->DiskGeometry.MediaType = 0xF8; // // 初始化 DBR // pBoot->Jmp[0] = 0xEB; pBoot->Jmp[1] = 0x58; pBoot->Jmp[2] = 0x90; strncpy(pBoot->strOemName, STRING_OEM_NAME, 8); pBoot->BytesPerSector = SIZE_PER_SECTOR; pBoot->SectorsPerCluster = (UCHAR)pDeviceExtension->DiskInfo.SectorsPerCluster; pBoot->ReservedSectors = 0x20; pBoot->NumberOfFats = 1; pBoot->RootEntries = 0; pBoot->SmallSectors = 0; pBoot->MediaDescriptor = (UCHAR)pDeviceExtension->DiskGeometry.MediaType; pBoot->SectorsPerTrack = (USHORT)pDeviceExtension->DiskGeometry.SectorsPerTrack; pBoot->NumberOfHeads = (USHORT)pDeviceExtension->DiskGeometry.TracksPerCylinder; pBoot->HiddenSectors = 0; pBoot->LargeSectors = pDeviceExtension->DiskInfo.DiskSize / SIZE_PER_SECTOR; ULONG FatEntries = pBoot->LargeSectors / pDeviceExtension->DiskInfo.SectorsPerCluster; ULONG FatBytes = FatEntries * 4; pBoot->SectorsPerFat32 = (FatBytes + 0x1FF) / SIZE_PER_SECTOR; pBoot->ExtendedFlag = 0x0; pBoot->FileSystemVersion = 0x0; pBoot->RootClusterNumber = 0x2; pBoot->FsInfoSectorNumber = 0x1; pBoot->BackupBootSector = 0x6; RtlZeroMemory(pBoot->Reserved1, 0xC); pBoot->PhysicalDriveNumber = 0x80; pBoot->Reserved2 = 0x0; pBoot->ExtendBootSignature = 0x29; pBoot->VolumeSerialNumber = 0x52368BA8; strncpy((char*)pBoot->VolumeLabel, STRING_VOLUME_LABEL, 8); strncpy((char*)pBoot->SystemId, STRING_FILE_SYSTEM, 8); pBoot->AA55[0] = 0x55; pBoot->AA55[1] = 0xAA; // // Fat // FatSector = (PULONG)(pBoot + 32); FatSector[0] = 0x0FFFFFF8; FatSector[1] = 0xFFFFFFFF; FatSector[2] = 0x0FFFFFFF; } ``` ## 处理卸载事件 ``` NTSTATUS IrpPnp(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pDeviceExtension = (PDEVICE_EXTENSION)DeviceObject->DeviceExtension; NTSTATUS ntStatus; ntStatus = IoAcquireRemoveLock(&pDeviceExtension->RemoveLock, Irp); if (STATUS_SUCCESS != ntStatus) { COMPLETE_REQUEST(Irp, ntStatus, 0); return ntStatus; } if (pStack->MinorFunction == IRP_MN_REMOVE_DEVICE) { Irp->IoStatus.Status = STATUS_SUCCESS; IoSkipCurrentIrpStackLocation(Irp); ntStatus = IoCallDriver(pDeviceExtension->NextDeviceObject, Irp); ReleaseDeviceExtension(pDeviceExtension, Irp); IoDeleteDevice(DeviceObject); return ntStatus; } IoReleaseRemoveLock(&pDeviceExtension->RemoveLock, Irp); IoSkipCurrentIrpStackLocation(Irp); return IoCallDriver(pDeviceExtension->NextDeviceObject, Irp); } ``` ## 处理写入事件 ``` NTSTATUS IrpWrite(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { BOOLEAN bAcquired = FALSE; PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pDeviceExtension = DeviceObject->DeviceExtension; ULONG information = 0; NTSTATUS ntStatus; PUCHAR pVa; do { ntStatus = IoAcquireRemoveLock(&pDeviceExtension->RemoveLock, Irp); if (!NT_SUCCESS(ntStatus)) { ERRPRINT(IoAcquireRemoveLock, ntStatus); break; } bAcquired = TRUE; if ((pStack->Parameters.Write.ByteOffset.QuadPart + pStack->Parameters.Write.Length > pDeviceExtension->DiskInfo.DiskSize) || (pStack->Parameters.Write.Length & (pDeviceExtension->DiskGeometry.BytesPerSector - 1))) { ntStatus = STATUS_INVALID_PARAMETER; break; } pVa = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if (pVa == NULL) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; } information = pStack->Parameters.Write.Length; RtlMoveMemory(pDeviceExtension->Memory + pStack->Parameters.Write.ByteOffset.LowPart, pVa, pStack->Parameters.Write.Length); ntStatus = STATUS_SUCCESS; } while (FALSE); if (bAcquired) IoReleaseRemoveLock(&pDeviceExtension->RemoveLock, Irp); COMPLETE_REQUEST(Irp, ntStatus, information); return ntStatus; } ``` ## 处理读取事件 ``` NTSTATUS IrpRead(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp) { BOOLEAN bAcquired = FALSE; PIO_STACK_LOCATION pStack = IoGetCurrentIrpStackLocation(Irp); PDEVICE_EXTENSION pDeviceExtension = DeviceObject->DeviceExtension; NTSTATUS ntStatus; ULONG information = 0; PUCHAR pVa; do { // // 获取移除锁 // ntStatus = IoAcquireRemoveLock(&pDeviceExtension->RemoveLock, Irp); if (STATUS_SUCCESS != ntStatus) { ERRPRINT(IoAcquireRemoveLock, ntStatus); break; } bAcquired = TRUE; // // 判断读取长度和范围的有效性 // if ((pStack->Parameters.Read.ByteOffset.QuadPart + pStack->Parameters.Read.Length > pDeviceExtension->DiskInfo.DiskSize) || (pStack->Parameters.Read.Length & (pDeviceExtension->DiskGeometry.BytesPerSector - 1))) { ntStatus = STATUS_INVALID_PARAMETER; break; } // // 获取MDL的系统地址 // pVa = MmGetSystemAddressForMdlSafe(Irp->MdlAddress, NormalPagePriority); if (pVa == NULL) { ntStatus = STATUS_INSUFFICIENT_RESOURCES; break; } information = pStack->Parameters.Read.Length; // // 返回数据 // RtlMoveMemory(pVa, pDeviceExtension->Memory + pStack->Parameters.Read.ByteOffset.LowPart, pStack->Parameters.Read.Length); ntStatus = STATUS_SUCCESS; } while (FALSE); // // 释放移除锁 // if (bAcquired) IoReleaseRemoveLock(&pDeviceExtension->RemoveLock, Irp); COMPLETE_REQUEST(Irp, ntStatus, information); return ntStatus; } ``` ## 处理获取磁盘分区信息事件 ``` // // MSDN: // 返回有关磁盘分区的类型、大小和特性的信息, // 驱动程序要在 Irp->AssociatedIrp.SystemBuffer 中返回 PARTITION_INFORMATION 数据 // // N.B. // Parameters.DeviceIoControl.OutputBufferLength >= sizeof(PARTITION_INFORMATION) // case IOCTL_DISK_GET_PARTITION_INFO: { if (pStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(PARTITION_INFORMATION)) { information = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } else { PPARTITION_INFORMATION pBuff = (PPARTITION_INFORMATION)(Irp->AssociatedIrp.SystemBuffer); pBuff->PartitionType = PARTITION_FAT32; pBuff->BootIndicator = FALSE; pBuff->RecognizedPartition = TRUE; pBuff->RewritePartition = FALSE; pBuff->StartingOffset.QuadPart = 0; pBuff->PartitionLength.QuadPart = pDeviceExtension->DiskInfo.DiskSize; pBuff->HiddenSectors = 0; pBuff->PartitionNumber = (ULONG)(1L); information = sizeof(PARTITION_INFORMATION); ntStatus = STATUS_SUCCESS; } break; } ``` ## 处理获取磁盘几何结构信息事件 ``` // // MSDN: // 返回有关物理磁盘几何结构的信息(介质类型、柱面数、每柱面磁道、每磁道扇区和每扇区字节数), // 驱动程序要在 Irp->AssociatedIrp.SystemBuffer 中返回 DISK_GEOMETRY 数据 // // N.B. // Parameters.DeviceIoControl.OutputBufferLength >= sizeof(DISK_GEOMETRY) // case IOCTL_DISK_GET_DRIVE_GEOMETRY: { if (pStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(DISK_GEOMETRY)) { information = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } else { PDISK_GEOMETRY pBuff = (PDISK_GEOMETRY)(Irp->AssociatedIrp.SystemBuffer); RtlCopyMemory(pBuff, &(pDeviceExtension->DiskGeometry), sizeof(DISK_GEOMETRY)); information = sizeof(DISK_GEOMETRY); ntStatus = STATUS_SUCCESS; } break; } ``` ## 处理询问磁盘是否可写事件 ``` // // MSDN: // 确定磁盘是否可写 // case IOCTL_DISK_IS_WRITABLE: { ntStatus = STATUS_SUCCESS; break; } ``` ## 处理获取长度事件 ``` // // MSDN: // 返回与请求目标设备对象相关联的磁盘、分区或卷的长度(以字节为单位), // 驱动程序要在 Irp->AssociatedIrp.SystemBuffer 中返回 GET_LENGTH_INFORMATION 数据 // // N.B. // Parameters.DeviceIoControl.OutputBufferLength >= sizeof(GET_LENGTH_INFORMATION) // case IOCTL_DISK_GET_LENGTH_INFO: { if (pStack->Parameters.DeviceIoControl.OutputBufferLength < sizeof(GET_LENGTH_INFORMATION)) { information = 0; ntStatus = STATUS_BUFFER_TOO_SMALL; } else { PGET_LENGTH_INFORMATION pInfo = (PGET_LENGTH_INFORMATION)(Irp->AssociatedIrp.SystemBuffer); pInfo->Length.QuadPart = pDeviceExtension->DiskInfo.DiskSize; information = sizeof(GET_LENGTH_INFORMATION); ntStatus = STATUS_SUCCESS; } break; } ```