Upgrade to Pro — share decks privately, control downloads, hide ads and more …

LLVM meets kernel

Yuma Kurogome
December 08, 2013

LLVM meets kernel

第九回 カーネル/VM探検隊 発表資料 http://peatix.com/event/22490 #kernelvm

Yuma Kurogome

December 08, 2013
Tweet

More Decks by Yuma Kurogome

Other Decks in Programming

Transcript

  1. LLVM meets kernel
    @ntddk

    View Slide

  2. whoami

    Yuma Kurogome(@ntddk)

    慶應義塾大学 SFC B1, 武田研

    留年の危機

    Synclogue Inc.

    Windows kernel, RCE, LLVM ← new!

    View Slide

  3. whoami

    CTF
    – EpsilonDelta(一応)
    – sutegoma2(潜入)
    – Kazusa

    HackInTheBox KL
    – ROPが解けなかった

    View Slide

  4. 今回話すこと

    LLVM

    Return-oriented programming(ROP)

    LLVMによるROP緩和技術

    LLVMLinux

    View Slide

  5. LLVM

    View Slide

  6. 詳しくは...

    View Slide

  7. LLVM

    プログラムの最適化を支援するコンパイラ基盤

    任意の言語 → LLVM IR → 任意の言語

    View Slide

  8. LLVMの構成

    Frontend

    Middlend

    Backend

    View Slide

  9. Frontend

    字句解析

    構文解析

    意味解析

    コード生成
    – LLVM IR

    Frontendを実装するだけで任意の言語のコンパ
    イラが作れる
    – MiddlendとBackendはLLVMデフォルトでも十分

    View Slide

  10. Middlend

    PassによるLLVM IRの解析と最適化
    – 関数全てに対するPass
    – ループ文に対するPass
    – ジャンプのない一連の処理に対するPass
    – etc...

    自分だけのPassでみんなと差をつけろ

    View Slide

  11. Backend

    アセンブリ生成

    実行オブジェクト生成

    LLVM IRの実行(JIT)

    コード生成(トランスレータ)

    独自の言語のソースコードを生成したい場合は
    Backendを実装する必要がある

    View Slide

  12. Clang

    C, C++, Obj-C, Obj-C++のFrontend

    C++14(N3797)の機能を完全に実装

    BSDライクなライセンス
    – gccはGPLv3

    View Slide

  13. ROP

    View Slide

  14. 脆弱性対策技術

    scanf("%s", buf);
    – EIP 0x41414141からが戦い

    プログラムに脆弱性があっても悪用されない機
    能の実現

    View Slide

  15. 脆弱性対策技術

    StackGuard
    – リターンアドレス付近に乱数を配置

    StackSheild
    – リターンアドレスを離れた位置に保存

    ASLR
    – アドレスのランダマイズ
    – 攻撃の成功率を下げる

    Exec Shield
    – データ実行防止

    View Slide

  16. ROP

    脆弱性攻略のための一技術
    – Exec Shieldを突破する

    Return-oriented programming

    短いコードブロックを組み合わせてシェルコー
    ドとする
    – ROP gadgets
    – シェルコードとして使える命令とリターンのセット
    – 命令をずらして解釈することも
    – ASLRがかかっていないファイルを利用

    View Slide

  17. ROP gadgets
    684a0f4e:
    pop eax
    ret
    684a2367:
    pop ecx
    ret
    684a123a:
    mov[ecx], eax
    ret
    0x684a123a
    0xfeedface
    0xdeadbeef
    0x684a2367
    0x684a0f4e

    View Slide

  18. View Slide

  19. Return-oriented rootkit

    Rootkit
    – カーネル構造体などを書き換える
    – 悪意のあるプログラムを隠蔽

    Return-oriented rootkit
    – Return-Oriented Rootkits: Bypassing Kenrel Code
    Integrity Protection Mechanism
    – ROPを利用したrootkit
    – ROPでカーネルの整合性検証をバイパスする

    View Slide

  20. Return-oriented rootkit

    カーネルの整合性検証
    – 未許可のLKMを実行しない

    LKMにシグネチャを付加して検証
    – みんな大好きVMM

    BitVisorとか
    – 書き込み可能なアドレスの実行権限を外す

    View Slide

  21. Return-oriented rootkit

    rootkitと名が付いているがLKMをロードする
    わけではない

    要するにカーネルモードでのROP

    LKMにバッファオーバーフローなどの脆弱性が
    ある場合の攻撃手法

    View Slide

  22. LLVMによるROP緩和技術

    View Slide

  23. Return-less kernel

    ROPでは任意の命令とリターンを組み合わせる

    じゃあカーネルから
    リターンをなくせば
    いいじゃん

    Defeating Return-Oriented Rootkits With
    “Return-less” Kernels

    せっかくだから俺はLLVMを使うぜ

    View Slide

  24. LLVMのFreeBSD対応

    まともに動くFreeBSDカーネルをビルドできる
    ようになったのは2009年2月25日

    Return-less kernelが発表されたのは2010年4月

    FreeBSD 8.0対象

    View Slide

  25. Return-less kernel

    3つの手法でカーネルからreturnを除去
    – Return indirection
    – Register allocation
    – Peephole optimization

    LLVM backendを中心に実装
    – マシン語の最適化
    – 1命令を減らす最適化はバックエンドでのみ可能

    View Slide

  26. Return indirection

    リターンアドレスをテーブルから取得してくる
    – retは直接スタック上の戻り先アドレスを読み込む
    – 別の位置にあるリターンアドレスを読み込んでから
    そのアドレスにジャンプするようにすればガジェッ
    トを無効化できる

    View Slide

  27. Return indirection

    call, retを新しい形式に置き換える
    push $index
    jmp dst
    ...
    pop %reg
    jmp *RegAddrBase(%reg)

    View Slide

  28. Register allocation

    Return indirectionだけでretを除去できるとは
    限らない

    x86は可変長であるためコンパイラがretを生成
    してしまうことがある
    mov %eax, %ebx -> 89 c3

    movなのに何故かret(0xc3)に...

    LLVM IRの仮想レジスタマッピング時に調整

    View Slide

  29. Register allocation

    llvm::Spiller

    LLVMのレジスタ割り当てアルゴリズム
    – Simple scan
    – Local scan

    これら2つは仮想レジスタから直接マッピング
    – Linear scan

    より高度な割り当て

    View Slide

  30. Register allocation

    Linear scanを利用

    X86RegisterInfo.tdを拡張
    – x86におけるレジスタ記述ファイル

    危険なレジスタ割り当てにアノテーション

    再割り当て

    ご安全に!

    View Slide

  31. Peephole optimization

    コード中の0xc3を書き換える
    – 即値でもretと解釈してROPに使える
    cmp $0xc3,%ecx

    mov $0xc4, %reg
    dec %reg
    cmp %reg, %ecx

    View Slide

  32. Peephole optimization

    FreeBSD 8.0におけるコード
    0xFFFFFFFF801A4F01: E9 C3 00 00 00
    jmpq 0xFFFFFFFF801A4FC9

    この0xc3の意味は?

    View Slide

  33. Peephole optimization

    jmpq命令の直後からのオフセット

    相対アドレスの調整で0xc3を排除できる
    0xFFFFFFFF801A4F01: E9 C4 00 00 00
    jmpq 0xFFFFFFFF801A4FCA
    0xFFFFFFFF801A4F06: 90
    nop

    View Slide

  34. LLVMLinux

    View Slide

  35. +

    View Slide

  36. LLVMLinux

    View Slide

  37. 現状

    LLVMでLinuxカーネルをビルドしたい!
    – Linuxカーネルはgccの拡張機能と癒着
    – LLVM/Clangはgccの規格違反の挙動を絶対に実装
    しない

    LLVMへの機能追加とカーネルへのパッチで実

    – gcc拡張の闇を取り除く

    View Slide

  38. gcc拡張の闇

    Variable length arrays in structs (VLAIS)
    – Variable length arrayの拡張
    – 構造体内で配列の長さを実行時指定
    – iptablesやHMACなどで利用されている
    struct foo_t {
    char a[n];/* Explicitly not allowed by C99/C11 */
    } foo;

    View Slide

  39. gcc拡張の闇

    __builtin_constant_pによる定数検出の回避
    – LLVM Bug 4898

    Inline syntax handling
    – GNU89

    __initと__exit

    レジスタ変数
    – x86
    register unsigned long current_stack_pointer asm("esp")
    __used;
    – ARM
    register unsigned long current_sp asm ("sp");

    View Slide

  40. Return-less Linux kernel

    そろそろLLVMでLinuxをビルドできそう

    LinuxでもReturn-less kernelを実現できたらい
    いよね

    GSoCとか...

    OSvってどうなの

    View Slide