狩る側と狩られる側の境界線:メモリフォレンジックによるC2通信の炙り出し
インシデントレスポンスの現場において、ネットワーク機器のログやEDRのアラートは常に「後手の情報」に過ぎない。高度な攻撃者は、初期侵入を果たしたその瞬間に、EDRのユーザーランド(リング3)フックを回避するためのAPIフッキング無効化、あるいは直接的なシステムコール(ダイレクト・システムコール)の実行によって、既知の監視レイヤから身を隠す。
だが、どれほど巧妙にディスク上の証拠を消し去り、プロセスの偽装を行おうとも、彼らが外部のCommand and Control(C2)サーバーと通信を維持している限り、カーネル空間の揮発メモリ(RAM)には必ずその痕跡が刻まれる。物理法則に逆らえないのと同様に、OSがTCP/IP通信を行うためには、カーネル内のネットワークスタック構造体を必ず実メモリ上に展開し続けなければならないのだ。
今回は、Volatilty 3等のメモリフォレンジックフレームワークを用いた netscan プラグインの深層活用を通じ、現代のサイバー犯罪者が用いるネットワーク隠蔽手法をいかにして暴き、アナリストが死角をつくべきかを実戦的な文脈で紐解いていく。
—
1. なぜディスクではなくメモリなのか:カーネル空間のネットワーク構造体
現代のマルウェア解析において、ディスクフォレンジックはすでに「死亡診断書」の作成に等しい。ランサムウェアが暴れ回った後や、APTグループが痕跡をワイパーで消し去った後では、手遅れであることが多い。ここで頼りになるのがメモリフォレンジックだが、その真価は「OSが何を知っているか」ではなく「OSが何を隠しきれていないか」を暴く点にある。
Windows OSにおいて、ネットワーク接続情報はカーネルメモリ上の ._EPROCESS 構造体配下にある ._PEB や、より直接的にはネットワークスタックの核心である TCP_ESTATE や ._KPROCESS と結びついたドライバ(tcpip.sys)のプール領域に保持される。
ダイレクト・カーネル・オブジェクト・マニピュレーション(DKOM)の限界
高度なルートキットは、DKOM(Direct Kernel Object Manipulation)を用いて、アクティブなプロセスリスト(ActiveProcessLinks)から自身のプロセスを切り離し、タスクマネージャーや一般的なセキュリティツールから姿を消す。しかし、tcpip.sys が管理するネットワークの接続プール(Endpoint / Listener)まで完全に切り離すことは極めて困難である。なぜなら、カーネルがパケットを正しくルーティングし、ACKを返し続けるためには、TCPコントロールブロック(TCB)のリンクを維持し続ける必要があるからだ。
ここに、攻撃者の最大の矛盾が生じる。「通信したいがためにカーネル内に存在せざるを得ない構造体」を、フォレンジックアナリストは見逃さない。
—
2. netscan プラグインの内部動作とスキャンロジック
Volatility 3における windows.netscan プラグインは、従来の connscan や sockets プラグインを統合し、より広範なネットワークアーティファクトを検出する。このプラグインがどのようにしてメモリから接続情報を復元しているのか、そのメカニズムを理解しておく必要がある。
netscan は、カーネルメモリプール(特に tcpip.sys が利用するプールタグや、ネットワーク関連のオブジェクトプール)をスキャンし、既知の構造体シグネチャ(プールヘッダやTCBのパターン)を総当たり的にパターンマッチング(カーネルプール・スキャニング)する。
これにより、以下の情報が抽出される。
- プロトコル: TCP v4 / v6, UDP v4 / v6
- ローカルアドレスおよびポート
- リモートアドレスおよびポート
- 接続状態: ESTABLISHED, LISTENING, TIME_WAIT など
- 生成元プロセス: PIDとプロセス名
- タイムスタンプ: 接続(または解放)の痕跡
隠蔽された接続の検出
通常のOS API(GetExtendedTcpTable など)は、rootkitによってフックされている場合、不正な接続を隠蔽して返す。しかし、netscan はAPIを経由せず、物理メモリの生データから直接プールを走査するため、APIレベルで隠蔽されたコネクションであっても容赦なく炙り出すことができる。
—
3. 実践:Volatility 3によるC2セッションの特定とトリアージ
実際のインシデントレスポンスにおいて、取得したメモリイメージ(RAWダンプ)から不審なネットワーク接続を特定し、関連するプロセスをあぶり出すまでのワークフローをコマンドラインベースで解説する。
ステップ1: ネットワーク接続一覧の抽出
まずは、ダンプされたメモリイメージに対して netscan を実行する。出力結果をファイルにリダイレクトしつつ、解析に必要な情報を絞り込む。
# Volatility 3を使用してメモリイメージからネットワーク接続情報を抽出する例
python3 vol.py -f suspicious_memory_dump.raw windows.netscan > netscan_results.txt
出力結果のフォーマットは概ね以下のようになる。
Grid
Offset Proto Local Address Foreign Address State Pid Owner Created
------------------------------------------------------------------------------------------------------------------------------------
0xfa8003a2b100 TCPv4 192.168.1.50:49154 185.220.101.5:443 ESTABLISHED 3412 updater.exe 2023-10-25 14:10:22
0xfa8004c12340 TCPv4 0.0.0.0:4444 0.0.0.0:0 LISTENING 4820 svchost.exe 2023-10-25 11:00:05
ステップ2: 異常性の評価(アナリストの眼)
上記の出力結果から、以下のポイントに着目してトリアージを行う。
1. 予期せぬ外部IPアドレス:
updater.exe のような正当性を装ったプロセスが、Torの出口ノードや、Known Badな脅威インテリジェンス(TI)にヒットする海外のVPSプロバイダ(例: Bulletproof Hosting事業者)と ESTABLISHED 状態になっている。
2. 不審なリスニングポート:
システムプロセスであるはずの svchost.exe が、Metasploitのデフォルトポートである 4444 や、一般的なバックドアが好む高位ポートで LISTENING になっている。これはプロセスインジェクションや、サービスDLLハイジャックの明白な兆候である。
ステップ3: 関連プロセスのメモリダンプと解析
不審なPID(例: 3412)が特定できたら、そのプロセスのメモリ空間を切り出し、マルウェアのバイナリ本体や、メモリ上に展開されたペイロード(シェルコードや設定情報)を回収する。
# 不審なPIDを指定してプロセスをメモリから切り出す
python3 vol.py -f suspicious_memory_dump.raw windows.dumpfile --pid 3412
切り出されたファイル(pid.3412.dmp など)に対して strings やYARAスキャンをかけ、C2のハードコードされたドメイン名や、通信に用いられるカスタム暗号化の鍵構造を特定する。
—
4. 攻撃者の進化とフォレンジックの未来
攻撃者もただ指をくわえて見ているわけではない。彼らはメモリフォレンジックの目をかいくぐるための新しい手法を次々と実戦投入している。
- ファイルレス・マルウェアとメモリ難読化:
プロセスホロウイングやリフレクティブDLLインジェクションに加え、メモリ上の文字列やAPIインポートテーブルを動的に暗号化し、静的なパターンマッチングや単純な文字列検索を無効化する手法が主流になっている。
- 直接的ネットワークスタック操作:
ユーザースペースのAPIだけでなく、tcpip.sys の内部関数テーブルを直接書き換え、特定のIPレンジやポートに関する情報をカーネルプールスキャンからも隠蔽しようとする試み(Direct Kernel Object Unlinkingの高度化)が研究されている。
これに対抗するため、我々DFIRエンジニアは、単なるツールの実行結果の読み解きにとどまらず、カーネルのデータ構造そのものの深い理解と、メモリ上の非連続な断片を再構成する能力が求められる。
ネットワーク接続情報は、攻撃者が残した「デジタルな足跡」の中で最も消去しにくい生きた証拠である。メモリを制する者が、インシデントレスポンスを制す。この原則は、今後どれほど技術が高度化しようとも変わることはない。
コメント