1#!/bin/sh
2#
3# american fuzzy lop - Advanced Persistent Graphing
4# -------------------------------------------------
5#
6# Written and maintained by Michal Zalewski <lcamtuf@google.com>
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#   http://www.apache.org/licenses/LICENSE-2.0
16#
17
18echo "progress plotting utility for afl-fuzz by <lcamtuf@google.com>"
19echo
20
21if [ ! "$#" = "2" ]; then
22
23  cat 1>&2 <<_EOF_
24This program generates gnuplot images from afl-fuzz output data. Usage:
25
26$0 afl_state_dir graph_output_dir
27
28The afl_state_dir parameter should point to an existing state directory for any
29active or stopped instance of afl-fuzz; while graph_output_dir should point to
30an empty directory where this tool can write the resulting plots to.
31
32The program will put index.html and three PNG images in the output directory;
33you should be able to view it with any web browser of your choice.
34
35_EOF_
36
37  exit 1
38
39fi
40
41if [ "$AFL_ALLOW_TMP" = "" ]; then
42
43  echo "$1" | grep -qE '^(/var)?/tmp/'
44  T1="$?"
45
46  echo "$2" | grep -qE '^(/var)?/tmp/'
47  T2="$?"
48
49  if [ "$T1" = "0" -o "$T2" = "0" ]; then
50
51    echo "[-] Error: this script shouldn't be used with shared /tmp directories." 1>&2
52    exit 1
53
54  fi
55
56fi
57
58if [ ! -f "$1/plot_data" ]; then
59
60  echo "[-] Error: input directory is not valid (missing 'plot_data')." 1>&2
61  exit 1
62
63fi
64
65BANNER="`cat "$1/fuzzer_stats" | grep '^afl_banner ' | cut -d: -f2- | cut -b2-`"
66
67test "$BANNER" = "" && BANNER="(none)"
68
69GNUPLOT=`which gnuplot 2>/dev/null`
70
71if [ "$GNUPLOT" = "" ]; then
72
73  echo "[-] Error: can't find 'gnuplot' in your \$PATH." 1>&2
74  exit 1
75
76fi
77
78mkdir "$2" 2>/dev/null
79
80if [ ! -d "$2" ]; then
81
82  echo "[-] Error: unable to create the output directory - pick another location." 1>&2
83  exit 1
84
85fi
86
87rm -f "$2/high_freq.png" "$2/low_freq.png" "$2/exec_speed.png"
88mv -f "$2/index.html" "$2/index.html.orig" 2>/dev/null
89
90echo "[*] Generating plots..."
91
92(
93
94cat <<_EOF_
95set terminal png truecolor enhanced size 1000,300 butt
96
97set output '$2/high_freq.png'
98
99set xdata time
100set timefmt '%s'
101set format x "%b %d\n%H:%M"
102set tics font 'small'
103unset mxtics
104unset mytics
105
106set grid xtics linetype 0 linecolor rgb '#e0e0e0'
107set grid ytics linetype 0 linecolor rgb '#e0e0e0'
108set border linecolor rgb '#50c0f0'
109set tics textcolor rgb '#000000'
110set key outside
111
112set autoscale xfixmin
113set autoscale xfixmax
114
115plot '$1/plot_data' using 1:4 with filledcurve x1 title 'total paths' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\
116     '' using 1:3 with filledcurve x1 title 'current path' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\
117     '' using 1:5 with lines title 'pending paths' linecolor rgb '#0090ff' linewidth 3, \\
118     '' using 1:6 with lines title 'pending favs' linecolor rgb '#c00080' linewidth 3, \\
119     '' using 1:2 with lines title 'cycles done' linecolor rgb '#c000f0' linewidth 3
120
121set terminal png truecolor enhanced size 1000,200 butt
122set output '$2/low_freq.png'
123
124plot '$1/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\
125     '' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\
126     '' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\
127     '' using 1:10 with lines title 'levels' linecolor rgb '#0090ff' linewidth 3
128
129set terminal png truecolor enhanced size 1000,200 butt
130set output '$2/exec_speed.png'
131
132plot '$1/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
133     '$1/plot_data' using 1:11 with lines title '    execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
134
135_EOF_
136
137) | gnuplot
138
139if [ ! -s "$2/exec_speed.png" ]; then
140
141  echo "[-] Error: something went wrong! Perhaps you have an ancient version of gnuplot?" 1>&2
142  exit 1
143
144fi
145
146echo "[*] Generating index.html..."
147
148cat >"$2/index.html" <<_EOF_
149<table style="font-family: 'Trebuchet MS', 'Tahoma', 'Arial', 'Helvetica'">
150<tr><td style="width: 18ex"><b>Banner:</b></td><td>$BANNER</td></tr>
151<tr><td><b>Directory:</b></td><td>$1</td></tr>
152<tr><td><b>Generated on:</b></td><td>`date`</td></tr>
153</table>
154<p>
155<img src="high_freq.png" width=1000 height=300><p>
156<img src="low_freq.png" width=1000 height=200><p>
157<img src="exec_speed.png" width=1000 height=200>
158
159_EOF_
160
161# Make it easy to remotely view results when outputting directly to a directory
162# served by Apache or other HTTP daemon. Since the plots aren't horribly
163# sensitive, this seems like a reasonable trade-off.
164
165chmod 755 "$2"
166chmod 644 "$2/high_freq.png" "$2/low_freq.png" "$2/exec_speed.png" "$2/index.html"
167
168echo "[+] All done - enjoy your charts!"
169
170exit 0
171