摘要 NTFS并非单一真相源。文件创建、修改、访问时间戳同时存在于MFT的$STANDARD_INFORMATION和$FILE_NAME属性中,且更新规则迥异。USN Journal以变更日志形式记录了每一次文件操作的精确时刻与原因码,$LogFile则以事务日志形式保存了更深层的元数据操作序列。攻击者常利用Timestomping技术篡改$SI时间戳以掩盖入侵时间线,但$FN时间戳、USN Record中的USN_REASON_DATA_OVERWRITE事件以及$LogFile中的重做/撤销记录往往被忽略。这三者在微秒级精度上的不一致,恰构成最坚固的证据链。 NTFS文件系统时间戳架构 $STANDARD_INFORMATION与$FILE_NAME NTFS的核心元素是主文件表(MFT),它存储系统中每个文件的条目。MFT中的每个条目包含许多存储文件描述元数据的属性。其中最为关键的两个属性——$STANDARD_INFORMATION($SI)和$FILE_NAME($FN)——各自独立存储着文件的MAC(B)时间戳:M(修改时间)、A(访问时间)、C(MFT变更时间)、B(创建时间)。 $SI属性中的时间戳大致与文件内容的交互相关——当你编辑一个文档、更改其权限或写入数据时,$SI时间戳会被更新。$FN属性中的时间戳则大致与文件位置和名称的交互相关——当你重命名文件、移动文件到另一个目录时,$FN时间戳会被更新。 这种设计上的分歧制造了一个天然的取证双轨系统:同一个文件,在不同的元数据属性中可能存储着不同的时间信息。关键点在于,攻击者通常只修改$STANDARD_INFORMATION中的时间,而忽略$FILE_NAME属性中的副本。 严格地说,修改$SI时间戳是一种极为常见的Timestomping方式,因为可以通过用户层面上的API进行操作——包括Cobalt Strike、Timestomp.exe和Metasploit在内的主流攻击工具都内置了此项功能。然而,修改$FN则需要调用内核API或滥用$FN时间戳的生成方式。已知的$FN篡改手段仅有两个:其一,在未引入Patch Guard的旧操作系统上,使用NtSetInformationFile和NtQueryInformationFile直接写入;其二,在任何操作系统上先篡改$SI,然后移动或重命名文件,Windows会自动将修改后的$SI复制到$FN中。 值得注意的是,在取证分析实践中广泛流传着两个误区:一是认为$FILE_NAME中的时间戳永远不会被篡改,二是认为自动化工具生成的时间戳纳秒部分必定为全零。事实上,高级攻击者完全可以通过上述方法同步修改$FN时间戳,部分经过定制化的工具(如Metasploit的timestomp模块)也支持带纳秒精度的时间戳生成。这要求取证分析师必须超越简单的$SI/$FN比对,深入到USN Journal和$LogFile层面进行交叉验证。 在实际攻击事件中,Timestomping的使用已相当普遍。APT28在入侵后的第一时间即篡改了后门文件的时间戳,APT29(Cozy Bear)在SolarWinds事件中大规模使用时间戳篡改以将其恶意DLL混入合法更新包,Lazarus Group更是直接复制calc.exe的时间戳注入到其恶意投放的文件中——这正是Cobalt Strike内置timestomp模块的标准操作方式。 MFT Record的物理结构 要深入理解上述两类时间戳的差异,必须了解MFT记录的物理结构。 每个MFT记录恰好为1024字节(1 KiB)。前42字节包含FileRecordHeader,紧接着是一系列属性的顺序排列。属性序列以类型为0xFFFFFFFF的结束标记终止。 FileRecordHeader的关键字段包括: 字段 类型 偏移 描述 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=目录,…