使えれば良いやradare2(静的解析編)
バイナリ関連の機能を一通り提供するフレームワークradare2
,通称r2
(d2
はない模様)による静的解析をざっくりと紹介する.CLIベースの使い方はいろんなサイトが詳しくやっているから,Visual Modeの使い方を中心に解説する.
radare2について
radare2
について軽く説明する.
radare2
は64ビットオフセット対応の16進バイナリエディタとして,2006年から開発が始まった.途中でportable reversing frameworkになり,更に,いつの間にかradare
からradare2
へとバージョンアップしている.経緯は知らない.バイナリエディタとして使われているところを見たこともやったこともない・・・.
x86
からxtensa
などのマニアックなアーキテクチャまで対応し,基数変換ツール(rax2
)やアセンブラ(rasm2
),バイナリ比較プログラム(radiff2
)など細かい所まで提供してくれる,とても素晴らしいプラットフォーム!
といえば聞こえは良いが,現実には挙動にビックリな地雷を抱えているところがあり,全面的に信用して使うと痛い目にあうというのが正直なところ(個人的な感想).
今までに出会った例としては,デバッグ中のプログラムがセグフォを起こすと,出力が無限ループ起こした.他には,巨大なプログラムを解析しようとすると,関数フラグなどの収集が終わらない.この状態だとCtrl+c
しても終了できない.Ctrl+z
で停止させて,改めてkill
する必要があった.まだ他にもある.
インストール
radare2
をインストールしていない場合は,ubuntuならapt/apt-get install radare2
,arch linuxならpacman -S radare2
で簡単に見つかるはず.ただし,ubuntuのパッケージはバージョンが古いことがあり,機能の一部が実装されていない可能性もある.不安な人は自前ビルドするとよい.自前ビルドは
$ git clone https://github.com/radare/radare2 $ cd radare2 && sys/install.sh $ sys/install.sh rootでインストールしたくない人はホームディレクトリにインストールする方法もある. $ sys/user.sh
で行う.
環境
$ uname -a Linux poppycompass 4.7.6-1-ARCH #1 SMP PREEMPT Fri Sep 30 19:28:42 CEST 2016 x86_64 GNU/Linux $ r2 -v radare2 0.10.2-git 10613 @ linux-little-x86-64 git.0.10.1-156-gcb11996 commit: cb119968dd590fbb0719243eadd7344c7293b996 build: 2016-03-16
現行のバージョンは0.10.6(2016/10/26現在)だから,少し古いバージョンでの解説となる.
カーネルバージョンから,先日発表されたDirty COW
(CVE-2016-5195)の餌食になりそうな雰囲気.この後無茶苦茶更新した.
解析対象
解析対象はカラフルな出力を行うプログラム.
/* color.c */ #include <stdio.h> void red(void) { printf("\x1b[31m"); puts("red"); } void blue(void) { printf("\x1b[34m"); puts("blue"); } void green(void) { printf("\x1b[32m"); puts("green"); } int main(void) { int i=1; if (i) { red(); blue(); green(); } else { return 1; } return 0; } /* E.O.F. */
変なif
文が入っているのは,コードに分岐を作りたかったから.
コンパイルは,
$ gcc -o color color.c -Wall
解析
いよいよr2
を起動する.r2
の操作性を一言で表現するなら,vim + gdb
.この辺りは素晴らしい.コマンド体系は独自すぎて少しわかりにくい.
$ r2 ./color [0x00400450]>
といった感じのシェルが起動する.?
でヘルプが見られる.
checksec
のような情報が欲しいときは,
[0x00400450]> iI pic false canary false nx true crypto false va true intrp /lib64/ld-linux-x86-64.so.2 bintype elf class ELF64 lang c arch x86 bits 64 machine AMD x86-64 architecture os linux minopsz 1 maxopsz 16 pcalign 0 subsys linux endian little stripped false static false linenum true lsyms true relocs true rpath NONE binsz 6605
今回はa(nalyze)コマンドで関数部のフラグを特定し,Visual Mode上で解析していく.最低限の解析のみならaa
,プログラム中の文字列などを扱いたいなら,aaa
コマンドを使う.ただし,stripされているプログラムだとaaa
では非常に時間がかかる.適宜使い分けるとよい.
[0x00400450]> aaa [x] Analyze all flags starting with sym. and entry0 (aa) [x] Analyze len bytes of instructions for references (aar) [x] Analyze function calls (aac) [*] Use -AA or aaaa to perform additional experimental analysis. [x] Construct a function name for all fcn.* (.afna @@ fcn.*) fcns: 16 xref: 39 sect: 514 code: 590 covr: 114 % [0x00400450]> afl # 解析した関数一覧を表示 0x00400000 60 2 sym.imp.__libc_start_main 0x00400400 23 3 sym._init 0x00400430 16 2 sym.imp.puts 0x00400440 16 2 sym.imp.printf 0x00400450 43 1 entry0 0x00400480 50 4 sym.deregister_tm_clones 0x004004c0 58 4 sym.register_tm_clones 0x00400500 28 3 sym.__do_global_dtors_aux 0x00400520 38 4 sym.frame_dummy 0x00400546 32 1 sym.red 0x00400566 32 1 sym.blue 0x00400586 32 1 sym.green 0x004005a6 50 4 sym.main 0x004005e0 101 4 sym.__libc_csu_init 0x00400650 2 1 sym.__libc_csu_fini 0x00400654 9 1 sym._fini
main関数から解析していく.
[0x00400450]> s sym.main # アドレス移動 [0x004005a6]> VV # Visual Mode起動 [0x004005a6]> VV @ sym.main (nodes 4 edges 4 zoom 100%) BB-NORM mouse:canvas-y movements-speed:5 =-----------------------------------= | [0x4005a6] | | ;-- main: | | (fcn) sym.main 50 | | ; var int local_0h @ rbp-0x0 | | ; var int local_4h @ rbp-0x4 | | push rbp | | mov rbp, rsp | | sub rsp, 0x10 | | mov dword [rbp - local_4h], 1 | | cmp dword [rbp - local_4h], 0 | | je 0x4005d1 ;[a] | =-----------------------------------= t f .---' '-------------------. | | | | =----------------= =----------------------= | 0x4005d1 | | 0x4005bb | | mov eax, 1 | | call sym.red ;[b] | =----------------= | call sym.blue ;[c] | v | call sym.green ;[d] | | | mov eax, 0 | | | jmp 0x4005d6 ;[e] | '------------. =----------------------= | v .----------' | | =----------------= | 0x4005d6 | | leave | | ret | =----------------=
上記のような表示になったと思う.分岐を起点としたブロックに分割されて,表示される.実際にはt(true),f(false)の線は色がついていて,非常に有り難い.vimと同様hjkl
で移動する.スペースキーを押すと,16進ダンプに跳ぶ.もう一回スペースキーを押すと戻る.
:
を押すことでr2
のコマンドを実行できる.sym.red
関数をテキストとしてディスアセンブルする.
Press <enter> to return to Visual mode. :> pdf@sym.main # pdf: 関数のディスアセンブル,'@'以降は引数に関数名やアドレスを与える / (fcn) sym.red 32 | ; CALL XREF from 0x004005bb (sym.red) | 0x00400546 55 push rbp | 0x00400547 4889e5 mov rbp, rsp | 0x0040054a bf64064000 mov edi, str._e_31m ; str._e_31m | 0x0040054f b800000000 mov eax, 0 | 0x00400554 e8e7feffff call sym.imp.printf | 0x00400559 bf6a064000 mov edi, 0x40066a | 0x0040055e e8cdfeffff call sym.imp.puts | 0x00400563 90 nop | 0x00400564 5d pop rbp \ 0x00400565 c3 ret
Visual Modeのままsym.red
に移動したいときは
Press <enter> to return to Visual mode. :> s sym.red<Enter><Enter> [0x004005a6]> VV @ sym.red (nodes 1 edges 0 zoom 100%) BB-NORM mouse:canvas-y movements-speed:5 =---------------------------= | [0x400546] | | (fcn) sym.red 32 | | push rbp | | mov rbp, rsp | | mov edi, str._e_31m | | mov eax, 0 | | call sym.imp.printf ;[a] | | mov edi, 0x40066a | | call sym.imp.puts ;[b] | | nop | | pop rbp | | ret | =---------------------------=
u
でmain関数に戻る.
終了
q
を2回押して,元のプロンプトに戻り,Ctrl+d
かexit
で終了.
最後に
radare2
のVisual Modeでの解析を中心とした使い方をざっくり説明した.機能としてはもっと膨大であるが,そのへんの解説はbookやヘルプに譲りたい.objdump
よりも直感的なコードを提供してくれるため,静的解析には非常に心強い.
今年の9月に世界初のradare2カンファレンスr2con-2016
が開催されたらしい.来年は是非行って,radare2
は「ラダレツゥー」と読んでいいのか確かめたい.しかし,金と言語の壁が厚い.
参考
radare2レポジトリ: GitHub - radare/radare2: unix-like reverse engineering framework and commandline tools
端末出力の色変更方法: C言語でターミナルで表示される文字をカラー表示させる : Serendip - Webデザイン・プログラミング
radare2 book: http://www.radare.org/get/radare.pdf
Dirty COW: Dirty COW (CVE-2016-5195)