/var/log/Sawada.log

SAINO中毒患者の備忘録。

radare2 覚書

最近何かとCTFでお世話になっているradare2だが,どうもコマンドの物忘れがひどいので自分用の覚書としてここに残しておく.随時更新する.

redare2って何

OSSとして開発が進んでいるReverse Engineering Framework.時々動作に難はあるものの,対応しているアーキテクチャやファイルフォーマットの多さから重宝している*1.元々はフォレンジックツールとして開発が始まったそうだが,今ではバイナリ解析用に逆アセンブルデバッグ機能も追加され,有用な機能を持ったツール群として radare2 に統合された.操作性はvim,gdbに近く馴染みやすい.素晴らしいね!CTFで利用する人も増えてきており,最近は標的型Malwareの解析BlackHatの成果発表でも見かけるなど実用性も上がってきている模様.詳細は以下.

github.com

やりたいこと

基本的には図のように表層解析や静的解析で使えれば嬉しい.

f:id:takuzoo3868:20181105230522p:plain
マルウェア解析の概略

具体的には,

  • 表層解析

    • ファイルサイズやファイルタイプの確認
    • プログラムの保護機能の有無を確認(RELRO/SSP/Nxbit/ASLR/PIE)
    • string情報の表示
  • 静的解析

    • 特定命令からの逆アセンブル
    • メモリアドレスに格納されている値の確認やデータの参照表示
    • ブレークポイントの設置とステップ実行によるデバッグ
    • IDAのようなグラフ機能で制御文などの確認

起動と初期動作

引数に解析したいプログラムのファイル名を指定して,radare2を起動する.

$ r2 <target_file>
$ r2 -d <target_file>   # デバッグ時にはオプションにdをつける

解析を終了する場合はqコマンドでradare2を終了できる.例に使ったのはksnctfの村人A. デバッグ時のradare shell起動はこんな感じ.尚,MacOSの場合はデバッグを有効化するためにコード署名が必要

f:id:takuzoo3868:20181109085616p:plain
ほのぼのとしたデバッグモードの起動画面

表層解析

対象プログラムの基本的な情報を表示

i: Information command

checksecのような情報や,import,export,string情報はi: Information command*2を使う.radare2ではメインとなるコマンドに続いて,「何がしたいのか」をサブコマンド・オプションで指定することで1つの実行としている.例えば,バイナリの情報を調べたい場合はiIコマンド(Binary info)で表示できる.

[0x08048500]> iI
arch     x86
baddr    0x8048000
binsz    5857
bintype  elf
bits     32
canary   false
sanitiz  false
class    ELF32
crypto   false
endian   little
- 省略 -

radare2は1文字 <-> 1命令の一対一対応で,各々の文字に(基本的には)意味がある. また,iコマンドに限らず,各コマンドの末尾に?を付けることでコマンドのヘルプを参照できる. 先程述べた,import情報はii,export情報はiEなど,string情報はizなどで確認できる.

[0x08048500]> ii
[Imports]
Num  Vaddr       Bind      Type Name
   1 0x08048464    WEAK  NOTYPE __gmon_start__
   2 0x00000000    WEAK  NOTYPE _Jv_RegisterClasses
   3 0x08048474  GLOBAL    FUNC putchar
   4 0x08048484  GLOBAL    FUNC fgets
   5 0x08048494  GLOBAL    FUNC __libc_start_main
   6 0x080484a4  GLOBAL    FUNC fopen
   7 0x080484b4  GLOBAL    FUNC printf
   8 0x080484c4  GLOBAL    FUNC puts
   9 0x080484e4  GLOBAL    FUNC strcmp
  12 0x080484d4  GLOBAL    FUNC __gxx_personality_v0
   2 0x00000000    WEAK  NOTYPE _Jv_RegisterClasses
