1 从一个test程序开始
1.1 安装AFL
首先,检查本地的clang和llvm是否安装,若未安装则安装一下
1 2 sudo apt-get install clang sudo apt-get install llvm
以上环境确认好后,下载并安装AFL
1 2 3 4 5 wget http://lcamtuf.coredump.cx/afl/releases/afl-2.52b.tgz tar -zxvf afl-2.52b.tgz cd afl-2.52b make sudo make install
以上操作做完,AFL就算是安装完毕啦。现在来看看AFL安装前后代码目录中文件的差别。以下先是安装前的目录:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 drwxr-xr-x 10 500 500 4096 Nov 5 2017 . drwxr-xr-x 3 root root 4096 Jun 2 09:49 .. -rw-r--r-- 1 500 500 23755 Nov 5 2017 afl-analyze.c -rw-r--r-- 1 500 500 15273 Nov 5 2017 afl-as.c -rw-r--r-- 1 500 500 21090 Nov 5 2017 afl-as.h -rwxr-xr-x 1 500 500 11392 Nov 5 2017 afl-cmin -rw-r--r-- 1 500 500 206076 Nov 5 2017 afl-fuzz.c -rw-r--r-- 1 500 500 8597 Nov 5 2017 afl-gcc.c -rw-r--r-- 1 500 500 5336 Nov 5 2017 afl-gotcpu.c -rwxr-xr-x 1 500 500 4913 Nov 5 2017 afl-plot -rw-r--r-- 1 500 500 16527 Nov 5 2017 afl-showmap.c -rw-r--r-- 1 500 500 25235 Nov 5 2017 afl-tmin.c -rwxr-xr-x 1 500 500 3655 Nov 5 2017 afl-whatsup -rw-r--r-- 1 500 500 12565 Nov 5 2017 alloc-inl.h -rw-r--r-- 1 500 500 11216 Nov 5 2017 config.h -rw-r--r-- 1 500 500 6574 Nov 5 2017 debug.h drwxr-xr-x 2 500 500 4096 Nov 5 2017 dictionaries drwxr-xr-x 4 500 500 4096 Nov 5 2017 docs drwxr-xr-x 12 500 500 4096 Nov 5 2017 experimental -rw-r--r-- 1 500 500 2065 Nov 5 2017 hash.h drwxr-xr-x 2 500 500 4096 Nov 5 2017 libdislocator drwxr-xr-x 2 500 500 4096 Nov 5 2017 libtokencap drwxr-xr-x 2 500 500 4096 Nov 5 2017 llvm_mode -rw-r--r-- 1 500 500 6987 Nov 5 2017 Makefile drwxr-xr-x 3 500 500 4096 Nov 5 2017 qemu_mode lrwxrwxrwx 1 500 500 24 Nov 5 2017 QuickStartGuide.txt -> docs/QuickStartGuide.txt lrwxrwxrwx 1 500 500 11 Nov 5 2017 README -> docs/README drwxr-xr-x 6 500 500 4096 Nov 5 2017 testcases -rw-r--r-- 1 500 500 789 Nov 5 2017 test-instr.c -rw-r--r-- 1 500 500 2292 Nov 5 2017 types.h
安装完成后,代码目录中的文件
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 drwxr-xr-x 10 500 500 4096 Jun 2 09:47 . drwxr-xr-x 7 root root 4096 Jun 1 18:42 .. -rwxr-xr-x 1 root root 90792 Jun 2 09:46 afl-analyze -rw-r--r-- 1 500 500 23755 Nov 5 2017 afl-analyze.c -rwxr-xr-x 1 root root 50808 Jun 2 09:46 afl-as -rw-r--r-- 1 500 500 15273 Nov 5 2017 afl-as.c -rw-r--r-- 1 500 500 21090 Nov 5 2017 afl-as.h lrwxrwxrwx 1 root root 7 Jun 2 09:46 afl-clang -> afl-gcc lrwxrwxrwx 1 root root 7 Jun 2 09:46 afl-clang++ -> afl-gcc -rwxr-xr-x 1 500 500 11392 Nov 5 2017 afl-cmin -rwxr-xr-x 1 root root 582872 Jun 2 09:46 afl-fuzz -rw-r--r-- 1 500 500 206076 Nov 5 2017 afl-fuzz.c lrwxrwxrwx 1 root root 7 Jun 2 09:46 afl-g++ -> afl-gcc -rwxr-xr-x 1 root root 35376 Jun 2 09:46 afl-gcc -rw-r--r-- 1 500 500 8597 Nov 5 2017 afl-gcc.c -rwxr-xr-x 1 root root 32240 Jun 2 09:46 afl-gotcpu -rw-r--r-- 1 500 500 5336 Nov 5 2017 afl-gotcpu.c -rwxr-xr-x 1 500 500 4913 Nov 5 2017 afl-plot -rwxr-xr-x 1 root root 76840 Jun 2 09:46 afl-showmap -rw-r--r-- 1 500 500 16527 Nov 5 2017 afl-showmap.c -rwxr-xr-x 1 root root 106280 Jun 2 09:46 afl-tmin -rw-r--r-- 1 500 500 25235 Nov 5 2017 afl-tmin.c -rwxr-xr-x 1 500 500 3655 Nov 5 2017 afl-whatsup -rw-r--r-- 1 500 500 12565 Nov 5 2017 alloc-inl.h lrwxrwxrwx 1 root root 6 Jun 2 09:46 as -> afl-as -rw-r--r-- 1 500 500 11216 Nov 5 2017 config.h -rw-r--r-- 1 500 500 6574 Nov 5 2017 debug.h drwxr-xr-x 2 500 500 4096 Nov 5 2017 dictionaries drwxr-xr-x 4 500 500 4096 Nov 5 2017 docs drwxr-xr-x 12 500 500 4096 Nov 5 2017 experimental -rw-r--r-- 1 500 500 2065 Nov 5 2017 hash.h drwxr-xr-x 2 500 500 4096 Nov 5 2017 libdislocator drwxr-xr-x 2 500 500 4096 Nov 5 2017 libtokencap drwxr-xr-x 2 500 500 4096 Nov 5 2017 llvm_mode -rw-r--r-- 1 500 500 6987 Nov 5 2017 Makefile drwxr-xr-x 3 500 500 4096 Nov 5 2017 qemu_mode lrwxrwxrwx 1 500 500 24 Nov 5 2017 QuickStartGuide.txt -> docs/QuickStartGuide.txt lrwxrwxrwx 1 500 500 11 Nov 5 2017 README -> docs/README drwxr-xr-x 6 500 500 4096 Nov 5 2017 testcases -rw-r--r-- 1 500 500 789 Nov 5 2017 test-instr.c -rw-r--r-- 1 500 500 2292 Nov 5 2017 types.h
可以看到afl安装后,文件夹下多了些二进制文件,是不是很简单。但是,在使用AFL进行fuzz测试前,一定要设置一下core_pattern ,否则会报错哦。
1 2 3 4 5 root@x:~/afl-test# cat /proc/sys/kernel/core_pattern |/usr/share/apport/apport %p %s %c %d %P root@x:~/afl-test# echo core > /proc/sys/kernel/core_pattern root@x:~/afl-test# cat /proc/sys/kernel/core_pattern core
1.2 跑起来看看
测试程序的代码使用了先知社区的示例代码,如下。平时我们编译c代码使用的是gcc,现在为了使用AFL进行fuzz,我们必须使用1.1节中编译出来的afl-gcc对目标代码进行插桩编译。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 #include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <string.h> #include <signal.h> int vuln (char *str) { int len = strlen (str); if (str[0 ] == 'A' && len == 66 ) { raise(SIGSEGV); } else if (str[0 ] == 'F' && len == 6 ) { raise(SIGSEGV); } else { printf ("it is good!\n" ); } return 0 ; } int main (int argc, char *argv[]) { char buf[100 ]={0 }; gets(buf); printf (buf); vuln(buf); return 0 ; }
接下来,需要做以下三件事:
(1)使用afl-gcc编译目标代码(即插桩)
1 $ afl-gcc test.c -g -o test
(2)新建测试用例(测试用例即待测程序的输入,可以随意给个文件作为起始用例。AFL会在此用例的基础上进行变异,好的测试用例有助于更快发现更多bug)
1 2 3 4 5 $ mkdir testcase $ cd testcase $ vim file123 123 qwe
(3)输出文件夹(发现的bug等信息会输出到该目录下)
最后,指定好以上三项的位置,执行如下命令,就会进入AFL主面板开始fuzz啦
1 afl-fuzz -i testcase/ -o output/ ./test
这里给一下我fuzz完成后(ctrl +c)的情况:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 root@x:~/afl-test# afl-fuzz -i testcase/ -o output/ ./test afl-fuzz 2.52b by <lcamtuf@google.com> [+] You have 8 CPU cores and 1 runnable tasks (utilization: 12%). [+] Try parallel jobs - see /usr/local/share/doc/afl/parallel_fuzzing.txt. [*] Checking CPU core loadout... [+] Found a free CPU core, binding to #0. [*] Checking core_pattern... [*] Setting up output directories... [+] Output directory exists but deemed OK to reuse. [*] Deleting old session data... [+] Output dir cleanup successful. [*] Scanning 'testcase/'... [+] No auto-generated dictionary tokens to reuse. [*] Creating hard links for all input files... [*] Validating target binary... [*] Attempting dry run with 'id:000000,orig:file1'... [*] Spinning up the fork server... [+] All right - fork server is up. len = 8, map size = 5, exec speed = 306 us [+] All test cases processed. [+] Here are some useful stats: Test case count : 1 favored, 0 variable, 1 total Bitmap range : 5 to 5 bits (average: 5.00 bits) Exec timing : 306 to 306 us (average: 306 us) [*] No -t option specified, so I'll use exec timeout of 20 ms. [+] All set and ready to roll! american fuzzy lop 2.52b (test) ┌─ process timing ─────────────────────────────────────┬─ overall results ─────┐ │ run time : 0 days, 0 hrs, 24 min, 9 sec │ cycles done : 2574 │ │ last new path : 0 days, 0 hrs, 24 min, 9 sec │ total paths : 3 │ │ last uniq crash : 0 days, 0 hrs, 14 min, 10 sec │ uniq crashes : 6 │ │ last uniq hang : none seen yet │ uniq hangs : 0 │ ├─ cycle progress ────────────────────┬─ map coverage ─┴───────────────────────┤ │ now processing : 2 (66.67%) │ map density : 0.01% / 0.01% │ │ paths timed out : 0 (0.00%) │ count coverage : 1.00 bits/tuple │ ├─ stage progress ────────────────────┼─ findings in depth ────────────────────┤ │ now trying : splice 9 │ favored paths : 3 (100.00%) │ │ stage execs : 47/48 (97.92%) │ new edges on : 3 (100.00%) │ │ total execs : 5.41M │ total crashes : 385k (6 unique) │ │ exec speed : 3330/sec │ total tmouts : 1 (1 unique) │ ├─ fuzzing strategy yields ───────────┴───────────────┬─ path geometry ────────┤ │ bit flips : 0/128, 0/125, 0/119 │ levels : 2 │ │ byte flips : 0/16, 0/13, 0/7 │ pending : 0 │ │ arithmetics : 2/896, 0/129, 0/9 │ pend fav : 0 │ │ known ints : 0/78, 0/339, 0/308 │ own finds : 2 │ │ dictionary : 0/0, 0/0, 0/0 │ imported : n/a │ │ havoc : 4/2.31M, 2/3.09M │ stability : 100.00% │ │ trim : 83.10%/16, 0.00% ├────────────────────────┘ ^C────────────────────────────────────────────────────┘ [cpu000: 23%] +++ Testing aborted by user +++ [+] We're done here. Have a nice day!
1.3 分析结果
fuzz完成后,根据AFL面板的信息我们知道有6个crash,因此我们进入output目录去分析
1 2 3 4 5 6 7 8 9 10 11 root@x:~/afl-test/output# ls -al total 108 drwxr-xr-x 5 root root 4096 Jun 2 10:15 . drwxr-xr-x 4 root root 4096 Jun 2 10:08 .. drwx------ 2 root root 4096 Jun 2 10:25 crashes -rw------- 1 root root 1 Jun 2 10:39 .cur_input -rw------- 1 root root 65536 Jun 2 10:16 fuzz_bitmap -rw------- 1 root root 739 Jun 2 10:39 fuzzer_stats drwx------ 2 root root 4096 Jun 2 10:15 hangs -rw------- 1 root root 15250 Jun 2 10:39 plot_data drwx------ 3 root root 4096 Jun 2 10:15 queue
crashes/ 文件夹中存放了fuzz过程中产生的crash样例
hangs/ 文件夹中存放了fuzz过程中产生的超时样例
queue/ 文件夹中存放了fuzz过程中不同执行路径的测试用例
使用xxd
命令查看产生的6个crash样例,然后可以将样例作为输入用gdb调试test程序。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 root@x:~/afl-test/output/crashes# xxd id:000000,sig:06,src:000000,op:havoc,rep:64 00000000: 1f20 0820 fe1f 2004 0020 200c 0064 1ffe . . .. .. ..d.. 00000010: 017f 2033 ff20 2000 180b 2020 2008 20e2 .. 3. ... . . 00000020: 1f20 e21f ff01 00ff ff20 2020 2002 0024 . ....... ..$ 00000030: ff00 0000 0000 0100 203a 200c 20e2 1f01 ........ : . ... 00000040: 2020 0019 0110 510b 2020 2002 0020 2020 ....Q. .. 00000050: 2020 2020 2020 2020 2020 2020 2020 2020 00000060: 2020 2020 2020 2020 2020 2020 2020 0820 . 00000070: 2020 0c20 e21f 2002 7f80 2020 6b20 0101 . .. ... k .. 00000080: 0101 0101 1d01 0101 0101 0101 0101 0101 ................ 00000090: 0101 0101 0101 0101 0101 0101 40ff 2080 ............@. . root@x:~/afl-test/output/crashes# xxd id:000001,sig:11,src:000002,op:arith8,pos:0,val:-28 00000000: 4662 6262 627f 001a Fbbbb... root@x:~/afl-test/output/crashes# xxd id:000002,sig:06,src:000002,op:havoc,rep:128 00000000: 3685 c13e 3e3e 002f 3e3e 203e 3e6a 3e3e 6..>>>./>> >>j>> 00000010: 3ee4 343e 3e3e 3e53 3d5b 146a 3e3e 2e3e >.4>>>>S=[.j>>.> 00000020: 3e3e 3e4e 3e6a 3e5c 273e 3e3e 3e3e 6a3e >>>N>j>\'>>>>>j> 00000030: 3e8c 3e3e 3e3e 4a3e 6a3e 3e27 d9c5 a8c5 >.>>>>J>j>>'.... 00000040: 5314 533e 3e1d 3e3e 3e3e 3e3e 3e3e 3e3e S.S>>.>>>>>>>>>> 00000050: 3e3e 3e3e 3e3e 3e3e 3e3e 3e3e 3e3e 3e3e >>>>>>>>>>>>>>>> 00000060: 3e3e 3e3e 3e2f 3e3e 343e 3e6a 3e3e 0080 >>>>>/>>4>>j>>.. 00000070: 3e3e 3e27 fb9c 9c9c 9c9c 9c9c 9c9c c5c5 >>>'............ 00000080: c5a6 c5e0 7fff ...... root@x:~/afl-test/output/crashes# xxd id:000003,sig:06,src:000001+000002,op:splice,rep:4 00000000: 2532 6e5a 627f fc19 %2nZb... root@x:~/afl-test/output/crashes# xxd id:000004,sig:06,src:000001,op:havoc,rep:128 00000000: 4106 00f2 5fdf 03a0 c5f6 dfdf 40a0 dff4 A..._.......@... 00000010: f5ff e5f4 f4fe 04f5 f4f4 f4f4 f4f4 f4f4 ................ 00000020: 0ef5 f4ff 800d f4b4 f400 f4f4 0edb eadf ................ 00000030: f8df dfe7 f400 eadd dfe7 df02 dff8 00d7 ................ 00000040: dfdf 01df dfdf ecdb eadf f8df dfe7 dfdf ................ 00000050: dff8 1ad7 dfdf 01da dfdf dedf dfdf dfdf ................ 00000060: dfdf dfdf dfdf dfdf dfdf dfde dfdf dfde ................ 00000070: ed00 e3e3 e316 0d00 0000 1000 00c0 dfe7 ................ 00000080: dfdf df00 d701 dfd6 0e ......... root@x:~/afl-test/output/crashes# xxd id:000005,sig:11,src:000002+000001,op:splice,rep:16 00000000: 4132 800f fe0f 0f0f 0f0f 220f 0f0f 0f0f A2........"..... 00000010: 0f0f 0f0f 0f0f 0f0f 0f0f 0ef0 0f22 0f0f .............".. 00000020: 0f0f 0f0f 0f0f 0f0f 0f0f 0f0f 0f0f 0f0f ................ 00000030: 0f0f 0f0f 0f0f 0f0f 0f0f 0f7f ff64 0f0f .............d.. 00000040: fc0e 000f 0f0f 0f0f 0fff ..........
1.4 继续已停止的fuzz测试
1 afl-fuzz -i- -o output ./test
1.5 结合ASAN的fuzz
ASAN只推荐在32位机器上使用。如果在64位机器上使用,也需将AFL编译成32位的。
1 2 Method 1. set AFL_USE_ASAN=1 before calling ‘make clean all’ Method 2. add -fsanitize=address option into makefile
1.6 文件fuzz
1.2和1.3节讲的是从stdin读取输入的目标程序,这里补充一下从文件读取输入的目标程序,以 readelf -a xxfile
为例。
有源码插桩:
1 afl-fuzz -i in/ -o out/ ./readelf -a @@
无源码插桩:
1 afl-fuzz -i in/ -o out/ -Q ./readelf -a @@
2 无源码AFL fuzz
无源码时,即无法对源码使用功能afl-gcc/afl-g++进行插桩编译时,整个fuzz过程会变得异常缓慢。但确实没有源码的情况下可使用该方法。
步骤1 :编译支持无源码fuzz的AFL
在afl源码目录下:
1 2 3 4 cd qemu_mode ./build_qemu_support.sh cd .. make install
步骤2 :跟1.2和1.3节一样,只不过有两点差异:
1 afl-fuzz -i testcase/ -o output/ -Q ./test
3 AFL文档学习
afl面板介绍:
https://lcamtuf.coredump.cx/afl/status_screen.txt
4 参考文档
初探AFL-Fuzz
小白初学AFL(American Fuzzy Lop)
AFL文件变异一览
AFL(American Fuzzy Lop) Cautions