NTFS はフォレンジックアナリストに三つの大きなメタデータアーティファクトを提供しますが、本当に欲しい問いに対して間違ったほうを読んでしまう確実な方法は、これらを混同することです。要点をまとめると:
| アーティファクト | 何を記録するか | 期間 | 粒度 | 位置 |
|---|---|---|---|---|
$MFT | すべてのファイルとディレクトリの現在の状態 — 名前、サイズ、タイムスタンプ、親 | 「今この瞬間」と最近削除されたエントリ | ファイル単位 | MFT エントリ 0 |
$UsnJrnl:$J | すべてのファイル作成/削除/リネーム/変更の循環ログ | 数日から数週間 | 操作単位 | \$Extend\$UsnJrnl:$J (代替データストリーム) |
$LogFile | NTFS がクラッシュリカバリに使用するトランザクションログ — メタデータ書き込みの生の before/after イメージ | 数分から数時間 | メタデータトランザクション単位 | \$LogFile (MFT エントリ 2) |
私が実際に使用している意思決定ツリーと、各アーティファクトがそれ単独では失敗する理由を以下に示します。
$MFT — 「今、何が存在するか」
マスターファイルテーブル は NTFS の背骨です。すべてのファイルやディレクトリには少なくとも一つの 1024 バイトのエントリがあり、$STANDARD_INFORMATION、一つ以上の $FILE_NAME 属性、そして実際のコンテンツを指すデータランを保持します。
$MFT を選ぶのは、問いが次のような場合です。
- このボリューム上に今何が存在するか (再利用される前の最近削除されたエントリを含む)。
- 特定のファイルの 4 つの NTFS タイムスタンプ (
$STANDARD_INFORMATIONと$FILE_NAMEの両方における M/A/C/B)。 - まだ割り当てられているエントリを持つ削除済みファイルのバイトを復元できるか。
- 親参照番号しか持たないレコードのフルパス — これはまさに本ページのパーサが
$MFTもドロップしたときに USN レコードを解決する方法です。
どんなに目を凝らしても教えてくれないこと:
- 火曜日の 14:32 にファイルに何が起きたか。4 つのタイムスタンプは最終状態であり、履歴ではありません。ファイルがいつ作成され、最後に触られたかは教えますが、リネームされ、リネームし直され、切り詰められ、上書きされ、削除され、同じ MFT エントリで新しいファイルが作成されたとは教えません。
ツール: Eric Zimmerman の MFTECmd がデファクトのパーサです。Omer BenAmram の mft Rust crate と David Kovar の analyzeMFT Python スクリプトがオープンソース側をカバーします。
$UsnJrnl:$J — 「何が、どの順で起きたか」
Update Sequence Number ジャーナルは、ボリューム上で発生するすべての作成、削除、リネーム、切り詰め、属性変更、クローズを記録します。背景は 入門記事 がオンディスク形式をカバーし、reason コードの記事 がビットレベルのフィールドリファレンスです。
これを選ぶのは、問いが次のような場合です。
- 削除される前のこのファイルのライフサイクル (リネームを含む) は何だったか。
- このボリュームで大量にファイルを暗号化したものがあるか — ランサムウェア検出 を参照。
- 流出のために大量にファイルをステージング・アーカイブしたものがあるか — 流出検出 を参照。
- タイムスタンプが改変されたか — timestomping を参照。
- 14:00 から 16:00 の間にユーザは何をしていたか — 活動タイムラインの再構築 を参照。
教えてくれないこと:
- 誰が何をしたか。ユーザ、プロセス、コマンドラインはなしです。Security.evtx の
4663(SACL が設定されていた場合のみ) または Sysmon イベント 11 と相関させます。 - 任意のファイルの内容。ジャーナルはストリームが変わったことを記録しますが、以前のバイトは記録しません。
- リングバッファのウィンドウより古いもの。デフォルトはストリップダウンされたクライアントで約 10 MB から、適切にサイジングされたサーバで 1 GB 以上の範囲で、数日から数週間の履歴に相当します。
ツール: Airbus CERT の usnrs、PoorBillionaire の USN-Journal-Parser、Eric Zimmerman の MFTECmd ($J もパースします)、そして本ページの WebAssembly パーサ。
$LogFile — 「NTFS が何をしようとしていたか」
これは NTFS がクラッシュリカバリに使用するメタデータジャーナルです。すべてのメタデータ書き込み — INDEX_ALLOCATION 更新、属性変更、MFT エントリの書き換え — の before/after イメージを記録します。フォーマットは未文書化ですが、リバースエンジニアリングは進んでいます。Joachim Metz の libfsntfs が最も網羅的なオープンリファレンスです。
これを選ぶのは、次のような場合です。
- ファイルが同じ数千件のトランザクション内で作成され削除され、親ディレクトリエントリがすでに上書きされている場合。
$LogFileはリーフ名と親を含む「before」イメージをまだ保持している可能性があります。 - 直接的な
$MFT操作が疑われる場合。$LogFileは、その後の可視状態がきれいに見えても、生の書き込みを記録します。 - ジャーナルが関心の瞬間をカバーするには疎すぎる (小さい、または最近ローテーションされた) が、過去 1 時間以内に発生した場合。
提供しないもの:
- ローテーションウィンドウ外のもの。
$LogFileは小さく、大量に再利用されます。多忙なファイルサーバでは、トランザクション履歴全体が 1 時間未満で巻き戻ることがあります。 - ファイルの内容。before/after イメージはメタデータのみです。
ツール: Jonas Schicht の LogFileParser、および libfsntfs に基づくあらゆるパーサ。
私が実際に使用する意思決定ツリー
どのファイルか分かっていますか?
├── はい → 現在の状態が欲しい? → $MFT (パス、タイムスタンプ、サイズ)
│ 履歴が欲しい? → まず $UsnJrnl、ごく最近の過去には $LogFile
└── いいえ → 時間枠は?
├── 直近数分間 → $LogFile (最も粒度が細かい)
├── 直近数日/数週間 → $UsnJrnl (信号対ノイズ比が最良)
└── ずっと前 → $MFT のみ。最終状態のタイムスタンプで妥協する覚悟
多数のファイルにまたがる相関を取っていますか?
└── $UsnJrnl は 3 つの中で、ソート可能な操作単位のタイムラインを持つ唯一のものです。
ファイルが削除されたが、それが存在したことを証明する必要がありますか?
└── まず $UsnJrnl (FileDelete レコードは親参照とタイムスタンプを運ぶ)
削除が新しければ backstop として $LogFile
エントリがまだ再利用されていなければ $MFT のみ
組み合わせるところで本当の仕事が起きる
3 つのアーティファクトはよく組み合わさります。これは、必要になるまで誰も強調しない部分です。
$MFT + $UsnJrnl は典型的なペアです。MFT はパス解決のためのディレクトリツリーを提供し、ジャーナルは操作の履歴を提供します。本ページのパーサは両ファイルをドロップすると、すべてのジャーナルレコードのフルパスを自動的に解決します。一緒に取得してください。10 回中 9 回は往復を一回節約できます。
$LogFile は backstop です。関心の瞬間をカバーするにはジャーナルが小さすぎるとき、または MFT の直接改ざんが疑われるときに、ここに手を伸ばします。
より広い文脈には、3 つの NTFS アーティファクトを EVTX (プロセスとオブジェクトのイベント)、Prefetch と AmCache (実行証拠)、Shimcache (ある時点でプログラムが実行された)、レジストリハイブ、ユーザが開いたファイルの証拠としての LNK ファイル と ジャンプリスト、ブラウザ履歴、リソース使用量のための SRUM、RecentFileCache と組み合わせてください。
参考資料
- Microsoft Learn — Master File Table と Change Journals。
- Brian Carrier 著 File System Forensic Analysis — NTFS 内部構造に関する書籍級のリファレンスです。
- Joachim Metz の
libfsntfsドキュメント —$LogFile内部構造に関する最も詳細なオープンリファレンスです。 - SANS DFIR — Windows Forensic Analysis ポスター は、アーティファクトスタックを一枚にまとめたラミネートの 1 ページです。