序論:揮発する証拠と、静かに残る「記憶の澱」
高度な標的型攻撃(APT)を仕掛ける攻撃者は、自らの足跡を消すことに長けている。彼らは侵入後、イベントログを消去し、プリフェッチ(Prefetch)ファイルを削除し、タイムスタンプを偽装(Timestomping)してフォレンジック調査を攪乱する。しかし、Windowsカーネルがシステムの互換性を維持するために執拗に記録し続ける「Shimcache(AppCompatCache)」までを完璧に、かつ不自然な痕跡を残さずに操作することは極めて困難だ。
多くのジュニアアナリストは、SYSTEMハイブのレジストリを解析して満足する。だが、我々シニアレベルの人間が真に注視すべきは、シャットダウンや再起動が行われる前の「メモリ上にのみ存在する最新のShimcacheステート」である。
本稿では、DFIRの現場で勝敗を分けるShimcacheの内部構造と、メモリフォレンジックを通じた実行履歴の特定、そして攻撃者が仕掛ける偽装工作をいかにして見破るかについて、深く掘り下げていく。
—
1. Shimcacheの深層解剖:互換性維持という名の「記録装置」
Shimcache(正式名称:Application Compatibility Cache)は、Windowsが実行ファイルの互換性問題を解決するために導入された仕組みだ。ファイルが実行、あるいは単に「フォルダ参照」などでOSのローダーに触れた際、そのパス、サイズ、最終更新日時(Standard Information属性)が記録される。
1.1 実行と存在の境界線
Shimcacheの最も厄介で、かつ興味深い点は、「記録されている=実行された」とは限らないという点だ。
しかし、Windows 7/8/10/11と進化する過程で、実行フラグの有無や記録タイミングのロジックは変化してきた。
- Windows 7まで: 実行フラグが存在し、明示的に実行されたかを確認できた。
- Windows 8以降: 実行フラグが構造体から事実上消え、ファイルが「存在した」ことの証明に重きが置かれるようになった。
我々アナリストは、Shimcacheを「実行ログ」ではなく、「攻撃者がシステムに持ち込み、OSが認識したバイナリのインベントリ」として扱うべきだ。
1.2 メモリとレジストリの同期ラグ
ここがDFIRにおける最大の盲点だ。Shimcacheのデータは通常、メモリ上のカーネル空間(ntoskrnl.exeの管理下)に保持されており、レジストリ(HKLM\SYSTEM\CurrentControlSet\Control\Session Manager\AppCompatCache)に書き出されるのはシステムのシャットダウン時のみである。
つまり、攻撃者が攻撃を終えてシステムを稼働させたまま立ち去った場合、ディスク上のレジストリを解析しても最新のマルウェア実行痕跡は出てこない。ライブメモリ、あるいはメモリダンプからの抽出が不可欠な理由はここにある。
—
2. メモリフォレンジックによるShimcache抽出の実践
生のメモリダンプからShimcacheを抽出するには、Volatilityなどのフレームワークを利用するのが定石だ。しかし、ツールを叩くだけでは不十分だ。抽出されたデータの「意味」を解釈する能力が問われる。
2.1 Volatilityによる解析例
以下は、メモリイメージからShimcacheをパースする際の思考プロセスだ。
# Volatility 3を使用してShimcache(AppCompatCache)をスキャン
python3 vol.py -f suspicious_memdump.mem windows.shimcache.Shimcache
このコマンドが返す出力結果には、以下の要素が含まれる。これらをどう読み解くかがプロの腕の見せ所だ。
| フィールド | 調査の着眼点 |
| :— | :— |
| Path | C:\Windows\Temp や C:\Users\Public などの書き込み権限が緩いパスに不審な .exe や .dll がないか。 |
| Last Modified Time | ファイル自体のタイムスタンプ。攻撃者が Timestomping を行っている場合、MFT(Master File Table)との乖離をチェックする。 |
| Order (Index) | ShimcacheはLIFO(Last In, First Out)形式で保持される。最新の実行ファイルほどインデックスが若い。 |
2.2 構造体のバイナリ解析(低レイヤの視点)
Shimcacheのデータ構造はWindowsのバージョンごとに異なるが、基本的には AppCompatCache エントリのリストだ。メモリ上の構造をパースするロジックをPythonの疑似コードで示す。
import struct
# Shimcacheのエントリ構造 (Windows 10 64bitの簡略化モデル)
# シニアアナリストは、オフセットのズレからOSのパッチレベルを推察することもある
def parse_shimcache_entry(buffer, offset):
# 先頭のシグネチャやサイズを確認
# Windows 10では、パスの長さ(2バイト) + パス文字列(Unicode)の構成
path_len = struct.unpack_from('<H', buffer, offset)[0]
if path_len == 0:
return None
# パス文字列の抽出 (UTF-16)
path = buffer[offset+2 : offset+2+path_len].decode('utf-16le', errors='replace')
# 最終更新日時 (FILETIME形式: 8バイト)
# ここに記録される時間は「実行時間」ではなく「ファイルの最終更新日時」であることに注意
last_mod_nanos = struct.unpack_from('<Q', buffer, offset + 2 + path_len)[0]
return {
"path": path,
"last_modified": last_mod_nanos
}
# 注意: 実際のフォレンジックでは、コントロール領域やフラグビットの解析も並行して行う
—
3. 攻撃者の隠蔽工作(Evasion)と対抗策
チーフホワイトハッカーとして、攻撃者の心理を先回りしよう。彼らはShimcacheの存在を知っている。
3.1 タイムストンピング(Timestomping)
攻撃者はマルウェアのタイムスタンプを kernel32.dll などと同じ日時に書き換える。しかし、Shimcacheに記録されるタイムスタンプは、ファイルがキャッシュに登録された瞬間の「ディスク上のタイムスタンプ」だ。
もし、$MFT 上の Standard_Information(SI)属性と FileName(FN)属性に乖離があり、かつShimcacheの記録が不自然に古い日付を示しているなら、それはタイムストンピングの強力な証拠となる。
3.2 サービス実行とインジェクション
Shimcacheは「ファイル」ベースの互換性管理だ。Process Hollowing や Reflective DLL Injection のように、ディスクにファイルを落とさずメモリ上だけで展開されるペイロードは、Shimcacheには残らない。
この場合、我々はShimcacheの「欠落」を証拠とする。Shimcacheには不審な記録がないのに、ネットワーク接続(netstat)やプロセスメモリの不審なセグメント(VAD解析)に異常がある場合、それは「ファイルレス攻撃」のシグネチャだ。
—
4. 監査と防御アーキテクチャへのフィードバック
Shimcache解析から得られた知見を、単なる「事後報告」で終わらせてはならない。
1. EDRの検知ロジック最適化:
Shimcacheに記録されたパスが、ホワイトリスト(C:\Program Files 等)外である場合、そのバイナリのハッシュを即座に特定し、フリート全体でスキャンをかける自動化パイプラインを構築する。
2. 揮発性データの定期的保全:
シャットダウンを待たずに、重要なエンドポイントからは定期的に AppCompatCache のメモリ内ステートを収集する仕組み(例:OSQueryや独自のIRエージェント)を導入する。
3. 生成AIを用いた相関分析:
Shimcache、Amcache、Prefetch、MFTの4つのタイムスタンプをAIに入力し、人間では気づきにくい数秒・数ミリ秒単位の「時間軸の矛盾」を自動検出するガードレイルを設計する。
結論:見えない糸を手繰り寄せる
Shimcacheは、WindowsというOSがスムーズに動くために吐き出す「排熱」のようなものだ。しかし、その熱の中には、攻撃者が確かにそこにいたという体温が残っている。
低レイヤのメモリ挙動を理解し、ツールが吐き出す結果の裏側にある構造体レベルのロジックを把握すること。それこそが、巧妙に隠蔽されたインシデントの真実を暴く、唯一の道である。我々DFIRのプロフェッショナルにとって、Shimcacheは単なるキャッシュではない。それは、サイバー空間における「消せない指紋」なのだ。
コメント