Skip to content

EVTX ファイル形式を解読する:チャンク、テンプレート、BinXML 内部

.evtx ファイルがバイト レベルでどう配置されているか — ファイル ヘッダ、64 KB チャンク、テンプレート テーブル、そしてそれを参照する BinXML レコード ストリーム。

公開 1 {n} 分で読める

Windows イベント ログ形式 — .evtx — は、行指向の .evt を置き換えるために Windows Vista で導入されました。バイナリ、追記専用、チャンク化されたコンテナで、単一プロセス(EventLog サービス)が書き込み、満杯になるとローテーションまたは封印するよう設計されています。レイアウトを理解すると、フォレンジック リカバリのケース — 部分ファイル、dirty チャンク、カービング — がずっと簡単になります。

ファイル ヘッダ

すべての .evtx は 4 KB のヘッダ(ElfFile\0\0 マジック、バージョン、チャンク数、最古 / 現在のチャンク インデックス、CRC32)で始まります。ヘッダはファイルがローテートされるかチャンクが封印されるたびにその場で書き換えられます。これにより DirtyFull フラグが有用な手がかりになります:Dirty がセットされたファイルは、ホストがクラッシュした、またはディスク イメージが稼働中に取得されたときに開いていたものです。

ヘッダの後には固定サイズのチャンクのシーケンスが続きます。

チャンク(64 KB)

各チャンクは正確に 64 KB で、独自の 512 バイト ヘッダ(ElfChnk\0 マジック、チャンク内の最初と最後のレコードのログ レコード ID、ファイル オフセット、2 つの CRC32 — 1 つはヘッダ用、1 つはレコード データ用)を持ちます。チャンクは独立しています:未割り当て空間からチャンクをカービングし、ファイルの残りなしでパースできます。これが EVTX をディスク フラグメントから回復可能にする所以です。

チャンク内部。

  • 文字列テーブル — このチャンク内でインターン化された文字列、オフセットで参照される。
  • テンプレート テーブル — このチャンクのレコードが使う XML テンプレート、これもオフセット インデックス付き。
  • レコードBinXML レコードのストリーム。各々が 1 つのテンプレートとレコードごとの置換値を参照。

BinXML とテンプレート

EVTX レコードは XML テキストとして格納されません。BinXML、すなわち XML ドキュメントのトークン化されたバイナリ表現として格納されます。空間節約のため、構造的スケルトン(要素名、属性名、ツリーの形)はテンプレートとして括り出され、チャンクのテンプレート テーブルに 1 回だけ格納されます。各レコードは「テンプレート ID 5 を値 [aliceS-1-5-21-...30xc000006a] で使え」と言うだけです。

レコードの XML を再構築するため、パーサは:

  1. レコードのトークン ストリームを読む。
  2. ID でチャンクのテンプレート テーブルからテンプレートをルックアップ。
  3. レコードごとの値をテンプレートのプレースホルダ位置に代入。
  4. 結果として得られる XML を出力。

これが、パーサ(本ページのものを動かす omerbenamram/evtx を含む)がチャンクローカルなコンテキストを追跡する必要がある理由です — テンプレート ID はファイル全体で大域的ではありません。

封印済み vs dirty チャンク

EventLog サービスがチャンクへの書き込みを完了し次に進むとき、チャンクの CRC32 を計算して書き、ヘッダを Full とマークします。クリーンなファイルは最後を除くすべてのチャンクがこの状態にあります。

Dirty チャンク — 最終更新時刻がファイル ヘッダの最終更新よりあと — はライブな末尾です。多くの場合パース可能ですが、レコード ストリームがトークン途中で終わる可能性があるためツールが読むのを拒否することがあります。フォレンジックでは重要で、ホストを書き込み途中で取得した攻撃者は dirty な末尾チャンクを見ることになり、そのチャンクに対するパーサの挙動(スキップ、エラー、可能な限り復元のどれか)が分かっている必要があります。

パーシングへの実用的な含意

  • 切り詰められた .evtx稼働中のホストから収集する ときによくあるケース — でもほとんどの場合大半が回復可能 — すべての完全なチャンクは独立。
  • 未割り当てからカービングされたチャンクは合成ファイル ヘッダでラップしてパース可能。
  • 1 つのチャンクのパース失敗はファイル全体の失敗を意味しない — 堅牢なパーサは次のチャンクに進む。
  • チャンクの CRC32 が改ざんをフラグする:CRC を再計算しない改ざんされたレコードは検知可能。