← ブログに戻る

Master File Table(MFT):NTFS の $MFT を解説する

· 読了 4 分

$MFT は NTFS がボリューム上のすべてのファイルとディレクトリを追跡するために使うインデックスです。同時に、Windows マシンから抽出できる中で最も情報量の多い単一のアーティファクトでもあります。ボリューム上の他のすべてのファイル、テーブル自身も含めて、その中に少なくとも 1 つのレコードを持っています。フォレンジックツールは、レコードが削除後も残るため、Windows がもはや存在を認めないファイルに関する難しい質問に答えます。脅威ハンターは、攻撃者は NTFS 上でファイルを動かすときに必ず $MFT に書き込まざるを得ないため、これを通じて永続化を追跡します。Windows のアーティファクトをバイトレベルで 1 つだけ学ぶなら、これを学ぶべきです。

これは私が始めた頃に欲しかったリファレンスです。テーブルとは何か、レコードはどう見えるか、レコードが持てる属性、先頭の予約済みシステムファイルが何を意味するか、悪名高い「Windows がマスターファイルテーブルを回復できません」エラーが実際に何を意味するか、そしてテーブルを自分で読む方法をカバーします。

Master File Table とは

$MFT はファイルです。単一のファイルです。すべての NTFS ボリュームの先頭付近の既知のオフセットにあります。パーティションのオフセット 0 にあるブートセクタ(BIOS Parameter Block の 512 バイト)には MftStartLcn というフィールドが含まれており、これが $MFT の最初のクラスタを指しています。その 1,024 バイトを読めばレコード 0、つまりテーブルの自己記述が得られます。

テーブルの各行は厳密に 1,024 バイトで、1 つのファイルまたは 1 つのディレクトリを記述します。すべてのレコードは、名前、タイムスタンプ、DOS スタイルのフラグ、セキュリティディスクリプタ参照、そしてデータそのもの(小さなファイル)またはデータが存在するディスククラスタのリスト(大きなファイル)を、型付き属性の連続としてエンコードして保持します。

NTFS は 1993 年に Windows NT 3.1 と共に導入され、Windows XP 以降のすべての固定ディスクで Windows のデフォルトファイルシステムです。FAT に取って代わりました。FAT は小さなアロケーションテーブルを保持し、ファイル名をディレクトリエントリ内に格納します。NTFS はあらゆるファイルに関するほぼすべてのメタデータを、1 つの構造化されたテーブル $MFT に格納します。その設計には記憶しておく価値のある 2 つの帰結があります。

  1. すべてのメタデータが一箇所にあります。 $MFT への単一のシークで、ボリューム上のあらゆるファイルを列挙できます。フォレンジックツール、アンチウイルスエンジン、インデックスサービス、バックアップソフトウェアがすべてこれを読み取るのはそのためです。同じ理由で、$MFT の破損は FAT の破損よりはるかに大きな問題になります。
  2. 削除されたファイルは自分のメタデータを残します。 NTFS がファイルを削除するとき、レコードヘッダの 1 つのビットをクリアし、ファイルのクラスタを $Bitmap で空きとマークします。レコードの残り(名前、タイムスタンプ、しばしばデータも)は、そのレコードスロットが再利用されるまでそのまま残ります。削除を生き残るもの を参照してください。

略語 MFT は Master File Table の略です。NTFS ではメタデータファイルの名前に $ プレフィックスが付くため、ディスク上では $MFT と書かれます。

$MFT のディスク上のレイアウト

NTFS がボリュームをフォーマットすると、パーティションの先頭付近に MFT ゾーンと呼ばれる領域を予約します。テーブルの最初の 16 レコードは NTFS メタデータファイル用に予約されています(後述)。レコード 0 はテーブル自身のエントリで、自分のクラスタを指し戻します。

$MFT はより多くのレコードが必要になるたび、予約ゾーンに拡張することで成長します。ゾーンが使い切られる前にボリュームが満杯になると、Windows は領域を縮小してユーザーデータのためのスペースを確保します。これが、年季の入ったファイルシステムで激しく断片化した $MFT が一般的な理由です。テーブルは縮小しません。スロットが作成されると $MFT に残り続け、削除は使用中フラグをクリアするだけです。これが、ほとんど使われていないボリュームでは現在のハイウォーターマークよりずっと上にある古い削除済みレコードが何年も残る理由です。

最初のレコードのバックアップは $MFTMirr にあり、ボリュームの中央に配置されます。$MFT 自身が読み取れない場合、NTFS は $MFTMirr を使って回復をブートストラップします。$MFTMirr と NTFS がそれを使うとき を参照してください。