[0x08048500]> iE
[Exports]
Num Paddr      Vaddr      Bind     Type Size Name
046 0x000006e0 0x080486e0 GLOBAL   FUNC    5 __libc_csu_fini
047 0x00000500 0x08048500 GLOBAL   FUNC    0 _start
050 0x00000798 0x08048798 GLOBAL    OBJ    4 _fp_hw
051 0x0000077c 0x0804877c GLOBAL   FUNC    0 _fini
055 0x0000079c 0x0804879c GLOBAL    OBJ    4 _IO_stdin_used
056 0x00000a00 0x08049a00 GLOBAL NOTYPE    0 __data_start
058 0x000007a0 0x080487a0 GLOBAL    OBJ    0 __dso_handle
059 0x000008e4 0x080498e4 GLOBAL    OBJ    0 __DTOR_END__
060 0x000006f0 0x080486f0 GLOBAL   FUNC   90 __libc_csu_init
062 ---------- 0x08049a04 GLOBAL NOTYPE    0 __bss_start
063 ---------- 0x08049a04 GLOBAL    OBJ    4 stdin@@GLIBC_2.0
064 ---------- 0x08049a10 GLOBAL NOTYPE    0 _end
066 ---------- 0x08049a04 GLOBAL NOTYPE    0 _edata
069 0x0000074a 0x0804874a GLOBAL   FUNC    0 __i686.get_pc_thunk.bx
070 0x000005b4 0x080485b4 GLOBAL   FUNC  298 main
071 0x00000424 0x08048424 GLOBAL   FUNC    0 _init
[0x08048500]> iz
[Strings]
Num Paddr      Vaddr      Len Size Section  Type  String
000 0x000007a4 0x080487a4  17  18 (.rodata) ascii What's your name?
001 0x000007b6 0x080487b6   4   5 (.rodata) ascii Hi, 
002 0x000007bb 0x080487bb  21  22 (.rodata) ascii Do you want the flag?
003 0x000007d5 0x080487d5  16  17 (.rodata) ascii I see. Good bye.
004 0x000007e8 0x080487e8   8   9 (.rodata) ascii flag.txt

静的解析

コード解析のための初歩

a: Analyze command

radare2ではIDAと違い,関数解析や相互参照など高度な解析を自動で行ってくれないで,a: Analyze commandを実行する必要がある. 少しづつ改善されているが,難読化されたプログラムなどに対して高度な解析を自動化してしまうと,処理に相当な時間がかかるためこのような仕様になっている(?). どうしても自動解析したい場合はradare2起動時に引数として-Aあるいは-AAを追加すればよい.

[0x08048500]> aaaa
[x] Analyze all flags starting with sym. and entry0 (aa)
[x] Analyze function calls (aac)
[x] Analyze len bytes of instructions for references (aar)
[x] Constructing a function name for fcn.* and sym.func.* functions (aan)
[x] Type matching analysis for all functions (afta)
[x] Emulate code to find computed references (aae)
[x] Analyze consecutive function (aat)
[0x08048500]> aaaaaaa
An r2 developer is coming to your place to manually analyze this program. Please wait for it

--press any key--

解析の程度はa,aa(analyze all),aaa,aaaaとオプションを増やすことで対象を広げている.しかし,iIコマンドの結果にstripped trueなどがある場合は,時間がかかるため最低限のaaコマンドが良い.この辺は表層解析の結果をみて臨機応変に使い分けすればOK.上の例ではaa,aac,aar,aan,afta,aae,aatまで実行している.それぞれの内容はヘルプを参照しておくれ.ちなみにaaaaaaa以上はジョークコマンドである.

この他にradare shell上でよく使うaコマンドには以下の通り.

コマンド 具体例 具体例の機能
ax: analyze ref/Xref axt コードやデータの参照先を表示
af: analyze Functions afl 自動解析(af,aa,aaaなど)で取得した関数のリストを表示

カレントアドレスの移動と逆アセンブル

s: Seek command

