ObjectID(オブジェクトID)についてまとめています。ObjectIDの仕組みをご存じの方には目新しい情報は含まれていません。fteの実装は後半のfteの処理内容に書いています。
ObjectIDの仕組み
NTFSではMFTエントリの属性として、$OBJECT_ID(0x40)が定義されておりファイルに付与することができます。この属性はDistributed Link Trackingサービスで使われています。Distributed Link TrackingサービスはWindows 2000からデフォルトでONになっており、例えばあるファイルのショートカットを作成して、その後にファイルを移動しても、ObjectIDの紐付けによりショートカットはファイルの場所を追跡できます。このように、ObjectIDは基本的にショートカットファイル(拡張子lnk)が作成された時点でファイルとショートカットファイル内に付与されます。
ショートカットファイルはスタートメニューやタスクバーにプログラムを追加(登録)した時点で作成されます。また、エクスプローラ経由もしくは「ファイルを開く」ダイアログ経由でファイルを開いた時点にも作成されます(ただしファイルの種類によっては対象外で、レジストリ「HKCR\ファイルタイプ\EditFlags」の設定によります)。下記はファイル"サンプル.txt"をエクスプローラもしくはメモ帳で開いた後の状態をファイルシステムレベルで記載した図です。
赤字がファイル毎に付与されるObjectIDで、青字がファイルシステム毎に付与されるVolumeIDを示します。"サンプル.txt"のアクセスにより、Windowsは「最近使ったファイル項目」(Recentフォルダ)に"サンプル.txt.lnk"(ショートカット)ファイルを作成します。同時に"サンプル.txt"のObjectIDを生成して、"サンプル.txt.lnk"ファイル内にそのObjectIDと現在のボリュームのVolumeIDを埋め込みます。また、ファイルシステム内の全ObjectIDを管理している$ObjIDファイルにも、"サンプル.txt"のObjectID/VolumeIDを登録します(Birth ObjectID/Birth VolumeIDについては後述)。
ObjectID/VolumeIDの構成
ObjectIDとVolumeIDはともに16バイト構成で、下記のように示すことができます。
ObjectIDはそのOS(PC)内でユニークな値でなければなりません。このような値を生成するための仕様がRFC4122(http://www.ietf.org/rfc/rfc4122.txt)で定められており、Windowsも基本的にはこの内容に従ってObjectIDを生成しています。具体的には上図のように3つのパートにわかれており、それぞれの内容は以下の通りです。
- Date/Time (8バイト)
1582/10/15 00:00:00 UTC(グレゴリオ暦の導入日)を起点とした経過時間(100ナノ秒単位)を60ビットで表現。残りの上位4ビットはバージョン情報(0x1)。 - Sequence (2バイト)
HKLM\SOFTWARE\Microsoft\Rpc\UuidSequenceNumberの下位14ビットと固定2ビット(10b)。XPではブートごとのインクリメンタルな値で、Vistaからはランダムな値。 - MAC (6バイト)
PCで認識しているNICのMACアドレス48ビット。複数のNICがある場合にどのMACアドレスが使用されるかは不明。
一方、VolumeIDはObjectIDと異なり生成される値の規則は不明ですが、最下位ビットは0であるという条件があります。したがって16進数表記では図の太字部分(2ケタ目)が偶数(0,2,4,6,8,A,C,Eのいずれか)になります。
ObjectIDのタイムスタンプ
ObjectIDを生成する際に使うタイムスタンプは、実際の値を見る限り、XPではOS起動後にObjectIDをはじめて付与した時間、VistaからはOS起動時間がベースでした。OSを停止するまでの間、WindowsはObjectIDを生成するたびにこの時間をベースに1ずつ増やしていきます。例えば、あるNTFSボリューム内で001.txt, 002.txt, 003.txtの3ファイルを作成し、001.txt, 002.txt, 003.txtの順にアクセスしてから002.txtファイルを削除します。この状態の$ObjIdファイル(全ObjectIDを管理している内部ファイル)を確認すると、以下のような値が格納されています。
(C:\$Extend\$ObjIdファイル内抜粋)
001.txt : ObjectID - 843C9FEDE7C8E111A078... (タイムスタンプ部分をデコードすると2012/07/08 19:30:24.7462020)
003.txt : ObjectID - 863C9FEDE7C8E111A078... (タイムスタンプ部分をデコードすると2012/07/08 19:30:24.7462022)
$ObjIdファイル内の情報から、以下のことがわかります。(簡略化のため対象はWindows 7として記載)
- 2012/07/08 19:30前後にPCを起動した
- このPCの起動から停止までの間に001.txtと003.txtファイルにアクセスした
- 001.txtファイル→003.txtファイルの順番でアクセスした
- 001.txtと003.txtのアクセスの間に、別のファイルにアクセスした(ObjectIDは853C9FEDE7C8E111A078...に相当し、このファイルは別ボリュームにあるか削除された→この例では002.txtが削除された)
このようにObjectIDのタイムスタンプ部分から、ファイルへのアクセス順序やファイル削除等に関する情報が得られます。
ローカルドライブ間のファイル移動
$ObjIdファイル内では、1エントリが1ファイルの内容に相当し、各エントリはObjectID, Birth VolumeID, Birth ObjectID, Birth DomainIDの4種類の情報を格納しています。Birth DomainIDは現在未実装のため常に0x00000000000000000000000000000000です。Birth VolumeIDは、ObjectID付与時に属するNTFSボリュームのVolumeIDです。1つのファイルシステムに閉じている限り、Birth VolumeIDは常に同じ値になるため特に気にする必要はありません。C、D、Eのように複数のNTFSボリュームがあり、ボリューム間でファイルを移動するとBirth VolumeIDは複数になります。
さらにBirth VolumeIDの最下位ビットは移動フラグの役割となり、ボリューム間でファイルを移動すると移動フラグがセットされます。例えばC, DドライブともにNTFSで、ObjectIDが付与されているD:\004.txtファイルをC:\に移動します。この状態でCボリュームの$ObjIdを参照すると以下の値が格納されています。
(C:\$Extend\$ObjIdファイル内抜粋)
001.txt : Birth VolumeID - A0594560EDA5A44A97C4...
003.txt : Birth VolumeID - A0594560EDA5A44A97C4...
004.txt : Birth VolumeID - 3BADA192BDC2484C87DD...
* CドライブのVolumeIDはA0594560EDA5A44A97C4...、DドライブのVolumeIDは3AADA192BDC2484C87DD...
VolumeIDは最下位ビットが0という条件がありましたが、このビットは移動フラグとなります。004.txtのBirth VolumeIDを見るとわかるように、最下位ビットが1担った結果、16進表記では2ケタ目が奇数(0,1,3,5,7,9,B,D,Fのいずれか)になります。なお、D:\004.txtに付与されたObjectIDはC:\移動後も同じ値を引き継ぎます。
つまり、Birth VolumeIDの16進表記時の2ケタ目が奇数であれば、そのファイルは元々は別ボリュームにあり、かつアクセスされていたことを示します。
リモート(ネットワーク)ドライブからのファイル移動
Birth ObjectIDとObjectIDは通常同一ですが、ファイルサーバなどのリモートのNTFSボリューム間でファイルを移動すると、Birth ObjectIDとObjectIDは異なる値になります。これはObjectIDがあるPC内ではユニークであることは保証するものの、別PCとのObjectIDとは重複する可能性があるためです。例えば、リモートのNTFSボリューム上でObjectIDが付与されているファイル005.txtをCドライブに移動します。この状態でCボリュームの$ObjIdを参照すると以下の値が格納されています。
(C:\$Extend\$ObjIdファイル内抜粋)
001.txt : ObjectID - 843C9FEDE7C8E111A078..., Birth ObjectID - 843C9FEDE7C8E111A078...
...
005.txt : ObjectID - 883C9FEDE7C8E111A078..., Birth ObjectID - 8167AD17D9C8E111B84B...
ObjectIDは新たに生成して、リモートドライブ上にファイルがあった時に付与されていたObjectIDはBirth ObjectIDとして残ります。言いかえると、ObjectIDとBirth ObjectIDが別の場合、そのファイルは元々はリモートのPCにあったことを示します。
ObjectID/VolumeIDの留意事項
ObjectID/VolumeIDの仕組みはあくまでもリンクの追跡のためであり、ファイルのコピー時には引き継がれません。ファイルをコピーすると、コピー元のファイルのObjectID/VolumeIDに変化はありませんが、コピー先のファイルには引き継がれずショートカットが作成されるまでObjectIDは付与されません。また、NTFS以外のボリュームにファイルを移動するとObjectID/VolumeIDは失われます。NTFSボリュームであってもポータブルデバイスの場合、ObjectIDは付与されますがVolumeIDが0x00000000000000000000000000000000に設定されることがあります。この場合ボリューム間の移動が発生してもObjectIDは引き継がれずに失われます。
fteの処理内容
fteのObjIDタブでボリュームを指定して実行すると、$ObjIdファイルを検索して中の情報をパースします。以下が実行結果の例です。
出力する項目の内容は以下の通りです。
- id - MFT ID
- name - ファイル名
- otime - ObjectID値のタイムスタンプ部分をデコードした結果
- objid - ObjectID
- bvolid - Birth VolumeID
- bobjid - Birth ObjectID
- remark - 未使用領域や別ドライブからの移動の検出用
otime項目をソートすることにより、PCの起動時間やファイルへのアクセス順序などがわかります。また、Birth VolumeIDやObjectIDとBirth ObjectIDを比較して、ドライブ間の移動があったパターンの場合にはremark項目に結果を表示します。"moved from local drive"の場合はローカルドライブからの移動、"moved from remote drive"の場合はリモートドライブからの移動を示します。
現在のfteの制限事項として、$ObjIdファイルの$INDEX_ALLOCATION属性のみチェックしています。ボリューム内でObjectIDが付与されている数が少ない(約5個以下の)場合には、$INDEX_ALLOCATION属性は作成されず$INDEX_ROOT属性にObjectIDが格納されます。その場合はfteでは何も結果は出しません。また、未使用領域内で見つかった項目についてはremark項目に"Found in unused area"と表示します。
参考情報
The Meaning of LIFE
http://computerforensics.parsonage.co.uk/downloads/TheMeaningofLIFE.pdf
[MS-SHLLINK]: Shell Link (.LNK) Binary File Format
http://msdn.microsoft.com/en-us/library/dd871305(v=prot.13).aspx
[MS-DLTM]: Distributed Link Tracking: Central Manager Protocol Specification
http://msdn.microsoft.com/en-us/library/cc227384(v=prot.13).aspx