← 返回博客

Master File Table(MFT):NTFS $MFT 详解

· 阅读 4 分钟

在磁盘上写作 $MFTMaster File Table(主文件表),是 NTFS 用来追踪卷上每个文件和目录的索引。它是每个 NTFS 分区上第一个用户可见的文件,而卷上的其他每一个文件 —— 包括这张表本身 —— 都在其中至少拥有一条记录。读取 $MFT 正是取证工具回答以下问题的方式:Windows 已不再承认存在的文件,究竟在何时被创建、叫什么名字、内容是什么、最后由谁触碰过。

本指南是一份完整参考。涵盖了这张表是什么、记录的布局方式、一条记录能承载哪些属性、表头那一小组保留的系统文件、「Windows cannot recover the master file table」到底意味着什么,以及如何使用本站的解析器自己读取 $MFT

什么是 Master File Table?

Master File Table 是一个名为 $MFT 的单一文件,位于每个 NTFS 卷起始附近的固定位置。NTFS —— New Technology File System —— 在 1993 年随 Windows NT 3.1 一同发布,取代 FAT 成为 Windows 的默认文件系统。与维护一张小型分配表、将文件名存放在目录条目里的 FAT 不同,NTFS 几乎把每个文件的全部元数据都塞进同一张结构化的表里:$MFT

表中的每一行都是一条 记录,大小正好是 1024 字节。每条记录描述一个文件或一个目录。记录里保存文件的名称、时间戳、DOS 风格的标志位、其数据所在的磁盘簇列表、安全描述符,以及若干其他属性 —— 全部以一小袋带类型字段的形式编码。

这一设计带来两个重大影响:

  1. 所有元数据集中在一处。 一次对 $MFT 的查找就足以枚举卷上的每个文件。取证和恢复工具都依赖这一点;杀毒扫描器与索引服务同样如此。
  2. 被删除的文件留下完好的元数据。 当 NTFS 删除一个文件时,只会清掉记录头里的一个比特位,并把文件的簇标记为空闲。记录的其余部分 —— 名称、时间戳,通常还包括数据 run —— 在该记录槽被重新使用之前都会保留原样。

缩写 MFT 代表 Master File Table。你会看到它被写作 MFT、$MFTthe MFT,指的都是同一种磁盘结构。

$MFT 在磁盘上的布局

当 NTFS 格式化一个卷时,会在分区开头附近预留一块称为 MFT zone 的区域。卷偏移 0 处的引导扇区包含一个指针(MftStartLcn 字段),指向 $MFT 的第一个簇。表的前 16 条记录被保留给 NTFS 的元数据文件(见下文);记录 0 是表自身的条目,回指其自身的簇。

每当需要更多记录时,$MFT 就会通过扩展到自己的预留区中而增长。如果在该预留区被耗尽之前卷就满了,Windows 会缩小这块区域以腾出空间给用户数据,这就是为什么在老旧的文件系统上,严重碎片化的 $MFT 是常见症状。

前几条记录的备份保存在另一个文件 $MFTMirr 中,通常被放置在卷的中部。如果 $MFT 本身被损坏,NTFS 会使用 $MFTMirr 来引导恢复 —— 这正是下文所述「Windows cannot recover the master file table」错误背后的机制。

FILE 记录的结构剖析

每条 MFT 记录都以四字节的 ASCII 签名 FILE 开头。(损坏的记录会改为使用 BAAD —— 这是 chkdsk 刻意写下的「墓碑」。)签名之后是一个固定的头部,再后面是一段长度可变的属性流。

记录头部包含:

  • 签名 —— 有效记录为 FILE,chkdsk 无法修复的记录为 BAAD
  • 更新序列号(USN)与 fixup 数组 —— 一个微型校验技巧,让 NTFS 能够检测撕裂写入。记录中每个 512 字节块的最后两字节会被替换为 USN;原始字节则被保存在 fixup 数组中。读取时,NTFS 验证 USN 并将原始字节还原。
  • 日志序列号 —— 指向 $LogFile,用于崩溃恢复。
  • 序列号 —— 每次该记录被重新使用时递增。与记录号组合后构成一个 64 位的 file reference,唯一标识某个文件的某次具体「化身」。
  • 硬链接计数 —— 指向该记录的 $FILE_NAME 属性数量。
  • 标志位 —— 其中最重要的是 bit 0,即 IN_USE。该位被清零表示已删除。
  • 基础文件记录引用 —— 对于属于表中其他位置的某条基础记录的扩展记录,此字段非零。

头部之后就是各个属性。每个属性都有自己的简短头部(类型、长度、resident/non-resident 标志、名称(如有)),后面跟着数据。属性没有固定顺序,但按惯例 $STANDARD_INFORMATION 位于最前,$DATA 位于最后。

