文件系统3:NTFS

NFTS总体结构如下

MFTMirr只备份前四个对象,但其位置相对不固定,通过Boot区确定其位置

Boot区

Boot区最多占16个扇区。第1个扇区是带有“引导”代码的引导扇区(DBR),接下来的15个扇区是引导扇区的初始程序加载器。在NTFS分区的最后一个扇区留有DBR备份。第一个扇区结构如下:

偏移 意义
0-2 跳转指令
3-A 厂商名
B-C 每扇区的字节数
D 每个簇的扇区数
E-F 保留扇区
10-12 总是0
13-14 NTFS不使用
15 介质描述符
16-17 总是0
18-19 每个轨道的扇区
1A-1B 轨道数
1C-1F 隐藏的扇区,其实就是从磁盘开始到第一个分区的扇区数
20-27 NTFS不使用
28-2F 总扇区数
30-37 MFT的簇号
38-3F MFTMirr的簇号
40 int8,每个MFT占用的字节数,值为2^(-1*字段的值)
41-43 保留
44 每个索引目录(文件夹记录文件名的地方)的簇数
45-47 NTFS不使用
48-4F 卷号
50-53 校验和
54-1FD 引导代码
1FE-1FF 扇区结束标记55 AA

举例

以磁盘0的D分区为例,分区格式为NTFS

从分区起始处的Boot区出发,数据如下,可以看到每簇扇区数为8,MFT在3簇,所以MFT在相对此分区开始的8*3扇区,此分区从2048扇区开始,所以MFT在2048+8*3=2072扇区。
可以在偏移40处知道每个MFT对象占2^(-1*-10)=1024B

主文件表 (MFT)

MFT包含了所有文件的信息,每个文件对应一个MFT对象,其中有几个文件是初始化时就创建好的,被称为元文件

元文件种类

文件名 在MFT记录中的顺序,即索引号 作用
$MFT 0 主文件表,包含了所有文件的信息
\(MFTMMirr|1|\)MFT前4个表项的备份
$LogFile 2 日志文件
$Volume 3 卷标和卷版本信息
$AttrDef 4 属性定义表
$Root 5 根文件夹
$Bitmap 6 位图,显示哪些簇在使用
$Boot 7 引导扇区
$BadClus 8 坏簇列表文件
$Secure 9 安全文件,用来控制文件的访问权限
$UpCase 10 大小写字符转换表,将小写字符转换为Unicode大写字符
$Extend 11 用于各种扩展
保留 12-15 保留
$Quota 24 配额管理文件,因为NTFS可以为每个用户设置其可以使用的最大空间
$ObjId 25 对象ID文件
$Reoarse 26 重解析点文件
$RmMetadata 27 记录事务元数据,即最近对文件系统的修改

MFT对象结构

每个MFT对象由MFT记录头和多个不同的属性组成。结构图示大致如下:

MFT记录头的结构

偏移 意义
0-3 签名,值为46 49 4C 45,即为FILE
4-5 更新序列号的偏移,在每个MFT对象所在的扇区尾,都会有2字节相同的标记值,用于保持一致性,被称为更新序列号
6-7 更新序列号的个数
8-F 日志序列号
10-11 序列号,第几个MFT对象(从1编号,备份$MFTMMirr的也为1)
12-13 硬链接数
14-15 第一个属性的偏移地址
16-17 标志,0:删除的文件,1:正常的文件,2:删除的目录,3:正常的目录
18-1B 此MFT对象的字节长度
1C-1F 此MFT对象分配的字节长度
20-27 基本文件记录中的文件索引号,只有在一个MFT对象无法完全存储一个文件时才使用,从0开始编号
28-29 下一个属性ID
2A-2B 保留
2C-2F 此MFT对象在MFT中的索引号(从0编号)
30-31 更新序列号,在每个MFT对象所在的扇区尾,都会有2字节相同的标记值,用于保持一致性,被称为更新序列号
32-33 更新数组1,如果数据在第一个扇区还没有完,但是结尾已经有更新序列号占了两个字节,就把本应该写在此处的两字节写在更新数组1处
34-35 更新数组2,与上同理,是数据在第二个扇区还没有完

举例

由BOOT区知MFT在2072扇区,所以MFT数据如下:

  • 其中红框偏移4-5处为更新序列号偏移,为30H处,所以为第二个红框处,其值为3A 00即更新序列号。在该扇区尾部即第三个红框处,也为更新序列号,要保持一致。
  • 偏移14-15处显示第一个属性偏移为38H,所以在偏移38H即红线处为第一个属性开始。
  • 2C-2F处显示为0,即索引号为0,表示该MFT对象对应的是一个元文件$MFT

属性的种类

