Winafl Build

实验环境

版本: Windows 10 专业版

版本号: 20H2

Winafl 搭建

Installing Visual Studio 2017 / Installing Visual Studio 2019

Installing git & cmake & python2

Installing DynamoRIO & WinAFL

下载 WINAFLhttps://github.com/googleprojectzero/winafl

下载DynamoRIOhttps://github.com/DynamoRIO/dynamorio/releases

下载后把二者解压到同一文件夹下,如 myafl,手动编译 x64环境

1
2
3
4
5
6
7
8
9
10
11
12
13
14
C:\Users\air\Desktop>cd myafl

C:\Users\air\Desktop\myafl>cd winafl

C:\Users\air\Desktop\myafl\winafl>mkdir build64

C:\Users\air\Desktop\myafl\winafl>cd build64
if VS2019
cmake -G"Visual Studio 16 2019" -A x64 .. -DDynamoRIO_DIR=C:\Users\air\Desktop\myafl\DynamoRIO\cmake
cmake --build . --config Release

if VS2017
cmake -G"Visual Studio 15 2017" -A x64 .. -DDynamoRIO_DIR=C:\Users\air\Desktop\myafl\DynamoRIO\cmake
cmake --build . --config Release

使用说明

DynamoRIO

1
2
3
4
5
6
7
8
9
10
// 1. 后面跟 <客户端> <客户端 参数> —(分割线) <目标程序 和 目标程序参数>
-c <client> [client options] — <app and args to run>
// 2.1 winafl.dll 参数说明。这也是插桩参数的使用[instrumentation options]
-debug # debug模式, 它会生成一个log文件
-target_module # 目标程序(只能有一个), 也是target_offset所在的模块
-target_offset # 目标程序偏移,相对于target_module的偏移,在method无法导出的时候使用
-fuzz_iterations # 目标程序重新启动一次内运行目标函数(即target_method)的最大迭代数
-nargs # 目标程序执行所需要的参数个数(包括目标程序本身)
-target_module # 目标函数,需要export或者调试符号(pdb)
-coverage_module # 计算覆盖率的模块,也就是目标程序会调用的模块(dll); (可以有多个)

WinAFL

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
-i dir        - input directory with test cases
-o dir - output directory for fuzzer findings
-t msec - timeout for each run
-D dir - directory containing DynamoRIO binaries (drrun, drconfig)
-P - use Intel PT tracing mode
-Y - enable the static instrumentation mode
-f file - location read by the fuzzed program
-m limit - memory limit for the target process
-p - persist DynamoRIO cache across target process restarts
-c cpu - the CPU to run the fuzzed program
-d - quick & dirty mode (skips deterministic steps)
-n - fuzz without instrumentation (dumb mode)
-x dir - optional fuzzer dictionary
-I msec - timeout for process initialization and first run
-T text - text banner to show on the screen
-M \\ -S id - distributed mode
-C - crash exploration mode (the peruvian rabbit thing)
-l path - a path to user-defined DLL for custom test cases processing
1
2
3
4
5
6
7
8
9
python winafl-cmin.py -D C:\Users\air\Desktop\myafl\DynamoRIO\bin64 -t 20000 -i C:\Users\air\Desktop\myafl\winafl\build64\bin\Release\tiff -o 

C:\Users\air\Desktop\myafl\winafl\build64\bin\Release\in -covtype edge -coverage_module xxx.dll -target_module xxx.exe -target_offset xxx -nargs 2 -- xxx.exe @@

.\afl-fuzz.exe -i in -o out -D C:\Users\air\Desktop\myafl\DynamoRIO\bin64 -t 20000 -- -target_module xxx.exe -coverage_module xxx.dll -target_offset xxx -nargs 2 -- xxx.exe @@

drrun.exe -c winafl.dll -debug -target_module test_gdiplus.exe -target_offset 0x10D0 -fuzz_iterations 10 -nargs 2 -- test_gdiplus.exe input.bmp

for i in *; do afl-tmin -i $i -o tmin-$i -- ~/path/to/tested/program [params] @@; done;

BUG

