【文章作者】: condor
【作者邮箱】: cracker@vip.qq.com
【作者主页】: http://hi.baidu.com/linshifei
【作者声明】: 只是感兴趣,没有其他目的。失误之处敬请诸位大侠赐教!


  这次要介绍的是Google 出品的Bunny(下载地址http://hi.baidu.com/linshifei/blog/item/d1c68b19d29827b14bedbcad.html),结合编译器使用,在有代码情况下效果应该不错。以下是之前的学习笔记,很多翻译来自手册,水平有限。



Google  Bunny the Fuzzer 学习笔记

  Bunny 是针对C程序的,实时反馈,高性能的,通用协议盲注入fuzzer。
  通过编译器技术实现无缝注入准确可靠的指令hook到目标程序中去。
  这些hook使得fuzzer可以实时获取 函数调用,执行路径,以及各类输入的返回值。
  Bunny使在不带来明显性能开销情况下,实时监控内部运行流程成为可能。
  目前版本支持  Linux, FreeBSD, OpenBSD, and Cygwin on IA32 and IA64 

几大优点:
  1 ,使用简单,修改项目的配置文件中的gcc即可,如:CC=/path/to/bunny-gcc ./configure
  2,很小的性能消耗。
  3, 从zlib,libpng到openssh,各种模块支持。不需要修改测试程序
  4,支持灵活配置,支持9中fuzz类型。可以控制fuzz 深度等等。自动保存crash case。支持并行fuzz等。


基本算法:
  1 使用已知的输入文件,初始化一个fuzzing 队列
  2 尝试几个fuzzing 队列中确定的输入,记录执行路径
  3 如果 执行路径与之前不同,记录使用的测试用例,并把该用例压栈。
  4 任何函数调用参数或者返回值已知运行路径变化,则记录
  5 如果程序出错了。记录并保持测试用例
  6 测试所有用例,直到fuzzing 队列为空

bunny实行9类型的fuzzing 策略(执行的时候会一个一个测试)
Fully random fuzzing of known execution path effectors 
Deterministic, walking bit flip of variable length 
Deterministic, walking value set operation of variable length 
Walking random value set of variable length 
Deterministic, walking block deletion of variable length 
Deterministic, walking block overwrite of variable length 
Deterministic, walking block duplication of variable length 
Deterministic, walking block swap of variable length 
Random stacking of any of the above operation (last resort) 


初探一个程序:

main(void) {
  foo1(value);
  foo2(2);
  something(3,4);
  name13(5,6,7);
  usleep(100000);
  BunnySnoop 10;
}

用 bunny-trace可以看到函数调用过程和返回值,什么用途,怎么使用,我也没有搞懂
总之能对执行路径进行记录:)

