mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 14:43:22 +00:00
Compare commits
195 Commits
Author | SHA1 | Date | |
---|---|---|---|
9f6b012fbf | |||
ec0b83f127 | |||
0c81982e67 | |||
5014b86c3c | |||
44b5e1f488 | |||
31652eeb2a | |||
4bb4d4ad00 | |||
5331eca5d9 | |||
74e264a20a | |||
f0937f96d4 | |||
92cbdb9f45 | |||
fe36ceaa55 | |||
0618bfd4ae | |||
bdfd38771a | |||
477063e9ee | |||
e46c106b89 | |||
69630338ff | |||
112759cd39 | |||
f8767c397b | |||
e8d098335b | |||
12a87cfacb | |||
2806d6be2f | |||
2d9b793dbb | |||
7f02f0da61 | |||
bc2ccf464f | |||
b8536ced09 | |||
1db82f3303 | |||
fd713413e8 | |||
2d4a4ba73f | |||
348f980f21 | |||
ca55858aa7 | |||
e639521b01 | |||
894339c5d7 | |||
e13dc9b7e6 | |||
5fb657f569 | |||
d2700c7525 | |||
4cf358b589 | |||
5e708b23c6 | |||
9419e39fdf | |||
c202d80dea | |||
eecbdd99e1 | |||
64293cdc82 | |||
f8a5f1cd9e | |||
a3125c38f4 | |||
224add0222 | |||
19636f748c | |||
7aa5e1c443 | |||
93279db71b | |||
5bf760510e | |||
03dc80afc4 | |||
fda3106fd9 | |||
9721a77204 | |||
92a8c2804f | |||
e1521fa8eb | |||
4e3cd8ac3f | |||
31a8beb449 | |||
e7d871c8bf | |||
56d5aa3101 | |||
c6a2a4046e | |||
6dd5e931fc | |||
635140ba43 | |||
497f341eac | |||
068aa13c6b | |||
ba7ae6c59d | |||
6ae95271be | |||
a2e0163cc1 | |||
1db3b81d2e | |||
0a16ea7487 | |||
a26bb0b0f2 | |||
7d3530a22e | |||
a87ea96913 | |||
81609a0f42 | |||
938edab25f | |||
29c9870658 | |||
b6c4f3775a | |||
5ee5564ae2 | |||
ab36756061 | |||
831b8f35d5 | |||
0cf78b7748 | |||
0892a2245e | |||
622474e9e4 | |||
0cabc12f91 | |||
b282ce999d | |||
24b9d74e70 | |||
c03f2897d0 | |||
90fbf59bf1 | |||
93c7cbd496 | |||
db60555c1b | |||
45117a3384 | |||
4d4880b428 | |||
ac6ccd53df | |||
4ec376bd6a | |||
3c0448305b | |||
a6029a10cc | |||
26eaf53a83 | |||
5d623a27ed | |||
69e554b941 | |||
7340374a7c | |||
67d356b73f | |||
da18f1f722 | |||
58abcceff5 | |||
ad0d0c77fb | |||
2c3f761ede | |||
70c60cfba7 | |||
f3b6d64ad3 | |||
43e9a13921 | |||
526dbe8f16 | |||
951a0e5225 | |||
458b939bc4 | |||
476aca5b67 | |||
96bf0f8323 | |||
58206a3180 | |||
f138ab8ac6 | |||
50839cf6e9 | |||
626a4434ed | |||
d84cc73d13 | |||
6b049536f1 | |||
1d17210d9f | |||
1582aa9da2 | |||
e01307a993 | |||
beb9f95359 | |||
c49a4c7027 | |||
b08df87f5c | |||
72226d6f89 | |||
40adc34413 | |||
eeae114b76 | |||
48a862c503 | |||
29544e4d2b | |||
420a90ff75 | |||
45603367bf | |||
f7ea0f569f | |||
2bf92848ff | |||
ad65cfb400 | |||
5ffc8c7076 | |||
8943ba0249 | |||
b02adf6b3f | |||
6ef5d7c135 | |||
9ece2e3f2c | |||
4b2cdaf47c | |||
9b5b71b61b | |||
59465bd249 | |||
ed50f37c79 | |||
a96bda82f9 | |||
1860f6e594 | |||
c9ad3acc9b | |||
93c7a42453 | |||
ee07fc9f6d | |||
443edcd771 | |||
6650ef4274 | |||
b85174fc8d | |||
08f6d59f50 | |||
2ed2ac80bc | |||
2300088446 | |||
306a917956 | |||
0ea53ea5b5 | |||
092260e9f9 | |||
52e19d35fa | |||
bf17953353 | |||
e46fac6063 | |||
6062668679 | |||
acc178e5dd | |||
31adb57fd7 | |||
7652406c12 | |||
a607adb7a3 | |||
036a79268b | |||
335b2d4542 | |||
603136efa0 | |||
1e01ccc8fd | |||
9f6d27ddce | |||
8fcd404352 | |||
b2b887d04d | |||
849994dedd | |||
1286d1906f | |||
fae760fc9e | |||
01f442d810 | |||
eaedf2e62f | |||
07e0b39126 | |||
98238ed763 | |||
340d6aa97c | |||
5ae4a7ae02 | |||
80158de3e8 | |||
730713193a | |||
fea76dff23 | |||
808022d3e0 | |||
eee78077e2 | |||
ca91d3fbc0 | |||
ad4a776fc6 | |||
ebdb71aeb0 | |||
6dc58750cf | |||
1b84448be3 | |||
61ceef64b1 | |||
775861ea94 | |||
602eceed8b | |||
629edb1e78 | |||
8012b555a8 |
1
.github/workflows/ci.yml
vendored
1
.github/workflows/ci.yml
vendored
@ -5,7 +5,6 @@ on:
|
||||
branches:
|
||||
- stable
|
||||
- dev
|
||||
- 420
|
||||
pull_request:
|
||||
branches:
|
||||
- dev # No need for stable-pull-request, as that equals dev-push
|
||||
|
@ -27,5 +27,5 @@ keywords:
|
||||
- qemu
|
||||
- llvm
|
||||
- unicorn-emulator
|
||||
- securiy
|
||||
- security
|
||||
license: AGPL-3.0-or-later
|
||||
|
16
GNUmakefile
16
GNUmakefile
@ -52,7 +52,7 @@ endif
|
||||
ifdef ASAN_BUILD
|
||||
$(info Compiling ASAN version of binaries)
|
||||
override CFLAGS += $(ASAN_CFLAGS)
|
||||
LDFLAGS += $(ASAN_LDFLAGS)
|
||||
override LDFLAGS += $(ASAN_LDFLAGS)
|
||||
endif
|
||||
ifdef UBSAN_BUILD
|
||||
$(info Compiling UBSAN version of binaries)
|
||||
@ -106,22 +106,22 @@ ifneq "$(SYS)" "Darwin"
|
||||
# SPECIAL_PERFORMANCE += -march=native
|
||||
#endif
|
||||
#ifndef DEBUG
|
||||
# CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||
#endif
|
||||
else
|
||||
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
||||
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
||||
LDFLAGS += $(SDK_LD)
|
||||
override LDFLAGS += $(SDK_LD)
|
||||
endif
|
||||
|
||||
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
|
||||
ifneq "$(COMPILER_TYPE)" ""
|
||||
#$(info gcc is being used)
|
||||
CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
||||
override CFLAGS_OPT += -Wno-error=format-truncation -Wno-format-truncation
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "SunOS"
|
||||
LDFLAGS = -lkstat -lrt -lsocket -lnsl
|
||||
override LDFLAGS = -lkstat -lrt -lsocket -lnsl
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
@ -131,8 +131,8 @@ ifdef STATIC
|
||||
PYFLAGS=
|
||||
PYTHON_INCLUDE = /
|
||||
|
||||
CFLAGS_OPT += -static
|
||||
LDFLAGS += -lm -lpthread -lz -lutil
|
||||
override CFLAGS_OPT += -static
|
||||
override LDFLAGS += -lm -lpthread -lz -lutil
|
||||
endif
|
||||
|
||||
ifdef PROFILING
|
||||
@ -759,7 +759,7 @@ endif
|
||||
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-13 and clang-13 or newer, see docs/INSTALL.md"
|
||||
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode successfully built" || echo "[-] LLVM LTO mode could not be built, it is optional, if you want it, please install LLVM 11-14. More information at instrumentation/README.lto.md on how to build it"
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
||||
@test -e afl-gcc-pass.so && echo "[+] gcc_mode successfully built" || echo "[-] gcc_mode could not be built, it is optional, install gcc-VERSION-plugin-dev to enable this"
|
||||
endif
|
||||
ifeq "$(SYS)" "Linux"
|
||||
ifndef NO_NYX
|
||||
|
@ -44,9 +44,9 @@ endif
|
||||
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
|
||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
||||
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
|
||||
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
|
||||
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[8-9]|^2[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
|
||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
||||
|
||||
Release version: [4.10c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.20a
|
||||
GitHub version: 4.21c
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
3
TODO.md
3
TODO.md
@ -2,6 +2,8 @@
|
||||
|
||||
## Must
|
||||
|
||||
- fast restart of afl-fuzz if cmdline + target hash is the same
|
||||
- check for null ptr for xml/curl/g_ string transform functions
|
||||
- hardened_usercopy=0 page_alloc.shuffle=0
|
||||
- add value_profile but only enable after 15 minutes without finds
|
||||
- cmplog max items env?
|
||||
@ -16,6 +18,7 @@
|
||||
## Should
|
||||
|
||||
- afl-crash-analysis
|
||||
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
|
||||
- support persistent and deferred fork server in afl-showmap?
|
||||
- better autodetection of shifting runtime timeout values
|
||||
- afl-plot to support multiple plot_data
|
||||
|
8
afl-cmin
8
afl-cmin
@ -13,7 +13,7 @@ awk -f - -- ${@+"$@"} <<'EOF'
|
||||
# awk script to minimize a test corpus of input files
|
||||
#
|
||||
# based on afl-cmin bash script written by Michal Zalewski
|
||||
# rewritten by Heiko Eißfeldt (hexcoder-)
|
||||
# rewritten by Heiko Eissfeldt (hexcoder-)
|
||||
# tested with:
|
||||
# gnu awk (x86 Linux)
|
||||
# bsd awk (x86 *BSD)
|
||||
@ -108,7 +108,7 @@ function usage() {
|
||||
"\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 (default: stdin)\n" \
|
||||
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
|
||||
" -t msec - run time limit for child process (default: 5000)\n" \
|
||||
" -O - use binary-only instrumentation (FRIDA mode)\n" \
|
||||
@ -603,8 +603,8 @@ BEGIN {
|
||||
# create path for the trace file from afl-showmap
|
||||
tracefile_path = trace_dir"/"fn
|
||||
# ensure the file size is not zero
|
||||
cmd = "du -b "tracefile_path
|
||||
"ls -l "tracefile_path
|
||||
cmd = "du -b \""tracefile_path"\""
|
||||
# "ls -l \""tracefile_path"\""
|
||||
cmd | getline output
|
||||
close(cmd)
|
||||
split(output, result, "\t")
|
||||
|
@ -152,6 +152,7 @@ Minimization settings:
|
||||
-e - solve for edge coverage only, ignore hit counts
|
||||
|
||||
For additional tips, please consult README.md.
|
||||
This script cannot read filenames that end with a space ' '.
|
||||
|
||||
Environment variables used:
|
||||
AFL_KEEP_TRACES: leave the temporary <out_dir>\.traces directory
|
||||
|
@ -124,17 +124,26 @@ kernel.sched_latency_ns=250000000
|
||||
EOF
|
||||
}
|
||||
|
||||
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null || echo Error: /etc/default/grub with GRUB_CMDLINE_LINUX_DEFAULT is not present, cannot set boot options
|
||||
grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub 2>/dev/null && {
|
||||
grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | grep -E -q 'noibrs pcid nopti' || {
|
||||
grub_try_disable_mitigation () {
|
||||
KEY="$1"
|
||||
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
|
||||
echo "Configuring performance boot options"
|
||||
LINE=`grep -E '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub | sed 's/^GRUB_CMDLINE_LINUX_DEFAULT=//' | tr -d '"'`
|
||||
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'`
|
||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||
echo Setting boot options in /etc/default/grub to GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"
|
||||
sed -i "s|^GRUB_CMDLINE_LINUX_DEFAULT=.*|GRUB_CMDLINE_LINUX_DEFAULT=\"$OPTIONS\"|" /etc/default/grub
|
||||
}
|
||||
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
|
||||
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
if grep -E -q '^GRUB_CMDLINE_LINUX=' /etc/default/grub || grep -E -q '^GRUB_CMDLINE_LINUX_DEFAULT=' /etc/default/grub; then
|
||||
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX_DEFAULT"
|
||||
# We also overwrite GRUB_CMDLINE_LINUX because some distributions already overwrite GRUB_CMDLINE_LINUX_DEFAULT
|
||||
grub_try_disable_mitigation "GRUB_CMDLINE_LINUX"
|
||||
else
|
||||
echo "Error: /etc/default/grub with GRUB_CMDLINE_LINUX is not present, cannot set boot options"
|
||||
fi
|
||||
|
||||
echo
|
||||
echo "Reboot and enjoy your fuzzing"
|
||||
exit 0
|
||||
|
49
afl-whatsup
49
afl-whatsup
@ -111,7 +111,13 @@ if [ -z "$NO_COLOR" ]; then
|
||||
RESET="$NC"
|
||||
fi
|
||||
|
||||
CUR_TIME=`date +%s`
|
||||
PLATFORM=`uname -s`
|
||||
if [ "$PLATFORM" = "Linux" ] ; then
|
||||
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
|
||||
else
|
||||
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
|
||||
CUR_TIME=`date +%s`
|
||||
fi
|
||||
|
||||
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
|
||||
trap "rm -f $TMP" 1 2 3 13 15
|
||||
@ -123,6 +129,7 @@ START_CNT=0
|
||||
TOTAL_TIME=0
|
||||
TOTAL_EXECS=0
|
||||
TOTAL_EPS=0
|
||||
TOTAL_EPLM=0
|
||||
TOTAL_CRASHES=0
|
||||
TOTAL_HANGS=0
|
||||
TOTAL_PFAV=0
|
||||
@ -182,6 +189,8 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
||||
|
||||
if [ -f "$i" ]; then
|
||||
|
||||
IS_STARTING=
|
||||
IS_DEAD=
|
||||
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
|
||||
. "$TMP"
|
||||
DIRECTORY=$DIR
|
||||
@ -212,9 +221,6 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
||||
|
||||
if ! kill -0 "$fuzzer_pid" 2>/dev/null; then
|
||||
|
||||
IS_STARTING=
|
||||
IS_DEAD=
|
||||
|
||||
if [ -e "$i" ] && [ -e "$j" ] && [ -n "$FUSER" ]; then
|
||||
|
||||
if [ "$i" -ot "$j" ]; then
|
||||
@ -273,11 +279,15 @@ for j in `find . -maxdepth 2 -iname fuzzer_setup | sort`; do
|
||||
ALIVE_CNT=$((ALIVE_CNT + 1))
|
||||
|
||||
EXEC_SEC=0
|
||||
EXEC_MIN=0
|
||||
test -z "$RUN_UNIX" -o "$RUN_UNIX" = 0 || EXEC_SEC=$((execs_done / RUN_UNIX))
|
||||
PATH_PERC=$((cur_item * 100 / corpus_count))
|
||||
|
||||
test "$IS_DEAD" = 1 || EXEC_MIN=$(echo $execs_ps_last_min|sed 's/\..*//')
|
||||
|
||||
TOTAL_TIME=$((TOTAL_TIME + RUN_UNIX))
|
||||
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
|
||||
TOTAL_EPLM=$((TOTAL_EPLM + EXEC_MIN))
|
||||
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
|
||||
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
|
||||
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
|
||||
@ -399,41 +409,44 @@ if [ -z "$SUMMARY_ONLY" -o -z "$MINIMAL_ONLY" ]; then
|
||||
echo
|
||||
fi
|
||||
|
||||
echo " Fuzzers alive : $ALIVE_CNT"
|
||||
echo " Fuzzers alive : $ALIVE_CNT"
|
||||
|
||||
if [ ! "$START_CNT" = "0" ]; then
|
||||
echo " Starting up : $START_CNT ($TXT)"
|
||||
echo " Starting up : $START_CNT ($TXT)"
|
||||
fi
|
||||
|
||||
if [ ! "$DEAD_CNT" = "0" ]; then
|
||||
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
||||
echo " Dead or remote : $DEAD_CNT ($TXT)"
|
||||
fi
|
||||
|
||||
echo " Total run time : $FMT_TIME"
|
||||
echo " Total run time : $FMT_TIME"
|
||||
if [ -z "$MINIMAL_ONLY" ]; then
|
||||
echo " Total execs : $FMT_EXECS"
|
||||
echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||
echo " Total execs : $FMT_EXECS"
|
||||
echo " Cumulative speed : $TOTAL_EPS execs/sec"
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Total average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||
fi
|
||||
fi
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Average speed : $((TOTAL_EPS / ALIVE_CNT)) execs/sec"
|
||||
echo "Current average speed : $TOTAL_EPLM execs/sec"
|
||||
fi
|
||||
if [ -z "$MINIMAL_ONLY" ]; then
|
||||
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||
echo " Pending items : $TOTAL_PFAV faves, $TOTAL_PENDING total"
|
||||
fi
|
||||
|
||||
if [ "$ALIVE_CNT" -gt "1" -o -n "$MINIMAL_ONLY" ]; then
|
||||
if [ "$ALIVE_CNT" -gt "0" ]; then
|
||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||
echo " Pending per fuzzer : $((TOTAL_PFAV/ALIVE_CNT)) faves, $((TOTAL_PENDING/ALIVE_CNT)) total (on average)"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo " Coverage reached : ${TOTAL_COVERAGE}%"
|
||||
echo " Crashes saved : $TOTAL_CRASHES"
|
||||
echo " Coverage reached : ${TOTAL_COVERAGE}%"
|
||||
echo " Crashes saved : $TOTAL_CRASHES"
|
||||
if [ -z "$MINIMAL_ONLY" ]; then
|
||||
echo " Hangs saved : $TOTAL_HANGS"
|
||||
echo "Cycles without finds : $TOTAL_WCOP"
|
||||
echo " Hangs saved : $TOTAL_HANGS"
|
||||
echo " Cycles without finds : $TOTAL_WCOP"
|
||||
fi
|
||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||
echo " Time without finds : $TOTAL_LAST_FIND"
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
@ -1,13 +1,13 @@
|
||||
CPU | MHz | threads | singlecore | multicore | afl-*-config |
|
||||
====================================================|=======|=========|============|===========|==============|
|
||||
Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|
||||
AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|
||||
AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|
||||
Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|
||||
12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|
||||
AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|
||||
Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|
||||
AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
|
||||
AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|
||||
AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|
||||
AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|
||||
|CPU | MHz | threads | singlecore | multicore | afl-*-config |
|
||||
|----------------------------------------------------|-------|---------|------------|-----------|--------------|
|
||||
|Raspberry Pi 5 | 2400 | 4 | 25786 | 101114 | both |
|
||||
|AMD EPYC 7282 16-Core Processor | 3194 | 32 | 87199 | 769001 | both |
|
||||
|AMD Ryzen 5 PRO 4650G with Radeon Graphics | 3700 | 12 | 95356 | 704840 | both |
|
||||
|Intel(R) Core(TM) i9-9900K CPU @ 3.60GHz | 4995 | 16 | 120064 | 1168943 | both |
|
||||
|12th Gen Intel(R) Core(TM) i7-1270P | 4761 | 16 | 149778 | 641219 | both |
|
||||
|AMD Ryzen 9 5950X 16-Core Processor | 4792 | 32 | 161690 | 2339763 | both |
|
||||
|Apple Mac Studio M2 Ultra 2023, Linux VM guest | 3500 | 16 | 163570 | 1157465 | both |
|
||||
|AMD Ryzen 9 6900HS with Radeon Graphics | 4676 | 16 | 62860 | 614404 | system |
|
||||
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|
||||
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|
||||
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|
||||
|
@ -205,7 +205,7 @@ async def save_benchmark_results() -> None:
|
||||
single = str(round(results.targets["test-instr-persist-shmem"]["singlecore"].execs_per_sec)).ljust(10)
|
||||
multi = str(round(results.targets["test-instr-persist-shmem"]["multicore"].execs_per_sec)).ljust(9)
|
||||
cores = str(args.fuzzers).ljust(7)
|
||||
comparisonfile.write(f"{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
|
||||
comparisonfile.write(f"|{cpu_model} | {cpu_mhz} | {cores} | {single} | {multi} | {aflconfig} |\n")
|
||||
print(blue(f" [*] Results have been written to the COMPARISON.md file."))
|
||||
with open("COMPARISON.md", "r") as comparisonfile:
|
||||
print(comparisonfile.read())
|
||||
|
@ -1,3 +1,4 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
@ -1,9 +1,6 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
s8 interesting_8[] = {INTERESTING_8};
|
||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
@ -155,7 +152,7 @@ int main(int argc, char *argv[]) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation output length: %zu\n", outlen);
|
||||
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
|
||||
|
||||
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
||||
fprintf(stderr, "Warning: incomplete write.\n");
|
||||
|
@ -1 +1 @@
|
||||
5ed4f8d
|
||||
95a6857
|
||||
|
Submodule custom_mutators/grammar_mutator/grammar_mutator updated: 5ed4f8d6e6...95a685773e
@ -22,10 +22,10 @@ afl_state_t *afl_struct;
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
u8 * mutator_buf;
|
||||
u8 * out_dir;
|
||||
u8 * tmp_dir;
|
||||
u8 * target;
|
||||
u8 *mutator_buf;
|
||||
u8 *out_dir;
|
||||
u8 *tmp_dir;
|
||||
u8 *target;
|
||||
uint32_t seed;
|
||||
|
||||
} my_mutator_t;
|
||||
@ -101,7 +101,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
/* When a new queue entry is added we run this input with the symcc
|
||||
instrumented binary */
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
@ -176,7 +176,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
|
||||
struct dirent **nl;
|
||||
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
|
||||
u8 * origin_name = basename(filename_new_queue);
|
||||
u8 *origin_name = basename(filename_new_queue);
|
||||
int32_t i;
|
||||
if (items > 0) {
|
||||
|
||||
@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
DBG("test=%s\n", fn);
|
||||
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
u8 *destination_name =
|
||||
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
|
||||
u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
|
||||
origin_name, nl[i]->d_name);
|
||||
rename(source_name, destination_name);
|
||||
ck_free(destination_name);
|
||||
DBG("found=%s\n", source_name);
|
||||
@ -248,7 +248,7 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
|
||||
for (i = 0; i < (u32)items; ++i) {
|
||||
|
||||
struct stat st;
|
||||
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
DBG("test=%s\n", fn);
|
||||
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
@ -282,12 +282,12 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
if (items <= 0) return 0;
|
||||
|
||||
for (i = 0; i < (u32)items; ++i) {
|
||||
for (i = 0; i < (s32)items; ++i) {
|
||||
|
||||
struct stat st;
|
||||
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
if (!done) {
|
||||
|
||||
if (done == 0) {
|
||||
struct stat st;
|
||||
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
|
||||
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
}
|
||||
|
||||
unlink(fn);
|
||||
ck_free(fn);
|
||||
|
||||
}
|
||||
|
||||
ck_free(fn);
|
||||
free(nl[i]);
|
||||
|
||||
}
|
||||
|
@ -3,12 +3,52 @@
|
||||
This is the list of all noteworthy changes made in every public
|
||||
release of the tool. See README.md for the general instruction manual.
|
||||
|
||||
### Version ++4.20a (dev)
|
||||
### Version ++4.21c (release)
|
||||
* afl-fuzz
|
||||
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
|
||||
do a switch from gettimeofday() to clock_gettime() which should be rather
|
||||
three times faster. The reason for this is unknown.
|
||||
- new queue selection algorithm based on 2 core years of queue data
|
||||
analysis. gives a noticable improvement on coverage although the results
|
||||
seem counterintuitive :-)
|
||||
- added AFL_DISABLE_REDUNDANT for huge queues
|
||||
- added `AFL_NO_SYNC` environment variable that does what you think it does
|
||||
- fix AFL_PERSISTENT_RECORD
|
||||
- run custom_post_process after standard trimming
|
||||
- prevent filenames in the queue that have spaces
|
||||
- minor fix for FAST schedules
|
||||
- more frequent stats update when syncing (todo: check performance impact)
|
||||
- now timing of calibration, trimming and syncing is measured seperately,
|
||||
thanks to @eqv!
|
||||
- -V timing is now accurately the fuzz time (without syncing), before
|
||||
long calibration times and syncing could result in now fuzzing being
|
||||
made when the time was already run out until then, thanks to @eqv!
|
||||
- fix -n uninstrumented mode when ending fuzzing
|
||||
- enhanced the ASAN configuration
|
||||
- make afl-fuzz use less memory with cmplog and fix a memleak
|
||||
* afl-cc:
|
||||
- re-enable i386 support that was accidently disabled
|
||||
- fixes for LTO and outdated afl-gcc mode for i386
|
||||
- fix COMPCOV split compare for old LLVMs
|
||||
- disable xml/curl/g_ string transform functions because we do not check
|
||||
for null pointers ... TODO
|
||||
- ensure shared memory variables are visible in weird build setups
|
||||
- compatability to new LLVM 19 changes
|
||||
* afl-cmin
|
||||
- work with input files that have a space
|
||||
* afl-showmap
|
||||
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
|
||||
- minor fix to collect coverage -C (thanks to @bet4it)
|
||||
* Fixed a shmem mmap bug (that rarely came up on MacOS)
|
||||
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
|
||||
|
||||
|
||||
### Version ++4.20c (release)
|
||||
! A new forkserver communication model is now introduced. afl-fuzz is
|
||||
backward compatible to old compiled targets if they are not built
|
||||
for CMPLOG/Redqueen, but new compiled targets will not work with
|
||||
old afl-fuzz versions!
|
||||
! Recompiled all targets that are instrumented for CMPLOG/Redqueen!
|
||||
! Recompile all targets that are instrumented for CMPLOG/Redqueen!
|
||||
- AFL++ now supports up to 4 billion coverage edges, up from 6 million.
|
||||
- New compile option: `make PERFORMANCE=1` - this will enable special
|
||||
CPU dependent optimizations that make everything more performant - but
|
||||
@ -22,15 +62,27 @@
|
||||
- small improvements to CMPLOG/redqueen
|
||||
- workround for a bug with MOpt -L when used with -M - in the future
|
||||
we will either remove or rewrite MOpt.
|
||||
- fix for `-t xxx+` feature
|
||||
- -e extension option now saves the queue items, crashes, etc. with the
|
||||
extension too
|
||||
- fixes for trimmming, correct -V time and reading stats on resume by eqv
|
||||
thanks a lot!
|
||||
- afl-cc:
|
||||
- added collision free caller instrumentation to LTO mode. activate with
|
||||
`AFL_LLVM_LTO_CALLER=1`. You can set a max depth to go through single
|
||||
block functions with `AFL_LLVM_LTO_CALLER_DEPTH` (default 0)
|
||||
- fixes for COMPCOV/LAF and most other modules
|
||||
- fix for GCC_PLUGIN cmplog that broke on std::strings
|
||||
- afl-whatsup:
|
||||
- now also displays current average speed
|
||||
- small bugfixes
|
||||
- custom mutators:
|
||||
- fixes for aflpp custom mutator and standalone tool
|
||||
- important fix to the symcc custom mutator
|
||||
- Minor edits to afl-persistent-config
|
||||
- Prevent temporary files being left behind on aborted afl-whatsup
|
||||
- More CPU benchmarks added to benchmark/
|
||||
|
||||
|
||||
### Version ++4.10c (release)
|
||||
- afl-fuzz:
|
||||
- default power schedule is now EXPLORE, due a fix in fast schedules
|
||||
|
102
docs/INSTALL.md
102
docs/INSTALL.md
@ -21,7 +21,7 @@ If you want to build AFL++ yourself, you have many options. The easiest choice
|
||||
is to build and install everything:
|
||||
|
||||
NOTE: depending on your Debian/Ubuntu/Kali/... release, replace `-14` with
|
||||
whatever llvm version is available. We recommend llvm 13, 14, 15 or 16.
|
||||
whatever llvm version is available. We recommend llvm 13 or newer.
|
||||
|
||||
```shell
|
||||
sudo apt-get update
|
||||
@ -67,7 +67,7 @@ These build targets exist:
|
||||
* unit: perform unit tests (based on cmocka)
|
||||
* help: shows these build options
|
||||
|
||||
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
|
||||
[Unless you are on macOS](https://developer.apple.com/library/archive/qa/qa1118/_index.html),
|
||||
you can also build statically linked versions of the AFL++ binaries by passing
|
||||
the `PERFORMANCE=1` argument to make:
|
||||
|
||||
@ -77,10 +77,10 @@ make PERFORMANCE=1
|
||||
|
||||
These build options exist:
|
||||
|
||||
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended!
|
||||
* STATIC - compile AFL++ static
|
||||
* CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)
|
||||
* ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
|
||||
* PERFORMANCE - compile with performance options that make the binary not transferable to other systems. Recommended (except on macOS)!
|
||||
* STATIC - compile AFL++ static (does not work on macOS)
|
||||
* CODE_COVERAGE - compile the target for code coverage (see [README.llvm.md](../instrumentation/README.llvm.md))
|
||||
* ASAN_BUILD - compiles AFL++ with address sanitizer for debug purposes
|
||||
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
|
||||
* DEBUG - no optimization, -ggdb3, all warnings and -Werror
|
||||
* LLVM_DEBUG - shows llvm deprecation warnings
|
||||
@ -92,7 +92,7 @@ These build options exist:
|
||||
* NO_NYX - disable building nyx mode dependencies
|
||||
* NO_CORESIGHT - disable building coresight (arm64 only)
|
||||
* NO_UNICORN_ARM64 - disable building unicorn on arm64
|
||||
* AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||
* AFL_NO_X86 - if compiling on non-Intel/AMD platforms
|
||||
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)
|
||||
|
||||
e.g.: `make LLVM_CONFIG=llvm-config-14`
|
||||
@ -101,8 +101,19 @@ e.g.: `make LLVM_CONFIG=llvm-config-14`
|
||||
|
||||
macOS has some gotchas due to the idiosyncrasies of the platform.
|
||||
|
||||
To build AFL, install llvm (and perhaps gcc) from brew and follow the general
|
||||
instructions for Linux. If possible, avoid Xcode at all cost.
|
||||
macOS supports SYSV shared memory used by AFL++'s instrumentation, but the
|
||||
default settings aren't sufficient. Before even building, increase
|
||||
them by running the provided script:
|
||||
|
||||
```shell
|
||||
sudo afl-system-config
|
||||
```
|
||||
|
||||
See
|
||||
[https://www.spy-hill.com/help/apple/SharedMemory.html](https://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||
for documentation for the shared memory settings and how to make them permanent.
|
||||
|
||||
Next, to build AFL++, install the following packages from brew:
|
||||
|
||||
```shell
|
||||
brew install wget git make cmake llvm gdb coreutils
|
||||
@ -113,38 +124,37 @@ You can check with `brew info llvm` to know where, then create a variable for it
|
||||
|
||||
```shell
|
||||
export HOMEBREW_BASE="/opt/homebrew/opt"
|
||||
# or
|
||||
```
|
||||
|
||||
or
|
||||
|
||||
```shell
|
||||
export HOMEBREW_BASE="/usr/local/opt"
|
||||
```
|
||||
|
||||
Be sure to setup `PATH` to point to the correct clang binaries and use the
|
||||
freshly installed clang, clang++, llvm-config, gmake and coreutils, e.g.:
|
||||
Set `PATH` to point to the brew clang, clang++, llvm-config, gmake and coreutils.
|
||||
Also use the brew clang compiler; the Xcode clang compiler must not be used.
|
||||
|
||||
```shell
|
||||
export PATH="$HOMEBREW_BASE/coreutils/libexec/gnubin:/usr/local/bin:$HOMEBREW_BASE/llvm/bin:$PATH"
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
gmake
|
||||
cd frida_mode
|
||||
gmake
|
||||
cd ..
|
||||
sudo gmake install
|
||||
```
|
||||
|
||||
`afl-gcc` will fail unless you have GCC installed, but that is using outdated
|
||||
instrumentation anyway. `afl-clang` might fail too depending on your PATH setup.
|
||||
But you don't want neither, you want `afl-clang-fast` anyway :) Note that
|
||||
`afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
|
||||
Then build following the general Linux instructions.
|
||||
|
||||
If everything worked, you should then have `afl-clang-fast` installed, which you can check with:
|
||||
|
||||
```shell
|
||||
which afl-clang-fast
|
||||
```
|
||||
|
||||
Note that `afl-clang-lto`, `afl-gcc-fast` and `qemu_mode` are not working on macOS.
|
||||
|
||||
The crash reporting daemon that comes by default with macOS will cause
|
||||
problems with fuzzing. You need to turn it off:
|
||||
problems with fuzzing. You need to turn it off, which you can do with `afl-system-config`.
|
||||
|
||||
```
|
||||
launchctl unload -w /System/Library/LaunchAgents/com.apple.ReportCrash.plist
|
||||
sudo launchctl unload -w /System/Library/LaunchDaemons/com.apple.ReportCrash.Root.plist
|
||||
```
|
||||
|
||||
The `fork()` semantics on OS X are a bit unusual compared to other unix systems
|
||||
The `fork()` semantics on macOS are a bit unusual compared to other unix systems
|
||||
and definitely don't look POSIX-compliant. This means two things:
|
||||
|
||||
- Fuzzing will be probably slower than on Linux. In fact, some folks report
|
||||
@ -157,39 +167,3 @@ and definitely don't look POSIX-compliant. This means two things:
|
||||
User emulation mode of QEMU does not appear to be supported on macOS, so
|
||||
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
|
||||
works on both x86 and arm64 macOS boxes.
|
||||
|
||||
macOS supports SYSV shared memory used by AFL's instrumentation, but the
|
||||
default settings aren't usable with AFL++. The default settings on 10.14 seem to
|
||||
be:
|
||||
|
||||
```bash
|
||||
$ ipcs -M
|
||||
IPC status from <running system> as of XXX
|
||||
shminfo:
|
||||
shmmax: 4194304 (max shared memory segment size)
|
||||
shmmin: 1 (min shared memory segment size)
|
||||
shmmni: 32 (max number of shared memory identifiers)
|
||||
shmseg: 8 (max shared memory segments per process)
|
||||
shmall: 1024 (max amount of shared memory in pages)
|
||||
```
|
||||
|
||||
To temporarily change your settings to something minimally usable with AFL++,
|
||||
run these commands as root:
|
||||
|
||||
```bash
|
||||
sysctl kern.sysv.shmmax=8388608
|
||||
sysctl kern.sysv.shmall=4096
|
||||
```
|
||||
|
||||
If you're running more than one instance of AFL, you likely want to make
|
||||
`shmall` bigger and increase `shmseg` as well:
|
||||
|
||||
```bash
|
||||
sysctl kern.sysv.shmmax=8388608
|
||||
sysctl kern.sysv.shmseg=48
|
||||
sysctl kern.sysv.shmall=98304
|
||||
```
|
||||
|
||||
See
|
||||
[http://www.spy-hill.com/help/apple/SharedMemory.html](http://www.spy-hill.com/help/apple/SharedMemory.html)
|
||||
for documentation for these settings and how to make them permanent.
|
||||
|
@ -266,6 +266,11 @@ trimmed input. Here's a quick API description:
|
||||
Omitting any of three trimming methods will cause the trimming to be disabled
|
||||
and trigger a fallback to the built-in default trimming routine.
|
||||
|
||||
**IMPORTANT** If you have a custom post process mutator that needs to be run
|
||||
after trimming, you must call it yourself at the end of your successful
|
||||
trimming!
|
||||
|
||||
|
||||
### Environment Variables
|
||||
|
||||
Optionally, the following environment variables are supported:
|
||||
|
@ -381,6 +381,9 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
- Setting `AFL_DISABLE_TRIM` tells afl-fuzz not to trim test cases. This is
|
||||
usually a bad idea!
|
||||
|
||||
- Setting `AFL_DISABLE_REDUNDANT` disables any queue items that are redundant.
|
||||
This can be useful with huge queues.
|
||||
|
||||
- Setting `AFL_KEEP_TIMEOUTS` will keep longer running inputs if they reach
|
||||
new coverage
|
||||
|
||||
@ -547,6 +550,9 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
use a custom afl-qemu-trace or if you need to modify the afl-qemu-trace
|
||||
arguments.
|
||||
|
||||
- `AFL_SHA1_FILENAMES` causes AFL++ to generate files named by the SHA1 hash
|
||||
of their contents, rather than use the standard `id:000000,...` names.
|
||||
|
||||
- `AFL_SHUFFLE_QUEUE` randomly reorders the input queue on startup. Requested
|
||||
by some users for unorthodox parallelized fuzzing setups, but not advisable
|
||||
otherwise.
|
||||
@ -582,6 +588,9 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
between fuzzing instances synchronization. Default sync time is 30 minutes,
|
||||
note that time is halved for -M main nodes.
|
||||
|
||||
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
|
||||
other syncing parameters.
|
||||
|
||||
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
|
||||
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
|
||||
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
|
||||
|
@ -958,7 +958,7 @@ too long for your overall available fuzz run time.
|
||||
campaign but not good for short CI runs.
|
||||
|
||||
How this can look like can, e.g., be seen at AFL++'s setup in Google's
|
||||
[oss-fuzz](https://github.com/google/oss-fuzz/blob/master/infra/base-images/base-builder/compile_afl)
|
||||
[previous oss-fuzz version](https://github.com/google/oss-fuzz/blob/3e2c5312417d1a6f9564472f3df1fd27759b289d/infra/base-images/base-builder/compile_afl)
|
||||
and
|
||||
[clusterfuzz](https://github.com/google/clusterfuzz/blob/master/src/clusterfuzz/_internal/bot/fuzzers/afl/launcher.py).
|
||||
|
||||
|
@ -49,14 +49,23 @@ void instrument_cache_init(void) {
|
||||
|
||||
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
|
||||
|
||||
FFATAL("Failed to setrlimit: %d", errno);
|
||||
FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE",
|
||||
errno);
|
||||
|
||||
}
|
||||
|
||||
map_base =
|
||||
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
|
||||
GUM_PAGE_READ | GUM_PAGE_WRITE);
|
||||
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
|
||||
if (map_base == MAP_FAILED) {
|
||||
|
||||
FFATAL(
|
||||
"Failed to map segment: %d. This can be caused by failure to setrlimit."
|
||||
"Disabling or reducing the size of the allocation using "
|
||||
"AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help",
|
||||
errno);
|
||||
|
||||
}
|
||||
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
|
||||
GUM_ADDRESS(map_base));
|
||||
|
@ -194,24 +194,23 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
|
||||
|
||||
if (details->file == NULL) {
|
||||
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
|
||||
} else {
|
||||
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
|
||||
details->file->path, details->file->offset);
|
||||
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
|
||||
details->file->offset);
|
||||
|
||||
}
|
||||
|
||||
@ -581,7 +580,7 @@ static GArray *merge_ranges(GArray *a) {
|
||||
|
||||
void ranges_print_debug_maps(void) {
|
||||
|
||||
FVERBOSE("Maps");
|
||||
OKF("Maps");
|
||||
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
|
||||
|
||||
}
|
||||
|
@ -2,7 +2,7 @@
|
||||
test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
|
||||
|
||||
OLD=$(grep -E '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
|
||||
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep -E 'frida-gum-devkit-[0-9.]*-linux-x86_64'|head -n 1|sed 's/.*frida-gum-devkit-//'|sed 's/-linux.*//')
|
||||
NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|grep 'Frida\ [0-9.]*'|head -n 1|sed 's/.*Frida\ //'| sed 's/<\/h2>//')
|
||||
|
||||
echo Current set version: $OLD
|
||||
echo Newest available version: $NEW
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -5,9 +5,9 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
Dominik Maier <mail@dmnk.co>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
@ -139,6 +139,10 @@
|
||||
#define AFL_RAND_RETURN u32
|
||||
#endif
|
||||
|
||||
#ifndef INTERESTING_32_LEN
|
||||
#error INTERESTING_32_LEN not defined - BUG!
|
||||
#endif
|
||||
|
||||
extern s8 interesting_8[INTERESTING_8_LEN];
|
||||
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
|
||||
extern s32
|
||||
@ -452,7 +456,8 @@ typedef struct afl_env_vars {
|
||||
afl_keep_timeouts, afl_no_crash_readme, afl_ignore_timeouts,
|
||||
afl_no_startup_calibration, afl_no_warn_instability,
|
||||
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
|
||||
afl_final_sync, afl_ignore_seed_problems;
|
||||
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
|
||||
afl_sha1_filenames, afl_no_sync;
|
||||
|
||||
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
|
||||
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
|
||||
@ -648,7 +653,11 @@ typedef struct afl_state {
|
||||
longest_find_time, /* Longest time taken for a find */
|
||||
exit_on_time, /* Delay to exit if no new paths */
|
||||
sync_time, /* Sync time (ms) */
|
||||
switch_fuzz_mode; /* auto or fixed fuzz mode */
|
||||
switch_fuzz_mode, /* auto or fixed fuzz mode */
|
||||
calibration_time_us, /* Time spend on calibration */
|
||||
sync_time_us, /* Time spend on sync */
|
||||
cmplog_time_us, /* Time spend on cmplog */
|
||||
trim_time_us; /* Time spend on trimming */
|
||||
|
||||
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||
subseq_tmouts; /* Number of timeouts in a row */
|
||||
@ -1215,6 +1224,11 @@ void show_stats_normal(afl_state_t *);
|
||||
void show_stats_pizza(afl_state_t *);
|
||||
void show_init_stats(afl_state_t *);
|
||||
|
||||
void update_calibration_time(afl_state_t *afl, u64 *time);
|
||||
void update_trim_time(afl_state_t *afl, u64 *time);
|
||||
void update_sync_time(afl_state_t *afl, u64 *time);
|
||||
void update_cmplog_time(afl_state_t *afl, u64 *time);
|
||||
|
||||
/* StatsD */
|
||||
|
||||
void statsd_setup_format(afl_state_t *afl);
|
||||
@ -1264,6 +1278,7 @@ void get_core_count(afl_state_t *);
|
||||
void fix_up_sync(afl_state_t *);
|
||||
void check_asan_opts(afl_state_t *);
|
||||
void check_binary(afl_state_t *, u8 *);
|
||||
u64 get_binary_hash(u8 *fn);
|
||||
void check_if_tty(afl_state_t *);
|
||||
void save_cmdline(afl_state_t *, u32, char **);
|
||||
void read_foreign_testcases(afl_state_t *, int);
|
||||
@ -1397,6 +1412,32 @@ void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q, u8 *in,
|
||||
|
||||
void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q, u8 *mem);
|
||||
|
||||
/* Compute the SHA1 hash of `data`, which is of `len` bytes, and return the
|
||||
* result as a `\0`-terminated hex string, which the caller much `ck_free`. */
|
||||
char *sha1_hex(const u8 *data, size_t len);
|
||||
|
||||
/* Apply `sha1_hex` to the first `len` bytes of data of the file at `fname`. */
|
||||
char *sha1_hex_for_file(const char *fname, u32 len);
|
||||
|
||||
/* Create file `fn`, but allow it to already exist if `AFL_SHA1_FILENAMES` is
|
||||
* enabled. */
|
||||
static inline int permissive_create(afl_state_t *afl, const char *fn) {
|
||||
|
||||
int fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||
if (unlikely(fd < 0)) {
|
||||
|
||||
if (!(afl->afl_env.afl_sha1_filenames && errno == EEXIST)) {
|
||||
|
||||
PFATAL("Unable to create '%s'", fn);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return fd;
|
||||
|
||||
}
|
||||
|
||||
#if TESTCASE_CACHE == 1
|
||||
#error define of TESTCASE_CACHE must be zero or larger than 1
|
||||
#endif
|
||||
|
@ -30,10 +30,17 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
#define MUT_STRATEGY_ARRAY_SIZE 256
|
||||
|
||||
#ifndef INTERESTING_32
|
||||
#error INTERESTING_32 is not defined - BUG!
|
||||
#endif
|
||||
|
||||
s8 interesting_8[] = {INTERESTING_8};
|
||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
|
||||
enum {
|
||||
|
||||
/* 00 */ MUT_FLIPBIT,
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -28,7 +28,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
|
||||
static unsigned short int inited = 0;
|
||||
char tcase[PATH_MAX];
|
||||
|
||||
if (is_replay_record) {
|
||||
if (is_replay_record && cycle_cnt) {
|
||||
|
||||
if (!inited) {
|
||||
|
||||
@ -59,7 +59,7 @@ int __afl_persistent_loop(unsigned int max_cnt) {
|
||||
|
||||
}
|
||||
|
||||
return --cycle_cnt;
|
||||
return cycle_cnt--;
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, a = volatile github dev, e = experimental branch
|
||||
#define VERSION "++4.20a"
|
||||
#define VERSION "++4.21c"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -324,9 +324,9 @@
|
||||
#define SYNC_INTERVAL 8
|
||||
|
||||
/* Sync time (minimum time between syncing in ms, time is halfed for -M main
|
||||
nodes) - default is 30 minutes: */
|
||||
nodes) - default is 20 minutes: */
|
||||
|
||||
#define SYNC_TIME (30 * 60 * 1000)
|
||||
#define SYNC_TIME (20 * 60 * 1000)
|
||||
|
||||
/* Output directory reuse grace period (minutes): */
|
||||
|
||||
@ -464,7 +464,7 @@
|
||||
/* Do not change this unless you really know what you are doing. */
|
||||
|
||||
#define MAP_SIZE (1U << MAP_SIZE_POW2)
|
||||
#if MAP_SIZE <= 65536
|
||||
#if MAP_SIZE <= 2097152
|
||||
#define MAP_INITIAL_SIZE (2 << 20) // = 2097152
|
||||
#else
|
||||
#define MAP_INITIAL_SIZE MAP_SIZE
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -21,17 +21,18 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
|
||||
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
|
||||
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
||||
"AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL", "AFL_CRASH_EXITCODE",
|
||||
"AFL_CRASHING_SEEDS_AS_NEW_CRASH", "AFL_CUSTOM_MUTATOR_LIBRARY",
|
||||
"AFL_CUSTOM_MUTATOR_ONLY", "AFL_CUSTOM_INFO_PROGRAM",
|
||||
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
||||
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
|
||||
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN", "AFL_DISABLE_TRIM",
|
||||
"AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
|
||||
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
|
||||
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
|
||||
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
|
||||
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
|
||||
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
|
||||
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
|
||||
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
|
||||
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
|
||||
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
|
||||
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
|
||||
"AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT",
|
||||
"AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION",
|
||||
"AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
|
||||
"AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
|
||||
"AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
|
||||
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
|
||||
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
|
||||
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
|
||||
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
|
||||
@ -80,14 +81,13 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
|
||||
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
|
||||
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
|
||||
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID",
|
||||
"AFL_LLVM_LTO_SKIPINIT"
|
||||
"AFL_LLVM_LTO_STARTID",
|
||||
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
|
||||
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
|
||||
"AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
|
||||
"AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
|
||||
#if defined USE_COLOR && !defined ALWAYS_COLORED
|
||||
"AFL_NO_COLOR", "AFL_NO_COLOUR",
|
||||
#endif
|
||||
"AFL_NO_CPU_RED",
|
||||
"AFL_NO_CPU_RED", "AFL_NO_SYNC",
|
||||
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option
|
||||
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
|
||||
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",
|
||||
@ -95,27 +95,27 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_MAX_DET_EXTRAS",
|
||||
"AFL_NO_X86", // not really an env but we dont want to warn on it
|
||||
"AFL_NOOPT", "AFL_NYX_AUX_SIZE", "AFL_NYX_DISABLE_SNAPSHOT_MODE",
|
||||
"AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT", "AFL_PASSTHROUGH", "AFL_PATH",
|
||||
"AFL_PERFORMANCE_FILE", "AFL_PERSISTENT_RECORD",
|
||||
"AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD", "AFL_TARGET_ENV",
|
||||
"AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN", "AFL_QEMU_COMPCOV",
|
||||
"AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS", "AFL_QEMU_DISABLE_CACHE",
|
||||
"AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL", "AFL_QEMU_PERSISTENT_ADDR",
|
||||
"AFL_QEMU_PERSISTENT_CNT", "AFL_QEMU_PERSISTENT_GPR",
|
||||
"AFL_QEMU_PERSISTENT_HOOK", "AFL_QEMU_PERSISTENT_MEM",
|
||||
"AFL_QEMU_PERSISTENT_RET", "AFL_QEMU_PERSISTENT_RETADDR_OFFSET",
|
||||
"AFL_QEMU_PERSISTENT_EXITS", "AFL_QEMU_INST_RANGES",
|
||||
"AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT", "AFL_QEMU_TRACK_UNSTABLE",
|
||||
"AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY", "AFL_REAL_PATH",
|
||||
"AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
|
||||
"AFL_SKIP_CRASHES", "AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST",
|
||||
"AFL_STATSD_PORT", "AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME",
|
||||
"AFL_TESTCACHE_SIZE", "AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT",
|
||||
"AFL_TMPDIR", "AFL_TOKEN_FILE", "AFL_TRACE_PC", "AFL_USE_ASAN",
|
||||
"AFL_USE_MSAN", "AFL_USE_TRACE_PC", "AFL_USE_UBSAN", "AFL_USE_TSAN",
|
||||
"AFL_USE_CFISAN", "AFL_USE_LSAN", "AFL_WINE_PATH", "AFL_NO_SNAPSHOT",
|
||||
"AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN", "AFL_USE_QASAN",
|
||||
"AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
||||
"AFL_NYX_HANDLE_INVALID_WRITE", "AFL_NYX_LOG", "AFL_NYX_REUSE_SNAPSHOT",
|
||||
"AFL_PASSTHROUGH", "AFL_PATH", "AFL_PERFORMANCE_FILE",
|
||||
"AFL_PERSISTENT_RECORD", "AFL_POST_PROCESS_KEEP_ORIGINAL", "AFL_PRELOAD",
|
||||
"AFL_TARGET_ENV", "AFL_PYTHON_MODULE", "AFL_QEMU_CUSTOM_BIN",
|
||||
"AFL_QEMU_COMPCOV", "AFL_QEMU_COMPCOV_DEBUG", "AFL_QEMU_DEBUG_MAPS",
|
||||
"AFL_QEMU_DISABLE_CACHE", "AFL_QEMU_DRIVER_NO_HOOK", "AFL_QEMU_FORCE_DFL",
|
||||
"AFL_QEMU_PERSISTENT_ADDR", "AFL_QEMU_PERSISTENT_CNT",
|
||||
"AFL_QEMU_PERSISTENT_GPR", "AFL_QEMU_PERSISTENT_HOOK",
|
||||
"AFL_QEMU_PERSISTENT_MEM", "AFL_QEMU_PERSISTENT_RET",
|
||||
"AFL_QEMU_PERSISTENT_RETADDR_OFFSET", "AFL_QEMU_PERSISTENT_EXITS",
|
||||
"AFL_QEMU_INST_RANGES", "AFL_QEMU_EXCLUDE_RANGES", "AFL_QEMU_SNAPSHOT",
|
||||
"AFL_QEMU_TRACK_UNSTABLE", "AFL_QUIET", "AFL_RANDOM_ALLOC_CANARY",
|
||||
"AFL_REAL_PATH", "AFL_SHA1_FILENAMES", "AFL_SHUFFLE_QUEUE",
|
||||
"AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ", "AFL_SKIP_CRASHES",
|
||||
"AFL_SKIP_OSSFUZZ", "AFL_STATSD", "AFL_STATSD_HOST", "AFL_STATSD_PORT",
|
||||
"AFL_STATSD_TAGS_FLAVOR", "AFL_SYNC_TIME", "AFL_TESTCACHE_SIZE",
|
||||
"AFL_TESTCACHE_ENTRIES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
|
||||
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
|
||||
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
|
||||
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
|
||||
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
||||
|
||||
};
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>>
|
||||
|
||||
@ -188,6 +188,8 @@ typedef struct afl_forkserver {
|
||||
|
||||
u8 persistent_mode;
|
||||
|
||||
u32 max_length;
|
||||
|
||||
#ifdef __linux__
|
||||
nyx_plugin_handler_t *nyx_handlers;
|
||||
char *out_dir_path; /* path to the output directory */
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -207,7 +207,7 @@ static __maybe_unused __always_inline unsigned e2k_add64carry_first(
|
||||
return (unsigned)__builtin_e2k_addcd_c(base, addend, 0);
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define add64carry_first(base, addend, sum) \
|
||||
e2k_add64carry_first(base, addend, sum)
|
||||
|
||||
@ -218,7 +218,7 @@ static __maybe_unused __always_inline unsigned e2k_add64carry_next(
|
||||
return (unsigned)__builtin_e2k_addcd_c(base, addend, carry);
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define add64carry_next(carry, base, addend, sum) \
|
||||
e2k_add64carry_next(carry, base, addend, sum)
|
||||
|
||||
@ -230,7 +230,7 @@ static __maybe_unused __always_inline void e2k_add64carry_last(unsigned carry,
|
||||
*sum = __builtin_e2k_addcd(base, addend, carry);
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define add64carry_last(carry, base, addend, sum) \
|
||||
e2k_add64carry_last(carry, base, addend, sum)
|
||||
#endif /* __iset__ >= 5 */
|
||||
@ -311,7 +311,7 @@ static __forceinline char msvc32_add64carry_first(uint64_t base,
|
||||
base_32h, addend_32h, sum32 + 1);
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define add64carry_first(base, addend, sum) \
|
||||
msvc32_add64carry_first(base, addend, sum)
|
||||
|
||||
@ -328,7 +328,7 @@ static __forceinline char msvc32_add64carry_next(char carry, uint64_t base,
|
||||
base_32h, addend_32h, sum32 + 1);
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define add64carry_next(carry, base, addend, sum) \
|
||||
msvc32_add64carry_next(carry, base, addend, sum)
|
||||
|
||||
@ -345,7 +345,7 @@ static __forceinline void msvc32_add64carry_last(char carry, uint64_t base,
|
||||
addend_32h, sum32 + 1);
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define add64carry_last(carry, base, addend, sum) \
|
||||
msvc32_add64carry_last(carry, base, addend, sum)
|
||||
#endif /* _MSC_FULL_VER >= 190024231 */
|
||||
@ -454,7 +454,7 @@ typedef struct {
|
||||
uint64_t unaligned_64;
|
||||
|
||||
} __attribute__((__packed__)) t1ha_unaligned_proxy;
|
||||
\
|
||||
|
||||
#define read_unaligned(ptr, bits) \
|
||||
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \
|
||||
t1ha_unaligned_proxy, unaligned_##bits))) \
|
||||
@ -539,6 +539,7 @@ static __always_inline const uint64_t *__attribute__((
|
||||
(void)(ptr); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif /* prefetch */
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -1734,7 +1734,7 @@ XXH128_hashFromCanonical(XXH_NOESCAPE const XXH128_canonical_t *src);
|
||||
* These declarations should only be used with static linking.
|
||||
* Never use them in association with dynamic linking!
|
||||
*****************************************************************************
|
||||
*/
|
||||
*/
|
||||
|
||||
/*
|
||||
* These definitions are only present to allow static allocation
|
||||
@ -2399,9 +2399,9 @@ XXH_PUBLIC_API XXH_errorcode XXH3_128bits_reset_withSecretandSeed(
|
||||
#define XXH_NO_STREAM
|
||||
#undef XXH_NO_STREAM /* don't actually */
|
||||
#endif /* XXH_DOXYGEN */
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
/*!
|
||||
* @}
|
||||
*/
|
||||
|
||||
#ifndef XXH_FORCE_MEMORY_ACCESS /* can be defined externally, on command \
|
||||
line for example */
|
||||
@ -2614,6 +2614,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) {
|
||||
_Static_assert((c), m); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#elif defined(__cplusplus) && (__cplusplus >= 201103L) /* C++11 */
|
||||
#define XXH_STATIC_ASSERT_WITH_MESSAGE(c, m) \
|
||||
do { \
|
||||
@ -2621,6 +2622,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) {
|
||||
static_assert((c), m); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#define XXH_STATIC_ASSERT_WITH_MESSAGE(c, m) \
|
||||
do { \
|
||||
@ -2632,6 +2634,7 @@ static void *XXH_memcpy(void *dest, const void *src, size_t size) {
|
||||
}; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#define XXH_STATIC_ASSERT(c) XXH_STATIC_ASSERT_WITH_MESSAGE((c), #c)
|
||||
#endif
|
||||
@ -2850,7 +2853,7 @@ static int XXH_isLittleEndian(void) {
|
||||
return one.c[0];
|
||||
|
||||
}
|
||||
\
|
||||
|
||||
#define XXH_CPU_LITTLE_ENDIAN XXH_isLittleEndian()
|
||||
#endif
|
||||
#endif
|
||||
@ -4679,6 +4682,7 @@ XXH_FORCE_INLINE xxh_u64x2 XXH_vec_mule(xxh_u32x4 a, xxh_u32x4 b) {
|
||||
acc = svadd_u64_x(mask, acc, mul); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif /* XXH_VECTOR == XXH_SVE */
|
||||
|
||||
/* prefetch
|
||||
@ -4737,12 +4741,14 @@ static const xxh_u8 XXH3_kSecret[XXH_SECRET_DEFAULT_SIZE] = {
|
||||
|
||||
};
|
||||
|
||||
static const xxh_u64 PRIME_MX1 = 0x165667919E3779F9ULL; /*!<
|
||||
0b0001011001010110011001111001000110011110001101110111100111111001
|
||||
*/
|
||||
static const xxh_u64 PRIME_MX2 = 0x9FB21C651E98DF25ULL; /*!<
|
||||
0b1001111110110010000111000110010100011110100110001101111100100101
|
||||
*/
|
||||
static const xxh_u64 PRIME_MX1 =
|
||||
0x165667919E3779F9ULL; /*!<
|
||||
0b0001011001010110011001111001000110011110001101110111100111111001
|
||||
*/
|
||||
static const xxh_u64 PRIME_MX2 =
|
||||
0x9FB21C651E98DF25ULL; /*!<
|
||||
0b1001111110110010000111000110010100011110100110001101111100100101
|
||||
*/
|
||||
|
||||
#ifdef XXH_OLD_NAMES
|
||||
#define kSecret XXH3_kSecret
|
||||
@ -7854,7 +7860,7 @@ XXH3_128bits_digest(XXH_NOESCAPE const XXH3_state_t *state) {
|
||||
}
|
||||
|
||||
#endif /* !XXH_NO_STREAM */
|
||||
/* 128-bit utility functions */
|
||||
/* 128-bit utility functions */
|
||||
|
||||
#include <string.h> /* memcmp, memcpy */
|
||||
|
||||
|
@ -486,7 +486,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
|
||||
|
||||
dFile.open(ptr, std::ofstream::out | std::ofstream::app);
|
||||
if (dFile.is_open()) WARNF("Cannot access document file %s", ptr);
|
||||
if (!dFile.is_open()) WARNF("Cannot access document file %s", ptr);
|
||||
|
||||
}
|
||||
|
||||
@ -1304,7 +1304,12 @@ u32 countCallers(Function *F) {
|
||||
|
||||
for (auto *U : F->users()) {
|
||||
|
||||
if (auto *CI = dyn_cast<CallInst>(U)) { ++callers; }
|
||||
if (auto *CI = dyn_cast<CallInst>(U)) {
|
||||
|
||||
++callers;
|
||||
(void)(CI);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -195,7 +195,7 @@ class ModuleSanitizerCoverageAFL
|
||||
|
||||
SanitizerCoverageOptions Options;
|
||||
|
||||
uint32_t instr = 0, selects = 0, unhandled = 0;
|
||||
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0;
|
||||
GlobalVariable *AFLMapPtr = NULL;
|
||||
ConstantInt *One = NULL;
|
||||
ConstantInt *Zero = NULL;
|
||||
@ -330,6 +330,8 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||
|
||||
if (getenv("AFL_DEBUG")) { debug = 1; }
|
||||
|
||||
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
|
||||
|
||||
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
|
||||
|
||||
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
|
||||
@ -638,6 +640,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||
// InjectTraceForCmp(F, CmpTraceTargets);
|
||||
// InjectTraceForSwitch(F, SwitchTraceTargets);
|
||||
|
||||
if (dump_cc) { calcCyclomaticComplexity(&F); }
|
||||
|
||||
}
|
||||
|
||||
GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
|
||||
|
@ -1617,7 +1617,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
||||
|
||||
}
|
||||
|
||||
if (pc_filter) {
|
||||
if (pc_filter && !mod_info->next) {
|
||||
|
||||
char PcDescr[1024];
|
||||
// This function is a part of the sanitizer run-time.
|
||||
@ -1644,7 +1644,8 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
||||
|
||||
}
|
||||
|
||||
if (__afl_filter_pcs && strstr(mod_info->name, __afl_filter_pcs_module)) {
|
||||
if (__afl_filter_pcs && !mod_info->next &&
|
||||
strstr(mod_info->name, __afl_filter_pcs_module)) {
|
||||
|
||||
u32 result_index;
|
||||
if (locate_in_pcs(PC, &result_index)) {
|
||||
@ -1669,7 +1670,7 @@ void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
|
||||
|
||||
}
|
||||
|
||||
mod_info->mapped = 1;
|
||||
if (__afl_pcmap_ptr) { mod_info->mapped = 1; }
|
||||
|
||||
if (__afl_debug) {
|
||||
|
||||
@ -1848,7 +1849,7 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
|
||||
to avoid duplicate calls (which can happen as an artifact of the underlying
|
||||
implementation in LLVM). */
|
||||
|
||||
if (__afl_final_loc < 5) __afl_final_loc = 5; // we skip the first 5 entries
|
||||
if (__afl_final_loc < 4) __afl_final_loc = 4; // we skip the first 5 entries
|
||||
|
||||
*(start++) = ++__afl_final_loc;
|
||||
|
||||
|
@ -180,19 +180,19 @@ struct afl_cmptrs_pass : afl_base_pass {
|
||||
c = DECL_CONTEXT(c);
|
||||
if (c && TREE_CODE(c) != TRANSLATION_UNIT_DECL) return false;
|
||||
|
||||
/* Check that the first nonstatic data member of the record type
|
||||
/* Check that the first nonstatic named data member of the record type
|
||||
is named _M_dataplus. */
|
||||
for (c = TYPE_FIELDS(t); c; c = DECL_CHAIN(c))
|
||||
if (TREE_CODE(c) == FIELD_DECL) break;
|
||||
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
|
||||
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
|
||||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_dataplus") != 0)
|
||||
return false;
|
||||
|
||||
/* Check that the second nonstatic data member of the record type
|
||||
/* Check that the second nonstatic named data member of the record type
|
||||
is named _M_string_length. */
|
||||
tree f2;
|
||||
for (f2 = DECL_CHAIN(c); f2; f2 = DECL_CHAIN(f2))
|
||||
if (TREE_CODE(f2) == FIELD_DECL) break;
|
||||
if (TREE_CODE(f2) == FIELD_DECL && DECL_NAME(f2)) break;
|
||||
if (!f2 /* No need to check this field's offset. */
|
||||
|| strcmp(IDENTIFIER_POINTER(DECL_NAME(f2)), "_M_string_length") != 0)
|
||||
return false;
|
||||
@ -208,9 +208,12 @@ struct afl_cmptrs_pass : afl_base_pass {
|
||||
strcmp(IDENTIFIER_POINTER(TYPE_IDENTIFIER(c)), "_Alloc_hider") != 0)
|
||||
return false;
|
||||
|
||||
/* And its first data member is named _M_p. */
|
||||
/* And its first nonstatic named data member should be named _M_p.
|
||||
There may be (unnamed) subobjects from empty base classes. We
|
||||
skip the subobjects, then check the offset of the first data
|
||||
member. */
|
||||
for (c = TYPE_FIELDS(c); c; c = DECL_CHAIN(c))
|
||||
if (TREE_CODE(c) == FIELD_DECL) break;
|
||||
if (TREE_CODE(c) == FIELD_DECL && DECL_NAME(c)) break;
|
||||
if (!c || !integer_zerop(DECL_FIELD_BIT_OFFSET(c)) ||
|
||||
strcmp(IDENTIFIER_POINTER(DECL_NAME(c)), "_M_p") != 0)
|
||||
return false;
|
||||
|
@ -26,6 +26,51 @@ static std::list<std::string> allowListFunctions;
|
||||
static std::list<std::string> denyListFiles;
|
||||
static std::list<std::string> denyListFunctions;
|
||||
|
||||
unsigned int calcCyclomaticComplexity(llvm::Function *F) {
|
||||
|
||||
unsigned int numBlocks = 0;
|
||||
unsigned int numEdges = 0;
|
||||
unsigned int numCalls = 0;
|
||||
|
||||
// Iterate through each basic block in the function
|
||||
for (BasicBlock &BB : *F) {
|
||||
|
||||
// count all nodes == basic blocks
|
||||
numBlocks++;
|
||||
// Count the number of successors (outgoing edges)
|
||||
for (BasicBlock *Succ : successors(&BB)) {
|
||||
|
||||
// count edges for CC
|
||||
numEdges++;
|
||||
(void)(Succ);
|
||||
|
||||
}
|
||||
|
||||
for (Instruction &I : BB) {
|
||||
|
||||
// every call is also an edge, so we need to count the calls too
|
||||
if (isa<CallInst>(&I) || isa<InvokeInst>(&I)) { numCalls++; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Cyclomatic Complexity V(G) = E - N + 2P
|
||||
// For a single function, P (number of connected components) is 1
|
||||
// Calls are considered to be an edge
|
||||
unsigned int CC = 2 + numCalls + numEdges - numBlocks;
|
||||
|
||||
// if (debug) {
|
||||
|
||||
fprintf(stderr, "CyclomaticComplexity for %s: %u\n",
|
||||
F->getName().str().c_str(), CC);
|
||||
|
||||
//}
|
||||
|
||||
return CC;
|
||||
|
||||
}
|
||||
|
||||
char *getBBName(const llvm::BasicBlock *BB) {
|
||||
|
||||
static char *name;
|
||||
@ -91,7 +136,11 @@ bool isIgnoreFunction(const llvm::Function *F) {
|
||||
|
||||
for (auto const &ignoreListFunc : ignoreList) {
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
if (F->getName().starts_with(ignoreListFunc)) { return true; }
|
||||
#else
|
||||
if (F->getName().startswith(ignoreListFunc)) { return true; }
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -55,6 +55,7 @@ void initInstrumentList();
|
||||
bool isInInstrumentList(llvm::Function *F, std::string Filename);
|
||||
unsigned long long int calculateCollisions(uint32_t edges);
|
||||
void scanForDangerousFunctions(llvm::Module *M);
|
||||
unsigned int calcCyclomaticComplexity(llvm::Function *F);
|
||||
|
||||
#ifndef IS_EXTERN
|
||||
#define IS_EXTERN
|
||||
|
@ -746,7 +746,7 @@ bool AFLdict2filePass::runOnModule(Module &M) {
|
||||
auto PA = PreservedAnalyses::all();
|
||||
return PA;
|
||||
#else
|
||||
return true;
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -128,7 +128,11 @@ llvmGetPassPluginInfo() {
|
||||
#if LLVM_VERSION_MAJOR <= 13
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
|
||||
MPM.addPass(AFLCoverage());
|
||||
@ -212,10 +216,6 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
u32 rand_seed;
|
||||
unsigned int cur_loc = 0;
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
|
||||
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
|
||||
gettimeofday(&tv, &tz);
|
||||
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
||||
@ -1081,7 +1081,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
}
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
return PA;
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
|
@ -680,13 +680,16 @@ bool CmpLogInstructions::runOnModule(Module &M) {
|
||||
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
be_quiet = 1;
|
||||
hookInstrs(M);
|
||||
bool ret = hookInstrs(M);
|
||||
verifyModule(M);
|
||||
|
||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||
return PreservedAnalyses::all();
|
||||
if (ret == false)
|
||||
return PreservedAnalyses::all();
|
||||
else
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -758,16 +758,16 @@ bool CmpLogRoutines::runOnModule(Module &M) {
|
||||
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
be_quiet = 1;
|
||||
hookRtns(M);
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
bool ret = hookRtns(M);
|
||||
verifyModule(M);
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
return PA;
|
||||
if (ret == false)
|
||||
return PreservedAnalyses::all();
|
||||
else
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -442,16 +442,16 @@ bool CmplogSwitches::runOnModule(Module &M) {
|
||||
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
be_quiet = 1;
|
||||
hookInstrs(M);
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
bool ret = hookInstrs(M);
|
||||
verifyModule(M);
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
return PA;
|
||||
if (ret == false)
|
||||
return PreservedAnalyses::all();
|
||||
else
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -54,6 +54,12 @@
|
||||
#define nullptr 0
|
||||
#endif
|
||||
|
||||
#if LLVM_MAJOR >= 19
|
||||
#define STARTSWITH starts_with
|
||||
#else
|
||||
#define STARTSWITH startswith
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
@ -89,7 +95,7 @@ class CompareTransform : public ModulePass {
|
||||
|
||||
#endif
|
||||
|
||||
return "cmplog transform";
|
||||
return "compcov transform";
|
||||
|
||||
}
|
||||
|
||||
@ -123,7 +129,11 @@ llvmGetPassPluginInfo() {
|
||||
#if LLVM_VERSION_MAJOR <= 13
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
|
||||
MPM.addPass(CompareTransform());
|
||||
@ -226,38 +236,38 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
||||
if (callInst->getCallingConv() != llvm::CallingConv::C) continue;
|
||||
StringRef FuncName = Callee->getName();
|
||||
isStrcmp &=
|
||||
(!FuncName.compare("strcmp") || !FuncName.compare("xmlStrcmp") ||
|
||||
(!FuncName.compare("strcmp") /*|| !FuncName.compare("xmlStrcmp") ||
|
||||
!FuncName.compare("xmlStrEqual") ||
|
||||
!FuncName.compare("curl_strequal") ||
|
||||
!FuncName.compare("strcsequal") ||
|
||||
!FuncName.compare("g_strcmp0"));
|
||||
!FuncName.compare("g_strcmp0")*/);
|
||||
isMemcmp &=
|
||||
(!FuncName.compare("memcmp") || !FuncName.compare("bcmp") ||
|
||||
!FuncName.compare("CRYPTO_memcmp") ||
|
||||
!FuncName.compare("OPENSSL_memcmp") ||
|
||||
!FuncName.compare("memcmp_const_time") ||
|
||||
!FuncName.compare("memcmpct"));
|
||||
isStrncmp &= (!FuncName.compare("strncmp") ||
|
||||
isStrncmp &= (!FuncName.compare("strncmp")/* ||
|
||||
!FuncName.compare("curl_strnequal") ||
|
||||
!FuncName.compare("xmlStrncmp"));
|
||||
!FuncName.compare("xmlStrncmp")*/);
|
||||
isStrcasecmp &= (!FuncName.compare("strcasecmp") ||
|
||||
!FuncName.compare("stricmp") ||
|
||||
!FuncName.compare("ap_cstr_casecmp") ||
|
||||
!FuncName.compare("OPENSSL_strcasecmp") ||
|
||||
!FuncName.compare("xmlStrcasecmp") ||
|
||||
/*!FuncName.compare("xmlStrcasecmp") ||
|
||||
!FuncName.compare("g_strcasecmp") ||
|
||||
!FuncName.compare("g_ascii_strcasecmp") ||
|
||||
!FuncName.compare("Curl_strcasecompare") ||
|
||||
!FuncName.compare("Curl_safe_strcasecompare") ||
|
||||
!FuncName.compare("Curl_safe_strcasecompare") ||*/
|
||||
!FuncName.compare("cmsstrcasecmp"));
|
||||
isStrncasecmp &= (!FuncName.compare("strncasecmp") ||
|
||||
!FuncName.compare("strnicmp") ||
|
||||
!FuncName.compare("ap_cstr_casecmpn") ||
|
||||
!FuncName.compare("OPENSSL_strncasecmp") ||
|
||||
!FuncName.compare("OPENSSL_strncasecmp") /*||
|
||||
!FuncName.compare("xmlStrncasecmp") ||
|
||||
!FuncName.compare("g_ascii_strncasecmp") ||
|
||||
!FuncName.compare("Curl_strncasecompare") ||
|
||||
!FuncName.compare("g_strncasecmp"));
|
||||
!FuncName.compare("g_strncasecmp")*/);
|
||||
isIntMemcpy &= !FuncName.compare("llvm.memcpy.p0i8.p0i8.i64");
|
||||
|
||||
if (!isStrcmp && !isMemcmp && !isStrncmp && !isStrcasecmp &&
|
||||
@ -461,8 +471,20 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
||||
bool isCaseInsensitive = false;
|
||||
bool needs_null = false;
|
||||
bool success_is_one = false;
|
||||
bool nullCheck = false;
|
||||
Function *Callee = callInst->getCalledFunction();
|
||||
|
||||
/*
|
||||
fprintf(stderr, "%s - %s - %s\n",
|
||||
callInst->getParent()
|
||||
->getParent()
|
||||
->getParent()
|
||||
->getName()
|
||||
.str()
|
||||
.c_str(),
|
||||
callInst->getParent()->getParent()->getName().str().c_str(),
|
||||
Callee ? Callee->getName().str().c_str() : "NULL");*/
|
||||
|
||||
if (Callee) {
|
||||
|
||||
if (!Callee->getName().compare("memcmp") ||
|
||||
@ -516,6 +538,11 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
||||
}
|
||||
|
||||
if (!isSizedcmp) needs_null = true;
|
||||
if (Callee->getName().STARTSWITH("g_") ||
|
||||
Callee->getName().STARTSWITH("curl_") ||
|
||||
Callee->getName().STARTSWITH("Curl_") ||
|
||||
Callee->getName().STARTSWITH("xml"))
|
||||
nullCheck = true;
|
||||
|
||||
Value *sizedValue = isSizedcmp ? callInst->getArgOperand(2) : NULL;
|
||||
bool isConstSized = sizedValue && isa<ConstantInt>(sizedValue);
|
||||
@ -600,8 +627,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
|
||||
/* split before the call instruction */
|
||||
BasicBlock *bb = callInst->getParent();
|
||||
BasicBlock *end_bb = bb->splitBasicBlock(BasicBlock::iterator(callInst));
|
||||
|
||||
BasicBlock *next_lenchk_bb = NULL;
|
||||
|
||||
if (nullCheck) { fprintf(stderr, "TODO: null check\n"); }
|
||||
|
||||
if (isSizedcmp && !isConstSized) {
|
||||
|
||||
next_lenchk_bb =
|
||||
@ -746,6 +775,8 @@ bool CompareTransform::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
bool ret = false;
|
||||
|
||||
if ((isatty(2) && getenv("AFL_QUIET") == NULL) || getenv("AFL_DEBUG") != NULL)
|
||||
printf(
|
||||
"Running compare-transform-pass by laf.intel@gmail.com, extended by "
|
||||
@ -753,11 +784,7 @@ bool CompareTransform::runOnModule(Module &M) {
|
||||
else
|
||||
be_quiet = 1;
|
||||
|
||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
|
||||
transformCmps(M, true, true, true, true, true);
|
||||
if (transformCmps(M, true, true, true, true, true) == true) ret = true;
|
||||
verifyModule(M);
|
||||
|
||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||
@ -767,9 +794,18 @@ bool CompareTransform::runOnModule(Module &M) {
|
||||
|
||||
}*/
|
||||
|
||||
return PA;
|
||||
if (ret == true) {
|
||||
|
||||
return PreservedAnalyses();
|
||||
|
||||
} else {
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -204,6 +204,8 @@ bool InjectionRoutines::hookRtns(Module &M) {
|
||||
Function *FuncPtr;
|
||||
#endif
|
||||
|
||||
bool ret = false;
|
||||
|
||||
/* iterate over all functions, bbs and instruction and add suitable calls */
|
||||
for (auto &F : M) {
|
||||
|
||||
@ -281,6 +283,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
|
||||
|
||||
IRBuilder<> IRB(callInst->getParent());
|
||||
IRB.SetInsertPoint(callInst);
|
||||
ret = true;
|
||||
|
||||
Value *parameter = callInst->getArgOperand(param);
|
||||
|
||||
@ -299,7 +302,7 @@ bool InjectionRoutines::hookRtns(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
return true;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -328,16 +331,16 @@ bool InjectionRoutines::runOnModule(Module &M) {
|
||||
if (getenv("AFL_LLVM_INJECTIONS_LDAP")) { doLDAP = true; }
|
||||
if (getenv("AFL_LLVM_INJECTIONS_XSS")) { doXSS = true; }
|
||||
|
||||
hookRtns(M);
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
bool ret = hookRtns(M);
|
||||
verifyModule(M);
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
return PA;
|
||||
if (ret == false)
|
||||
return PreservedAnalyses::all();
|
||||
else
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -1,7 +1,7 @@
|
||||
/*
|
||||
* Copyright 2016 laf-intel
|
||||
* extended for floating point by Heiko Eißfeldt
|
||||
* adapted to new pass manager by Heiko Eißfeldt
|
||||
* extended for floating point by Heiko Eissfeldt
|
||||
* adapted to new pass manager by Heiko Eissfeldt
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
@ -189,7 +189,11 @@ llvmGetPassPluginInfo() {
|
||||
#if LLVM_VERSION_MAJOR <= 13
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
|
||||
MPM.addPass(SplitComparesTransform());
|
||||
@ -262,8 +266,11 @@ bool SplitComparesTransform::simplifyFPCompares(Module &M) {
|
||||
|
||||
/* this is probably not needed but we do it anyway */
|
||||
if (TyOp0 != TyOp1) { continue; }
|
||||
|
||||
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
|
||||
int constants = 0;
|
||||
if (llvm::isa<llvm::Constant>(op0)) { ++constants; }
|
||||
if (llvm::isa<llvm::Constant>(op1)) { ++constants; }
|
||||
if (constants != 1) { continue; }
|
||||
|
||||
fcomps.push_back(selectcmpInst);
|
||||
|
||||
@ -935,7 +942,7 @@ size_t SplitComparesTransform::nextPowerOfTwo(size_t in) {
|
||||
/* splits fcmps into two nested fcmps with sign compare and the rest */
|
||||
size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
size_t count = 0;
|
||||
size_t counts = 0;
|
||||
|
||||
LLVMContext &C = M.getContext();
|
||||
|
||||
@ -951,7 +958,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
} else {
|
||||
|
||||
return count;
|
||||
return counts;
|
||||
|
||||
}
|
||||
|
||||
@ -1004,7 +1011,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
if (!fcomps.size()) { return count; }
|
||||
if (!fcomps.size()) { return counts; }
|
||||
|
||||
IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
|
||||
|
||||
@ -1690,11 +1697,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
#else
|
||||
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
|
||||
#endif
|
||||
++count;
|
||||
++counts;
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
return counts;
|
||||
|
||||
}
|
||||
|
||||
@ -1743,10 +1750,6 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
#if LLVM_MAJOR >= 11
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
|
||||
if (enableFPSplit) {
|
||||
|
||||
simplifyFPCompares(M);
|
||||
@ -1778,15 +1781,13 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
||||
|
||||
auto op0 = CI->getOperand(0);
|
||||
auto op1 = CI->getOperand(1);
|
||||
if (!op0 || !op1) {
|
||||
|
||||
#if LLVM_MAJOR >= 11
|
||||
return PA;
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
|
||||
}
|
||||
// has to valid operands
|
||||
if (!op0 || !op1) { continue; }
|
||||
// has exactly one constant and one variable
|
||||
int constants = 0;
|
||||
if (dyn_cast<ConstantInt>(op0)) { ++constants; }
|
||||
if (dyn_cast<ConstantInt>(op1)) { ++constants; }
|
||||
if (constants != 1) { continue; }
|
||||
|
||||
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
|
||||
if (iTy1 && isa<IntegerType>(op1->getType())) {
|
||||
@ -1814,6 +1815,8 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
bool ret = count == 0 ? false : true;
|
||||
|
||||
bool brokenDebug = false;
|
||||
if (verifyModule(M, &errs()
|
||||
#if LLVM_VERSION_MAJOR >= 4 || \
|
||||
@ -1852,9 +1855,12 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
||||
|
||||
}*/
|
||||
|
||||
return PA;
|
||||
if (ret == false)
|
||||
return PreservedAnalyses::all();
|
||||
else
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -137,7 +137,11 @@ llvmGetPassPluginInfo() {
|
||||
#if LLVM_VERSION_MAJOR <= 13
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
|
||||
MPM.addPass(SplitSwitchesTransform());
|
||||
@ -516,11 +520,7 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
|
||||
else
|
||||
be_quiet = 1;
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
|
||||
splitSwitches(M);
|
||||
bool ret = splitSwitches(M);
|
||||
verifyModule(M);
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
@ -530,9 +530,12 @@ bool SplitSwitchesTransform::runOnModule(Module &M) {
|
||||
|
||||
}*/
|
||||
|
||||
return PA;
|
||||
if (ret == false)
|
||||
return PreservedAnalyses::all();
|
||||
else
|
||||
return PreservedAnalyses();
|
||||
#else
|
||||
return true;
|
||||
return ret;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
@ -1 +1 @@
|
||||
40033af00c
|
||||
a6f0632a65
|
||||
|
@ -202,6 +202,8 @@ QEMU_CONF_FLAGS=" \
|
||||
--disable-xfsctl \
|
||||
--target-list="${CPU_TARGET}-linux-user" \
|
||||
--without-default-devices \
|
||||
--extra-cflags=-Wno-int-conversion \
|
||||
--disable-werror \
|
||||
"
|
||||
|
||||
if [ -n "${CROSS_PREFIX}" ]; then
|
||||
@ -215,8 +217,10 @@ if [ "$STATIC" = "1" ]; then
|
||||
echo Building STATIC binary
|
||||
|
||||
# static PIE causes https://github.com/AFLplusplus/AFLplusplus/issues/892
|
||||
# plugin support requires dynamic linking
|
||||
QEMU_CONF_FLAGS="$QEMU_CONF_FLAGS \
|
||||
--static --disable-pie \
|
||||
--disable-plugins \
|
||||
--extra-cflags=-DAFL_QEMU_STATIC_BUILD=1 \
|
||||
"
|
||||
|
||||
@ -241,7 +245,6 @@ if [ "$DEBUG" = "1" ]; then
|
||||
--enable-debug-stack-usage \
|
||||
--enable-debug-tcg \
|
||||
--enable-qom-cast-debug \
|
||||
--enable-werror \
|
||||
"
|
||||
|
||||
else
|
||||
@ -252,7 +255,6 @@ else
|
||||
--disable-debug-tcg \
|
||||
--disable-qom-cast-debug \
|
||||
--disable-stack-protector \
|
||||
--disable-werror \
|
||||
--disable-docs \
|
||||
"
|
||||
|
||||
|
Submodule qemu_mode/qemuafl updated: 40033af00c...a6f0632a65
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
|
111
src/afl-cc.c
111
src/afl-cc.c
@ -17,6 +17,10 @@
|
||||
|
||||
#define AFL_MAIN
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE 1
|
||||
#endif
|
||||
|
||||
#include "common.h"
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
@ -32,7 +36,9 @@
|
||||
#include <limits.h>
|
||||
#include <assert.h>
|
||||
#include <ctype.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#if (LLVM_MAJOR - 0 == 0)
|
||||
#undef LLVM_MAJOR
|
||||
@ -464,6 +470,8 @@ u8 *find_object(aflcc_state_t *aflcc, u8 *obj) {
|
||||
*slash = 0;
|
||||
tmp = alloc_printf("%s/%s", exepath, obj);
|
||||
|
||||
if (aflcc->debug) DEBUGF("Trying %s\n", tmp);
|
||||
|
||||
if (!access(tmp, R_OK)) { return tmp; }
|
||||
|
||||
ck_free(tmp);
|
||||
@ -517,8 +525,8 @@ void find_built_deps(aflcc_state_t *aflcc) {
|
||||
|
||||
char *ptr = NULL;
|
||||
|
||||
#if defined(__x86_64__)
|
||||
if ((ptr = find_object(aflcc, "as")) != NULL) {
|
||||
#if defined(__x86_64__) || defined(__i386__)
|
||||
if ((ptr = find_object(aflcc, "afl-as")) != NULL) {
|
||||
|
||||
#ifndef __APPLE__
|
||||
// on OSX clang masquerades as GCC
|
||||
@ -828,7 +836,8 @@ static void instrument_mode_old_environ(aflcc_state_t *aflcc) {
|
||||
}
|
||||
|
||||
if (getenv("AFL_LLVM_CTX")) aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CTX;
|
||||
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") || getenv("AFL_LLVM_LTO_CTX"))
|
||||
if (getenv("AFL_LLVM_CALLER") || getenv("AFL_LLVM_LTO_CALLER") ||
|
||||
getenv("AFL_LLVM_LTO_CTX"))
|
||||
aflcc->instrument_opt_mode |= INSTRUMENT_OPT_CALLER;
|
||||
|
||||
if (getenv("AFL_LLVM_NGRAM_SIZE")) {
|
||||
@ -1260,13 +1269,8 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
aflcc->instrument_mode == INSTRUMENT_PCGUARD) {
|
||||
|
||||
aflcc->lto_mode = 1;
|
||||
// force CFG
|
||||
// if (!aflcc->instrument_mode) {
|
||||
|
||||
aflcc->instrument_mode = INSTRUMENT_PCGUARD;
|
||||
|
||||
// }
|
||||
|
||||
} else if (aflcc->instrument_mode == INSTRUMENT_CLASSIC) {
|
||||
|
||||
aflcc->lto_mode = 1;
|
||||
@ -1368,6 +1372,13 @@ void mode_final_checkout(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_LLVM_DICT2FILE") &&
|
||||
(getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
|
||||
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
|
||||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
|
||||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES")))
|
||||
FATAL("AFL_LLVM_DICT2FILE is incompatible with AFL_LLVM_LAF_*");
|
||||
|
||||
aflcc->cmplog_mode = getenv("AFL_CMPLOG") || getenv("AFL_LLVM_CMPLOG") ||
|
||||
getenv("AFL_GCC_CMPLOG");
|
||||
|
||||
@ -1575,8 +1586,10 @@ void add_defs_persistent_mode(aflcc_state_t *aflcc) {
|
||||
insert_param(aflcc,
|
||||
"-D__AFL_FUZZ_INIT()="
|
||||
"int __afl_sharedmem_fuzzing = 1;"
|
||||
"extern unsigned int *__afl_fuzz_len;"
|
||||
"extern unsigned char *__afl_fuzz_ptr;"
|
||||
"extern __attribute__((visibility(\"default\"))) "
|
||||
"unsigned int *__afl_fuzz_len;"
|
||||
"extern __attribute__((visibility(\"default\"))) "
|
||||
"unsigned char *__afl_fuzz_ptr;"
|
||||
"unsigned char __afl_fuzz_alt[1048576];"
|
||||
"unsigned char *__afl_fuzz_alt_ptr = __afl_fuzz_alt;");
|
||||
|
||||
@ -1898,7 +1911,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
|
||||
}
|
||||
|
||||
add_defs_fortify(aflcc, 0);
|
||||
if (!aflcc->have_asan) { insert_param(aflcc, "-fsanitize=address"); }
|
||||
if (!aflcc->have_asan) {
|
||||
|
||||
insert_param(aflcc, "-fsanitize=address");
|
||||
insert_param(aflcc, "-fno-common");
|
||||
|
||||
}
|
||||
|
||||
aflcc->have_asan = 1;
|
||||
|
||||
} else if (getenv("AFL_USE_MSAN") || aflcc->have_msan) {
|
||||
@ -2347,8 +2366,7 @@ static void add_aflpplib(aflcc_state_t *aflcc) {
|
||||
insert_param(aflcc, afllib);
|
||||
|
||||
#ifdef __APPLE__
|
||||
insert_param(aflcc, "-Wl,-undefined");
|
||||
insert_param(aflcc, "dynamic_lookup");
|
||||
insert_param(aflcc, "-Wl,-undefined,dynamic_lookup");
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -2379,7 +2397,11 @@ void add_runtime(aflcc_state_t *aflcc) {
|
||||
if (aflcc->plusplus_mode && strlen(libdir) && strncmp(libdir, "/usr", 4) &&
|
||||
strncmp(libdir, "/lib", 4)) {
|
||||
|
||||
#ifdef __APPLE__
|
||||
u8 *libdir_opt = strdup("-Wl,-rpath," LLVM_LIBDIR);
|
||||
#else
|
||||
u8 *libdir_opt = strdup("-Wl,-rpath=" LLVM_LIBDIR);
|
||||
#endif
|
||||
insert_param(aflcc, libdir_opt);
|
||||
|
||||
}
|
||||
@ -2461,13 +2483,60 @@ void add_runtime(aflcc_state_t *aflcc) {
|
||||
*/
|
||||
void add_assembler(aflcc_state_t *aflcc) {
|
||||
|
||||
u8 *afl_as = find_object(aflcc, "as");
|
||||
u8 *afl_as = find_object(aflcc, "afl-as");
|
||||
|
||||
if (!afl_as) FATAL("Cannot find 'as' (symlink to 'afl-as').");
|
||||
if (!afl_as) FATAL("Cannot find 'afl-as'.");
|
||||
|
||||
u8 *slash = strrchr(afl_as, '/');
|
||||
if (slash) *slash = 0;
|
||||
|
||||
// Search for 'as' may be unreliable in some cases (see #2058)
|
||||
// so use 'afl-as' instead, because 'as' is usually a symbolic link,
|
||||
// or can be a renamed copy of 'afl-as' created in the same dir.
|
||||
// Now we should verify if the compiler can find the 'as' we need.
|
||||
|
||||
#define AFL_AS_ERR "(should be a symlink or copy of 'afl-as')"
|
||||
|
||||
u8 *afl_as_dup = alloc_printf("%s/as", afl_as);
|
||||
|
||||
int fd = open(afl_as_dup, O_RDONLY);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s' " AFL_AS_ERR, afl_as_dup); }
|
||||
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0) {
|
||||
|
||||
PFATAL("Unable to fstat '%s' " AFL_AS_ERR, afl_as_dup);
|
||||
|
||||
}
|
||||
|
||||
u32 f_len = st.st_size;
|
||||
|
||||
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (f_data == MAP_FAILED) {
|
||||
|
||||
PFATAL("Unable to mmap file '%s' " AFL_AS_ERR, afl_as_dup);
|
||||
|
||||
}
|
||||
|
||||
close(fd);
|
||||
|
||||
// "AFL_AS" is a const str passed to getenv in afl-as.c
|
||||
if (!memmem(f_data, f_len, "AFL_AS", strlen("AFL_AS") + 1)) {
|
||||
|
||||
FATAL(
|
||||
"Looks like '%s' is not a valid symlink or copy of '%s/afl-as'. "
|
||||
"It is a prerequisite to override system-wide 'as' for "
|
||||
"instrumentation.",
|
||||
afl_as_dup, afl_as);
|
||||
|
||||
}
|
||||
|
||||
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
|
||||
|
||||
ck_free(afl_as_dup);
|
||||
|
||||
#undef AFL_AS_ERR
|
||||
|
||||
insert_param(aflcc, "-B");
|
||||
insert_param(aflcc, afl_as);
|
||||
|
||||
@ -2724,11 +2793,11 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
"MODES: NCC PERSIST DICT LAF "
|
||||
"CMPLOG SELECT\n"
|
||||
" [LLVM] LLVM: %s%s\n"
|
||||
" PCGUARD %s yes yes module yes yes "
|
||||
" PCGUARD %s yes yes module yes yes "
|
||||
"yes\n"
|
||||
" NATIVE AVAILABLE no yes no no "
|
||||
"part. yes\n"
|
||||
" CLASSIC %s no yes module yes yes "
|
||||
" CLASSIC %s no yes module yes yes "
|
||||
"yes\n"
|
||||
" - NORMAL\n"
|
||||
" - CALLER\n"
|
||||
@ -2745,10 +2814,10 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
" [GCC/CLANG] simple gcc/clang: %s%s\n"
|
||||
" CLASSIC DEFAULT no no no no no "
|
||||
"no\n\n",
|
||||
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
|
||||
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
|
||||
aflcc->compiler_mode == LLVM ? " [SELECTED]" : "",
|
||||
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
|
||||
aflcc->have_llvm ? "AVAILABLE" : "unavailable!",
|
||||
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
|
||||
aflcc->have_llvm ? "AVAILABLE " : "unavailable!",
|
||||
aflcc->have_lto ? "AVAILABLE" : "unavailable!",
|
||||
aflcc->compiler_mode == LTO ? " [SELECTED]" : "",
|
||||
aflcc->have_gcc_plugin ? "AVAILABLE" : "unavailable!",
|
||||
@ -2774,7 +2843,7 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
" The best is LTO but it often needs RANLIB and AR settings outside "
|
||||
"of afl-cc.\n\n");
|
||||
|
||||
#if LLVM_MAJOR > 10 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
|
||||
#if LLVM_MAJOR >= 11 || (LLVM_MAJOR == 10 && LLVM_MINOR > 0)
|
||||
#define NATIVE_MSG \
|
||||
" LLVM-NATIVE: use llvm's native PCGUARD instrumentation (less " \
|
||||
"performant)\n"
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -34,6 +34,7 @@
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
@ -86,9 +87,10 @@ void set_sanitizer_defaults() {
|
||||
u8 *have_lsan_options = getenv("LSAN_OPTIONS");
|
||||
u8 have_san_options = 0;
|
||||
u8 default_options[1024] =
|
||||
"detect_odr_violation=0:abort_on_error=1:symbolize=0:allocator_may_"
|
||||
"return_null=1:handle_segv=0:handle_sigbus=0:handle_abort=0:handle_"
|
||||
"sigfpe=0:handle_sigill=0:";
|
||||
"detect_odr_violation=0:abort_on_error=1:symbolize=0:"
|
||||
"allocator_may_return_null=1:handle_segv=0:handle_sigbus=0:"
|
||||
"handle_abort=0:handle_sigfpe=0:handle_sigill=0:"
|
||||
"detect_stack_use_after_return=0:check_initialization_order=0:";
|
||||
|
||||
if (have_asan_options || have_ubsan_options || have_msan_options ||
|
||||
have_lsan_options) {
|
||||
@ -985,7 +987,7 @@ inline u64 get_cur_time(void) {
|
||||
|
||||
/* Get unix time in microseconds */
|
||||
|
||||
u64 get_cur_time_us(void) {
|
||||
inline u64 get_cur_time_us(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
@ -27,6 +27,9 @@
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#ifdef AFL_PERSISTENT_RECORD
|
||||
#include "afl-fuzz.h"
|
||||
#endif
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
#include "common.h"
|
||||
@ -575,7 +578,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
void *nyx_config = fsrv->nyx_handlers->nyx_config_load(fsrv->target_path);
|
||||
|
||||
fsrv->nyx_handlers->nyx_config_set_workdir_path(nyx_config, workdir_path);
|
||||
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config, MAX_FILE);
|
||||
fsrv->nyx_handlers->nyx_config_set_input_buffer_size(nyx_config,
|
||||
fsrv->max_length);
|
||||
fsrv->nyx_handlers->nyx_config_set_input_buffer_write_protection(nyx_config,
|
||||
true);
|
||||
|
||||
@ -724,7 +728,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
}
|
||||
|
||||
/* autodict in Nyx mode */
|
||||
if (!ignore_autodict) {
|
||||
if (!ignore_autodict && fsrv->add_extra_func) {
|
||||
|
||||
char *x =
|
||||
alloc_printf("%s/workdir/dump/afl_autodict.txt", fsrv->out_dir_path);
|
||||
@ -1111,7 +1115,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
}
|
||||
|
||||
if ((status & FS_NEW_OPT_SHDMEM_FUZZ)) {
|
||||
if (status & FS_NEW_OPT_SHDMEM_FUZZ) {
|
||||
|
||||
if (fsrv->support_shmem_fuzz) {
|
||||
|
||||
@ -1128,7 +1132,9 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
}
|
||||
|
||||
if ((status & FS_NEW_OPT_AUTODICT)) {
|
||||
if (status & FS_NEW_OPT_AUTODICT) {
|
||||
|
||||
// even if we do not need the dictionary we have to read it
|
||||
|
||||
u32 dict_size;
|
||||
if (read(fsrv->fsrv_st_fd, &dict_size, 4) != 4) {
|
||||
@ -1152,12 +1158,11 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
|
||||
}
|
||||
|
||||
while (dict_size != 0) {
|
||||
while (offset < dict_size) {
|
||||
|
||||
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size);
|
||||
rlen = read(fsrv->fsrv_st_fd, dict + offset, dict_size - offset);
|
||||
if (rlen > 0) {
|
||||
|
||||
dict_size -= rlen;
|
||||
offset += rlen;
|
||||
|
||||
} else {
|
||||
@ -1165,7 +1170,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
FATAL(
|
||||
"Reading autodictionary fail at position %u with %u bytes "
|
||||
"left.",
|
||||
offset, dict_size);
|
||||
offset, dict_size - offset);
|
||||
|
||||
}
|
||||
|
||||
@ -1174,14 +1179,24 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
|
||||
offset = 0;
|
||||
while (offset < dict_size && (u8)dict[offset] + offset < dict_size) {
|
||||
|
||||
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
||||
(u8)dict[offset]);
|
||||
if (!ignore_autodict && fsrv->add_extra_func) {
|
||||
|
||||
fsrv->add_extra_func(fsrv->afl_ptr, dict + offset + 1,
|
||||
(u8)dict[offset]);
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
offset += (1 + dict[offset]);
|
||||
count++;
|
||||
|
||||
}
|
||||
|
||||
if (!be_quiet) { ACTF("Loaded %u autodictionary entries", count); }
|
||||
if (!be_quiet && count) {
|
||||
|
||||
ACTF("Loaded %u autodictionary entries", count);
|
||||
|
||||
}
|
||||
|
||||
ck_free(dict);
|
||||
|
||||
}
|
||||
@ -1640,7 +1655,8 @@ void afl_fsrv_kill(afl_forkserver_t *fsrv) {
|
||||
if (fsrv->fsrv_pid > 0) {
|
||||
|
||||
kill(fsrv->fsrv_pid, fsrv->fsrv_kill_signal);
|
||||
waitpid(fsrv->fsrv_pid, NULL, 0);
|
||||
usleep(25);
|
||||
waitpid(fsrv->fsrv_pid, NULL, WNOHANG);
|
||||
|
||||
}
|
||||
|
||||
@ -1828,6 +1844,8 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
case Timeout:
|
||||
return FSRV_RUN_TMOUT;
|
||||
case InvalidWriteToPayload:
|
||||
if (!!getenv("AFL_NYX_HANDLE_INVALID_WRITE")) { return FSRV_RUN_CRASH; }
|
||||
|
||||
/* ??? */
|
||||
FATAL("FixMe: Nyx InvalidWriteToPayload handler is missing");
|
||||
break;
|
||||
@ -1861,7 +1879,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
territory. */
|
||||
|
||||
#ifdef __linux__
|
||||
if (!fsrv->nyx_mode) {
|
||||
if (likely(!fsrv->nyx_mode)) {
|
||||
|
||||
memset(fsrv->trace_bits, 0, fsrv->map_size);
|
||||
MEM_BARRIER();
|
||||
@ -1931,7 +1949,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
|
||||
if (exec_ms > timeout) {
|
||||
|
||||
/* If there was no response from forkserver after timeout seconds,
|
||||
/* If there was no response from forkserver after timeout milliseconds,
|
||||
we kill the child. The forkserver should inform us afterwards */
|
||||
|
||||
s32 tmp_pid = fsrv->child_pid;
|
||||
@ -2003,7 +2021,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
if (unlikely(fsrv->persistent_record)) {
|
||||
|
||||
retval = FSRV_RUN_TMOUT;
|
||||
persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u";
|
||||
persistent_out_fmt = "%s/hangs/RECORD:%06u,cnt:%06u%s%s";
|
||||
goto store_persistent_record;
|
||||
|
||||
}
|
||||
@ -2039,7 +2057,7 @@ afl_fsrv_run_target(afl_forkserver_t *fsrv, u32 timeout,
|
||||
if (unlikely(fsrv->persistent_record)) {
|
||||
|
||||
retval = FSRV_RUN_CRASH;
|
||||
persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u";
|
||||
persistent_out_fmt = "%s/crashes/RECORD:%06u,cnt:%06u%s%s";
|
||||
goto store_persistent_record;
|
||||
|
||||
}
|
||||
@ -2065,8 +2083,13 @@ store_persistent_record: {
|
||||
u32 len = fsrv->persistent_record_len[entry];
|
||||
if (likely(len && data)) {
|
||||
|
||||
snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
|
||||
fsrv->persistent_record_cnt, writecnt++);
|
||||
snprintf(
|
||||
fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
|
||||
fsrv->persistent_record_cnt, writecnt++,
|
||||
((afl_state_t *)(fsrv->afl_ptr))->file_extension ? "." : "",
|
||||
((afl_state_t *)(fsrv->afl_ptr))->file_extension
|
||||
? (const char *)((afl_state_t *)(fsrv->afl_ptr))->file_extension
|
||||
: "");
|
||||
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||
if (fd >= 0) {
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -527,21 +527,41 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
queue_fn =
|
||||
alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_items,
|
||||
describe_op(afl, new_bits + is_timeout,
|
||||
NAME_MAX - strlen("id:000000,")));
|
||||
if (!afl->afl_env.afl_sha1_filenames) {
|
||||
|
||||
queue_fn = alloc_printf(
|
||||
"%s/queue/id:%06u,%s%s%s", afl->out_dir, afl->queued_items,
|
||||
describe_op(afl, new_bits + is_timeout,
|
||||
NAME_MAX - strlen("id:000000,")),
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
} else {
|
||||
|
||||
const char *hex = sha1_hex(mem, len);
|
||||
queue_fn = alloc_printf(
|
||||
"%s/queue/%s%s%s", afl->out_dir, hex, afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
ck_free((char *)hex);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
queue_fn =
|
||||
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_items);
|
||||
queue_fn = alloc_printf(
|
||||
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", queue_fn); }
|
||||
ck_write(fd, mem, len, queue_fn);
|
||||
close(fd);
|
||||
fd = permissive_create(afl, queue_fn);
|
||||
if (likely(fd >= 0)) {
|
||||
|
||||
ck_write(fd, mem, len, queue_fn);
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
add_to_queue(afl, queue_fn, len, 0);
|
||||
|
||||
if (unlikely(afl->fuzz_mode) &&
|
||||
@ -739,14 +759,29 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
|
||||
afl->saved_hangs,
|
||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")));
|
||||
if (!afl->afl_env.afl_sha1_filenames) {
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s%s%s", afl->out_dir,
|
||||
afl->saved_hangs,
|
||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
} else {
|
||||
|
||||
const char *hex = sha1_hex(mem, len);
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/%s%s%s", afl->out_dir, hex,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
ck_free((char *)hex);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
|
||||
afl->saved_hangs);
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu%s%s", afl->out_dir,
|
||||
afl->saved_hangs, afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
@ -792,14 +827,30 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
||||
afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")));
|
||||
if (!afl->afl_env.afl_sha1_filenames) {
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s",
|
||||
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,sig:00,")),
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
} else {
|
||||
|
||||
const char *hex = sha1_hex(mem, len);
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
ck_free((char *)hex);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
|
||||
afl->saved_crashes, afl->fsrv.last_kill_signal);
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
|
||||
afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
@ -862,10 +913,13 @@ save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
/* If we're here, we apparently want to save the crash or hang
|
||||
test case, too. */
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||
if (unlikely(fd < 0)) { PFATAL("Unable to create '%s'", fn); }
|
||||
ck_write(fd, mem, len, fn);
|
||||
close(fd);
|
||||
fd = permissive_create(afl, fn);
|
||||
if (fd >= 0) {
|
||||
|
||||
ck_write(fd, mem, len, fn);
|
||||
close(fd);
|
||||
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (afl->fsrv.nyx_mode && fault == FSRV_RUN_CRASH) {
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -742,8 +742,11 @@ void save_auto(afl_state_t *afl) {
|
||||
|
||||
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
|
||||
|
||||
u8 *fn =
|
||||
alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
|
||||
u8 *fn = alloc_printf(
|
||||
"%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
s32 fd;
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, DEFAULT_PERMISSION);
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -459,6 +459,24 @@ void bind_to_free_cpu(afl_state_t *afl) {
|
||||
|
||||
#endif /* HAVE_AFFINITY */
|
||||
|
||||
/* transforms spaces in a string to underscores (inplace) */
|
||||
|
||||
static void no_spaces(u8 *string) {
|
||||
|
||||
if (string) {
|
||||
|
||||
u8 *ptr = string;
|
||||
while (*ptr != 0) {
|
||||
|
||||
if (*ptr == ' ') { *ptr = '_'; }
|
||||
++ptr;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Shuffle an array of pointers. Might be slightly biased. */
|
||||
|
||||
static void shuffle_ptrs(afl_state_t *afl, void **ptrs, u32 cnt) {
|
||||
@ -559,6 +577,8 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
afl->stage_cur = 0;
|
||||
afl->stage_max = 0;
|
||||
|
||||
show_stats(afl);
|
||||
|
||||
for (i = 0; i < (u32)nl_cnt; ++i) {
|
||||
|
||||
struct stat st;
|
||||
@ -637,7 +657,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
munmap(mem, st.st_size);
|
||||
close(fd);
|
||||
|
||||
if (st.st_mtime > mtime_max) mtime_max = st.st_mtime;
|
||||
if (st.st_mtime > mtime_max) {
|
||||
|
||||
mtime_max = st.st_mtime;
|
||||
show_stats(afl);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -914,6 +939,14 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
|
||||
res = calibrate_case(afl, q, use_mem, 0, 1);
|
||||
|
||||
/* For AFLFast schedules we update the queue entry */
|
||||
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE) &&
|
||||
likely(q->exec_cksum)) {
|
||||
|
||||
q->n_fuzz_entry = q->exec_cksum % N_FUZZ_SIZE;
|
||||
|
||||
}
|
||||
|
||||
if (afl->stop_soon) { return; }
|
||||
|
||||
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
|
||||
@ -1157,18 +1190,35 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
snprintf(crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s",
|
||||
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||
describe_op(afl, 0,
|
||||
NAME_MAX - strlen("id:000000,sig:00,") -
|
||||
strlen(use_name)),
|
||||
use_name);
|
||||
if (!afl->afl_env.afl_sha1_filenames) {
|
||||
|
||||
snprintf(
|
||||
crash_fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s%s%s%s",
|
||||
afl->out_dir, afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||
describe_op(
|
||||
afl, 0,
|
||||
NAME_MAX - strlen("id:000000,sig:00,") - strlen(use_name)),
|
||||
use_name, afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
} else {
|
||||
|
||||
const char *hex = sha1_hex(use_mem, read_len);
|
||||
snprintf(
|
||||
crash_fn, PATH_MAX, "%s/crashes/%s%s%s", afl->out_dir, hex,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
ck_free((char *)hex);
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
snprintf(crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u",
|
||||
afl->out_dir, afl->saved_crashes,
|
||||
afl->fsrv.last_kill_signal);
|
||||
snprintf(
|
||||
crash_fn, PATH_MAX, "%s/crashes/id_%06llu_%02u%s%s", afl->out_dir,
|
||||
afl->saved_crashes, afl->fsrv.last_kill_signal,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
#endif
|
||||
|
||||
@ -1372,11 +1422,11 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
static void link_or_copy(u8 *old_path, u8 *new_path) {
|
||||
|
||||
s32 i = link(old_path, new_path);
|
||||
if (!i) { return; }
|
||||
|
||||
s32 sfd, dfd;
|
||||
u8 *tmp;
|
||||
|
||||
if (!i) { return; }
|
||||
|
||||
sfd = open(old_path, O_RDONLY);
|
||||
if (sfd < 0) { PFATAL("Unable to open '%s'", old_path); }
|
||||
|
||||
@ -1439,7 +1489,9 @@ void pivot_inputs(afl_state_t *afl) {
|
||||
u32 src_id;
|
||||
|
||||
afl->resuming_fuzz = 1;
|
||||
nfn = alloc_printf("%s/queue/%s", afl->out_dir, rsl);
|
||||
nfn = alloc_printf(
|
||||
"%s/queue/%s%s%s", afl->out_dir, rsl, afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
/* Since we're at it, let's also get the parent and figure out the
|
||||
appropriate depth for this entry. */
|
||||
@ -1479,12 +1531,33 @@ void pivot_inputs(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
nfn = alloc_printf("%s/queue/id:%06u,time:0,execs:%llu,orig:%s",
|
||||
afl->out_dir, id, afl->fsrv.total_execs, use_name);
|
||||
if (!afl->afl_env.afl_sha1_filenames) {
|
||||
|
||||
nfn = alloc_printf(
|
||||
"%s/queue/id:%06u,time:0,execs:%llu,orig:%s%s%s", afl->out_dir, id,
|
||||
afl->fsrv.total_execs, use_name, afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
} else {
|
||||
|
||||
const char *hex = sha1_hex_for_file(q->fname, q->len);
|
||||
nfn = alloc_printf(
|
||||
"%s/queue/%s%s%s", afl->out_dir, hex,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
ck_free((char *)hex);
|
||||
|
||||
}
|
||||
|
||||
u8 *pos = strrchr(nfn, '/');
|
||||
no_spaces(pos + 30);
|
||||
|
||||
#else
|
||||
|
||||
nfn = alloc_printf("%s/queue/id_%06u", afl->out_dir, id);
|
||||
nfn = alloc_printf(
|
||||
"%s/queue/id_%06u%s%s", afl->out_dir, id,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
@ -1691,10 +1764,11 @@ double get_runnable_processes(void) {
|
||||
|
||||
void nuke_resume_dir(afl_state_t *afl) {
|
||||
|
||||
u8 *fn;
|
||||
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
|
||||
u8 *fn;
|
||||
|
||||
fn = alloc_printf("%s/_resume/.state/deterministic_done", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/_resume/.state/auto_extras", afl->out_dir);
|
||||
@ -1702,11 +1776,11 @@ void nuke_resume_dir(afl_state_t *afl) {
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/_resume/.state/redundant_edges", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/_resume/.state/variable_behavior", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/_resume/.state", afl->out_dir);
|
||||
@ -1714,7 +1788,7 @@ void nuke_resume_dir(afl_state_t *afl) {
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/_resume", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
return;
|
||||
@ -1731,8 +1805,9 @@ dir_cleanup_failed:
|
||||
|
||||
static void handle_existing_out_dir(afl_state_t *afl) {
|
||||
|
||||
FILE *f;
|
||||
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
|
||||
u8 *const case_prefix = afl->afl_env.afl_sha1_filenames ? "" : CASE_PREFIX;
|
||||
FILE *f;
|
||||
u8 *fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
|
||||
|
||||
/* See if the output directory is locked. If yes, bail out. If not,
|
||||
create a lock that will persist for the lifetime of the process
|
||||
@ -1854,7 +1929,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
||||
/* Next, we need to clean up <afl->out_dir>/queue/.state/ subdirectories: */
|
||||
|
||||
fn = alloc_printf("%s/queue/.state/deterministic_done", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/queue/.state/auto_extras", afl->out_dir);
|
||||
@ -1862,11 +1937,11 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/queue/.state/redundant_edges", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/queue/.state/variable_behavior", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
/* Then, get rid of the .state subdirectory itself (should be empty by now)
|
||||
@ -1877,7 +1952,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/queue", afl->out_dir);
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
/* All right, let's do <afl->out_dir>/crashes/id:* and
|
||||
@ -1924,7 +1999,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
||||
#ifdef AFL_PERSISTENT_RECORD
|
||||
delete_files(fn, RECORD_PREFIX);
|
||||
#endif
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
fn = alloc_printf("%s/hangs", afl->out_dir);
|
||||
@ -1959,7 +2034,7 @@ static void handle_existing_out_dir(afl_state_t *afl) {
|
||||
#ifdef AFL_PERSISTENT_RECORD
|
||||
delete_files(fn, RECORD_PREFIX);
|
||||
#endif
|
||||
if (delete_files(fn, CASE_PREFIX)) { goto dir_cleanup_failed; }
|
||||
if (delete_files(fn, case_prefix)) { goto dir_cleanup_failed; }
|
||||
ck_free(fn);
|
||||
|
||||
/* And now, for some finishing touches. */
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Shengtuo Hu
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -60,32 +60,6 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
double compute_weight(afl_state_t *afl, struct queue_entry *q,
|
||||
double avg_exec_us, double avg_bitmap_size,
|
||||
double avg_top_size) {
|
||||
|
||||
double weight = 1.0;
|
||||
|
||||
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||
|
||||
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
|
||||
if (likely(hits)) { weight /= (log10(hits) + 1); }
|
||||
|
||||
}
|
||||
|
||||
if (likely(afl->schedule < RARE)) { weight *= (avg_exec_us / q->exec_us); }
|
||||
weight *= (log(q->bitmap_size) / avg_bitmap_size);
|
||||
weight *= (1 + (q->tc_ref / avg_top_size));
|
||||
|
||||
if (unlikely(weight < 0.1)) { weight = 0.1; }
|
||||
if (unlikely(q->favored)) { weight *= 5; }
|
||||
if (unlikely(!q->was_fuzzed)) { weight *= 2; }
|
||||
if (unlikely(q->fs_redundant)) { weight *= 0.8; }
|
||||
|
||||
return weight;
|
||||
|
||||
}
|
||||
|
||||
/* create the alias table that allows weighted random selection - expensive */
|
||||
|
||||
void create_alias_table(afl_state_t *afl) {
|
||||
@ -117,7 +91,7 @@ void create_alias_table(afl_state_t *afl) {
|
||||
|
||||
double avg_exec_us = 0.0;
|
||||
double avg_bitmap_size = 0.0;
|
||||
double avg_top_size = 0.0;
|
||||
double avg_len = 0.0;
|
||||
u32 active = 0;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
@ -129,7 +103,7 @@ void create_alias_table(afl_state_t *afl) {
|
||||
|
||||
avg_exec_us += q->exec_us;
|
||||
avg_bitmap_size += log(q->bitmap_size);
|
||||
avg_top_size += q->tc_ref;
|
||||
avg_len += q->len;
|
||||
++active;
|
||||
|
||||
}
|
||||
@ -138,7 +112,7 @@ void create_alias_table(afl_state_t *afl) {
|
||||
|
||||
avg_exec_us /= active;
|
||||
avg_bitmap_size /= active;
|
||||
avg_top_size /= active;
|
||||
avg_len /= active;
|
||||
|
||||
for (i = 0; i < n; i++) {
|
||||
|
||||
@ -146,8 +120,59 @@ void create_alias_table(afl_state_t *afl) {
|
||||
|
||||
if (likely(!q->disabled)) {
|
||||
|
||||
q->weight =
|
||||
compute_weight(afl, q, avg_exec_us, avg_bitmap_size, avg_top_size);
|
||||
double weight = 1.0;
|
||||
{ // inline does result in a compile error with LTO, weird
|
||||
|
||||
if (likely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||
|
||||
u32 hits = afl->n_fuzz[q->n_fuzz_entry];
|
||||
if (likely(hits)) { weight /= (log10(hits) + 1); }
|
||||
|
||||
}
|
||||
|
||||
if (likely(afl->schedule < RARE)) {
|
||||
|
||||
double t = q->exec_us / avg_exec_us;
|
||||
if (likely(t < 0.1)) {
|
||||
|
||||
// nothing
|
||||
|
||||
} else if (likely(t <= 0.25))
|
||||
|
||||
weight *= 0.9;
|
||||
else if (likely(t <= 0.5)) {
|
||||
|
||||
// nothing
|
||||
|
||||
} else if (likely(t < 1.0))
|
||||
|
||||
weight *= 1.15;
|
||||
else if (unlikely(t > 2.5 && t < 5.0))
|
||||
weight *= 1.1;
|
||||
// else nothing
|
||||
|
||||
}
|
||||
|
||||
double l = q->len / avg_len;
|
||||
if (likely(l < 0.1))
|
||||
weight *= 0.75;
|
||||
else if (likely(l < 0.25))
|
||||
weight *= 1.1;
|
||||
else if (unlikely(l >= 10))
|
||||
weight *= 1.1;
|
||||
|
||||
double bms = q->bitmap_size / avg_bitmap_size;
|
||||
if (likely(bms < 0.5))
|
||||
weight *= (1.0 + ((bms - 0.5) / 2));
|
||||
else if (unlikely(bms > 1.33))
|
||||
weight *= 1.1;
|
||||
|
||||
if (unlikely(!q->was_fuzzed)) { weight *= 2.5; }
|
||||
if (unlikely(q->fs_redundant)) { weight *= 0.75; }
|
||||
|
||||
}
|
||||
|
||||
q->weight = weight;
|
||||
q->perf_score = calculate_score(afl, q);
|
||||
sum += q->weight;
|
||||
|
||||
@ -370,9 +395,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
s32 fd;
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
|
||||
if (fd < 0) { PFATAL("Unable to create '%s'", fn); }
|
||||
close(fd);
|
||||
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
|
||||
fd = permissive_create(afl, fn);
|
||||
if (fd >= 0) { close(fd); }
|
||||
|
||||
} else {
|
||||
|
||||
@ -596,6 +621,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
q->trace_mini = NULL;
|
||||
q->testcase_buf = NULL;
|
||||
q->mother = afl->queue_cur;
|
||||
q->weight = 1.0;
|
||||
q->perf_score = 100;
|
||||
|
||||
#ifdef INTROSPECTION
|
||||
q->bitsmap_size = afl->bitsmap_size;
|
||||
@ -1201,9 +1228,11 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
|
||||
|
||||
u32 len = q->len;
|
||||
|
||||
if (len != old_len) {
|
||||
// only realloc if necessary or useful
|
||||
// (a custom trim can make the testcase larger)
|
||||
if (unlikely(len > old_len || len < old_len + 1024)) {
|
||||
|
||||
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
|
||||
afl->q_testcase_cache_size += len - old_len;
|
||||
q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
|
||||
|
||||
if (unlikely(!q->testcase_buf)) {
|
||||
@ -1232,41 +1261,48 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
|
||||
|
||||
if (likely(q->testcase_buf)) {
|
||||
|
||||
u32 is_same = in == q->testcase_buf;
|
||||
if (likely(in != q->testcase_buf)) {
|
||||
|
||||
if (likely(len != old_len)) {
|
||||
// only realloc if we save memory
|
||||
if (unlikely(len < old_len + 1024)) {
|
||||
|
||||
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
|
||||
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
|
||||
|
||||
if (likely(ptr)) {
|
||||
if (likely(ptr)) {
|
||||
|
||||
q->testcase_buf = ptr;
|
||||
afl->q_testcase_cache_size = afl->q_testcase_cache_size + len - old_len;
|
||||
q->testcase_buf = ptr;
|
||||
afl->q_testcase_cache_size += len - old_len;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
memcpy(q->testcase_buf, in, len);
|
||||
|
||||
if (unlikely(!is_same)) { memcpy(q->testcase_buf, in, len); }
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Returns the testcase buf from the file behind this queue entry.
|
||||
Increases the refcount. */
|
||||
Increases the refcount. */
|
||||
|
||||
inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
u32 len = q->len;
|
||||
if (likely(q->testcase_buf)) { return q->testcase_buf; }
|
||||
|
||||
/* first handle if no testcase cache is configured */
|
||||
u32 len = q->len;
|
||||
double weight = q->weight;
|
||||
|
||||
if (unlikely(!afl->q_testcase_max_cache_size)) {
|
||||
// first handle if no testcase cache is configured, or if the
|
||||
// weighting of the testcase is below average.
|
||||
|
||||
if (unlikely(weight < 1.0 || !afl->q_testcase_max_cache_size)) {
|
||||
|
||||
u8 *buf;
|
||||
|
||||
if (unlikely(q == afl->queue_cur)) {
|
||||
if (likely(q == afl->queue_cur)) {
|
||||
|
||||
buf = (u8 *)afl_realloc((void **)&afl->testcase_buf, len);
|
||||
|
||||
@ -1292,117 +1328,113 @@ inline u8 *queue_testcase_get(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
/* now handle the testcase cache */
|
||||
/* now handle the testcase cache and we know it is an interesting one */
|
||||
|
||||
if (unlikely(!q->testcase_buf)) {
|
||||
/* Buf not cached, let's load it */
|
||||
u32 tid = afl->q_testcase_max_cache_count;
|
||||
static u32 do_once = 0; // because even threaded we would want this. WIP
|
||||
|
||||
/* Buf not cached, let's load it */
|
||||
u32 tid = afl->q_testcase_max_cache_count;
|
||||
static u32 do_once = 0; // because even threaded we would want this. WIP
|
||||
while (unlikely(
|
||||
(afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size &&
|
||||
afl->q_testcase_cache_count > 1) ||
|
||||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
|
||||
|
||||
while (unlikely(
|
||||
afl->q_testcase_cache_size + len >= afl->q_testcase_max_cache_size ||
|
||||
afl->q_testcase_cache_count >= afl->q_testcase_max_cache_entries - 1)) {
|
||||
/* We want a max number of entries to the cache that we learn.
|
||||
Very simple: once the cache is filled by size - that is the max. */
|
||||
|
||||
/* We want a max number of entries to the cache that we learn.
|
||||
Very simple: once the cache is filled by size - that is the max. */
|
||||
if (unlikely(
|
||||
afl->q_testcase_cache_size + len >=
|
||||
afl->q_testcase_max_cache_size &&
|
||||
(afl->q_testcase_cache_count < afl->q_testcase_max_cache_entries &&
|
||||
afl->q_testcase_max_cache_count <
|
||||
afl->q_testcase_max_cache_entries) &&
|
||||
!do_once)) {
|
||||
|
||||
if (unlikely(afl->q_testcase_cache_size + len >=
|
||||
afl->q_testcase_max_cache_size &&
|
||||
(afl->q_testcase_cache_count <
|
||||
afl->q_testcase_max_cache_entries &&
|
||||
afl->q_testcase_max_cache_count <
|
||||
afl->q_testcase_max_cache_entries) &&
|
||||
!do_once)) {
|
||||
if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) {
|
||||
|
||||
if (afl->q_testcase_max_cache_count > afl->q_testcase_cache_count) {
|
||||
afl->q_testcase_max_cache_entries = afl->q_testcase_max_cache_count + 1;
|
||||
|
||||
afl->q_testcase_max_cache_entries =
|
||||
afl->q_testcase_max_cache_count + 1;
|
||||
} else {
|
||||
|
||||
} else {
|
||||
|
||||
afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1;
|
||||
|
||||
}
|
||||
|
||||
do_once = 1;
|
||||
// release unneeded memory
|
||||
afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
|
||||
afl->q_testcase_cache,
|
||||
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
|
||||
afl->q_testcase_max_cache_entries = afl->q_testcase_cache_count + 1;
|
||||
|
||||
}
|
||||
|
||||
/* Cache full. We neet to evict one or more to map one.
|
||||
Get a random one which is not in use */
|
||||
|
||||
do {
|
||||
|
||||
// if the cache (MB) is not enough for the queue then this gets
|
||||
// undesirable because q_testcase_max_cache_count grows sometimes
|
||||
// although the number of items in the cache will not change hence
|
||||
// more and more loops
|
||||
tid = rand_below(afl, afl->q_testcase_max_cache_count);
|
||||
|
||||
} while (afl->q_testcase_cache[tid] == NULL ||
|
||||
|
||||
afl->q_testcase_cache[tid] == afl->queue_cur);
|
||||
|
||||
struct queue_entry *old_cached = afl->q_testcase_cache[tid];
|
||||
free(old_cached->testcase_buf);
|
||||
old_cached->testcase_buf = NULL;
|
||||
afl->q_testcase_cache_size -= old_cached->len;
|
||||
afl->q_testcase_cache[tid] = NULL;
|
||||
--afl->q_testcase_cache_count;
|
||||
++afl->q_testcase_evictions;
|
||||
if (tid < afl->q_testcase_smallest_free)
|
||||
afl->q_testcase_smallest_free = tid;
|
||||
do_once = 1;
|
||||
// release unneeded memory
|
||||
afl->q_testcase_cache = (struct queue_entry **)ck_realloc(
|
||||
afl->q_testcase_cache,
|
||||
(afl->q_testcase_max_cache_entries + 1) * sizeof(size_t));
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(tid >= afl->q_testcase_max_cache_entries)) {
|
||||
/* Cache full. We neet to evict one or more to map one.
|
||||
Get a random one which is not in use */
|
||||
|
||||
// uh we were full, so now we have to search from start
|
||||
tid = afl->q_testcase_smallest_free;
|
||||
do {
|
||||
|
||||
}
|
||||
// if the cache (MB) is not enough for the queue then this gets
|
||||
// undesirable because q_testcase_max_cache_count grows sometimes
|
||||
// although the number of items in the cache will not change hence
|
||||
// more and more loops
|
||||
tid = rand_below(afl, afl->q_testcase_max_cache_count);
|
||||
|
||||
// we need this while loop in case there were ever previous evictions but
|
||||
// not in this call.
|
||||
while (unlikely(afl->q_testcase_cache[tid] != NULL))
|
||||
++tid;
|
||||
} while (afl->q_testcase_cache[tid] == NULL ||
|
||||
|
||||
/* Map the test case into memory. */
|
||||
afl->q_testcase_cache[tid] == afl->queue_cur);
|
||||
|
||||
int fd = open((char *)q->fname, O_RDONLY);
|
||||
struct queue_entry *old_cached = afl->q_testcase_cache[tid];
|
||||
free(old_cached->testcase_buf);
|
||||
old_cached->testcase_buf = NULL;
|
||||
afl->q_testcase_cache_size -= old_cached->len;
|
||||
afl->q_testcase_cache[tid] = NULL;
|
||||
--afl->q_testcase_cache_count;
|
||||
++afl->q_testcase_evictions;
|
||||
if (tid < afl->q_testcase_smallest_free)
|
||||
afl->q_testcase_smallest_free = tid;
|
||||
|
||||
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
|
||||
}
|
||||
|
||||
q->testcase_buf = (u8 *)malloc(len);
|
||||
if (unlikely(tid >= afl->q_testcase_max_cache_entries)) {
|
||||
|
||||
if (unlikely(!q->testcase_buf)) {
|
||||
// uh we were full, so now we have to search from start
|
||||
tid = afl->q_testcase_smallest_free;
|
||||
|
||||
PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
|
||||
}
|
||||
|
||||
}
|
||||
// we need this while loop in case there were ever previous evictions but
|
||||
// not in this call.
|
||||
while (unlikely(afl->q_testcase_cache[tid] != NULL))
|
||||
++tid;
|
||||
|
||||
ck_read(fd, q->testcase_buf, len, q->fname);
|
||||
close(fd);
|
||||
/* Map the test case into memory. */
|
||||
|
||||
/* Register testcase as cached */
|
||||
afl->q_testcase_cache[tid] = q;
|
||||
afl->q_testcase_cache_size += len;
|
||||
++afl->q_testcase_cache_count;
|
||||
if (likely(tid >= afl->q_testcase_max_cache_count)) {
|
||||
int fd = open((char *)q->fname, O_RDONLY);
|
||||
|
||||
afl->q_testcase_max_cache_count = tid + 1;
|
||||
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", (char *)q->fname); }
|
||||
|
||||
} else if (unlikely(tid == afl->q_testcase_smallest_free)) {
|
||||
q->testcase_buf = (u8 *)malloc(len);
|
||||
|
||||
afl->q_testcase_smallest_free = tid + 1;
|
||||
if (unlikely(!q->testcase_buf)) {
|
||||
|
||||
}
|
||||
PFATAL("Unable to malloc '%s' with len %u", (char *)q->fname, len);
|
||||
|
||||
}
|
||||
|
||||
ck_read(fd, q->testcase_buf, len, q->fname);
|
||||
close(fd);
|
||||
|
||||
/* Register testcase as cached */
|
||||
afl->q_testcase_cache[tid] = q;
|
||||
afl->q_testcase_cache_size += len;
|
||||
++afl->q_testcase_cache_count;
|
||||
if (likely(tid >= afl->q_testcase_max_cache_count)) {
|
||||
|
||||
afl->q_testcase_max_cache_count = tid + 1;
|
||||
|
||||
} else if (unlikely(tid == afl->q_testcase_smallest_free)) {
|
||||
|
||||
afl->q_testcase_smallest_free = tid + 1;
|
||||
|
||||
}
|
||||
|
||||
@ -1417,12 +1449,13 @@ inline void queue_testcase_store_mem(afl_state_t *afl, struct queue_entry *q,
|
||||
|
||||
u32 len = q->len;
|
||||
|
||||
if (unlikely(afl->q_testcase_cache_size + len >=
|
||||
if (unlikely(q->weight < 1.0 ||
|
||||
afl->q_testcase_cache_size + len >=
|
||||
afl->q_testcase_max_cache_size ||
|
||||
afl->q_testcase_cache_count >=
|
||||
afl->q_testcase_max_cache_entries - 1)) {
|
||||
|
||||
// no space? will be loaded regularly later.
|
||||
// no space or uninteresting? will be loaded regularly later.
|
||||
return;
|
||||
|
||||
}
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -322,7 +322,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
|
||||
|
||||
memcpy(backup, buf, len);
|
||||
memcpy(changed, buf, len);
|
||||
if (afl->cmplog_random_colorization) {
|
||||
if (likely(afl->cmplog_random_colorization)) {
|
||||
|
||||
random_replace(afl, changed, len);
|
||||
|
||||
@ -402,6 +402,7 @@ static u8 colorization(afl_state_t *afl, u8 *buf, u32 len,
|
||||
|
||||
u32 i = 1;
|
||||
u32 positions = 0;
|
||||
|
||||
while (i) {
|
||||
|
||||
restart:
|
||||
@ -2764,15 +2765,15 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
||||
#ifdef _DEBUG
|
||||
u32 j;
|
||||
struct cmp_header *hh = &afl->orig_cmp_map->headers[key];
|
||||
fprintf(stderr, "RTN N hits=%u id=%u shape=%u attr=%u v0=", h->hits, h->id,
|
||||
hshape, h->attribute);
|
||||
fprintf(stderr, "RTN N hits=%u shape=%u attr=%u v0=", h->hits, hshape,
|
||||
h->attribute);
|
||||
for (j = 0; j < 8; j++)
|
||||
fprintf(stderr, "%02x", o->v0[j]);
|
||||
fprintf(stderr, " v1=");
|
||||
for (j = 0; j < 8; j++)
|
||||
fprintf(stderr, "%02x", o->v1[j]);
|
||||
fprintf(stderr, "\nRTN O hits=%u id=%u shape=%u attr=%u o0=", hh->hits,
|
||||
hh->id, hshape, hh->attribute);
|
||||
fprintf(stderr, "\nRTN O hits=%u shape=%u attr=%u o0=", hh->hits, hshape,
|
||||
hh->attribute);
|
||||
for (j = 0; j < 8; j++)
|
||||
fprintf(stderr, "%02x", orig_o->v0[j]);
|
||||
fprintf(stderr, " o1=");
|
||||
@ -2937,7 +2938,8 @@ static u8 rtn_fuzz(afl_state_t *afl, u32 key, u8 *orig_buf, u8 *buf, u8 *cbuf,
|
||||
// afl->queue_cur->exec_cksum
|
||||
u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
u8 r = 1;
|
||||
u64 cmplog_start_us = get_cur_time_us();
|
||||
u8 r = 1;
|
||||
if (unlikely(!afl->pass_stats)) {
|
||||
|
||||
afl->pass_stats = ck_alloc(sizeof(struct afl_pass_stat) * CMP_MAP_W);
|
||||
@ -2965,7 +2967,12 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
if (!afl->queue_cur->taint || !afl->queue_cur->cmplog_colorinput) {
|
||||
|
||||
if (unlikely(colorization(afl, buf, len, &taint))) { return 1; }
|
||||
if (unlikely(colorization(afl, buf, len, &taint))) {
|
||||
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
// no taint? still try, create a dummy to prevent again colorization
|
||||
if (!taint) {
|
||||
@ -2974,6 +2981,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
fprintf(stderr, "TAINT FAILED\n");
|
||||
#endif
|
||||
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -2994,17 +3002,20 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
|
||||
struct tainted *t = taint;
|
||||
|
||||
#ifdef _DEBUG
|
||||
while (t) {
|
||||
|
||||
#ifdef _DEBUG
|
||||
fprintf(stderr, "T: idx=%u len=%u\n", t->pos, t->len);
|
||||
#endif
|
||||
t = t->next;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#if defined(_DEBUG) || defined(CMPLOG_INTROSPECTION)
|
||||
u64 start_time = get_cur_time();
|
||||
u32 cmp_locations = 0;
|
||||
@ -3025,6 +3036,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
return 1;
|
||||
|
||||
}
|
||||
@ -3048,6 +3060,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
return 1;
|
||||
|
||||
}
|
||||
@ -3066,6 +3079,7 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
u64 orig_hit_cnt, new_hit_cnt;
|
||||
u64 orig_execs = afl->fsrv.total_execs;
|
||||
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
|
||||
afl->stage_name = "input-to-state";
|
||||
afl->stage_short = "its";
|
||||
@ -3142,33 +3156,35 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
|
||||
}
|
||||
|
||||
r = 0;
|
||||
|
||||
exit_its:
|
||||
|
||||
if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
|
||||
// if (afl->cmplog_lvl == CMPLOG_LVL_MAX) {
|
||||
|
||||
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
|
||||
afl->queue_cur->colorized = CMPLOG_LVL_MAX;
|
||||
|
||||
if (afl->queue_cur->cmplog_colorinput) {
|
||||
if (afl->queue_cur->cmplog_colorinput) {
|
||||
|
||||
ck_free(afl->queue_cur->cmplog_colorinput);
|
||||
ck_free(afl->queue_cur->cmplog_colorinput);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
while (taint) {
|
||||
while (taint) {
|
||||
|
||||
t = taint->next;
|
||||
ck_free(taint);
|
||||
taint = t;
|
||||
t = taint->next;
|
||||
ck_free(taint);
|
||||
taint = t;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
afl->queue_cur->taint = NULL;
|
||||
afl->queue_cur->taint = NULL;
|
||||
|
||||
} else {
|
||||
/*} else {
|
||||
|
||||
afl->queue_cur->colorized = LVL2;
|
||||
|
||||
@ -3182,7 +3198,7 @@ exit_its:
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}*/
|
||||
|
||||
#ifdef CMPLOG_COMBINE
|
||||
if (afl->queued_items + afl->saved_crashes > orig_hit_cnt + 1) {
|
||||
@ -3270,6 +3286,7 @@ exit_its:
|
||||
|
||||
#endif
|
||||
|
||||
update_cmplog_time(afl, &cmplog_start_us);
|
||||
return r;
|
||||
|
||||
}
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
@ -409,6 +409,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
u32 use_tmout = afl->fsrv.exec_tmout;
|
||||
u8 *old_sn = afl->stage_name;
|
||||
|
||||
u64 calibration_start_us = get_cur_time_us();
|
||||
if (unlikely(afl->shm.cmplog_mode)) { q->exec_cksum = 0; }
|
||||
|
||||
/* Be a bit more generous about timeouts when resuming sessions, or when
|
||||
@ -504,6 +505,10 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, use_tmout);
|
||||
|
||||
// update the time spend in calibration after each execution, as those may
|
||||
// be slow
|
||||
update_calibration_time(afl, &calibration_start_us);
|
||||
|
||||
/* afl->stop_soon is set by the handler for Ctrl+C. When it's pressed,
|
||||
we want to bail out quickly. */
|
||||
|
||||
@ -601,6 +606,8 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
}
|
||||
|
||||
q->exec_us = diff_us / afl->stage_max;
|
||||
if (unlikely(!q->exec_us)) { q->exec_us = 1; }
|
||||
|
||||
q->bitmap_size = count_bytes(afl, afl->fsrv.trace_bits);
|
||||
q->handicap = handicap;
|
||||
q->cal_failed = 0;
|
||||
@ -650,6 +657,7 @@ abort_calibration:
|
||||
|
||||
if (!first_run) { show_stats(afl); }
|
||||
|
||||
update_calibration_time(afl, &calibration_start_us);
|
||||
return fault;
|
||||
|
||||
}
|
||||
@ -658,6 +666,8 @@ abort_calibration:
|
||||
|
||||
void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
if (unlikely(afl->afl_env.afl_no_sync)) { return; }
|
||||
|
||||
DIR *sd;
|
||||
struct dirent *sd_ent;
|
||||
u32 sync_cnt = 0, synced = 0, entries = 0;
|
||||
@ -669,11 +679,16 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
afl->stage_max = afl->stage_cur = 0;
|
||||
afl->cur_depth = 0;
|
||||
|
||||
u64 sync_start_us = get_cur_time_us();
|
||||
/* Look at the entries created for every other fuzzer in the sync directory.
|
||||
*/
|
||||
|
||||
while ((sd_ent = readdir(sd))) {
|
||||
|
||||
// since sync can take substantial amounts of time, update time spend every
|
||||
// iteration
|
||||
update_sync_time(afl, &sync_start_us);
|
||||
|
||||
u8 qd_synced_path[PATH_MAX], qd_path[PATH_MAX];
|
||||
u32 min_accept = 0, next_min_accept = 0;
|
||||
|
||||
@ -760,6 +775,8 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
afl->stage_cur = 0;
|
||||
afl->stage_max = 0;
|
||||
|
||||
show_stats(afl);
|
||||
|
||||
/* For every file queued by this fuzzer, parse ID and see if we have
|
||||
looked at it before; exec a test case if not. */
|
||||
|
||||
@ -811,15 +828,15 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
/* See what happens. We rely on save_if_interesting() to catch major
|
||||
errors and save the test case. */
|
||||
|
||||
(void)write_to_testcase(afl, (void **)&mem, st.st_size, 1);
|
||||
u32 new_len = write_to_testcase(afl, (void **)&mem, st.st_size, 1);
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
if (afl->stop_soon) { goto close_sync; }
|
||||
|
||||
afl->syncing_party = sd_ent->d_name;
|
||||
afl->queued_imported +=
|
||||
save_if_interesting(afl, mem, st.st_size, fault);
|
||||
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
|
||||
show_stats(afl);
|
||||
afl->syncing_party = 0;
|
||||
|
||||
munmap(mem, st.st_size);
|
||||
@ -861,6 +878,9 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
if (afl->foreign_sync_cnt) read_foreign_testcases(afl, 0);
|
||||
|
||||
// add time in sync one last time
|
||||
update_sync_time(afl, &sync_start_us);
|
||||
|
||||
afl->last_sync_time = get_cur_time();
|
||||
afl->last_sync_cycle = afl->queue_cycle;
|
||||
|
||||
@ -872,8 +892,9 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
u8 needs_write = 0, fault = 0;
|
||||
u32 orig_len = q->len;
|
||||
|
||||
u64 trim_start_us = get_cur_time_us();
|
||||
/* Custom mutator trimmer */
|
||||
if (afl->custom_mutators_count) {
|
||||
|
||||
@ -897,11 +918,15 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
}
|
||||
|
||||
if (custom_trimmed) return trimmed_case;
|
||||
if (custom_trimmed) {
|
||||
|
||||
fault = trimmed_case;
|
||||
goto abort_trimming;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u8 needs_write = 0, fault = 0;
|
||||
u32 trim_exec = 0;
|
||||
u32 remove_len;
|
||||
u32 len_p2;
|
||||
@ -912,7 +937,12 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
detected, it will still work to some extent, so we don't check for
|
||||
this. */
|
||||
|
||||
if (unlikely(q->len < 5)) { return 0; }
|
||||
if (unlikely(q->len < 5)) {
|
||||
|
||||
fault = 0;
|
||||
goto abort_trimming;
|
||||
|
||||
}
|
||||
|
||||
afl->stage_name = afl->stage_name_buf;
|
||||
afl->bytes_trim_in += q->len;
|
||||
@ -946,6 +976,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
update_trim_time(afl, &trim_start_us);
|
||||
|
||||
if (afl->stop_soon || fault == FSRV_RUN_ERROR) { goto abort_trimming; }
|
||||
|
||||
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
|
||||
@ -972,7 +1004,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
/* Let's save a clean trace, which will be needed by
|
||||
update_bitmap_score once we're done with the trimming stuff. */
|
||||
|
||||
if (!needs_write) {
|
||||
|
||||
needs_write = 1;
|
||||
@ -987,7 +1018,6 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
}
|
||||
|
||||
/* Since this can be slow, update the screen every now and then. */
|
||||
|
||||
if (!(trim_exec++ % afl->stats_update_freq)) { show_stats(afl); }
|
||||
++afl->stage_cur;
|
||||
|
||||
@ -1002,6 +1032,68 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
if (needs_write) {
|
||||
|
||||
// run afl_custom_post_process
|
||||
|
||||
if (unlikely(afl->custom_mutators_count) &&
|
||||
likely(!afl->afl_env.afl_post_process_keep_original)) {
|
||||
|
||||
ssize_t new_size = q->len;
|
||||
u8 *new_mem = in_buf;
|
||||
u8 *new_buf = NULL;
|
||||
|
||||
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
|
||||
|
||||
if (el->afl_custom_post_process) {
|
||||
|
||||
new_size = el->afl_custom_post_process(el->data, new_mem, new_size,
|
||||
&new_buf);
|
||||
|
||||
if (unlikely(!new_buf || new_size <= 0)) {
|
||||
|
||||
new_size = 0;
|
||||
new_buf = new_mem;
|
||||
|
||||
} else {
|
||||
|
||||
new_mem = new_buf;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (unlikely(!new_size)) {
|
||||
|
||||
new_size = q->len;
|
||||
new_mem = in_buf;
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(new_size < afl->min_length)) {
|
||||
|
||||
new_size = afl->min_length;
|
||||
|
||||
} else if (unlikely(new_size > afl->max_length)) {
|
||||
|
||||
new_size = afl->max_length;
|
||||
|
||||
}
|
||||
|
||||
q->len = new_size;
|
||||
|
||||
if (new_mem != in_buf && new_mem != NULL) {
|
||||
|
||||
new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), new_size);
|
||||
if (unlikely(!new_buf)) { PFATAL("alloc"); }
|
||||
memcpy(new_buf, new_mem, new_size);
|
||||
|
||||
in_buf = new_buf;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
s32 fd;
|
||||
|
||||
if (unlikely(afl->no_unlink)) {
|
||||
@ -1039,8 +1131,9 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
}
|
||||
|
||||
abort_trimming:
|
||||
|
||||
afl->bytes_trim_out += q->len;
|
||||
update_trim_time(afl, &trim_start_us);
|
||||
|
||||
return fault;
|
||||
|
||||
}
|
||||
|
@ -33,15 +33,15 @@ u8 is_det_timeout(u64 cur_ms, u8 is_flip) {
|
||||
|
||||
u8 should_det_fuzz(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
if (!afl->skipdet_g->virgin_det_bits) {
|
||||
if (unlikely(!afl->skipdet_g->virgin_det_bits)) {
|
||||
|
||||
afl->skipdet_g->virgin_det_bits =
|
||||
(u8 *)ck_alloc(sizeof(u8) * afl->fsrv.map_size);
|
||||
|
||||
}
|
||||
|
||||
if (!q->favored || q->passed_det) return 0;
|
||||
if (!q->trace_mini) return 0;
|
||||
if (likely(!q->favored || q->passed_det)) return 0;
|
||||
if (unlikely(!q->trace_mini)) return 0;
|
||||
|
||||
if (!afl->skipdet_g->last_cov_undet)
|
||||
afl->skipdet_g->last_cov_undet = get_cur_time();
|
||||
@ -122,7 +122,8 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
afl->stage_cur = 0;
|
||||
orig_hit_cnt = afl->queued_items + afl->saved_crashes;
|
||||
|
||||
u8 *inf_eff_map = (u8 *)ck_alloc(sizeof(u8) * len);
|
||||
static u8 *inf_eff_map;
|
||||
inf_eff_map = (u8 *)ck_realloc(inf_eff_map, sizeof(u8) * len);
|
||||
memset(inf_eff_map, 1, sizeof(u8) * len);
|
||||
|
||||
if (common_fuzz_stuff(afl, orig_buf, len)) { return 0; }
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -28,10 +28,6 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "envs.h"
|
||||
|
||||
s8 interesting_8[] = {INTERESTING_8};
|
||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
|
||||
char *power_names[POWER_SCHEDULES_NUM] = {"explore", "mmopt", "exploit",
|
||||
"fast", "coe", "lin",
|
||||
"quad", "rare", "seek"};
|
||||
@ -283,6 +279,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
afl->afl_env.afl_final_sync =
|
||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||
|
||||
} else if (!strncmp(env, "AFL_NO_SYNC",
|
||||
|
||||
afl_environment_variable_len)) {
|
||||
|
||||
afl->afl_env.afl_no_sync =
|
||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||
|
||||
} else if (!strncmp(env, "AFL_CUSTOM_MUTATOR_ONLY",
|
||||
|
||||
afl_environment_variable_len)) {
|
||||
@ -297,6 +300,16 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
afl->afl_env.afl_cmplog_only_new =
|
||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||
|
||||
} else if (!strncmp(env, "AFL_DISABLE_REDUNDANT",
|
||||
|
||||
afl_environment_variable_len) ||
|
||||
!strncmp(env, "AFL_NO_REDUNDANT",
|
||||
|
||||
afl_environment_variable_len)) {
|
||||
|
||||
afl->afl_env.afl_disable_redundant =
|
||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||
|
||||
} else if (!strncmp(env, "AFL_NO_STARTUP_CALIBRATION",
|
||||
|
||||
afl_environment_variable_len)) {
|
||||
@ -623,6 +636,13 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
} else if (!strncmp(env, "AFL_SHA1_FILENAMES",
|
||||
|
||||
afl_environment_variable_len)) {
|
||||
|
||||
afl->afl_env.afl_sha1_filenames =
|
||||
get_afl_env(afl_environment_variables[i]) ? 1 : 0;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
@ -749,8 +769,9 @@ void afl_states_stop(void) {
|
||||
if (el->fsrv.fsrv_pid > 0) {
|
||||
|
||||
kill(el->fsrv.fsrv_pid, el->fsrv.fsrv_kill_signal);
|
||||
usleep(100);
|
||||
/* Make sure the forkserver does not end up as zombie. */
|
||||
waitpid(el->fsrv.fsrv_pid, NULL, 0);
|
||||
waitpid(el->fsrv.fsrv_pid, NULL, WNOHANG);
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,8 +5,9 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
Dominik Meier <mail@dmnk.co>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
@ -133,6 +134,12 @@ void write_setup_file(afl_state_t *afl, u32 argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
static bool starts_with(char *key, char *line) {
|
||||
|
||||
return strncmp(key, line, strlen(key)) == 0;
|
||||
|
||||
}
|
||||
|
||||
/* load some of the existing stats file when resuming.*/
|
||||
void load_stats_file(afl_state_t *afl) {
|
||||
|
||||
@ -175,58 +182,90 @@ void load_stats_file(afl_state_t *afl) {
|
||||
strcpy(keystring, lstartptr);
|
||||
lptr++;
|
||||
char *nptr;
|
||||
switch (lineno) {
|
||||
if (starts_with("run_time", keystring)) {
|
||||
|
||||
case 3:
|
||||
if (!strcmp(keystring, "run_time "))
|
||||
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
|
||||
break;
|
||||
case 5:
|
||||
if (!strcmp(keystring, "cycles_done "))
|
||||
afl->queue_cycle =
|
||||
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
|
||||
break;
|
||||
case 7:
|
||||
if (!strcmp(keystring, "execs_done "))
|
||||
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
|
||||
break;
|
||||
case 10:
|
||||
if (!strcmp(keystring, "corpus_count ")) {
|
||||
afl->prev_run_time = 1000 * strtoull(lptr, &nptr, 10);
|
||||
|
||||
u32 corpus_count = strtoul(lptr, &nptr, 10);
|
||||
if (corpus_count != afl->queued_items) {
|
||||
}
|
||||
|
||||
WARNF(
|
||||
"queue/ has been modified -- things might not work, you're "
|
||||
"on your own!");
|
||||
if (starts_with("cycles_done", keystring)) {
|
||||
|
||||
}
|
||||
afl->queue_cycle =
|
||||
strtoull(lptr, &nptr, 10) ? strtoull(lptr, &nptr, 10) + 1 : 0;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
break;
|
||||
case 12:
|
||||
if (!strcmp(keystring, "corpus_found "))
|
||||
afl->queued_discovered = strtoul(lptr, &nptr, 10);
|
||||
break;
|
||||
case 13:
|
||||
if (!strcmp(keystring, "corpus_imported "))
|
||||
afl->queued_imported = strtoul(lptr, &nptr, 10);
|
||||
break;
|
||||
case 14:
|
||||
if (!strcmp(keystring, "max_depth "))
|
||||
afl->max_depth = strtoul(lptr, &nptr, 10);
|
||||
break;
|
||||
case 21:
|
||||
if (!strcmp(keystring, "saved_crashes "))
|
||||
afl->saved_crashes = strtoull(lptr, &nptr, 10);
|
||||
break;
|
||||
case 22:
|
||||
if (!strcmp(keystring, "saved_hangs "))
|
||||
afl->saved_hangs = strtoull(lptr, &nptr, 10);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
if (starts_with("calibration_time", keystring)) {
|
||||
|
||||
afl->calibration_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("sync_time", keystring)) {
|
||||
|
||||
afl->sync_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("cmplog_time", keystring)) {
|
||||
|
||||
afl->cmplog_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("trim_time", keystring)) {
|
||||
|
||||
afl->trim_time_us = strtoull(lptr, &nptr, 10) * 1000000;
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("execs_done", keystring)) {
|
||||
|
||||
afl->fsrv.total_execs = strtoull(lptr, &nptr, 10);
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("corpus_count", keystring)) {
|
||||
|
||||
u32 corpus_count = strtoul(lptr, &nptr, 10);
|
||||
if (corpus_count != afl->queued_items) {
|
||||
|
||||
WARNF(
|
||||
"queue/ has been modified -- things might not work, you're "
|
||||
"on your own!");
|
||||
sleep(3);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("corpus_found", keystring)) {
|
||||
|
||||
afl->queued_discovered = strtoul(lptr, &nptr, 10);
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("corpus_imported", keystring)) {
|
||||
|
||||
afl->queued_imported = strtoul(lptr, &nptr, 10);
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("max_depth", keystring)) {
|
||||
|
||||
afl->max_depth = strtoul(lptr, &nptr, 10);
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("saved_crashes", keystring)) {
|
||||
|
||||
afl->saved_crashes = strtoull(lptr, &nptr, 10);
|
||||
|
||||
}
|
||||
|
||||
if (starts_with("saved_hangs", keystring)) {
|
||||
|
||||
afl->saved_hangs = strtoull(lptr, &nptr, 10);
|
||||
|
||||
}
|
||||
|
||||
@ -288,8 +327,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
#ifndef __HAIKU__
|
||||
if (getrusage(RUSAGE_CHILDREN, &rus)) { rus.ru_maxrss = 0; }
|
||||
#endif
|
||||
u64 runtime = afl->prev_run_time + cur_time - afl->start_time;
|
||||
if (!runtime) { runtime = 1; }
|
||||
u64 runtime_ms = afl->prev_run_time + cur_time - afl->start_time;
|
||||
u64 overhead_ms = (afl->calibration_time_us + afl->sync_time_us +
|
||||
afl->trim_time_us + afl->cmplog_time_us) /
|
||||
1000;
|
||||
if (!runtime_ms) { runtime_ms = 1; }
|
||||
|
||||
fprintf(
|
||||
f,
|
||||
@ -300,6 +342,11 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
"cycles_done : %llu\n"
|
||||
"cycles_wo_finds : %llu\n"
|
||||
"time_wo_finds : %llu\n"
|
||||
"fuzz_time : %llu\n"
|
||||
"calibration_time : %llu\n"
|
||||
"cmplog_time : %llu\n"
|
||||
"sync_time : %llu\n"
|
||||
"trim_time : %llu\n"
|
||||
"execs_done : %llu\n"
|
||||
"execs_per_sec : %0.02f\n"
|
||||
"execs_ps_last_min : %0.02f\n"
|
||||
@ -337,15 +384,19 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
"\n"
|
||||
"target_mode : %s%s%s%s%s%s%s%s%s%s\n"
|
||||
"command_line : %s\n",
|
||||
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
|
||||
runtime / 1000, (u32)getpid(),
|
||||
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
|
||||
runtime_ms / 1000, (u32)getpid(),
|
||||
afl->queue_cycle ? (afl->queue_cycle - 1) : 0, afl->cycles_wo_finds,
|
||||
afl->longest_find_time > cur_time - afl->last_find_time
|
||||
? afl->longest_find_time / 1000
|
||||
: ((afl->start_time == 0 || afl->last_find_time == 0)
|
||||
? 0
|
||||
: (cur_time - afl->last_find_time) / 1000),
|
||||
afl->fsrv.total_execs, afl->fsrv.total_execs / ((double)(runtime) / 1000),
|
||||
(runtime_ms - MIN(runtime_ms, overhead_ms)) / 1000,
|
||||
afl->calibration_time_us / 1000000, afl->cmplog_time_us / 1000000,
|
||||
afl->sync_time_us / 1000000, afl->trim_time_us / 1000000,
|
||||
afl->fsrv.total_execs,
|
||||
afl->fsrv.total_execs / ((double)(runtime_ms) / 1000),
|
||||
afl->last_avg_execs_saved, afl->queued_items, afl->queued_favored,
|
||||
afl->queued_discovered, afl->queued_imported, afl->queued_variable,
|
||||
afl->max_depth, afl->current_entry, afl->pending_favored,
|
||||
@ -589,9 +640,10 @@ void show_stats_normal(afl_state_t *afl) {
|
||||
|
||||
cur_ms = get_cur_time();
|
||||
|
||||
if (afl->most_time_key) {
|
||||
if (afl->most_time_key && afl->queue_cycle) {
|
||||
|
||||
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
|
||||
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
|
||||
cur_ms - afl->start_time) {
|
||||
|
||||
afl->most_time_key = 2;
|
||||
afl->stop_soon = 2;
|
||||
@ -600,7 +652,7 @@ void show_stats_normal(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
if (afl->most_execs_key == 1) {
|
||||
if (afl->most_execs_key == 1 && afl->queue_cycle) {
|
||||
|
||||
if (afl->most_execs <= afl->fsrv.total_execs) {
|
||||
|
||||
@ -876,6 +928,10 @@ void show_stats_normal(afl_state_t *afl) {
|
||||
|
||||
#endif
|
||||
|
||||
if (banner_pad)
|
||||
for (u32 i = 0; i < banner_pad; ++i)
|
||||
strcat(banner, " ");
|
||||
|
||||
}
|
||||
|
||||
SAYF("\n%s\n", banner);
|
||||
@ -1284,7 +1340,9 @@ void show_stats_normal(afl_state_t *afl) {
|
||||
|
||||
sprintf(tmp, "disabled, ");
|
||||
|
||||
} else if (unlikely(!afl->bytes_trim_out)) {
|
||||
} else if (unlikely(!afl->bytes_trim_out ||
|
||||
|
||||
afl->bytes_trim_in <= afl->bytes_trim_out)) {
|
||||
|
||||
sprintf(tmp, "n/a, ");
|
||||
|
||||
@ -1301,7 +1359,9 @@ void show_stats_normal(afl_state_t *afl) {
|
||||
|
||||
strcat(tmp, "disabled");
|
||||
|
||||
} else if (unlikely(!afl->blocks_eff_total)) {
|
||||
} else if (unlikely(!afl->blocks_eff_total ||
|
||||
|
||||
afl->blocks_eff_select >= afl->blocks_eff_total)) {
|
||||
|
||||
strcat(tmp, "n/a");
|
||||
|
||||
@ -1415,9 +1475,10 @@ void show_stats_pizza(afl_state_t *afl) {
|
||||
|
||||
cur_ms = get_cur_time();
|
||||
|
||||
if (afl->most_time_key) {
|
||||
if (afl->most_time_key && afl->queue_cycle) {
|
||||
|
||||
if (afl->most_time * 1000 < cur_ms - afl->start_time) {
|
||||
if (afl->most_time * 1000 + afl->sync_time_us / 1000 <
|
||||
cur_ms - afl->start_time) {
|
||||
|
||||
afl->most_time_key = 2;
|
||||
afl->stop_soon = 2;
|
||||
@ -1426,7 +1487,7 @@ void show_stats_pizza(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
if (afl->most_execs_key == 1) {
|
||||
if (afl->most_execs_key == 1 && afl->queue_cycle) {
|
||||
|
||||
if (afl->most_execs <= afl->fsrv.total_execs) {
|
||||
|
||||
@ -2435,3 +2496,35 @@ void show_init_stats(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
inline void update_calibration_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->calibration_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
inline void update_trim_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->trim_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
inline void update_sync_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->sync_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
inline void update_cmplog_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->cmplog_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
|
123
src/afl-fuzz.c
123
src/afl-fuzz.c
@ -5,8 +5,9 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
Dominik Meier <mail@dmnk.co>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>, and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
@ -199,7 +200,8 @@ static void usage(u8 *argv0, int more_help) {
|
||||
|
||||
"Test settings:\n"
|
||||
" -s seed - use a fixed seed for the RNG\n"
|
||||
" -V seconds - fuzz for a specified time then terminate\n"
|
||||
" -V seconds - fuzz for a specified time then terminate (fuzz time "
|
||||
"only!)\n"
|
||||
" -E execs - fuzz for an approx. no. of total executions then "
|
||||
"terminate\n"
|
||||
" Note: not precise and can have several more "
|
||||
@ -262,6 +264,7 @@ static void usage(u8 *argv0, int more_help) {
|
||||
"AFL_CYCLE_SCHEDULES: after completing a cycle, switch to a different -p schedule\n"
|
||||
"AFL_DEBUG: extra debugging output for Python mode trimming\n"
|
||||
"AFL_DEBUG_CHILD: do not suppress stdout/stderr from target\n"
|
||||
"AFL_DISABLE_REDUNDANT: disable any queue item that is redundant\n"
|
||||
"AFL_DISABLE_TRIM: disable the trimming of test cases\n"
|
||||
"AFL_DUMB_FORKSRV: use fork server without feedback from target\n"
|
||||
"AFL_EXIT_WHEN_DONE: exit when all inputs are run and no new finds are found\n"
|
||||
@ -332,6 +335,7 @@ static void usage(u8 *argv0, int more_help) {
|
||||
"AFL_STATSD_PORT: change default statsd port (default: 8125)\n"
|
||||
"AFL_STATSD_TAGS_FLAVOR: set statsd tags format (default: disable tags)\n"
|
||||
" suported formats: dogstatsd, librato, signalfx, influxdb\n"
|
||||
"AFL_NO_SYNC: disables all syncing\n"
|
||||
"AFL_SYNC_TIME: sync time between fuzzing instances (in minutes)\n"
|
||||
"AFL_FINAL_SYNC: sync a final time when exiting (will delay the exit!)\n"
|
||||
"AFL_NO_CRASH_README: do not create a README in the crashes directory\n"
|
||||
@ -911,8 +915,15 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
u8 suffix = 'M';
|
||||
|
||||
if (mem_limit_given) { FATAL("Multiple -m options not supported"); }
|
||||
mem_limit_given = 1;
|
||||
if (mem_limit_given) {
|
||||
|
||||
WARNF("Overriding previous -m option.");
|
||||
|
||||
} else {
|
||||
|
||||
mem_limit_given = 1;
|
||||
|
||||
}
|
||||
|
||||
if (!optarg) { FATAL("Wrong usage of -m"); }
|
||||
|
||||
@ -1458,15 +1469,16 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
#endif
|
||||
|
||||
configure_afl_kill_signals(&afl->fsrv, afl->afl_env.afl_child_kill_signal,
|
||||
afl->afl_env.afl_fsrv_kill_signal,
|
||||
(afl->fsrv.qemu_mode || afl->unicorn_mode
|
||||
configure_afl_kill_signals(
|
||||
&afl->fsrv, afl->afl_env.afl_child_kill_signal,
|
||||
afl->afl_env.afl_fsrv_kill_signal,
|
||||
(afl->fsrv.qemu_mode || afl->unicorn_mode || afl->fsrv.use_fauxsrv
|
||||
#ifdef __linux__
|
||||
|| afl->fsrv.nyx_mode
|
||||
|| afl->fsrv.nyx_mode
|
||||
#endif
|
||||
)
|
||||
? SIGKILL
|
||||
: SIGTERM);
|
||||
)
|
||||
? SIGKILL
|
||||
: SIGTERM);
|
||||
|
||||
setup_signal_handlers();
|
||||
check_asan_opts(afl);
|
||||
@ -1562,7 +1574,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
setenv("__AFL_OUT_DIR", afl->out_dir, 1);
|
||||
|
||||
if (get_afl_env("AFL_DISABLE_TRIM")) { afl->disable_trim = 1; }
|
||||
if (get_afl_env("AFL_DISABLE_TRIM") || get_afl_env("AFL_NO_TRIM")) {
|
||||
|
||||
afl->disable_trim = 1;
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI")) {
|
||||
|
||||
@ -1798,6 +1814,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
afl_realloc(AFL_BUF_PARAM(ex), min_alloc);
|
||||
|
||||
afl->fsrv.use_fauxsrv = afl->non_instrumented_mode == 1 || afl->no_forkserver;
|
||||
afl->fsrv.max_length = afl->max_length;
|
||||
|
||||
#ifdef __linux__
|
||||
if (!afl->fsrv.nyx_mode) {
|
||||
@ -2073,6 +2090,17 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
/* Simply code if AFL_TMPDIR is used or not */
|
||||
if (!afl->afl_env.afl_tmpdir) {
|
||||
|
||||
afl->tmp_dir = afl->out_dir;
|
||||
|
||||
} else {
|
||||
|
||||
afl->tmp_dir = afl->afl_env.afl_tmpdir;
|
||||
|
||||
}
|
||||
|
||||
write_setup_file(afl, argc, argv);
|
||||
|
||||
setup_cmdline_file(afl, argv + optind);
|
||||
@ -2085,8 +2113,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (!afl->timeout_given) { find_timeout(afl); } // only for resumes!
|
||||
|
||||
if ((afl->tmp_dir = afl->afl_env.afl_tmpdir) != NULL &&
|
||||
!afl->in_place_resume) {
|
||||
if (afl->afl_env.afl_tmpdir && !afl->in_place_resume) {
|
||||
|
||||
char tmpfile[PATH_MAX];
|
||||
|
||||
@ -2111,10 +2138,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
afl->tmp_dir = afl->out_dir;
|
||||
|
||||
}
|
||||
|
||||
/* If we don't have a file name chosen yet, use a safe default. */
|
||||
@ -2493,8 +2516,15 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
for (entry = 0; entry < afl->queued_items; ++entry)
|
||||
if (!afl->queue_buf[entry]->disabled)
|
||||
if (afl->queue_buf[entry]->exec_us > max_ms)
|
||||
max_ms = afl->queue_buf[entry]->exec_us;
|
||||
if ((afl->queue_buf[entry]->exec_us / 1000) > max_ms)
|
||||
max_ms = afl->queue_buf[entry]->exec_us / 1000;
|
||||
|
||||
// Add 20% as a safety margin, capped to exec_tmout given in -t option
|
||||
max_ms *= 1.2;
|
||||
if (max_ms > afl->fsrv.exec_tmout) max_ms = afl->fsrv.exec_tmout;
|
||||
|
||||
// Ensure that there is a sensible timeout even for very fast binaries
|
||||
if (max_ms < 5) max_ms = 5;
|
||||
|
||||
afl->fsrv.exec_tmout = max_ms;
|
||||
afl->timeout_given = 1;
|
||||
@ -2530,8 +2560,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
// (void)nice(-20); // does not improve the speed
|
||||
// real start time, we reset, so this works correctly with -V
|
||||
afl->start_time = get_cur_time();
|
||||
|
||||
#ifdef INTROSPECTION
|
||||
u32 prev_saved_crashes = 0, prev_saved_tmouts = 0;
|
||||
@ -2552,6 +2580,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
OKF("Writing mutation introspection to '%s'", ifn);
|
||||
#endif
|
||||
|
||||
// real start time, we reset, so this works correctly with -V
|
||||
afl->start_time = get_cur_time();
|
||||
|
||||
while (likely(!afl->stop_soon)) {
|
||||
|
||||
cull_queue(afl);
|
||||
@ -2564,7 +2595,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
(!afl->queue_cycle && afl->afl_env.afl_import_first)) &&
|
||||
afl->sync_id)) {
|
||||
|
||||
if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
|
||||
if (unlikely(!afl->queue_cycle && afl->afl_env.afl_import_first)) {
|
||||
|
||||
OKF("Syncing queues from other fuzzer instances first ...");
|
||||
|
||||
@ -2575,6 +2606,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
++afl->queue_cycle;
|
||||
if (afl->afl_env.afl_no_ui) {
|
||||
|
||||
ACTF("Entering queue cycle %llu\n", afl->queue_cycle);
|
||||
|
||||
}
|
||||
|
||||
runs_in_current_cycle = (u32)-1;
|
||||
afl->cur_skipped_items = 0;
|
||||
|
||||
@ -2583,7 +2620,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
// queue is fully cycled.
|
||||
time_t cursec = time(NULL);
|
||||
struct tm *curdate = localtime(&cursec);
|
||||
if (likely(!afl->afl_env.afl_pizza_mode)) {
|
||||
if (unlikely(!afl->afl_env.afl_pizza_mode)) {
|
||||
|
||||
if (unlikely(curdate->tm_mon == 3 && curdate->tm_mday == 1)) {
|
||||
|
||||
@ -2628,13 +2665,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->not_on_tty)) {
|
||||
|
||||
ACTF("Entering queue cycle %llu.", afl->queue_cycle);
|
||||
fflush(stdout);
|
||||
|
||||
}
|
||||
|
||||
/* If we had a full queue cycle with no new finds, try
|
||||
recombination strategies next. */
|
||||
|
||||
@ -2920,26 +2950,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (likely(!afl->stop_soon && afl->sync_id)) {
|
||||
|
||||
if (likely(afl->skip_deterministic)) {
|
||||
if (unlikely(afl->is_main_node)) {
|
||||
|
||||
if (unlikely(afl->is_main_node)) {
|
||||
if (unlikely(cur_time > (afl->sync_time >> 1) + afl->last_sync_time)) {
|
||||
|
||||
if (unlikely(cur_time >
|
||||
(afl->sync_time >> 1) + afl->last_sync_time)) {
|
||||
if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
|
||||
|
||||
if (!(sync_interval_cnt++ % (SYNC_INTERVAL / 3))) {
|
||||
|
||||
sync_fuzzers(afl);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
|
||||
|
||||
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
|
||||
sync_fuzzers(afl);
|
||||
|
||||
}
|
||||
|
||||
@ -2947,7 +2964,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
} else {
|
||||
|
||||
sync_fuzzers(afl);
|
||||
if (unlikely(cur_time > afl->sync_time + afl->last_sync_time)) {
|
||||
|
||||
if (!(sync_interval_cnt++ % SYNC_INTERVAL)) { sync_fuzzers(afl); }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -3061,7 +3082,7 @@ stop_fuzzing:
|
||||
afl_fsrv_deinit(&afl->fsrv);
|
||||
|
||||
/* remove tmpfile */
|
||||
if (afl->tmp_dir != NULL && !afl->in_place_resume && afl->fsrv.out_file) {
|
||||
if (!afl->in_place_resume && afl->fsrv.out_file) {
|
||||
|
||||
(void)unlink(afl->fsrv.out_file);
|
||||
|
||||
|
@ -5,7 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
|
@ -5,7 +5,7 @@
|
||||
Written by Marc Heuse <mh@mh-sec.de> for AFL++
|
||||
|
||||
Maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
Dominik Maier <domenukk@gmail.com>
|
||||
|
||||
|
@ -95,3 +95,331 @@ inline u64 hash64(u8 *key, u32 len, u64 seed) {
|
||||
|
||||
}
|
||||
|
||||
/* Hash a file */
|
||||
|
||||
u64 get_binary_hash(u8 *fn) {
|
||||
|
||||
int fd = open(fn, O_RDONLY);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", fn); }
|
||||
struct stat st;
|
||||
if (fstat(fd, &st) < 0) { PFATAL("Unable to fstat '%s'", fn); }
|
||||
u32 f_len = st.st_size;
|
||||
u8 *f_data = mmap(0, f_len, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
if (f_data == MAP_FAILED) { PFATAL("Unable to mmap file '%s'", fn); }
|
||||
close(fd);
|
||||
u64 hash = hash64(f_data, f_len, 0);
|
||||
if (munmap(f_data, f_len)) { PFATAL("unmap() failed"); }
|
||||
return hash;
|
||||
|
||||
}
|
||||
|
||||
// Public domain SHA1 implementation copied from:
|
||||
// https://github.com/x42/liboauth/blob/7001b8256cd654952ec2515b055d2c5b243be600/src/sha1.c
|
||||
|
||||
/* This code is public-domain - it is based on libcrypt
|
||||
* placed in the public domain by Wei Dai and other contributors.
|
||||
*/
|
||||
// gcc -Wall -DSHA1TEST -o sha1test sha1.c && ./sha1test
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef __BIG_ENDIAN__
|
||||
#define SHA_BIG_ENDIAN
|
||||
#elif defined __LITTLE_ENDIAN__
|
||||
/* override */
|
||||
#elif defined __BYTE_ORDER
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define SHA_BIG_ENDIAN
|
||||
#endif
|
||||
#else // ! defined __LITTLE_ENDIAN__
|
||||
#include <endian.h> // machine/endian.h
|
||||
#if __BYTE_ORDER__ == __ORDER_BIG_ENDIAN__
|
||||
#define SHA_BIG_ENDIAN
|
||||
#endif
|
||||
#endif
|
||||
|
||||
/* header */
|
||||
|
||||
#define HASH_LENGTH 20
|
||||
#define BLOCK_LENGTH 64
|
||||
|
||||
typedef struct sha1nfo {
|
||||
|
||||
uint32_t buffer[BLOCK_LENGTH / 4];
|
||||
uint32_t state[HASH_LENGTH / 4];
|
||||
uint32_t byteCount;
|
||||
uint8_t bufferOffset;
|
||||
uint8_t keyBuffer[BLOCK_LENGTH];
|
||||
uint8_t innerHash[HASH_LENGTH];
|
||||
|
||||
} sha1nfo;
|
||||
|
||||
/* public API - prototypes - TODO: doxygen*/
|
||||
|
||||
/**
|
||||
*/
|
||||
void sha1_init(sha1nfo *s);
|
||||
/**
|
||||
*/
|
||||
void sha1_writebyte(sha1nfo *s, uint8_t data);
|
||||
/**
|
||||
*/
|
||||
void sha1_write(sha1nfo *s, const char *data, size_t len);
|
||||
/**
|
||||
*/
|
||||
uint8_t *sha1_result(sha1nfo *s);
|
||||
/**
|
||||
*/
|
||||
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength);
|
||||
/**
|
||||
*/
|
||||
uint8_t *sha1_resultHmac(sha1nfo *s);
|
||||
|
||||
/* code */
|
||||
#define SHA1_K0 0x5a827999
|
||||
#define SHA1_K20 0x6ed9eba1
|
||||
#define SHA1_K40 0x8f1bbcdc
|
||||
#define SHA1_K60 0xca62c1d6
|
||||
|
||||
void sha1_init(sha1nfo *s) {
|
||||
|
||||
s->state[0] = 0x67452301;
|
||||
s->state[1] = 0xefcdab89;
|
||||
s->state[2] = 0x98badcfe;
|
||||
s->state[3] = 0x10325476;
|
||||
s->state[4] = 0xc3d2e1f0;
|
||||
s->byteCount = 0;
|
||||
s->bufferOffset = 0;
|
||||
|
||||
}
|
||||
|
||||
uint32_t sha1_rol32(uint32_t number, uint8_t bits) {
|
||||
|
||||
return ((number << bits) | (number >> (32 - bits)));
|
||||
|
||||
}
|
||||
|
||||
void sha1_hashBlock(sha1nfo *s) {
|
||||
|
||||
uint8_t i;
|
||||
uint32_t a, b, c, d, e, t;
|
||||
|
||||
a = s->state[0];
|
||||
b = s->state[1];
|
||||
c = s->state[2];
|
||||
d = s->state[3];
|
||||
e = s->state[4];
|
||||
for (i = 0; i < 80; i++) {
|
||||
|
||||
if (i >= 16) {
|
||||
|
||||
t = s->buffer[(i + 13) & 15] ^ s->buffer[(i + 8) & 15] ^
|
||||
s->buffer[(i + 2) & 15] ^ s->buffer[i & 15];
|
||||
s->buffer[i & 15] = sha1_rol32(t, 1);
|
||||
|
||||
}
|
||||
|
||||
if (i < 20) {
|
||||
|
||||
t = (d ^ (b & (c ^ d))) + SHA1_K0;
|
||||
|
||||
} else if (i < 40) {
|
||||
|
||||
t = (b ^ c ^ d) + SHA1_K20;
|
||||
|
||||
} else if (i < 60) {
|
||||
|
||||
t = ((b & c) | (d & (b | c))) + SHA1_K40;
|
||||
|
||||
} else {
|
||||
|
||||
t = (b ^ c ^ d) + SHA1_K60;
|
||||
|
||||
}
|
||||
|
||||
t += sha1_rol32(a, 5) + e + s->buffer[i & 15];
|
||||
e = d;
|
||||
d = c;
|
||||
c = sha1_rol32(b, 30);
|
||||
b = a;
|
||||
a = t;
|
||||
|
||||
}
|
||||
|
||||
s->state[0] += a;
|
||||
s->state[1] += b;
|
||||
s->state[2] += c;
|
||||
s->state[3] += d;
|
||||
s->state[4] += e;
|
||||
|
||||
}
|
||||
|
||||
void sha1_addUncounted(sha1nfo *s, uint8_t data) {
|
||||
|
||||
uint8_t *const b = (uint8_t *)s->buffer;
|
||||
#ifdef SHA_BIG_ENDIAN
|
||||
b[s->bufferOffset] = data;
|
||||
#else
|
||||
b[s->bufferOffset ^ 3] = data;
|
||||
#endif
|
||||
s->bufferOffset++;
|
||||
if (s->bufferOffset == BLOCK_LENGTH) {
|
||||
|
||||
sha1_hashBlock(s);
|
||||
s->bufferOffset = 0;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void sha1_writebyte(sha1nfo *s, uint8_t data) {
|
||||
|
||||
++s->byteCount;
|
||||
sha1_addUncounted(s, data);
|
||||
|
||||
}
|
||||
|
||||
void sha1_write(sha1nfo *s, const char *data, size_t len) {
|
||||
|
||||
for (; len--;)
|
||||
sha1_writebyte(s, (uint8_t)*data++);
|
||||
|
||||
}
|
||||
|
||||
void sha1_pad(sha1nfo *s) {
|
||||
|
||||
// Implement SHA-1 padding (fips180-2 §5.1.1)
|
||||
|
||||
// Pad with 0x80 followed by 0x00 until the end of the block
|
||||
sha1_addUncounted(s, 0x80);
|
||||
while (s->bufferOffset != 56)
|
||||
sha1_addUncounted(s, 0x00);
|
||||
|
||||
// Append length in the last 8 bytes
|
||||
sha1_addUncounted(s, 0); // We're only using 32 bit lengths
|
||||
sha1_addUncounted(s, 0); // But SHA-1 supports 64 bit lengths
|
||||
sha1_addUncounted(s, 0); // So zero pad the top bits
|
||||
sha1_addUncounted(s, s->byteCount >> 29); // Shifting to multiply by 8
|
||||
sha1_addUncounted(
|
||||
s, s->byteCount >> 21); // as SHA-1 supports bitstreams as well as
|
||||
sha1_addUncounted(s, s->byteCount >> 13); // byte.
|
||||
sha1_addUncounted(s, s->byteCount >> 5);
|
||||
sha1_addUncounted(s, s->byteCount << 3);
|
||||
|
||||
}
|
||||
|
||||
uint8_t *sha1_result(sha1nfo *s) {
|
||||
|
||||
// Pad to complete the last block
|
||||
sha1_pad(s);
|
||||
|
||||
#ifndef SHA_BIG_ENDIAN
|
||||
// Swap byte order back
|
||||
int i;
|
||||
for (i = 0; i < 5; i++) {
|
||||
|
||||
s->state[i] = (((s->state[i]) << 24) & 0xff000000) |
|
||||
(((s->state[i]) << 8) & 0x00ff0000) |
|
||||
(((s->state[i]) >> 8) & 0x0000ff00) |
|
||||
(((s->state[i]) >> 24) & 0x000000ff);
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Return pointer to hash (20 characters)
|
||||
return (uint8_t *)s->state;
|
||||
|
||||
}
|
||||
|
||||
#define HMAC_IPAD 0x36
|
||||
#define HMAC_OPAD 0x5c
|
||||
|
||||
void sha1_initHmac(sha1nfo *s, const uint8_t *key, int keyLength) {
|
||||
|
||||
uint8_t i;
|
||||
memset(s->keyBuffer, 0, BLOCK_LENGTH);
|
||||
if (keyLength > BLOCK_LENGTH) {
|
||||
|
||||
// Hash long keys
|
||||
sha1_init(s);
|
||||
for (; keyLength--;)
|
||||
sha1_writebyte(s, *key++);
|
||||
memcpy(s->keyBuffer, sha1_result(s), HASH_LENGTH);
|
||||
|
||||
} else {
|
||||
|
||||
// Block length keys are used as is
|
||||
memcpy(s->keyBuffer, key, keyLength);
|
||||
|
||||
}
|
||||
|
||||
// Start inner hash
|
||||
sha1_init(s);
|
||||
for (i = 0; i < BLOCK_LENGTH; i++) {
|
||||
|
||||
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_IPAD);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
uint8_t *sha1_resultHmac(sha1nfo *s) {
|
||||
|
||||
uint8_t i;
|
||||
// Complete inner hash
|
||||
memcpy(s->innerHash, sha1_result(s), HASH_LENGTH);
|
||||
// Calculate outer hash
|
||||
sha1_init(s);
|
||||
for (i = 0; i < BLOCK_LENGTH; i++)
|
||||
sha1_writebyte(s, s->keyBuffer[i] ^ HMAC_OPAD);
|
||||
for (i = 0; i < HASH_LENGTH; i++)
|
||||
sha1_writebyte(s, s->innerHash[i]);
|
||||
return sha1_result(s);
|
||||
|
||||
}
|
||||
|
||||
// End public domain SHA1 implementation
|
||||
|
||||
void sha1(const u8 *data, size_t len, u8 *out) {
|
||||
|
||||
sha1nfo s;
|
||||
sha1_init(&s);
|
||||
sha1_write(&s, (const char *)data, len);
|
||||
memcpy(out, sha1_result(&s), HASH_LENGTH);
|
||||
|
||||
}
|
||||
|
||||
char *sha1_hex(const u8 *data, size_t len) {
|
||||
|
||||
u8 digest[HASH_LENGTH];
|
||||
sha1(data, len, digest);
|
||||
u8 *hex = ck_alloc(HASH_LENGTH * 2 + 1);
|
||||
for (size_t i = 0; i < HASH_LENGTH; ++i) {
|
||||
|
||||
sprintf((char *)(hex + i * 2), "%02x", digest[i]);
|
||||
|
||||
}
|
||||
|
||||
return hex;
|
||||
|
||||
}
|
||||
|
||||
char *sha1_hex_for_file(const char *fname, u32 len) {
|
||||
|
||||
int fd = open(fname, O_RDONLY);
|
||||
if (fd < 0) { PFATAL("Unable to open '%s'", fname); }
|
||||
|
||||
u32 read_len = MIN(len, (u32)MAX_FILE);
|
||||
u8 *tmp = ck_alloc(read_len);
|
||||
ck_read(fd, tmp, read_len, fname);
|
||||
|
||||
close(fd);
|
||||
|
||||
char *hex = sha1_hex(tmp, read_len);
|
||||
ck_free(tmp);
|
||||
return hex;
|
||||
|
||||
}
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
@ -239,15 +239,15 @@ u8 *afl_shm_init(sharedmem_t *shm, size_t map_size,
|
||||
if (shm->cmplog_g_shm_fd == -1) { PFATAL("shm_open() failed"); }
|
||||
|
||||
/* configure the size of the shared memory segment */
|
||||
if (ftruncate(shm->cmplog_g_shm_fd, map_size)) {
|
||||
if (ftruncate(shm->cmplog_g_shm_fd, sizeof(struct cmp_map))) {
|
||||
|
||||
PFATAL("setup_shm(): cmplog ftruncate() failed");
|
||||
|
||||
}
|
||||
|
||||
/* map the shared memory segment to the address space of the process */
|
||||
shm->cmp_map = mmap(0, map_size, PROT_READ | PROT_WRITE, MAP_SHARED,
|
||||
shm->cmplog_g_shm_fd, 0);
|
||||
shm->cmp_map = mmap(0, sizeof(struct cmp_map), PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED, shm->cmplog_g_shm_fd, 0);
|
||||
if (shm->cmp_map == MAP_FAILED) {
|
||||
|
||||
close(shm->cmplog_g_shm_fd);
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
@ -178,7 +178,8 @@ fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
|
||||
void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
u8 *mem = fsrv->trace_bits;
|
||||
const u8 *map = binary_mode ? count_class_binary : count_class_human;
|
||||
const u8 *map = (binary_mode || collect_coverage) ? count_class_binary
|
||||
: count_class_human;
|
||||
|
||||
u32 i = map_size;
|
||||
|
||||
@ -224,8 +225,13 @@ static void at_exit_handler(void) {
|
||||
|
||||
if (remove_shm) {
|
||||
|
||||
remove_shm = false;
|
||||
if (shm.map) afl_shm_deinit(&shm);
|
||||
if (fsrv->use_shmem_fuzz) deinit_shmem(fsrv, shm_fuzz);
|
||||
if ((shm_fuzz && shm_fuzz->shmemfuzz_mode) || fsrv->use_shmem_fuzz) {
|
||||
|
||||
shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -240,14 +246,7 @@ static void analyze_results(afl_forkserver_t *fsrv) {
|
||||
u32 i;
|
||||
for (i = 0; i < map_size; i++) {
|
||||
|
||||
if (fsrv->trace_bits[i]) {
|
||||
|
||||
total += fsrv->trace_bits[i];
|
||||
if (fsrv->trace_bits[i] > highest) highest = fsrv->trace_bits[i];
|
||||
// if (!coverage_map[i]) { coverage_map[i] = 1; }
|
||||
coverage_map[i] |= fsrv->trace_bits[i];
|
||||
|
||||
}
|
||||
if (fsrv->trace_bits[i]) { coverage_map[i] |= fsrv->trace_bits[i]; }
|
||||
|
||||
}
|
||||
|
||||
@ -1339,6 +1338,8 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (collect_coverage) { binary_mode = false; } // ensure this
|
||||
|
||||
if (optind == argc || !out_file) { usage(argv[0]); }
|
||||
|
||||
if (in_dir && in_filelist) { FATAL("you can only specify either -i or -I"); }
|
||||
@ -1531,6 +1532,8 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
/* initialize cmplog_mode */
|
||||
shm_fuzz->cmplog_mode = 0;
|
||||
atexit(at_exit_handler);
|
||||
|
||||
u8 *map = afl_shm_init(shm_fuzz, MAX_FILE + sizeof(u32), 1);
|
||||
shm_fuzz->shmemfuzz_mode = true;
|
||||
if (!map) { FATAL("BUG: Zero return from afl_shm_init."); }
|
||||
@ -1677,12 +1680,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
if ((coverage_map = (u8 *)malloc(map_size + 64)) == NULL)
|
||||
FATAL("coult not grab memory");
|
||||
edges_only = false;
|
||||
raw_instr_output = true;
|
||||
|
||||
}
|
||||
|
||||
atexit(at_exit_handler);
|
||||
|
||||
if (get_afl_env("AFL_DEBUG")) {
|
||||
|
||||
int j = optind;
|
||||
@ -1699,9 +1699,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
map_size = fsrv->map_size;
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
if (in_dir) {
|
||||
|
||||
if (execute_testcases(in_dir) == 0) {
|
||||
@ -1733,9 +1736,12 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
} else {
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (!fsrv->nyx_mode) {
|
||||
|
||||
@ -1782,9 +1788,9 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
remove_shm = 0;
|
||||
remove_shm = false;
|
||||
afl_shm_deinit(&shm);
|
||||
if (fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz);
|
||||
if (fsrv->use_shmem_fuzz) { shm_fuzz = deinit_shmem(fsrv, shm_fuzz); }
|
||||
|
||||
u32 ret;
|
||||
|
||||
|
@ -7,7 +7,7 @@
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com> and
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
@ -82,6 +82,8 @@ static u8 crash_mode, /* Crash-centric mode? */
|
||||
remove_shm = 1, /* remove shmem on exit? */
|
||||
debug; /* debug mode */
|
||||
|
||||
static u32 del_len_limit = 1; /* Minimum block deletion length */
|
||||
|
||||
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
||||
|
||||
static afl_forkserver_t *fsrv;
|
||||
@ -480,7 +482,7 @@ next_del_blksize:
|
||||
|
||||
}
|
||||
|
||||
if (del_len > 1 && in_len >= 1) {
|
||||
if (del_len > del_len_limit && in_len >= 1) {
|
||||
|
||||
del_len /= 2;
|
||||
goto next_del_blksize;
|
||||
@ -796,8 +798,9 @@ static void usage(u8 *argv0) {
|
||||
"Minimization settings:\n"
|
||||
|
||||
" -e - solve for edge coverage only, ignore hit counts\n"
|
||||
" -x - treat non-zero exit codes as crashes\n\n"
|
||||
" -H - minimize a hang (hang mode)\n"
|
||||
" -l bytes - set minimum block deletion length to speed up minimization\n"
|
||||
" -x - treat non-zero exit codes as crashes\n"
|
||||
" -H - minimize a hang (hang mode)\n\n"
|
||||
|
||||
"For additional tips, please consult %s/README.md.\n\n"
|
||||
|
||||
@ -829,8 +832,9 @@ static void usage(u8 *argv0) {
|
||||
|
||||
int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0,
|
||||
del_limit_given = 0;
|
||||
char **use_argv;
|
||||
|
||||
char **argv = argv_cpy_dup(argc, argv_orig);
|
||||
@ -846,7 +850,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n");
|
||||
|
||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWXYHh")) > 0) {
|
||||
while ((opt = getopt(argc, argv, "+i:o:f:m:t:l:B:xeAOQUWXYHh")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
@ -1055,6 +1059,24 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
read_bitmap(optarg, mask_bitmap, map_size);
|
||||
break;
|
||||
|
||||
case 'l':
|
||||
if (del_limit_given) { FATAL("Multiple -l options not supported"); }
|
||||
del_limit_given = 1;
|
||||
|
||||
if (!optarg) { FATAL("Wrong usage of -l"); }
|
||||
|
||||
if (optarg[0] == '-') { FATAL("Dangerously low value of -l"); }
|
||||
|
||||
del_len_limit = atoi(optarg);
|
||||
|
||||
if (del_len_limit < 1 || del_len_limit > TMIN_MAX_FILE) {
|
||||
|
||||
FATAL("Value of -l out of range between 1 and TMIN_MAX_FILE");
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
case 'h':
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
|
@ -10,12 +10,9 @@ int LLVMFuzzerTestOneInput(const uint8_t *buf, size_t i) {
|
||||
|
||||
if (i < 15) return -1;
|
||||
if (buf[0] != 'A') return 0;
|
||||
if (buf[1] != 'B') return 0;
|
||||
if (buf[2] != 'C') return 0;
|
||||
if (buf[3] != 'D') return 0;
|
||||
int *icmp = (int *)(buf + 4);
|
||||
int *icmp = (int *)(buf + 1);
|
||||
if (*icmp != 0x69694141) return 0;
|
||||
if (memcmp(buf + 8, "1234EF", 6) == 0) abort();
|
||||
if (memcmp(buf + 5, "1234EF", 6) == 0) abort();
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -197,7 +197,8 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
for I in char short int long "long long"; do
|
||||
for BITS in 8 16 32 64; do
|
||||
bin="$testcase-split-$I-$BITS.compcov"
|
||||
AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
|
||||
#AFL_LLVM_INSTRUMENT=AFL
|
||||
AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1;
|
||||
if ! test -e "$bin"; then
|
||||
cat test.out
|
||||
$ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!";
|
||||
@ -263,13 +264,12 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
}
|
||||
rm -f test-compcov test.out instrumentlist.txt
|
||||
AFL_LLVM_CMPLOG=1 ../afl-clang-fast -o test-cmplog test-cmplog.c > /dev/null 2>&1
|
||||
../afl-clang-fast -O0 -o test-c test-cmplog.c > /dev/null 2>&1
|
||||
test -e test-cmplog && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for llvm_mode cmplog, this will take approx 10 seconds"
|
||||
{
|
||||
mkdir -p in
|
||||
echo 00000000000000000000000000000000 > in/in
|
||||
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -l 3 -m none -V30 -i in -o out -c ./test-cmplog -- ./test-c >>errors 2>&1
|
||||
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -Z -l 3 -m none -V30 -i in -o out -c 0 -- ./test-cmplog >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"
|
||||
@ -284,7 +284,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
$ECHO "$YELLOW[-] we cannot test llvm_mode cmplog because it is not present"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
rm -rf errors test-cmplog test-c in core.*
|
||||
rm -rf errors test-cmplog in core.*
|
||||
../afl-clang-fast -o test-persistent ../utils/persistent_mode/persistent_demo.c > /dev/null 2>&1
|
||||
test -e test-persistent && {
|
||||
echo foo | AFL_QUIET=1 ../afl-showmap -m ${MEM_LIMIT} -o /dev/null -q -r ./test-persistent && {
|
||||
|
@ -1 +1 @@
|
||||
63aab0f
|
||||
4b4fdab1
|
||||
|
@ -89,8 +89,8 @@ def dump_arch_info():
|
||||
|
||||
def dump_regs():
|
||||
reg_state = {}
|
||||
for reg in current_arch.all_registers:
|
||||
reg_val = get_register(reg)
|
||||
for reg in gef.arch.registers:
|
||||
reg_val = gef.arch.register(reg)
|
||||
reg_state[reg.strip().strip("$")] = reg_val
|
||||
|
||||
return reg_state
|
||||
@ -101,7 +101,9 @@ def dump_process_memory(output_dir):
|
||||
final_segment_list = []
|
||||
|
||||
# GEF:
|
||||
vmmap = get_process_maps()
|
||||
vmmap = gef.memory.maps
|
||||
memory = GefMemoryManager()
|
||||
|
||||
if not vmmap:
|
||||
print("No address mapping information found")
|
||||
return final_segment_list
|
||||
@ -126,7 +128,7 @@ def dump_process_memory(output_dir):
|
||||
if entry.is_readable() and not "(deleted)" in entry.path:
|
||||
try:
|
||||
# Compress and dump the content to a file
|
||||
seg_content = read_memory(entry.page_start, entry.size)
|
||||
seg_content = memory.read(entry.page_start, entry.size)
|
||||
if seg_content == None:
|
||||
print(
|
||||
"Segment empty: @0x{0:016x} (size:UNKNOWN) {1}".format(
|
||||
|
@ -136,7 +136,7 @@ def overlap_alignments(segments, memory):
|
||||
|
||||
# https://github.com/llvm-mirror/llvm/blob/master/include/llvm/ADT/Triple.h
|
||||
def get_arch():
|
||||
arch, arch_vendor, arch_os = lldb.target.GetTriple().split("-")
|
||||
arch, arch_vendor, arch_os, *arch_remains = lldb.debugger.GetSelectedTarget().GetTriple().split("-")
|
||||
if arch == "x86_64":
|
||||
return "x64"
|
||||
elif arch == "x86" or arch == "i386":
|
||||
@ -165,7 +165,7 @@ def dump_arch_info():
|
||||
|
||||
def dump_regs():
|
||||
reg_state = {}
|
||||
for reg_list in lldb.frame.GetRegisters():
|
||||
for reg_list in lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetRegisters():
|
||||
if "general purpose registers" in reg_list.GetName().lower():
|
||||
for reg in reg_list:
|
||||
reg_state[reg.GetName()] = int(reg.GetValue(), 16)
|
||||
@ -180,8 +180,9 @@ def get_section_info(sec):
|
||||
module_name = sec.addr.module.file.GetFilename()
|
||||
module_name = module_name if module_name is not None else ""
|
||||
long_name = module_name + "." + name
|
||||
load_addr = sec.addr.GetLoadAddress(lldb.debugger.GetSelectedTarget())
|
||||
|
||||
return sec.addr.load_addr, (sec.addr.load_addr + sec.size), sec.size, long_name
|
||||
return load_addr, (load_addr + sec.size), sec.size, long_name
|
||||
|
||||
|
||||
def dump_process_memory(output_dir):
|
||||
@ -191,7 +192,7 @@ def dump_process_memory(output_dir):
|
||||
|
||||
# 1st pass:
|
||||
# Loop over the segments, fill in the segment info dictionary
|
||||
for module in lldb.target.module_iter():
|
||||
for module in lldb.debugger.GetSelectedTarget().module_iter():
|
||||
for seg_ea in module.section_iter():
|
||||
seg_info = {"module": module.file.GetFilename()}
|
||||
(
|
||||
@ -201,8 +202,8 @@ def dump_process_memory(output_dir):
|
||||
seg_info["name"],
|
||||
) = get_section_info(seg_ea)
|
||||
# TODO: Ugly hack for -1 LONG address on 32-bit
|
||||
if seg_info["start"] >= sys.maxint or seg_size <= 0:
|
||||
print "Throwing away page: {}".format(seg_info["name"])
|
||||
if seg_info["start"] >= sys.maxsize or seg_size <= 0:
|
||||
print ("Throwing away page: {}".format(seg_info["name"]))
|
||||
continue
|
||||
|
||||
# Page-align segment
|
||||
@ -212,7 +213,7 @@ def dump_process_memory(output_dir):
|
||||
raw_segment_list.append(seg_info)
|
||||
|
||||
# Add the stack memory region (just hardcode 0x1000 around the current SP)
|
||||
sp = lldb.frame.GetSP()
|
||||
sp = lldb.debugger.GetSelectedTarget().GetProcess().GetSelectedThread().GetSelectedFrame().GetSP()
|
||||
start_sp = ALIGN_PAGE_DOWN(sp)
|
||||
raw_segment_list.append(
|
||||
{"start": start_sp, "end": start_sp + 0x1000, "name": "STACK"}
|
||||
@ -228,7 +229,7 @@ def dump_process_memory(output_dir):
|
||||
start_addr = -1
|
||||
next_region_addr = 0
|
||||
while next_region_addr > start_addr:
|
||||
err = lldb.process.GetMemoryRegionInfo(next_region_addr, mem_info)
|
||||
err = lldb.debugger.GetSelectedTarget().GetProcess().GetMemoryRegionInfo(next_region_addr, mem_info)
|
||||
# TODO: Should check err.success. If False, what do we do?
|
||||
if not err.success:
|
||||
break
|
||||
@ -267,7 +268,7 @@ def dump_process_memory(output_dir):
|
||||
region_name = seg_info["name"]
|
||||
# Compress and dump the content to a file
|
||||
err = lldb.SBError()
|
||||
seg_content = lldb.process.ReadMemory(
|
||||
seg_content = lldb.debugger.GetSelectedTarget().GetProcess().ReadMemory(
|
||||
start_addr, end_addr - start_addr, err
|
||||
)
|
||||
if seg_content == None:
|
||||
@ -340,11 +341,12 @@ def main():
|
||||
index_file.close()
|
||||
print ("Done.")
|
||||
|
||||
except Exception, e:
|
||||
except Exception as e:
|
||||
print ("!!! ERROR:\n\t{}".format(repr(e)))
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
lldb.debugger = lldb.SBDebugger.Create()
|
||||
main()
|
||||
elif lldb.debugger:
|
||||
main()
|
||||
|
@ -111,12 +111,14 @@ def dump_regs():
|
||||
reg_state = {}
|
||||
for reg in pwndbg.gdblib.regs.all:
|
||||
reg_val = pwndbg.gdblib.regs[reg]
|
||||
if reg_val is None:
|
||||
continue
|
||||
# current dumper script looks for register values to be hex strings
|
||||
# reg_str = "0x{:08x}".format(reg_val)
|
||||
# if "64" in get_arch():
|
||||
# reg_str = "0x{:016x}".format(reg_val)
|
||||
# reg_state[reg.strip().strip('$')] = reg_str
|
||||
reg_state[reg.strip().strip("$")] = reg_val
|
||||
reg_state[reg.strip().strip("$")] = int(reg_val)
|
||||
return reg_state
|
||||
|
||||
|
||||
|
@ -21,10 +21,10 @@ import zlib
|
||||
|
||||
# Unicorn imports
|
||||
from unicornafl import *
|
||||
from unicornafl.arm_const import *
|
||||
from unicornafl.arm64_const import *
|
||||
from unicornafl.x86_const import *
|
||||
from unicornafl.mips_const import *
|
||||
from unicorn.arm_const import *
|
||||
from unicorn.arm64_const import *
|
||||
from unicorn.x86_const import *
|
||||
from unicorn.mips_const import *
|
||||
|
||||
# If Capstone libraries are availible (only check once)
|
||||
try:
|
||||
@ -87,9 +87,10 @@ class UnicornSimpleHeap(object):
|
||||
|
||||
_uc = None # Unicorn engine instance to interact with
|
||||
_chunks = [] # List of all known chunks
|
||||
_chunks_freed = [] # List of all freed chunks
|
||||
_debug_print = False # True to print debug information
|
||||
|
||||
def __init__(self, uc, debug_print=False):
|
||||
def __init__(self, uc, debug_print=False, uaf_check=False):
|
||||
self._uc = uc
|
||||
self._debug_print = debug_print
|
||||
|
||||
@ -101,12 +102,23 @@ class UnicornSimpleHeap(object):
|
||||
# - Allocate at least 1 4k page of memory to make Unicorn happy
|
||||
# - Add guard pages at the start and end of the region
|
||||
total_chunk_size = UNICORN_PAGE_SIZE + ALIGN_PAGE_UP(size) + UNICORN_PAGE_SIZE
|
||||
|
||||
if size == 0:
|
||||
return 0
|
||||
|
||||
# Gross but efficient way to find space for the chunk:
|
||||
chunk = None
|
||||
for addr in range(self.HEAP_MIN_ADDR, self.HEAP_MAX_ADDR, UNICORN_PAGE_SIZE):
|
||||
try:
|
||||
self._uc.mem_map(addr, total_chunk_size, UC_PROT_READ | UC_PROT_WRITE)
|
||||
chunk = self.HeapChunk(addr, total_chunk_size, size)
|
||||
|
||||
if self.uaf_check:
|
||||
for chunk_freed in self._chunks_freed:
|
||||
if chunk_freed.is_buffer_in_chunk(chunk.data_addr, 1):
|
||||
self._chunks_freed.remove(chunk_freed)
|
||||
break
|
||||
|
||||
if self._debug_print:
|
||||
print(
|
||||
"Allocating 0x{0:x}-byte chunk @ 0x{1:016x}".format(
|
||||
@ -148,6 +160,9 @@ class UnicornSimpleHeap(object):
|
||||
return new_chunk_addr
|
||||
|
||||
def free(self, addr):
|
||||
if addr == 0:
|
||||
return False
|
||||
|
||||
for chunk in self._chunks:
|
||||
if chunk.is_buffer_in_chunk(addr, 1):
|
||||
if self._debug_print:
|
||||
@ -157,9 +172,14 @@ class UnicornSimpleHeap(object):
|
||||
)
|
||||
)
|
||||
self._uc.mem_unmap(chunk.actual_addr, chunk.total_size)
|
||||
|
||||
if self.uaf_check:
|
||||
self._chunks_freed.append(chunk)
|
||||
|
||||
self._chunks.remove(chunk)
|
||||
return True
|
||||
return False
|
||||
# Freed an object that doesn't exist. Maybe 'dobule-free' or 'invalid free' vulnerability here.
|
||||
self._uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
|
||||
|
||||
# Implements basic guard-page functionality
|
||||
def __check_mem_access(self, uc, access, address, size, value, user_data):
|
||||
@ -179,6 +199,15 @@ class UnicornSimpleHeap(object):
|
||||
# Force a memory-based crash
|
||||
uc.force_crash(UcError(UC_ERR_READ_PROT))
|
||||
|
||||
if self.uaf_check:
|
||||
for chunk in self._chunks_freed:
|
||||
if address >= chunk.actual_addr and (
|
||||
(address + size) <= (chunk.actual_addr + chunk.total_size)
|
||||
):
|
||||
if chunk.is_buffer_in_chunk(address, size):
|
||||
print("Use-after-free @ 0x{0:016x}".format(address))
|
||||
uc.force_crash(UcError(UC_ERR_FETCH_UNMAPPED))
|
||||
|
||||
|
||||
# ---------------------------
|
||||
# ---- Loading function
|
||||
|
@ -119,7 +119,7 @@ def main():
|
||||
binary_code = binary_file.read()
|
||||
binary_file.close()
|
||||
|
||||
# Apply constraints to the mutated input
|
||||
# Assert that the binary size is within limits
|
||||
if len(binary_code) > CODE_SIZE_MAX:
|
||||
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
|
||||
return
|
||||
|
Submodule unicorn_mode/unicornafl updated: 63aab0f752...4b4fdab161
@ -10,6 +10,7 @@ PROGRAMS = afl-network-client afl-network-server
|
||||
HASH=\#
|
||||
|
||||
CFLAGS += -Wno-pointer-sign
|
||||
LDFLAGS += -ldl
|
||||
|
||||
ifdef STATIC
|
||||
CFLAGS += -static
|
||||
|
@ -69,3 +69,21 @@ need to be changed for other OSes.
|
||||
|
||||
Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen)
|
||||
|
||||
Also, the following example (generate_libtoken_dict.sh) shows how to use a script to capture tokens from the
|
||||
files in the target output directory,
|
||||
and then generate a dictionary file from those tokens.
|
||||
|
||||
#### usage:
|
||||
```bash
|
||||
./generate_libtoken_dict.sh -p /path/to/libtokencap.so -b /path/to/target/program -o /path/to/target/output -t 5 -- [-program_args]
|
||||
```
|
||||
#### description opts:
|
||||
- ```-o``` : Path to target output directory ;
|
||||
- ```-b``` : Path to target program binary ;
|
||||
- ```-p``` : Path to LD_PRELOAD library ;
|
||||
- ```-t``` : Timeout in seconds ;
|
||||
- ```-- [-program_args]```: Any additional arguments required by the target binary can be specified after ```--```.
|
||||
|
||||
#### output:
|
||||
A sorted and unique token dictionary file with the extension ``*.dict``
|
||||
is created in the same directory as the target output containing tokens captured during the execution of the target binary.
|
||||
|
55
utils/libtokencap/generate_libtoken_dict.sh
Normal file
55
utils/libtokencap/generate_libtoken_dict.sh
Normal file
@ -0,0 +1,55 @@
|
||||
#help
|
||||
usage() {
|
||||
echo "Usage: $0 -o <target_output> -b <target_bin> -p <LD_PRELOAD_PATH> [-t <timeout_sec>] -- [target_args]"
|
||||
echo "Options:"
|
||||
echo " -o Path to target output directory"
|
||||
echo " -b Path to target program binary"
|
||||
echo " -p Path to LD_PRELOAD library"
|
||||
echo " -t Timeout in seconds"
|
||||
exit 1
|
||||
}
|
||||
|
||||
#parse cli options
|
||||
while getopts ":o:b:p:t:" opt; do
|
||||
case $opt in
|
||||
o) target_output="$OPTARG" ;;
|
||||
b) target_bin="$OPTARG" ;;
|
||||
p) LD_PRELOAD_PATH="$OPTARG" ;;
|
||||
t) timeout_sec="$OPTARG" ;;
|
||||
\?) echo "Invalid option: -$OPTARG" >&2; usage ;;
|
||||
:) echo "Option -$OPTARG requires an argument." >&2; usage ;;
|
||||
esac
|
||||
done
|
||||
|
||||
#shift away the parsed opts
|
||||
shift $((OPTIND - 1))
|
||||
|
||||
#check options
|
||||
if [ -z "$target_output" ] || [ -z "$target_bin" ] || [ -z "$LD_PRELOAD_PATH" ]; then
|
||||
echo "Error: Missing mandatory opts" >&2
|
||||
usage
|
||||
fi
|
||||
|
||||
# initialize vars
|
||||
AFL_TOKEN_FILE="${PWD}/temp_output.txt"
|
||||
AFL_DICT_FILE="${PWD}/$(basename "$target_bin")_tokens.dict"
|
||||
|
||||
#generate token-file
|
||||
{
|
||||
touch "$AFL_TOKEN_FILE"
|
||||
for i in $(find "$target_output" -type f -name "id*"); do
|
||||
LD_PRELOAD="$LD_PRELOAD_PATH" \
|
||||
timeout -s SIGKILL "$timeout_sec" \
|
||||
"$target_bin" "$@" "$i"
|
||||
done
|
||||
} >"$AFL_TOKEN_FILE"
|
||||
|
||||
# sort & remove duplicates
|
||||
sort -u "$AFL_TOKEN_FILE" >"$AFL_DICT_FILE"
|
||||
|
||||
# delete temp-file
|
||||
rm "$AFL_TOKEN_FILE"
|
||||
|
||||
# print done-message
|
||||
echo "Token dictionary created: $AFL_DICT_FILE"
|
||||
echo "Script completed successfully"
|
Reference in New Issue
Block a user