• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1#!/bin/sh
2#
3# american fuzzy lop++ - Advanced Persistent Graphing
4# -------------------------------------------------
5#
6# Originally written by Michal Zalewski
7# Based on a design & prototype by Michael Rash.
8#
9# Copyright 2014, 2015 Google Inc. All rights reserved.
10#
11# Licensed under the Apache License, Version 2.0 (the "License");
12# you may not use this file except in compliance with the License.
13# You may obtain a copy of the License at:
14#
15#   https://www.apache.org/licenses/LICENSE-2.0
16#
17
18get_abs_path() {
19  echo $(cd "`dirname "$1"`" && pwd)/"`basename "$1"`"
20}
21
22echo "progress plotting utility for afl-fuzz by Michal Zalewski"
23echo
24
25GRAPHICAL="0"
26
27if [ "$1"  = "-g" ] || [ "$1" = "--graphical" ]; then
28GRAPHICAL="1"
29shift
30fi
31
32if [ "$#" != "2" ]; then
33
34  cat 1>&2 <<_EOF_
35$0 [ -g | --graphical ] afl_state_dir graph_output_dir
36
37This program generates gnuplot images from afl-fuzz output data.
38
39Usage:
40
41    afl_state_dir       should point to an existing state directory for any
42                        active or stopped instance of afl-fuzz
43    graph_output_dir    should point to an empty directory where this
44                        tool can write the resulting plots to
45    -g, --graphical     (optional) display the plots in a graphical window
46                        (you should have built afl-plot-ui to use this option)
47
48The program will put index.html and three PNG images in the output directory;
49you should be able to view it with any web browser of your choice.
50_EOF_
51
52  exit 1
53
54fi
55
56inputdir=`get_abs_path "$1"`
57outputdir=`get_abs_path "$2"`
58
59#if [ "$AFL_ALLOW_TMP" = "" ]; then
60#
61#  echo "$inputdir" | grep -qE '^(/var)?/tmp/'
62#  T1="$?"
63#
64#  echo "$outputdir" | grep -qE '^(/var)?/tmp/'
65#  T2="$?"
66#
67#  if [ "$T1" = "0" -o "$T2" = "0" ]; then
68#
69#    echo "[-] Error: this script shouldn't be used with shared /tmp directories." 1>&2
70#    exit 1
71#
72#  fi
73#
74#fi
75
76if [ ! -f "$inputdir/plot_data" ]; then
77
78  echo "[-] Error: input directory is not valid (missing 'plot_data')." 1>&2
79  exit 1
80
81fi
82
83LINES=`cat "$inputdir/plot_data" | wc -l`
84
85if [ "$LINES" -lt 3 ]; then
86
87  echo "[-] Error: plot_data carries too little data, let it run longer." 1>&2
88  exit 1
89
90fi
91
92BANNER="`cat "$inputdir/fuzzer_stats" 2> /dev/null | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`"
93
94test "$BANNER" = "" && BANNER="(none)"
95
96GNUPLOT=`command -v gnuplot 2>/dev/null`
97
98if [ "$GNUPLOT" = "" ]; then
99
100  echo "[-] Error: can't find 'gnuplot' in your \$PATH." 1>&2
101  exit 1
102
103fi
104
105mkdir "$outputdir" 2>/dev/null
106
107if [ ! -d "$outputdir" ]; then
108
109  echo "[-] Error: unable to create the output directory - pick another location." 1>&2
110  exit 1
111
112fi
113
114rm -f "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png"
115mv -f "$outputdir/index.html" "$outputdir/index.html.orig" 2>/dev/null
116
117GNUPLOT_SETUP="
118#set xdata time
119#set timefmt '%s'
120#set format x \"%b %d\n%H:%M\"
121set tics font 'small'
122unset mxtics
123unset mytics
124
125set grid xtics linetype 0 linecolor rgb '#e0e0e0'
126set grid ytics linetype 0 linecolor rgb '#e0e0e0'
127set border linecolor rgb '#50c0f0'
128set tics textcolor rgb '#000000'
129set key outside
130
131set autoscale xfixmin
132set autoscale xfixmax
133
134set xlabel \"relative time in seconds\" font \"small\"
135"
136
137PLOT_HF="
138set terminal png truecolor enhanced size 1000,300 butt
139set output '$outputdir/high_freq.png'
140
141$GNUPLOT_SETUP
142
143plot '$inputdir/plot_data' using 1:4 with filledcurve x1 title 'corpus count' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\
144     '' using 1:3 with filledcurve x1 title 'current fuzz item' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\
145     '' using 1:5 with lines title 'pending items' linecolor rgb '#0090ff' linewidth 3, \\
146     '' using 1:6 with lines title 'pending favs' linecolor rgb '#c00080' linewidth 3, \\
147     '' using 1:2 with lines title 'cycles done' linecolor rgb '#c000f0' linewidth 3
148"
149
150PLOT_LF="
151set terminal png truecolor enhanced size 1000,200 butt
152set output '$outputdir/low_freq.png'
153
154$GNUPLOT_SETUP
155
156plot '$inputdir/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\
157     '' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\
158     '' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\
159     '' using 1:10 with lines title 'levels' linecolor rgb '#0090ff' linewidth 3
160"
161
162PLOT_ES="
163set terminal png truecolor enhanced size 1000,200 butt
164set output '$outputdir/exec_speed.png'
165
166$GNUPLOT_SETUP
167
168plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
169     '$inputdir/plot_data' using 1:11 with lines title '    execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
170"
171
172PLOT_EG="
173set terminal png truecolor enhanced size 1000,300 butt
174set output '$outputdir/edges.png'
175
176$GNUPLOT_SETUP
177
178plot '$inputdir/plot_data' using 1:13 with lines title '        edges' linecolor rgb '#0090ff' linewidth 3
179"
180
181if [ "$#" = "2" ] && [ "$GRAPHICAL" = "1" ]; then
182
183afl-plot-ui -h > /dev/null 2>&1
184
185if [ "$?" != "0" ]; then
186
187cat 1>&2 <<_EOF_
188You do not seem to have the afl-plot-ui utility installed. If you have installed afl-plot-ui, make sure the afl-plot-ui executable is in your PATH.
189If you are still facing any problems, please open an issue at https://github.com/AFLplusplus/AFLplusplus/issues.
190
191No plots have been generated. Please rerun without the "-g" or "--graphical" flag to generate the plots.
192_EOF_
193
194exit 1
195
196fi
197
198rm -rf "$outputdir/.tmp"
199mkdir -p "$outputdir/.tmp"
200mkfifo "$outputdir/.tmp/win_ids" || exit 1
201
202afl-plot-ui > "$outputdir/.tmp/win_ids" &
203W_IDS=$(cat "$outputdir/.tmp/win_ids")
204
205rm -rf "$outputdir/.tmp"
206
207W_ID1=$(echo "$W_IDS" | head -n 1)
208W_ID2=$(echo "$W_IDS" | head -n 2 | tail -n 1)
209W_ID3=$(echo "$W_IDS" | head -n 3 | tail -n 1)
210W_ID4=$(echo "$W_IDS" | tail -n 1)
211
212echo "[*] Generating plots..."
213
214(
215
216cat << _EOF_
217
218$PLOT_HF
219set term x11 window "$W_ID3"
220set output
221replot
222pause mouse close
223
224_EOF_
225
226) | gnuplot 2> /dev/null &
227
228(
229
230cat << _EOF_
231
232$PLOT_LF
233set term x11 window "$W_ID4"
234set output
235replot
236pause mouse close
237
238_EOF_
239
240) | gnuplot 2> /dev/null &
241
242(
243
244cat << _EOF_
245
246$PLOT_ES
247set term x11 window "$W_ID2"
248set output
249replot
250pause mouse close
251
252_EOF_
253
254) | gnuplot 2> /dev/null &
255
256(
257
258cat << _EOF_
259
260$PLOT_EG
261set term x11 window "$W_ID1"
262set output
263replot
264pause mouse close
265
266_EOF_
267
268) | gnuplot 2> /dev/null &
269
270sleep 1
271
272else
273
274echo "[*] Generating plots..."
275
276(
277
278cat << _EOF_
279
280$PLOT_HF
281
282$PLOT_LF
283
284$PLOT_ES
285
286$PLOT_EG
287
288_EOF_
289
290) | gnuplot
291
292echo "[?] You can also use -g flag to view the plots in an GUI window, and interact with the plots (if you have built afl-plot-ui). Run \"afl-plot-h\" to know more."
293
294fi
295
296if [ ! -s "$outputdir/exec_speed.png" ]; then
297
298  echo "[-] Error: something went wrong! Perhaps you have an ancient version of gnuplot?" 1>&2
299  exit 1
300
301fi
302
303echo "[*] Generating index.html..."
304
305cat >"$outputdir/index.html" <<_EOF_
306<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
307<tr><td style="width: 18ex"><b>Banner:</b></td><td>$BANNER</td></tr>
308<tr><td><b>Directory:</b></td><td>$inputdir</td></tr>
309<tr><td><b>Generated on:</b></td><td>`date`</td></tr>
310</table>
311<p>
312<img src="edges.png" width=1000 height=300>
313<img src="high_freq.png" width=1000 height=300><p>
314<img src="low_freq.png" width=1000 height=200><p>
315<img src="exec_speed.png" width=1000 height=200>
316
317_EOF_
318
319# Make it easy to remotely view results when outputting directly to a directory
320# served by Apache or other HTTP daemon. Since the plots aren't horribly
321# sensitive, this seems like a reasonable trade-off.
322
323chmod 755 "$outputdir"
324chmod 644 "$outputdir/high_freq.png" "$outputdir/low_freq.png" "$outputdir/exec_speed.png" "$outputdir/edges.png" "$outputdir/index.html"
325
326echo "[+] All done - enjoy your charts!"
327
328exit 0
329