Master File Table

MFT

NTFSファイルシステムから分析者にとって最も価値のある情報源は、マスターファイルテーブル(MFT)である。 MFTの開始セクタの場所は、ディスクのブート セクタで見つけることができ、ボリューム内のすべてのファイルとディレクトリは、MFTのエントリを持っています。 MFTの各エントリーは1024バイトの大きさで、MFTの解析が非常に簡単になっています。 各MFTレコードまたはエントリは、ASCII文字列「FILE」(エントリにエラーがある場合は「BAAD」で始まる)で始まり、それぞれ独自の識別子と構造を持つ1つ以上(多くの場合、複数)の属性で構成されています。 図4.1はMFTエントリーの一部を示しています。

Figure 4.1. 各MFTエントリの最初の42バイトは、12個の要素を持つヘッダ構造からなり、残りの982バイトはヘッダ内の値とエントリ内に含まれるさまざまな属性に大きく依存する。 MFT エントリのヘッダー内のすべての要素が法医学分析者にとってすぐに役立つわけではありませんが、図 4.2 はすぐに役立つ要素の 5 つを示しています。 図4.2 MFTレコードのヘッダー項目(リトルエンディアン順)

図4.2(図4.1から一部を抽出)に示すように、レコードの最初に見える「FILE」署名を見てください。 次に、エントリが割り当てられたり解放されたりするときにインクリメントされるシーケンス番号(値)が見えます。 この特定のMFTエントリは、実際にはMFT内の最初のレコードであり、ファイル「$MFT」を参照しているため、シーケンス番号は1です。 次に、このレコードのエントリを持っているディレクトリの数を示すリンクカウントです(ハードリンクによりこの値は増加します)。 レコード内のオフセット0x38を見ると、最初の属性の識別子が0x10、つまり16であることがわかります。 これは、エントリが割り当てられているかどうか (0x01 ビットが設定されている場合) と、エントリがディレクトリであるかどうか (0x02 ビットが設定されている場合) を示しています。 つまり、この 2 つの値から、エントリが割り当てられているのか削除されているのか、またファイルなのかディレクトリなのかを判断することができるのだ。 ヘッダをパースしたときの擬似コードは次のようになります。

if ($mft{flags} & 0x0001) – allocate; else unallocated/deleted

if ($mft{flags} & 0x0002) – folder/directory; else file

図 4.2 で見えるフラグの値は “0x01” でこれは allocate ファイルであることを表しています。 0x00 の値は削除されたファイルを示し、0x03 の値は割り当てられたディレクトリを示します。

Tip

MFT Records

MFT レコードは一度作成したら削除しません。新しいレコードは必要に応じて MFT に加えられ、削除済みファイルのレコードは再利用されます。

前述のように、最初の42バイトのみが構造化されており、それ以降はMFTエントリの残りは1つ以上の属性フィールドで構成されています。 MFT エントリ内に特定の属性が必要であるという正式な仕様や声明はありませんが、ほとんどの MFT エントリには $STANDARD_INFORMATION 属性と $FILE_NAME 属性が含まれていることが予想されます。 このセクションでは、フォレンジック・アナリストにとって貴重なタイムスタンプ情報を提供する、この2つの属性について説明します。 また、$DATA 属性についても簡単に説明し、残りの属性については、興味と関心のある読者のための練習問題として残します。

各属性のヘッダーには 16 バイトのヘッダーがあり、属性の種類、属性全体の長さ、その属性が MFT エントリーに常駐するかなどの要素を識別します。

Note

MFT Metadata Files

MFTの最初の16エントリにはメタデータ・ファイルに関する情報が含まれるが、これらはすべて使用されない可能性がある。 使用されないものは割り当てられた状態のまま、基本情報のみが含まれます。

このヘッダー情報を使用すると、MFT エントリを解析して、各属性から貴重な情報を抽出することができます。 たとえば、$STANDARD_INFORMATION 属性 (常に常駐) はすべてのファイルおよびディレクトリ エントリに存在し、0x10 (すなわち 16) の識別子を持ちます。 この属性には、コマンド プロンプトで “dir” と入力したときに表示される、MFT エントリのファイル時間(とにかく 3 つ)が含まれています。ファイルまたはディレクトリの変更時間、最終アクセス時間、作成(誕生)日(「MAC」時間とも呼ばれる)が含まれています。 この属性には、MFTエントリが最後に変更された時刻を指定する4番目の時刻値が含まれています。 これらの時間をすべて合わせて、「MACE」(「E」は MFT エントリ変更時間を指す)または「MACB」(「C」は MFT エントリ変更時間を指す)時間と呼びます。

