【入門編】 メモリダンプからのインメモリ実行型マルウェア(Fileless Malware)の抽出 – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

こんにちは!日々の開発やインフラの保守、本当にお疲れ様です。セキュリティの勉強を始めると、専門用語が次から次へと出てきて「うっ……」と頭が痛くなりますよね。でも、安心してください。セキュリティは、私たちの身の回りにある「防犯」の仕組みと本質はまったく同じなんです。

今回は、インシデントレスポンス(DFIR)の現場でも特に厄介とされる「インメモリ実行型マルウェア(ファイルレスマルウェア)」について、メモリフォレンジックの視点から一緒に紐解いていきましょう。

ディスクに証拠を残さないずる賢い泥棒を、どうやって見つけ出すのか? 一歩ずつ、優しく解説していきますね。

—

1. 家の鍵を壊さずに侵入する?「ファイルレスマルウェア」の正体

普段、私たちのパソコン(Windowsなど)には、ウイルス対策ソフトが入っていますよね。これは、いわば「頑丈な玄関の鍵」や「防犯カメラ」のようなものです。怪しい人間(ウイルス)がハードディスク(家の敷地内)に侵入しようとすると、警備員が「おっと、そのファイルは怪しいですね!」と捕まえてくれます。

しかし、攻撃者たちも賢いです。
「ハードディスクにファイルを置くから見つかるんだ。それなら、ファイルを一切残さず、パソコンの『メモリ(RAM)』というリビングのソファの上だけでこっそり暴れ回ればいいや!」と考えました。

これが、今回テーマにするファイルレスマルウェアです。

ディスク(ハードディスクやSSD)には悪意ある実体ファイルが一切書き込まれないため、通常のウイルス対策ソフト(ファイルスキャン)ではすり抜けてしまいます。彼らは、正当なプログラム(例えば、Windowsの正規機能である powershell.exe や explorer.exe など)のなかにこっそり入り込み、メモリ上で悪意あるコードを動かします。

代表的な手口:「プロセス・ハロウィーニング(Process Hollowing)」

ちょっと面白い(そして恐ろしい)例えをしますね。
泥棒が、警察官の制服(正規のプログラム)を着て街を歩いていると想像してください。本物の警察官(中身)はどこかに縛り上げられていて、中身だけが泥棒に入れ替わっています。外見からは「警察官が歩いている」ようにしか見えないので、誰も怪しみません。

これが「プロセス・ハロウィーニング」です。正規のプログラムのメモリ空間を一度からっぽ(Hollow=中身をくり抜く)にして、そこにマルウェアのコードを流し込むわけです。

—

2. メモリフォレンジックってなに?

「ディスクに証拠がないなら、もうお手上げじゃないか!」と思いますよね。
ここで登場するのが、私たちセキュリティアナリストの武器である「メモリフォレンジック」です。

メモリ(RAM)とは、パソコンの電源を切ると消えてしまう「短期記憶」の場所です。人間で言えば「今、頭の中で考えていること」ですね。電源が入っている限り、マルウェアがリビング(メモリ)のどこで暴れ回っていたか、その足跡や生々しい息づかいが必ず残っています。

このメモリの様子をごそっとファイルとして保存したものを「メモリダンプ」と呼びます。現場では、このメモリダンプという「事件現場の形跡」を解析して、見えない泥棒の正体をあぶり出すんです。

—

3. 実践:Volatilityを使ったメモリからのマルウェア抽出

では、具体的にどうやってメモリから怪しいコードを見つけ出すのか、現場でよく使われるオープンソースの解析ツール Volatility(ボラティリティ)を例に見ていきましょう。

初心者の方でもイメージしやすいように、コマンドの流れと「なぜそれを調べるのか」を解説しますね。

ステップ1:動いているプロセスの一覧を確認する

まずは、メモリ上でどんなプログラムが動いているかをリストアップします。泥棒がどの制服を着てすまし顔をしているかを探す作業です。

# Windowsのメモリダンプ(memory.dmp)から、プロセスの一覧を抽出するコマンド
volatility -f memory.dmp --profile=Win10x64_19041 pslist

