← ブログに戻る

MFT レコードの内部: シグネチャ、ヘッダー、属性

· 読了 1 分

Master File Table のすべてのエントリは 1,024 バイトで、同じレイアウトで配置されています。固定ヘッダー、小さな修復構造、その後に型付き属性のストリームが続きます。この記事はそのレイアウトを詳しく見ていきます — $MFT の生バイトを 16 進エディタで読んだり、自前のパーサーを書いたりするときに必要となる種類の詳細です。

FILE シグネチャ

すべてのレコードの最初の 4 バイトは ASCII 文字列 FILE(46 49 4C 45)です。パーサーはこれを錨として、生のボリュームから孤立したレコードをスキャンします。FILE で始まる 1,024 バイト境界はすべて MFT レコードであり、テーブル自身のヘッダーが読めなくても認識できます。

chkdsk が修復できなかったレコードは、代わりに BAAD(42 41 41 44)というシグネチャを持ちます。NTFS はこれらのレコードを消去せずに残します — スロットのシーケンス番号は保持されます — が、残りのバイトは信頼してはいけません。

レコード ヘッダー

シグネチャの後の 56 バイトは、これがどんな種類のレコードか、そしてどう安全に読むかを記述します。

  • 更新シーケンス配列のオフセット(2 バイト)と 配列のサイズ(16 ビット ワード単位)(2 バイト)。両方でフィックスアップ データを記述します(後述)。
  • $LogFile シーケンス番号(8 バイト)。クラッシュ リカバリのためにトランザクション ログを指し返します。
  • シーケンス番号(2 バイト)。レコード スロットが再利用されるたびに加算されます。
  • ハード リンク カウント(2 バイト)。$FILE_NAME 属性 1 つにつき 1。
  • 最初の属性へのオフセット(2 バイト)。
  • フラグ(2 バイト)。ビット 0 が IN_USE、ビット 1 がディレクトリを示します。
  • 使用サイズ(4 バイト)と 割り当てサイズ(4 バイト)。標準ボリュームでは割り当てサイズは常に 1,024 です。
  • 基底ファイル レコード参照(8 バイト)。1 ファイルの属性が 1 レコードに収まりきらないときに使われる 拡張レコード では非ゼロになります。
  • 次の属性 ID(2 バイト)。新しい属性に一意な ID を割り当てるために使われます。
  • レコード番号(4 バイト、NTFS 3.1+)。自己参照で、解析の整合性チェックに便利です。

削除済みファイルの解析の信頼性は、シーケンス番号が支えています。レコード番号単独では再利用されますが、64 ビットの ファイル参照(レコード番号 + シーケンス番号)は再利用されません。あるレコード番号における現在のシーケンスと食い違う参照は、以前の住人 — 通常は削除されたファイル — を指すポインタです。

フィックスアップ配列

NTFS は 更新シーケンス配列(USA、または フィックスアップ配列)という小さな仕組みで、書き込み途中破損(torn write)を検出します。1,024 バイトのレコードはまた 512 バイトのセクタ 2 つに分割されています。NTFS は次の処理を行います。

  1. 16 ビットの 更新シーケンス番号(USN — 同じ頭字語ですが $UsnJrnl の USN とは無関係)を選びます。
  2. 書き込み前に 各 512 バイト セクタの末尾 2 バイト をその USN で置き換えます。
  3. 各セクタの元の末尾 2 バイトを、USN 自身の直後にフィックスアップ配列内に順番に格納します。

読み出し時、NTFS は各セクタの末尾 2 バイトが USN と一致するか確認します。一致すれば、セクタは一緒に書かれたと判断し、元のバイトをフィックスアップ配列から取り出して戻します。どれかのセクタの末尾が一致しなければ、書き込みは途切れており、そのレコードは疑わしいと判定されます。

つまり、フィックスアップを適用せずに $MFT を 1 バイト単位で読むパーサーは、各レコードのオフセット 510 と 1022 でゴミを受け取ります。本格的な MFT パーサーは、レコードを見つけた直後にまずフィックスアップを適用します。

属性ストリーム

ヘッダー(とフィックスアップ配列)の後にファイルの属性が続きます。各属性はそれ自身の短いヘッダー — 型コード、長さ、常駐/非常駐フラグ、任意の名前 — から始まり、続いて属性のデータが置かれます。属性は 8 バイト境界で整列され、隙間なく書かれ、0xFFFFFFFF の番兵で終端されます。

最小限のレコードは 3 つを持ちます。

  • $STANDARD_INFORMATION(0x10)— タイムスタンプと DOS フラグ。
  • $FILE_NAME(0x30)— 名前、親ディレクトリ参照、もう 1 組のタイムスタンプ。
  • $DATA(0x80)— ファイルの内容。小さなファイルではインラインで常駐、それ以外ではクラスタ ランのリスト。

レコードはこれよりも多くを持つことがあり、ファイルの属性が 1 つの 1,024 バイト スロットに収まらないときには $ATTRIBUTE_LIST も含まれます。完全な一覧は Master File Table のリファレンス にあります。

フォレンジックで重要な理由

安定した 1,024 バイトのレイアウトと FILE シグネチャの組み合わせが、削除された NTFS ファイルのカービングを可能にしています。$MFT 自身がなくなっていても、生ボリュームを FILE ヘッダーで走査すれば、ほとんどのレコード — 削除エントリの名前、タイムスタンプ、そして(小さなファイルでは)データ — が回復できます。フィックスアップ機構によって、USA が検証される限り、回収されたこれらのレコードを信頼できます。

外部リソース