当一条记录的空间不够用时 —— 碎片过多、ADS 过多、文件名异常长 —— 就会长出一个 $ATTRIBUTE_LIST 属性,指向表中其他位置的一条或多条 扩展记录。解析器必须沿着这条链跟踪下去,才能拼装出完整的文件。

$MFT 中存储的文件属性

这是关键词 「what file attributes are stored in the master file table」 背后最常见的搜索。下面是 NTFS 属性类型的完整列表,附带十六进制代码:

| Type | Hex | 用途 | |------|-----|------| | $STANDARD_INFORMATION | 0x10 | 四个时间戳(创建、修改、访问、MFT 修改)、DOS 标志、属主 ID、安全 ID、USN。 | | $ATTRIBUTE_LIST | 0x20 | 当文件属性超出单条记录时,指向扩展记录的指针。 | | $FILE_NAME | 0x30 | 文件名、父目录引用、已分配大小与真实大小,以及第二组四个时间戳。一个文件可以有多个 —— 每条硬链接一个,8.3 短名一个。 | | $OBJECT_ID | 0x40 | 128 位对象标识符,由 Distributed Link Tracking 服务使用。 | | $SECURITY_DESCRIPTOR | 0x50 | 旧式的逐文件 ACL。现代 NTFS 将 ACL 集中存放在 $Secure 中,通过 $STANDARD_INFORMATION 里的 ID 引用。 | | $VOLUME_NAME | 0x60 | 仅出现在记录 3($Volume)。保存卷标。 | | $VOLUME_INFORMATION | 0x70 | NTFS 版本号,dirty 标志。 | | $DATA | 0x80 | 文件内容。对于极小的文件为常驻;否则为非常驻(一组簇运行)。一个文件可以携带多个 $DATA 属性 —— 未命名的那个是主数据流,命名的则是 备用数据流。 | | $INDEX_ROOT | 0x90 | B+ 树的根。被目录($I30)、reparse point 索引以及其他索引结构使用。 | | $INDEX_ALLOCATION | 0xA0 | 大型索引的非常驻延续部分。 | | $BITMAP | 0xB0 | $MFT 自身或大型目录的分配位图。 | | $REPARSE_POINT | 0xC0 | 符号链接、junction、挂载点、OneDrive 占位符。 | | $EA_INFORMATION / $EA | 0xD0 / 0xE0 | 源自 OS/2 时代的扩展属性。在现代 Windows 上罕见。 | | $LOGGED_UTILITY_STREAM | 0x100 | EFS 加密元数据($EFS)、TxF 事务数据。 |

一条记录至少始终携带 $STANDARD_INFORMATION、一个 $FILE_NAME 和一个 $DATA。其余都是可选的,由具体功能决定。

常驻数据 vs 非常驻数据

在真实卷上,大多数 $DATA 属性都是 非常驻 的:属性头中携带一份紧凑的 cluster runs 列表(起始 LCN 加长度,反复出现),而文件的字节位于磁盘上的别处。属性头本身很小。

如果文件足够小 —— 通常在扣除其他属性后小于约 700 字节 —— NTFS 就会把字节内联存放在记录中。这就是 常驻数据,也是取证工作中最有用的物件之一:几周前被删除的一个小文本文件,其内容仍可能逐字节地保存在某条已释放的 $MFT 记录中。深入阅读见 resident-data

前十六条记录里的 NTFS 元数据文件

$MFT 的前 16 条记录被保留给 NTFS 自身的簿记文件。它们以 $ 开头,以免与用户文件名冲突。值得了解的几个:

| 记录号 | 文件 | 含义 | |--------|------|------| | 0 | $MFT | 表自身。 | | 1 | $MFTMirr | $MFT 前几条记录的备份。 | | 2 | $LogFile | 用于崩溃后撤销或重放未完成操作的事务日志。 | | 3 | $Volume | 卷标和 dirty 标志。 | | 4 | $AttrDef | 有效属性类型的 schema。 | | 5 | . | 根目录。 | | 6 | $Bitmap | 卷上每个簇一比特;追踪分配情况。 | | 7 | $Boot | 引导扇区的副本。 | | 8 | $BadClus | 稀疏文件,其 run 指向文件系统标记为坏簇的每个簇。 | | 9 | $Secure | 安全描述符的集中存储。 | | 10 | $UpCase | 用于大小写不敏感名称比较的 Unicode 大写映射表。 | | 11 | $Extend | 一个目录,包含较新的系统文件:$ObjId$Quota$Reparse$UsnJrnl$RmMetadata。 |

变更日志 $UsnJrnl(位于 $Extend 下)在取证中尤为有用 —— 它记录了卷上的每一次元数据变更,可与 $MFT 互补,用于时间线重建。参见 usn-journal

