BBYR Achieve
返回信息流
这是一条镜像帖。来源:北邮人论坛 / soft-design / #904同步于 1 周前
SoftDesign机器人发帖

Re: 如何获取NTFS分区的卷标

alexxin
1 周前镜像同步1 回复
对于分区表的定位,我也没做过,不过思路大概有,在分区表中,TYPE段为05的是Extended Partition,用来超越最大4个Primary Partition的限制,对于Partition Table,只能有0~1个Extended Partition Entry,而对于每一个Extended Partition 的开始的一个Section都含有一个Partition Table(多了3个),这个样就形成一个嵌套结构。 像PQ这样的分区软件就是对于分区表中的入口,对于05 (Extended Partition) 做特殊处理来遍历所有分区,而在PQ中的驱动器号,一般是按照顺序安排的,如果文件系统是NTFS,这个信息好像是存放在系统的某个地方,具体不清楚。 如果你要对NTFS卷进行写操作,那要看你实现的环境,不过由于NTFS是非公开的,实现写操作有一定的危险,特别是如果开启EFS加密的卷,写入操作就更容易出问题,即使是PQ也只是按照比较老的NTFS版本(PQ貌似最高支持到1.2)来实现格式化的功能,对于跨系统读写比较成熟的工具是Wininternals的NTFS for DOS/9x 但其实现利用了NT系列的成品驱动ntfs.sys和ntoskrnl.exe。 Linux平台下好像有支持NTFS卷读操作的驱动,可惜我对Linux不是很熟悉。 对于NTFS的磁盘结构可以参考 1.Windows Internals 4/e (第三版叫 Inside Windows 2000 3/e) 2.Windows 2000 Native API 中的附录NTFS On Disk Structure 3.Undocumented NTFS
订阅后,新回复会通过你的通知中心匿名送达。
1 条回复
alexxin机器人#1 · 1 周前
我又回来啦~~~~^_^~~~~~~也算是有那么一点点收获吧,不过以下内容都是反汇编得到的,可能会有不准确的地方。 你的需求还真是特别阿,我搞了2天终于有点头绪了,其实最先我就想到过,不过只是认为太麻烦了,那就是遍历! 先说一下思路, 首先对从分区表那里得到的分区信息建立一个表,然后从每个在windows下的驱动器号获得其对应的分区信息和原先建立的表比较,获得全部分区对应的那个Driver Letter.这个方法看起来很烦把.我原以为PQMagic会有什么新的东西,跟了很久,原来他也不过用了这种方法而已,(失望。。。。。)。 思路写完了,有兴趣的话再看看Windows和PQ实现的过程(貌似违反其License了 :-P)。 先从Windows开始。Windows Xp/03下面即NT内核的系统,所有的逻辑驱动器号是一个位于\\??\\下的一个SymbolicLink,Windows会对于每个分区建立两个内核 对象用于维护,一个是\Device\HarddiskVolume<x>,x是这个卷的编号,从1开始,与物理分区没有具体关系,这个设备由FtDisk.sys (Fault-Tolerant Disk Driver)进行维护。并且负责对每个分区建立相对应的DosDevice既逻辑驱动器符号(在\\??\\下),令外ftdisk还会对每个分区建立型 为\\Device\\Harddisk<x>\\Partition<x>的SymbolicLink(这个SymbolicLink首先由Disk.sys建立,指向Disk.sys建立的分区对象,后由ftdisk.sys改写指 向其建立的卷对象)。 另一个是"\\Device\\Harddisk%d\\DP(%d)%#I64x-%#I64x+%lx",由Disk.sys(Class Driver)进行维护,这个没有对应的DosDevice,在用户态下不可访问, 一般由FtDisk用来做底层实现。 从这个结构上可以看出来,Disk.sys是一个Class Driver,用来实现对物理磁盘进行管理,包括对分区表的解析等等,这个部分只有\??\PysicalDriver<x>一个 接口。而FtDisk用来对物理分区进行抽象,建立卷和罗逻驱动器,一般对于逻辑驱动器的访问都交由FtDisk来处理,而在这个部分,它建立的卷设备名字都是形如 HarddiskVolumeX的样子,X是从1开始顺序计数的,与物理磁盘分区无关,只是在建立时,由PnpManager传递给他一个物理分区设备对象的指针,他把相关的访问 转换为对应的分区的访问,再交给Disk.sys进行处理。 说完这些,可以注意到,Windows在设法把这些东西全都隐藏起来,换句话说就是并没有提供一种直接的方式可以从分区表来找出对应的驱动器号的方式。而且我 们用CreateFile只能访问\\??\\目录下的东西,而相关需要的信息在\\??\\下的只有一些分区信息而已。那么怎么获得这些东西呢?就只有用Native API(由ntdll.dll导出,System Service的用户态接口,详细信息可查看 《Windows 2000 Native API》一书)。 那么我们再来看看PQMagic是怎么实现这个东西的。 1.用CreateFile获得\\\\.\\PhysicalDriver<x>句柄,然后获得所有相关的信息,具体为,用DeviceIoControl读取磁盘结构信息,根据分区表分别读取磁盘的 MBR,扩展分区等信息。 2.用GetDriverType获取A~Z的类型,若类型为DRIVE_FIXED则,获取其对应的设备对象,具体实现方式利用ZwOpenSymbolicLinkObject获取形如"\\??\\C:"的对 象句柄,然后用ZwQuerySymbolicLinkObject获得其对应的设备对象名(如:"\\device\\harddiskvolume1")。 *注:ZwOpenSymbolicLinkObject和ZwQuerySymbolicLinkObject都是Native API。 3.由于对于每个分区,Disk.sys会建立形如"\\Device\\Harddisk<x>\\Partition<x>"的SymbolicLinkObject,那么就可以用这个获得物理磁盘的对应关系, 同样用ZwOpenSymbolicLinkObject和ZwQuerySymbolicLinkObject获得它指向的设备对象名(一般形如"\\device\\harddiskvolume1"),就可以同2中获得的对 象名对应。 4.用ZwDeviceIoContorlFile对于每个驱动发送IOCTL_DISK_GET_PARTITION_INFO指令获得分区信息,主要是起始偏移,单位为byte,PQ会将其转化为Sector,然 后利用这个信息同分区表中获得的信息进行比较,建立物理分区同磁盘设备对象的对应关系。 注:这里PQ用的是ZwDeviceIoControlFile而不是Win32 Api中的DeviceIoControl,原因不清楚,不知道可不可以互换。 流程如图 +-------------------------------+ +-------------------------------+ + "*:" + + "\device\harddisk?\partition" + +-------------------------------+ +-------------------------------+ || || ZwOpenSymbolicLinkObject an ZwQuerySybmolicLinkObject \/ \/ +-------------------------------+ match +-------------------------------+ + \device\harddiskvolume? + <----> + "\device\harddisk?\partition" + +-------------------------------+ +-------------------------------+ || \/ +-------------------------------+ match + ZwDeviceIoContorlFile + <------- Partitions from MBR or EMBR +-------------------------------+ 另外还有一种思路,就是利用WMI,貌似大部分Windows的驱动设备都支持WMI接口,可能就想当于作了一个磁盘管理器的表示部分,不过不确定它是用WMI实现的 ,但可惜的是这部分也是Undocumented的,并且都是基于RPC的(见到就头大),我对着方向不是很熟悉,也就没继续跟, PS: 不知道hiboy是不时已经弄出来了,如果有其他的方法也共享出来吧。 至于卷标,在Win32下面倒是可以用GetVolumeInformation,但是它要求那个卷必须是Mounted,如果是Unmounted的卷,可以用ZwQueryVolumeInfomationFile来获得,这又是一个Native API。