4.1 常见的文件系统
文件系统主要用来管理文件,是在逻辑的分区里面的独立数据。每个分区可以有不同的文件系统,互相独立,互不影响。分区在使用之前也要格式化,格式化就是在这个分区建立文件系统。
根据操作系统的不同,支持的文件系统也不一样。微软Windows平台的文件系统主要有FAT12、FAT16、FAT32、NTFS、ExFAT,其中FAT12和FAT16濒临灭绝,FAT32(File Allocation Table File System)主要应用在小容量设备,结构比较简单,但是有很多限制,比如支持最大4G的文件。NTFS(New Technology File System)则是最常用的文件系统,特点很多,如高安全性、可恢复性、文件压缩、磁盘配额、B-树文件管理、EFS加密等,NTFS有几个版本,最新版是4.0,但是这些版本的技术细节微软是不公布的,无法得知差异,公开的资料只是很表面的描述文件系统的构成,Windows 7内置的NTFS文件系统版本是3.1。ExFAT(Extended File Allocation Table File System)是微软最新的文件系统,从Windows Embeded 6.0引入的为闪存而生的。随着闪存的容量暴涨,FAT32已经无法满足需求,而NTFS格式不适合闪存,微软才推出ExFAT。ExFAT主要特点是支持更大的分区、更大的文件、更大的簇大小、支持访问控制列表、支持TFAT等等。
4.2 簇的概念
在介绍文件系统之前很有必要理解簇,因为FAT32及NTFS都是以簇为单位的。簇(Cluster)是存放文件数据的最小单位,由一定数量的扇区组成。扇区是对于物理磁盘的单位,系统就把几个扇区组成一个簇,通常是8、16个扇区,这样就可以从物理抽象到逻辑。文件存储的时都是占用簇的整数倍扇区,如果数据小于一个簇也要占用一个簇的空间。
4.3 FAT32文件系统结构
FAT32(File Allocation Table File System)文件系统是微软从Windows 95开始使用的,它能够支持大于32MB小于32G的分区。
FAT32文件系统主要由DBR及其保留扇区、FAT表(两个相同的FAT表)、DATA区三部分组成,简单的结构如图4-1。
文件系统是在格式化的时候由程序产生的,三个部分的具体含义如下:
DBR及其保留扇区:即DOS Boot Record,DOS引导记录,也是操作系统引导记录,在DBR之后是一定的保留扇区,根据不同的格式化程序保留的数目不一样。
FAT表:即File Allocation Table,文件分配表,记录簇的使用情况和下一个簇的簇号。FAT表有两份,为FAT1和FAT2,其中FAT2是FAT1的备份,是完全相同、同步更新的,分析的时候只要看其中一个就可以。
DATA:也就是数据区,存放着目录和文件的数据等。
4.4 DBR及其保留扇区
FAT32文件系统的DBR由五部分组成:跳转指令、OEM代码、BPB、引导程序和结束标志,完整的FAT32文件系统DBR如图4-2所示。
跳转指令:占用3个字节,它将程序执行流程跳转到引导程序起始处。如EB 58翻译成汇编是 JMP 58,因为这条指令占用两个字节,计算出绝对偏移地址是5A,这个地址恰好是引导程序的起始偏移地址,这样就可以把控制权交给引导程序。EB 58接下来的是一条空指令NOP(90H)。
OEM代码:占用8个字节,由格式化程序的厂商规定,这个OEM代码只是标识作用,不会对文件系统产生影响。图4-2中OEM代码为“MSDOS5.0”,说明是由微软 Windows 2000以上的操作系统创建的。
BPB:是BIOS Parameter Block,即BIOS参数块。从偏移地址0BH开始,占用79个字节。BPB记录整个文件系统非常重要的信息,如果丢失或者出错,分区就有问题了。各个字节都有独特的含义,具体如表4-1。
表4-1 BPB结构含义
偏移 | 长度 | 含义 | 偏移 | 长度 | 含义 |
0x0B | 2 | 每扇区字节数 | 0x0D | 1 | 每簇扇区数 |
0x0E | 2 | DOS保留扇区数 | 0x10 | 1 | FAT表个数 |
0x11 | 4 | 未用 | 0x15 | 1 | 介质描述符 |
0x16 | 2 | 未用 | 0x18 | 2 | 每磁道扇区数 |
0x1A | 2 | 磁头数 | 0x1C | 4 | 隐藏扇区 |
0x20 | 4 | 该分区的扇区总数 | 0x24 | 4 | 每FAT扇区数 |
0x28 | 2 | 标记 | 0x2A | 2 | 版本 |
0x2C | 4 | 根目录首簇号 | 0x30 | 2 | 文件系统扇区号 |
0x32 | 2 | DBR备份扇区号 | 0x34 | 12 | 保留 |
0x40 | 1 | BIOS驱动器号 | 0x41 | 1 | 未用 |
0x42 | 1 | 扩展引导标记 | 0x43 | 4 | 卷序列号 |
0x47 | 11 | 卷标 | 0x52 | 8 | 文件系统类型 |
解析的时候只要找到偏移地址读取值然后转化为10进制即可。需要注意的图4-2中是使用Winhex解析,低字节优先的,读取数据的时候应该从最后字节开始。
引导程序:偏移地址5AH开始,占用420个字节,Windows 98之前的系统,这段代码负责完成DOS三个系统文件的装入,Windows 2000之后的系统,则负责将NTLDR文件装入,windows 7系统则负责将BOOTMGR装入。如果一个分区没有安装操作系统,这段代码是没有意义的。
结束标志:偏移1FEH,和MBR、EBR类似,都是55AA。
以上五个部分共占用512字节,一个扇区大小,称为DOS引导扇区。DBR中除了第五部分结束标志固定不变之外,其余4个部分是不确定的,随操作系统版本、分区的参数变化而变化。
4.5 FAT表
FAT(File Allocation Table)即文件分配表,这个表对正常的文件系统有很大关系。每个FAT32分区有两份相同的FAT表:FAT1和FAT2,其中FAT1是主FAT表,FAT2是备份,起始偏移地址和大小都在DBR的BPB里有记录。但是FAT表是紧跟在保留扇区的。两个FAT表物理上也是相连的。FAT表是由FAT表项构成的,FAT32中,每4个字节就是一个FAT表项。每个FAT表项都有自己的编号,编号从0开始。这个编号对应着数据区中的簇号,FAT表项记录着簇的使用情况,如在FAT表中,编号10的项记录着数据区10号簇的使用情况。FAT表项的意义如表4-2。
表4-2 FAT32表项分配含义
FAT表项值 | 含义 |
0000 0000H | 未使用的簇 |
0000 0002H ~ 0FFF FFEFH | 一个已经使用的簇 |
0FFF FFF0 ~ 0FFF FFF6H | 保留 |
0FFF FFF7H | 坏簇 |
0FFF FFF8H ~ 0FFF FFFFH | 文件结束簇 |
FAT表项中,如果对应的簇没有使用,其值为00000000H,代表这个簇可以分配来存储文件。如果对应的簇被使用并且还没到文件的结束,这时FAT表项值就为下一个存储数据的簇号,这样就可以形成了连续存储的表项链。如果FAT表项对应的簇被使用并且到了这个文件的结尾,后面没有后继簇了,FAT表项值就为0FFF FFF8 ~ 0FFF FFFFH。如果FAT表项对应的簇是坏簇,则值为0FFF FFF7H,说明不能用了,系统就不会再分配此簇存放数据。可见,FAT表项实质就是对数据区簇的使用说明。
FAT表项中,有两个是特殊的表项,第0号和1号表项,这两个表项不对应具体的数据区簇。0号表项通常用来存放分区所在的介质类型,例如硬盘的介质类型为”F8”,则0号表项值为0FFFFFF8H;1号表项用来存储文件系统的肮脏标志,表明文件系统被非法卸载或者磁盘存在表面错误。由此,前两个表项特殊用途,真正表示数据的表项是2号表项以后,所以对应的数据区簇号也是从2开始编号,不存在0、1号数据簇。
系统定位FAT32文件系统的FAT表步骤如下:
系统通过该分区的分区表信息,定位到这个分区,其实就是定位到DBR扇区。
读取DBR中的BPB,通过DBR偏移0EH~0FH处的“DBR保留扇区数”这个参数,就可以得到FAT1表的偏移地址。
再根据DBR偏移0x24~0x27处的“每FAT扇区数”,DBR保留扇区数加上每FAT扇区数就得到FAT2表的偏移地址。FAT定位完毕。
4.6 FAT32数据区
FAT32文件系统数据区就是紧随着FAT表的部分,一直到分区的结束。数据区被划分为一个一个簇,每个簇都有自己的编号,编号从2号开始。不管目录还是真正的文件数据,都存放在数据区。数据区簇的使用情况都由FAT表描述,而且是一一对应。
4.7目录项分析
在FAT32文件系统中,把文件及文件夹的目录当成了文件进行管理,同样放在数据区,这些记录称为目录项。目录项主要记录了文件及文件夹的文件名、扩展名、创建及修改时间日期、文件的起始簇号、文件大小等。每个目录项的大小是32字节,目录项和数据一样,首先是申请一个簇的空间,存放很多个目录项,当一个簇放满时再申请一个新簇,FAT表中对应的旧簇就指向这个新簇,这样系统就可以根据指示找到完整的目录项。
FAT32的目录项有四类:短文件名目录项、长文件名目录项、”.”及”..”目录项、卷标目录项。
短文件名目录项:主要记录一个文件或文件夹的重要信息,32个字节具体含义如表4-3所示。
表4-3 短文件名目录项结构及含义
字节偏移 | 长度(字节) | 含义 | |
0x00 | 8 | 主文件名 | |
0x08 | 3 | 文件扩展名 | |
0x0B | 1 |
文 件 属 性 | 00000000(读写) |
00000001(只读) | |||
00000010(隐藏) | |||
00000100(系统) | |||
00001000(卷标) | |||
00010000(子目录) | |||
00100000(存档) | |||
0x0C | 1 | 未用 | |
0x0D | 1 | 文件创建时间,精确到10ms | |
0x0E | 2 | 文件创建时间,包括时分秒 | |
0x10 | 2 | 文件创建日期,包括年月日 | |
0x12 | 2 | 文件最近访问日期,包括年月日 | |
0x14 | 2 | 文件起始簇号的高位 | |
0x16 | 2 | 文件修改时间,包括时分秒 | |
0x18 | 2 | 文件修改日期,包括年月日 | |
0x1A | 2 | 文件起始簇号的低位 | |
0x1C | 4 | 文件大小(以字节为单位) |
根据表4-3,就可以解析出文件的各种属性,其中文件起始簇号是高位和低位合起来共同构成文件的起始簇号。短文件名只支持传统的8.3文件名格式,但FAT32是支持长文件名的,这就要靠长文件名目录项解决这个问题。
长文件名目录项:每个长文件目录项也是占用32个字节,一个目录项作为长文件名目录项使用时,属性字节为0FH,能够存储13个字符,如果文件名很长,就需要多个多个目录项存储这个长文件名,这些目录项按倒序排列在其短文件名目录项之前。长文件名的目录项结构含义如表4-4。
表4-4 FAT32长文件名目录项含义
偏移 | 长度(字节) | 含义 |
0x00 | 1 | 序列号 |
0x01 | 10 | 文件名的第1~5的Unicode字符 |
0x0B | 1 | 长文件名目录项属性标志,为0F |
0x0C | 1 | 未使用 |
0x0D | 1 | 短文件名校验和 |
0x0E | 12 | 文件名的第6~11个Unicode字符 |
0x1A | 2 | 始终为0 |
0x1C | 2 | 文件名的第12~13个Unicode字符 |
长文件名最重要的是目录项的序列号,是从短文件名往上不断递增的。
“.”及”..”目录项:这个目录项出现在每个子目录的开始两个目录项,表示这是一个子目录。”.”目录项描述的起始簇号是本子目录所在的号。”..”目录项描述的起始簇号是上一级目录的起始簇号,且这两个目录项表示的文件大小都为0,和所有的普通目录项一样,不记录大小。系统利用”.”表示本目录,利用”..”表示上一级目录,上一级目录也有本目录的描述,这样返回上一层和定位本目录都有记录,形成双向关系,从而把整个文件系统联系在一起。
卷标目录项:卷标就是分区的名字,当做一个普通的文件记录描述。这个目录项在整个分区只出现一次,而且是放在根目录。
根目录是一个特殊的目录,在创建文件系统时就已经创建好了,而且一般是在第2簇,也就是数据区的开始位置。因为是根目录,没有上一级目录,所以这个目录没有特殊的”.”及”..”子目录项。根目录的起始簇号在DBR的BPB也有记录,可能是为了便于系统的管理查找。
恩,又要看下一回分析了。