属性类型(16进制) 描述
10 记录标准信息
20 属性列表:当一个文件需要多个文件记录时,用来描述文件的属性列表
30 文件名属性
40 对象ID
50 安全描述
60 卷名
70 卷信息
80 文件数据内容
90 索引(可以看做是文件夹)根属性
A0 索引分配树节点,当90属性存储不下使用
B0 MFT文件和索引的位图
C0 重解析点
D0 扩充属性信息
E0 扩充属性
F0 早期NTFS才有的属性
100 EFS加密属性

属性结构

每个属性可以分为两个部分:属性头和属性体

因为一个MFT对象空间有限,如果要MFT对象要记录的属性超过空间大小,剩下的部分就要在MFT之外的区域存储,存储采用簇流运行的方式。因此对以上属性又可以分为常驻属性,即优先保存在MFT区域中,和非常驻属性,即优先放到MFT区域外。

簇流是存放数据的区域
簇流运行是记录簇流具体在文件系统哪个位置的代码
簇流运行第一个字节的低四位表示:该字节后几个字节为一组,这一组表示簇流的大小
簇流运行第一个字节的高四位表示:该字节后几个字节为一组,这一组表示簇流的起始簇号(相对于当前簇流),如果起始簇号为负,表示下个簇流在这个簇流前面

常驻属性的结构如下:

偏移(相对于每个属性内) 意义
0-3 属性类型
4-7 属性的总字节数
8 0:常驻属性,1:非常驻属性
9 属性名的长度
A-B 相对于属性头的属性名的偏移
C-D 0001:压缩,4000:加密,8000:稀疏
E-F 属性ID
10-13 属性体的字节数
14-15 属性体相对属性的偏移,因为在属性头后可能有属性名
16 索引标志
17 保留
18- 属性体

非常驻属性结构如下:

偏移(相对于每个属性内) 意义
0-3 属性类型
4-7 属性的总字节数
8 0:常驻属性,1:非常驻属性
9 属性名的长度
A-B 相对于属性头的属性名的偏移
C-D 0001:压缩,4000:加密,8000:稀疏
E-F 属性ID
10-17 文件数据起始虚拟簇号,一定为00
18-1F 文件数据结束虚拟簇号
20-21 簇流运行的偏移地址
22-23 压缩的大小,2的幂次,为0表示没有压缩
24-27 保留
28-2F 属性体占用的字节数
30-37 属性体实际占用的字节数
38-3F 属性体的初始大小
40- 簇流运行信息

属性体

不同属性类型的属性体的结构不同

10属性的属性体

偏移(相对于每个属性体内) 意义
0-7 文件创建时间
8-F 最后修改时间
10-17 MFT修改时间
18-1F 最后访问时间
20-23 文件属性,1:只读,2:隐藏,4:系统,20H:存档,40H:设备,80H:常规,100H:临时,200H:稀疏文件,400H:重解析点,800H:压缩,1000H:脱机,2000H:未编入索引,4000H:加密
24-27 最高版本号
28-2B 版本号
2C-2F 分类ID
30-33 所有者ID
34-37 安全ID
38-3F 磁盘配额
40-47 更新序列号

接着上面例子的红划线处看,首先是属性头(绿线表示)。

偏移0-3(相对于属性内),即图中38-3B处值为10,表示属性类型为记录标准信息的属性
4-7处属性总字节数,刚好为红框框处
8处是0,表示为常驻属性
9处是0,表示没有属性名
A-B是24,表示相对于属性头的属性名的偏移,但是属性名又为0,说明属性头占24B,在属性头后直接为属性体。所以在14-15处可以看到属性体相对属性头的偏移也为24

接着是属性体
偏移20-23处(相对于每个属性体内),即图中偏移70-73处,值为6,表示是系统隐藏文件

30属性的属性体

偏移(相对于每个属性体内) 意义
0-3 父目录的参考号,即MFT对象序列号
4-5 保留
6-7 父目录的更新序列号
8-F 文件创建时间
10-17 文件修改时间
18-1F MFT的修改时间
20-27 文件最后修改时间
28-2F 文件分配大小
30-37 文件实际大小
38-3B 文件属性,1:只读,2:隐藏,4:系统,20H:存档,40H:设备,80H:常规,100H:临时,200H:稀疏文件,400H:重解析点,800H:压缩,1000H:脱机,2000H:未编入索引,4000H:加密
3C-3F 重解析点
40 文件名的长度
41 文件名的命名方式,00:文件名大小写敏感,字符\和空字符不能用,01:字符*/:<>\不能用,最后一个字符不能是.或空格,02:只能是大写字符,长度1-8,.是连接符,最后0-3个字符为扩展名,03:采用01或者02的命名方式
42- unicode编码的文件名

