← 返回博客

Volume Shadow Copy 与 $MFT:每一份快照都是被冻结的 MFT

· 阅读 2 分钟

多数分析师把 Volume Shadow Copy 当成 Windows 的备份机制。其实它也是一座取证金矿——因为每一份快照都包含被拍下那一刻的完整、冻结的 $MFT 副本。一台有五份快照的工作站就给你六次对文件系统的独立观察(今天加上五个历史时点)。每一次都由不同代码路径签名,每一次在不同时间被写下。它们彼此之间的 diff 就是你能拿到的、最接近"卷如何变化的连续记录"的东西。

这篇文章讲怎么用它。

VSS 捕获什么

Volume Shadow Copy Service 对 NTFS 卷做时间点快照。每份快照是写时复制的增量:当在线卷上的某个块即将被修改时,原值会先被保留到 shadow copy 中。快照如实反映创建瞬间的卷,包含:

  • $MFT(快照时刻整张表,包括当时每条记录的状态)
  • $UsnJrnl:$J(直到该时点的 journal)
  • $LogFile
  • 每一份用户文件(除 VSS 排除项外,默认排除项包括 pagefile.syshiberfil.sys%TMP% 的内容)

在一台典型的 Windows 端点上,快照会自动产生:

  • Windows Update 安装前。
  • 系统还原在配置变更(驱动安装、某些软件安装)时触发。
  • 第三方备份软件(Veeam、Acronis、MSP 远程管理工具)。
  • 在批量操作前请求快照的特定应用。

一台常态更新的工作站很容易就有 5 到 10 份回溯几个月的快照。装有备份软件的服务器可能更多。

这为什么对取证重要

在线 MFT 是一次观察。有了快照,你得到的是一组观察序列。每个历史 MFT 都记录了那一刻卷的状态,包括:

  • 当时存在、自那以后被删除的文件。 可从快照中完整恢复,若属于范围内,连数据簇也能拿回来。
  • 现在存在、当时不在的文件。 证明何时被引入。一旦你能把一条文件钉在"快照 N 与快照 N+1 之间出现",就有了一个创建窗口。
  • 时间戳与今天不同的记录。 暴露在这段间隔里发生过的重命名、移动与 timestomping。
  • 独立于 VSS 的相互验证。 快照由与在线卷不同的代码路径写入。要一致地伪造两者很难。

快照在勒索软件案件中尤其有用。多数家族会先试着删 VSS,但有时它们会漏掉由第三方备份软件用不同 VSS writer ID 触发的快照,或者找不到挂载的外部盘上的快照。一份未被擦掉的加密前快照就能给你原件。见 MFT 中的勒索软件模式

列出快照

从一个提升权限的 PowerShell 或 cmd:

vssadmin list shadows

每条结果会显示一个 Shadow Copy Volume 路径,形如 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy7。该路径可作为一个独立的卷挂载,结构同 NTFS。

如果要更多细节(快照 ID、创建时间、VSS writer):

vssadmin list shadows /for=C:

从取证镜像中,使用 libvshadow

vshadowinfo disk.dd
vshadowmount disk.dd /mnt/shadows

vshadowinfo 列举 .dd.E01 镜像中的快照。vshadowmount 把它们暴露为单独的虚拟卷(vss1vss2……)。每一个都可像 NTFS 卷一样被解析。这是离线 VSS 抽取的标准工具,不需要 Windows 机器。

从快照中抽取 $MFT

快照挂载好之后(无论是在线系统或通过 vshadowmount),$MFT 在快照根目录的同一偏移处。用与在线相同的工具拉它:

  • fsutil(在线系统):fsutil file queryextents \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopy7\$Mft 返回 extent;原始读取把文件拼起来。
  • FTK Imager:把 shadow copy 设备加为证据,定位到 $MFT,导出。
  • Sleuth Kit 的 icat(镜像):icat -o <offset> vss1 0 > mft_vss1.bin。Inode 0 永远是 $MFT
  • KAPEMFT target 与 --vss 标志。KAPE 会依次在每个被枚举到的快照上跑这个 target,并把每份快照的抽取放到独立子目录里。

在线系统层面的细节见 抽取 $MFT

对比两份 MFT

最便宜又有用的分析就是 diff。把两份 $MFT 都解析成每条记录一行的 CSV,按记录号排序,做 diff:

mft_dump -o csv mft_today.bin > today.csv
mft_dump -o csv mft_vss3.bin  > vss3.csv
diff <(sort today.csv) <(sort vss3.csv) > changes.diff