cmin

[-] PROGRAM ABORT : Unexpected result from pipe! expected ‘P’, instead received ‘C’

put winafl-cmin.py winafl.dll and other winafl program in the same directory as your test program.

test winafl-cmin.py

1
python winafl-cmin.py -D D:\Dropbox\fuzzing\DynamoRIO\bin64 -t 20000 -i  D:\Dropbox\fuzzing\test\input  -o D:\Dropbox\fuzzing\test\minset -covtype edge -coverage_module user32.dll -target_module TestLoadSimple.exe -target_offset 0x11910 -nargs 2 -v -- TestLoadSimple.exe @@

test afl-fuzz.exe

1
afl-fuzz.exe -i D:\Dropbox\fuzzing\test\minset -o output -M master -D D:\Dropbox\fuzzing\DynamoRIO\bin64 -t 20000 -- -coverage_module user32.dll -target_module TestLoadSimple.exe -target_offset 0x11910 -nargs 2 -- TestLoadSimple.exe @@

dry-run

1
2
3
[!] Dry-run failed, 2 executions resulted differently: 
Tuples matching? False
Return codes matching? True

这个 Bug,我感觉是winafl-cmin.py写的有些问题,目前大概发现两种解决办法。

First:https://symeonp.github.io/2017/09/17/fuzzing-winafl.html,参考这篇作者,让 target 执行一次样本,把垃圾样本剔除。

Second:在执行winafl-cmin.py的时候,加入 --skip-dry-run,跳过 dry-run

time out

我所碰到的情况都是 target偏移没有找对,然后运行 winafl的时候就会无限 time out

Honggfuzz Build

实验环境

Ubuntu 18.04

HonggFuzz 搭建

1
2
3
4
5
6
7
$ sudo apt install clang-10
$ sudo apt install libbfd-dev
$ sudo apt install libunwind8-dev
$ git clone https://github.com/google/honggfuzz.git
$ cd honggfuzz
honggfuzz$ make
honggfuzz$ sudo make install

