如何从磁盘镜像(或活动系统)中提取 $UsnJrnl:$J

实战指南:从取证镜像、已挂载卷或运行中的 Windows 主机里拿出 NTFS USN 日志 — 使用 FTK Imager、X-Ways、The Sleuth Kit、fsutil 与 PowerShell。

作者: 阅读约 2 分钟

处理 USN 日志最难的部分通常不是解析,而是先把文件搞到手。$UsnJrnl:$J 是备用数据流,不是普通文件,因此它不出现在资源管理器里,简单的 copy 不会带走它,robocopy 还会默默骗你说已经拿到了。这是按照你通常会遇到它的三个地方分门别类的实操指南:取证镜像、已挂载卷、运行中的机器。

你要找的东西

日志位于:

\$Extend\$UsnJrnl:$J

$Extend 是隐藏的 NTFS 元数据目录,$J$UsnJrnl 元数据文件上两个备用数据流之一。另一个数据流叫 $Max,只保存日志配置的最大大小和 allocation delta — 没有任何记录。如果误抓了 $Max,你只会拿到几字节没用的配置。一定要选 $J

Microsoft 在 Change Journals 参考USN_RECORD_V2 结构参考 中文档化了布局。典型的 $J 在 30 MB 到几个 GB 之间,取决于安装时 fsutil usn 是怎么配置的。Windows 客户端默认约 32 MB;服务器常被设置为 1 GB 或更大。

$J 时,顺手从同卷抓一份 $MFT。没有它,解析器只能给你末端文件名 — 每条记录绑定到父 MFT 表项号,而不是路径。两份文件都有,就能免费得到完整路径。

从取证磁盘镜像 (E01、dd、AFF4)

DFIR 中最常见的情况。选你已经持有许可证的工具。

FTK Imager (免费, GUI)

  1. File → Add Evidence Item,打开镜像。
  2. 一路展开到 [root]/$Extend/$UsnJrnl
  3. 面板里 $J$Max 显示为兄弟行。右击 $J 并选择 Export Files

"兄弟行"这个细节是新手常踩的坑:右击父文件并导出默认流(空的)很容易发生。请明确选中 $J 那一行。

X-Ways Forensics (商业)

展开 Root directory → $Extend → $UsnJrnl$J 流出现在下面。Recover/Copy 把它写出来。同样的路径,同样的坑。

The Sleuth Kit (免费, 命令行, 跨平台)

大多数 Mac/Linux 分析师会用的工具。TSK 的 icat 是标准工具:

# 找到 $UsnJrnl 的 MFT 表项
fls -r -p image.dd | grep '\$UsnJrnl'

# 假设报告 inode 为 81,$J 流是属性 128-2:
icat image.dd 81-128-2 > UsnJrnl-J.bin

<inode>-<type>-<id> 三元组是 TSK 寻址备用数据流的方式。属性名以 :$J 结尾的那一个就是你要的;fls 的长输出会显示出来。

Velociraptor 与 KAPE

用于大范围分诊采集时,Velociraptor 的 Windows.NTFS.MFT 工件包和 Kroll 的 KAPE 都会自动抓日志。KAPE 用 target 文件(!ALLUSNJournal);Velociraptor 用 parse_ntfs 插件。两者也会同一轮一起抓 $MFT$LogFile,这正是你真正想要的。

从已挂载的卷

如果镜像通过 Linux 的 ntfs-3g 或 Windows 的 Arsenal Image Mounter 只读挂载,元数据路径会以普通文件的形式出现,但大多数工具拒绝透明地读取备用数据流。

在使用 ntfs-3g 的 Linux 上,数据流可以直接读:

sudo cat '/mnt/image/$Extend/$UsnJrnl:$J' > UsnJrnl-J.bin

根据 streams_interface 挂载选项,:$J 可能会显示为单独的路径组件。先用 ls -la /mnt/image/\$Extend/ 检查一下。

从运行中的 Windows 主机

需要管理员权限和一个懂 NTFS 的读取器,因为 Windows 即便对管理员进程也屏蔽对元数据文件的普通访问。

RawCopy

Eric Zimmerman 的工具套件包含 RawCopy.exe(以及 RawCopy64.exe),它会绕过标准文件 API:

RawCopy.exe /FileNamePath:"C:\$Extend\$UsnJrnl:$J" /OutputPath:"D:\Out"

KAPE 的 USNJournal target 在底层用的就是它。

PowerForensics (纯 PowerShell)

如果不能落地二进制,PowerForensics 用纯 PowerShell 读取原始 NTFS 结构:

Import-Module PowerForensics
Get-ForensicFileRecord -Path 'C:\$Extend\$UsnJrnl' |
  ForEach-Object { $_.GetContent() } |
  Set-Content -Path 'C:\Out\UsnJrnl-J.bin' -Encoding Byte

内置 fsutil(用于验证, 而非提取)

fsutil usn 是日志受支持的控制面,但不是提取工具。它能读取、查询和删除记录,但不能流式输出完整的 $J 块。它的用处在于尝试提取之前先确认日志已启用且大小已配置:

fsutil usn queryjournal C:

Status: 0x00000000Maximum Size 非零表示日志处于活动状态。0x80000005 表示已禁用,且在 fsutil usn createjournal 创建之前没有东西可提取。生命周期命令及其权限要求,请见 fsutil usn 参考

提取之后

拿到 $J 文件后,把它拖到本页顶部的解析器中,或喂给你信任的任一离线工具:usnrsPoorBillionaire/USN-Journal-Parser,或 Eric Zimmerman 的 MFTECmd(虽然名字这样,它也解析 $J)。

同时抓 $MFT(表项 0,与 $Extend 相邻的位置)。两份文件都提供后,上述任一解析器都能沿父引用链解析出每条日志记录的完整路径。没有 $MFT,你只能孤零零地读文件名。

抓取 NTFS 元数据时,如能顺便抓 $LogFile也不要客气。它很小,周转很快,在仅靠日志回溯不够的事件中,$LogFile 就是你的兜底。USN journal vs MFT vs LogFile 一文 说明了三者各自何时派得上用场。

常见陷阱

资源管理器复制。$UsnJrnl 拖放复制的是默认无名数据流,空的。不会有警告。请改用上面的任一工具。

日志已禁用。 工作组机器和过度精简的镜像有时会把日志关掉。fsutil usn queryjournal 是最便宜的飞行前检查。

前导稀疏零字节。 日志是稀疏数据流。刚雕刻出的 $J 前几百兆字节可能全是零,直到第一条真实记录才出现。usnrs、本页解析器以及大多数其他工具会自动跳过。如果你从零写解析器,扫描第一个非零字,然后查找一个合理的 RecordLength 值。

环形缓冲区回卷。 根据活动量,日志可能已经回卷 — 较旧的条目消失了。文件中最小的 USN 告诉你该卷的历史实际能回溯多远。把它当作硬性下限。

误抓 $Max 同一个父文件,但没有记录。如果你的雕刻得到一个很小的文件(几字节到几 KB),那基本可以确定你抓错了数据流。

延伸阅读

  • Microsoft Learn — API 表面与生命周期请见 Change Journals
  • Eric Zimmerman 的工具文档 — RawCopy 与其余套件 端到端覆盖了活动主机采集。
  • The Sleuth Kit 的 flsicat 手册页 — 镜像级提取的权威命令行参考。
  • KAPE 文档 — Kroll 公开了包括 USNJournal!BasicCollection 在内的 target 文件;阅读 target 的 XML 是了解一次彻底分诊采集的最快方式。