【入門編】 メモリダンプにおけるカーネルオブジェクトの不整合解析とRootkit検知 – インシデントレスポンス & フォレンジック(DFIR)防御ガイド

こんにちは!セキュリティチームで日々、泥臭いインシデント調査を行っているアナリストの私です。

「メモリフォレンジック」とか「DKOM」なんて言葉を聞くと、「うわっ、なんだか難しそう……宇宙語みたいだな……」って身構えてしまいますよね。でも、安心してください。今回は、身近な「防犯」の仕組みに例えながら、一歩ずつ優しく解きほぐしていきますよ。

新人のIT担当者の方も、セキュリティに興味を持ち始めた開発者の方も、この記事を読み終える頃には「なるほど、攻撃者はそういう裏技を使っていて、僕たちはこうやって見破るんだ!」とスッキリ理解できるようになります。一緒に楽しく学んでいきましょう!

—

1. 泥棒の新しい手口:プロセスを「透明人間」にするDKOM

まずは、今回の主役である「DKOM(Direct Kernel Object Manipulation:直接カーネルオブジェクト操作)」というサイバー攻撃のテクニックについて、私たちの身近な「おうちの防犯」に例えてお話ししますね。

家の鍵と「名簿」の仕組み

あなたの会社や自宅には、出入りする人を管理するための「名簿(台帳)」がありますよね。パソコンの中(特にWindowsなどのOS)でも全く同じことが起きています。
パソコンの中で動いているアプリやプログラム(これを「プロセス」と呼びます)は、OSが持っている「EPROCESS構造体(タスク管理名簿)」という特別なデータ構造にしっかり名前が書き込まれて初めて、「動いているもの」として認められます。

普段、タスクマネージャーを開くと、「今、メモ帳が動いているな」「ブラウザが開いているな」というのが一覧で分かりますよね。あれは、OSがこの名簿をきれいに読み上げて私たちに見せてくれているからなんです。

悪意あるプログラム(Rootkit)の悪巧み

もし、悪いハッカーがパソコンの中に侵入して、こっそり不正なプログラム(Rootkit)を動かしたとしましょう。
普通なら、タスクマネージャーを開けば「怪しいプログラムが動いている!」とすぐにバレてしまいます。それじゃあ困るので、泥棒(攻撃者)はこんなずるい手を使います。

「タスクマネージャーの名簿のページから、自分の名前だけをこっそりハサミで切り取っちゃえ!」

これがDKOMの正体です。
OSの中心核(カーネル)にあるデータ構造を直接書き換えて、プロセスのリンクリスト(次へ、次へと繋がっている鎖)から自分の存在をプツッと切り離してしまうんです。名簿から名前を消されたプロセスは、タスクマネージャーから見ると「まるで最初からいなかった(透明人間)」状態になります。これが、巧妙なRootkitによるプロセス隠蔽のメカニズムというわけです。

—

2. なぜ「メモリ」を見る必要があるのか?

「タスクマネージャーに映らないなら、見つけるのは不可能じゃないですか?」
そう思いますよね。通常のアプリ画面やコマンド(tasklistなど)を使っているだけでは、OSの「偽りの名簿」を見せられているだけなので、見つけることはできません。

そこで登場するのが、今回のテーマである「メモリフォレンジック」です。
メモリ(RAM)というのは、パソコンが今まさに頭の中で考えていること、記憶していることがそのまま詰まっている「脳みそ」のsnapshots(写真)です。

OSがどんなに「そんなプロセスはいないよ」とうそぶいても、メモリの隅々を直接覗き見れば、脳みその記憶のどこかにその不正なプログラムの痕跡がポツンと残されているんです。これが、私たちフォレンジックアナリストの調査の起点になります。

—

3. 探偵の眼:リンクリストとスケジューラキューの「不整合」を見破る

では、いよいよ核心に迫りましょう。隠された透明人間を、私たちはどうやって見つけ出すのでしょうか?

ここに、セキュリティ調査における最大の「盲点」であり、私たちが使う「探偵のテクニック」があります。

2つのリストを突き合わせる

Windowsのカーネルは、プロセスを管理するために主に次の2つの情報を持っています。

1. ActiveProcessLinks(リンクリスト):
プロセス同士が「次はこの人、その次はこの人」と数珠つなぎになっている名簿の鎖です。DKOMを使う攻撃者は、まさにこの鎖をプチッと切断して、自分を隠します。
2. スケジューラキュー(プロセッサが次に実行するタスクの順番待ち行列):
CPU(パソコンの頭脳)は、実際に作業をするために「次にどのプログラムに仕事を渡そうか」という別の待ち行列(キュー)を持っています。CPUは、この待ち行列に名前がないと実際に仕事を処理できません。

ここがポイントです!
攻撃者は「名簿(リンクリスト)」からは自分の名前を上手に消去しましたが、CPUに仕事をしてもらうための「待ち行列(スケジューラキュー)」から自分を綺麗に消し忘れたり、消すことができなかったりすることが多いのです。

「名簿には名前がないのに、なぜかCPUの仕事の順番待ちにはちゃっかり並んでいる幽霊」