自動解析で得られた関数や,特定のアドレスへカレントアドレスを移動する場合にはs: Seek commandを使う.カレントアドレスはradare shellのプロンプトに表示されている.カレントアドレスを移動せずに特定のコマンドを実行したい場合は<cmd> @ <address>とすれば良い.

[0x08048500]> afl
0x08048424    3 48           sym._init
0x08048464    1 6            loc.imp.__gmon_start
0x08048474    1 6            sym.imp.putchar
0x08048484    1 6            sym.imp.fgets
0x08048494    1 6            sym.imp.__libc_start_main
0x080484a4    1 6            sym.imp.fopen
0x080484b4    1 6            sym.imp.printf
0x080484c4    1 6            sym.imp.puts
0x080484d4    1 6            sym.imp.__gxx_personality_v0
0x080484e4    1 6            sym.imp.strcmp
0x08048500    1 33           entry0
0x08048530    6 86           sym.__do_global_dtors_aux
0x08048590    4 36           sym.frame_dummy
0x080485b4    8 298          sym.main
0x080486e0    1 5            sym.__libc_csu_fini
0x080486f0    4 90           sym.__libc_csu_init
0x0804874a    1 4            sym.__i686.get_pc_thunk.bx
0x08048750    4 43           sym.__do_global_ctors_aux
0x0804877c    1 28           sym._fini
[0x08048500]> s sym.main
[0x080485b4]> 

上に例は,自動解析でわかったmain関数(0x080485b4 8 298 sym.main)へカレントアドレス([0x08048500]>)の移動(s sym.main)を行っている([0x080485b4]>).

pd: print disassemble command

アセンブルについてはpdコマンドを用いる.デフォルトは数十命令ぶんを逆アセンブルしてくれる.引数で命令数の指定もできる.pdfコマンドは関数全体を逆アセンブルしてshellに表示してくれる.先程main関数へ移動したので実行してみるとこんな感じ*3.一部のスクショ.

f:id:takuzoo3868:20181109205109p:plain
main関数を逆アセンブルした画面

f:id:takuzoo3868:20181109205122p:plain
左側でgotoの宛先が可視化されていたり,コメント内容も色々変更できるらしい

また,disassembleより高級なdecompileを使用したい場合は,radare2のパッケージマネージャであるr2pmを使ってr2decをインストールできる.このデコンパイラは多数のアーキテクチャに対応しており,IDA買えず人権低めの自分は重宝している*4.標準でもpdcコマンドでclangっぽくデコンパイル可能だが,このプラグインを導入したほうが可読性も高めゆえおすすめ.自分はradare2rcにe cmd.pdc = pdd存在を無かったことにしている.r2decを導入するとpddコマンドでデコンパイル結果がshell上に表示される.

f:id:takuzoo3868:20181109230626p:plain
pdcコマンドによる何かそれっぽいデコンパイル
f:id:takuzoo3868:20181109230641p:plain
r2decによる見やすいデコンパイル

グラフ機能などを備えたヴィジュアルモード

V: Visual mode command

