自動でバグを見つける!プログラム解析と動的バイナリ計装

192 Views

May 20, 20

スライド概要

DBI (Dynamic Binary Instrumentation) の技術を活用してバッファーオーバーフローを検知する例を紹介します。

profile-image

サイボウズ・ラボ株式会社で教育向けのOSやCPU、コンパイラなどの研究開発をしています。

シェア

またはPlayer版

埋め込む »CMSなどでJSが使えない場合

関連スライド

各ページのテキスト
1.

自動でバグを見つける! プログラム解析と動的バイナリ計装 カジュアルTechスシ 2020年5月28日 サイボウズ・ラボ株式会社 内田公太 1

2.

自己紹介 • 研究員 at サイボウズ・ラボ • サイボウズ本社に2014年新卒入社 • Hazama→SRE • 2020年1月にラボへ転籍 • カフェ部(酒)担当 • 紅茶も好きです 2 /13

3.

研究分野 • 計算機科学の教育 • 「OSを作る」ことを通してCS教育 • 教育用OS「MikanOS」の作成 • プログラム解析 • プログラムの動作を調べる • バグを見つける • 今日の主題 3 /13

4.
[beta]
バッファーオーバーフロー
• バッファーオーバーランとも
• 問題:次のプログラムに潜むバグを指摘せよ
(制限時間30秒)

int main() {
char* p = malloc(10);
for (int i = 0; i < 10; ++i) {
p[i] = '0' + i;
}
p[10] = '\0';
printf("p = %s\n", p);
}
4

/13

5.
[beta]
静的解析
• プログラムを動かさずに解析
• 代表的なツール:Lint

int main() {
char* p = malloc(10);
for (int i = 0; i < 10; ++i) {
p[i] = '0' + i;
}
p[10] = '\0';
printf("p = %s\n", p);
}

• pのヌルチェックをしていない
• pの末尾を超えて書き込んでいる
• pをfreeしていない
バッファーオーバーフロー

5

/13

6.

バッファーオーバーフロー malloc()の戻り値 '0' '1' '2' '3' '4' '5' '6' '7' '8' '9' NUL 10バイト 6 /13

7.

動的解析 • プログラムを動かして解析 • 代表的なツール:GDB • 実際の値で正確な検査ができる • バイナリさえあれば動かせる • マルウェアの解析 • ソースコードの情報は使えない • この条件付きjmpはifかwhileか? 00000000004004a0 <main>: 4004a0: sub rsp,0x8 4004a4: mov edi,0xa 4004a9: call 400470 <malloc@plt> 4004ae: mov esi,0x400684 4004b3: mov BYTE PTR [rax],0x30 4004b6: mov BYTE PTR [rax+0x1],0x31 4004ba: mov BYTE PTR [rax+0x2],0x32 4004be: mov BYTE PTR [rax+0x3],0x33 … 7 /13

8.

バイナリ計装(今日の主題) • Binary Instrumentation • 実行ファイルに検査コードを埋め込む • 代表的なツール:Intel Pin • 一般に,実行ファイルに機械語を埋め 込むとアドレスがずれる • →再アセンブルが必要 • Intel Pinはそれをやってくれる 00000000004004a0 <main>: 4004a0: sub rsp,0x8 4004a4: mov edi,0xa 4004a9: call 400470 … 8 /13

9.
[beta]
DBIでバッファーオーバーフローを発見
• 動的バイナリ計装:実行時にバイナリ計装する
• 検出方針:
• mallocの引数と戻り値を記録しておき
• メモリアクセス時にアクセス先アドレスを検査
int main() {
char* p = malloc(10);
for (int i = 0; i < 10; ++i) {
p[i] = '0' + i;
}
p[10] = '\0';
printf("p = %s\n", p);
}

引数と戻り値を記録
メモリアクセスを検査

9

/13

10.

自作解析ツールの出力 $ ../../../pin -t obj-intel64/MyPinTool.so -- ./a.out =============================================== This application is instrumented by MyPinTool =============================================== Found out-of-bounds memory write at f2f01a (IP=4004e2) p = 0123456789 =============================================== MyPinTool analysis results: Heap Objects: f2f010: size=0xa f2f030: size=0x400 =============================================== 10 /13

11.

自作解析ツールの出力 $ ../../../pin -t obj-intel64/MyPinTool.so -- ./a.out =============================================== This application is instrumented by MyPinTool =============================================== Found out-of-bounds memory write at f2f01a (IP=4004e2) p = 0123456789 解析対象アプリの出力 =============================================== MyPinTool analysis results: Heap Objects: f2f010: size=0xa f2f030: size=0x400 =============================================== 11 /13

12.

mallocを置き換える Intel Pinの機能で関数置換 RTN_ReplaceSignature() 0000000000400470 <malloc@plt>: 400470: jmp QWORD PTR [rip+0x200baa] 400476: push 0x1 40047b: jmp 400450 <_init+0x28> … もとのプログラム 検査用malloc malloc()をラップ サイズとアドレスを記録 heap_objs 12 /13

13.

メモリアクセスを検査 指定した命令のメモリ参照の個数 INS_MemoryOperandCount() 00000000004004a0 <main>: 4004a0: sub rsp,0x8 指定した命令の直前に関数呼び出しを挿入 4004a4: mov edi,0xa 4004a9: call 400470 <malloc@plt> INS_InsertCall() … 4004da: mov BYTE PTR [rax+0x8],0x38 CheckOverflow() 4004de: mov BYTE PTR [rax+0x9],0x39 4004e2: mov BYTE PTR [rax+0xa],0x0 4004e6: xor eax,eax メモリアドレスが 4004e8: call 400480 <__printf_chk@plt> 範囲内であることを検査 もとのプログラム heap_objs 13 /13