【テクニカル・上級編】 メモリ上のコマンド履歴とシェルセッションの復元 – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

消された足跡を求めて:揮発性メモリに刻印された「真実」のコマンドライン

インシデントレスポンスの最前線に立つ我々にとって、ディスク上のログほど信用できないものはない。洗練された攻撃者は、システムに侵入した直後、まず第一に HISTCONTROL=ignoreboth を唱え、あるいは Clear-History で自らの痕跡を抹消する。彼らにとって、.bash_history や ConsoleHost_history.txt を残すことは素人が犯す最大の屈辱だからだ。

しかし、攻撃者がどれほど巧妙に「ディスク上の過去」を消し去ろうとも、実行されたコマンドの残滓は必ず 揮発性メモリ(RAM) のどこかに漂っている。プロセスが生存している限り、あるいはページが上書きされない限り、ヒープ領域やスタック、あるいは I/O バッファの中に、彼らが秘密裏に実行した C2 サーバーへの通信コマンドや、横展開(Lateral Movement)のための認証情報が「生」の状態で残されている。

本稿では、一般的なフォレンジックの教科書が触れない、bash や PowerShell の内部構造に踏み込んだメモリ解析の神髄を詳解する。

—

1. Bash メモリフォレンジックの深淵:Readline バッファの解体

Linux 環境において、攻撃者が unset HISTFILE を実行した場合、ディスクフォレンジックは無力化される。ここで我々が注目すべきは、bash が利用する GNU Readline ライブラリの挙動だ。

bash プロセスの構造とヒープ解析

bash は入力されたコマンドを処理する際、内部的な履歴リスト(history_list)をメモリ上に保持する。このリストはポインタの配列であり、各要素がコマンド文字列を格納したメモリブロックを指している。

Volatility 3 等のツールを用いて linux.bash.bash プラグインを実行するのが定石だが、高度なパッカーや難読化シェルを使われた場合、シグネチャベースのスキャンは失敗する。その場合、我々は procfs のメモリマップからヒープ領域([heap])をダンプし、以下のロジックで「浮遊する文字列」をカービングする必要がある。

実用的なアプローチ:ヒープからのコマンドライン抽出

以下の Python スクリプトの断片は、メモリダンプから bash のコマンドライン特有のパターン(ヌル終端の文字列と、それに続くメタデータ構造)を抽出する際のロジックを示している。

import re

def extract_bash_commands(memory_dump_path):
    # bashの履歴エントリは通常、タイムスタンプ(#162...)や
    # 特定の制御文字の後に続く。ここでは一般的なコマンドパターンを検索。
    # ターゲット:環境変数を含む複雑なワンライナー
    pattern = re.compile(b'[a-zA-Z0-9_/.\- ]{5,512}')
    
    with open(memory_dump_path, 'rb') as f:
        data = f.read()
        # ヒープ領域に特徴的な、環境変数設定を伴うコマンドを抽出
        matches = pattern.findall(data)
        for match in matches:
            cmd = match.decode('utf-8', errors='ignore')
            # 攻撃者が好むキーワードでフィルタリング
            if "curl" in cmd or "wget" in cmd or "chmod +x" in cmd:
                print(f"[!] Suspect Command Found: {cmd}")

# メモリダンプ(例: bashプロセスのmemファイル)を解析
# extract_bash_commands("/tmp/bash_process_mem.dump")

—

2. Windows PowerShell:難読化の裏側に潜む「デコード済み」の真実

Windows 環境における現代の攻撃は、ほぼ 100% PowerShell を介して行われる。攻撃者は Base64 でエンコードされた巨大なペイロードを -EncodedCommand で実行するが、これは序の口に過ぎない。

AMSI とメモリ内バッファ

Windows 10 以降、Antimalware Scan Interface (AMSI) が導入された。ここで重要なのは、「どれほど難読化されていても、実行の瞬間には平文のスクリプトブロックがメモリ上に展開される」 という物理的な制約だ。

PowerShell プロセス(powershell.exe または pwsh.exe)のメモリ内には、以下の 2 箇所に重要なアーティファクトが残る。

1. ConsoleHost の入力バッファ: conhost.exe のメモリ領域。ユーザーが直接入力したコマンドが保持される。
2. CLR (Common Language Runtime) ヒープ: .NET オブジェクトとして、実行されたスクリプトブロック(ScriptBlock)がキャッシュされる。

PowerShell 履歴の抽出ロジック(Volatility 3)

チーフホワイトハッカーとして現場で指揮を執る際、私はまず windows.pslist でプロセスを特定し、次に windows.memmap でターゲットプロセスの全ページをエクスポートさせる。

# 特定のPowerShellプロセスのメモリをダンプ
python3 vol.py -f memory.dmp windows.memmap --pid <PID> --dump

# 文字列抽出を行い、スクリプトブロックの開始シグネチャを検索
strings -e l pid.<PID>.dmp | grep -A 5 "ScriptBlockText"

PowerShell 5.0 以降、Script Block Logging (Event ID 4104) が有効であればログに残るが、攻撃者は Reflection を用いてメモリ上の AmsiInitFailed フラグを書き換え、ロギング自体を無効化してくる。しかし、この「フラグを書き換えるためのコード」自体がメモリに残るという皮肉な結果を招く。

—

3. 次世代の防衛アーキテクチャ:ガードレイルとしての eBPF と ETW

メモリフォレンジックは常に「事後」の作業だ。しかし、テックリードやセキュリティアーキテクトが設計すべきは、これらの揮発性情報を 「準リアルタイムで永続化」 する機構である。

Linux: eBPF による実行時引数の捕捉

auditd は重く、バイパスされやすい。現代的な設計では、eBPF (Extended Berkeley Packet Filter) を用いて、カーネルレベルで execve システムコールをフックし、引数(argv)をユーザー空間のコレクタにストリーミングする。

// eBPF Cコード断片: execveの引数を捕捉する概念
SEC("tracepoint/syscalls/sys_enter_execve")
int trace_execve(struct trace_event_raw_sys_enter* ctx) {
    const char *filename;
    // filenameポインタから実行ファイル名を読み取る
    filename = (const char *)PT_REGS_PARM1(&ctx->args);
    // ここでユーザー空間へデータを送信(bpf_perf_event_output)
    return 0;
}

Windows: ETW (Event Tracing for Windows) の戦略的活用

EDR (Endpoint Detection and Response) の核心は ETW にある。特に Microsoft-Windows-PowerShell プロバイダーを購読することで、メモリ上でのみ展開される難読化解除後のコードを捕捉できる。ガードレイルとしての設計指針は、これらのイベントを SIEM に飛ばすだけでなく、「不審な難読化パターン(例:過度なバッククォートの使用)」 を検知した瞬間に、プロセスのメモリダンプを自動生成させるオートメーションを組むことだ。

—

4. 結論:アーキテクトに求められる視点

メモリフォレンジックは、攻撃者との「情報の非対称性」を埋める最後の手段である。攻撃者がログを消し、バイナリをメモリ上でのみ実行(Fileless Malware)したとしても、計算機アーキテクチャの根本である「実行にはメモリが必要である」という原則からは逃れられない。

我々プロフェッショナルが構築すべきは、単なる壁(ファイアウォール)ではない。攻撃者が侵入した際、その一挙手一投足を、彼らが気づかないうちにメモリから吸い上げ、解析し、反撃の糧とするための 「インテリジェントな観測基盤」 である。

インシデントレスポンスの現場において、最も価値のある情報は常に、最も消えやすい場所にある。それを忘れてはならない。

コメント

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