Help us understand the problem. What is going on with this article?

angr+bingraphvisで実行パス差分ビューワを作ってみる

More than 1 year has passed since last update.

そういえばAdvent Calendarの時期だったので昨日書いたスクリプトを供養してみる。
この記事はセキュリティツール系 Advent Calendar 2018 13日目の記事です。

実行パス差分ビューワーというのは同じプログラムに対して2つの入力を与えた時の実行パスの差分を可視化するツール。(名前は今適当に考えた)
例えば以下のような"AB"という文字を受理するプログラムがあるとして、

test.c
#include <stdio.h>
#include <stdlib.h>

void one_match() {
        puts("One match");
}

void all_match() {
        puts("Accepted!");
}

int main(int argc, char *argv[]) {
        FILE *fp;
        char buf[32] = {0};
        if (argc < 2) { 
                fprintf(stderr, "usage: ./test <input>\n");
                exit(0);
        }
        fp = fopen(argv[1], "r");
        fread(buf, sizeof(char), 31, fp);
        if (buf[0] == 'A') {
                if (buf[1] == 'B') {
                        all_match();
                        return 0;
                } else {
                        one_match();
                }
        }
        puts("Not good");
        return 0;        
}

"AX"という文字列を与えるとone_match()の後"Not good"、
"AB"という文字列を与えるとall_match()、
とそれぞれ異なる実行パスを通るがこれを良い感じに可視化したい。

$ cat test1.in test2.in
AX
AB
$ ./test test1.in 
One match
Not good
$ ./test test2.in 
Accepted!

angr+Bingraphvis

今回やりたい事は主に2つ。
- 2つの入力それぞれの実行トレースを記録
- 得られたトレースの差分をCFG上に何らかの形で表示

今回はangrとBingraphvisという物を使った。
Bingraphvisというのはangrの生成したCFGを可視化するためのangr-utilsを支えているコアライブラリ。CFGのノード操作や変形、プロットをやってくれる。
これとangrのQEMURunner(トレーサー)を使って、
1. QEMURunnerで2つの入力に対してトレースを記録
2. CFGEmulatedでmain関数以降のCFGを生成
3. Bingraphvizでトレースの差分に当たるCFGノードを色付け
4. CFGをpngとして保存

というのをやった。
ラッパーのangr-utilsを使わなかった理由は、独自のトレース差分を用いたCFG変形を定義して使いたかったため。
先程例に上げたプログラムに対して実行すると下の用な画像を吐いてくれる。

$ python3 input-tracer.py -b ./test -i test1.in,test2.in -v
[+] Opening binary ./test
[+] CFG Cache found 
CFG size = 46
[+] Tracing .... test1.in
Size: 46079
[+] Tracing .... test2.in
Size: 46033
[+] CFG processing ....
Graph len= 30
[+] Complete! Saved to outd/input_trace_test_entire.png

input_trace_test_entire.png

赤がtest1.inで青がtest2.inを与えた時のパス。共通は黒。

CFGFastを使って関数ごとにプロット

UNIXユーティリティのようなプログラムに対して上記を行うと、とてつもなく巨大な(ノード数5000〜)CFGをプロットしてしまい数万ピクセルの画像が生成されてしまう。当然ビューワーも表示できずに落ちるので可視化の意味を損なう。
CFG全体でなく差分のあるノードのみ表示する事もできるが(上のコマンドから-vを抜く)、差分のみでも非常に大きい場合がある。
そこで、プログラムの関数ごとに画像を分けてCFGをプロットする機能も付けた。

  1. QEMURunnerで2つの入力に対してトレースを記録
  2. angrのCFGFastでバイナリ内で定義されている関数一覧取得。
  3. 各関数ごとに上記と同じ処理を実行

-fオプションを付けると有効化。

$ python3 ./input-tracer.py -b mp3_player -i invalid.mp3,1.mp3 -f                              
[+] Opening binary mp3_player                                 
[+] Searching for all the functions (using CFGFast)                             
100% |#####################################| Elapsed Time: 0:00:02 Time: 0:00:02
   ==> 106 functions to process.                                                
[+] Tracing .... invalid.mp3                                                    
Size: 1305732                                                                   
[+] Tracing .... 1.mp3                                                          
Size: 6084333                                                                   
[+] CFG processing ....                                                         
[+] (0/106) Computing Accurate CFG for function _init (0x8049cd8)               
[+] CFG Cache found                                                             
Graph len= 0                                                                    
[+] Complete! Saved to outd/input_trace_mpg321-0.3.0__init.png                  
[+] (1/106) Computing Accurate CFG for function sub_8049d0c (0x8049d0c)         
[+] CFG Cache found  

例えば"ABCD"のような明らかにinvalidなmp3データとvalidなmp3データでプレイヤーに与えてみる。
outdに各関数ごとのCFG差分がプロットされる。
input-tracer.png

calc_lengthというmp3プレイヤー内の関数の差分を見てみると以下のようになっている。

input_trace_mpg321-0.3.0_calc_length.png

ソースコード

コードは以下にある
https://gist.github.com/RKX1209/3cb60b0fa0ba92da6575716680f32aa0

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away