注重 tradecraft 的操作者不会只是删除证据。他们会伪装留下的东西。最常见的动作是 timestomping — 改写 NTFS 文件的时间戳,让文件看起来无辜,或让它过老到滑出调查窗口。这一招过去很可靠。可一旦 USN 日志打开 — 而它在每台现代 Windows 主机上默认就是开的 — 它就会留下足够特征的签名,一条过滤加一次父路径解析就能让它现形。
本文走一遍 timestomping 在磁盘上做了什么、日志如何揭穿它,以及用同一份痕迹"顺带"还能捕获哪些其他反取证手段。
NTFS 时间戳快速回顾
每个 MFT 表项 在两个属性中携带时间戳:
$STANDARD_INFORMATION(SI)。用户态工具和大部分 API 读写的时间戳。dir、资源管理器、Get-ChildItem、os.stat、GetFileTime都返回 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,同时伴随触发时间戳更新的真正写入DataExtend或DataOverwrite。 - timestomp 则在同一
FileReferenceNumber上产生前面没有任何写入的孤立BasicInfoChange | Close。
当你在同一句柄会话内看到 BasicInfoChange | Close 且没有 DataOverwrite、DataExtend、FileCreate 或 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 重写究竟何时发生 — 这就是你写进报告的时间戳。两者一拼,案件几乎自己就写完了:
- MFT 比较在
\Windows\System32\drivers\suspicious.sys上标出 SI < FN。 - 日志在该文件的
FileReferenceNumber上、2026-04-12 03:08:14Z,有一条没有任何邻近写入的BasicInfoChange | Close。 - 那个时间戳就是操作者运行
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(通常没有),安全日志会为
SeRestorePrivilege或SeManageVolumePrivilege记录 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 初筛:
- 过滤出 reason 掩码恰好为
BasicInfoChange | Close的记录。大多数解析器默认是"包含该位";本扫描需要精确匹配。 - 对每个候选,查看同一
FileReferenceNumber前 5 分钟的记录。如果没有DataOverwrite、DataExtend、FileCreate或 rename,就标记该记录。 - 对被标记的记录,计算 MFT 中 SI 与 FN 的差值。按绝对差排序。
列表顶部就是你的 timestomping。其余被标记条目通常是 attrib +H 或 attrib +R 调用,或脚本切换 read-only — 视上下文而定,对典型 IR 调查而言通常没意思,但为了完备,值得保留在排序输出里。
本页的解析器公开了精确掩码过滤。第 3 步需要同时开着解析过的 $MFT;大多数分析师用 Eric Zimmerman 的 MFTECmd 导出 CSV,再在电子表格里做透视。
这条路线抓不到的东西
完全绕过日志的反取证动作的简短清单:
- 从外部介质引导并改写磁盘。 从未触及运行中的 OS,也从未写过日志。
- 在同一偏移保留内容大小且不更新 SI 的用户态文件重写。 会产生
DataOverwrite记录,但原内容已经丢失。日志看到了写入,但没看到之前那里是什么。 - 在做任何事之前禁用日志。 日志只能记录它运行时发生的事。
对这些情况,你需要 $LogFile、Volume Shadow Copies、主机外遥测,或一份在事件发生足够近时刻获取、还含有相关状态的 RAM 转储。
延伸阅读
- Microsoft Learn — File Times 与
NtSetInformationFileAPI 参考。后者是每个 timestomping 工具最终都会调用的系统调用。 - Eric Zimmerman 的 MFTECmd — 把 SI 与 FN 时间戳输出到扁平 CSV 的离线规范解析器。
- Joachim Metz 的 libfsntfs 文档 — 关于
$LogFile内部最详尽的开放参考。当仅靠日志不够时,它就是第二个证人。 - Brian Carrier, File System Forensic Analysis — 关于 NTFS 元数据属性的那一章,至今仍是 SI 与 FN 在不同操作下行为的规范参考。