午前2時の亡霊:なぜディスクフォレンジックは失敗するのか
午前2時、私は端末の前に座り、まるで何かに取り憑かれたかのような挙動を示すUbuntuウェブサーバーを監視していました。これは、実戦的なLinuxインシデントレスポンスの知見が試される瞬間でした。全コアのCPU使用率は98%に達しているにもかかわらず、topコマンドが報告するロードアベレージはほぼゼロでした。/var/log/auth.logや/var/log/syslogを徹底的に調べましたが、それらはあまりにも「綺麗」すぎました。
攻撃者は用意周到でした。ログを消去し、lsやpsといった標準的なツールから自身の存在を隠すためにルートキットを導入していたのです。これはスクリプトキディによる犯行ではなく、システムの揮発性メモリ内に完全に居座る執拗な脅威でした。
侵入がこれほどまでに隠密なレベルに達すると、ハードドライブをチェックしても行き止まりです。ディスクフォレンジックは「過去」を示しますが、メモリフォレンジックは「今この瞬間」を明らかにします。Volatility 3は、効率的なLinuxインシデント対応において不可欠なツールです。これを使えば、侵害されたオペレーティングシステムをバイパスして、攻撃者が何を見せようとしているかに関わらず、カーネルが実際に何を行っているかを正確に把握できます。
分析ラボの構築
このガイドではVolatility 3を使用します。Volatility 2は10年間にわたりコミュニティに貢献してきましたが、現代のLinuxカーネルへの対応に苦慮しており、古いPython 2の依存関係に頼っています。Volatility 3は大幅に高速化されており、シンボルファイルの処理もはるかにスムーズです。
1. ツールキットのセットアップ
分析は必ず、あらかじめLinuxの要塞化が施されたクリーンなマシンで行ってください。感染したホスト上でフォレンジックツールを実行すると、マルウェアに察知されたり、証拠が破損したりするリスクがあります。まずはコアとなる依存関係をインストールしましょう:
sudo apt update
sudo apt install -y python3 python3-pip git
git clone https://github.com/volatilityfoundation/volatility3.git
cd volatility3
pip3 install -r requirements.txt
2. RAMイメージの取得
調査を開始する前に、RAMのスナップショットが必要です。Linuxを対象とする場合、Microsoft製の**AVML** (Acquire Volatile Memory Dump) をお勧めします。これはスタティックバイナリであるため、対象のマシンにライブラリをインストールする必要がありません。これにより、フォレンジックによる痕跡を最小限に抑え、「観測者効果」による証拠の変質を防ぐことができます。
対象のマシンで以下のコマンドを実行し、mem.dumpファイルを生成します:
# スタティックバイナリをダウンロード
wget https://github.com/microsoft/avml/releases/download/v0.14.0/avml
chmod +x avml
# 16GBまたは32GBのメモリイメージをキャプチャ
sudo ./avml mem.dump
完了したら、SFTPや安全なドライブを使用して、そのmem.dumpファイルを分析用のワークステーションに移動します。
シンボルの壁:データを理解するために
Linuxカーネルは非常に多様であるため、メモリ分析は一筋縄ではいきません。Microsoftのサーバーからシンボルを取得できるWindowsとは異なり、Linuxでは特定のカーネルバージョン(例:5.15.0-71-generic)に一致する中間シンボルファイル(ISF)が必要です。
多くのエンジニアがここで躓きます。まず、Volatilityがイメージを識別できるか確認します:
python3 vol.py -f mem.dump banner.Banner
バナーからカーネルバージョンが判明しても他のプラグインが失敗する場合は、シンボルを提供する必要があります。Ubuntuのような標準的なディストリビューションの場合、dwarf2jsonツールを使用してデバッグシンボルをVolatilityが理解できる形式に変換できます。このガイドでは、生成されたJSONファイルをvolatility3/symbols/linux/に配置済みであると仮定します。
調査の開始:パン屑リストを辿る
環境が整ったら、本格的なマルウェアハンティングを開始します。私は通常、侵入経路、永続化メカニズム、そしてC2(コマンド&コントロール)へのコールバックの3点に注目します。
1. 隠しプロセスの追跡
攻撃者はしばしば、カーネル内のtask_structリストからプロセスを切り離すことで、プロセスを隠蔽します。pslistはカーネルが認識している実行中のプロセスを表示しますが、psscanは「亡霊」を見つけ出します。
python3 vol.py -f mem.dump linux.pslist.PsList
python3 vol.py -f mem.dump linux.psscan.PsScan
2つの出力を比較してください。プロセスがpsscanには存在するがpslistには存在しない場合、隠しプロセスを発見したことになります。kworker_unboundのような不審な名前や、本来あるはずのないroot権限で動作しているプロセスを探してください。
2. ネットワークテレメトリの分析
侵害されたサーバーは、ほとんどの場合、マスター(攻撃者)と通信を行います。攻撃者が稼働中のシステム上でnetstatからソケットを隠したとしても、接続データはRAMに刻み込まれたままです。
python3 vol.py -f mem.dump linux.netstat.NetStat
4444や31337といった大きな番号のポートへの接続を検索してください。既知のCDNや管理用レンジ外のIPアドレスを探します。不審なIPへの接続が見つかったら、直ちにそのプロセスID(PID)をメモしてください。
3. 注入されたコードの特定
高度なマルウェアは、nginxやsystemdのような正当なプロセスにシェルコードを注入することがよくあります。malfindプラグインは、書き込み可能かつ実行可能なメモリ領域を特定します。これは重大な警告サインです。
python3 vol.py -f mem.dump linux.malfind.Malfind
malfindが領域をフラグ立てすると、ヘキサダンプが表示されます。ELFヘッダーやNOPスレッド(0x90バイトの長い連続)を探してください。これらは、実行を待機しているペイロードの明らかな兆候です。
4. カーネルレベルのフックを暴く
最も危険なルートキットは、システムコールテーブルを「フック」します。彼らはreadなどの呼び出しを傍受してファイルを隠したり、getdentsを傍受してディレクトリを隠したりします。これは通常のLinuxファイル改ざん検知ツールすら回避する高度な攻撃です。
python3 vol.py -f mem.dump linux.check_syscall.Check_syscall
システムコールがコアカーネル(vmlinux)外のメモリアドレスを指している場合、Volatilityはそれをハイライトします。これはカーネルレベルで侵害されている決定的な証拠(スモーキング・ガン)です。
フォレンジックのマインドセット
分析の成功は、単にコマンドを実行することではなく、「ストーリー」を組み立てることにあります。不審なネットワーク接続から特定のPIDを特定し、そのPIDに対してmalfindを実行して注入されたコードを確認します。最後に、lsofプラグインを使用して、攻撃者が削除する前にそのプロセスがどのファイルに触れていたかを確認します。
python3 vol.py -f mem.dump linux.lsof.Lsof --pid <不審なPID>
メモリフォレンジックは、侵害されたOSが隠そうとする真実を可視化します。漠然とした疑念を、確かな技術的証拠へと変えてくれます。このデータこそが、インフラを再構築し、攻撃者の再侵入を防ぐために必要なものです。