FILE レコードの解剖

すべての MFT レコードは 4 バイトの ASCII シグネチャ FILE46 49 4C 45)で始まります。破損したレコードは代わりに BAAD を持ちます。これは chkdsk がレコードを修復できなかったときに書き込む墓標です。シグネチャの後に 56 バイトのヘッダ、次に fixup 配列、そして 0xFFFFFFFF で終端された型付き属性のストリームが続きます。

ヘッダは、最もよく手に取るフィールドを保持しています。

  • シグネチャ。 有効なレコードでは FILE、修復不能では BAAD
  • Update sequence(fixup)配列。 torn write 検出の小技です。レコード内の各 512 バイトブロックの末尾 2 バイトを USN で置き換え、元の値をこの配列に保存します。読み取り時に NTFS は USN を検証し元のバイトを復元します。
  • $LogFile シーケンス番号。 クラッシュリカバリ用の $LogFile へのポインタです。
  • シーケンス番号。 レコードスロットが再利用されるたびに増加します。レコード番号と組み合わせると、ファイルの特定の実体を一意に識別する 64 ビットの ファイル参照 が形成されます。
  • ハードリンクカウント。 レコードを指す $FILE_NAME 属性の数。
  • フラグ。 ビット 0 は IN_USE(クリアは削除済み)。ビット 1 は DIRECTORY
  • Base file record 参照。 テーブル内の他の場所にあるベースレコードに属する拡張レコードでは非ゼロ。
  • Used と allocated サイズ。 Used はこのレコードが 1,024 バイトのスロットの実際に消費する量、allocated はスロットサイズ(標準ボリュームでは常に 1,024)です。

ヘッダと属性ストリームのバイト単位のウォークスルーは MFT レコードの内部 を参照してください。

ヘッダの後に属性が続きます。それぞれが独自の短いヘッダ(タイプ、長さ、レジデント/非レジデントフラグ、オプションの名前)を持ち、データが続きます。固定の順序はありませんが、実務上は $STANDARD_INFORMATION が先、$DATA が最後です。スペースが足りなくなったレコード(フラグメントが多すぎる、ADS が多すぎる、異常に長い名前)は $ATTRIBUTE_LIST 属性を生やし、テーブル内のどこかにある 1 つまたは複数の拡張レコードを指します。パーサはチェーンをたどってファイルを再構成しなければなりません。

$MFT に格納されるファイル属性

NTFS 属性タイプの規範的なリスト、16 進コード付きです。

| タイプ | Hex | 目的 | |------|-----|---------| | $STANDARD_INFORMATION | 0x10 | 4 つのタイムスタンプ(created、modified、accessed、MFT-modified)、DOS フラグ、所有者 ID、セキュリティ ID、USN ポインタ。 | | $ATTRIBUTE_LIST | 0x20 | ファイルの属性が 1 つのレコードに収まらないときの拡張レコードへのポインタ。 | | $FILE_NAME | 0x30 | 1 つのファイル名、親ディレクトリ参照、アロケート済みと実サイズ、そして 2 つ目の 4 つのタイムスタンプの組。ファイルは複数(ハードリンクごとに 1 つ、加えて有効ボリュームの 8.3 短縮名)を持つことがあります。 | | $OBJECT_ID | 0x40 | Distributed Link Tracking サービスが使う 128 ビットのオブジェクト識別子。 | | $SECURITY_DESCRIPTOR | 0x50 | レガシーなファイルごとの ACL。最新の NTFS は ACL を $Secure に集中して格納し、$STANDARD_INFORMATION から ID で参照します。 | | $VOLUME_NAME | 0x60 | レコード 3($Volume)にのみ。ボリュームラベルを保持します。 | | $VOLUME_INFORMATION | 0x70 | NTFS バージョン、dirty フラグ。 | | $DATA | 0x80 | ファイルの内容。非常に小さなファイルではレジデント、それ以外は非レジデント(クラスタのランリスト)。ファイルは複数の $DATA 属性を持てます。名前のないものがプライマリストリーム、名前付きは 代替データストリーム です。 | | $INDEX_ROOT | 0x90 | B+ ツリーのルート。ディレクトリ($I30)、リパースポイントインデックス、その他のインデックス化された構造で使用されます。 | | $INDEX_ALLOCATION | 0xA0 | 大規模インデックスの非レジデントの続き。 | | $BITMAP | 0xB0 | $MFT 自体または大きなディレクトリのアロケーションビットマップ。 | | $REPARSE_POINT | 0xC0 | symlink、junction、マウントポイント、OneDrive プレースホルダ、dedup スタブ。 | | $EA_INFORMATION / $EA | 0xD0 / 0xE0 | OS/2 時代の拡張属性。最新の Windows では稀です。WSL1 が POSIX メタデータに使用したのが、気にすべき唯一の文脈です。 | | $LOGGED_UTILITY_STREAM | 0x100 | EFS 暗号化メタデータ($EFS)、TxF トランザクションデータ。 |

