いまさらながら,情報セキュリティ系論文紹介 Advent Calendar 2016あるいはBitVisor Advent Calendar 2016に投稿されるはずだった文章を供養する.
はじめに
本稿では,シン,すなわち薄いハイパーバイザ (thin hypervisor) の動向を紹介する.
薄いハイパーバイザとは,小規模であることを志向したハイパーバイザだ——ということにしておこう.小規模というのは,一部のイベントのみトラップするということだ.メリットとしては,実装・学習コストやオーバーヘッド,TCB (trusted computing base) を削減できる点が挙げられる.
用語の初出はBitVisorの論文[T. Shinagawa, et al. VEE’09]だが,多くはWindows向けルートキットとして開発されたBlue Pillという手法[J. Rutkowska. Black Hat USA’06]の流れを汲んでいる.そのため,ブート時からゲストを掌握するのではなく,のちほど——あえてchain of trustの構築を放棄して——カーネルドライバとしてロードされるものが一般的である.そのほか,単一のゲストのみ対象とする,セキュリティを意識しているといった傾向が見られる.
前編となる今回は,3種類の薄いハイパーバイザを見ていく.
ksm
リポジトリ | https://github.com/asamy/ksm |
形態 | カーネルドライバ |
仮想化支援機能 | Intel VT-x with EPT |
サポートしている環境 | Windows 7/8/8.1/10, Linux |
言語 | C, アセンブリ言語 |
ライセンス | GNU GPL v2 |
ksmは高速,拡張可能かつ小規模であることを旨としているハイパーバイザで,アンチウイルスソフトウェアやサンドボックスへの利用を意識して開発されている.機能は以下の通り:
- IDT Shadowing
- EPT violation #VE (Broadwell以降)
- EPTP switching VMFUNC (Haswell以降,もしサポートされていなければVMCALLで代替)
- Builtin Userspace physical memory sandboxer (ビルドオプション)
- Builtin Introspection engine (ビルドオプション)
- APIC virtualization (実験的機能)
- VMX Nesting (実験的機能)
主なソースコードは以下の通り:
main_nt.c , main_linux.c |
カーネルドライバのエントリポイント,ioctl ディスパッチ |
ksm.c |
ハイパーバイザ全体の初期化 |
vmx.S , vmx.asm |
IDTやEPT violationのトラップ,ゲストのレジスタ退避 |
vcpu.c |
VMCSの読み書き |
exit.c |
VMExitのハンドラ |
um/um.c |
ユーザーランドのエージェント |
sandbox.c |
サンドボックス機能 |
introspect.c |
イントロスペクション機能 |
epage.c |
EPTフック機能 |
mm.c |
メモリ管理 |
hotplug.c |
CPUホットプラグに関する処理 |
カーネルドライバをロードし,ユーザーランドのエージェントからioctl
を発行,サンドボックス機能またはイントロスペクション機能,EPT機能を呼び出すという流れになっている.詳細はDocumentation/SPEC.rst
を参照のこと.
SimpleVisor
リポジトリ | https://github.com/ionescu007/SimpleVisor |
形態 | カーネルドライバ |
仮想化支援機能 | Intel VT-x with EPT, AMD-V |
サポートしている環境 | Windows 8/8.1/10, UEFI |
言語 | C, アセンブリ言語 |
ライセンス | 2 clause BSD |
SimpleVisorは,名前の通り極力シンプルであることをめざしたハイパーバイザだ.全体で1700行程度.開発者はWindows Internalsの著者のひとりで,README.md
にはこう書かれている:
Have you always been curious on how to build a hypervisor? Has Intel’s documentation (the many hundreds of pages) gotten you down? Have the samples you’ve found online just made things more confusing, or required weeks of reading through dozens of thousands of lines and code? If so, SimpleVisor might be the project for you.
そういうわけで,SimpleVisorはIntel SDM (とくに,ハイパーバイザまわりはVol. 3C) の解読にうんざりした人向けだ.学習にはもってこい.CPUID
, INVD
, VMX
, XSETBV
のみトラップするようになっており,ネストには対応していない.しかし,XenやBochsでさえ追いついていない最新の仮想化支援機能にいちはやく追随しようとしている.
主なソースコードは以下の通り:
nt/shvos.c |
カーネルドライバのエントリポイント |
shv.c |
VMExit/VMEntryのコールバック関数の登録 |
shvvp.c |
コールバック関数の実体,仮想CPUの初期化 |
shvvmx.c |
VMCSの初期化 |
shvvmxhv.c |
VMExitのハンドラ |
shvutil.c |
GDTの変換 |
シンプル.
HyperPlatform
リポジトリ | https://github.com/tandasat/HyperPlatform |
形態 | カーネルドライバ |
仮想化支援機能 | Intel VT-x with EPT |
サポートしている環境 | Windows 7/8.1/10 |
言語 | C++, アセンブリ言語 |
ライセンス | MIT |
HyperPlatformは,カーネルランドで動くコード,すなわちWindows向けルートキットやWindowsカーネル自体の解析を目的として開発されているハイパーバイザ.物理メモリと仮想メモリへのアクセス,関数呼び出し,命令単位のコード実行を監視できるようになっている[S. Tanda. REcon’16].
主なソースコードは以下の通り:
driver.cpp |
カーネルドライバのエントリポイント,各種コールバック関数の登録 |
log.cpp |
ログ出力 |
global_object.cpp |
グローバル変数の初期化 |
performance.cpp |
パフォーマンス計測 |
util.cpp |
PTE_BASE の取得,メモリアドレス変換,VMCALLのラッパなど |
power_callback.cpp |
電源状態のコールバック関数 |
hotplug_callback.cpp |
CPUホットプラグのコールバック関数 |
vm.cpp |
仮想CPUの初期化,VMCSの読み書き |
ept.cpp |
EPTの構成 |
vmm.cpp |
命令のトラップ,VMExitのハンドラ |
Arch/x64/x64.asm , Arch/x86/x86.asm |
VMX命令呼び出しにともなう命令列 |
kernel_stl.cpp |
ntoskrnl経由でカーネルドライバからSTLを利用する |
エントリポイントから手続き的に書き下されていて,わかりやすい.ハイパーバイザとしての機能もさることながら,STLを強引に呼び出すハックがかっこいい.
この拡張例には以下がある:
MemoryMon | カーネルランドへのコード挿入を検知する |
EopMon | マルウェアによる特権昇格攻撃を検知する |
DdiMon | EPTを用いたAPIフック |
GuardMon | PatchGuardの挙動解析 |
いずれもカーネルドライバのエントリポイントで追加機能を初期化するしくみ.
やや温め納豆は遠くなりにけり.
おわりに
いずれもSandy Bridge以降のいまどきの環境であれば動作する.
卒業研究ではQEMUをベースとしたマルウェア解析環境を開発していたのだけど,やはり速度面に難があるし,このあたりの技術を再検討しないとなー.
なお,今回取り上げなかったハイパーバイザには以下のようなものがある:
MoRE | ルートキット文脈のハイパーバイザ.やや古い |
HyperBone | HyperPlatformと似た機能をもつ.やや古い |
Noah | 未踏のアレ.OS X上でLinuxバイナリを動かす.MacBook持ってないので試せないのだわ |
Bareflank | type 1, 2, ドライバいずれの形態のVMMもサポートしたライブラリ.しかもC++で書ける |
なかでもBareflankがヤバいので後編ではこれを読んでいきます.