为什么许多分区管理工具(如 EASEUS Partition Master、Acronis Disk Director 等)需要自己的驱动程序才能运行?
换句话说,他们需要做什么,而没有专职司机就无法完成?
在 Windows 中,从用户模式直接访问磁盘是完全可能的,所以我很好奇为什么这些工具坚持安装自定义驱动程序来完成它们的工作。这背后的原因是什么?
答案1
@David Schwartz 认为这是因为他们拦截了所有磁盘访问。这听起来确实可信。但我想知道这是否就是全部。我一直在研究 EaseUS 驱动程序。empmntdrv.sys
有几点需要注意:
当我启动 UI 时它会立即加载,实际上并没有对任何内容进行分区。
EaseUS 论坛有很多有人抱怨没有显示分区当他们启动 UI 时,EaseUS 支持人员给出的标准答案是:重新安装驱动程序。这让我想到它实际上被用来读取表格。
拿出重磅武器:PE 探索器反汇编驱动程序文件。当然,对我来说,大部分都是希腊语,但确实有几件事很突出。首先,符号表显示了对 进行的系统调用列表
ntoskrnel.exe
,其中包括对符号链接的破坏:; Imports from ntoskrnl.exe extrn DbgPrint extrn ExAllocatePoolWithTag extrn ExFreePoolWithTag extrn IoBuildAsynchronousFsdRequest extrn IoBuildDeviceIoControlRequest extrn IoCreateDevice extrn IoCreateSymbolicLink extrn IoDeleteDevice extrn IoDeleteSymbolicLink extrn IoFreeIrp extrn IoFreeMdl extrn IoGetAttachedDeviceReference extrn IoGetDeviceObjectPointer extrn IofCallDriver extrn IofCompleteRequest extrn KeBugCheckEx extrn KeInitializeEvent extrn KeSetEvent extrn KeTickCount extrn KeWaitForSingleObject extrn MmMapLockedPagesSpecifyCache extrn MmUnlockPages extrn ObfDereferenceObject extrn ObfReferenceObject extrn RtlAnsiCharToUnicodeChar extrn RtlInitUnicodeString extrn RtlUnicodeStringToInteger extrn memcpy extrn memset
还要注意,这些不是过滤驱动程序例程,而是低级 IO 例程。(不是
FltGetDiskDeviceObject
,而是IoGetDeviceObjectPointer
。)进一步的侦查发现了一些可能提供更多线索的常量。与大多数 Windows 编译代码一样,PDB 文件有一个硬引用,通常带有创建它的计算机上的路径:
h:\epm2.0\01_projectarea\00_source\epm2\mod.windiskaccessdriver\windiskaccessdriver\objfre_wxp_x86\i386\epmntdrv.pdb
这可能是开发人员的实际项目名称:“win 磁盘访问驱动程序”我认为他们需要驱动程序以对他们有用的方式实际读取表。
然后有这个常数,它看起来真的很有趣:
\Device\Harddisk%u\Partition0
这看起来很有趣,我追踪了它在反汇编代码中被引用的位置,然后我找到了这里:
0001051E 68C6190100 push L000119C6 00010523 6A78 push 00000078h 00010525 50 push eax 00010526 E85BFFFFFF call SUB_L00010486 0001052B 83C420 add esp,00000020h 0001052E 85C0 test eax,eax 00010530 7404 jz L00010536 00010532 L00010532: 00010532 33C0 xor eax,eax 00010534 EB43 jmp L00010579 00010536 L00010536: 00010536 8D4584 lea eax,[ebp-7Ch] 00010539 50 push eax 0001053A 8D8574FFFFFF lea eax,[ebp-0000008Ch] 00010540 50 push eax 00010541 FF15941A0100 call [ntoskrnl.exe!RtlInitUnicodeString] 00010547 8D4580 lea eax,[ebp-80h] 0001054A 50 push eax 0001054B 8D857CFFFFFF lea eax,[ebp-00000084h] 00010551 50 push eax 00010552 56 push esi 00010553 8D8574FFFFFF lea eax,[ebp-0000008Ch] 00010559 50 push eax 0001055A FF15901A0100 call [ntoskrnl.exe!IoGetDeviceObjectPointer]
那么有什么神奇的东西可以
IoGetDeviceObjectPointer
,它只在内核模式下可用,当您调用它时会告诉您\Device\Harddisk0\Partition0
?从comp.os.ms-windows.programmer.nt.kernel-mode 的古老帖子:
如果您使用 IoGetDeviceObjectPointer() 获取指向 \device\harddisk(n)\partition(n) 的指针,那么您将获得指向分区设备对象的指针。如果您想要物理磁盘设备对象,则需要获取指向 \device\harddisk(n)\partition0 的指针。
因此,partition0 让我们能够物理磁盘
这为我们提供了许多低于磁盘逻辑级别的性能指标和计数器。
最后,尝试找到我认为它可能实际使用驱动程序的时间。我从 EaseUS 运行了“表面测试”,并看到了性能统计数据。他们可能从用户级别执行此操作,但在 Process Explorer 中,当我拍摄快照时,我突然看到 dll
Device.mo
处于活动状态:大概是系统与驱动程序通信的部分。
仍然不确定这是否是问题的正确答案。但无论如何,探索很有趣!谢谢阅读。
答案2
他们需要拦截所有磁盘访问。例如,假设您正在克隆分区。如果在克隆过程中对磁盘进行了任何写入,则必须在允许写入之前克隆写入的扇区,否则生成的克隆将不一致。