これこそが、リンクリストとスケジューラキューの「不整合」です。この矛盾を見つけることができれば、「おや、ここに透明人間がいるぞ!」と一発で暴くことができるというわけです。

—

4. 実践:Volatility 3を使ったメモリ解析のハンズオン

百聞は一見にしかず。実際に私たちが現場で使っているオープンソースのメモリフォレンジックフレームワーク Volatility 3 を使って、この不整合を検出し、Rootkitを見つけるアプローチを覗いてみましょう。

実務でそのまま参考にできるよう、Pythonを用いた自動化やスキャンのイメージを見ていきます。

ボラティリティによるプロセス列挙の基本コマンド

まずは、メモリダンプファイル(memory.dmp)から、通常のリンクリスト(ActiveProcessLinks)をベースにしたプロセス一覧を取得してみます。

# ボラティリティ3を使用して、Windowsのプロセス一覧を抽出する基本コマンド
python vol.py -f memory.dmp windows.pslist

この pslist コマンドは、先ほどお話した「リンクリスト」を順番に辿ってプロセスを表示します。もしDKOMによってリストから切り離されたプロセスがあれば、ここには表示されません。

DKOM検知プラグイン(psscan)の活用

次に、リンクリストを辿るのではなく、メモリ上の特定のパターン(EPROCESS構造体の目印となるプールタグ Proc など)を直接「総当たり(スキャン)」で探すコマンドを実行します。

# リンクリストに依存せず、メモリ空間全体からEPROCESS構造体をスキャンする
python vol.py -f memory.dmp windows.psscan

ここで、強力な比較のテクニックが生まれます。

  • pslist の結果(名簿に載っている正当なプロセス)
  • psscan の結果(メモリ上に実在しているすべてのプロセス)

この2つの結果を突き合わせ、psscan には存在するのに、pslist には表示されないプロセスを見つけ出します。これが、DKOMによって隠されたプロセスの決定的な証拠となります。

検知スクリプトのアイデア(Python風疑似コード)

現場のインシデントレスポンスでは、こうした差分を自動で抽出するスクリプトを組むことがよくあります。以下に、その考え方をシンプルなコードで表現してみます。

# -*- coding: utf-8 -*-
"""
インシデントレスポンス用:プロセスリストの不整合(DKOM)検出スクリプトの概念モデル
"""

def detect_dkom_anomalies(pslist_processes, psscan_processes):
    """
    pslist(リンクリスト上のプロセス)と
    psscan(メモリプール上の実在プロセス)を比較し、
    隠蔽されたプロセス(DKOMの痕跡)を検出する関数
    """
    # PID(プロセスID)のセットを作成
    visible_pids = {proc['pid'] for proc in pslist_processes}
    raw_memory_pids = {proc['pid'] for proc in psscan_processes}
    
    # メモリ上には存在するが、リンクリストから消されているPIDを特定
    hidden_pids = raw_memory_pids - visible_pids
    
    if hidden_pids:
        print(f"[!] 警告: DKOMによるプロセス隠蔽の可能性があります!")
        print(f"[!] 隠蔽が疑われるPID一覧: {hidden_pids}")
        
        for pid in hidden_pids:
            # 詳細情報を取得してアナリストに通知
            process_detail = next(p for p in psscan_processes if p['pid'] == pid)
            print(f"    -> 該当プロセス名: {process_detail['name']}, Offset: {process_detail['offset']}")
    else:
        print("[+] プロセスリストの整合性に異常は検出されませんでした。")

# 使用例(イメージ)
# pslist_result = get_pslist_from_volatility()
# psscan_result = get_psscan_from_volatility()
# detect_dkom_anomalies(pslist_result, psscan_result)

このように、機械的にリストの差分を取るだけでも、巧妙に身を隠したRootkitの尻尾をしっかりと掴むことができるのです。

—

5. まとめと一歩ずつ進むセキュリティ対策

今回は、メモリダンプにおけるカーネルオブジェクトの不整合解析と、DKOMによるRootkit検知のメカニズムについてお話ししました。

  • 攻撃のメカニズム: Rootkitは EPROCESS のリンクリスト(名簿)から自分の名前を外し、透明人間になろうとする。
  • 私たちの防衛・解析手法: リンクリストと、メモリ上の実在スキャン(あるいはスケジューラ側の情報)との「不整合」を突いて、隠された痕跡を見つけ出す。

「セキュリティの調査って難しそう」と感じていた方も、このように「名簿と現実の突合せ」というシンプルな構造に置き換えてみると、グッと身近に感じられたのではないでしょうか?

インシデントレスポンスの世界は、泥臭い作業の積み重ねです。でも、基礎をしっかり固めておけば、どんなに巧妙な隠蔽工作を行うサイバー攻撃者であっても、必ずどこかにボロ(不整合)が出るものを見つけ出せるようになります。

焦らず、一歩ずつ、一緒にセキュリティのスキルを磨いていきましょう!次の調査現場でも、あなたのその探偵の目がきっと役に立ちますよ。

コメント

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