皆さん、こんにちは!日々、スマートフォンアプリの開発やサーバーの運用、セキュリティ対策にお疲れ様です。
今回は、インシデントレスポンス(DFIR)の現場でも特に「泥臭く、かつ奥が深い」領域である、Android端末のメモリフォレンジック(物理メモリダンプの取得手法)についてお話しします。
「スマホのメモリを見るって、なんだか映画のハッカーみたいで難しそう…」と思われるかもしれませんが、大丈夫です!今回は、身近な「家の鍵と泥棒の防犯」に例えながら、一歩ずつ分かりやすく紐解いていきましょう。
—
そもそも「メモリフォレンジック」ってなに?(家の鍵に例えてみよう)
皆さんの家には、玄関の鍵がありますよね。お出かけするときには鍵をかけ、家の中には大切な通帳やパスワードのメモがしまってあります。
スマートフォンも全く同じです。
- ストレージ(SSDやSDカード):家の中の「タンス」や「金庫」。アプリのデータや写真がずっと保存されています。
- メモリ(RAM):リビングの「机の上」。今まさに開いているアプリや、入力中のパスワード、通信中の暗号鍵などが一時的に広げられています。
警察やセキュリティ調査員(私たちDFIRアナリスト)が事件現場に駆けつけたとき、タンスの中身を見るだけでは分からないことがあります。「犯人が最後に何をしていたか」「机の上にどんな秘密のメモが置きっぱなしだったか」を知るには、リビングの机の上(=メモリ)をそのまま写真に撮る必要があります。これが「メモリダンプ」です。
しかし、泥棒(攻撃者)も、あるいは私たち調査員も、他人の家(Android端末)の机の上のものを勝手に見るには、色々な高い壁を越えなければなりません。
—
Root権限がある環境でのメモリ取得(合鍵を持っている状態)
まずは、端末にRoot権限(管理者権限)がある場合のお話です。
Androidの心臓部であるOS(Linuxカーネル)は非常に厳格に守られており、普通のアプリやユーザーが勝手にメモリの中身をのぞき見ることはできません。しかし、Root権限を持っているということは、いわば「家全体の合鍵を最初から持っている状態」です。
カーネルモジュール(LKM)を用いたメモリ抽出
現場の調査では、LKM(Loadable Kernel Module:ロード可能カーネルモジュール)と呼ばれるプログラムを端末の内部に直接組み込んで、メモリを丸ごとファイルとして吐き出させることがよくあります。
これは、いわば「専門の合鍵を使って家に入り、リビングの机の上の状態をそっくりそのまま段ボール箱に詰めて持ち出す作業」です。
実際に、フォレンジック調査で使われるツール(LiMEなど)をビルドして実行する際のイメージを見てみましょう。
# 【検証環境用】LiME(Linux Memory Extractor)をコンパイルしてメモリを吸い出すスクリプトの例
# ※実際の業務ではターゲット端末のカーネルヘッダーに合わせたビルドが必要です
# 1. 必要なソースコードを準備し、カーネルモジュールをビルドします
make -C /lib/modules/$(uname -r)/build M=$(pwd) modules
# 2. 生成されたモジュール(lime.ko)を、出力先ファイル名を指定してカーネルにロードします
# pathパラメータに、ダンプデータの保存先(SDカードやマウントした外部ストレージ)を指定します
insmod lime.ko "path=/sdcard/memory_dump.bin format=raw"
# 3. ダンプが無事に完了したら、痕跡を最小限にするためにモジュールをアンロードします
rmmod lime
Root権限さえあれば、このように端末の頭脳の深部までアクセスし、マルウェアが残した痕跡や暗号鍵を完璧に回収することができます。しかし、実際のインシデントレスポンスでは、攻撃を受けた端末がすでにRoot化されているとは限りません。むしろ、セキュリティが保たれた「Rootなし(ノーマル状態)」の端末と対峙することのほうが多いのです。
—
Root権限がない環境の限界(厳重に施錠された高級マンション)
では、Root権限がない端末、つまり市販されている一般的な状態のAndroid端末からメモリを抜き取ろうとすると、どうなるでしょうか?
これは、「泥棒がピッキング技術を使っても、頑丈な二重ロックと防犯ガラスに阻まれて中が見えない状態」です。Androidのセキュリティ機構(SELinuxやサンドボックス)は非常に優秀で、権限のない外部からのメモリ読み取り要求を徹底的にブロックします。
ここで、よくある「Root権限がない環境でのアプローチ」の限界について見ていきましょう。
1. ADBバックアップ(adb backup)の限界
昔のAndroidバージョンでは、PCからadb backupコマンドを実行することで、アプリのデータをまるっとPCに吸い出すことができました。しかし、近年のAndroid(Android 9以降など)では、アプリ側でバックアップが明示的に禁止(allowBackup="false")されていることが多く、メモリの生データどころか、アプリの重要データすらまともに抜けなくなっています。
2. デバッグインターフェース(JDWPなど)の限界
開発者向け機能である「USBデバッグ」を悪用して、動いているアプリのプロセスにアタッチ(接続)し、メモリを覗き見ようとする手法もあります。
しかし、これも「リリースビルド(本番用)」のアプリではデバッグが完全に無効化されているため、特定のプロセスの中身をのぞき見ることは極めて困難です。
つまり、Root権限がない環境において、PCから魔法のように一発で物理メモリ全体(RAM全体)を綺麗な形でダンプし取る「銀の弾丸(万能な手法)」は存在しないのが現実です。
—
現場のプロはどう立ち向かうのか?(代替アプローチ)
「じゃあ、Root権限がない端末でインシデントが起きたら、何も調査できないの?」と思われるかもしれませんが、そんなことはありません!DFIRの現場では、次のような「代替の証拠保全」を組み合わせます。
1. ファイルシステムの論理抽出(Logical Extraction)
- メモリそのものは取れなくても、通常のストレージ内にあるログファイル(
/data/local/tmp/やアプリのキャッシュ、データベース)をADB経由やリカバリモードで回収し、事後解析を行います。
2. メモリの「断片」の回収
- 完全にメモリをダンプできなくても、クラッシュ時に自動生成されるダンプファイル(TombstoneやANRログ)の中に、当時メモリ上で何が起きていたかのヒント(レジスタの値やスタックトレース)が残されていることがあります。
—
一歩ずつ対策を学んでいきましょう!
いかがでしたでしょうか?
今回は、Androidのメモリフォレンジックにおける「Root権限がある場合の強力な手法(LKM)」と「Root権限がない場合の厳しい現実(セキュリティの壁)」について、家の鍵に例えて解説しました。
セキュリティの世界は、攻撃者と防御者のイタチごっこです。
「どうやって中身を覗き見るか(フォレンジック)」を知ることは、「どうすれば見られないようにアプリやOSを守れるか(セキュアコーディングや端末保護)」を理解するための最高の近道になります。
最初は複雑に見えるコマンドや概念も、一つひとつの意味を紐解いていけば必ず理解できます。ぜひ、今日の知識を皆さんの日々の開発やセキュリティ学習に役立ててくださいね。
それでは、次の記事でお会いしましょう!
コメント