レコードは常に少なくとも $STANDARD_INFORMATION、1 つの $FILE_NAME、1 つの $DATA を持ちます。それ以外はすべてオプションで機能駆動です。

レジデントと非レジデントのデータ

実際のボリューム上のほとんどの $DATA 属性は 非レジデント です。属性ヘッダはコンパクトな クラスタラン のリスト(開始 LCN と長さの組み合わせ、繰り返し)を保持し、ファイルのバイトはディスク上の別の場所にあります。属性ヘッダ自体は小さいです。

ファイルが十分に小さい場合(通常、他の属性を考慮に入れて約 700 バイト未満)、NTFS はバイトをレコード内にインラインで格納します。それが レジデントデータ であり、フォレンジック作業で最も有用なアーティファクトの 1 つです。数週間前に削除された小さなテキストファイルの内容が、未割り当ての $MFT レコード内にバイト単位でそのまま座っていることがあります。サイズしきい値と何を探すべきかは resident data を参照してください。

$MFT の最初の 16 レコードにある NTFS メタデータファイル

$MFT の最初の 16 レコードは NTFS 自身の帳簿用に予約されています。$ で始まるためユーザーファイル名と衝突しません。知っておく価値のあるものは次のとおりです。

| Rec # | ファイル | 何か | |-------|------|------------| | 0 | $MFT | テーブル自身。その $DATA ランリストは自分のクラスタを指します。 | | 1 | $MFTMirr | $MFT の最初のレコードの部分バックアップ。 | | 2 | $LogFile | クラッシュ後の不完全な操作を取り消しまたは再実行するためのトランザクションログ。 | | 3 | $Volume | ボリュームラベルと dirty フラグ。 | | 4 | $AttrDef | 有効な属性タイプのスキーマ。 | | 5 | . | ルートディレクトリ。 | | 6 | $Bitmap | ボリューム上のクラスタごとに 1 ビット。アロケーションを追跡します。 | | 7 | $Boot | ブートセクタのコピー。 | | 8 | $BadClus | ファイルシステムが不良としてマークしたすべてのクラスタをランで指すスパースファイル。 | | 9 | $Secure | セキュリティディスクリプタの集中ストア。 | | 10 | $UpCase | 大文字小文字区別のない名前比較に使用される Unicode 大文字マッピングテーブル。 | | 11 | $Extend | より新しいシステムファイルを含むディレクトリ。$ObjId$Quota$Reparse$UsnJrnl$RmMetadata。 |

変更ジャーナル $UsnJrnl$Extend 配下)はフォレンジックで特に有用です。ボリューム上のあらゆるメタデータ変更をログし、タイムライン再構築のために $MFT を補完します。ジャーナルとファイルテーブルの組み合わせ を参照してください。

$MFT がおかしくなったとき

エラー "Windows cannot recover master file table. CHKDSK aborted" は、chkdsk$MFT を読み取れず、$MFTMirr にもフォールバックできないときに表示されます。この時点で、NTFS はすでに組み込みの自己修復で試行し失敗しています。私が見てきた根本原因を、実際にどれくらいの頻度でそれぞれだったかでランク付けすると次のとおりです。

  • 物理メディアの故障。 MFT ゾーンの不良セクタが読み取りでゴミを返します。通常 SMART データが裏付けます。dd ではなく ddrescue でディスクをイメージ化し、イメージ上で作業します。
  • メタデータ集中型操作中の突然の電源喪失。 トランザクションログが通常これらをロールバックしますが、破損した $LogFile はロールバックを破ります。
  • ドライバまたはフィルタレベルの破損。 不適切に動作するディスク暗号化スタック、ファイルシステムのミニフィルタ、バグのあるストレージドライバが不整合なレコードを書き込むことがあります。互いに争う複数のセキュリティエージェントを持つホストで一般的です。
  • 悪意ある上書き。 ワイパーや一部のランサムウェアファミリー(特に Petya と初期の NotPetya の波)はボリュームをマウント不能にするために $MFT を故意に落書きします。MFT におけるランサムウェアパターン を参照してください。