IDAのようなグラフで見たい場合やTUIとして扱いたい場合はV: Visual mode commandを使う.操作の雰囲気はvimに近く,hjklで画面を移動したり,qキーでradare shellに戻ったり,:キーで一時的にradare shellが使えるなどなど.

  • Vコマンド
    この表示方法で起動すると,Hexdump, disassemble, debugger, word-hexidecimal, etc...と様々な表示ができる.それぞれコマンドにより描画できる表示だがヴィジュアルモードを使うと切替が便利.pまたはPキーで表示切替,数字キーで対応するcall/jumpへ移動,oで指定のオフセットへ移動,xキーでaxtコマンドのようにxref表示,vキーで関数/変数の解析用UI表示,uキーで操作した数字またはoキーからUndoする.

    f:id:takuzoo3868:20181110001308p:plain
    Visual modeでHexdumpの表示
    f:id:takuzoo3868:20181110001738p:plain
    Visual modeでDubuggerの表示
    f:id:takuzoo3868:20181110002825p:plain
    Visual modeで関数/変数の解析用UI表示

  • VVコマンド
    こちらはIDAのようなグラフビュー関連の表示ができる.またVコマンドからはSpaceキーによってこちらへ切替も可能.制御文による遷移の確認に役立つ.基本的な操作は上のモードと同じ.shift+dキーでアセンブリも同時に表示が可能.

    f:id:takuzoo3868:20181110013056p:plain
    Visual modeでグラフの表示
    f:id:takuzoo3868:20181110013104p:plain
    Visual modeでミニグラフの表示

  • V!コマンド
    radareでTUIのような操作ができる.それぞれのパネルへの移動はtabキーやw-->hjkl,メニューの利用はmキーを使う.パネルの分割やその他の操作方法は同様に?で確認できる.

    f:id:takuzoo3868:20181110020600p:plain
    Visual modeでTUIの表示

デバッグ

d: debug command

デバッグモードで起動した際には,デバッグが可能となる(それはそう).ブレークポイント置いて,continueして,ステップ実行...とかプログラムの挙動調査で使うやつ.その際はd: debug commandを使う.また具体例として,プログラムがパッキングされている場合*5などは,OEP(Original Entry Point)を探し出しメモリ上に展開されたソースを解析したりすることになる*6*7.そんなときにデバッグは有効.使えそうなコマンドを表にまとめておく.

  • 実行フロー関連
コマンド 機能
dc Breakpointの設置箇所までプログラムの実行(gdbのcontinue)
dcu <address> 指定したアドレスまで実行.e.g. dcu sym.main
ds ステップ実行(gdbのsi)
dcr 関数がstack frame returnになる,つまり抜けるまで実行
dr <register> レジストリ内部の格納情報を表示
  • Breakpoint関連
コマンド 機能
db <address> 指定したアドレスにBreakpointを設置
dbc <address> <r2_cmd> BP設置かつ実行されたときに使うr2コマンドの登録
drx <num> <addr> <len> <rwx> 読み/書き/実行で指定アドレス範囲にアクセスしたときHBP*8設置
db- <address> BPの削除
drx- <address> HBPの削除
  • メモリマップ関連
コマンド 機能
dm プロセスのメモリマップを表示(gdbのvmmap)
dmi <address | libname>
読み込みのあったDLL symbolのリストを表示
  • メモリダンプ関連
コマンド 機能
wtf <filename> <size> @<starting_address>
指定アドレスから指定サイズ分の情報をダンプ
dmd <filename> @<address>
メモリマップの情報をダンプ

そんなunpackingとかしない場合は,VppコマンドでVisual debugger modeを使ったほうがサッとできる. F2でtoggle breakpoint,F4でrun to cursor,F7でsingle step,F8でstep over,F9でcontinueが使える.大変便利.

おわりに

とりあえず自分がよく使うコマンドを中心にまとめた.記事を書く過程で知らなかった機能や使い方の勉強にもなった.CTFやcrackme,降ってきた検体で精進する. radare2は自前のカンファレンスも開催しており各年のリポジトリに豊富な資料が残っている.radare2 bookの冊子体やswagを配布しているそうなので一度は行ってみたい...

github.com

github.com

*1:x86にも対応しており無料で使えるので有り難い

*2:rabin2でも同様の機能.

*3:radare2は265のカラーテーマが使える.自分は机に植物がないのでlimaを使っている.ecoコマンドで色々と変更できる.

*4:この他に自分がよく使うデコンパイラはavast社のretdec

*5:https://www.packerinspector.com/oakland-2015-dpi.pdf

*6:radare2に自動のunpackerパッケージがあるのかはわからない.あればとても便利だね.

*7:radare2でのunpack関連はここが大変よくまとまってる.

*8:Hardware Break Point