【実務・中級編】 メモリ上のファイルレスマルウェアの抽出と静的解析への引き渡し – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

「ディスクには何も残さない」という悪夢:メモリフォレンジックで紐解くファイルレス攻撃の正体

現場でインシデント対応をしていると、「サーバーに侵入された痕跡があるのに、ログを漁っても不審なファイルが見当たらない」という相談をよく受ける。これが現代の攻撃者の常套手段、ファイルレス・マルウェアだ。

彼らはディスクにマルウェアを書き込むような古典的なことはしない。メモリ(RAM)上だけで動作し、OSの正規のプロセスにコードを注入(Process Injection)して居座る。ディスクをスキャンしても何も検知できないため、従来のアンチウイルスソフトは無力化されることが多い。今日は、この「幽霊」をいかにしてメモリから引きずり出し、GhidraやIDA Proで解析可能な形に落とし込むか、その泥臭いプロセスを共有しよう。

—

1. 現場の現実:メモリから「ナマのコード」を救い出す

メモリフォレンジックの王道ツールといえば Volatility だ。しかし、単にダンプを取るだけでは終わらない。重要なのは、攻撃者が注入した「不正なメモリ領域」をどう特定し、それをどうバイナリとして復元するかだ。

攻撃者は往々にして、VirtualAllocEx などのAPIを悪用し、正規プロセス(explorer.exe や svchost.exe など)の中に実行可能領域を確保する。

解析のワークフロー

1. メモリダンプの取得: DumpIt 等でフルダンプを取得。
2. 不審なVAD(Virtual Address Descriptor)の探索: volatility3 を使い、windows.vadinfo を実行する。ここで PAGE_EXECUTE_READWRITE(RWX)属性を持つ領域を特定するのが定石だ。
3. バイナリの抽出: 特定した領域のオフセットを基に windows.vaddump を実行し、RAWデータを切り出す。
4. 再構成(Reconstruction): 切り出したデータにはPEヘッダーが欠けていることが多い。必要に応じて、手動でPEヘッダーをパッチし、IDA Proで読み込める状態にする。

ここで重要なのは、「機械的にツールを回すな」ということだ。メモリ上の文字列やAPIインポートテーブルの断片から、攻撃者が何をしようとしているのか、その動機を読み取る洞察力が、解析者には求められる。

—

2. ファイルレス攻撃を「根絶」するための防御実装

ファイルレス攻撃の多くは、PowerShellの悪用や、WMI(Windows Management Instrumentation)を経由したリモート実行から始まる。これらを防ぐための確実な防御策は、「実行権限の最小化」と「スクリプト実行ポリシーの厳格化」に尽きる。

実践:PHPにおける「コマンドインジェクション」を殺す

Webアプリの脆弱性が攻撃の足がかりになることは非常に多い。バックエンドで exec() や system() を使う際は、シェルを直接呼び出すのではなく、引数を厳密にエスケープし、許可されたコマンド以外を弾く実装が必要だ。

<?php
/**
 * 脆弱な実装例: exec("ping " . $_GET['host']);
 * これだと攻撃者は "127.0.0.1; powershell -Command ... " と送り込んでくる。
 */

function safe_ping($host) {
    // 1. ホワイトリストによるバリデーション
    if (!filter_var($host, FILTER_VALIDATE_IP)) {
        throw new Exception("不正なIPアドレス形式です");
    }

    // 2. シェルを経由せず、引数を配列として渡す (PHP 7.4+以降の推奨)
    // execの代わりにproc_openを使い、環境変数や入出力を制御する
    $descriptorspec = [
        0 => ["pipe", "r"], // stdin
        1 => ["pipe", "w"], // stdout
        2 => ["pipe", "w"]  // stderr
    ];

    // コマンドは配列で渡し、シェルインジェクションを防ぐ
    $process = proc_open(['/usr/bin/ping', '-c', '1', $host], $descriptorspec, $pipes);
    
    if (is_resource($process)) {
        $output = stream_get_contents($pipes[1]);
        fclose($pipes[0]); fclose($pipes[1]); fclose($pipes[2]);
        proc_close($process);
        return $output;
    }
}
?>

インフラ設定:PowerShellのロックダウン

Windowsサーバーを運用しているなら、PowerShellの実行ポリシーを強制し、ログを集中管理すること。

# 管理者権限で実行:スクリプト実行を制限し、ログを厳格化する
Set-ExecutionPolicy RemoteSigned -Scope LocalMachine

# Script Block Loggingを有効化(攻撃者のコマンドをログに残す)
# グループポリシー設定: 
# [管理用テンプレート] > [Windows コンポーネント] > [Windows PowerShell] 
# > [PowerShell スクリプト ブロックのログ記録を有効にする] を「有効」に設定

—

3. 最後に:エンジニアが持つべき「疑心暗鬼」

ファイルレス攻撃は、システムが「正常に動いている」ように見えても、裏で静かにデータを持ち出している可能性がある。

解析の現場では、「ツールが何も言わない=安全」という思い込みが最大の脆弱性だ。プロセスツリーを眺め、親プロセスが不自然な子プロセスを生成していないか、ネットワーク接続のソケットがどこに向いているか。そうした違和感を嗅ぎ分ける嗅覚こそが、我々エンジニアの最後の砦となる。

次にシステムのログを眺める時は、ただエラーを探すのではなく、「誰が、どのプロセスを使って、何を実行したのか」というストーリーを組み立ててみてほしい。その先には、教科書には載っていない「本当の攻撃者の顔」が見えてくるはずだ。

もし調査中に不可解なメモリダンプにぶつかったら、恐れずにGhidraを開こう。バイナリと向き合う時間は、君のエンジニアとしてのレベルを確実に引き上げてくれる。健闘を祈る。

コメント

タイトルとURLをコピーしました