about summary refs log tree commit diff
diff options
context:
space:
mode:
-rwxr-xr-xafl-cmin.bash107
-rw-r--r--docs/Changelog.md2
2 files changed, 96 insertions, 13 deletions
diff --git a/afl-cmin.bash b/afl-cmin.bash
index 5258758e..ba7083fa 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -7,6 +7,8 @@
 #
 # Copyright 2014, 2015 Google Inc. All rights reserved.
 #
+# Copyright 2019-2023 AFLplusplus
+#
 # Licensed under the Apache License, Version 2.0 (the "License");
 # you may not use this file except in compliance with the License.
 # You may obtain a copy of the License at:
@@ -36,7 +38,7 @@
 # array sizes.
 #
 
-echo "corpus minimization tool for afl-fuzz by Michal Zalewski"
+echo "corpus minimization tool for afl-fuzz"
 echo
 
 #########
@@ -46,14 +48,14 @@ echo
 # Process command-line options...
 
 MEM_LIMIT=none
-TIMEOUT=none
+TIMEOUT=5000
 
-unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
-  AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE UNICORN_MODE
+unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN F_ARG \
+  AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE UNICORN_MODE T_ARG
 
 export AFL_QUIET=1
 
-while getopts "+i:o:f:m:t:eOQUAChXY" opt; do
+while getopts "+i:o:f:m:t:T:eOQUAChXY" opt; do
 
   case "$opt" in 
 
@@ -69,6 +71,7 @@ while getopts "+i:o:f:m:t:eOQUAChXY" opt; do
          ;;
     "f")
          STDIN_FILE="$OPTARG"
+         F_ARG=1
          ;;
     "m")
          MEM_LIMIT="$OPTARG"
@@ -106,6 +109,9 @@ while getopts "+i:o:f:m:t:eOQUAChXY" opt; do
          EXTRA_PAR="$EXTRA_PAR -U"
          UNICORN_MODE=1
          ;;    
+    "T")
+         T_ARG="$OPTARG"
+         ;;
     "?")
          exit 1
          ;;
@@ -130,9 +136,10 @@ Required parameters:
 
 Execution control settings:
 
-  -f file       - location read by the fuzzed program (stdin)
-  -m megs       - memory limit for child process ($MEM_LIMIT MB)
-  -t msec       - run time limit for child process (none)
+  -T tasks      - how many parallel processes to create (default=1, "all"=nproc)
+  -f file       - location read by the fuzzed program (default: stdin)
+  -m megs       - memory limit for child process (default=$MEM_LIMIT MB)
+  -t msec       - run time limit for child process (default: 5000ms)
   -O            - use binary-only instrumentation (FRIDA mode)
   -Q            - use binary-only instrumentation (QEMU mode)
   -U            - use unicorn-based instrumentation (Unicorn mode)
@@ -199,6 +206,11 @@ fi
 
 # Check for obvious errors.
 
+if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" ]; then
+  echo "[-] Error: -T and -f can not be used together." 1>&2
+  exit 1
+fi
+
 if [ ! "$MEM_LIMIT" = "none" ]; then
 
   if [ "$MEM_LIMIT" -lt "5" ]; then
@@ -233,7 +245,7 @@ if [ "$NYX_MODE" = "" ]; then
 
 fi
 
-grep -aq AFL_DUMP_MAP_SIZE "./$TARGET_BIN" && {
+grep -aq AFL_DUMP_MAP_SIZE "$TARGET_BIN" && {
   echo "[!] Trying to obtain the map size of the target ..."
   MAPSIZE=`AFL_DUMP_MAP_SIZE=1 "./$TARGET_BIN" 2>/dev/null`
   test -n "$MAPSIZE" && {
@@ -299,14 +311,29 @@ if [ ! -x "$SHOWMAP" ]; then
   exit 1
 fi
 
+THREADS=
+if [ ! "$T_ARG" = "" ]; then
+  if [ "$T_ARG" = "all" ]; then
+    THREADS=$(nproc)
+  else
+    if [ "$T_ARG" -gt 0 -a "$T_ARG" -le "$(nproc)" ]; then
+      THREADS=$T_ARG
+    else
+      echo "[-] Error: -T parameter must between 1 and $(nproc) or \"all\"." 1>&2
+    fi
+  fi
+fi
+
 IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`))
 
 if [ "$IN_COUNT" = "0" ]; then
-  echo "[+] Hmm, no inputs in the target directory. Nothing to be done."
+  echo "[-] Hmm, no inputs in the target directory. Nothing to be done."
   rm -rf "$TRACE_DIR"
   exit 1
 fi
 
+echo "[+] Found $IN_COUNT files for minimizing."
+
 FIRST_FILE=`ls "$IN_DIR" | head -1`
 
 # Make sure that we're not dealing with a directory.
@@ -355,6 +382,18 @@ else
 
 fi
 
+TMPFILE=$OUT_DIR/.list.$$
+if [ ! "$THREADS" = "" ]; then
+  ls -- "$IN_DIR" > $TMPFILE 2>/dev/null
+  IN_COUNT=$(cat $TMPFILE | wc -l)
+  SPLIT=$(($IN_COUNT / $THREADS))
+  if [ "$(($IN_COUNT % $THREADS))" -gt 0 ]; then
+    SPLIT=$(($SPLIT + 1))
+  fi
+  echo "[+] Splitting workload into $THREADS tasks with $SPLIT items on average each."
+  split -l $SPLIT $TMPFILE $TMPFILE.
+fi
+
 # Let's roll!
 
 #############################
@@ -363,6 +402,7 @@ fi
 
 echo "[*] Obtaining traces for input files in '$IN_DIR'..."
 
+if [ "$THREADS" = "" ]; then
 (
 
   CUR=0
@@ -386,17 +426,58 @@ echo "[*] Obtaining traces for input files in '$IN_DIR'..."
       printf "\\r    Processing file $CUR/$IN_COUNT... "
 
       cp "$IN_DIR/$fn" "$STDIN_FILE"
-
       "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
 
     done
 
-
   fi
 
+  echo
+
 )
 
-echo
+else
+
+  PIDS=
+  CNT=0
+  for inputs in $(ls ${TMPFILE}.*); do
+
+(
+
+  if [ "$STDIN_FILE" = "" ]; then
+
+    cat $inputs | while read -r fn; do
+
+      "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -- "$@" <"$IN_DIR/$fn"
+
+    done
+
+  else
+
+    STDIN_FILE="$inputs.$$"
+    cat $inputs | while read -r fn; do
+
+      cp "$IN_DIR/$fn" "$STDIN_FILE"
+      "$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
+
+    done
+
+  fi
+
+) &
+
+  PIDS="$PIDS $!"
+  done
+
+  echo "[+] Waiting for running tasks IDs:$PIDS"
+  wait
+  echo "[+] all $THREADS running tasks completed."
+  rm -f ${TMPFILE}*
+
+  echo trace dir files: $(ls $TRACE_DIR/*|wc -l)
+
+fi
+
 
 ##########################
 # STEP 2: SORTING TUPLES #
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 14323ae0..816a864d 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -14,6 +14,8 @@
   - afl-showmap:
     - added custom mutator post_process and send support
     - add `-I filelist` option, an alternative to `-i in_dir`
+  - afl-cmin.bash:
+    - `-T threads` parallel task support, huge speedup!
   - a new grammar custom mutator atnwalk was submitted by @voidptr127 !