在 USN 日志中识破 timestomping 与反取证

篡改 MFT 时间戳的攻击者,藏不过 change journal。$STANDARD_INFORMATION 与 $FILE_NAME 的不一致,以及意外出现的 BasicInfoChange 记录,如何揭穿反取证行为。

作者: 阅读约 2 分钟

注重 tradecraft 的操作者不会只是删除证据。他们会伪装留下的东西。最常见的动作是 timestomping — 改写 NTFS 文件的时间戳,让文件看起来无辜,或让它过老到滑出调查窗口。这一招过去很可靠。可一旦 USN 日志打开 — 而它在每台现代 Windows 主机上默认就是开的 — 它就会留下足够特征的签名,一条过滤加一次父路径解析就能让它现形。

本文走一遍 timestomping 在磁盘上做了什么、日志如何揭穿它,以及用同一份痕迹"顺带"还能捕获哪些其他反取证手段。

NTFS 时间戳快速回顾

每个 MFT 表项 在两个属性中携带时间戳:

  • $STANDARD_INFORMATION (SI)。用户态工具和大部分 API 读写的时间戳。dir、资源管理器、Get-ChildItemos.statGetFileTime 都返回 SI。Microsoft 在 NTFS 文件时间参考 中文档化了布局。
  • $FILE_NAME (FN)。NTFS 为每个 $FILE_NAME 属性在内部设置的时间戳(若被硬链接,文件可有多个名字)。FN 值更难修改 — 只在特定操作时更新,内核也不公开干净的 API 去重写它们。

timestomping 工具默认盯着 SI。传统的 Metasploit timestomp.exe、SetMACE,以及具备中等手艺的操作者所写的几十种自定义植入,都通过 NtSetInformationFile 配合 FileBasicInformation 载荷重写 $STANDARD_INFORMATION。现代植入(包括 Cobalt Strike 的 timestomp 命令)也能直接操作 MFT 来重写 FN,这更复杂,且会留下额外的 $LogFile 证据。

无论哪种方式,写入 MFT 表项的动作都会点亮日志。

日志为时间戳编辑记录了什么

当 SI 时间戳被写入时,NTFS 会在文件的 FileReferenceNumber 上发出一条 BasicInfoChange | Close 记录。那条记录就是诊断:

  • 合法的 touch 会产生 BasicInfoChange | Close,同时伴随触发时间戳更新的真正写入 DataExtendDataOverwrite
  • timestomp 则在同一 FileReferenceNumber 上产生前面没有任何写入的孤立 BasicInfoChange | Close

当你在同一句柄会话内看到 BasicInfoChange | Close 且没有 DataOverwriteDataExtendFileCreate 或 rename 时,你看到的就是元数据操纵。其中绝大多数是 timestomping;其余是属性切换(+H+R、压缩开关)和 EFS 状态变更。

SI 与 FN 的比较

最权威的 timestomping 检测,是把每个文件的 SI 时间戳与其 FN 时间戳作对比。该模式源自 Mandiant 早期的 Windows 取证研究,并在 Brian Carrier 的 File System Forensic Analysis 中有阐述。应让你警觉的形态:

  • SI 早于 FN。 一个文件不可能在它的名字存在之前被合法修改。这是经典的铁证。
  • SI 超出 FN 不切实际的未来。 操作者把表观年龄向前推,试图让文件看起来像干净安装时的系统文件。
  • SI 和 FN 都干净得不像话 — 秒数都是整数、M/A/C/B 完全相同、全都对应某个已知的 Windows 安装日期。即使没有单独成对触发,也值得多看一眼。

日志是对比较的补充而非替代。MFT 比较告诉你有什么动过时间戳。日志告诉你 SI 重写究竟何时发生 — 这就是你写进报告的时间戳。两者一拼,案件几乎自己就写完了:

  1. MFT 比较在 \Windows\System32\drivers\suspicious.sys 上标出 SI < FN。
  2. 日志在该文件的 FileReferenceNumber 上、2026-04-12 03:08:14Z,有一条没有任何邻近写入的 BasicInfoChange | Close
  3. 那个时间戳就是操作者运行 timestomp 命令的时刻。再与 Sysmon 事件 1 关联,就拿到了进程。

$LogFile 与日志应当一致

日志在每个文件粒度记录写入。$LogFile 在元数据写入粒度记录底层 MFT 事务。一次 timestomp 会产生:

  • $LogFile 中一条修改目标表项 $STANDARD_INFORMATION 属性的 MFT 写入事务。
  • 日志中一条 BasicInfoChange | Close

如果 $LogFile 显示某文件上有 MFT 更新事务,而日志中却没有对应的 BasicInfoChange | Close,那操作者可能已经通过擦除 $UsnJrnl 再新建一个的方式删除了日志记录。这个动作是可行的(fsutil usn deletejournal /D /N C: 后跟 fsutil usn createjournal /m ... /a ... C:),但它本身就很响。