root@condor:/usr/local/condor/bunny/bunny/tests# ../bunny-trace ./a.out 
NOTE: File descriptor #99 closed, defaulting to stderr instead.
bunny-trace 0.92-beta (Nov 11 2007 09:10:55) by <lcamtuf@google.com>
+++ Trace of './a.out' started at 2007/11/11 11:50:44 +++
[22174] 000 .- main()
Hello cruel world.
[22174] 001 | .- foo1(1)
How are you?
[22174] 001 | `- = 7
Goodbye.
[22174] 001 | .- foo2(2)
[22174] 001 | `- = 9
[22174] 001 | .- something(3, 4)
[22174] 001 | `- = 0
[22174] 001 | .- name13(5, 6, 7)
[22174] 001 | `- = 0
[22174] 001 +--- 10
[22174] 000 `- = 0
--- Process 22174 exited (code=0) ---
+++ Trace complete (0.104 secs) +++

来测试强大的bunnymain,写一个测试程序在特定输入情况下(\x00\x10\x20\x30),也就是某个程序执行路径会core:

testcase2.c:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>

char c[3];

void do_nothing(time_t t) { }


void dostuff3(int param) {
  char* x = (char*)0x5;
  if (param == 0x30) *x = 5;
}

void dostuff2(void) {
  if (c[2] == 0x20) dostuff3(c[3]);//当程序输入为0x30,时候core

}


void dostuff1(void) {
  if (c[1] == 0x10) dostuff2();
}


int main(int argc,char** argv) {

  do_nothing(time(0));

  read(0,c,4);

  printf("testout:%s\n",c);

  if (c[0] == 0x00) dostuff1();

}



用bunny-gcc编译

root@condor:/usr/local/condor/bunny/bunny/tests# ../bunny-gcc testcase2.c 
[bunny] bunny-gcc 0.92-beta (Nov 11 2007 09:10:55) by <lcamtuf@google.com>
[bunny] STAGE 1/3: Precompiling 'testcase2.c'...
[bunny] STAGE 2/3: Injected 24 hooks into 'testcase2.c' (14500 tokens).
[bunny] STAGE 3/3: Compiling and linking executable to default location...

创建测试用例
mkdir test
mkdir test/in_dir    
mkdir test/out_dir    
cd test/in_dir/
echo "aaaaaaaaaaaaaaaaaaaaaaaaa" >case2


开始fuzz,开始看到实时输出 ,已经使用9类型的fuzzing 策略情况
root@condor:/usr/local/condor/bunny/bunny# ./bunny-main  -i condortest/in_dir -o condortest/out_dir ./condortest/a.out 
Bunny the Fuzzer - a high-performance instrumented fuzzer by <lcamtuf@google.com>
---------------------------------------------------------------------------------

  Code version : 0.92-beta (Nov 11 2007 09:12:23)
    Start date : Sun Nov 11 12:47:17 2007
   Target exec : ./condortest/a.out
  Command line : <none>
   Input files : condortest/in_dir/
   State files : condortest/out_dir/
   Fuzz output : <target stdin>
   Random seed : 18e97029
  All settings : T=5000,2000 B=8+1 C=8+1,8 A=10 X=9,19,27+8 R=4096*8 L0=32,16 r00 c=2 U0 E=200 f0 k0 F=0

[+] Flow controller launched, 26 bytes fuzzable.

=== Fuzzing cycle 0/0 (condortest/in_dir) ===

[+] New call path - process calibration: ..DONE (full mode)
    Variations detected for 2/6 function parameters.
    Tracing 1 process, 2 functions, 26 bytes fuzzable (c=664289305ab59e32 p=58373b44393788d1)
[+] Attempting variable window walking bit flipping (1/8).
[+] Attempting walking value pattern set (2/8).
    + New call path stored at 'condortest/out_dir/case000/000' (c=8f70a5dd499b769f).
      Triggered by setting offset #0 to 0 (byte).
    + New call path stored at 'condortest/out_dir/case000/001' (c=232ce465aa212661).
      Triggered by setting offset #0 to 4096 (word).
[+] Attempting walking value randomization (3/8).
[+] Attempting block deletion operations (4/8).
[+] Attempting block overwrite operations (5/8).
[+] Attempting block cloning operations (6/8).
[+] Attempting block swap operations (7/8).
[+] Attempting random stacking and rearrangement (8/8).
[+] Fuzzing cycle completed successfully (12937 execs).

=== Fuzzing cycle 1/2 (condortest/out_dir/case000/000) ===

[+] New call path - process calibration: ..DONE (full mode)
    Variations detected for 2/7 function parameters.
    Tracing 1 process, 3 functions, 26 bytes fuzzable (c=8f70a5dd499b769f p=f3de545d78778dbf)
[+] Attempting variable window walking bit flipping (1/8).
[+] Attempting walking value pattern set (2/8).
[+] Attempting walking value randomization (3/8).
[+] Attempting block deletion operations (4/8).
[+] Attempting block overwrite operations (5/8).
[+] Attempting block cloning operations (6/8).
[+] Attempting block swap operations (7/8).
[+] Attempting random stacking and rearrangement (8/8).
[+] Fuzzing cycle completed successfully (12937 execs).

=== Fuzzing cycle 2/2 (condortest/out_dir/case000/001) ===

[+] New call path - process calibration: ..DONE (full mode)
    Variations detected for 2/8 function parameters.
    Tracing 1 process, 4 functions, 26 bytes fuzzable (c=232ce465aa212661 p=2a500770ecabc530)
[+] Attempting variable window walking bit flipping (1/8).
[+] Attempting walking value pattern set (2/8).
    + New call path stored at 'condortest/out_dir/case000/002' (c=c52f2f83c2faaac6).
      Triggered by setting offset #2 to 32 (byte).
[+] Attempting walking value randomization (3/8).
[+] Attempting block deletion operations (4/8).
[+] Attempting block overwrite operations (5/8).
[+] Attempting block cloning operations (6/8).
[+] Attempting block swap operations (7/8).
[+] Attempting random stacking and rearrangement (8/8).
[+] Fuzzing cycle completed successfully (12937 execs).

=== Fuzzing cycle 3/3 (condortest/out_dir/case000/002) ===

[+] New call path - process calibration: ..DONE (full mode)
    Variations detected for 2/10 function parameters.
    Tracing 1 process, 5 functions, 26 bytes fuzzable (c=c52f2f83c2faaac6 p=a3e892bbaeb14d5a)
[+] Attempting variable window walking bit flipping (1/8).
[+] Attempting walking value pattern set (2/8).
[+] Attempting walking value randomization (3/8).

+++ FAULT CONDITION DETECTED +++   发现fault了 哈哈
Diagnosis : CRASH (died on supplied input)
Location  : dostuff3(...)  发现关键地方 这个函数
Capture   : condortest/out_dir/FAULT000/003
Trigger   : setting offset #3 to 14640 (word).

[!] Fuzzing cycle terminated on abort condition (3165 execs).

  Fuzz cycles executed : 4 (1 partial)
    Processes launched : 41976
      Fault conditions : 1
       Call path count : 4 (+0 ignored)
  Parameter variations : 4 (+0 ignored)
     Effector segments : 0
    Total running time : 0:00:30
   Average performance : 1578.05 execs/sec

[+] Exiting gracefully.


看看使测试fualt的case:
root@condor:/usr/local/condor/bunny/bunny# hexdump  condortest/out_dir/FAULT000/003/case2 
0000000 1000 3020 6139 6161 6161 6161 6161 6161
0000010 6161 6161 6161 6161 0a61               
000001a

哈哈 看到1000 3020 没有:)

看看我们的测试用例 你就明白了,原理应该是 一定的变异。
之前提到的基本算法:根据变异输入,确定是否运行路径变化,
然后不断调整输入,直到覆盖全部运行路径。

root@condor:/usr/local/condor/bunny/bunny/condortest/in_dir# hexdump case2 
0000000 6161 6161 6161 6161 6161 6161 6161 6161
0000010 6161 6161 6161 6161 0a61               
000001a

2007-07-18