要找的东西:

  • vss3 里存在但在 today 缺失或标为已删除的记录。 在这段间隔被删除的文件。快照里仍是删除之前的记录;元数据与(常常还有)数据都能恢复。
  • today 存在但在 vss3 没有的记录。 在间隔中被引入的文件。它们的创建落在快照与今天之间。
  • SI 时间戳向后回退的记录。 可能的 timestomping;快照才是基线真相。
  • $FILE_NAME 父引用变化的记录。 文件被移动到了另一个目录。
  • 序列号跳了不止 1 的记录。 槽位在这段间隔内被复用了不止一次。剧烈翻动,或刻意复用槽位。

同样的 diff 在 $UsnJrnl 这一层会更丰富;把它与 MFT diff 配在一起,能拼出更完整的图。有些快照里的 USN journal 内容已经在在线 journal 中被轮转出去了。把多份快照的 USN journal 组合起来,能复原出比在线 journal 单独所保存的更长的活动历史。

让付出值得的几个案例

下面是几个 VSS-MFT diff 解决过的真实案例:

  • 一次"误删"声明。 用户说他上周二误删了一个文件。把周一的快照与今天做 MFT diff,结果显示该文件实际上是先被重命名、然后被某个非用户进程打开,三天后才被删的。完全是另一个故事。
  • 驻留在 \Windows\Temp\ 的持续后门。 在线 MFT 没有痕迹;清理脚本跑过了。两周前的快照里却有一份带常驻 $DATA 的二进制。哈希命中了一个已知恶意家族。
  • 加密前的 MFT。 一次勒索软件运行加密了 C: 上的一切。vssadmin delete shadows 跑过了,但一份由 Veeam 触发、用了不同 writer ID 的快照活了下来。加密前 MFT 被恢复,原件被还原,未付赎金。

VSS 是把单一时间点的取证变成时间序列的那个工件。它值得你认真去采集。

限制

快照可以被删除。 vssadmin delete shadows /all 是一行命令的清除手段,存在于所有现代勒索软件 playbook 中。已经被淘汰掉的快照就是没了。VSS 有一个固定最大值(每卷默认 64,实际中常因磁盘空间而更少)。

快照并非任意时间点。 你拿到的是计划任务或安装器触发的那些。事件发生的精确时刻往往没有快照。最接近的通常对于常打补丁的工作站是一天以内,对于带备份软件的服务器是几个小时以内。

较旧 $MFT 中的常驻数据不会被保留超过那份快照。 如果某文件曾在某份快照中存在且足够小到可常驻,那份快照里有它的字节。请不要期望从该删除之后才拍的快照里再恢复。

被排除的路径不在快照里。 %TMP%pagefile.sys、注册表里某些卷影副本排除项,会导致部分取证工件不被保留。页面文件内存转储 工件能补上 VSS 不覆盖的部分。

快照在跨进程层面不是 crash-consistent。 快照在某一瞬间捕获整个卷,但并不与应用层做协调。打开的文件(尤其是数据库)在快照中可能处于不一致状态。NTFS 自身是带日志且一致的;文件 内部 的内容只是应用在那一刻所刷盘的东西。

常见问题

在 Linux 上能读 VSS 快照吗?

可以。libvshadow 是跨平台的。用 vshadowmount 挂载镜像后,任何支持 NTFS 的工具都可以把这些快照卷当作普通文件读取。

快照里包含像 $MFT 这样的系统文件吗?

包含。VSS 快照捕获快照时刻卷上的每一个块,包括 $MFT 起始处的元数据文件。这恰恰也是快照之所以有用的原因。

Windows 保留多少份快照?

默认每卷至多 64 份。该设置是注册表里的 MaxShadowCopies,很少被自定义。在装有备份软件的服务器上,实际上限通常由备份软件保留的份数决定。

Shadow copy 数据对擦写有韧性吗?

对在线卷上单个文件的删除有韧性,本来就是为这个设计的。对 vssadmin delete shadows、全盘擦写、物理介质损坏,以及拥有管理员权限的恶意行为者都没有韧性。

外部盘上的快照呢?

不太常见但存在。被配置为 File History 或装有自带备份软件的外部盘可能有快照。对任何卷执行 vssadmin list shadows /for=<drive>:,找形如 \\?\GLOBALROOT\Device\HarddiskVolumeShadowCopyN 的路径。

延伸阅读

外部资源