警告

ファイル時間

NTFS ファイルの時間は、グリニッジ標準時と同様の協定世界時 (UTC) 形式で記録されます。 これはすべての時刻に当てはまります。各 MFT エントリで、ファイル レコードには少なくとも 8 つの時刻が関連付けられ、多くの場合、12 またはそれ以上があります。 FAT ファイル システムでは、ファイルの時刻はローカル システム時刻形式で管理されます。

$FILE_NAME 属性 (識別子 0x30、または 48) もほとんどのファイルおよびディレクトリ MFT エントリで見つかります。 STANDARD_INFORMATION属性と同様に、この属性は常に常駐し、4つの時間値も含みますが、これらの時間値は通常、ファイルがシステム上に作成されるときに設定されます。 STANDARD_INFORMATION属性のファイル時刻とは異なり、これらのファイル時刻は通常のシステム活動や悪意のある改ざんの影響を受けないため、不正な活動の指標として使用でき、システムが感染した時刻を難読化するための措置を講じることができます。 以下のコードサンプル(parseSIAttr()関数)は、$STANDARD_INFORMATION属性の解析方法の一例を示しています。

sub parseSIAttr {

my $si = shift;

my %si;

my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)

= unpack(“VVCCvvv”,substr($si,0,22));

my $content = substr($si,$ofs_content,$sz_content).My %si;$sz_content;my %si;$sz_content;$sz_content;$sz_content;$sz_content;my %sz_content;$sz_content;$sz_content;$sz_content;$sz_content;$sz_content

my ($t0,$t1) = unpack(“VV”,substr($content,0,8));

$si{c_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,8,8));

$si{m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,16,8));

$si{mft_m_time} = getTime($t0,$t1)を実行。

my ($t0,$t1) = unpack(“VV”,substr($content,24,8));

$si{a_time} = getTime($t0,$t1);

$si{flags} = unpack(“V”,substr($content,32,4));

return %si.VVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVV

}

Tip

GetTime

先ほどの parseSIAttr() 属性のコードリストで見られた getTime() 関数は Andreas Schuster から借りたコードで、64 ビットの FILETIME オブジェクトタイムスタンプを 32 ビット Unix 時間に変換し、さらに Perl の内蔵関数 gmtime() により人間の読める時間に翻訳しているものです。 そのコードは以下のように表示されます。

sub getTime($$) {

my $lo = shift;

my $hi = shift;

my $t;

if ($lo == 0 && $hi == 0) {

$t = 0.0

$t = 0;

} else {

$lo -= 0xd53e8000;

$hi -= 0x019db1de;

$t = int($hi*429.0);

$lo -= 0xd53e8000;

$hi -= 0x019db1de4967296 + $lo/1e7);

};

$t = 0 if ($t < 0);

return $t;

}

このコードはどこから展開されたか関係なくあらゆるFILEIMEオブジェクトを解析、翻訳するのに非常に有用である。

通常のシステムでは、多くの MFT エントリは 2 つの $FILE_NAME 属性を持ちます。1 つはファイル (またはディレクトリ) のフルネーム、もう 1 つは DOS, 8.3 ファイル名を保持するためのものです。 たとえば、ファイル名が “myreallylongfile.txt” である場合、8.3 ファイル名は “myreal~1.txt” と表示されます。 これは、古いファイルシステムや長いファイル名をサポートしていないファイルシステムとの互換性のために残されています。 そのため、通常のWindowsシステムでは、ほぼ同じ内容の2つの$FILE_NAME属性を持つMFTエントリーが多数存在することは珍しくありません。 次のコードサンプル(parseFNAttr()関数)は、MFTエントリから$FILE_NAME属性を解析し、利用可能なデータを抽出する方法の例を示しています。

