幽霊はRAMに宿る:Volatility 3による揮発性メモリ解析の深淵
インシデントレスポンスの現場において、ストレージのフォレンジック(死体検視)だけでは攻撃の全貌を捉えられない時代になって久しい。現代の高度な脅威アクター(APT)やランサムウェアのオペレーターは、ファイルレスマルウェア、インメモリ・インジェクション、さらには反射型DLLロード駆使し、ディスク上に痕跡を残さない「生きた」侵入を試みる。彼らが活動の足場を築くのは、いつだって揮発性メモリ(RAM)の深淵だ。
電源を落とせば消え失せるデータの中にこそ、攻撃者の真の足跡が残されている。今回は、オープンソースのメモリフォレンジックフレームワークである Volatility 3 を用い、プロセスリストやネットワーク接続情報といった揮発性アーティファクトをいかにして抽出し、解読するか。その実戦的なアプローチを、低レイヤの挙動とともにお伝えしよう。
—
1. 現場の現実:なぜ「生きたメモリ」をキャプチャするのか
ディスクフォレンジックは、いわば事件現場の鑑識作業であり、すでに終わった犯行の痕跡を回収する作業だ。しかし、メモリフォレンジックは、心臓がまだ動いている状態でのバイタルサイン測定に等しい。
攻撃者が利用する Reflective DLL Injection や Process Hollowing といった手法は、正当なプロセス(例えば svchost.exe や explorer.exe)の仮想アドレス空間の一部を書き換え、あるいは不正なコードをインジェクションして実行する。ディスク上のバイナリは完全な「クリーン」な状態を保ったまま、メモリ上だけで悪意ある挙動が展開されるため、静的なファイルスキャンすり抜けられてしまう。
ここで、OSの仮想メモリ管理機構、ページテーブル、そしてプロセス制御ブロック(EPROCESS構造体など)の内部構造を理解しているアナリストだけが、隠された真実を引き出すことができる。
—
2. Volatility 3のセットアップとアーキテクチャの理解
かつての Volatility 2 はPython 2に依存し、プロファイル(シンボルテーブル)の事前準備やバージョン依存性の地獄に悩まされたものだ。しかし、完全に書き直された Volatility 3 は、Python 3への完全移行を果たし、シンボル情報を動的に解決するアーキテクチャを手に入れた。
まずは、実戦で即座に使える環境構築の基本を押さえておこう。
環境構築と基本コマンド
通常、解析専用のクリーンなワークステーション(Linux環境推奨)上でPython仮想環境を構築し、公式リポジトリからインストールを行う。
# 作業用ディレクトリの作成と仮想環境の有効化
python3 -m venv vol3_env
source vol3_env/bin/activate
# Volatility 3本体のクローンとインストール
git clone https://github.com/volatilityfoundation/volatility3.git
cd volatility3
pip install -e .
# インストールされたプラグインとバージョンを確認する
python3 vol.py -h
メモリダンプファイル(memdump.raw や .dmp)を手に入れたら、最初に実行すべきはOSやカーネルのプロファイルを自動判別し、基本的なプロセス構造体をリストアップすることだ。
—
3. プロセスリストの抽出:隠されたプロセスの炙り出し
メモリ上のプロセスを列挙する際、実務で最も直面するのが「通常のタスクマネージャーや ps コマンドでは見えないプロセス」の存在だ。マルウェアは、OSのプロセスリスト(ActiveProcessLinks二重連結リスト)から自身のノードを切り離す DKOM (Direct Kernel Object Manipulation) を用いて姿を隠す。
Volatility 3では、複数の異なる視点からプロセスを列挙することで、この隠蔽工作を暴く。
windows.pslist と windows.psscan の比較
windows.pslist: OSのカーネルが管理する通常のプロセスリスト(ActiveProcessLinks)を辿ってプロセスを表示する。windows.psscan: メモリプールを直接スキャンし、プロセスオブジェクトの目印となるプールタグ(WindowsではProc等)を総当たりで検出する。
もし pslist には現れないが psscan にのみ存在するプロセスがあれば、それはプロセスアンリンク(DKOM)を実行した隠しプロセス、あるいはすでに終了したプロセスの残骸(ゾンビ状態)である可能性が極めて高い。
# カーネルのリンクリストをベースにしたプロセス列挙
python3 vol.py -f /path/to/memdump.raw windows.pslist
# メモリプールスキャンによる隠しプロセス(DKOM検出)の炙り出し
python3 vol.py -f /path/to/memdump.raw windows.psscan
ここで得られた出力結果から、親プロセスID(PPID)と子プロセスの関係、実行バイナリのパス、そしてプロセスが生成されたタイムスタンプを精査し、不自然なツリー構造(例: cmd.exe から不審なPowerShellが起動し、さらに外部通信を行っている等)を特定する。
—
4. ネットワーク接続情報の抽出:C2通信の痕跡を掴む
プロセスが特定できたら、次に確認すべきはネットワークの状況だ。攻撃者は侵入後、必ず外部のC2(Command and Control)サーバーとの間で通信を確立するか、あるいは内部ネットワークへのラテラルムーブメント(横展開)を試みる。
Windowsのネットワークスタックは複雑であり、TCP/IPドライバ(tcpip.sys)の内部構造体(TCPListener、TCPEndpoint、UDPEndpointなど)を解析する必要がある。
windows.netstat プラグインの活用
Volatility 3の windows.netstat プラグインは、メモリ上のネットワーク関連構造体を走査し、アクティブなコネクション、リスニングポート、関連するプロセスID(PID)をマッピングする。
# メモリダンプからネットワーク接続状況を抽出する
python3 vol.py -f /path/to/memdump.raw windows.netstat
【実務での着眼点】
- 孤立したコネクション: 既に終了したはずのプロセスや、
pslistで正体が掴めないプロセスが外部IPアドレスとセッションを維持していないか。 - 不審なポートバインド: 管理外の高位ポートや、既知のマルウェアが好んで使用するポート(例: 4444, 8080等)でリッスンしているプロセスはないか。
- 親プロセスの正当性: 例えば
lsass.exeやcsrss.exeのようなシステムプロセスが直接外部と通信している場合、それはプロセスインジェクションによって乗っ取られている明白なシグナルである。
—
5. 発展:インメモリ・インジェクションの検知と次の一手
プロセスリストとネットワーク接続情報を手に入れただけでは、真のインシデントレスポンスとは言えない。真の脅威ハンターは、そこからさらに踏み込み、メモリ上のコード片そのものを抽出する。
例えば、不審なプロセスの仮想メモリ領域をダンプするには windows.memmap や windows.dumpfiles プラグインを使用する。
# 特定の不審なPID(例: 3120)の仮想メモリ領域をファイルとして書き出す
python3 vol.py -f /path/to/memdump.raw windows.memdump --pid 3120
こうして抽出したバイナリを、Yaraルールを用いたスキャンにかけたり、リバースエンジニアリングツール(GhidraやIDA Pro)に投入して静的解析を行うことで、マルウェアのペイロードや設定情報(C2のドメイン名、暗号化キーなど)を完全な形で回収することができる。
—
結びに代えて:泥臭い解析の先にあるもの
高度化するサイバー攻撃の前に、シグネチャベースの防御や自動化されたアラートだけでは限界がある。攻撃者が巧妙にシステム内部へ潜伏し、証拠を隠滅しようと試みるとき、最後に頼りになるのは「RAMの中に残された生々しい物理的事実」だ。
コマンドの構文やツールの使い方を覚えることは、フォレンジックのスタートラインに立ったに過ぎない。重要なのは、その出力結果の裏にあるOSの内部構造、メモリ管理のメカニズム、そして攻撃者のロジックを立体的に想像する力である。
幽霊はRAMに宿る。その姿を暴くのは、他の誰でもない、画面の前に座るアナリストの執念なのだから。
コメント