フォレンジック的に妥当な対応は以下のとおりです。

  1. 直ちにボリュームへの書き込みを停止します。 以降の書き込みはすべて回復の可能性を減らします。
  2. FTK Imager、ddddrescueディスクをイメージ化 し、既知の正常な宛先に書き出します。ハッシュを検証します。
  3. オリジナルではなくイメージ上で作業します。testdiskR-Studio、またはボリュームを直接シグネチャスキャンして FILE レコードを探す手動パースを試します。$MFT へのディスク上のポインタが失われていても、レコード自体は通常まだ認識可能です。
  4. データ回復ではなくボリュームをオンラインに戻すことが目標なら、その時だけイメージに対して chkdsk /f を実行します。

書き込み可能なボリュームでの chkdsk /b は不良クラスタマーカーをクリアできますが、理解できないレコードを破棄することもあります。イメージを持ち、可用性がフォレンジックな忠実性に優ると判断した後でのみ、オリジナルで実行してください。

$MFT の読み方

現実的な選択肢は 3 つあります。

  • MFTECmd(Eric Zimmerman)。ほとんどのタイムラインツールが期待する bodyfile に近いレイアウトの CSV を生成する Windows CLI です。インシデントレスポンダーの事実上の標準。
  • omerbenamram/mft。Rust のクレートと CLI(mft_dump)です。このサイトが使うパーサで、分析をスクリプト化したり、より大きなパイプラインに組み込んだりしたいときに有用です。
  • このサイトのブラウザパーサ。 $MFTホームページ にドロップすると、同じ Rust パーサが WebAssembly にコンパイルされて完全にブラウザ内で動作します。何もアップロードされません。

具体的な利点と欠点の比較は MFT パーサツール を参照してください。解析済み $MFT の実用的なワークフローについては タイムラインの構築削除済みファイル$MFT の抽出 を参照してください。

よくある質問

MFT は何の略ですか?

MFT は Master File Table の略です。NTFS ではメタデータファイル名にドル記号がプレフィックスされるため、ディスク上では $MFT と書かれます。

Master File Table は何に使われますか?

NTFS がボリューム上のあらゆるファイルとディレクトリを見つけるために使うインデックスです。各エントリはファイルの名前、タイムスタンプ、セキュリティ情報、属性、そしてディスク上のデータの位置を格納します。

Master File Table にはどのファイル属性が格納されますか?

最低限、すべてのレコードは $STANDARD_INFORMATION(タイムスタンプ、DOS フラグ)、$FILE_NAME(名前と 2 つ目のタイムスタンプの組)、$DATA(ファイルの内容またはそれへのポインタ)を保持します。レコードはまた、$ATTRIBUTE_LIST$OBJECT_ID$SECURITY_DESCRIPTOR$INDEX_ROOT$INDEX_ALLOCATION$BITMAP$REPARSE_POINT$EA$LOGGED_UTILITY_STREAM をファイルに応じて持つこともあります。完全なリファレンスは上記の属性テーブルにあります。

Master File Table の大きさはどれくらいですか?

各レコードは 1,024 バイトです。テーブルはデフォルトでボリュームの約 12.5%(MFT ゾーン)を予約しますが、実際に必要なスペースしか消費しません。100 万ファイルのボリュームは大まかに 1 GB の $MFT を持ちます。

$MFT と $MFTMirr は同じですか?

いいえ。$MFTMirr$MFT の最初の数レコードの部分バックアップで、メインテーブルのヘッダが破損したときに NTFS が回復をブートストラップできるよう、ディスク上の別の場所に置かれています。

破損したマスターファイルテーブルはどう修正しますか?

まずディスクをイメージ化します。次にイメージに対して chkdsk /f を実行する(速いがレコードを破棄する可能性あり)か、FILE シグネチャをスキャンして生クラスタからテーブルを再アセンブルできる回復ツールを使います(遅いが、より多くの証拠を保存)。イメージ化前にオリジナルボリュームに対して chkdsk を実行しないでください。

Linux や macOS で $MFT を読めますか?

はい。$MFT はただのファイルです。生の $MFT ダンプを受け入れるパーサはどの OS でも動作します。omerbenamram/mftanalyzeMFT、このサイトのブラウザツールなど。ライブマウントされたボリュームからファイルを 抽出 するには Windows が必要なだけです。

参考資料

  • Microsoft, Master File Table。公式かつ簡素なリファレンスです。
  • Brian Carrier, File System Forensic Analysis。NTFS のレイアウトと回復に関する最良の単行書です。
  • linux-ntfs プロジェクトの NTFS ドキュメント。すべての属性のフィールドオフセットを、長年のリバースエンジニアリングから得たものです。

外部リソース