1
【技術解説/紹介】
S2E:
Selective Symbolic Execution Engine
NTTセキュアプラットフォーム研究所
中島明日香
2014/3/24
•S2E: A Platform for In Vivo Multi-Path Analysis of Software Systems. Vitaly Chipounov, Volodymyr Kuznetsov, George
Candea. 16th Intl. Conference on Architectural Support for Programming Languages and Operating Systems (ASPLOS),
Newport Beach, CA, March 2011.
※スライド中に利用されている図等の出典元は上記論文
• S2E概要
• シンボリック実行とは
• 選択的シンボリック実行とは
• S2Eのシステム概要
• S2Eの機能概要
• シンボリック実行の方法(概要)
• シンボリック実行の方法(詳細)
• S2Eを利用した研究
• 参考文献
2
目次
S2E概要
3
ソフトウェアの性能測定
リバースエンジニアリング
ソフトウェアのバグ発見
想定利用形態
概要
Vitaly Chipounov, Volodymyr Kuznetsov, George Candea
School of Computer and Communication Sciences
´Ecole Polytechnique F´ed´erale de Lausanne (EPFL), Switzerland
開発者
公式サイト https://s2e.epfl.ch/projects/s2e
GoogleGroups https://groups.google.com/forum/#!forum/s2e-dev
バイナリファイルを、実行環境そのもの(ライブラリ、カーネル、デバイスドライバ)を含めて
シンボリック実行するためのシステム。「選択的シンボリック実行」と呼ばれる、新しい
シンボリック実行の手法を利用して、実用的なシンボリック実行を目指したもの(2010年公開)
シンボリック実行とは[1/6]
4
シンボリック実行とは
シンボリック実行は、プログラムを、そのプログラムに含まれる変数に
具体的な数値を入力する代わりに、数値を代表するシンボルでプログラムを
模擬的に実行し、その結果を評価する技術
1976年に考案された手法/日本語「記号的実行」
ソースコードが主流/バイナリも
既存のシンボリック実行のツール
EXE/KLEE (Stanford) LLVMbitcodeを利用
CUTE (UIUC) ソースコードを利用
DART (ベル研究所) ソースコードを利用
SAGE(Microsoft Research) バイナリ
シンボリック実行とは[2/6]
5
シンボリック実行の仕組み
変数をシンボルとして扱い、プログラムを模擬的に実行する。
分岐条件が出てきたら、制約を記録し、forkして全ての分岐先に分かれる
利用目的
ソフトウェアテスト [テストケース生成]
Automatic Exploit Generation
迷路/簡単なCrackmeを解く
脆弱性発見
後から制約ソルバーを利用し、記録した制約からテストケース生成も可
6
シンボリック実行とは[3/6]
例
パス
シンボリック実行の用語
プログラムの実行パス
制約 プログラムの特定の実行パスを実現するための条件
if(number < 5000){
if(number == 1337 ){
vuln_function();
}
function1();
}
if(number < 5000)
vuln_function();
if(number == 1337)
function1()
制約ソルバー 制約を解くプログラム
・Number変数をシンボルとして扱う場合
7
シンボリック実行とは[4/6]
if(number < 5000)
vuln_function();
if(number == 1337)
function1()
パス
パス
シンボリック実行の用語
プログラムの実行パス
制約 プログラムの特定の実行パスを実現するための条件
制約ソルバー 制約を解くプログラム
8
シンボリック実行とは[5/6]
if(number < 5000)
vuln_function();
if(number == 1337)
function1()
制約
number < 5000 && number == 1337
パス
シンボリック実行の用語
プログラムの実行パス
制約 プログラムの特定の実行パスを実現するための条件
制約ソルバー 制約を解くプログラム
9
シンボリック実行とは[6/6]
if(number < 5000)
vuln_function();
if(number == 1337)
function1()
制約ソルバー
number < 5000 && number == 1337
パス
シンボリック実行の用語
プログラムの実行パス
制約 プログラムの特定の実行パスを実現するための条件
制約ソルバー 制約を解くプログラム
上記を実行するための値は
1337であることを算出
選択的シンボリック実行とは[1/2]
10
選択的シンボリック実行とは?
実システムでプログラムを実行させると、プログラム中の命令に応じて様々な部分が呼び
出される(ライブラリ、カーネル、デバイスドライバなど)
全てのプログラムのパスを通っていたら、簡単にPath Explosionしてしまう
そこで、シンボリック実行を行う部分を、限定可能にしたのが
選択的シンボリック実行
11
選択的シンボリック実行とは[2/3]
選択的シンボリック実行のイメージ
シンボリック実行を行いたい部分以外は、コンクリート(特定の値)で実行
12
選択的シンボリック実行とは[3/3]
その他の選択的シンボリック実行
データによる 選択的シンボリック実行
コードによる 選択的シンボリック実行
優先順位度による 選択的シンボリック実行
シンボル化するデータ[変数]を指定し、その変数が使用されている部分のみ
シンボリック実行する
シンボリック実行を行いたい部分[カーネル、ライブラリ等]を選択し、
シンボリック実行する。データによるシンボリック実行と組み合わせて使用する。
興味が無いパス(n回以上ループしている)を削除する等
13
S2Eのシステム概要[1/5]
利用技術
システム概要
ホストOS:Ubuntu 12.04 64bit
LLVM
QEMU
ゲストOS:Debian 6.0.2.1/Windos XP SP3 en (32bit)
QEMUを利用して統合的なシンボリック実行環境を準備
様々なCPUアーキテクチャに対応
KLEE(シンボリック実行エンジン)
STP (制約ソルバー)
14
KLEE
S2Eのシステム概要[2/5]
http://klee.github.io/klee/GetStarted.html公式サイト
LLVMbitcodeを利用したシンボリック実行エンジン[?]
int get_sign(int x) {
if (x == 0)
return 0;
if (x < 0)
return -1;
else
return 1;
}
int main() {
int a;
klee_make_symbolic(&a, sizeof(a), “a”);
return get_sign(a);
}
KLEEの使い方
シンボル化
処理
・サンプルプログラム
klee get_sign.o
llvm-gcc --emit-llvm -c -g get_sign.c
・実行→すべてのパスを実行し、その実行パスを再現するテストケースを生成
Cristian Cadar, Daniel Dunbar, Dawson Engler,Stanford 2008年
15
S2Eのシステム概要[3/5]
前提
QEMU上でx86→LLVM bitcodeに変換する仕組みを開発
(バイナリ変換-DBT)[?]
KLEEはLLVM bitcodeを利用する
用語
LLVM bitcode
マイクロオペレーション
LLVM用の中間言語のこと
命令セットアーキテクチャによって定められた
命令を、プロセッサ内でさらに分割した単純な
命令のこと
16
S2Eのシステム概要[4/5]
前提
QEMU上でx86→LLVM bitcodeに変換する仕組みを開発
(バイナリ変換-DBT)[?]
KLEEはLLVM bitcodeを利用する
1.x86を逆アセンブルする
手順
2.マイクロオペレーションに変換
3.LLVM Code Dictionaryを使用して
LLVM bitcodeに変換する
17
S2Eのシステム概要[5/5]
S2E内のシンボリック実行の流れ
1.逆アセンブル
LLVMbitcodeに変換後、
KLEEに実行させる
通常実行時に利用する
マシンコードに変換後、
CPUに実行させる
2.マイクロオペレーションに変換
3.もしシンボル化されたデータに
アクセスしていたら
4.もし通常の実行であったら
18
シンボリック実行の方法(概要)
シンボリック実行方法
シンボリック実行を補助するプラグイン
Annotationを利用する方法 [方法3]
Init_env.soを利用する方法 [方法2]
カスタム命令[S2Eopcode]を直接利用する方法 [方法1]
StageManager: helps exploring library entry points more efficiently.
EdgeKiller: kills execution paths that execute some sequence of instructions
(e.g., polling loops).
BaseInstructions:implements various custom instructions to control symbolic execution from the guest.
SymbolicHardware: implements symbolic PCI and ISA devices as well as symbolic interrupts and DMA.
CodeSelector: disables forking outside of the modules of interest
Annotation: plugin lets you intercept arbitrary instructions and function calls/returns
and write Lua scripts to manipulate the execution state, kill paths, etc.
19
シンボリック実行の方法[方法1]
カスタム命令を直接利用する方法
S2E opcodes S2EのゲストOS上で利用するカスタム命令。S2Eopcodesを実行すると、
S2Eが直接割り込みを行い、シンボリック実行の設定に関わる処理を行う
例: S2SYM: シンボルデータを作成する
S2OUT: デバッグ情報を出力する
S2DIS: マルチパス実行をOFFにする
Cのプログラムに埋め込まれたS2Eのカスタム命令(S2SYM)
20
シンボリック実行の方法[方法1]
使用方法
ソースコード中に、何のデータをシンボルとして利用したいのかを記述する
利用例
自分自身が書いたプログラムを検査したい時
PINを利用する例
System TAPを利用する例
21
シンボリック実行の方法[方法1]
自分自身が書いたプログラムをシンボリック実行したい時
#include “s2e.h”
int main(void){
char str[3];
s2e_enable_forking();
s2e_make_symbolic(str, 2, "str");
if(str[0] == '¥n' || str[1] == '¥n') {
printf("Not enough characters¥n");
} else {
if(str[0] >= 'a' && str[0] <= 'z')
printf("First char is lowercase¥n");
else
printf("First char is not lowercase¥n");
if(str[0] >= '0' && str[0] <= '9')
printf("First char is a digit¥n");
else
printf("First char is not a digit¥n");
if(str[0] == str[1])
printf("First and second chars are the same¥n");
else
printf("First and second chars are not the same¥n");
}
s2e_disable_forking();
s2e_get_example(str, 2);
printf("'%c%c' %02x %02x¥n", str[0], str[1],
(unsigned char) str[0], (unsigned char) str[1]);
return 0;
}
int main(void){
char str[3];
printf("Enter two characters: ");
if(!fgets(str, sizeof(str), stdin))
return 1;
if(str[0] == '¥n' || str[1] == '¥n') {
printf("Not enough characters¥n");
} else {
if(str[0] >= 'a' && str[0] <= 'z')
printf("First char is lowercase¥n");
else
printf("First char is not lowercase¥n");
if(str[0] >= '0' && str[0] <= '9')
printf("First char is a digit¥n");
else
printf("First char is not a digit¥n");
if(str[0] == str[1])
printf("First and second chars are the same¥n");
else
printf("First and second chars are not the
same¥n");
}
return 0;
}
シンボル化
処理
22
シンボリック実行の方法[方法1]
SystemTAPを利用した方法
SystemTAPのprobeを利用して、パケットにシンボルデータを挿入する方法
23
シンボリック実行の方法[方法2]
init_env.soを利用する方法
LD_PRELOAD=/home/s2e/guest/init_env/init_env.so
/bin/echo --select-process-userspace --sym-args 0 2 4
方法[例]
Echo の引数に0-2個の4バイトのシンボル化したデータを渡す。
その際に、シンボリック実行する領域としては、実行プロセスの
ユーザースペースのコード領域内のみ、に限定する
24
シンボリック実行の方法[方法3]
Annotationを利用する方法
configファイルを利用(LuaScript)
function annotation_example(state, plg)
-- Write custom Lua code here (e.g., to inject symbolic values)
end
pluginsConfig.Annotation =
{
init1 = {
active=true,
module="pcntpci5_sys_1",
address=0x169c9,
instructionAnnotation="annotation_example"
}
}
Windowsのドライバpcntpci5.sys中で、0x169c9のアドレスが呼ばれたら、
annotation_example関数を実行する
25
パフォーマンスについて
実行速度
通常のQEMUの3倍オーバーヘッドがかかる
通常のQEMUの78倍オーバーヘッドがかかる
コンコリック実行時
シンボリック実行時
主にx86→LLVM bitcodeの変換に負荷がかかっている
S2Eを利用した研究
26
脆弱性関連
Automatic Exploit Generation関連
Dowsing for overflows: A guided fuzzer to find buffer boundary violations. Istvan Haller,
Asia Slowinska, Matthias Neugschwandtner, Herbert Bos, USENIX Security’13,
Washington, DC, August 2013
SymDrive: Testing Drivers without Devices. OSDI'12 Proceedings of the 10th
USENIX conference on Operating Systems Design and Implementation
CRAX: Software Crash Analysis for Automatic Exploit Generation by Modeling Attacks as
Symbolic Continuations. . Shih-Kun Huang,Min-Hsiang Huang,Po-Yen Huang,Chung-Wei
Lai,Han-Lin Lu,Wai-Meng Leong. Information Technology Service Center,Department of
Computer Science National Chiao Tung University Hsinchu, Taiwan, 2012 IEEE Sixth
International Conference on Software Security and Reliability
参考文献
27
•S2E: A Platform for In Vivo Multi-Path Analysis of Software Systems. Vitaly
Chipounov, Volodymyr Kuznetsov, George Candea. 16th Intl. Conference on
Architectural Support for Programming Languages and Operating Systems
(ASPLOS), Newport Beach, CA, March 2011.
•Testing Closed-Source Binary Device Drivers with DDT. Volodymyr Kuznetsov,
Vitaly Chipounov, George Candea. USENIX Annual Technical Conference
(USENIX), Boston, MA, June 2010.
•Reverse Engineering of Binary Device Drivers with RevNIC. Vitaly Chipounov
and George Candea. 5th ACM SIGOPS/EuroSys European Conference on
Computer Systems (EuroSys), Paris, France, April 2010.
•Selective Symbolic Execution. Vitaly Chipounov, Vlad Georgescu, Cristian Zamfir,
George Candea. Proc. 5th Workshop on Hot Topics in System Dependability,
Lisbon, Portugal, June 2009

技術紹介: S2E: Selective Symbolic Execution Engine