还是接着上面的例子看,10属性下一个是30属性,其属性头是划红线处,30属性也为常驻属性。
然后看属性体
偏移0-3处,即绿色划线处表示父目录的MFT对象索引号为5,而在前面知道索引号为5的元文件为根文件夹
蓝线处为文件分配大小和文件实际大小
偏移38-3B处,即图中阴影E8-EB处为6,表示是系统隐藏文件
偏移40处,即图中阴影F0处为4,表示文件名为4字符长,之后的偏移41处,表示文件命名方式
之后就是unicode编码的文件名了,一个字符由两字节表示,为字符$MFT

80属性的属性体

如果是常驻属性,则属性体为数据内容
如果为非常驻属性,则属性体为簇流运行

继续接着看,30属性后为80属性
偏移8处为1,表示为非常驻属性。
红线处为文件数据起始虚拟簇号(一般为0)和文件数据的结束虚拟簇号(值为20415,起始就是占多少簇)
偏移20-21处,即绿色划线处为簇流的偏移地址,为64,即蓝色划线处为簇流运行
其第一个字节的低四位为2,表示后面两个字节为一组,即C0 4F,表示簇流大小,为几个簇,值为20416(与上面的结束虚拟簇号相对应),扇区为2072+20416*8=165400
其第一个字节的高四位为1,表示再后面一个字节为一组,即03,表示簇流起始簇号,算出扇区正好为2072,也就是这个文件的数据就从这里开始(因为就是$MFT文件)

90属性的属性体

索引根节点

偏移(相对于索引根节点内) 意义
0-3 属性类型
4-7 校对规则
8-B 每个索引缓冲区的字节数
C 每个索引缓冲区的簇数
D-F 保留

索引头

偏移(相对于索引头内) 意义
0-3 第一个索引项的偏移,相对于属性体的偏移
4-7 索引项的字节数
8-B 索引项的分配字节数
C 0:根索引,1:索引分配
D-F 保留

索引项

偏移(相对于索引头内) 意义
0-3 文件的MFT对象序列号
4-5 保留
6-7 更新序列号
8-9 本索引项字节数
A-B 文件名属性体字节数(索引项从10到结尾字节数)
C-D 0:没有子节点,1:有子节点,2:最后一个索引项
E-F 保留
10-13 父目录的MFT序列号
14-15 保留
16-17 父目录的更新序列号
18-1F 文件创建时间
20-27 文件最后修改时间
28-2F MFT最后修改时间
30-37 最后访问时间
38-3F 文件分配大小
40-47 文件实际大小
48-4F 文件属性,1:只读,2:隐藏,4:系统,20H:存档,40H:设备,80H:常规,100H:临时,200H:稀疏文件,400H:重解析点,800H:压缩,1000H:脱机,2000H:未编入索引,4000H:加密
50 文件名长度
51 文件名的命名方式
52- 文件名

接着上面的例子,跳转到根目录对应的MFT对象区域,找到90属性,如图中阴影部分,分析可知其为常驻属性,属性头红色划线标记,属性名绿色划线标记,剩下为属性体

之后,蓝色括号部分为索引根节点,红框处为每个索引缓冲区的字节数,为4096,蓝色划线处为每个索引缓冲区簇数,为1

红色括号处为索引头,偏移4-7,即图中偏移为84-87处值为00 00 00 28,所以该索引项大小为28H(从索引头开始算,到阴影部分结尾)
偏移C处表示该索引项是索引分配,所以应该找后面紧接着的A0属性的属性体

A0属性的属性体

当文件夹中内容很少时,用90属性存,否则使用A0属性,属性使用簇流。
在其索引缓冲区包含一个索引头和多个索引项,索引项与90属性索引项相同

索引头结构

偏移 意义
0-3 标志,为INDX
4-5 更新序列号偏移
6-7 更新序列号与更新数组单位大小
8-9 日志文件序列号
10-17 本索引缓冲区的第几个簇(从0开始,有时候一个簇存放不下)
18-1B 索引项的偏移(相对于18位置)
1C-1F 索引项的大小
20-23 索引项的分配大小
24 0:叶节点,1:还有子节点
25-27 保留
28-29 更新序列号
2A 更新序列号数组

继续接着上面的例子看,数据如下图阴影处所示,红线处为簇流运行,其余部分为非常驻属性体。分析其簇流运行,起始簇号为00 E6 8B 即59019,大小为一个簇,可以找到其索引缓冲区

索引缓冲区如下
红框处为索引头,剩下的为各个索引项,只看第一个索引项,即阴影处
偏移0-3处为04,表示为元文件$AttrDef的MFT对象的索引项
8-9表示本索引项的字节数
10-13表示父目录的MFT序列号,为5,也就是根目录

参考

https://www.bilibili.com/video/BV1ia411F7av?p=1
https://www.ntfs.com/ntfs_basics.htm
https://blog.csdn.net/enjoy5512/category_6144112.html
基于NTFS文件系统的文件恢复程序的设计与实现 于天佐

posted @ 2022-04-26 21:52  启林O_o  阅读(830)  评论(0编辑  收藏  举报