当 $MFT 出问题时:损坏与「Windows cannot recover the master file table」

错误信息 「Windows cannot recover master file table. CHKDSK aborted」 出现在 chkdsk 既无法读取 $MFT、也无法回退到 $MFTMirr 的时候。当你看到这条消息时,NTFS 已经尝试过自己的内置自修复并失败了。

常见根因:

  • 物理介质故障。 MFT zone 内的坏扇区会让读取返回乱码。SMART 数据通常能佐证。
  • 元数据密集型操作期间的突然断电。 事务日志一般能回滚这类问题,但已损坏的 $LogFile 会让回滚失效。
  • 驱动或筛选器层的损坏。 行为异常的磁盘加密栈、文件系统微筛选器或有 bug 的存储驱动可能写出不一致的记录。
  • 恶意覆写。 擦除器和一些勒索软件家族会故意在 $MFT 上涂抹,以增加恢复难度。

从取证角度合理的应对方式是:

  1. 立即停止对该卷的所有写入。 之后每一次写入都会降低恢复成功率。
  2. 对磁盘做镜像,用 FTK Imager、ddddrescue 写入一个已知良好的目标。校验哈希。
  3. 在镜像上工作,而不是在原盘上。试试 testdiskR-Studio,或通过直接对卷做签名扫描寻找 FILE 记录的手工解析 —— 即便磁盘上指向 $MFT 的指针已不复存在,记录本身通常仍然可被识别。
  4. 只有当目标是让卷重新上线、而非恢复数据时,才在镜像上运行 chkdsk /f

在可写卷上运行 chkdsk /b 可以清除坏簇标记,但它也可能丢弃它无法理解的记录。仅在你已经取得镜像、并且认定可用性优先于取证保真度之后,才在原盘上运行它。

如何读取 $MFT

你有三种现实的选项:

  • MFTECmd(Eric Zimmerman 出品) —— Windows 下的 CLI,输出大多数时间线工具所期望的 bodyfile 风格 CSV。事实上的事件响应人员标准工具。
  • omerbenamram/mft —— 一个 Rust crate 与 CLI。本站使用的同一款解析器,适合脚本化分析或嵌入到更大的流水线中。
  • 本站的浏览器解析器 —— 把 $MFT 拖到主页上,它会在你的浏览器里运行同一个编译为 WebAssembly 的 Rust 解析器,完全本地处理。不会上传任何内容。适合无需安装即可快速阅读的场景,或者政策禁止把证据发送到云端服务时。

如果你想看三者的具体优缺点对比,见 mft-parser-tools。基于已解析 $MFT 的实用工作流,见 build-mft-timelinedeleted-filesextracting-mft

常见问题

MFT 是什么的缩写?

MFT 是 Master File Table 的缩写。在磁盘上也写作 $MFT,因为在 NTFS 中,美元符号是元数据文件名的前缀。

Master File Table 是干什么用的?

它是 NTFS 用来定位卷上每个文件和目录的索引。每个条目存储该文件的名称、时间戳、安全信息、属性以及其数据在磁盘上的位置。

Master File Table 中存储了哪些文件属性?

每条记录至少携带 $STANDARD_INFORMATION(时间戳、DOS 标志)、$FILE_NAME(名称及第二组时间戳)与 $DATA(文件内容或指向其的指针)。根据文件不同,记录还可能携带 $ATTRIBUTE_LIST$OBJECT_ID$SECURITY_DESCRIPTOR$INDEX_ROOT$INDEX_ALLOCATION$BITMAP$REPARSE_POINT$EA$LOGGED_UTILITY_STREAM。完整参考见上方的属性表。

Master File Table 有多大?

每条记录 1024 字节。默认情况下,该表为自己保留约 12.5% 的卷空间(即 MFT zone),但只会实际占用所需的空间。一个有百万级文件的卷,$MFT 大约为 1 GB。

$MFT 和 $MFTMirr 是一回事吗?

不是。$MFTMirr$MFT 前几条记录的部分备份,被放置在磁盘的别处,以便在主表头部损坏时让 NTFS 能够引导恢复。

如何修复损坏的 Master File Table?

先对磁盘做镜像。然后要么对镜像运行 chkdsk /f(速度快,可能丢弃部分记录),要么使用能够扫描 FILE 签名并从原始簇重建表的恢复工具(速度慢,但保留更多证据)。在做镜像之前,切勿对原始卷运行 chkdsk

我能在 Linux 或 macOS 上读取 $MFT 吗?

可以。$MFT 只是一个普通文件。任何接受原始 $MFT dump 的解析器都能在任意操作系统上工作 —— omerbenamram/mftanalyzeMFT、本站的浏览器工具皆可。你只在需要从已挂载的活动卷中 提取 文件时才需要 Windows。

外部资源