文件系统
- 文件系统就是对数据存储管理的一种机制
- 常见的文件系统如 NTFS、FAT32、exFAT 等,每种文件系统都有不同的管理方式
- NTFS、FAT32、exFAT 文件系统的第一个扇区叫作 DBR 系统引导扇区
FAT32 文件系统的结构
DBR | 保留区 | FAT1 | FAT2 | 数据区 |
DBR 的数据结构
概念
- 扇区:扇区是硬盘读写的基本单位,一般情况下每扇区的大小是 512 字节。在硬盘中每个扇区都有自己的编号,从零开始编号。
- 簇:文件系统中用簇来做数据存储的单位(簇大小是 2 的整数次幂,最大是 128 扇区每簇)
- FAT 表:文件分配表( File Allocation Table )用来描述文件系统内存储单元的分配状态及文件内容的前后链接关系的表格
- 根目录的起始簇号:也是数据区的开始位置(一般为 2 号簇)
FSINFO 扇区的数据结构
在 FAT32 的保留区中除了 DBR 还有个 FSINFO 信息区,用来记录文件系统中空闲簇数和下一个可用的簇号
FAT 表的作用和特点
FAT 表
- 文件分配表( File Allocation Table )用来描述文件系统簇的分配状态及文件内容的前后链接关系的表格
- 每个 FAT 表项占 4 个字节,(因为每个字节有 8Bit,所以 FAT 表项有 32Bit ,文件系统名 FAT32 就是这么来的) 所以每个扇区有 128 个 FAT 表的表项
- 0 号表项 是“ F8FFFF0F”, 可以当做是 FAT 表的签名标志
- FAT 表从 2 号表项开始记录,数据区的每个簇号都有一个 FAT 表项对应
- 每个 FAT 表项记录着文件或目录的下一个簇号
- 每个 FAT 表项记录的簇数大多是连续的,如果不是连续的就会产生碎片
- FAT2 是 FAT1 的备份(FAT2 的起始扇区号=FAT1 的起始扇区号+FAT 表大小)
- 用 “FFFFFF0F”来表示文件或目录的结束簇号,文件的结束簇就是 “FFFFFF0F”标记位置的簇号 -1(就是列数*行数(行数不超过 4,因为每个表项占 4 个字节))
- 用“FFFFFFF7”来表示坏簇
根目录
根目录的位置计算:FAT 的起始扇区号 + FAT 表的大小 * 2(绝大多数情况下根目录都是 2 号簇)
- 目录项分为短文件名目录项和长文件名目录项
- "."目录项表示这个目录本身,".."目录项表示这个目录的父级目录
- 如果文件名不到 8 个字符,用 0x20 填充
- 如果文件名超过 8 个字符时则会被截断,提取前 6 个字符再加“ ~1” (如果有同名目录项,这个数值会加 1 ),然后再加上扩展名
短文件名目录项数据结构
解释
文件名的 ASCII 码
文件名的 ASCII 码指的是红框框出来的部分[31 32 33 20 20 20 20 20 ],很明显这是一个短文件名,不足的部分都用 20 填充了,后面三位[20 20 20]代表文件后缀名,因为这是一个目录,所以是三个 20
这是一个长文件名,因为字节数超过了 8 个所以后面的用~1 代替了,后面的 3 个字节显示的是 TXT,说明这是一个文本文件
文件属性
接着跟着文件后缀名后面一个字节的(用橙色框框出来的)就代表了文件属性,详见上表
文件时间(不用记)
再往后面几个字节保存的就是关于文件时间的内容,这里的精度是毫秒,只不过软件显示不出来
创建时间
用绿框和蓝框标出来的代表文件创建时间,这个时间可以在数据解释器里查看(在数据解释器里勾上 DOS Date 选项,这里要看的话也要把后面的蓝色框选上)
最后访问时间
黑色框就表示了文件的最后访问时间,由于数据解释器的 DOS 是 32bit 的原因需要选择 4 位值才能正确读数,但是记录时间的值只有两位,所以要选择蓝色框内的两位值,蓝色和黑色框内的值是完全相同的,我们选中蓝色框内的值的时候,数据解释器就能正确读取最后访问时间的值了
最后修改时间
紫色框表示的是最后修改时间,因为只有两位,所以不能用数据解释器查看
起始簇
红色表示的是起始簇的高 16 位,橙色的是起始簇的低 16 位
当高 16 位被清空时(1A-1B)起始簇的低 16 位,存储着文件的真实簇号,如果高 16 位还未清空就需要加上高 16 位的值才是真实的簇号
起始簇号 = 低 16 位的数值 + (高 16 位的数值*65536 )
文件大小字节数
在最后四个字节(蓝框)表示了文件的真实字节数,因为这一项可以表示的最大值为[FF FF FF FF],最大字节数为 4,294,967,295,转换以下大约就是 4GB,所以 FAT32 文件系统最大只能存 4GB 的文件
注意
- 一个长的文件,他如果有一个长文件名,那么同时也会有一个短文件名,一般情况下只需要看它的短文件名就可以获得我们想要的信息
- 一个文件的目录 32 个字节为一组,所以如果要搜索来找文件的话偏移要填 32=0
长文件名目录项数据结构
当文件名超过 8 个字节时,就需要用长文件名目录项来存储文件名。长文件名目录项的 0x0B 位置的标志一定是 0x0F,目录项是用 Unicode 编码存储文件名的。
解释
目录项序号
在之前的短文件目录项数据(黑框)的上面,用红框标出来的就是长文件名的目录项序号,从下往上依次增大(每 32 位为一组),到最后一个目录项(序号的最后一个)时,前面那个数为 4,来表示最后一个目录项
文件属性
长文件名的每一项都有长文件名的标志 OF
文件名
画框的部分就是文件的文件名,都是用 Unicode 来编码的,绿色框是文件名的第 1-5 个字符,蓝色是 6-11 个字符,紫色是 11-12 个字符
其他
- 文件名如果有英文字母,需要先转成大写字母再转成 ASCII 编码。
- 文件被删除时,其目录项的第一个字符被修改成 0XE5 。
- 算出文件的起始簇号后跳转到对应的簇,选择关于文件的所有数据,
右键-编辑-复制选块-至新文件
,这样就是手工提取文件 - 像这种数据结构在子目录里也是同样适用的
- 目录项 0C 位置第 5 位二进制位如果是 1,那么扩展名小写,第 4 位二进制位如果是 1,那么文件名小写
用 FAT 表找出目录的下一个簇
当目录下有很多个文件时,此时一个簇肯定存不下这些文件目录数据,此时计算机就会再用一个簇来记录,但这两个簇往往是不连续的,此时就需要通过 FAT 表来定位目录的下个簇是第几号簇
在 FAT 表中,看到第三个表项,如果第三个表项不是"FFFFFF0F",那就说明这一项就是根目录的下一个簇号,后面的簇就用这个簇号*4 得到偏移量,再点击跳转到偏移量(注意这里要换成 10 进制),以此类推就可以找到所有的簇
找出根目录下的子目录
当根目录被损坏时,就无法定位到下面的文件夹,此时在查找 16 进制数值里输入
[2E2E2020202020202020203F3F3F3F3F3F3F3F3F00003F3F3F3F],然后勾选通配符3F
,512=32,等待全部都扫完就可以找到根目录下的子目录了。原理是这个其实是每个父级目录记录的数据,根目录下面的文件夹的父级目录都是根目录,所以直接搜索父级目录的 16 进制数就可以搜出来
- 每个文件夹的最前面两个目录项,一定是“ 。” 和“ ..” 目录项,分别表示子目录本身和父目录。
- 在根目录下的文件夹 父目录的簇号是 0
- 在别的文件夹里的文件夹,它的父目录就是父目录文件夹本身簇号
FAT32 中文件创建、删除和格式化
创建文件
创建一个文件时做了哪些操作
- 新建一个 txt 的空文档 ,只是多了一条目录项,因为此时文档里面还没有数据
- 给 txt 文档增加内容时 1 号扇区文件系统的空闲簇号减少,下个可用簇改变
- FAT1、FAT2 会增加一个 FAT 表项
- 数据区的数据改变
手工创建文件
依照短文件名目录项数据结构里的解释,来依次填写数据就可以了,要注意下一个可用簇号,填完了之后要去 FAT 表里加一个 FAT 表项
步骤:
- 新建一个目录项
- 给数据区的内容赋值
- 给 FAT1 表相应的 FAT 表项标记簇已用
删除文件
删除文件到回收站
- 1 号扇区的空闲簇号 -1,下个可用簇向下移了一个簇
- FAT1 和 FAT2 多了一个 FAT 表项
- 文件目录项第一个字节变成 E5
- 回收站的目录里 多了两个目录项
- 数据区多了一个配置文件的内容
在回收站里清除
- 1 号扇区空闲簇数增加,下个可用簇号改变
- FAT1 和 FAT2 相应的表项清空
- 回收站的子目录里面的相应的目录项第一个字节变成 E5
按 shift 直接删除文件
- 1 号扇区的空闲簇号变大,下个可用簇号改变
- FAT1 和 FAT2 会释放相应的 FAT 表项
- 对应目录项的第一个字节改成 E5
有高位簇的文件删除
- 1 号扇区空闲簇数和下个可用簇号改变
- 文件对应的 FAT1 和 FAT2 的 FAT 表项清空
- 目录项的第一个字节变成,高位簇被清零
恢复被删除的文件
软件恢复
在目录浏览器中勾选列出曾经存在过的项目
,然后找到被删除的文件,右键-恢复,出现的对话框选是或否都可以。恢复出来的文件第一个字符会变成下划线,因为被删除的文件第一个字节会变成 E5,而 E5 就是下划线
手工恢复
在根目录的扇区下可以用肉眼看一下第一个字节是不是 E5,是的话在对着看一下文件名是不是要恢复的那一个,然后根据高 16 位和低 16 位的数来定位到该文件的簇号,最后框选该文件的全部数据右键至新文件就可以了(可以先定位到文件的头部,再根据文件的字节数来跳转偏移数定位到文件的尾部,这里偏移要换成 10 进制)
恢复有高位簇的文件(手动计算被删除的高位簇)
先获取到文件的低位簇,然后用这个数 +65536(这里是簇号),一直试,看到有数据的看看文件头是不是要找到文件,最后就可以提取出来了
剪切文件
剪切到别的盘
- 1 号扇区空闲簇数和下个可用簇号改变
- 文件对应的 FAT1 和 FAT2 的 FAT 表现清空
- 目录项的第一个字节变成 E5
- 目录的项的高位簇被清零
剪切到别的文件夹
- 将原先的目录项第一个字节标记成 E5
- 在剪切后的子目录里生成一个目录项
格式化
- DBR 里面的参数改变
- 1 号扇区里面的参数改变
- FAT1 和 FAT2 被清空
- 根目录也被清空,如果有卷标,那么会有一条卷标目录项
恢复格式化
虚拟子目录
方法的话跟用 FAT 表找出目录的下一个簇是一样的,因为格式化没有动数据区的数据,所以文件其实是还在的,只不过 FAT 表项和根目录的目录项被清空了,所以我们搜索根目录下的所有子目录,在查找 16 进制里输入[2E2E2020202020202020203F3F3F3F3F3F3F3F3F00003F3F3F3F]
然后找出所有子目录之后,转到根目录的扇区那里,虚拟出对应数量的文件夹,然后填写对应的簇号(高位簇和地位簇)
手工提取根目录下的文件
可以搜索文件头来定位文件,比如说 zip 的文件头[50 4B 03 04],就可以直接搜索这个文件头来定位文件,如果不知道文件的文件头的话,可以新建一个对应的文件,然后打开这个文件看文件头
手工计算 DBR 的参数
当查找出来的子目录的簇号对应的扇区号和当前扇区号不同,说明 DBR 里的参数已经被改了,此时就要修改 DBR 中的参数
此时可以算一下原来的簇大小,如果说搜出来根目录下的子目录有两个及以上的话,就可以用大的子目录扇区号-小的子目录扇区号除以两者簇号相减。比如说第一个子目录的簇号是 3,扇区号是 40976,第二个子目录簇号是 5,扇区号是 41008,就用 41008-40976=32/(5-3)=16,先相减得到相差的扇区号,再除以相差的簇号就是一个簇的扇区数
再计算一下根目录的起始扇区号,就是子目录的扇区号-(簇号 -2)*簇大小,比如 40976-(3-2)*16=40960(因为根目录是在二号簇的)
然后改动 DBR 扇区中一个簇的大小(0 号扇区第一排倒数第 3 位(0D),注意用数据解释器中 8bit 那一栏插入)和根目录起始扇区号,再改 FAT 表大小(24-27),算法是(根目录起始扇区号-FAT 表起始扇区号)/2(原理是根目录的起始扇区号=FAT 表起始扇区号+FAT 表大小*2)
取巧方法
在管理里新建一个和原来盘一样大小的虚拟磁盘,然后直接复制新磁盘里的 DBR 数据,再和扫出来的子目录对扇区号,如果不对的话就格式化这个新磁盘,把分配单元格大小更改一个数值,然后再复制,就这样一次一次试就可以试出来
磁盘未被格式化的恢复
当打开磁盘显示磁盘需要格式化的时候或者在管理里显示这个盘的格式为 RAW,代表系统已经不能识别到这个盘的文件格式,此时就可以用 winhex 来恢复里面的数据
利用备份 DBR 恢复
FAT32 文件系统的备份 DBR 在 6 号扇区,此时只要把这个扇区里的内容直接复制到真正的 DBR 扇区里就行了
用格式化的参数恢复
当 winhex 都识别不到这个盘的格式的话,就代表这个盘的备份 DBR 也已经损坏了,此时就可以使用创建一个虚拟磁盘的方法了,把新建的虚拟磁盘的 DBR 里的数据复制到盘里的 DBR 扇区,这样就可以显示出文件了(如果不行就多格式化多试几次),直接右击恢复就行了
有时候 FAT1 没有数据,就要用 FAT2 里的数据,如果 FAT2 也被损坏的的话,就用 FAT2 残留的数据赖倒推 FAT 表
手工计算 DBR 的参数
这一个和前面那个"手工计算 DBR 的参数"是类似的,先找子目录算,然后填入 DBR,这里 DBR 要新建一个虚拟磁盘,把 DBR 数据复制过来
利用 FAT 表算出簇大小
当根目录下没有子目录的时候,就要利用 FAT 表来恢复了。首先要搜索 FAT 表的头[F8 FF FF 0F],搜出 FAT1 和 FAT2 后记下两个表的扇区号,用 FAT2 扇区号-FAT1 扇区号就是 FAT 表的大小,然后用这个数加上 FAT2 的扇区号就是根目录的位置了。因为 FAT1 和 FAT2 是一样的,所以大小也是一样的,用 FAT2 的位置加上 FAT 表的大小就是根目录的位置。
然后算一下有多少个 FAT 表项,用 FAT 表大小乘 128,再用总扇区数减去根目录的扇区号算出扇区数,用这个扇区数除以 FAT 表项就是簇大小了(这里有可能算出来的是小数,要四舍五入到 2 的 n 次方的数(1,2,4,8))
((总扇区数-根目录扇区号)/(FAT表大小)*128=簇大小)
文件或目录损坏的原因和恢复方法
windows 打开一个盘、目录或文件提示文件或目录损坏,这种情况下一般是 FAT 表损坏,如果是盘打不开了,那就大概率是 FAT 中根目录的 FAT 表项清除了,只需要在 3 号 FAT 表项填上 FFFFFF0F 就可以了,如果是文件夹或目录的话也大概是这个问题,只需要修复对应的 FAT 表项就行了。有一种更简单的方法就是直接从 winhex 里恢复。
文件名变乱码的原因和修复方法
当一个文件夹的文件名变成乱码,数据区也变成乱码的时候,这个时候要搜索这个文件夹下的所有子目录,具体方法的话和前面的"找出根目录下的所有子目录"方法是一样的,只不过这里要填写这个文件夹的簇号(用文件夹所在的扇区数算),比如说以前在根目录下要查找的 16 进制数为[2E2E2020202020202020203F3F3F3F3F3F3F3F3F00003F3F3F3F0000],现在的话就要把文件夹对应的高位簇和低位簇给填进去(这里要填的话注意把算出来的 16 进制数从后往前一个字节一个字节的写进去,或者把 10 进制数写进数据解释器中自动转换),找到所有子目录之后再记一下他们所在的簇号,用虚拟子目录的方法把这些文件夹全部恢复
注意这样的方法还是只能恢复文件夹下的文件夹中的文件,文件夹下的文件恢复还是要搜索对应的文件头