Slide 1

Slide 1 text

QEMUの Dynamic Binary Translationが あって良かったねという話 5/25/2014 第十回カーネル/VM探検隊 @ntddk

Slide 2

Slide 2 text

自己紹介 ● Yuma Kurogome(@ntddk) ● Keio Univ. B2 ● 作ったことがあるもの – デバドラ, OS, VMM, EFI Application ● 作ったことがないもの – CPU, GPU, ネットワーク機器 ● チョトモワカラナイのにインターンでQEMUを 触ることになってしまった ● ので調べた

Slide 3

Slide 3 text

アッ ● この発表は遅延評価されました

Slide 4

Slide 4 text

なぜQEMUか ● QEMUのソースは魔窟[要出典] – 構造体(クロージャ)のポインタを謎のマクロに投げ 続ける – Pure Cで書かれているにも関わらず ● new ● object ● クラスの継承

Slide 5

Slide 5 text

なぜQEMUか ● 仮想化技術について学びたいなら……。 – bhyve – BitVisor – QEMUを読む優先度はあまり高くないのでは[要出典] https://twitter.com/syuu1228/status/460748398962806787

Slide 6

Slide 6 text

なぜQEMUか ● Dynamic binary translation(DBT)ができるから – 動的バイナリ変換

Slide 7

Slide 7 text

QEMUのエミュレーション方式 ● QEMUは2つの動作モードをサポートしている – カーネルモードエミュレーション ● あるアーキテクチャ向けのOSを 異なるアーキテクチャのホスト上で動かす – ユーザーモードエミュレーション ● あるアーキテクチャ向けにビルドされたバイナリを、 異なるアーキテクチャで動かす ● QEMUはdynamic binary translationによってこ れらを実現

Slide 8

Slide 8 text

QEMUの論文 ● F. Bellard. QEMU, a fast and portable dynamic translator. In USENIX, 2005. – 開発者による論文 – Wikiには”QEMU is a generic and open source machine emulator and virtualizer.”とあり、 – 今でこそQEMUはKVMの一部になっているが、 – そもそもVT-xを云々というよりdynamic translator としての側面が大きい[要出典] ● DBTがQEMUの肝[要出典]

Slide 9

Slide 9 text

Tiny Code Generatorの概略 ● Tiny Code Generator(TCG)によってDBT を実現 ● ゲストのコードを逆アセンブル ● 中間コードに変換 ● 中間コードをホストのコードに 変換 Vitaly Chipounov and George Candea. Dynamically Translating x86 to LLVM using QEMU. In EPFL, 2010.

Slide 10

Slide 10 text

TCG ● main()からcpu_exec() ● cpu-exec.cのtb_find_fast/slow()でunchained blockまで実行 cpu_exec() Prologue Epilogue Pre-generated code Translation Cache Code QEMU Internals

Slide 11

Slide 11 text

TCG Guest Code TCG Operations Host Code gen_intermediate_code() tcg_gen_code() ● target-[architecture] /translate.c ● tcg/tcg.c QEMU Internals

Slide 12

Slide 12 text

TCG Guest Code TCG Operations Host Code gen_intermediate_code() tcg_gen_code() push %ebp mov %esp,%ebp not %eax add %eax,%edx mov %edx,%eax xor $0x55555555,%eax pop %ebp ret QEMU Internals

Slide 13

Slide 13 text

TCG Guest Code TCG Operations Host Code gen_intermediate_code() tcg_gen_code() ld_i32 tmp2,env,$0x10 qemu_ld32u tmp0,tmp2,$0xffffffff ld_i32 tmp4,env,$0x10 movi_i32 tmp14,$0x4 add_i32 tmp4,tmp4,tmp14 st_i32 tmp4,env,$0x10 st_i32 tmp0,env,$0x20 movi_i32 cc_op,$0x18 exit_tb $0x0 QEMU Internals

Slide 14

Slide 14 text

TCG Guest Code TCG Operations Host Code gen_intermediate_code() tcg_gen_code() mov 0x10(%ebp),%eax mov 0x10(%ebp),%edx mov (%ecx),%eax mov %eax,%ecx add $0x4,%edx mov %edx,0x10(%ebp) mov %eax,0x20(%ebp) mov $0x18,%eax mov %eax,0x30(%ebp) xor %eax,%eax jmp 0xba0db428 (retのみ) QEMU Internals

Slide 15

Slide 15 text

TCG ● Translation Block(TB) – translate-all.hで定義されたBasic Block – 分岐命令かページの境界まででコードを区切る ● コードキャッシュからreturnしていると遅くな るため、TBを繋げて実行 ● なんかLLVMっぽくないですか?

Slide 16

