お久しぶりです、あかりです。
さらっと読んだ論文を雑に内容をまとめてメモとして残していきたいと思います。習慣化できたらいいね。
今回は、Process Implanting: A New Active Introspection Framework for Virtualization (2011) *1を読みました。
Process Implanting という不穏な名前から分かるように、VMM からゲスト OS にプロセスを「埋め込み」ます。埋め込むと言っても、ゲスト OS のプロセスをただ生やすのではなく、プロセスの中にプロセスを埋め込みます。変態的でいいですね。
プロセスを埋め込まれたプロセス (victim process) は、外っ面(プロセス名, pid など)はそのまま、中のプロセスの処理をします。中のプロセスは、VMM の連携と保護によって、他プロセスから終了されることはありません。中のプロセスは VMM によって中断可能で、すると victim process の元のコンテキストは復元され、何食わぬ顔で victim process の処理をします。中のプロセスが終了すると、これもまた victim process の元のコンテキストは復元され victim process の処理を始めます。
このプロセスは、以下の4つの要件を守るように設計されています。
- ステルス性 (Stealthiness)
ゲストOS上の他プロセスから見つからない。
- 分離性 (Isolation)
なるべくゲストOSの資源に頼らず実行する。例えば、動的リンクされる共有Cライブラリが汚染されている可能性を考慮し、埋め込まれたプロセスには全てのライブラリを静的リンクする。
- 堅牢性 (Robustness)
他プロセスやゲストOSによってプロセスが終了されない。
- 完全性 (Completeness)
埋め込まれたプロセスが終了する際、victim process やゲストOSに証拠を残さないようにする。
背景
ユーザプロセスとして動くマルウェア検知ツールや解析エンジンは、同じユーザプロセスとして動くマルウェアに脆弱です。マルウェアにとって、マルウェア対策ツールのプロセスを検知し対策を取ることは簡単なためです。
そこで考えられたのが VMM や外の VM からマルウェア検知や解析を行う VMI (Virtual Machine Introspection) という手法です。これによりマルウェアによって対策ツールの存在を認知されることはなくなりましたが*2、マルウェアのコンテキスト取得が難しいという問題があります (semantic gap, 例: VMM からプロセスの backtrace は取れない)。
この論文では、Process Implating という手法を使って対策ツールをマルウェアにとって人畜無害そうなプロセスにカモフラージュすることで、マルウェアからの検知、終了を逃れつつコンテキストを得るということをします。
方法(ざっくりと)
initialization
埋め込みたいプロセスのイメージを VM に割り当てられている物理メモリの領域外にマップします。
camouflage
victim process へのコンテキストスイッチ時に process を埋め込むという手法を採用しています。ゲスト Linux の __switch_to
に trap をしかけることで、コンテキストスイッチ発生時に毎回 VMM への遷移が発生するため、victim process へのコンテキストスイッチを検知することができます。
implanting
ざっくりと次のような手順で victim process に プロセスを埋め込みます。
- victim プロセスのコンテキストを保存する
- 物理ページテーブル (おそらく VMM が内部で持っている ゲスト物理アドレス→ホスト物理アドレスのページテーブル) を initialization フェーズでマップしたメモリ領域を指すように書き換える
- 2と辻褄が合うようにシャドウページテーブルと Memory Descriptor を書き換える
- カーネルスタック上のユーザレジスタを埋め込むプロセスのレジスタの値に設定する
- コンテキストスイッチが発生、埋め込まれたプロセスの処理を開始する
checkpointing
埋め込まれたプロセスを中断し、コンテキストを保存し victim process に処理を戻します。埋め込まれたプロセスはいつでも再開できます。
exit
埋め込まれたプロセスが終了するとき、そのまま exit システムコールを発行してしまうと victim process も一緒に逝くことになるので、ここでも VMM の介入が必要になります。
ゲスト Linux の sys_exit
と sys_exit_group
に trap をしかけることで、exit システムコール時に VMM に処理が遷移するので、ここで victim process の復元を行います。
victim process の復元後は、自身がいままで他のプロセスを埋め込まれていたことなど知らずに、処理を再開します。
*1:https://www.cs.purdue.edu/homes/dxu/pubs/SRDS11.pdf
*2:VMM の存在を認知されることはある