ShimCache を解析する:Windows 10 と 11 のバイナリフォーマット

読了 2 分

TL;DR. 先頭 u32 = ヘッダーサイズ(典型的には 0x300x36)。そのオフセットで各エントリは 4 バイトのマジック 10ts から始まり、12 バイトのヘッダーと可変長のボディ(UTF-16LE のパス(長さ前置、NUL 終端なし)、FILETIME mtime、末尾のデータブロブ)が続きます。実行フラグは Windows 10 で廃止されました。

XP 以降の Windows は、バージョンごとに異なる ShimCache レイアウトを採用してきました。Windows 10 / 11 のバリエーションは、今日の調査員が最も多く遭遇するもので、ルールさえわかれば解析は比較的容易です。本稿はそのフォーマットを最初から最後まで辿ります。

Windows 10/11 ShimCache エントリのバイナリレイアウト

解析対象の Blob

出発点は次の場所のバイナリ値です。

HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache\AppCompatCache

SYSTEM ハイブからこの値を取り出した状態(ShimCache の保存場所を参照)であれば、手元には数十 KB から数百 KB の単一の Blob があります。Blob には小さなヘッダの後に、既知のマジック値で始まるエントリ列が続きます。

ヘッダ

Blob の最初の 4 バイトの little-endian 値は、最初のエントリへのオフセット を表します。Windows 10 / 11 ではビルドによって 0x300x340x350x36 のいずれかが多いです。0x80 を置くハイブもあり、これは同じ 10ts / 00ts エントリ署名を用いる Windows 8.x レイアウトを示します。

防御的なパーサはヘッダサイズをハードコードしません。最初の u32 を読み、そのオフセットのバイトが既知のエントリの先頭であることを検証します。宣言されたオフセットに 10ts00ts も見当たらない場合は、10ts を前方検索して再開してください — 実システムが時折生成するわずかに規格外なハイブを扱えます。

Windows 10 / 11 エントリのバイト構造

各エントリは 4 バイトのシグネチャ 10ts0x31 0x30 0x74 0x73)から始まります。完全なレイアウトは次のとおりです。

オフセットサイズフィールド
0x004マジック — "10ts"
0x044シーケンス / 不明(パーサで無視されることが多い)
0x084エントリデータサイズ — このフィールド以降のバイト数
0x0C2パスサイズ(バイト数、UTF-16LE)
0x0ENパスバイト列(UTF-16LE、終端なし
0x0E + N8最終更新時刻 — FILETIME(1601-01-01 UTC からの 100 ns 単位)
0x16 + N4末尾データサイズ
0x1A + NM末尾データ(通常は空または小さい)

エントリの総サイズは 0x0C + entry_data_size です。次のエントリはその直後から始まります。

実務上の 2 点:

  1. パスは UTF-16LEヌル終端ではありません。パスサイズフィールドを使ってください — ヌルまで読んではいけません。
  2. FILETIME はファイルの $STANDARD_INFORMATION mtime であり、プログラムの実行時刻ではありません。理由は 実行証明に関する記事 を参照。

Windows 10 で消えたもの

旧バージョンの Windows は、各エントリ内に Executed フラグを格納していました。Windows 10 / 11 ではこのフラグが完全に削除されています。キャッシュ内には実行を判定する手段がありません — Prefetch、AmCache、イベントログ が必要です。

実装の指針

堅牢なパーサは次のように動作します。

  1. ヘッダが指すオフセットで 4 バイトのマジックを検証する。
  2. エントリデータサイズを読みながら順に進める。
  3. パスを UTF-16LE としてデコードする。
  4. FILETIME を下流ツールが扱いやすい時刻形式(Unix ミリ秒など)に変換する。
  5. OS フォーマットラベル(Windows 10/11、8.x、8.0 の別)を露出して下流のフィルタに供する。

実装の参照例として、オープンソースの Shimcache Parser は上記アルゴリズムを Rust で実装し、ブラウザに WebAssembly として配信します — サーバなし、アップロードなしです。

リファレンス実装

関連記事