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