← 返回博客

在不破坏运行中的 Windows 主机的前提下提取 $MFT

· 阅读 2 分钟

$MFT 位于每个 NTFS 卷的起始处,只要卷处于挂载状态,Windows 就一直对它持有独占锁。xcopy 会失败。Robocopy 会失败。朴素的 PowerShell Copy-Item 会失败,或者在某些配置下,悄无声息地产出一个大小看起来对、内部却已损坏的截断拷贝。你需要一个可以读取原始卷、绕过文件系统锁、并能从簇运行中组装出 $MFT 的工具。

实际中我信任三个方案。它们覆盖了我每周遇到的在线主机取证场景。

方案 1:KAPE,IR 的默认选择

如果你在做事件响应、且就在一台 Windows 主机上,答案是用 KAPE 加 MFT target。它一次性拉取 $MFT$MFTMirr$LogFile$UsnJrnl:$J$Boot$Secure:$SDS 和一小批相关文件,保留收集到的文件的原始时间戳,并写出一个整齐的目录树带去分析。

kape.exe --tsource C: --target MFT --tdest C:\triage --vss

--vss 是大家常忘的那个 flag。它告诉 KAPE 把源上每个 Volume Shadow Copy 中的 $MFT(以及该 target 的其它部分)也拉过来。更早的快照独立地有用,应当作为惯例一并采集。怎么处理它们见 Volume Shadow Copy 与 $MFT

KAPE 通过底层使用 RawCopy.exe 的原始卷读取器来应对文件锁问题。采集到的文件与取证镜像得到的内容逐位相同。除非有特别理由,否则就用它。

方案 2:FTK Imager,GUI 备选

FTK Imager 至今仍是采集用的标准免费 GUI 工具。当主机上没有 KAPE,而你只想抓一次 $MFT 就走时,就用它。流程:

  1. FileAdd Evidence ItemPhysical Drive(仅当你从远程共享或挂载镜像工作时才使用 Logical Drive)。
  2. 选择磁盘并让它枚举出卷。
  3. 在左侧树形结构中展开 NTFS 卷的根。$MFT$MFTMirr$LogFile$Volume$AttrDef$Bitmap 以及其它元数据文件即使资源管理器把它们隐藏掉,也会显示在那里。
  4. 右键 $MFTExport Files。立刻做哈希(SHA-256)。

FTK Imager 通过映射物理设备并自行解析 NTFS 来读取被锁定的卷。导出的就是磁盘上真实的文件,包含 fixup 数组等一切。

同一套流程也能读取 .dd.E01.AFF4 镜像。如果你已经有离线镜像,把它作为证据挂载即可走相同的导出路径。

方案 3:当什么都装不上时,fsutil 加原始读取

在不允许投放 KAPE 或 FTK Imager 的强化主机上,内置的 fsutil 命令可以告诉你 $MFT 在哪儿:

fsutil file queryextents C:\$Mft

输出是一系列(Virtual Cluster Number、Logical Cluster Number、length)三元组。要把它变成文件,就在每个 LCN 上读取原始卷并拼起来。带有对 CreateFile(\\.\C:, GENERIC_READ) 的 P/Invoke 的 PowerShell 可以胜任;GitHub 上任何一个小型 PowerShell 原始读取模块也可以。Joakim Schicht 的 RawCopy.exe(与 KAPE 内部使用的代码相同)是最简单的独立工具。

这是一块积木,不是最终答案。当策略禁止加载其他工具链时再用。

大家常错的地方

Copy-Item -Force 拷贝。 有时它确实成功,你会得到一个文件。但这个文件只是 Windows 对一个已打开句柄做常规 ReadFile 调用所返回的内容,在多数构建上它并不是真正的 $MFT。永远用 fsutil file queryextents 核对大小是否对得上。

忘了 $MFTMirr 和事务日志。 $MFTMirr 是 16 条记录的保险。事务日志($LogFile,以及 $Extend\$RmMetadata 下每个资源的 $TxfLog 文件)携带着采集时可能尚未写入 $MFT 的操作。请一并采集。KAPE 免费替你做这件事。

不取 USN journal。 $UsnJrnl:$J 对时间线重建至关重要(见 把 journal 与 file table 配对)。它会轮转,意味着等两天再回来取就会丢证据。第一次就取下来。

在不用 VSS 的情况下从在线系统采集。 在线的 MFT 在卷层级上是一致的(NTFS 有日志),但如果主机繁忙,你可能会得到一份 $MFT 和一份 $UsnJrnl,它们之间相差几十秒,因为 MFT 是先被读的。先创建 VSS 快照,再从快照读取两者。快照把它们冻结在同一时刻。

信任所采集文件上的错误时间戳。 导出的 $MFT 上的"modified"时间是你采集工具设置的。对字节做哈希,把哈希和采集时间写入一份单独的日志,并在所有地方引用该日志。

我实际用的基于 VSS 的采集

当我在在线主机上、想要在某个干净时间点拿到 $MFT 加 journal 加日志时,这是我的片段:

vssadmin create shadow /for=C:

从输出里读出 Shadow Copy Volume Name,然后把该路径作为你偏好工具的源:

robocopy "\\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN" "D:\triage" "$MFT" "$MFTMirr" "$LogFile" "$Extend\$UsnJrnl:$J" /R:1 /W:1

Robocopy 能从 VSS 设备路径读取,因为快照被作为一个独立卷挂载,没有在线的独占锁。文件落盘后立刻做哈希;如果该快照是你创建的应当删除(vssadmin delete shadows /shadow={GUID}),然后离开。

这是我知道的、不需要安装任何 Windows 默认之外内容的最干净的在线采集方式。

从磁盘镜像读取

如果你已经有 .dd.E01 镜像,那就完全跳过锁的问题。以只读方式挂载镜像(xmountewfmount,对支持 VSS 的镜像用 vshadowmount),或者使用直接消费镜像的解析器。$MFT 总位于从分区偏移 0 的引导扇区中得到的 MftStartLcn 处。Sleuth Kit 的 icat -o <partition_offset> image.dd 0 即可提取该文件。Inode 0 永远是 $MFT

分析前的校验

采集完毕立刻对文件做哈希(SHA-256)。在解析之前再做一次。比大家承认的更频繁地会出现不匹配,通常是采集中途的磁盘压力,或拷贝工具默默重试部分读取所致。

然后做一次结构性检查。解析前十条记录,确认每条都有 FILE 签名,确认 0 号记录就是 $MFT 自身且其 $DATA runlist 自引用,确认 1 号记录是 $MFTMirr,确认 5 号记录是根目录、具有 $INDEX_ROOT 属性。任何一项不符,说明这次采集不合格,必须重做。MFTECmd 与 mft_dump 在文件被破坏时都会抛出警告;别屏蔽它们。

延伸阅读

  • Eric Zimmerman,MFTECmd 与 KAPE。KapeFiles 仓库定义了规范的 MFT target,值得一读以理解会被采集什么。
  • Joakim Schicht,RawCopy。多数在线 MFT 采集工具底下的原始卷读取器。
  • Microsoft,Volume Shadow Copy Service。你做干净采集时所依赖的快照语义参考。

外部资源