mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-10 17:21:33 +00:00
commit
7ca1b85c5e
1
TODO.md
1
TODO.md
@ -10,7 +10,6 @@
|
|||||||
- parallel builds for source-only targets
|
- parallel builds for source-only targets
|
||||||
- get rid of check_binary, replace with more forkserver communication
|
- get rid of check_binary, replace with more forkserver communication
|
||||||
- first fuzzer should be a main automatically? not sure.
|
- first fuzzer should be a main automatically? not sure.
|
||||||
- reload fuzz binary on signal
|
|
||||||
|
|
||||||
## Maybe
|
## Maybe
|
||||||
|
|
||||||
|
111
afl-cmin
111
afl-cmin
@ -103,9 +103,10 @@ function usage() {
|
|||||||
" -o dir - output directory for minimized files\n" \
|
" -o dir - output directory for minimized files\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Execution control settings:\n" \
|
"Execution control settings:\n" \
|
||||||
|
" -T tasks - how many parallel tasks to run (default: 1, all=nproc)\n" \
|
||||||
" -f file - location read by the fuzzed program (stdin)\n" \
|
" -f file - location read by the fuzzed program (stdin)\n" \
|
||||||
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
||||||
" -t msec - run time limit for child process (default: none)\n" \
|
" -t msec - run time limit for child process (default: 5000)\n" \
|
||||||
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
||||||
" -Q - use binary-only instrumentation (QEMU mode)\n" \
|
" -Q - use binary-only instrumentation (QEMU mode)\n" \
|
||||||
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
|
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
|
||||||
@ -119,7 +120,6 @@ function usage() {
|
|||||||
"For additional tips, please consult README.md\n" \
|
"For additional tips, please consult README.md\n" \
|
||||||
"\n" \
|
"\n" \
|
||||||
"Environment variables used:\n" \
|
"Environment variables used:\n" \
|
||||||
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \
|
|
||||||
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
|
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
|
||||||
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
|
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
|
||||||
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
|
"AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \
|
||||||
@ -159,13 +159,19 @@ BEGIN {
|
|||||||
# process options
|
# process options
|
||||||
Opterr = 1 # default is to diagnose
|
Opterr = 1 # default is to diagnose
|
||||||
Optind = 1 # skip ARGV[0]
|
Optind = 1 # skip ARGV[0]
|
||||||
while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXY?")) != -1) {
|
while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eACOQUXYT:?")) != -1) {
|
||||||
if (_go_c == "i") {
|
if (_go_c == "i") {
|
||||||
if (!Optarg) usage()
|
if (!Optarg) usage()
|
||||||
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||||
in_dir = Optarg
|
in_dir = Optarg
|
||||||
continue
|
continue
|
||||||
} else
|
} else
|
||||||
|
if (_go_c == "T") {
|
||||||
|
if (!Optarg) usage()
|
||||||
|
if (threads) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||||
|
threads = Optarg
|
||||||
|
continue
|
||||||
|
} else
|
||||||
if (_go_c == "o") {
|
if (_go_c == "o") {
|
||||||
if (!Optarg) usage()
|
if (!Optarg) usage()
|
||||||
if (out_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
if (out_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
|
||||||
@ -234,7 +240,7 @@ BEGIN {
|
|||||||
} # while options
|
} # while options
|
||||||
|
|
||||||
if (!mem_limit) mem_limit = "none"
|
if (!mem_limit) mem_limit = "none"
|
||||||
if (!timeout) timeout = "none"
|
if (!timeout) timeout = "5000"
|
||||||
|
|
||||||
# get program args
|
# get program args
|
||||||
i = 0
|
i = 0
|
||||||
@ -253,21 +259,30 @@ BEGIN {
|
|||||||
# Do a sanity check to discourage the use of /tmp, since we can't really
|
# Do a sanity check to discourage the use of /tmp, since we can't really
|
||||||
# handle this safely from an awk script.
|
# handle this safely from an awk script.
|
||||||
|
|
||||||
if (!ENVIRON["AFL_ALLOW_TMP"]) {
|
#if (!ENVIRON["AFL_ALLOW_TMP"]) {
|
||||||
dirlist[0] = in_dir
|
# dirlist[0] = in_dir
|
||||||
dirlist[1] = target_bin
|
# dirlist[1] = target_bin
|
||||||
dirlist[2] = out_dir
|
# dirlist[2] = out_dir
|
||||||
dirlist[3] = stdin_file
|
# dirlist[3] = stdin_file
|
||||||
"pwd" | getline dirlist[4] # current directory
|
# "pwd" | getline dirlist[4] # current directory
|
||||||
for (dirind in dirlist) {
|
# for (dirind in dirlist) {
|
||||||
dir = dirlist[dirind]
|
# dir = dirlist[dirind]
|
||||||
|
#
|
||||||
|
# if (dir ~ /^(\/var)?\/tmp/) {
|
||||||
|
# print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr"
|
||||||
|
# exit 1
|
||||||
|
# }
|
||||||
|
# }
|
||||||
|
# delete dirlist
|
||||||
|
#}
|
||||||
|
|
||||||
if (dir ~ /^(\/var)?\/tmp/) {
|
if (threads && stdin_file) {
|
||||||
print "[-] Error: do not use this script in /tmp or /var/tmp." > "/dev/stderr"
|
print "[-] Error: -T and -f cannot be used together." > "/dev/stderr"
|
||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
}
|
|
||||||
delete dirlist
|
if (!threads && !stdin_file && !nyx_mode) {
|
||||||
|
print "[*] Are you aware of the '-T all' parallelize option that improves the speed for large/slow corpuses?"
|
||||||
}
|
}
|
||||||
|
|
||||||
# If @@ is specified, but there's no -f, let's come up with a temporary input
|
# If @@ is specified, but there's no -f, let's come up with a temporary input
|
||||||
@ -350,6 +365,18 @@ BEGIN {
|
|||||||
exit 1
|
exit 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (threads) {
|
||||||
|
"nproc" | getline nproc
|
||||||
|
if (threads == "all") {
|
||||||
|
threads = nproc
|
||||||
|
} else {
|
||||||
|
if (!(threads > 1 && threads <= nproc)) {
|
||||||
|
print "[-] Error: -T option must be between 1 and "nproc" or \"all\"." > "/dev/stderr"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
# Check for the more efficient way to copy files...
|
# Check for the more efficient way to copy files...
|
||||||
if (0 != system("mkdir -p -m 0700 "trace_dir)) {
|
if (0 != system("mkdir -p -m 0700 "trace_dir)) {
|
||||||
print "[-] Error: Cannot create directory "trace_dir > "/dev/stderr"
|
print "[-] Error: Cannot create directory "trace_dir > "/dev/stderr"
|
||||||
@ -459,9 +486,59 @@ BEGIN {
|
|||||||
# STEP 1: Collecting traces #
|
# STEP 1: Collecting traces #
|
||||||
#############################
|
#############################
|
||||||
|
|
||||||
|
if (threads) {
|
||||||
|
|
||||||
|
inputsperfile = in_count / threads
|
||||||
|
if (in_count % threads) {
|
||||||
|
inputsperfile++;
|
||||||
|
}
|
||||||
|
|
||||||
|
cnt = 0;
|
||||||
|
tmpfile=out_dir "/.filelist"
|
||||||
|
for (instance = 1; instance < threads; instance++) {
|
||||||
|
for (i = 0; i < inputsperfile; i++) {
|
||||||
|
print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."instance
|
||||||
|
cnt++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (; cnt < in_count; cnt++) {
|
||||||
|
print in_dir"/"infilesSmallToBigFull[cnt] >> tmpfile"."threads
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
print "[*] Obtaining traces for "in_count" input files in '"in_dir"'."
|
print "[*] Obtaining traces for "in_count" input files in '"in_dir"'."
|
||||||
|
|
||||||
cur = 0;
|
cur = 0;
|
||||||
|
|
||||||
|
if (threads > 1) {
|
||||||
|
|
||||||
|
print "[*] Creating " threads " parallel tasks with about " inputsperfile " each."
|
||||||
|
for (i = 1; i <= threads; i++) {
|
||||||
|
|
||||||
|
if (!stdin_file) {
|
||||||
|
# print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &"
|
||||||
|
retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -- \""target_bin"\" "prog_args_string"; > "tmpfile"."i".done ; } &")
|
||||||
|
} else {
|
||||||
|
stdin_file=tmpfile"."i".stdin"
|
||||||
|
# print " { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null; > "tmpfile"."i".done ; } &"
|
||||||
|
retval = system(" { "AFL_MAP_SIZE AFL_CMIN_ALLOW_ANY AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -I \""tmpfile"."i"\" -H \""stdin_file"\" -- \""target_bin"\" "prog_args_string" </dev/null; > "tmpfile"."i".done ; } &")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "[*] Waiting for parallel tasks to complete ..."
|
||||||
|
# wait for all processes to finish
|
||||||
|
ok=0
|
||||||
|
while (ok < threads) {
|
||||||
|
ok=0
|
||||||
|
for (i = 1; i <= threads; i++) {
|
||||||
|
if (system("test -f "tmpfile"."i".done") == 0) {
|
||||||
|
ok++
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
print "[*] Done!"
|
||||||
|
system("rm -f "tmpfile"*")
|
||||||
|
} else {
|
||||||
if (!stdin_file) {
|
if (!stdin_file) {
|
||||||
print " Processing "in_count" files (forkserver mode)..."
|
print " Processing "in_count" files (forkserver mode)..."
|
||||||
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
|
# print AFL_CMIN_CRASHES_ONLY"\""showmap"\" -m "mem_limit" -t "timeout" -o \""trace_dir"\" -Z "extra_par" -i \""in_dir"\" -- \""target_bin"\" "prog_args_string
|
||||||
@ -482,6 +559,8 @@ BEGIN {
|
|||||||
exit retval
|
exit retval
|
||||||
}
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
#######################################################
|
#######################################################
|
||||||
# STEP 2: register smallest input file for each tuple #
|
# STEP 2: register smallest input file for each tuple #
|
||||||
# STEP 3: copy that file (at most once) #
|
# STEP 3: copy that file (at most once) #
|
||||||
|
112
afl-cmin.bash
112
afl-cmin.bash
@ -7,6 +7,8 @@
|
|||||||
#
|
#
|
||||||
# Copyright 2014, 2015 Google Inc. All rights reserved.
|
# Copyright 2014, 2015 Google Inc. All rights reserved.
|
||||||
#
|
#
|
||||||
|
# Copyright 2019-2023 AFLplusplus
|
||||||
|
#
|
||||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
# you may not use this file except in compliance with the License.
|
# you may not use this file except in compliance with the License.
|
||||||
# You may obtain a copy of the License at:
|
# You may obtain a copy of the License at:
|
||||||
@ -36,7 +38,7 @@
|
|||||||
# array sizes.
|
# array sizes.
|
||||||
#
|
#
|
||||||
|
|
||||||
echo "corpus minimization tool for afl-fuzz by Michal Zalewski"
|
echo "corpus minimization tool for afl-fuzz"
|
||||||
echo
|
echo
|
||||||
|
|
||||||
#########
|
#########
|
||||||
@ -46,14 +48,14 @@ echo
|
|||||||
# Process command-line options...
|
# Process command-line options...
|
||||||
|
|
||||||
MEM_LIMIT=none
|
MEM_LIMIT=none
|
||||||
TIMEOUT=none
|
TIMEOUT=5000
|
||||||
|
|
||||||
unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
|
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
|
AFL_CMIN_CRASHES_ONLY AFL_CMIN_ALLOW_ANY QEMU_MODE UNICORN_MODE T_ARG
|
||||||
|
|
||||||
export AFL_QUIET=1
|
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
|
case "$opt" in
|
||||||
|
|
||||||
@ -69,6 +71,7 @@ while getopts "+i:o:f:m:t:eOQUAChXY" opt; do
|
|||||||
;;
|
;;
|
||||||
"f")
|
"f")
|
||||||
STDIN_FILE="$OPTARG"
|
STDIN_FILE="$OPTARG"
|
||||||
|
F_ARG=1
|
||||||
;;
|
;;
|
||||||
"m")
|
"m")
|
||||||
MEM_LIMIT="$OPTARG"
|
MEM_LIMIT="$OPTARG"
|
||||||
@ -106,6 +109,9 @@ while getopts "+i:o:f:m:t:eOQUAChXY" opt; do
|
|||||||
EXTRA_PAR="$EXTRA_PAR -U"
|
EXTRA_PAR="$EXTRA_PAR -U"
|
||||||
UNICORN_MODE=1
|
UNICORN_MODE=1
|
||||||
;;
|
;;
|
||||||
|
"T")
|
||||||
|
T_ARG="$OPTARG"
|
||||||
|
;;
|
||||||
"?")
|
"?")
|
||||||
exit 1
|
exit 1
|
||||||
;;
|
;;
|
||||||
@ -130,9 +136,10 @@ Required parameters:
|
|||||||
|
|
||||||
Execution control settings:
|
Execution control settings:
|
||||||
|
|
||||||
-f file - location read by the fuzzed program (stdin)
|
-T tasks - how many parallel processes to create (default=1, "all"=nproc)
|
||||||
-m megs - memory limit for child process ($MEM_LIMIT MB)
|
-f file - location read by the fuzzed program (default: stdin)
|
||||||
-t msec - run time limit for child process (none)
|
-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)
|
-O - use binary-only instrumentation (FRIDA mode)
|
||||||
-Q - use binary-only instrumentation (QEMU mode)
|
-Q - use binary-only instrumentation (QEMU mode)
|
||||||
-U - use unicorn-based instrumentation (Unicorn mode)
|
-U - use unicorn-based instrumentation (Unicorn mode)
|
||||||
@ -199,6 +206,11 @@ fi
|
|||||||
|
|
||||||
# Check for obvious errors.
|
# Check for obvious errors.
|
||||||
|
|
||||||
|
if [ ! "$T_ARG" = "" -a ! "$F_ARG" = "" -a ! "$NYX_MODE" == 1 ]; then
|
||||||
|
echo "[-] Error: -T and -f can not be used together." 1>&2
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
if [ ! "$MEM_LIMIT" = "none" ]; then
|
if [ ! "$MEM_LIMIT" = "none" ]; then
|
||||||
|
|
||||||
if [ "$MEM_LIMIT" -lt "5" ]; then
|
if [ "$MEM_LIMIT" -lt "5" ]; then
|
||||||
@ -233,7 +245,7 @@ if [ "$NYX_MODE" = "" ]; then
|
|||||||
|
|
||||||
fi
|
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 ..."
|
echo "[!] Trying to obtain the map size of the target ..."
|
||||||
MAPSIZE=`AFL_DUMP_MAP_SIZE=1 "./$TARGET_BIN" 2>/dev/null`
|
MAPSIZE=`AFL_DUMP_MAP_SIZE=1 "./$TARGET_BIN" 2>/dev/null`
|
||||||
test -n "$MAPSIZE" && {
|
test -n "$MAPSIZE" && {
|
||||||
@ -299,14 +311,34 @@ if [ ! -x "$SHOWMAP" ]; then
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
THREADS=
|
||||||
|
if [ ! "$T_ARG" = "" ]; then
|
||||||
|
if [ "$T_ARG" = "all" ]; then
|
||||||
|
THREADS=$(nproc)
|
||||||
|
else
|
||||||
|
if [ "$T_ARG" -gt 1 -a "$T_ARG" -le "$(nproc)" ]; then
|
||||||
|
THREADS=$T_ARG
|
||||||
|
else
|
||||||
|
echo "[-] Error: -T parameter must between 2 and $(nproc) or \"all\"." 1>&2
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
else
|
||||||
|
if [ "$F_ARG" = ""]; then
|
||||||
|
echo "[*] Are you aware of the '-T all' parallelize option that massively improves the speed?"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`))
|
IN_COUNT=$((`ls -- "$IN_DIR" 2>/dev/null | wc -l`))
|
||||||
|
|
||||||
if [ "$IN_COUNT" = "0" ]; then
|
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"
|
rm -rf "$TRACE_DIR"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
echo "[*] Are you aware that afl-cmin is faster than this afl-cmin.bash script?"
|
||||||
|
echo "[+] Found $IN_COUNT files for minimizing."
|
||||||
|
|
||||||
FIRST_FILE=`ls "$IN_DIR" | head -1`
|
FIRST_FILE=`ls "$IN_DIR" | head -1`
|
||||||
|
|
||||||
# Make sure that we're not dealing with a directory.
|
# Make sure that we're not dealing with a directory.
|
||||||
@ -355,6 +387,18 @@ else
|
|||||||
|
|
||||||
fi
|
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!
|
# Let's roll!
|
||||||
|
|
||||||
#############################
|
#############################
|
||||||
@ -363,6 +407,7 @@ fi
|
|||||||
|
|
||||||
echo "[*] Obtaining traces for input files in '$IN_DIR'..."
|
echo "[*] Obtaining traces for input files in '$IN_DIR'..."
|
||||||
|
|
||||||
|
if [ "$THREADS" = "" ]; then
|
||||||
(
|
(
|
||||||
|
|
||||||
CUR=0
|
CUR=0
|
||||||
@ -386,17 +431,58 @@ echo "[*] Obtaining traces for input files in '$IN_DIR'..."
|
|||||||
printf "\\r Processing file $CUR/$IN_COUNT... "
|
printf "\\r Processing file $CUR/$IN_COUNT... "
|
||||||
|
|
||||||
cp "$IN_DIR/$fn" "$STDIN_FILE"
|
cp "$IN_DIR/$fn" "$STDIN_FILE"
|
||||||
|
|
||||||
"$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
|
"$SHOWMAP" -m "$MEM_LIMIT" -t "$TIMEOUT" -o "$TRACE_DIR/$fn" -Z $EXTRA_PAR -H "$STDIN_FILE" -- "$@" </dev/null
|
||||||
|
|
||||||
done
|
done
|
||||||
|
|
||||||
|
|
||||||
fi
|
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 #
|
# STEP 2: SORTING TUPLES #
|
||||||
|
7
custom_mutators/atnwalk/Makefile
Normal file
7
custom_mutators/atnwalk/Makefile
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
all: atnwalk.so
|
||||||
|
|
||||||
|
atnwalk.so: atnwalk.c
|
||||||
|
$(CC) -I ../../include/ -shared -fPIC -O3 -o atnwalk.so atnwalk.c
|
||||||
|
|
||||||
|
clean:
|
||||||
|
rm -f *.so *.o *~ core
|
@ -6,9 +6,7 @@ Refer to [https://github.com/atnwalk/testbed](https://github.com/atnwalk/testbed
|
|||||||
|
|
||||||
## Build
|
## Build
|
||||||
|
|
||||||
```bash
|
Just type `make` to build `atnwalk.so`.
|
||||||
gcc -I ../../include/ -shared -fPIC -Wall -O3 atnwalk.c -o atnwalk.so
|
|
||||||
```
|
|
||||||
|
|
||||||
## Run
|
## Run
|
||||||
|
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
#ifndef CUSTOM_MUTATOR_HELPERS
|
|
||||||
#define CUSTOM_MUTATOR_HELPERS
|
|
||||||
|
|
||||||
#include "config.h"
|
|
||||||
#include "types.h"
|
|
||||||
#include "afl-fuzz.h"
|
|
||||||
#include <stdlib.h>
|
|
||||||
|
|
||||||
#define INITIAL_GROWTH_SIZE (64)
|
|
||||||
|
|
||||||
/* Use in a struct: creates a name_buf and a name_size variable. */
|
|
||||||
#define BUF_VAR(type, name) \
|
|
||||||
type * name##_buf; \
|
|
||||||
size_t name##_size;
|
|
||||||
/* this filles in `&structptr->something_buf, &structptr->something_size`. */
|
|
||||||
#define BUF_PARAMS(struct, name) \
|
|
||||||
(void **)&struct->name##_buf, &struct->name##_size
|
|
||||||
|
|
||||||
#undef INITIAL_GROWTH_SIZE
|
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
|
||||||
#include "custom_mutator_helpers.h"
|
#include "afl-fuzz.h"
|
||||||
#include "mangle.h"
|
#include "mangle.h"
|
||||||
|
|
||||||
#define NUMBER_OF_MUTATIONS 5
|
#define NUMBER_OF_MUTATIONS 5
|
||||||
@ -65,7 +65,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
|||||||
/* When a new queue entry is added we check if there are new dictionary
|
/* When a new queue entry is added we check if there are new dictionary
|
||||||
entries to add to honggfuzz structure */
|
entries to add to honggfuzz structure */
|
||||||
|
|
||||||
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
void afl_custom_queue_new_entry(my_mutator_t *data,
|
||||||
const uint8_t *filename_new_queue,
|
const uint8_t *filename_new_queue,
|
||||||
const uint8_t *filename_orig_queue) {
|
const uint8_t *filename_orig_queue) {
|
||||||
|
|
||||||
@ -97,7 +97,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return 0;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,10 +40,15 @@
|
|||||||
#include "libhfcommon/util.h"
|
#include "libhfcommon/util.h"
|
||||||
|
|
||||||
static inline size_t mangle_LenLeft(run_t *run, size_t off) {
|
static inline size_t mangle_LenLeft(run_t *run, size_t off) {
|
||||||
|
|
||||||
if (off >= run->dynfile->size) {
|
if (off >= run->dynfile->size) {
|
||||||
|
|
||||||
LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
|
LOG_F("Offset is too large: off:%zu >= len:%zu", off, run->dynfile->size);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return (run->dynfile->size - off - 1);
|
return (run->dynfile->size - off - 1);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -51,46 +56,46 @@ static inline size_t mangle_LenLeft(run_t* run, size_t off) {
|
|||||||
* Based on an idea by https://twitter.com/gamozolabs
|
* Based on an idea by https://twitter.com/gamozolabs
|
||||||
*/
|
*/
|
||||||
static inline size_t mangle_getLen(size_t max) {
|
static inline size_t mangle_getLen(size_t max) {
|
||||||
|
|
||||||
if (max > _HF_INPUT_MAX_SIZE) {
|
if (max > _HF_INPUT_MAX_SIZE) {
|
||||||
LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max, (size_t)_HF_INPUT_MAX_SIZE);
|
|
||||||
}
|
LOG_F("max (%zu) > _HF_INPUT_MAX_SIZE (%zu)", max,
|
||||||
if (max == 0) {
|
(size_t)_HF_INPUT_MAX_SIZE);
|
||||||
LOG_F("max == 0");
|
|
||||||
}
|
|
||||||
if (max == 1) {
|
|
||||||
return 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (max == 0) { LOG_F("max == 0"); }
|
||||||
|
if (max == 1) { return 1; }
|
||||||
|
|
||||||
/* Give 50% chance the the uniform distribution */
|
/* Give 50% chance the the uniform distribution */
|
||||||
if (util_rnd64() & 1) {
|
if (util_rnd64() & 1) { return (size_t)util_rndGet(1, max); }
|
||||||
return (size_t)util_rndGet(1, max);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* effectively exprand() */
|
/* effectively exprand() */
|
||||||
return (size_t)util_rndGet(1, util_rndGet(1, max));
|
return (size_t)util_rndGet(1, util_rndGet(1, max));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prefer smaller values here, so use mangle_getLen() */
|
/* Prefer smaller values here, so use mangle_getLen() */
|
||||||
static inline size_t mangle_getOffSet(run_t *run) {
|
static inline size_t mangle_getOffSet(run_t *run) {
|
||||||
|
|
||||||
return mangle_getLen(run->dynfile->size) - 1;
|
return mangle_getLen(run->dynfile->size) - 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Offset which can be equal to the file size */
|
/* Offset which can be equal to the file size */
|
||||||
static inline size_t mangle_getOffSetPlus1(run_t *run) {
|
static inline size_t mangle_getOffSetPlus1(run_t *run) {
|
||||||
|
|
||||||
size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
|
size_t reqlen = HF_MIN(run->dynfile->size + 1, _HF_INPUT_MAX_SIZE);
|
||||||
return mangle_getLen(reqlen) - 1;
|
return mangle_getLen(reqlen) - 1;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_t len) {
|
static inline void mangle_Move(run_t *run, size_t off_from, size_t off_to,
|
||||||
if (off_from >= run->dynfile->size) {
|
size_t len) {
|
||||||
return;
|
|
||||||
}
|
if (off_from >= run->dynfile->size) { return; }
|
||||||
if (off_to >= run->dynfile->size) {
|
if (off_to >= run->dynfile->size) { return; }
|
||||||
return;
|
if (off_from == off_to) { return; }
|
||||||
}
|
|
||||||
if (off_from == off_to) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len_from = run->dynfile->size - off_from;
|
size_t len_from = run->dynfile->size - off_from;
|
||||||
len = HF_MIN(len, len_from);
|
len = HF_MIN(len, len_from);
|
||||||
@ -99,65 +104,79 @@ static inline void mangle_Move(run_t* run, size_t off_from, size_t off_to, size_
|
|||||||
len = HF_MIN(len, len_to);
|
len = HF_MIN(len, len_to);
|
||||||
|
|
||||||
memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
|
memmove(&run->dynfile->data[off_to], &run->dynfile->data[off_from], len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mangle_Overwrite(
|
static inline void mangle_Overwrite(run_t *run, size_t off, const uint8_t *src,
|
||||||
run_t* run, size_t off, const uint8_t* src, size_t len, bool printable) {
|
size_t len, bool printable) {
|
||||||
if (len == 0) {
|
|
||||||
return;
|
if (len == 0) { return; }
|
||||||
}
|
|
||||||
size_t maxToCopy = run->dynfile->size - off;
|
size_t maxToCopy = run->dynfile->size - off;
|
||||||
if (len > maxToCopy) {
|
if (len > maxToCopy) { len = maxToCopy; }
|
||||||
len = maxToCopy;
|
|
||||||
}
|
|
||||||
|
|
||||||
memmove(&run->dynfile->data[off], src, len);
|
memmove(&run->dynfile->data[off], src, len);
|
||||||
if (printable) {
|
if (printable) { util_turnToPrintable(&run->dynfile->data[off], len); }
|
||||||
util_turnToPrintable(&run->dynfile->data[off], len);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline size_t mangle_Inflate(run_t* run, size_t off, size_t len, bool printable) {
|
static inline size_t mangle_Inflate(run_t *run, size_t off, size_t len,
|
||||||
if (run->dynfile->size >= run->global->mutate.maxInputSz) {
|
bool printable) {
|
||||||
return 0;
|
|
||||||
}
|
if (run->dynfile->size >= run->global->mutate.maxInputSz) { return 0; }
|
||||||
if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
|
if (len > (run->global->mutate.maxInputSz - run->dynfile->size)) {
|
||||||
|
|
||||||
len = run->global->mutate.maxInputSz - run->dynfile->size;
|
len = run->global->mutate.maxInputSz - run->dynfile->size;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input_setSize(run, run->dynfile->size + len);
|
input_setSize(run, run->dynfile->size + len);
|
||||||
mangle_Move(run, off, off + len, run->dynfile->size);
|
mangle_Move(run, off, off + len, run->dynfile->size);
|
||||||
if (printable) {
|
if (printable) { memset(&run->dynfile->data[off], ' ', len); }
|
||||||
memset(&run->dynfile->data[off], ' ', len);
|
|
||||||
}
|
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mangle_Insert(
|
static inline void mangle_Insert(run_t *run, size_t off, const uint8_t *val,
|
||||||
run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
|
size_t len, bool printable) {
|
||||||
|
|
||||||
len = mangle_Inflate(run, off, len, printable);
|
len = mangle_Inflate(run, off, len, printable);
|
||||||
mangle_Overwrite(run, off, val, len, printable);
|
mangle_Overwrite(run, off, val, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mangle_UseValue(run_t* run, const uint8_t* val, size_t len, bool printable) {
|
static inline void mangle_UseValue(run_t *run, const uint8_t *val, size_t len,
|
||||||
|
bool printable) {
|
||||||
|
|
||||||
if (util_rnd64() & 1) {
|
if (util_rnd64() & 1) {
|
||||||
|
|
||||||
mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
|
mangle_Overwrite(run, mangle_getOffSet(run), val, len, printable);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
|
mangle_Insert(run, mangle_getOffSetPlus1(run), val, len, printable);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mangle_UseValueAt(
|
|
||||||
run_t* run, size_t off, const uint8_t* val, size_t len, bool printable) {
|
|
||||||
if (util_rnd64() & 1) {
|
|
||||||
mangle_Overwrite(run, off, val, len, printable);
|
|
||||||
} else {
|
|
||||||
mangle_Insert(run, off, val, len, printable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static inline void mangle_UseValueAt(run_t *run, size_t off, const uint8_t *val,
|
||||||
|
size_t len, bool printable) {
|
||||||
|
|
||||||
|
if (util_rnd64() & 1) {
|
||||||
|
|
||||||
|
mangle_Overwrite(run, off, val, len, printable);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
mangle_Insert(run, off, val, len, printable);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) {
|
static void mangle_MemSwap(run_t *run, bool printable HF_ATTR_UNUSED) {
|
||||||
|
|
||||||
/* No big deal if those two are overlapping */
|
/* No big deal if those two are overlapping */
|
||||||
size_t off1 = mangle_getOffSet(run);
|
size_t off1 = mangle_getOffSet(run);
|
||||||
size_t maxlen1 = run->dynfile->size - off1;
|
size_t maxlen1 = run->dynfile->size - off1;
|
||||||
@ -165,82 +184,105 @@ static void mangle_MemSwap(run_t* run, bool printable HF_ATTR_UNUSED) {
|
|||||||
size_t maxlen2 = run->dynfile->size - off2;
|
size_t maxlen2 = run->dynfile->size - off2;
|
||||||
size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
|
size_t len = mangle_getLen(HF_MIN(maxlen1, maxlen2));
|
||||||
|
|
||||||
if (off1 == off2) {
|
if (off1 == off2) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (size_t i = 0; i < (len / 2); i++) {
|
for (size_t i = 0; i < (len / 2); i++) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* First - from the head, next from the tail. Don't worry about layout of the overlapping
|
* First - from the head, next from the tail. Don't worry about layout of
|
||||||
* part - there's no good solution to that, and it can be left somewhat scrambled,
|
* the overlapping part - there's no good solution to that, and it can be
|
||||||
* while still preserving the entropy
|
* left somewhat scrambled, while still preserving the entropy
|
||||||
*/
|
*/
|
||||||
const uint8_t tmp1 = run->dynfile->data[off2 + i];
|
const uint8_t tmp1 = run->dynfile->data[off2 + i];
|
||||||
run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i];
|
run->dynfile->data[off2 + i] = run->dynfile->data[off1 + i];
|
||||||
run->dynfile->data[off1 + i] = tmp1;
|
run->dynfile->data[off1 + i] = tmp1;
|
||||||
const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i];
|
const uint8_t tmp2 = run->dynfile->data[off2 + (len - 1) - i];
|
||||||
run->dynfile->data[off2 + (len - 1) - i] = run->dynfile->data[off1 + (len - 1) - i];
|
run->dynfile->data[off2 + (len - 1) - i] =
|
||||||
|
run->dynfile->data[off1 + (len - 1) - i];
|
||||||
run->dynfile->data[off1 + (len - 1) - i] = tmp2;
|
run->dynfile->data[off1 + (len - 1) - i] = tmp2;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) {
|
static void mangle_MemCopy(run_t *run, bool printable HF_ATTR_UNUSED) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||||
|
|
||||||
/* Use a temp buf, as Insert/Inflate can change source bytes */
|
/* Use a temp buf, as Insert/Inflate can change source bytes */
|
||||||
uint8_t *tmpbuf = (uint8_t *)util_Malloc(len);
|
uint8_t *tmpbuf = (uint8_t *)util_Malloc(len);
|
||||||
defer {
|
defer {
|
||||||
|
|
||||||
free(tmpbuf);
|
free(tmpbuf);
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
memmove(tmpbuf, &run->dynfile->data[off], len);
|
memmove(tmpbuf, &run->dynfile->data[off], len);
|
||||||
|
|
||||||
mangle_UseValue(run, tmpbuf, len, printable);
|
mangle_UseValue(run, tmpbuf, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_Bytes(run_t *run, bool printable) {
|
static void mangle_Bytes(run_t *run, bool printable) {
|
||||||
|
|
||||||
uint16_t buf;
|
uint16_t buf;
|
||||||
if (printable) {
|
if (printable) {
|
||||||
|
|
||||||
util_rndBufPrintable((uint8_t *)&buf, sizeof(buf));
|
util_rndBufPrintable((uint8_t *)&buf, sizeof(buf));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
buf = util_rnd64();
|
buf = util_rnd64();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Overwrite with random 1-2-byte values */
|
/* Overwrite with random 1-2-byte values */
|
||||||
size_t toCopy = util_rndGet(1, 2);
|
size_t toCopy = util_rndGet(1, 2);
|
||||||
mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable);
|
mangle_UseValue(run, (const uint8_t *)&buf, toCopy, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_ByteRepeat(run_t *run, bool printable) {
|
static void mangle_ByteRepeat(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
size_t destOff = off + 1;
|
size_t destOff = off + 1;
|
||||||
size_t maxSz = run->dynfile->size - destOff;
|
size_t maxSz = run->dynfile->size - destOff;
|
||||||
|
|
||||||
/* No space to repeat */
|
/* No space to repeat */
|
||||||
if (!maxSz) {
|
if (!maxSz) {
|
||||||
|
|
||||||
mangle_Bytes(run, printable);
|
mangle_Bytes(run, printable);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t len = mangle_getLen(maxSz);
|
size_t len = mangle_getLen(maxSz);
|
||||||
if (util_rnd64() & 0x1) {
|
if (util_rnd64() & 0x1) {
|
||||||
|
|
||||||
len = mangle_Inflate(run, destOff, len, printable);
|
len = mangle_Inflate(run, destOff, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
|
memset(&run->dynfile->data[destOff], run->dynfile->data[off], len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_Bit(run_t *run, bool printable) {
|
static void mangle_Bit(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
|
run->dynfile->data[off] ^= (uint8_t)(1U << util_rndGet(0, 7));
|
||||||
if (printable) {
|
if (printable) { util_turnToPrintable(&(run->dynfile->data[off]), 1); }
|
||||||
util_turnToPrintable(&(run->dynfile->data[off]), 1);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static const struct {
|
static const struct {
|
||||||
|
|
||||||
const uint8_t val[8];
|
const uint8_t val[8];
|
||||||
const size_t size;
|
const size_t size;
|
||||||
|
|
||||||
} mangleMagicVals[] = {
|
} mangleMagicVals[] = {
|
||||||
|
|
||||||
/* 1B - No endianness */
|
/* 1B - No endianness */
|
||||||
{"\x00\x00\x00\x00\x00\x00\x00\x00", 1},
|
{"\x00\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||||
{"\x01\x00\x00\x00\x00\x00\x00\x00", 1},
|
{"\x01\x00\x00\x00\x00\x00\x00\x00", 1},
|
||||||
@ -472,160 +514,206 @@ static const struct {
|
|||||||
{"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
|
{"\x00\x00\x00\x00\x00\x00\x00\x80", 8},
|
||||||
{"\x01\x00\x00\x00\x00\x00\x00\x80", 8},
|
{"\x01\x00\x00\x00\x00\x00\x00\x80", 8},
|
||||||
{"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
|
{"\xFE\xFF\xFF\xFF\xFF\xFF\xFF\xFF", 8},
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static void mangle_Magic(run_t *run, bool printable) {
|
static void mangle_Magic(run_t *run, bool printable) {
|
||||||
|
|
||||||
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
|
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleMagicVals) - 1);
|
||||||
mangle_UseValue(run, mangleMagicVals[choice].val, mangleMagicVals[choice].size, printable);
|
mangle_UseValue(run, mangleMagicVals[choice].val,
|
||||||
|
mangleMagicVals[choice].size, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_StaticDict(run_t *run, bool printable) {
|
static void mangle_StaticDict(run_t *run, bool printable) {
|
||||||
|
|
||||||
if (run->global->mutate.dictionaryCnt == 0) {
|
if (run->global->mutate.dictionaryCnt == 0) {
|
||||||
|
|
||||||
mangle_Bytes(run, printable);
|
mangle_Bytes(run, printable);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
|
uint64_t choice = util_rndGet(0, run->global->mutate.dictionaryCnt - 1);
|
||||||
mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
|
mangle_UseValue(run, run->global->mutate.dictionary[choice].val,
|
||||||
run->global->mutate.dictionary[choice].len, printable);
|
run->global->mutate.dictionary[choice].len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) {
|
static inline const uint8_t *mangle_FeedbackDict(run_t *run, size_t *len) {
|
||||||
if (!run->global->feedback.cmpFeedback) {
|
|
||||||
return NULL;
|
if (!run->global->feedback.cmpFeedback) { return NULL; }
|
||||||
}
|
|
||||||
cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap;
|
cmpfeedback_t *cmpf = run->global->feedback.cmpFeedbackMap;
|
||||||
uint32_t cnt = ATOMIC_GET(cmpf->cnt);
|
uint32_t cnt = ATOMIC_GET(cmpf->cnt);
|
||||||
if (cnt == 0) {
|
if (cnt == 0) { return NULL; }
|
||||||
return NULL;
|
if (cnt > ARRAYSIZE(cmpf->valArr)) { cnt = ARRAYSIZE(cmpf->valArr); }
|
||||||
}
|
|
||||||
if (cnt > ARRAYSIZE(cmpf->valArr)) {
|
|
||||||
cnt = ARRAYSIZE(cmpf->valArr);
|
|
||||||
}
|
|
||||||
uint32_t choice = util_rndGet(0, cnt - 1);
|
uint32_t choice = util_rndGet(0, cnt - 1);
|
||||||
*len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
|
*len = (size_t)ATOMIC_GET(cmpf->valArr[choice].len);
|
||||||
if (*len == 0) {
|
if (*len == 0) { return NULL; }
|
||||||
return NULL;
|
|
||||||
}
|
|
||||||
return cmpf->valArr[choice].val;
|
return cmpf->valArr[choice].val;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_ConstFeedbackDict(run_t *run, bool printable) {
|
static void mangle_ConstFeedbackDict(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t len;
|
size_t len;
|
||||||
const uint8_t *val = mangle_FeedbackDict(run, &len);
|
const uint8_t *val = mangle_FeedbackDict(run, &len);
|
||||||
if (val == NULL) {
|
if (val == NULL) {
|
||||||
|
|
||||||
mangle_Bytes(run, printable);
|
mangle_Bytes(run, printable);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_UseValue(run, val, len, printable);
|
mangle_UseValue(run, val, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_MemSet(run_t *run, bool printable) {
|
static void mangle_MemSet(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||||
int val = printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
|
int val =
|
||||||
|
printable ? (int)util_rndPrintable() : (int)util_rndGet(0, UINT8_MAX);
|
||||||
|
|
||||||
if (util_rnd64() & 1) {
|
if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); }
|
||||||
len = mangle_Inflate(run, off, len, printable);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&run->dynfile->data[off], val, len);
|
memset(&run->dynfile->data[off], val, len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_MemClr(run_t *run, bool printable) {
|
static void mangle_MemClr(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||||
int val = printable ? ' ' : 0;
|
int val = printable ? ' ' : 0;
|
||||||
|
|
||||||
if (util_rnd64() & 1) {
|
if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); }
|
||||||
len = mangle_Inflate(run, off, len, printable);
|
|
||||||
}
|
|
||||||
|
|
||||||
memset(&run->dynfile->data[off], val, len);
|
memset(&run->dynfile->data[off], val, len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_RandomBuf(run_t *run, bool printable) {
|
static void mangle_RandomBuf(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
size_t len = mangle_getLen(run->dynfile->size - off);
|
size_t len = mangle_getLen(run->dynfile->size - off);
|
||||||
|
|
||||||
if (util_rnd64() & 1) {
|
if (util_rnd64() & 1) { len = mangle_Inflate(run, off, len, printable); }
|
||||||
len = mangle_Inflate(run, off, len, printable);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (printable) {
|
if (printable) {
|
||||||
|
|
||||||
util_rndBufPrintable(&run->dynfile->data[off], len);
|
util_rndBufPrintable(&run->dynfile->data[off], len);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
util_rndBuf(&run->dynfile->data[off], len);
|
util_rndBuf(&run->dynfile->data[off], len);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void mangle_AddSubWithRange(
|
}
|
||||||
run_t* run, size_t off, size_t varLen, uint64_t range, bool printable) {
|
|
||||||
|
static inline void mangle_AddSubWithRange(run_t *run, size_t off, size_t varLen,
|
||||||
|
uint64_t range, bool printable) {
|
||||||
|
|
||||||
int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
|
int64_t delta = (int64_t)util_rndGet(0, range * 2) - (int64_t)range;
|
||||||
|
|
||||||
switch (varLen) {
|
switch (varLen) {
|
||||||
|
|
||||||
case 1: {
|
case 1: {
|
||||||
|
|
||||||
run->dynfile->data[off] += delta;
|
run->dynfile->data[off] += delta;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 2: {
|
case 2: {
|
||||||
|
|
||||||
int16_t val;
|
int16_t val;
|
||||||
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
||||||
if (util_rnd64() & 0x1) {
|
if (util_rnd64() & 0x1) {
|
||||||
|
|
||||||
val += delta;
|
val += delta;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Foreign endianess */
|
/* Foreign endianess */
|
||||||
val = __builtin_bswap16(val);
|
val = __builtin_bswap16(val);
|
||||||
val += delta;
|
val += delta;
|
||||||
val = __builtin_bswap16(val);
|
val = __builtin_bswap16(val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
|
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 4: {
|
case 4: {
|
||||||
|
|
||||||
int32_t val;
|
int32_t val;
|
||||||
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
||||||
if (util_rnd64() & 0x1) {
|
if (util_rnd64() & 0x1) {
|
||||||
|
|
||||||
val += delta;
|
val += delta;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Foreign endianess */
|
/* Foreign endianess */
|
||||||
val = __builtin_bswap32(val);
|
val = __builtin_bswap32(val);
|
||||||
val += delta;
|
val += delta;
|
||||||
val = __builtin_bswap32(val);
|
val = __builtin_bswap32(val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
|
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
case 8: {
|
case 8: {
|
||||||
|
|
||||||
int64_t val;
|
int64_t val;
|
||||||
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
memcpy(&val, &run->dynfile->data[off], sizeof(val));
|
||||||
if (util_rnd64() & 0x1) {
|
if (util_rnd64() & 0x1) {
|
||||||
|
|
||||||
val += delta;
|
val += delta;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
/* Foreign endianess */
|
/* Foreign endianess */
|
||||||
val = __builtin_bswap64(val);
|
val = __builtin_bswap64(val);
|
||||||
val += delta;
|
val += delta;
|
||||||
val = __builtin_bswap64(val);
|
val = __builtin_bswap64(val);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
|
mangle_Overwrite(run, off, (uint8_t *)&val, varLen, printable);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
default: {
|
default: {
|
||||||
|
|
||||||
LOG_F("Unknown variable length size: %zu", varLen);
|
LOG_F("Unknown variable length size: %zu", varLen);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_AddSub(run_t *run, bool printable) {
|
static void mangle_AddSub(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
|
|
||||||
/* 1,2,4,8 */
|
/* 1,2,4,8 */
|
||||||
size_t varLen = 1U << util_rndGet(0, 3);
|
size_t varLen = 1U << util_rndGet(0, 3);
|
||||||
if ((run->dynfile->size - off) < varLen) {
|
if ((run->dynfile->size - off) < varLen) { varLen = 1; }
|
||||||
varLen = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
uint64_t range;
|
uint64_t range;
|
||||||
switch (varLen) {
|
switch (varLen) {
|
||||||
|
|
||||||
case 1:
|
case 1:
|
||||||
range = 16;
|
range = 16;
|
||||||
break;
|
break;
|
||||||
@ -640,107 +728,140 @@ static void mangle_AddSub(run_t* run, bool printable) {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_F("Invalid operand size: %zu", varLen);
|
LOG_F("Invalid operand size: %zu", varLen);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_AddSubWithRange(run, off, varLen, range, printable);
|
mangle_AddSubWithRange(run, off, varLen, range, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_IncByte(run_t *run, bool printable) {
|
static void mangle_IncByte(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
if (printable) {
|
if (printable) {
|
||||||
|
|
||||||
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
|
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 1) % 95 + 32;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
run->dynfile->data[off] += (uint8_t)1UL;
|
run->dynfile->data[off] += (uint8_t)1UL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_DecByte(run_t *run, bool printable) {
|
static void mangle_DecByte(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
if (printable) {
|
if (printable) {
|
||||||
|
|
||||||
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
|
run->dynfile->data[off] = (run->dynfile->data[off] - 32 + 94) % 95 + 32;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
run->dynfile->data[off] -= (uint8_t)1UL;
|
run->dynfile->data[off] -= (uint8_t)1UL;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_NegByte(run_t *run, bool printable) {
|
static void mangle_NegByte(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
if (printable) {
|
if (printable) {
|
||||||
|
|
||||||
run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
|
run->dynfile->data[off] = 94 - (run->dynfile->data[off] - 32) + 32;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
run->dynfile->data[off] = ~(run->dynfile->data[off]);
|
run->dynfile->data[off] = ~(run->dynfile->data[off]);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_Expand(run_t *run, bool printable) {
|
static void mangle_Expand(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
size_t len;
|
size_t len;
|
||||||
if (util_rnd64() % 16) {
|
if (util_rnd64() % 16) {
|
||||||
|
|
||||||
len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
|
len = mangle_getLen(HF_MIN(16, run->global->mutate.maxInputSz - off));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
len = mangle_getLen(run->global->mutate.maxInputSz - off);
|
len = mangle_getLen(run->global->mutate.maxInputSz - off);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mangle_Inflate(run, off, len, printable);
|
mangle_Inflate(run, off, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) {
|
static void mangle_Shrink(run_t *run, bool printable HF_ATTR_UNUSED) {
|
||||||
if (run->dynfile->size <= 2U) {
|
|
||||||
return;
|
if (run->dynfile->size <= 2U) { return; }
|
||||||
}
|
|
||||||
|
|
||||||
size_t off_start = mangle_getOffSet(run);
|
size_t off_start = mangle_getOffSet(run);
|
||||||
size_t len = mangle_LenLeft(run, off_start);
|
size_t len = mangle_LenLeft(run, off_start);
|
||||||
if (len == 0) {
|
if (len == 0) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (util_rnd64() % 16) {
|
if (util_rnd64() % 16) {
|
||||||
|
|
||||||
len = mangle_getLen(HF_MIN(16, len));
|
len = mangle_getLen(HF_MIN(16, len));
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
len = mangle_getLen(len);
|
len = mangle_getLen(len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t off_end = off_start + len;
|
size_t off_end = off_start + len;
|
||||||
size_t len_to_move = run->dynfile->size - off_end;
|
size_t len_to_move = run->dynfile->size - off_end;
|
||||||
|
|
||||||
mangle_Move(run, off_end, off_start, len_to_move);
|
mangle_Move(run, off_end, off_start, len_to_move);
|
||||||
input_setSize(run, run->dynfile->size - len);
|
input_setSize(run, run->dynfile->size - len);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_ASCIINum(run_t *run, bool printable) {
|
static void mangle_ASCIINum(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t len = util_rndGet(2, 8);
|
size_t len = util_rndGet(2, 8);
|
||||||
|
|
||||||
char buf[20];
|
char buf[20];
|
||||||
snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
|
snprintf(buf, sizeof(buf), "%-19" PRId64, (int64_t)util_rnd64());
|
||||||
|
|
||||||
mangle_UseValue(run, (const uint8_t *)buf, len, printable);
|
mangle_UseValue(run, (const uint8_t *)buf, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_ASCIINumChange(run_t *run, bool printable) {
|
static void mangle_ASCIINumChange(run_t *run, bool printable) {
|
||||||
|
|
||||||
size_t off = mangle_getOffSet(run);
|
size_t off = mangle_getOffSet(run);
|
||||||
|
|
||||||
/* Find a digit */
|
/* Find a digit */
|
||||||
for (; off < run->dynfile->size; off++) {
|
for (; off < run->dynfile->size; off++) {
|
||||||
if (isdigit(run->dynfile->data[off])) {
|
|
||||||
break;
|
if (isdigit(run->dynfile->data[off])) { break; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t left = run->dynfile->size - off;
|
size_t left = run->dynfile->size - off;
|
||||||
if (left == 0) {
|
if (left == 0) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
size_t len = 0;
|
size_t len = 0;
|
||||||
uint64_t val = 0;
|
uint64_t val = 0;
|
||||||
/* 20 is maximum lenght of a string representing a 64-bit unsigned value */
|
/* 20 is maximum lenght of a string representing a 64-bit unsigned value */
|
||||||
for (len = 0; (len < 20) && (len < left); len++) {
|
for (len = 0; (len < 20) && (len < left); len++) {
|
||||||
|
|
||||||
char c = run->dynfile->data[off + len];
|
char c = run->dynfile->data[off + len];
|
||||||
if (!isdigit(c)) {
|
if (!isdigit(c)) { break; }
|
||||||
break;
|
|
||||||
}
|
|
||||||
val *= 10;
|
val *= 10;
|
||||||
val += (c - '0');
|
val += (c - '0');
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (util_rndGet(0, 7)) {
|
switch (util_rndGet(0, 7)) {
|
||||||
|
|
||||||
case 0:
|
case 0:
|
||||||
val++;
|
val++;
|
||||||
break;
|
break;
|
||||||
@ -767,43 +888,56 @@ static void mangle_ASCIINumChange(run_t* run, bool printable) {
|
|||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
LOG_F("Invalid choice");
|
LOG_F("Invalid choice");
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
char buf[20];
|
char buf[20];
|
||||||
snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
|
snprintf(buf, sizeof(buf), "%-19" PRIu64, val);
|
||||||
|
|
||||||
mangle_UseValueAt(run, off, (const uint8_t *)buf, len, printable);
|
mangle_UseValueAt(run, off, (const uint8_t *)buf, len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_Splice(run_t *run, bool printable) {
|
static void mangle_Splice(run_t *run, bool printable) {
|
||||||
|
|
||||||
if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
|
if (run->global->feedback.dynFileMethod == _HF_DYNFILE_NONE) {
|
||||||
|
|
||||||
mangle_Bytes(run, printable);
|
mangle_Bytes(run, printable);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t sz = 0;
|
size_t sz = 0;
|
||||||
const uint8_t *buf = input_getRandomInputAsBuf(run, &sz);
|
const uint8_t *buf = input_getRandomInputAsBuf(run, &sz);
|
||||||
if (!buf) {
|
if (!buf) {
|
||||||
|
|
||||||
LOG_E("input_getRandomInputAsBuf() returned no input");
|
LOG_E("input_getRandomInputAsBuf() returned no input");
|
||||||
mangle_Bytes(run, printable);
|
mangle_Bytes(run, printable);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sz) {
|
if (!sz) {
|
||||||
|
|
||||||
mangle_Bytes(run, printable);
|
mangle_Bytes(run, printable);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
size_t remoteOff = mangle_getLen(sz) - 1;
|
size_t remoteOff = mangle_getLen(sz) - 1;
|
||||||
size_t len = mangle_getLen(sz - remoteOff);
|
size_t len = mangle_getLen(sz - remoteOff);
|
||||||
mangle_UseValue(run, &buf[remoteOff], len, printable);
|
mangle_UseValue(run, &buf[remoteOff], len, printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void mangle_Resize(run_t *run, bool printable) {
|
static void mangle_Resize(run_t *run, bool printable) {
|
||||||
|
|
||||||
ssize_t oldsz = run->dynfile->size;
|
ssize_t oldsz = run->dynfile->size;
|
||||||
ssize_t newsz = 0;
|
ssize_t newsz = 0;
|
||||||
|
|
||||||
uint64_t choice = util_rndGet(0, 32);
|
uint64_t choice = util_rndGet(0, 32);
|
||||||
switch (choice) {
|
switch (choice) {
|
||||||
|
|
||||||
case 0: /* Set new size arbitrarily */
|
case 0: /* Set new size arbitrarily */
|
||||||
newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
|
newsz = (ssize_t)util_rndGet(1, run->global->mutate.maxInputSz);
|
||||||
break;
|
break;
|
||||||
@ -825,83 +959,98 @@ static void mangle_Resize(run_t* run, bool printable) {
|
|||||||
default:
|
default:
|
||||||
LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
|
LOG_F("Illegal value from util_rndGet: %" PRIu64, choice);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
if (newsz < 1) {
|
|
||||||
newsz = 1;
|
if (newsz < 1) { newsz = 1; }
|
||||||
}
|
|
||||||
if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
|
if (newsz > (ssize_t)run->global->mutate.maxInputSz) {
|
||||||
|
|
||||||
newsz = run->global->mutate.maxInputSz;
|
newsz = run->global->mutate.maxInputSz;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
input_setSize(run, (size_t)newsz);
|
input_setSize(run, (size_t)newsz);
|
||||||
if (newsz > oldsz) {
|
if (newsz > oldsz) {
|
||||||
if (printable) {
|
|
||||||
memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz);
|
if (printable) { memset(&run->dynfile->data[oldsz], ' ', newsz - oldsz); }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void mangle_mangleContent(run_t *run, int speed_factor) {
|
void mangle_mangleContent(run_t *run, int speed_factor) {
|
||||||
|
|
||||||
static void (*const mangleFuncs[])(run_t * run, bool printable) = {
|
static void (*const mangleFuncs[])(run_t * run, bool printable) = {
|
||||||
mangle_Shrink,
|
|
||||||
mangle_Expand,
|
mangle_Shrink, mangle_Expand, mangle_Bit,
|
||||||
mangle_Bit,
|
mangle_IncByte, mangle_DecByte, mangle_NegByte,
|
||||||
mangle_IncByte,
|
mangle_AddSub, mangle_MemSet, mangle_MemClr,
|
||||||
mangle_DecByte,
|
mangle_MemSwap, mangle_MemCopy, mangle_Bytes,
|
||||||
mangle_NegByte,
|
mangle_ASCIINum, mangle_ASCIINumChange, mangle_ByteRepeat,
|
||||||
mangle_AddSub,
|
mangle_Magic, mangle_StaticDict, mangle_ConstFeedbackDict,
|
||||||
mangle_MemSet,
|
mangle_RandomBuf, mangle_Splice,
|
||||||
mangle_MemClr,
|
|
||||||
mangle_MemSwap,
|
|
||||||
mangle_MemCopy,
|
|
||||||
mangle_Bytes,
|
|
||||||
mangle_ASCIINum,
|
|
||||||
mangle_ASCIINumChange,
|
|
||||||
mangle_ByteRepeat,
|
|
||||||
mangle_Magic,
|
|
||||||
mangle_StaticDict,
|
|
||||||
mangle_ConstFeedbackDict,
|
|
||||||
mangle_RandomBuf,
|
|
||||||
mangle_Splice,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (run->mutationsPerRun == 0U) {
|
if (run->mutationsPerRun == 0U) { return; }
|
||||||
return;
|
|
||||||
}
|
|
||||||
if (run->dynfile->size == 0U) {
|
if (run->dynfile->size == 0U) {
|
||||||
|
|
||||||
mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
|
mangle_Resize(run, /* printable= */ run->global->cfg.only_printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t changesCnt = run->global->mutate.mutationsPerRun;
|
uint64_t changesCnt = run->global->mutate.mutationsPerRun;
|
||||||
|
|
||||||
if (speed_factor < 5) {
|
if (speed_factor < 5) {
|
||||||
|
|
||||||
changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
|
changesCnt = util_rndGet(1, run->global->mutate.mutationsPerRun);
|
||||||
|
|
||||||
} else if (speed_factor < 10) {
|
} else if (speed_factor < 10) {
|
||||||
|
|
||||||
changesCnt = run->global->mutate.mutationsPerRun;
|
changesCnt = run->global->mutate.mutationsPerRun;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
changesCnt = HF_MIN(speed_factor, 10);
|
changesCnt = HF_MIN(speed_factor, 10);
|
||||||
changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
|
changesCnt = HF_MAX(changesCnt, (run->global->mutate.mutationsPerRun * 5));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* If last coverage acquisition was more than 5 secs ago, use splicing more frequently */
|
/* If last coverage acquisition was more than 5 secs ago, use splicing more
|
||||||
|
* frequently */
|
||||||
if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
|
if ((time(NULL) - ATOMIC_GET(run->global->timing.lastCovUpdate)) > 5) {
|
||||||
|
|
||||||
if (util_rnd64() & 0x1) {
|
if (util_rnd64() & 0x1) {
|
||||||
|
|
||||||
mangle_Splice(run, run->global->cfg.only_printable);
|
mangle_Splice(run, run->global->cfg.only_printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for (uint64_t x = 0; x < changesCnt; x++) {
|
for (uint64_t x = 0; x < changesCnt; x++) {
|
||||||
|
|
||||||
if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
|
if (run->global->feedback.cmpFeedback && (util_rnd64() & 0x1)) {
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback dictionary
|
* mangle_ConstFeedbackDict() is quite powerful if the dynamic feedback
|
||||||
* exists. If so, give it 50% chance of being used among all mangling functions.
|
* dictionary exists. If so, give it 50% chance of being used among all
|
||||||
|
* mangling functions.
|
||||||
*/
|
*/
|
||||||
mangle_ConstFeedbackDict(run, /* printable= */ run->global->cfg.only_printable);
|
mangle_ConstFeedbackDict(
|
||||||
|
run, /* printable= */ run->global->cfg.only_printable);
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
|
uint64_t choice = util_rndGet(0, ARRAYSIZE(mangleFuncs) - 1);
|
||||||
mangleFuncs[choice](run, /* printable= */ run->global->cfg.only_printable);
|
mangleFuncs[choice](run,
|
||||||
|
/* printable= */ run->global->cfg.only_printable);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
wmb();
|
wmb();
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +0,0 @@
|
|||||||
../examples/custom_mutator_helpers.h
|
|
@ -1,6 +1,5 @@
|
|||||||
// This simple example just creates random buffer <= 100 filled with 'A'
|
// This simple example just creates random buffer <= 100 filled with 'A'
|
||||||
// needs -I /path/to/AFLplusplus/include
|
// needs -I /path/to/AFLplusplus/include
|
||||||
//#include "custom_mutator_helpers.h"
|
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
@ -8,19 +7,17 @@
|
|||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#include "radamsa.h"
|
#include "radamsa.h"
|
||||||
#include "custom_mutator_helpers.h"
|
#include "afl-fuzz.h"
|
||||||
|
|
||||||
typedef struct my_mutator {
|
typedef struct my_mutator {
|
||||||
|
|
||||||
afl_t *afl;
|
afl_state_t *afl;
|
||||||
|
|
||||||
u8 *mutator_buf;
|
u8 *mutator_buf;
|
||||||
|
|
||||||
unsigned int seed;
|
unsigned int seed;
|
||||||
|
|
||||||
} my_mutator_t;
|
} my_mutator_t;
|
||||||
|
|
||||||
my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
|
my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||||
|
|
||||||
srand(seed);
|
srand(seed);
|
||||||
my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
|
my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
|
||||||
|
@ -5,10 +5,19 @@
|
|||||||
|
|
||||||
### Version ++4.07a (dev)
|
### Version ++4.07a (dev)
|
||||||
- afl-fuzz:
|
- afl-fuzz:
|
||||||
|
- reverse reading the seeds only on restarts (increases performance)
|
||||||
- new env `AFL_POST_PROCESS_KEEP_ORIGINAL` to keep the orignal
|
- new env `AFL_POST_PROCESS_KEEP_ORIGINAL` to keep the orignal
|
||||||
data before post process on finds
|
data before post process on finds (for atnwalk custom mutator)
|
||||||
|
- new env `AFL_IGNORE_PROBLEMS_COVERAGE` to ignore coverage from
|
||||||
|
loaded libs after forkserver initialization (required by Mozilla)
|
||||||
|
- afl-cc:
|
||||||
|
- new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM
|
||||||
|
(https://github.com/fgsect/WAFL) project
|
||||||
- afl-showmap:
|
- afl-showmap:
|
||||||
- added custom mutator post_process and send support
|
- added custom mutator post_process and send support
|
||||||
|
- add `-I filelist` option, an alternative to `-i in_dir`
|
||||||
|
- afl-cmin + afl-cmin.bash:
|
||||||
|
- `-T threads` parallel task support, can be a huge speedup!
|
||||||
- a new grammar custom mutator atnwalk was submitted by @voidptr127 !
|
- a new grammar custom mutator atnwalk was submitted by @voidptr127 !
|
||||||
|
|
||||||
|
|
||||||
|
@ -229,7 +229,8 @@ If you find an interesting or important question missing, submit it via
|
|||||||
If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then
|
If this is not a viable option, you can set `AFL_IGNORE_PROBLEMS=1` but then
|
||||||
the existing map will be used also for the newly loaded libraries, which
|
the existing map will be used also for the newly loaded libraries, which
|
||||||
allows it to work, however, the efficiency of the fuzzing will be partially
|
allows it to work, however, the efficiency of the fuzzing will be partially
|
||||||
degraded.
|
degraded. Note that there is additionally `AFL_IGNORE_PROBLEMS_COVERAGE` to
|
||||||
|
additionally tell AFL++ to ignore any coverage from the late loaded libaries.
|
||||||
</p></details>
|
</p></details>
|
||||||
|
|
||||||
<details>
|
<details>
|
||||||
|
@ -156,7 +156,7 @@ Available options:
|
|||||||
- LTO - LTO instrumentation
|
- LTO - LTO instrumentation
|
||||||
- NATIVE - clang's original pcguard based instrumentation
|
- NATIVE - clang's original pcguard based instrumentation
|
||||||
- NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16)
|
- NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16)
|
||||||
- PCGUARD - our own pcgard based instrumentation (default)
|
- PCGUARD - our own pcguard based instrumentation (default)
|
||||||
|
|
||||||
#### CMPLOG
|
#### CMPLOG
|
||||||
|
|
||||||
@ -240,7 +240,9 @@ combined.
|
|||||||
the default `0x10000`. A value of 0 or empty sets the map address to be
|
the default `0x10000`. A value of 0 or empty sets the map address to be
|
||||||
dynamic (the original AFL way, which is slower).
|
dynamic (the original AFL way, which is slower).
|
||||||
- `AFL_LLVM_MAP_DYNAMIC` sets the shared memory address to be dynamic.
|
- `AFL_LLVM_MAP_DYNAMIC` sets the shared memory address to be dynamic.
|
||||||
|
- `AFL_LLVM_LTO_SKIPINIT` skips adding initialization code. Some global vars
|
||||||
|
(e.g. the highest location ID) are not injected. Needed to instrument with
|
||||||
|
[WAFL](https://github.com/fgsect/WAFL.git).
|
||||||
For more information, see
|
For more information, see
|
||||||
[instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
[instrumentation/README.lto.md](../instrumentation/README.lto.md).
|
||||||
|
|
||||||
@ -404,7 +406,8 @@ checks or alter some of the more exotic semantics of the tool:
|
|||||||
|
|
||||||
- If afl-fuzz encounters an incorrect fuzzing setup during a fuzzing session
|
- If afl-fuzz encounters an incorrect fuzzing setup during a fuzzing session
|
||||||
(not at startup), it will terminate. If you do not want this, then you can
|
(not at startup), it will terminate. If you do not want this, then you can
|
||||||
set `AFL_IGNORE_PROBLEMS`.
|
set `AFL_IGNORE_PROBLEMS`. If you additionally want to also ignore coverage
|
||||||
|
from late loaded libraries, you can set `AFL_IGNORE_PROBLEMS_COVERAGE`.
|
||||||
|
|
||||||
- When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the
|
- When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the
|
||||||
fuzzer to import test cases from other instances before doing anything else.
|
fuzzer to import test cases from other instances before doing anything else.
|
||||||
|
@ -106,6 +106,7 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_HARDEN",
|
"AFL_HARDEN",
|
||||||
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES",
|
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES",
|
||||||
"AFL_IGNORE_PROBLEMS",
|
"AFL_IGNORE_PROBLEMS",
|
||||||
|
"AFL_IGNORE_PROBLEMS_COVERAGE",
|
||||||
"AFL_IGNORE_TIMEOUTS",
|
"AFL_IGNORE_TIMEOUTS",
|
||||||
"AFL_IGNORE_UNKNOWN_ENVS",
|
"AFL_IGNORE_UNKNOWN_ENVS",
|
||||||
"AFL_IMPORT_FIRST",
|
"AFL_IMPORT_FIRST",
|
||||||
@ -160,8 +161,9 @@ static char *afl_environment_variables[] = {
|
|||||||
"AFL_LLVM_SKIP_NEVERZERO",
|
"AFL_LLVM_SKIP_NEVERZERO",
|
||||||
"AFL_NO_AFFINITY",
|
"AFL_NO_AFFINITY",
|
||||||
"AFL_TRY_AFFINITY",
|
"AFL_TRY_AFFINITY",
|
||||||
"AFL_LLVM_LTO_STARTID",
|
|
||||||
"AFL_LLVM_LTO_DONTWRITEID",
|
"AFL_LLVM_LTO_DONTWRITEID",
|
||||||
|
"AFL_LLVM_LTO_SKIPINIT"
|
||||||
|
"AFL_LLVM_LTO_STARTID",
|
||||||
"AFL_NO_ARITH",
|
"AFL_NO_ARITH",
|
||||||
"AFL_NO_AUTODICT",
|
"AFL_NO_AUTODICT",
|
||||||
"AFL_NO_BUILTIN",
|
"AFL_NO_BUILTIN",
|
||||||
|
@ -1005,7 +1005,8 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
|||||||
// afl++ START
|
// afl++ START
|
||||||
if (dFile.is_open()) dFile.close();
|
if (dFile.is_open()) dFile.close();
|
||||||
|
|
||||||
if (!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr) {
|
if (!getenv("AFL_LLVM_LTO_SKIPINIT") &&
|
||||||
|
(!getenv("AFL_LLVM_LTO_DONTWRITEID") || dictionary.size() || map_addr)) {
|
||||||
|
|
||||||
// yes we could create our own function, insert it into ctors ...
|
// yes we could create our own function, insert it into ctors ...
|
||||||
// but this would be a pain in the butt ... so we use afl-llvm-rt-lto.o
|
// but this would be a pain in the butt ... so we use afl-llvm-rt-lto.o
|
||||||
|
@ -1563,17 +1563,27 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
|
|||||||
"[-] FATAL: forkserver is already up, but an instrumented dlopen() "
|
"[-] FATAL: forkserver is already up, but an instrumented dlopen() "
|
||||||
"library loaded afterwards. You must AFL_PRELOAD such libraries to "
|
"library loaded afterwards. You must AFL_PRELOAD such libraries to "
|
||||||
"be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n"
|
"be able to fuzz them or LD_PRELOAD to run outside of afl-fuzz.\n"
|
||||||
"To ignore this set AFL_IGNORE_PROBLEMS=1 but this will be bad for "
|
"To ignore this set AFL_IGNORE_PROBLEMS=1 but this will lead to "
|
||||||
"coverage.\n");
|
"ambiguous coverage data.\n"
|
||||||
|
"In addition, you can set AFL_IGNORE_PROBLEMS_COVERAGE=1 to "
|
||||||
|
"ignore the additional coverage instead (use with caution!).\n");
|
||||||
abort();
|
abort();
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
u8 ignore_dso_after_fs = !!getenv("AFL_IGNORE_PROBLEMS_COVERAGE");
|
||||||
|
if (__afl_debug && ignore_dso_after_fs) {
|
||||||
|
|
||||||
|
fprintf(stderr, "Ignoring coverage from dynamically loaded code\n");
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
static u32 offset = 5;
|
static u32 offset = 5;
|
||||||
|
|
||||||
while (start < stop) {
|
while (start < stop) {
|
||||||
|
|
||||||
if (likely(inst_ratio == 100) || R(100) < inst_ratio) {
|
if (!ignore_dso_after_fs &&
|
||||||
|
(likely(inst_ratio == 100) || R(100) < inst_ratio)) {
|
||||||
|
|
||||||
*(start++) = offset;
|
*(start++) = offset;
|
||||||
|
|
||||||
|
@ -2099,6 +2099,8 @@ int main(int argc, char **argv, char **envp) {
|
|||||||
"bb\n"
|
"bb\n"
|
||||||
" AFL_REAL_LD: use this lld linker instead of the compiled in "
|
" AFL_REAL_LD: use this lld linker instead of the compiled in "
|
||||||
"path\n"
|
"path\n"
|
||||||
|
" AFL_LLVM_LTO_SKIPINIT: don't inject initialization code "
|
||||||
|
"(used in WAFL mode)\n"
|
||||||
"If anything fails - be sure to read README.lto.md!\n");
|
"If anything fails - be sure to read README.lto.md!\n");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -718,10 +718,21 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
|
|||||||
|
|
||||||
if (nl_cnt) {
|
if (nl_cnt) {
|
||||||
|
|
||||||
|
u32 done = 0;
|
||||||
|
|
||||||
|
if (unlikely(afl->in_place_resume)) {
|
||||||
|
|
||||||
i = nl_cnt;
|
i = nl_cnt;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
i = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
do {
|
do {
|
||||||
|
|
||||||
--i;
|
if (unlikely(afl->in_place_resume)) { --i; }
|
||||||
|
|
||||||
struct stat st;
|
struct stat st;
|
||||||
u8 dfn[PATH_MAX];
|
u8 dfn[PATH_MAX];
|
||||||
@ -745,7 +756,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
|
|||||||
free(nl[i]); /* not tracked */
|
free(nl[i]); /* not tracked */
|
||||||
read_testcases(afl, fn2);
|
read_testcases(afl, fn2);
|
||||||
ck_free(fn2);
|
ck_free(fn2);
|
||||||
continue;
|
goto next_entry;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -754,7 +765,7 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
|
|||||||
if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
|
if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
|
||||||
|
|
||||||
ck_free(fn2);
|
ck_free(fn2);
|
||||||
continue;
|
goto next_entry;
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -801,18 +812,18 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
next_entry:
|
||||||
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
if (unlikely(afl->in_place_resume)) {
|
||||||
|
|
||||||
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size,
|
if (unlikely(i == 0)) { done = 1; }
|
||||||
HASH_CONST); afl->queue_top->n_fuzz_entry = cksum % N_FUZZ_SIZE;
|
|
||||||
afl->n_fuzz[afl->queue_top->n_fuzz_entry] = 1;
|
} else {
|
||||||
|
|
||||||
|
if (unlikely(++i >= (u32)nl_cnt)) { done = 1; }
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
*/
|
} while (!done);
|
||||||
|
|
||||||
} while (i > 0);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -259,6 +259,8 @@ static void usage(u8 *argv0, int more_help) {
|
|||||||
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
|
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
|
||||||
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
|
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
|
||||||
"AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
|
"AFL_IGNORE_PROBLEMS: do not abort fuzzing if an incorrect setup is detected\n"
|
||||||
|
"AFL_IGNORE_PROBLEMS_COVERAGE: if set in addition to AFL_IGNORE_PROBLEMS - also\n"
|
||||||
|
" ignore those libs for coverage\n"
|
||||||
"AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
|
"AFL_IGNORE_TIMEOUTS: do not process or save any timeouts\n"
|
||||||
"AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
|
"AFL_IGNORE_UNKNOWN_ENVS: don't warn on unknown env vars\n"
|
||||||
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
|
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
|
||||||
|
@ -69,7 +69,9 @@ static afl_state_t *afl;
|
|||||||
static char *stdin_file; /* stdin file */
|
static char *stdin_file; /* stdin file */
|
||||||
|
|
||||||
static u8 *in_dir = NULL, /* input folder */
|
static u8 *in_dir = NULL, /* input folder */
|
||||||
*out_file = NULL, *at_file = NULL; /* Substitution string for @@ */
|
*out_file = NULL, /* output file or directory */
|
||||||
|
*at_file = NULL, /* Substitution string for @@ */
|
||||||
|
*in_filelist = NULL; /* input file list */
|
||||||
|
|
||||||
static u8 outfile[PATH_MAX];
|
static u8 outfile[PATH_MAX];
|
||||||
|
|
||||||
@ -878,6 +880,103 @@ u32 execute_testcases(u8 *dir) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
u32 execute_testcases_filelist(u8 *fn) {
|
||||||
|
|
||||||
|
u32 done = 0;
|
||||||
|
u8 buf[4096];
|
||||||
|
u8 val_buf[2][STRINGIFY_VAL_SIZE_MAX];
|
||||||
|
FILE *f;
|
||||||
|
|
||||||
|
if (!be_quiet) { ACTF("Reading from '%s'...", fn); }
|
||||||
|
|
||||||
|
if ((f = fopen(fn, "r")) == NULL) { FATAL("could not open '%s'", fn); }
|
||||||
|
|
||||||
|
while (fgets(buf, sizeof(buf), f) != NULL) {
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
u8 *fn2 = buf, *fn3;
|
||||||
|
|
||||||
|
while (*fn2 == ' ') {
|
||||||
|
|
||||||
|
++fn2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
while (*fn2 &&
|
||||||
|
(fn2[strlen(fn2) - 1] == '\r' || fn2[strlen(fn2) - 1] == '\n' ||
|
||||||
|
fn2[strlen(fn2) - 1] == ' ')) {
|
||||||
|
|
||||||
|
fn2[strlen(fn2) - 1] = 0;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (debug) { printf("Getting coverage for '%s'\n", fn2); }
|
||||||
|
|
||||||
|
if (!*fn2) { continue; }
|
||||||
|
|
||||||
|
if (lstat(fn2, &st) || access(fn2, R_OK)) {
|
||||||
|
|
||||||
|
WARNF("Unable to access '%s'", fn2);
|
||||||
|
continue;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
++done;
|
||||||
|
|
||||||
|
if (!S_ISREG(st.st_mode) || !st.st_size) { continue; }
|
||||||
|
|
||||||
|
if ((fn3 = strrchr(fn2, '/'))) {
|
||||||
|
|
||||||
|
++fn3;
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
fn3 = fn2;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (st.st_size > MAX_FILE && !be_quiet && !quiet_mode) {
|
||||||
|
|
||||||
|
WARNF("Test case '%s' is too big (%s, limit is %s), partial reading", fn2,
|
||||||
|
stringify_mem_size(val_buf[0], sizeof(val_buf[0]), st.st_size),
|
||||||
|
stringify_mem_size(val_buf[1], sizeof(val_buf[1]), MAX_FILE));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!collect_coverage) {
|
||||||
|
|
||||||
|
snprintf(outfile, sizeof(outfile), "%s/%s", out_file, fn3);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (read_file(fn2)) {
|
||||||
|
|
||||||
|
if (wait_for_gdb) {
|
||||||
|
|
||||||
|
fprintf(stderr, "exec: gdb -p %d\n", fsrv->child_pid);
|
||||||
|
fprintf(stderr, "exec: kill -CONT %d\n", getpid());
|
||||||
|
kill(0, SIGSTOP);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
showmap_run_target_forkserver(fsrv, in_data, in_len);
|
||||||
|
ck_free(in_data);
|
||||||
|
|
||||||
|
if (child_crashed && debug) { WARNF("crashed: %s", fn2); }
|
||||||
|
|
||||||
|
if (collect_coverage)
|
||||||
|
analyze_results(fsrv);
|
||||||
|
else
|
||||||
|
tcnt = write_results_to_file(fsrv, outfile);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
return done;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
/* Show banner. */
|
/* Show banner. */
|
||||||
|
|
||||||
static void show_banner(void) {
|
static void show_banner(void) {
|
||||||
@ -920,6 +1019,7 @@ static void usage(u8 *argv0) {
|
|||||||
" With -C, -o is a file, without -C it must be a "
|
" With -C, -o is a file, without -C it must be a "
|
||||||
"directory\n"
|
"directory\n"
|
||||||
" and each bitmap will be written there individually.\n"
|
" and each bitmap will be written there individually.\n"
|
||||||
|
" -I filelist - alternatively to -i, -I is a list of files\n"
|
||||||
" -C - collect coverage, writes all edges to -o and gives a "
|
" -C - collect coverage, writes all edges to -o and gives a "
|
||||||
"summary\n"
|
"summary\n"
|
||||||
" Must be combined with -i.\n"
|
" Must be combined with -i.\n"
|
||||||
@ -932,7 +1032,7 @@ static void usage(u8 *argv0) {
|
|||||||
"This tool displays raw tuple data captured by AFL instrumentation.\n"
|
"This tool displays raw tuple data captured by AFL instrumentation.\n"
|
||||||
"For additional help, consult %s/README.md.\n\n"
|
"For additional help, consult %s/README.md.\n\n"
|
||||||
|
|
||||||
"If you use -i mode, then custom mutator post_process send send "
|
"If you use -i/-I mode, then custom mutator post_process send send "
|
||||||
"functionality\n"
|
"functionality\n"
|
||||||
"is supported.\n\n"
|
"is supported.\n\n"
|
||||||
|
|
||||||
@ -994,7 +1094,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
|
if (getenv("AFL_QUIET") != NULL) { be_quiet = true; }
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
|
while ((opt = getopt(argc, argv, "+i:I:o:f:m:t:AeqCZOH:QUWbcrshXY")) > 0) {
|
||||||
|
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
|
|
||||||
@ -1012,6 +1112,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
in_dir = optarg;
|
in_dir = optarg;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
case 'I':
|
||||||
|
if (in_filelist) { FATAL("Multiple -I options not supported"); }
|
||||||
|
in_filelist = optarg;
|
||||||
|
break;
|
||||||
|
|
||||||
case 'o':
|
case 'o':
|
||||||
|
|
||||||
if (out_file) { FATAL("Multiple -o options not supported"); }
|
if (out_file) { FATAL("Multiple -o options not supported"); }
|
||||||
@ -1234,10 +1339,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
if (optind == argc || !out_file) { usage(argv[0]); }
|
if (optind == argc || !out_file) { usage(argv[0]); }
|
||||||
|
|
||||||
if (in_dir) {
|
if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
|
||||||
|
|
||||||
|
if (in_dir || in_filelist) {
|
||||||
|
|
||||||
if (!out_file && !collect_coverage)
|
if (!out_file && !collect_coverage)
|
||||||
FATAL("for -i you need to specify either -C and/or -o");
|
FATAL("for -i/-I you need to specify either -C and/or -o");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1294,7 +1401,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_dir) {
|
if (in_dir || in_filelist) {
|
||||||
|
|
||||||
/* If we don't have a file name chosen yet, use a safe default. */
|
/* If we don't have a file name chosen yet, use a safe default. */
|
||||||
u8 *use_dir = ".";
|
u8 *use_dir = ".";
|
||||||
@ -1400,7 +1507,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef __linux__
|
#ifdef __linux__
|
||||||
if (!fsrv->nyx_mode && in_dir) {
|
if (!fsrv->nyx_mode && (in_dir || in_filelist)) {
|
||||||
|
|
||||||
(void)check_binary_signatures(fsrv->target_path);
|
(void)check_binary_signatures(fsrv->target_path);
|
||||||
|
|
||||||
@ -1483,7 +1590,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_dir) {
|
if (in_dir || in_filelist) {
|
||||||
|
|
||||||
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||||
afl->afl_env.afl_custom_mutator_library =
|
afl->afl_env.afl_custom_mutator_library =
|
||||||
@ -1496,34 +1603,47 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
|
if (getenv("AFL_CUSTOM_MUTATOR_LIBRARY") || getenv("AFL_PYTHON_MODULE")) {
|
||||||
|
|
||||||
WARNF(
|
WARNF(
|
||||||
"Custom mutator environment detected, this is only supported in -i "
|
"Custom mutator environment detected, this is only supported in "
|
||||||
"mode!\n");
|
"-i/-I mode!\n");
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (in_dir) {
|
if (in_dir || in_filelist) {
|
||||||
|
|
||||||
DIR *dir_in, *dir_out = NULL;
|
DIR *dir_in, *dir_out = NULL;
|
||||||
|
u8 *dn = NULL;
|
||||||
|
|
||||||
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
|
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
|
||||||
|
|
||||||
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
|
||||||
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
|
||||||
|
|
||||||
|
if (in_filelist) {
|
||||||
|
|
||||||
|
if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
// if a queue subdirectory exists switch to that
|
// if a queue subdirectory exists switch to that
|
||||||
u8 *dn = alloc_printf("%s/queue", in_dir);
|
dn = alloc_printf("%s/queue", in_dir);
|
||||||
|
|
||||||
if ((dir_in = opendir(dn)) != NULL) {
|
if ((dir_in = opendir(dn)) != NULL) {
|
||||||
|
|
||||||
closedir(dir_in);
|
closedir(dir_in);
|
||||||
in_dir = dn;
|
in_dir = dn;
|
||||||
|
|
||||||
} else
|
} else {
|
||||||
|
|
||||||
ck_free(dn);
|
ck_free(dn);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
|
if (!be_quiet) ACTF("Reading from directory '%s'...", in_dir);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!collect_coverage) {
|
if (!collect_coverage) {
|
||||||
|
|
||||||
if (!(dir_out = opendir(out_file))) {
|
if (!(dir_out = opendir(out_file))) {
|
||||||
@ -1576,12 +1696,24 @@ int main(int argc, char **argv_orig, char **envp) {
|
|||||||
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)
|
||||||
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
||||||
|
|
||||||
|
if (in_dir) {
|
||||||
|
|
||||||
if (execute_testcases(in_dir) == 0) {
|
if (execute_testcases(in_dir) == 0) {
|
||||||
|
|
||||||
FATAL("could not read input testcases from %s", in_dir);
|
FATAL("could not read input testcases from %s", in_dir);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
} else {
|
||||||
|
|
||||||
|
if (execute_testcases_filelist(in_filelist) == 0) {
|
||||||
|
|
||||||
|
FATAL("could not read input testcases from %s", in_filelist);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); }
|
if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); }
|
||||||
|
|
||||||
if (dir_out) { closedir(dir_out); }
|
if (dir_out) { closedir(dir_out); }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user