みなさん、こんにちは!インシデントレスポンスやデジタルフォレンジック(DFIR)の現場を長年歩んできたセキュリティアナリストの視点から、今回は少しディープでありながら、とっても実用的なテーマをお届けします。
「メモリフォレンジック」と聞くと、なんだか映画のハッカーみたいで難しそうに聞こえますよね。「ディスクの調査だけでも大変なのに、揮発性(電源を消すと消えちゃう)のメモリまで調べるなんて無理!」と思っていませんか?
大丈夫です。今回は、新人のIT担当者や日頃は開発に没頭しているエンジニアの方向けに、「家の鍵と泥棒の足跡」に例えながら、メモリ上の情報とディスク上のファイル履歴を組み合わせて攻撃者の足取りを暴く「タイムライン分析」の極意を、優しく紐解いていきたいと思います。
一歩ずつ、一緒に学んでいきましょう!
—
1. なぜ「メモリ」と「ディスク(MFT)」の両方が必要なの?
まずは、私たちの身近な空間に例えて考えてみましょう。
あなたの家で、リビングの机の上に置いてあったはずの大切な書類が、ある日突然なくなってしまったとします。ここで犯人を見つけようとしたとき、あなたならどこを探しますか?
1. ディスク(MFT = Master File Table)に例えるなら:
玄関の「防犯カメラの映像」や、床に残された「泥棒の足跡」です。いつ誰が家に入ってきたのか、どの部屋のドア(ファイル)を開けたのかという「動かぬ証拠(歴史の記録)」がカレンダーや日記のように正確に残ります。WindowsのNTFSファイルシステムにおけるMFTは、まさにこの「家の中のすべてのファイルの出入りを記録した巨大な台帳」です。
2. メモリ(RAM)に例えるなら:
犯人がその場に残していった「温かいコーヒーのカップ」や「いま現在握りしめている合鍵」です。電源を切ってしまうと消えてしまいますが、「いま、まさに何が起きているのか」「実行中のプログラムがどんな悪だくみをしているのか」というリアルタイムの生々しい証拠が詰まっています。
攻撃者は「証拠」を消そうとする
狡猾な攻撃者は、侵入した後にディスク上のログを消したり、タイムスタンプを書き換えたりして足跡を隠そうとします(これをアンチ・フォレンジックと呼びます)。しかし、彼らが「実行中のプログラム」としてメモリ上で動いていた瞬間の痕跡までは、完全に消し去ることはなかなかできません。
だからこそ、「ディスク(MFT)という確実な歴史の記録」と、「メモリという犯行中の生々しい足跡」をガチャンと突き合わせる(相関分析する)ことで、攻撃者がいつ、どのミリ秒の瞬間に忍び込んだのかを完璧に暴き出すことができるのです。
—
2. 実践!MFTとメモリ情報を結びつけるタイムライン分析
では、具体的にどのように調査を進めるのか、現場のフローを覗いてみましょう。
ステップ1:メモリから「怪しいプロセス」を抽出する
まずは、被害に遭ったサーバーやPCのメモリをまるごとファイルとして保存(ダンプ)し、分析ツール(代表的なオープンソースツールとして Volatility 3 などがあります)を使って、当時どんなプログラムが動いていたかを調べます。
例えば、怪しい powershell.exe が見つかったとしましょう。このプロセスには、以下のような情報が残っています。
- プロセスが起動した正確な時刻(Process Creation Time)
- 実行された引数(隠しコマンドやダウンロード元のURLなど)
ステップ2:ディスクのMFTから「ファイルの生成・変更時刻」を抽出する
次に、ディスク側にあるMFTを解析します。WindowsのMFTには、ファイルが作られたり($STANDARD_INFORMATION や $FILE_NAME )、書き換えられたりした時刻がミリ秒単位で記録されています。
ここで、メモリで見つかった怪しいPowerShellが「外部から怪しいマルウェアの実行ファイルをダウンロードした時刻」と、ディスクのMFT上で「そのマルウェアのファイルが作成された時刻」をタイムライン上で並べてみます。
もし、メモリ上の活動時刻とMFT上のファイル作成時刻がピタリと一致したら……? これこそが、攻撃者がシステムを完全に掌握した「決定的な瞬間(Patient Zero)」の証明になります。
—
3. 実務で役立つ!タイムライン結合のためのPythonスクリプト例
現場のインシデントレスポンスでは、何万行ものメモリログとMFTのCSVデータを手作業で突き合わせるのは不可能に近いので、簡単なスクリプトを使って時刻のソートや結合を行います。
以下のサンプルコードは、メモリから抽出したイベントとMFTのイベントを読み込み、時系列順にきれいに並べ替えて出力する実用的なスクリプトの例です。実務のインフラ構築やログ解析の自動化の参考にしてみてください。
import csv
from datetime import datetime
def load_events_from_csv(file_path, source_name):
"""
CSVファイルからイベント情報を読み込み、
共通のフォーマット(時刻, イベント内容, 出典)のリストに変換する関数です。
"""
events = []
try:
with open(file_path, mode='r', encoding='utf-8') as f:
reader = csv.DictReader(f)
for row in reader:
# CSV内の「Timestamp」列と「Description」列を想定しています
timestamp_str = row.get('Timestamp')
description = row.get('Description')
if timestamp_str:
# 文字列の時刻をPythonのdatetimeオブジェクトに変換
# ミリ秒まで正確にパースできるようにフォーマットを指定します
dt = datetime.strptime(timestamp_str, '%Y-%m-%d %H:%M:%S.%f')
events.append({
'timestamp': dt,
'description': f"[{source_name}] {description}"
})
except FileNotFoundError:
print(f"注意: ファイル {file_path} が見つかりませんでした。パスを確認してください。")
return events
def main():
# 1. メモリフォレンジックツール(例: Volatility)から出力されたCSV
memory_csv = 'memory_process_events.csv'
# 2. ディスクのMFT解析ツール(例: MFTDump)から出力されたCSV
mft_csv = 'mft_file_events.csv'
print("メモリとMFTのログを読み込んでいます...")
memory_events = load_events_from_csv(memory_csv, 'MEMORY')
mft_events = load_events_from_csv(mft_csv, 'DISK_MFT')
# 両方のイベントをひとつのリストに結合
all_events = memory_events + mft_events
# 発生時刻(timestamp)の古い順に並べ替え(タイムラインの作成)
all_events.sort(key=lambda x: x['timestamp'])
print("\n--- 統合タイムライン分析結果(時系列順) ---")
for event in all_events:
# ミリ秒まで含めた綺麗な形式でコンソールに出力します
time_formatted = event['timestamp'].strftime('%Y-%m-%d %H:%M:%S.%f')[:-3]
print(f"{time_formatted} | {event['description']}")
if __name__ == '__main__':
main()
このコードのポイント
datetime.strptimeを使って、ミリ秒単位(%f)の細かいタイムスタンプまで正確に処理できるようにしています。- メモリ側の足跡とMFT側の足跡を混ぜ合わせ、
sort()関数で時系列に並べ替えることで、「何が起きた後に、どのファイルが作成されたか」という因果関係が一目でわかるようになっています。
—
4. 最後に:インシデントに備えて私たちができること
メモリ情報とMFTの突き合わせによるタイムライン分析は、攻撃者の「嘘(タイムスタンプの改ざんなど)」を見破るための強力な武器になります。
最初は、見慣れない用語や複雑なデータ構造に圧倒されてしまうかもしれません。でも、身の回りの防犯と同じように、「どこにどんな足跡が残るのか」という基本の仕組みを少しずつ理解していけば、必ずサイバー攻撃の痕跡を見つけ出せるようになります。
インシデントはいつ何時やってくるかわかりませんが、慌てず、正確な証拠を一つずつ繋ぎ合わせていきましょう。一歩ずつ、確実にスキルアップしていけば大丈夫です!次回の解説もお楽しみに!
コメント