sub parseFNAttr {

my $fn = shift;

my %fn;

my ($type,$len,$res,$name_len,$name_ofs,$flags,$id,$sz_content,$ofs_content)

= unpack(“VVCCvvv”,substr($fn,0,22));

my $content = substr($fn,$ofs_content,$sz_content).My %sz_content;my %sz_content;my %sz_content;My %sz_content;my %sz_content;my %sz_content;my %sz_content;my %sz_content;My %sz_content;my %sz_content

$fn{parent_ref} = unpack(“V”,substr($content,0,4));

$fn{parent_seq} = unpack(“v”,substr($content,6,2))とする。

my ($t0,$t1) = unpack(“VV”,substr($content,8,8));

$fn{c_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,16,8));

$fn{m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,24,8)).My (vv), $t1) = unpack(“VV”,substr($ontent,20,8));

$fn{mft_m_time} = getTime($t0,$t1);

my ($t0,$t1) = unpack(“VV”,substr($content,32,8));.

$fn{a_time} = getTime($t0,$t1);

$fn{flags} = unpack(“V”,substr($content,56,4));

$fn{len_name} = unpack(“C”,substr($content,64,1));

$fn{namespace} = unpack(“C”,substr($content,65,1));

$fn{len_name} = $fn{len_name}。 * 2 if ($fn{namespace} > 0);

$fn{name} = substr($content,66,$fn{len_name});

$fn{name} = cleanStr($fn{name}) if ($fn{namespace} > 0).If ($fn{nameespace}).If ($fn{nameespace} > 0).If ($fn{name}).If ($fn{namepass}

$fn{name} =~ s/x0c/msx2e/g;

$fn{name} =~ s///g;

return %fn;

}

最後に述べるのは$DATA属性(識別子 0x80、128)である。 この属性は、ファイルの実際の内容を含むか、または参照します。 属性ヘッダーの非居住者フラグが設定されていない場合、ファイルの内容はMFTエントリーの$DATA属性内に常駐し、ヘッダーと2つの追加構造体に続いて存在します。 これは一般に、短いテキスト・ファイルなど、700バイト未満のファイルに当てはまります。 データが常駐しない場合、”data runs” (データがディスク上にある場所) を翻訳する必要があります。

$DATA 属性の data runs を解析するサンプル コードは非常に複雑なので、ここでは紹介しません。 同様に、常駐する $DATA 属性から情報を抽出するコードは些細なもので、属性ヘッダーの後のいくつかの追加情報 (コンテンツのサイズとコンテンツへのオフセット) を解析することからなります。

いくつかのオープン ソース ツールが、MFT を解析し (特に $STANDARD_INFORMATION および $FILE_NAME 属性)、解析者がタイムスタンプ付きデータを利用できるようにします。 その1つがDavid Kovar氏のanalyzemft.py Pythonスクリプトで、Web上のhttp://www.integriography.com/projects/analyzeMFTに掲載されています。 これは、http://code.google.com/p/winforensicaanalysis にある WinForensicAnalysis Google Code Project で入手できます。

Brian Carrier の “The SleuthKit” (TSK) ツールは、取得した画像やライブ システムからファイル システムおよびファイル システム メタデータ情報を幅広く収集するツールとしておそらく最もよく知られています。 たとえば、取得したイメージからファイル システムの $STANDARD_INFORMATION 属性ファイル時間のリストを収集するために、解析者は次のようなコマンドを使用します:

C:\tsk>fls -f ntfs -m C:/ -p -r G:\casexp.img > G:\casefiles

このコマンドは、ファイルシステムの活動のタイムラインに変換する前にこの情報を保存するための中間ファイル形式である「bodyfile」と呼ばれるものを生成します。 このオフセット情報は、Hex エディターまたは mmls.exe を使用して手動で決定することができます。 アナリストがリモート システムに正しく接続し、システムの C:\ ドライブを自分のシステムで F:\ としてマウントしている場合、次のようなコマンドを使用して、C:⽋パーティション内のファイルに対する $STANDARD_INFORMATION 属性ファイル時間を収集できます:

C:\tsk>fls -f ntfs -m C:/ -p -r \.\F: > g:\casefiles

TSKツール一式、およびドキュメントと使用情報は、SleuthKit Webサイト、http://www.sleuthkit.org.

で見ることができる。

コメントを残す

メールアドレスが公開されることはありません。