日志能捕获的其他反取证动作

禁用或抹除日志

fsutil usn deletejournal /D /N C: 会完全移除日志。运行之后:

  • 日志文件被重建为空。调用之前的记录永久消失。
  • $UsnJrnl 的 MFT 表项被重新写入,$LogFile 会记录这一点。
  • 如果配置了 SACL(通常没有),安全日志会为 SeRestorePrivilegeSeManageVolumePrivilege 记录 Sensitive Privilege Use 事件。

日志无法告诉你之前里面是什么,但"禁用日志"这个动作本身就是强烈的反取证信号。Microsoft 在 fsutil usn 参考 中文档化了管理命令。

知道日志存在的操作者倾向于做两件事之一:撤出时清掉(吵闹),或有选择地不在其中留下证据(更难,要求不碰磁盘)。在某已知事件窗口附近日志可疑地空的主机上,把这点当作待验证的假设。

备用数据流

ADS 隐藏比我还老,而日志干净地记录了它。StreamChange reason 位在文件的某个备用数据流被添加、重命名或移除时触发。按 StreamChange 过滤,卷上每一次 ADS 创建/修改事件都浮上来。

预期的误报:浏览器下载产生的合法 Zone.Identifier 流(与宿主文件的 FileCreate 配对),邮件客户端的 Mark-of-the-Web 流,SmartScreen 状态。其他在已签名系统二进制、\Windows\System32\ 内文件,或非正常浏览器下载路径之外的用户配置二进制上出现的 StreamChange 记录,都值得过目。

硬链接技巧

HardLinkChange 在硬链接被添加或移除时触发。操作者有时用硬链接让恶意二进制可通过两个父目录访问,从而绕过 AppLocker 规则和基于路径的 EDR 控制。按 FileReferenceNumber 转视角,查看给定 inode 的全部父目录。

Reparse point 滥用

ReparsePointChange 在 reparse point — junction、符号链接、mount point — 被添加、修改或移除时亮起。寻找在 \$Recycle.Bin\\Users\Default\\ProgramData\ 等本不该出现的位置创建的 reparse point。回收站解析器$Recycle.Bin 一侧的互补痕迹。

安全与对象 ID 变更

SecurityChange 暴露 ACL 与所有者的重写。ObjectIdChange 暴露较少见的对象 ID 操纵。两者在健康主机上都很安静。用户配置二进制或系统文件上的爆发值得跟进。

实操扫描流程

用解析过的日志做最快的 timestomping 初筛:

  1. 过滤出 reason 掩码恰好BasicInfoChange | Close 的记录。大多数解析器默认是"包含该位";本扫描需要精确匹配。
  2. 对每个候选,查看同一 FileReferenceNumber 前 5 分钟的记录。如果没有 DataOverwriteDataExtendFileCreate 或 rename,就标记该记录。
  3. 对被标记的记录,计算 MFT 中 SI 与 FN 的差值。按绝对差排序。

列表顶部就是你的 timestomping。其余被标记条目通常是 attrib +Hattrib +R 调用,或脚本切换 read-only — 视上下文而定,对典型 IR 调查而言通常没意思,但为了完备,值得保留在排序输出里。

本页的解析器公开了精确掩码过滤。第 3 步需要同时开着解析过的 $MFT;大多数分析师用 Eric Zimmerman 的 MFTECmd 导出 CSV,再在电子表格里做透视。

这条路线抓不到的东西

完全绕过日志的反取证动作的简短清单:

  • 从外部介质引导并改写磁盘。 从未触及运行中的 OS,也从未写过日志。
  • 在同一偏移保留内容大小且不更新 SI 的用户态文件重写。 会产生 DataOverwrite 记录,但原内容已经丢失。日志看到了写入,但没看到之前那里是什么。
  • 在做任何事之前禁用日志。 日志只能记录它运行时发生的事。

对这些情况,你需要 $LogFile、Volume Shadow Copies、主机外遥测,或一份在事件发生足够近时刻获取、还含有相关状态的 RAM 转储

延伸阅读

  • Microsoft Learn — File TimesNtSetInformationFile API 参考。后者是每个 timestomping 工具最终都会调用的系统调用。
  • Eric Zimmerman 的 MFTECmd — 把 SI 与 FN 时间戳输出到扁平 CSV 的离线规范解析器。
  • Joachim Metz 的 libfsntfs 文档 — 关于 $LogFile 内部最详尽的开放参考。当仅靠日志不够时,它就是第二个证人。
  • Brian Carrier, File System Forensic Analysis — 关于 NTFS 元数据属性的那一章,至今仍是 SI 与 FN 在不同操作下行为的规范参考。