ここで、不自然な親子関係(親プロセスが本来とは違うプログラムになっているなど)を見つけるのが第一歩です。

ステップ2:怪しいプロセスのメモリ空間をのぞき見する(プロセス・ダンプ)

怪しいプロセス(例えば、不審な動きをしている powershell.exe や、名前が似せられた偽物のプロセス)が見つかったら、そのプロセスがメモリ上で使っている領域を丸ごとファイルとして抜き出します。

# PID(プロセスID)が 1234 のプロセスのメモリ領域をファイルとして切り出す
volatility -f memory.dmp --profile=Win10x64_19041 procdump -p 1234 -D ./dump_output/

これで、executable.1234.exe のようなファイルが手に入ります。これが、メモリ上でこっそり実行されていた「中身の正体(マルウェアの断片)」です。

ステップ3:Reflective DLL Injectionの痕跡を探す

ファイルレスマルウェアの多くは、「リフレクティブDLLインジェクション」という高度な技術を使います。通常のWindowsの仕組みを使わず、自分で自分をメモリ上にロードしてしまう手口です。

volatility には、こうした「怪しいメモリの領域」を見つける便利なプラグイン(探偵犬のようなもの)が用意されています。

# プロセス内の不審なメモリ領域(実行権限があり、DLLのヘッダーを持つ場所)をスキャンする
volatility -f memory.dmp --profile=Win10x64_19041 ldrmodules -p 1234

もし、ディスク上のファイルとメモリ上の実体が一致しないモジュールが見つかった場合、それは「メモリ上で勝手にロードされた不正なプログラム(インメモリ実行型マルウェア)」である可能性が極めて高いと言えます。

—

4. 抽出したコードをどう料理する?(リバースエンジニアリングへのバトンタッチ)

メモリから無事に怪しいコード(バイナリ)を抽出できたら、次はそれを安全な隔離環境(サンドボックス)で解析したり、デバッガーで中身を覗いたりします。

実務の現場では、抽出したコードのヘッダー部分を確認することがよくあります。例えば、Windowsの実行ファイルが持つ「PEヘッダー」の始まりには、お馴染みのマジックナンバーである MZ という文字(4D 5A)が隠されています。

もし自作のスクリプト等で、メモリダンプから特定のコード片を切り出す処理を書く場合、以下のようなPythonのコード片が参考になるかもしれません。

# Pythonを使った簡単なメモリダンプからの特定パターン(MZヘッダー)検索のイメージ
def find_pe_headers(memory_data):
    """
    メモリデータのバイト列から、PEヘッダーの開始位置(MZ)を探すサンプル関数
    """
    offset = 0
    while True:
        # MZヘッダーのシグネチャ (b'MZ') を探す
        offset = memory_data.find(b'MZ', offset)
        if offset == -1:
            break
        
        print(f"[*] 潜在的なPEヘッダー(実行ファイル)の痕跡をオフセット 0x{offset:X} で発見しました!")
        offset += 2 # 次の検索のために進める

# 使用例(実際のファイル読み込み等の処理は省略しています)
# with open("memory.dmp", "rb") as f:
#     memory_bytes = f.read()
#     find_pe_headers(memory_bytes)

このように、目に見えないファイルレスの脅威であっても、メモリという足跡を丁寧に辿ることで、確実にその正体を暴くことができるのです。

—

さいごに:一歩ずつ対策を学んでいきましょう!

「ファイルレスマルウェア」や「メモリフォレンジック」と聞くと、なんだかSF映画のように難しく感じられたかもしれません。でも、基本はシンプルです。

1. ディスクにないなら、メモリ(頭の中)を覗けばいい。
2. 正規のプログラムに化けている不審な挙動(親子関係や不自然なメモリ領域)を見逃さない。
3. 専用のツールを使って、メモリから怪しい断片を回収する。

セキュリティの道は一日にしてならずです。最初は難解なコマンドに戸惑うかもしれませんが、日々のインフラ運用や小さなログの確認の積み重ねが、いざという時の強力な盾になります。

これからも一歩ずつ、一緒に楽しくセキュリティを学んでいきましょうね!

コメント

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