然后在 /usr/bin里面将 clang-10修改为clang clang++-10修改为clang++(其实就是把clang-10设置成默认版本

1
2
3
4
5
6
7
8
9
10
11
12
13
14
air@ubuntu:~$ clang -v
clang version 10.0.0-4ubuntu1~18.04.2
Target: x86_64-pc-linux-gnu
Thread model: posix
InstalledDir: /usr/bin
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/8
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/7.5.0
Found candidate GCC installation: /usr/lib/gcc/x86_64-linux-gnu/8
Selected GCC installation: /usr/bin/../lib/gcc/x86_64-linux-gnu/7.5.0
Candidate multilib: .;@m64
Selected multilib: .;@m64

HoggFuzz 使用文档:https://github.com/google/honggfuzz/blob/master/docs/USAGE.md

使用说明

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
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
Usage: ./honggfuzz [options] -- path_to_command [args]
Options:
--help|-h
Help plz..
--input|-i VALUE
Path to a directory containing initial file corpus
--output VALUE
Output data (new dynamic coverage corpus, or the minimized coverage corpus) is written to this directory (default: input directory is used)
--persistent|-P
Enable persistent fuzzing (use hfuzz_cc/hfuzz-clang to compile code). This will be auto-detected!!!
--instrument|-z
*DEFAULT-MODE-BY-DEFAULT* Enable compile-time instrumentation (use hfuzz_cc/hfuzz-clang to compile code)
--minimize|-M
Minimize the input corpus. It will most likely delete some corpus files (from the --input directory) if no --output is used!
--noinst|-x
Static mode only, disable any instrumentation (hw/sw) feedback
--keep_output|-Q
Don't close children's stdin, stdout, stderr; can be noisy
--timeout|-t VALUE
Timeout in seconds (default: 10)
--threads|-n VALUE
Number of concurrent fuzzing threads (default: number of CPUs / 2)
--stdin_input|-s
Provide fuzzing input on STDIN, instead of ___FILE___
--mutations_per_run|-r VALUE
Maximal number of mutations per one run (default: 6)
--logfile|-l VALUE
Log file
--verbose|-v
Disable ANSI console; use simple log output
--verifier|-V
Enable crashes verifier
--debug|-d
Show debug messages (level >= 4)
--quiet|-q
Show only warnings and more serious messages (level <= 1)
--extension|-e VALUE
Input file extension (e.g. 'swf'), (default: 'fuzz')
--workspace|-W VALUE
Workspace directory to save crashes & runtime files (default: '.')
--crashdir VALUE
Directory where crashes are saved to (default: workspace directory)
--covdir_all VALUE
** DEPRECATED ** use --output
--covdir_new VALUE
New coverage (beyond the dry-run fuzzing phase) is written to this separate directory
--dict|-w VALUE
Dictionary file. Format:http://llvm.org/docs/LibFuzzer.html#dictionaries
--stackhash_bl|-B VALUE
Stackhashes blacklist file (one entry per line)
--mutate_cmd|-c VALUE
External command producing fuzz files (instead of internal mutators)
--pprocess_cmd VALUE
External command postprocessing files produced by internal mutators
--ffmutate_cmd VALUE
External command mutating files which have effective coverage feedback
--run_time VALUE
Number of seconds this fuzzing session will last (default: 0 [no limit])
--iterations|-N VALUE
Number of fuzzing iterations (default: 0 [no limit])
--rlimit_as VALUE
Per process RLIMIT_AS in MiB (default: 0 [no limit])
--rlimit_rss VALUE
Per process RLIMIT_RSS in MiB (default: 0 [no limit]). It will also set *SAN's soft_rss_limit_mb if used
--rlimit_data VALUE
Per process RLIMIT_DATA in MiB (default: 0 [no limit])
--rlimit_core VALUE
Per process RLIMIT_CORE in MiB (default: 0 [no cores are produced])
--report|-R VALUE
Write report to this file (default: '<workdir>/HONGGFUZZ.REPORT.TXT')
--max_file_size|-F VALUE
Maximal size of files processed by the fuzzer in bytes (default: 1048576 = 1MB)
--clear_env
Clear all environment variables before executing the binary
--env|-E VALUE
Pass this environment variable, can be used multiple times
--save_all|-u
Save all test-cases (not only the unique ones) by appending the current time-stamp to the filenames
--save_smaller|-U
Save smaller test-cases, renaming first found with .orig suffix
--tmout_sigvtalrm|-T
Use SIGVTALRM to kill timeouting processes (default: use SIGKILL)
--sanitizers|-S
Enable sanitizers settings (default: false)
--monitor_sigabrt VALUE
Monitor SIGABRT (default: false for Android, true for other platforms)
--no_fb_timeout VALUE
Skip feedback if the process has timeouted (default: false)
--exit_upon_crash
Exit upon seeing the first crash (default: false)
--socket_fuzzer
Instrument external fuzzer via socket
--netdriver
Use netdriver (libhfnetdriver/). In most cases it will be autodetected through a binary signature
--only_printable
Only generate printable inputs
--linux_symbols_bl VALUE
Symbols blacklist filter file (one entry per line)
--linux_symbols_wl VALUE
Symbols whitelist filter file (one entry per line)
--linux_addr_low_limit VALUE
Address limit (from si.si_addr) below which crashes are not reported, (default: 0)
--linux_keep_aslr
Don't disable ASLR randomization, might be useful with MSAN
--linux_perf_ignore_above VALUE
Ignore perf events which report IPs above this address
--linux_perf_instr
Use PERF_COUNT_HW_INSTRUCTIONS perf
--linux_perf_branch
Use PERF_COUNT_HW_BRANCH_INSTRUCTIONS perf
--linux_perf_bts_edge
Use Intel BTS to count unique edges
--linux_perf_ipt_block
Use Intel Processor Trace to count unique blocks (requires libipt.so)
--linux_perf_kernel_only
Gather kernel-only coverage with Intel PT and with Intel BTS
--linux_ns_net
Use Linux NET namespace isolation
--linux_ns_pid
Use Linux PID namespace isolation
--linux_ns_ipc
Use Linux IPC namespace isolation

Examples:
Run the binary over a mutated file chosen from the directory. Disable fuzzing feedback (static mode):
honggfuzz -i input_dir -x -- /usr/bin/djpeg ___FILE___
As above, provide input over STDIN:
honggfuzz -i input_dir -x -s -- /usr/bin/djpeg
Use compile-time instrumentation (-fsanitize-coverage=trace-pc-guard,...):
honggfuzz -i input_dir -- /usr/bin/djpeg ___FILE___
Use persistent mode w/o instrumentation:
honggfuzz -i input_dir -P -x -- /usr/bin/djpeg_persistent_mode
Use persistent mode and compile-time (-fsanitize-coverage=trace-pc-guard,...) instrumentation:
honggfuzz -i input_dir -P -- /usr/bin/djpeg_persistent_mode
Run the binary with dynamically generate inputs, maximize total no. of instructions:
honggfuzz --linux_perf_instr -- /usr/bin/djpeg ___FILE___
As above, maximize total no. of branches:
honggfuzz --linux_perf_branch -- /usr/bin/djpeg ___FILE___
As above, maximize unique branches (edges) via Intel BTS:
honggfuzz --linux_perf_bts_edge -- /usr/bin/djpeg ___FILE___
As above, maximize unique code blocks via Intel Processor Trace (requires libipt.so):
honggfuzz --linux_perf_ipt_block -- /usr/bin/djpeg ___FILE___

示例

1
2
3
4
5
6
7
$ sudo apt install pkg-config m4 libtool automake autoconf
$ git clone https://github.com/LibRaw/LibRaw.git
$ cd LibRaw
../Libraw$ export CC=hfuzz-clang CXX=hfuzz-clang++
../Libraw$ autoreconf --install
../Libraw$ ./configure
../Libraw$ make

libtool: link: hfuzz-clang++ -g -O2 -fopenmp -o bin/.libs/dcraw_emu samples/bin_dcraw_emu-dcraw_emu.o lib/.libs/libraw.so -lz -lm -fopenmp

编译插桩成功

然后我们用 honggfuzz 跑一下

1
2
3
LibRaw/bin/.libs$ export LD_LIBRARY_PATH=../../lib/.libs/
LibRaw/bin/.libs$ ./dcraw_emu
LibRaw/bin/.libs$ honggfuzz -f ../in -W ../out -t 5 -- ./dcraw_emu ___FILE___

页面显示大致如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
-···········[ 0 days 00 hrs 28 mins 42 secs ] ··········
Iterations : 35,520 [35. 52k]
Mode [3/3] : Feedback Driven Mode
Target : ./dcraw_ enu FILE_
Threads : 1, CPUs: 2, CPU%: 200% [ 100%/CPU]
Speed : 0/sec [avg: 20]
Crashes : 78 [unique: 55, blocklist: o, verified: 0]
Timeouts : 46 [5 sec]
Corpus size : 2,965, nax: 1, 048,576 bytes, init: 20 files
Cov Update : 0 days 00 hrs 00 mins 02 secs ago
Coverage : edge: 1,110/19,858 [5%] pc: 140 cnp: 89 ,337
··········· [ LOGS ] ········· / honggfuzz 2.4 / -
z:409 Tm:3,746us (i/b/h/e/p/c) New:0/0/0/0/0/6, Cur:0/0/0/0/0/178
Sz:430 Tฅ:4 , 501us (t/b/h/e/p/c) New:0/0/0/0/0/2, Cur:0/0/0/0/0/178
Sz :228001 Tm:238,719us (i/b/h/e/p/c) New:0/0/0/0/0/17, Cur :0/0/0/2/0/302

AFL Build

详细参考上篇:https://0xfocu5.github.io/posts/2ba75ee3/

  • 直接安装:sudo apt install afl
  • 官网下载压缩包,解压后在目录中打开终端输入:sudo make;sudo make install

参考

https://github.com/googleprojectzero/winafl/issues/179

https://github.com/googleprojectzero/winafl

https://x9security.com/installing-winafl/