NTFS 文件系统时间戳取证分析:Timestomping 检测与四源交叉验证框架
摘要
文件系统时间戳是数字取证中重建攻击时间线的核心依据,但其本身也是攻击者篡改的重点目标。NTFS 文件系统同时维护四套独立的时间戳记录机制——MFT 的 $STANDARD_INFORMATION 与 $FILE_NAME 属性、USN Journal 变更日志与 $LogFile 事务日志,各自以不同的精度、更新规则与访问权限运行。本文系统分析 NTFS 时间戳架构的取证价值,分类讨论三种 Timestomping 手段的技术原理与固有痕迹,提出基于四源交叉验证的自动化检测框架,并给出基于 MFTECmd 与 exhume_ntfs 的实战工具链实现。
关键词:NTFS;Timestomping;数字取证;USN Journal;MFT
1. 引言
NTFS 是 Windows 操作系统的核心文件系统,其时间戳存储机制远非单一的时间值数组。MFT(主文件表)中的 $STANDARD_INFORMATION($SI)和 $FILE_NAME($FN)属性各自独立维护文件的 MACB(修改、访问、MFT 变更、创建)时间戳,且更新规则迥异。此外,USN Journal 以变更日志形式记录每次文件操作的精确时刻与原因码,$LogFile 则以事务日志形式保存元数据操作的底层序列。
这种多源冗余设计在文件系统一致性层面或属偶然,但在数字取证领域构成了天然的时间戳交叉验证体系。攻击者常利用 Timestomping 技术篡改 $SI 时间戳以掩盖入侵痕迹,但 $FN、USN Journal 及 $LogFile 中的对应记录往往被忽略——三者之间的微秒级精度不一致,恰构成最坚固的证据链。
2. NTFS 时间戳架构
2.1 $SI 与 $FN 双轨机制
NTFS 以 MFT 为核心索引结构,每个文件对应一条 MFT 记录。每条记录包含多个属性,其中 $STANDARD_INFORMATION(属性类型 0x10)与 $FILE_NAME(属性类型 0x30)各自独立存储文件的 MACB 时间戳。
$SI 属性的时间戳与文件内容的交互相关——文档编辑、权限变更或数据写入均会触发 $SI 更新。$FN 属性的时间戳与文件位置和名称的交互相关——重命名、移动等操作触发 $FN 更新。这种设计分歧制造了天然的双轨取证系统:同一文件在不同元数据属性中可能存储着差异化的时间信息。
关键点在于,攻击者通常只修改 $SI 时间戳,而忽略 $FN 中的副本。修改 $SI 可通过用户态 API 完成——Cobalt Strike、Timestomp.exe 和 Metasploit 均内置此功能。修改 $FN 则需内核 API 或利用 Windows 的文件重命名机制将 $SI 自动复制到 $FN。
2.2 MFT 记录物理结构
每条 MFT 记录固定为 1024 字节(1 KiB)。前 42 字节为 FileRecordHeader,其后为属性序列,以 0xFFFFFFFF 结束标记终止。关键字段如下:
| 字段 | 类型 | 偏移 | 描述 |
|---|---|---|---|
signature | [u8; 4] | 0x00 | 总是 b"FILE" |
usa_offset | u16 | 0x04 | 更新序列数组偏移 |
lsn | u64 | 0x08 | $LogFile 序列号,用于日志关联 |
sequence_number | u16 | 0x10 | 每次记录复用递增 |
attrs_offset | u16 | 0x14 | 首个属性偏移(通常 0x30) |
flags | u16 | 0x16 | 0x01=已分配, 0x02=目录 |
base_file_record | u64 | 0x20 | 扩展记录指向基本记录 |
其中 lsn 字段是连接 MFT 与 $LogFile 两大取证数据源的核心桥梁,记录了最后一次修改此 MFT 记录的日志序列号 。属性头部标识类型(0x10 = $SI,0x30 = $FN,0x80 = $DATA)及常驻/非常驻状态。
2.3 时间戳精度与纳秒分析
NTFS 时间戳以 64 位 FILETIME 格式存储,精度 100 纳秒,起始点 1601 年 1 月 1 日。正常文件操作产生的时间戳具有精确的纳秒分量——例如 131683876627452045 对应 2018-04-16 21:27:42.7452045。当攻击者使用系统工具(如 PowerShell 的 Get-Item)修改时间戳时,纳秒分量通常被置零——131683876620000000 虽然对应同一时刻,但纳秒部分全零在整数表示中极为突出。
值得强调的是,纳秒全零检测仅能捕获使用标准系统工具的低水平攻击者。经过定制的高级攻击工具(如 Metasploit 的 timestomp 模块)可生成带真实纳秒精度的时间戳,此时纳秒检测本身不足以排除篡改可能。
3. 文件系统日志机制
3.1 USN Journal 变更日志
USN Journal(\$Extend\$UsnJrnl)是 NTFS 为每次文件系统变更提供的持久化日志 ,包含两个备用数据流:$J(实际变更记录)和 $Max(配置信息)。其核心价值在于记录文件创建、删除、重命名与数据变更的高层次操作,不受操作者权限或意图影响。
USN Record 经历三个版本演进:
| 版本 | 引入版本 | 文件引用大小 | 包含文件名 | 包含时间戳 | 核心特性 |
|---|---|---|---|---|---|
| v2 | Vista | 64 位 | 是 | 是 | 基础记录 |
| v3 | Windows 8 | 128 位 | 是 | 是 | 扩展文件引用 |
| v4 | Windows 10 | 128 位 | 否 | 否 | Range Tracking |
v4 记录的核心设计转变在于关注文件被修改的具体字节范围而非文件名与时间戳。其 USN_RECORD_EXTENT 结构(Offset / Length)精确记录修改的字节偏移范围。Windows 保证每次 Range Tracking 产生 v4 记录后,文件关闭时会追加一条含 USN_REASON_CLOSE 的 v3 记录以补全文件名和时间戳。
USN_REASON 位掩码的关键取证含义:
USN_REASON_DATA_OVERWRITE(0x00000002):精确标记文件数据被覆盖的时刻。攻击者修改 MFT $SI 时间戳后,后续任何数据写入操作均被记录,且此记录无法被追溯性删除或篡改。USN_REASON_BASIC_INFO_CHANGE(0x00008000):直接对应文件属性修改,包括时间戳篡改本身——该记录就是 Timestomping 操作的最直接证据。USN_REASON_FILE_CREATE(0x00000100):文件首次创建的精确时刻,可用于与 MFT 声称的创建时间进行比对。
3.2 $LogFile 事务日志
$LogFile 是 NTFS 的事务日志,以预写式日志(WAL)机制记录文件系统元数据的每一次变更操作。与 USN Journal 记录高层次操作不同,$LogFile 记录的是底层元数据变更——一个 USN 事件可能在 $LogFile 中对应数十条低层次记录。
常见操作码与取证含义:
| 操作 | $LogFile 操作 | USN Journal 对应事件 |
|---|---|---|
| 文件创建 | InitializeFileRecordSegment + AddIndexEntryAllocation | FileCreate |
| 文件删除 | DeleteIndexEntryAllocation + DeallocateFileRecordSegment | FileDelete |
| 重命名 | DeleteIndexEntryAllocation + AddIndexEntryAllocation | RenameOldName → RenameNewName |
| 时间戳修改 | SetBasicInfo + UpdateStandardInfo | BasicInfoChange |
其关键取证价值在于:当攻击者修改 $SI 时间戳时,$LogFile 中会留下 OpenFileRecord → SetBasicInfo → UpdateStandardInfo → CloseFileRecord 的操作序列。若攻击者通过文件重命名同步修改 $FN,还会包含 DeleteIndexEntry → UpdateFileName → AddIndexEntry。无论 MFT 中如何修改,$LogFile 中各操作的相对时序和间隔均揭示真实过程。
4. Timestomping 技术分类分析
4.1 用户态 API 修改($SI 层)
攻击者利用用户态 API 直接修改 $SI 时间戳,是最基础也最广泛使用的 Timestomping 手段:
(Get-Item "backdoor.dll").CreationTime = (Get-Date "2020-03-15")
(Get-Item "backdoor.dll").LastWriteTime = (Get-Date "2020-03-15")
痕迹:仅修改 $SI,$FN 不随动,两者时间戳产生偏差;纳秒分量被置零;USN Journal 中产生 BASIC_INFO_CHANGE 记录。
4.2 文件重命名同步修改($FN 层)
攻击者先通过用户态 API 修改 $SI,随后移动或重命名文件。Windows 自动将修改后的 $SI 时间戳复制到 $FN 属性,使两组时间戳保持一致。
痕迹:尽管 $SI/$FN 不再矛盾,但 USN Journal 中同时留下 BASIC_INFO_CHANGE(Timestomping 时刻)和 RENAME_OLD_NAME / RENAME_NEW_NAME(重命名时刻)的记录序列。攻击者无法追溯性修改这两类事件的时间戳。
4.3 内核级 API 直接写入($SI + $FN 层)
在未引入 Patch Guard 的旧版 Windows 上,攻击者可通过 NtSetInformationFile 和 NtQueryInformationFile 直接修改 $FN 时间戳。通过直接磁盘写入,还可同时修改两条 MFT 属性而不触发文件系统级事件。
痕迹:$SI 与 $FN 一致,USN Journal 仍会记录 BASIC_INFO_CHANGE。直接磁盘写入虽可绕过部分日志,但对 $LogFile 的篡改本身会产生新的日志记录——完全无痕在技术上极其困难。
4.4 局限性分析
真正无痕 的 Timestomping 需同时满足:内核级直接磁盘写入修改 $SI 和 $FN;修改或删除 USN Journal 中关联的 BASIC_INFO_CHANGE 记录;修改或删除 $LogFile 中关联的事务记录;确保所有修改的纳秒精度一致。USN Journal 与 $LogFile 使用不同的二进制格式和存储机制,且对日志的修改本身又会产生新的记录——这使得完全无痕的 Timestomping 在理论可行但实际操作中几乎无法实现。
4.5 $LogFile 漏洞(CVE-2025-49689)
2025 年,安全研究员 Sergey Tarasov 披露了 $LogFile 日志重放机制中的本地提权漏洞 CVE-2025-49689,影响自 Windows XP SP1 以来所有版本。漏洞根源在于 ntfs!NtfsMountVolume 解析 $LogFile 事务记录时的整型溢出,可导致任意覆写与安全描述符篡改。
这一发现对取证分析提出了新的挑战:攻击者可利用 $LogFile 日志重放机制向文件系统注入恶意记录,制造虚假操作时间线,或直接擦除关键事务记录。常规的取证假设——"$LogFile 记录总是真实可信"——需要在漏洞利用场景下重新审视。
5. 四源交叉验证框架
5.1 验证逻辑
给定以下四套独立时间戳记录体系:
| 数据源 | 时间戳类型 | 精度 | 可篡改程度 | 存储位置 |
|---|---|---|---|---|
| $SI | MACB | 100 纳秒 | 用户态 API | MFT $STANDARD_INFORMATION |
| $FN | MACB | 100 纳秒 | 需内核 API 或重命名 | MFT $FILE_NAME |
| USN Journal | 操作时间 | 取决于记录 | 需内核权限,操作留痕 | \$UsnJrnl:\$J |
| $LogFile | 事务时间 | 取决于记录 | 极高难度,需直接写磁盘 | \$LogFile |
交叉验证的核心逻辑:若同一文件的四套时间戳之间存在不一致(如 $SI 显示 2018 年的创建时间,但 USN Journal 显示该文件 2025 年才首次出现 FILE_CREATE 事件),则 $SI 时间戳必然是伪造的。
5.2 验证流程
以可疑可执行文件为例:
- $SI / $FN 比对:使用 MFT 解析工具提取两组时间戳。差异超过阈值则标记可疑。
- USN Journal 回溯:搜索文件的 MFT 引用号,关注
FILE_CREATE(首现时刻)和BASIC_INFO_CHANGE(Timestomping 时刻)记录。 - $LogFile 深度验证:搜索关联事务日志条目,
SetBasicInfo操作的时间即为 Timestomping 真实时刻。 - 纳秒精度检验:检查 FILETIME 值的纳秒分量是否为全零——低级 Timestomping 的信号。