Successfully reported this slideshow.
We use your LinkedIn profile and activity data to personalize ads and to show you more relevant ads. You can change your ad preferences anytime.

how to port * to BitVisor

2017/12/05 BitVisor Summit 6

Related Books

Free with a 30 day trial from Scribd

See all

Related Audiobooks

Free with a 30 day trial from Scribd

See all
  • Be the first to comment

how to port * to BitVisor

  1. 1. BitVisorに「移植」する 東京農工大学 市川 遼 2017/12/05 BitVisor Summit 6
  2. 2. 自己紹介 ● 東京農工大学 工学府情報工学専攻1年 ● twitter: @icchyr ● CTF: TokyoWesterns ● 研究: OS, セキュリティ
  3. 3. 本日お話しすること ● LVisorについて ● LVisorの実装上の課題 ○ BitVisorのどの部分で動かすのか ○ どうやって呼び出すのか ○ エラーが起きたらどうするのか ○ 依存ライブラリはどうするのか ○ etc. ● これらを解決する方法を検討 ○ BitVisorに外部のプログラムを移植した例は多くあるが, ソースコードが公開されているものは少ない ○ 初期実装ではひたすらアドホックに試した → 後に限界が見えてきた ■ なるべくソースコードを改変する必要がない方法を模索 ○ 実装する上での具体的な手順について共有
  4. 4. LVisorの背景 ● VMMに汎用スクリプト言語を組み込むモチベーション ○ 比較的簡単に複雑な処理を記述可能 ○ eval相当の機能がある場合は動的にプログラムを追加可能 ○ 通常VMMに動的に機能を追加するのは難しい ● BitVisorにVMI (Virtual Machine Introspection) があるとうれしい ○ ゲストOSから不可視 ■ マルウェア解析環境として適している ○ 他のVMMに比べてパフォーマンスが優れている ■ 解析効率の向上 ● BitVisorにLuaとLibVMIを組み込んだ ○ 普通のBitVisorでは処理を追加するために Cで直接VMMを書き換える必要がある ○ スクリプト言語でBitVisorを使いたい ○ LibVMI+シンボル情報でゲスト OS解析の補助 ○ Luaのプログラムをルールとしてプロセスやネットワークを監視
  5. 5. Luaを選んだ理由 ● Luaの特徴 ○ (比較的) 早い ○ バイナリが小さい,依存ライブラリが少ない (最低限libc, libmのみ) ○ 記述方法が多様 ■ 手続き型 ■ プロトタイプベース ■ など ○ インターフェースとして有用 ● BitVisorの特徴 ○ 早い ○ VMMが小さい ○ 拡張のハードルが高い ■ processなどを書いてビルドし直す必要がある ● BitVisorに組み込む上でLuaは比較的相性が良い
  6. 6. インターフェースとしてのLua ● LuaをインターフェースとするAPIを提供 ○ システムコールフック ○ 仮想メモリアクセス ○ ネットワークパケットフィルタ ● オブジェクト指向でデータにアクセス ○ フックするイベントに対して処理を登録 ○ イベントハンドラにフック対象に関わるオブジェクトが渡される ● Luaはプロトタイプベースなので記述しやすい ○ メソッドに対して動的に処理を追加できる ○ 関数の動作を上書きすることが可能なため用途に合わせてフレームワーク的に扱える
  7. 7. LVisorの例 ● 使用例 ○ /tmp/ で始まるバイナリが起動 (execve) された時に全てのネットワーク通信を遮断 ○ 現状プロセス単位の通信は制御できない denyall = function(eth) return DROP end execve_hook = function(args) filename = args[0] -- execveの第一引数 (filename) へのポインタを取得 filename_s = pmem.read(filename, 0x100) -- filenameを文字列で取得 -- /tmp/で始まるバイナリの場合全てのネットワーク通信を遮断 if string.match(filename_s, “^/tmp/”) ~= nil then net.eth.hooks.add(“*”, “*”, “denyall”, denyall) end end syscall.hooks.add(“netproc”, execve_hook)
  8. 8. LVisorの実装方法
  9. 9. BitVisorに機能を追加する方法 ● BitVisorで処理を走らせる手段 ○ 一回のみ ■ INITFUNC ○ 定期的 ■ thread ○ dbgshから任意のタイミング ■ process ○ ゲストOSから任意のタイミング ■ vmmcall ● BitVisorの実装 (vpn, storageなど) ○ BitVisorの機能が必要な部分のみ msgbufで呼び出し,それ以外は保護ドメインで処理 ○ 必要な時のみしかRing 0で動作させない方針
  10. 10. LVisorの実装方針 ● Ring 0で動かすのは得策ではない ○ 移植するプログラムが巨大であるため ● 基本的にvpnやstorage等と同じ方針をとる ○ 必要な部分だけmsgbufでやりとりする ○ Lua,LibVMIは保護ドメインで動作させる ● まずLuaのインタプリタを組み込み,次にLibVMIを移植 ● 環境 ○ Lua: 5.3.3 ○ LibVMI: 2016年9月時点でのGitHubの版
  11. 11. BitVisorのビルドシステムおさらい ● makeをベースとしたビルドシステム ○ 下の階層をビルドした結果を上の階層にリンク ○ オブジェクト (.o) を作る場合は subdirs-1 に追加 ○ 静的ライブラリ (.a) を作る場合は asubdirs-1 に追加 ○ objs-1 にオブジェクトファイルを追加することでビルド対象を決定 ○ CFLAGSを書き換えることでコンパイルオプションを調節 ○ 基本的にカレントディレクトリは一番上 (bitvisor/) になることに注意 ● processのビルド ○ $(name)-objs にオブジェクトファイルを追加 ○ $(name)-libs に依存ライブラリ (.a) を追加 ○ bins-1 にprocessとして登録する名前を追加
  12. 12. リンクについて ● BitVisorは基本的にstatic link ○ dynamic linkがサポートされていない ○ そもそもサポートする必要がない (再利用されるコードが極めて小さいため ) ○ バイナリのローダは存在するがライブラリのローダは存在しない ● Ring 0の部分は最終的に全て同じ階層でリンクされる ○ どこかにシンボルが存在していればよい ○ processからリンクしたい場合は process-dependsに加える必要がある
  13. 13. ソースコードの配置場所 ● 全てprocess配下に置くのが正しいか? ○ vpnやstorageはそうではない ■ dbgshから呼び出すことを想定していない ● 例: vpn ○ vpn/lib/user.c に処理を書き,process/vpn.c ではexternのようにして呼び出す ○ この構成のメリット ■ process/Makefileを汚さない ■ process/ 以外からもリンクすることができる ● musl, LibVMIは一番上の階層に置く
  14. 14. 移植に必要な手順 ● 静的ライブラリまたはオブジェクトを作成する ○ BitVisorのビルドシステムに組み込む ■ findコマンドなどである程度自動化 , コンパイルオプションに注意 ○ プロジェクトのMakefileを直接叩く ■ カレントディレクトリに注意 ● 必要なプログラムの依存関係に加える ○ processであれば$(name)-libs ○ それ以外であればasubdirs-1 (or subdirs-1) ● 標準的なOSの機能を使う部分は修正する必要がある ○ 標準入出力, メモリ管理は特にBitVisorに合わせる必要がある
  15. 15. Luaの組み込み方法 ● Luaは比較的移植がしやすい ○ 依存ライブラリが少ない ○ 全てのソースコードが同じ階層に存在し,コンパイルしたオブジェクトをリンクするだけ ■ ビルドシステムへの負担が少ない ○ 静的ライブラリ (.a) を作成できればよい ● BitVisorのビルドシステムに組み込む ○ BitVisorのビルドシステムを理解する ○ process/ 以下にluaのソースコードを丸ごとコピー ○ LuaのMakefileをBitVisor向けに編集 (objs-1にLuaのプログラムを追加していくだけ ) ○ process/MakefileにLuaに関わる部分を追記 ● これだけでは動かない ○ libcが必要 ○ BitVisorは部分的にしかlibcの関数をサポートしていない
  16. 16. libcの組み込み方法 ● 必要なlibcを移植するのは大変 → 既存のlibcを移植する ● どのlibcを使うか? ○ eglibc ○ uClibc ○ newlib ○ musl libc ○ etc. ○ 比較的サイズが小さくビルドも簡単な musl libcを採用 ● BitVisorに合わせた変更が必要 ○ ファイルシステムおよび fdの概念が存在しない ○ BitVisorのprocess/libでサポートしている関数に注目 ■ 標準出力 (printf) ■ 標準入力 (lineinput) ■ メモリ管理 (alloc/free) ○ 最低限これらの機能と接続しないと動作しない
  17. 17. libcの組み込み方法 ● muslの関数を編集 ○ 標準出力 ■ __fwritexでputcharを使う (process/lib/lib_putchar.c) ■ muslのprintfを使えるようにするため ● BitVisorのprintfは浮動小数点系のフォーマット指定子に対応していない ○ 標準入力 ■ libc側で対応せずにprocessの入力を受け取るところで対処 ○ メモリ管理 ■ malloc ● process/lib/lib_mm.c:alloc を使うように修正 ■ free ● process/lib/lib_mm.c:free を使うように修正 ■ realloc ● size == 0の時のバグを修正 ■ 確保可能な領域は各 processでheap, heaplenを定義して調整
  18. 18. libcの組み込み方法 ● ビルドシステムの修正 ○ muslのMakefileをBitVisorに対応させるのは困難 ○ BitVisorのmake中にmuslのmakeを走らせるようにする ■ cleanを回避する場合は ifndef clean_p の中に書く (clean時に定義される変数の一つ ) ● リンク方法の検討 ○ プロジェクトの.aを直接リンクする (ビルド時に生成された .aを指定) ○ BitVisorのビルドシステムで.aを作る (ビルド時に生成された .oを集める) ← こちらを採用 ● 例: include makefiles/musl.mak ifndef clean_p $(info building musl...) $(info $(shell cd $(musl_dir) && make -j4 && cd - >/dev/null)) objs-1 += $(musl_o) endif
  19. 19. Luaの組み込み方法 (続き) ● Luaのインタプリタを用意する ○ lua.cをprocess向けに編集 ○ lua_writelineマクロとlua_readlineマクロをそれぞれ編集 ■ printfとlineinputを使うように修正 ○ main関数を修正 ■ setlimitを呼び出して大きくスタックを確保するように修正 ● 標準ではスタックが足りなくてクラッシュする ■ pushcfunction~reportまで削除し,代わりに doREPLを呼び出す ● argc, argvが存在しないためpushcfunctionが使えない ■ exitprocessで終了 ● 浮動小数点レジスタのサポート ○ VMM起動時にCR0を操作して有効化しておく (一時的な措置) ● debugshのprocessからLuaインタプリタが使用可能に
  20. 20. LibVMIの組み込み方法 ● LibVMIはlibcの他にGlib, json-cに依存 ○ libcと同様の方法でビルドシステムに組み込む ● LibVMIのBitVisor対応 ○ XenをベースにBitVisor用のdriverを作成 ■ ゲストOSのCPUの読み書き ■ ゲストOSの物理メモリの読み書き ■ ゲストOSの電源操作 (pause, resume, halt) ■ メモリサイズの取得 ○ CPUレジスタ操作,メモリ操作があれば理論上は動作する ○ rekallのprofileを用意 ■ 現状はファイルシステムが無いのでバイナリの dataセクションに埋め込む ■ objcopyでJSONを変換 ■ サイズが非常に大きい (Linuxで約3.3M) ため改善の必要あり
  21. 21. LibVMIの組み込み方法 ● ビルドシステムの修正 ○ LibVMIのビルドシステムはKVM, Xenなどの本来対応する VMM用のライブラリに深く依存 ○ BitVisor用のdriverをビルドするようにMakefileを作成 ■ libvmi/およびその下のarch, driver, os以下 ● 例: include makefiles/libvmi.mak CFLAGS += $(libvmi_INCLUDE) curdir = $(libvmi_dir)/driver subdirs-1 += bitvisor obj = $(subst .c,.o,$(shell find $(curdir) -maxdepth 1 -name "*.c")) objs-1 += $(obj:$(curdir)/%=%)
  22. 22. 近況 ● Luaはほぼ完全に動作 ○ muslのprint系が壊れていて変な出力が出るものの特に影響はない ● LibVMIが完全に動いていない ○ 動きはするがオフセットがずれている ● ネットワーク監視が完全に動いていない ○ netapiの使い方が把握しきれていない ● 全てのAPIに対応できていない
  23. 23. まとめ ● BitVisorへの移植は比較的容易な手順で実現可能 ○ 一番上の階層にプロジェクト用のディレクトリを切り分ける ○ プロジェクトをそのままコピーする ○ Makefile内でプロジェクトのビルドを行う ○ 生成された.oファイルを検索してobjs-1に追加 ● libc, GLibcが移植できたため大抵のプログラムは移植可能 ○ OSの機能を必要とするものは移植できない ○ BitVisorを拡張するのが容易に

×