QEMUのDynamic Binary Translationがあって良かったねという話

QEMUのDynamic Binary Translationがあって良かったねという話

第十回カーネル/VM探検隊 発表資料

5c6358240ec94522f70cf7b0e657f58f?s=128

Yuma Kurogome

May 25, 2014
Tweet

Transcript

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

  2. 自己紹介 • Yuma Kurogome(@ntddk) • Keio Univ. B2 • 作ったことがあるもの

    – デバドラ, OS, VMM, EFI Application • 作ったことがないもの – CPU, GPU, ネットワーク機器 • チョトモワカラナイのにインターンでQEMUを 触ることになってしまった • ので調べた
  3. アッ • この発表は遅延評価されました

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

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

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

  7. QEMUのエミュレーション方式 • QEMUは2つの動作モードをサポートしている – カーネルモードエミュレーション • あるアーキテクチャ向けのOSを 異なるアーキテクチャのホスト上で動かす – ユーザーモードエミュレーション

    • あるアーキテクチャ向けにビルドされたバイナリを、 異なるアーキテクチャで動かす • QEMUはdynamic binary translationによってこ れらを実現
  8. 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の肝[要出典]
  9. Tiny Code Generatorの概略 • Tiny Code Generator(TCG)によってDBT を実現 • ゲストのコードを逆アセンブル

    • 中間コードに変換 • 中間コードをホストのコードに 変換 Vitaly Chipounov and George Candea. Dynamically Translating x86 to LLVM using QEMU. In EPFL, 2010.
  10. 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
  11. TCG Guest Code TCG Operations Host Code gen_intermediate_code() tcg_gen_code() •

    target-[architecture] /translate.c • tcg/tcg.c QEMU Internals
  12. 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
  13. 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
  14. 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
  15. TCG • Translation Block(TB) – translate-all.hで定義されたBasic Block – 分岐命令かページの境界まででコードを区切る •

    コードキャッシュからreturnしていると遅くな るため、TBを繋げて実行 • なんかLLVMっぽくないですか?
  16. QEMUのDBT(TCG)で何ができるか • バイナリをLLVMに逆コンパイル – S2E[ASPLOS11]

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

  18. S2EにおけるDBT Vitaly Chipounov and George Candea. Dynamically Translating x86 to

    LLVM using QEMU. In EPFL, 2010.
  19. S2EにおけるDBT • x86とLLVM bitcodeの間にあるsemantic gapを どうするか? – Dagger(dagger.repzret.org)はオレオレIRを実装 • S2EはTCGで参照される辞書にLLVMの命令を

    登録 • LLVM bitcodeに変換されたバイナリを KLEE[OSDI08]に投げる
  20. KLEE • 与えられたソースコードをLLVMでビルド • Symbolic executionからテストケースを生成 • Coreutilsに試したところ、15年に渡る手動テス トを上回るカバレッジを89時間で達成!

  21. Symbolic execution • 記号実行と訳される • 変数に代数シンボルを与えて監視 • プログラムはある結果に収束するか • どの入力値でどの実行パスを通るか

    • 条件分岐に行き当たる度に分岐が実行可能か SAT solverに解かせる • あらゆる実行パスを通りたい
  22. SAT solver • ブール式の充足可能性問題を解くプログラム • 式は連言標準形(CNF)で与えられる ( a1 or !a2

    or a3 ... or an) and ( b1 or b2 or !b3 ... or !bn) and … – リテラル: a1や!a2といった命題変数またはその否定 – 節: 複数のリテラルの選言(or) – CNF式: 複数の節の連言(and)
  23. SAT solver • ベースになっているのはDPLLアルゴリズム – 変数に値を代入して矛盾が起きるまで探索 – ヒューリスティックに変数を選択 – 分割規則を適用、再帰的な二分探索

    – 式を満たす変数割当が見つかればSAT
  24. KLEEのSAT solver • KLEEはSTPを使用 – 前身のEXE[CCS06]のために開発された – 厳密にはSAT solverの上位版であるSMT solver

    • SMT solver – ブール式に加えて「背景理論」をサポートす • 配列 • ビットベクトル • etc …
  25. 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)
  26. S2Eのまとめ • x86とLLVM bitcodeの間にあるsemantic gapを QEMUで克服 • Windowsバイナリに対してsymbolic execution を通じてテストケースを生成

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

  28. OptiCode • バイナリをLLVM bitcodeに変換 – QEMUを用いたのかどうかは不明 • LLVMの最適化パスによって難読化を除去 – レジスタに無意味な値を挿入する難読化

    • -dse, -simplifycfg – NOPと等価の命令を挿入する難読化 • -constprop, -instcombine – レジスタへの代入をばらけさせる難読化 • -instcombine – etc …
  29. OptiCode • Opaque predicateへの対応 – LLVMによる最適化では解除できない – 常に真(偽)となる条件文を挿入、 実行されない箇所にコードを配置するというもの –

    LLVM bitcodeに対してsymbolic execution – OptiCodeではSMT solverにZ3を使用
  30. OptiCodeのまとめ • マルウェアをLLVM bitcodeに逆コンパイル • LLVMの最適化パスをそのまま難読化の解除に 使える • LLVM bitcodeに逆コンパイルできれば

    symbolic executionで難読化の解除もできる
  31. まとめ • QEMUはアーキテクチャ間のコード変換を実現 • LLVMへの逆コンパイルとsymbolic execution への適用 • QEMUのDBTがあって良かったね