【入門編】 メモリ上のファイルレスマルウェアの実行コード抽出と静的解析 – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

こんにちは!インシデントレスポンスの現場を渡り歩いているSOCアナリストです。
今回は、セキュリティの世界で新人エンジニアや開発者の頭を悩ませる「ファイルレスマルウェア」について、一緒に紐解いていきたいと思います。

「ディスクに痕跡を残さず、メモリ上でこっそり動く」なんて聞くと、なんだか映画のハッカーみたいで身構えてしまいますよね。でも大丈夫です。基礎から一歩ずつ、実務で使えるノウハウまで優しく解説していきますので、リラックスして読んでくださいね。

—

1. ファイルレスマルウェアってなに? 家の鍵に例えて理解しよう

セキュリティのニュースを見ていると、「ファイルレスマルウェア」という言葉をよく見かけますよね。文字通り「ファイルを残さない」厄介な仕組みですが、まずは身近な防犯に例えてイメージしてみましょう。

皆さんの家には、頑丈な玄関のドアと鍵(これが従来のアンチウイルスソフトやファイルの検査に当たります)がありますよね。泥棒が家に侵入するとき、普通はピッキングをしたり、窓ガラスを割ったりして「形跡(=ファイル)」を残します。

しかし、ファイルレスマルウェアは一味違います。
彼らは、あらかじめ家の中に開いていた「換気口(=正規のWindowsの機能やパワーシェルなど)」からスルスルと忍び込みます。そして、家の中に入った瞬間に自分の姿(怪しいプログラムのファイル)をゴミ箱に捨ててしまい、リビングのソファ(=PCのメモリ:RAM)の上だけでこっそり悪巧みを実行するんです。

これだと、警察(アンチウイルスソフト)が玄関や部屋中を探し回っても、「怪しい道具(ファイル)」がどこにも落ちていないので、見つけるのが非常に難しくなりますよね。これが、ファイルレスマルウェアの正体です。

—

2. 攻撃者はメモリのどこに隠れているのか?

では、攻撃者はメモリのどこに身を潜めているのでしょうか?

Windowsの中には、アプリが動くための作業机がたくさん用意されています。これをメモリ管理の用語で 「VAD(Virtual Address Descriptor)」 と呼びます。
VADは、いわば「メモリという広大なトランクの中身の目録」のようなものです。

正規のアプリが使う場所もあれば、マルウェアがこっそり陣取っている怪しい場所もあります。インシデントレスポンスの現場では、この目録(VAD)をくまなくチェックして、「おや、このエリア、誰も使っていないはずなのに何やらプログラムが動いているぞ?」という不審なエリアを見つけ出すことが最初の第一歩になります。

—

3. 実践!メモリから隠しコードをダンプして取り出そう

ここからは、実際に現場で行われている調査の手法を、少しだけ覗いてみましょう。
「メモリ上に展開された怪しいコードを捕まえて、じっくり解析できるようにファイルとして外に引っ張り出す(ダンプする)」という作業を行います。

今回は、Pythonのフォレンジックフレームワークである Volatility 3 を使った基本的なアプローチをご紹介します。難しく考えず、「メモリという写真立てから、怪しい犯人の姿を切り抜く作業」だと思ってくださいね。

ステップ1:怪しいプロセスの当たりをつける

まずは、どのアプリ(プロセス)の中で悪事が行われているかを探します。以下のコマンドで、怪しい動きをしているプロセスの一覧を覗いてみましょう。

# Volatility 3を使って実行中のプロセス一覧を表示するコマンド
python vol.py -f memdump.raw windows.pslist

ここで、普段は見慣れない名前のプロセスや、正規のWindows機能(例えば powershell.exe や explorer.exe など)の親子関係がおかしいものを発見したら、それがターゲットです。

ステップ2:VADツリーから隠しコードを特定してダンプする

ターゲットのプロセスID(PID)が分かったら、次はVAD(メモリの目録)をスキャンして、怪しい領域(ディスク上のファイルと紐づいていない、メモリ上だけで生きている領域)を探し、ファイルとして抽出します。

# 特定のプロセスのVAD情報を確認し、怪しいメモリ領域をファイルとして書き出すコマンド
python vol.py -f memdump.raw windows.vadinfo --pid 1234

現場では、このVAD情報の中から「アクセス権限が PAGE_EXECUTE_READWRITE(読める・書ける・実行できる)」になっており、かつディスク上のファイルパスが綺麗に紐づいていない怪しいチャンク(塊)を見つけ出し、次のようなツールやスクリプトでダンプ(保存)します。

# 【概念コード】メモリ上の特定アドレスからバイナリデータを切り出すイメージのPythonコード
def dump_memory_region(process_handle, start_address, size):
    """
    メモリの特定アドレスからペイロード(実行コード)を安全に抽出し、
    静的解析用のバイナリファイルとして保存するためのサンプルです。
    """
    print(f"[*] アドレス 0x{start_address:x} から {size} バイトのデータをダンプ中...")
    
    # 実際のメモリ読み取り処理(Windows APIの ReadProcessMemory 等をラップ)
    raw_payload = read_virtual_memory(process_handle, start_address, size)
    
    # IDA ProやGhidraなどの解析ツールに食わせるためのファイルに出力
    output_filename = f"extracted_payload_0x{start_address:x}.bin"
    with open(output_filename, "wb") as f:
        f.write(raw_payload)
        
    print(f"[+] ダンプ完了!保存ファイル: {output_filename}")

# ※注意: 実際のインシデント現場では、専用のVolatilityプラグインやデバッガーを使用します。

—

4. ダンプしたコードをIDA Proで料理する

無事に怪しいコードを extracted_payload.bin のような形で取り出せたら、次はセキュリティエンジニアの腕の見せどころ、静的解析のステージです。

ここで登場するのが、リバースエンジニアリングの定番ツールである IDA Pro や、オープンソースの Ghidra です。

1. ツールの起動とファイルの読み込み
先ほどダンプしたバイナリファイルを、IDA Proにドラッグ&ドロップします。
2. アーキテクチャの指定
大半のWindowsマルウェアは x86 (32bit) か x64 (64bit) ですので、適切なアーキテクチャを選択して「OK」を押します。
3. アセンブリ言語の解析
ツールが自動的に機械語(バイナリ)を人間が読めるアセンブリ言語に翻訳してくれます。

ファイルレスマルウェアのコードは、メモリ上で動くために少し特殊な工夫(APIハッシュを使った動的API解決など)がされていることが多いですが、落ち着いてコードの流れを追っていくと、「あ、こいつは外部のC2サーバーと通信しようとしているな」「レジストリを書き換えようとしているな」という攻撃者の意図がハッキリと見えてきます。

—

5. 一歩ずつ、確実な対策を学んでいきましょう!

今回は、メモリ上に潜むファイルレスマルウェアの正体から、VADを使ったダンプ、そしてIDA Proでの解析へ繋げるアプローチまでを解説しました。

「なんだか手順が多くて難しそう…」と感じた方もいらっしゃるかもしれませんが、インシデントレスポンスは一日にして成らずです。日々の業務や検証環境でのトライアルを通じて、少しずつ「メモリの仕組み」や「ツールの使い方」に慣れていけば大丈夫です。

まずは手元の環境でメモリイメージを安全に取得する方法を試すところから、一歩ずつ進めてみましょう。皆さんのセキュリティライフが実りあるものになるよう、これからも応援しています!

コメント

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