Slide 16 text

QEMUのDBT(TCG)で何ができるか ● バイナリをLLVMに逆コンパイル – S2E[ASPLOS11]

Slide 17

Slide 17 text

S2E ● s2e.epfl.ch ● WindowsバイナリをLLVM bitcodeに変換する

Slide 18

Slide 18 text

S2EにおけるDBT Vitaly Chipounov and George Candea. Dynamically Translating x86 to LLVM using QEMU. In EPFL, 2010.

Slide 19

Slide 19 text

S2EにおけるDBT ● x86とLLVM bitcodeの間にあるsemantic gapを どうするか? – Dagger(dagger.repzret.org)はオレオレIRを実装 ● S2EはTCGで参照される辞書にLLVMの命令を 登録 ● LLVM bitcodeに変換されたバイナリを KLEE[OSDI08]に投げる

Slide 20

Slide 20 text

KLEE ● 与えられたソースコードをLLVMでビルド ● Symbolic executionからテストケースを生成 ● Coreutilsに試したところ、15年に渡る手動テス トを上回るカバレッジを89時間で達成!

Slide 21

Slide 21 text

Symbolic execution ● 記号実行と訳される ● 変数に代数シンボルを与えて監視 ● プログラムはある結果に収束するか ● どの入力値でどの実行パスを通るか ● 条件分岐に行き当たる度に分岐が実行可能か SAT solverに解かせる ● あらゆる実行パスを通りたい

Slide 22

Slide 22 text

SAT solver ● ブール式の充足可能性問題を解くプログラム ● 式は連言標準形(CNF)で与えられる ( a1 or !a2 or a3 ... or an) and ( b1 or b2 or !b3 ... or !bn) and … – リテラル: a1や!a2といった命題変数またはその否定 – 節: 複数のリテラルの選言(or) – CNF式: 複数の節の連言(and)

Slide 23

Slide 23 text

SAT solver ● ベースになっているのはDPLLアルゴリズム – 変数に値を代入して矛盾が起きるまで探索 – ヒューリスティックに変数を選択 – 分割規則を適用、再帰的な二分探索 – 式を満たす変数割当が見つかればSAT

Slide 24

Slide 24 text

KLEEのSAT solver ● KLEEはSTPを使用 – 前身のEXE[CCS06]のために開発された – 厳密にはSAT solverの上位版であるSMT solver ● SMT solver – ブール式に加えて「背景理論」をサポートす ● 配列 ● ビットベクトル ● etc …

Slide 25

Slide 25 text

S2Eにおけるsymbolic execution ● Q. バイナリを直接symbolic executionすれば良 いのでは? ● A. x86はSSAでないのでレジスタがコンフリク トを起こすかも mov esi, 0x13 mov edx, 0x2014 mov esi, 0x13 … mov esi, 0x2014 (esi == 0x13) and (edx == 0x2014) (esi == 0x13) and (esi == 0x2014)

Slide 26

Slide 26 text

S2Eのまとめ ● x86とLLVM bitcodeの間にあるsemantic gapを QEMUで克服 ● Windowsバイナリに対してsymbolic execution を通じてテストケースを生成 ● LLVMデコンパイラとして使える

Slide 27

Slide 27 text

LLVMデコンパイラで何ができるか ● Windowsバイナリからテストケース生成 – S2E[ASPLOS11] ● マルウェアの難読化を解除する – OptiCode[Syscan13]

Slide 28

Slide 28 text

OptiCode ● バイナリをLLVM bitcodeに変換 – QEMUを用いたのかどうかは不明 ● LLVMの最適化パスによって難読化を除去 – レジスタに無意味な値を挿入する難読化 ● -dse, -simplifycfg – NOPと等価の命令を挿入する難読化 ● -constprop, -instcombine – レジスタへの代入をばらけさせる難読化 ● -instcombine – etc …

Slide 29

Slide 29 text

OptiCode ● Opaque predicateへの対応 – LLVMによる最適化では解除できない – 常に真(偽)となる条件文を挿入、 実行されない箇所にコードを配置するというもの – LLVM bitcodeに対してsymbolic execution – OptiCodeではSMT solverにZ3を使用

Slide 30

Slide 30 text

OptiCodeのまとめ ● マルウェアをLLVM bitcodeに逆コンパイル ● LLVMの最適化パスをそのまま難読化の解除に 使える ● LLVM bitcodeに逆コンパイルできれば symbolic executionで難読化の解除もできる

Slide 31

Slide 31 text

まとめ ● QEMUはアーキテクチャ間のコード変換を実現 ● LLVMへの逆コンパイルとsymbolic execution への適用 ● QEMUのDBTがあって良かったね