mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 14:43:22 +00:00
Compare commits
76 Commits
Author | SHA1 | Date | |
---|---|---|---|
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 |
@ -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,7 +44,7 @@ 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_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && 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.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.20a
|
||||
GitHub version: 4.20c
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
2
afl-cmin
2
afl-cmin
@ -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" \
|
||||
|
@ -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
|
||||
|
41
afl-whatsup
41
afl-whatsup
@ -123,6 +123,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 +183,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 +215,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 +273,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 +403,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");
|
||||
|
@ -3,12 +3,12 @@
|
||||
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.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,10 +22,21 @@
|
||||
- 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
|
||||
- Fixes for aflpp custom mutator and standalone tool
|
||||
- Minor edits to afl-persistent-config
|
||||
- Prevent temporary files being left behind on aborted afl-whatsup
|
||||
- More CPU benchmarks added to benchmark/
|
||||
|
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.
|
||||
|
@ -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).
|
||||
|
||||
|
@ -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,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.
|
||||
@ -648,7 +648,10 @@ 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 */
|
||||
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 +1218,10 @@ 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);
|
||||
|
||||
/* StatsD */
|
||||
|
||||
void statsd_setup_format(afl_state_t *afl);
|
||||
|
@ -30,10 +30,13 @@
|
||||
|
||||
#include <stdbool.h>
|
||||
#include <inttypes.h>
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
#define MUT_STRATEGY_ARRAY_SIZE 256
|
||||
|
||||
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,
|
||||
|
@ -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--;
|
||||
|
||||
}
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, a = volatile github dev, e = experimental branch
|
||||
#define VERSION "++4.20a"
|
||||
#define VERSION "++4.20c"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
|
@ -95,26 +95,26 @@ 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_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_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
|
||||
|
||||
};
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -341,7 +341,7 @@ llvmGetPassPluginInfo() {
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 15
|
||||
PB.registerFullLinkTimeOptimizationLastEPCallback(
|
||||
PB.registerFullLinkTimeOptimizationEarlyEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
@ -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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -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) {
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
||||
}
|
||||
|
@ -89,7 +89,7 @@ class CompareTransform : public ModulePass {
|
||||
|
||||
#endif
|
||||
|
||||
return "cmplog transform";
|
||||
return "compcov transform";
|
||||
|
||||
}
|
||||
|
||||
@ -123,7 +123,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());
|
||||
@ -746,6 +750,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 +759,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 +769,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
|
||||
|
||||
}
|
||||
|
@ -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());
|
||||
@ -935,7 +939,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 +955,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
} else {
|
||||
|
||||
return count;
|
||||
return counts;
|
||||
|
||||
}
|
||||
|
||||
@ -1004,7 +1008,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
if (!fcomps.size()) { return count; }
|
||||
if (!fcomps.size()) { return counts; }
|
||||
|
||||
IntegerType *Int1Ty = IntegerType::getInt1Ty(C);
|
||||
|
||||
@ -1690,11 +1694,11 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
#else
|
||||
ReplaceInstWithInst(FcmpInst->getParent()->getInstList(), ii, PN);
|
||||
#endif
|
||||
++count;
|
||||
++counts;
|
||||
|
||||
}
|
||||
|
||||
return count;
|
||||
return counts;
|
||||
|
||||
}
|
||||
|
||||
@ -1743,10 +1747,6 @@ bool SplitComparesTransform::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
#if LLVM_MAJOR >= 11
|
||||
auto PA = PreservedAnalyses::all();
|
||||
#endif
|
||||
|
||||
if (enableFPSplit) {
|
||||
|
||||
simplifyFPCompares(M);
|
||||
@ -1778,15 +1778,7 @@ 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
|
||||
|
||||
}
|
||||
if (!op0 || !op1) { continue; }
|
||||
|
||||
auto iTy1 = dyn_cast<IntegerType>(op0->getType());
|
||||
if (iTy1 && isa<IntegerType>(op1->getType())) {
|
||||
@ -1814,6 +1806,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 +1846,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
|
||||
|
||||
}
|
||||
|
@ -215,8 +215,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 \
|
||||
"
|
||||
|
||||
|
14
src/afl-cc.c
14
src/afl-cc.c
@ -828,7 +828,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")) {
|
||||
@ -1368,6 +1369,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");
|
||||
|
||||
@ -2379,7 +2387,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);
|
||||
|
||||
}
|
||||
|
@ -34,6 +34,7 @@
|
||||
#endif
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
#include <time.h>
|
||||
#include <math.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
@ -58,6 +59,27 @@ u8 last_intr = 0;
|
||||
#define AFL_PATH "/usr/local/lib/afl/"
|
||||
#endif
|
||||
|
||||
/* - Some BSD (i.e.: FreeBSD) offer the FAST clock source as
|
||||
* equivalent to Linux COARSE clock source. Aliasing COARSE to
|
||||
* FAST on such systems when COARSE is not already defined.
|
||||
* - macOS has no support of CLOCK_MONOTONIC_COARSE clock type.
|
||||
*/
|
||||
#if defined(OS_DARWIN) || defined(OS_SUNOS) || defined(__APPLE__) || \
|
||||
defined(__sun) || defined(__NetBSD__)
|
||||
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC
|
||||
#elif defined(OS_FREEBSD)
|
||||
#define CLOCK_MONOTONIC_COARSE CLOCK_MONOTONIC_FAST
|
||||
#endif
|
||||
|
||||
/* Convert seconds to milliseconds. */
|
||||
#define SEC_TO_MS(sec) ((sec) * 1000)
|
||||
/* Convert seconds to microseconds. */
|
||||
#define SEC_TO_US(sec) ((sec) * 1000000)
|
||||
/* Convert nanoseconds to milliseconds. */
|
||||
#define NS_TO_MS(ns) ((ns) / 1000000)
|
||||
/* Convert nanoseconds to microseconds. */
|
||||
#define NS_TO_US(ns) ((ns) / 1000)
|
||||
|
||||
void *afl_memmem(const void *haystack, size_t haystacklen, const void *needle,
|
||||
size_t needlelen) {
|
||||
|
||||
@ -974,12 +996,16 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
|
||||
|
||||
inline u64 get_cur_time(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
struct timespec ts;
|
||||
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||
if (rc == -1) {
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
|
||||
strerror(errno));
|
||||
|
||||
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
|
||||
}
|
||||
|
||||
return SEC_TO_MS((uint64_t)ts.tv_sec) + NS_TO_MS((uint64_t)ts.tv_nsec);
|
||||
|
||||
}
|
||||
|
||||
@ -987,12 +1013,16 @@ inline u64 get_cur_time(void) {
|
||||
|
||||
u64 get_cur_time_us(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
struct timespec ts;
|
||||
int rc = clock_gettime(CLOCK_MONOTONIC_COARSE, &ts);
|
||||
if (rc == -1) {
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
PFATAL("Failed to obtain timestamp (errno = %i: %s)\n", errno,
|
||||
strerror(errno));
|
||||
|
||||
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
|
||||
}
|
||||
|
||||
return SEC_TO_US((uint64_t)ts.tv_sec) + NS_TO_US((uint64_t)ts.tv_nsec);
|
||||
|
||||
}
|
||||
|
||||
|
@ -724,7 +724,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 +1111,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 +1128,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 +1154,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 +1166,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 +1175,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);
|
||||
|
||||
}
|
||||
@ -1828,6 +1839,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 +1874,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 +1944,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 +2016,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 +2052,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;
|
||||
|
||||
}
|
||||
@ -2066,7 +2079,9 @@ store_persistent_record: {
|
||||
if (likely(len && data)) {
|
||||
|
||||
snprintf(fn, sizeof(fn), persistent_out_fmt, fsrv->persistent_record_dir,
|
||||
fsrv->persistent_record_cnt, writecnt++);
|
||||
fsrv->persistent_record_cnt, writecnt++,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
int fd = open(fn, O_CREAT | O_TRUNC | O_WRONLY, 0644);
|
||||
if (fd >= 0) {
|
||||
|
||||
|
@ -527,15 +527,19 @@ 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,")));
|
||||
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
|
||||
|
||||
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);
|
||||
@ -739,14 +743,17 @@ 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,
|
||||
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,")));
|
||||
describe_op(afl, 0, NAME_MAX - strlen("id:000000,")),
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
#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 +799,18 @@ 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,")));
|
||||
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
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -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);
|
||||
|
@ -1157,18 +1157,22 @@ 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);
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
@ -1439,7 +1443,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 +1485,17 @@ 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);
|
||||
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
|
||||
|
||||
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 */
|
||||
|
||||
|
@ -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. */
|
||||
|
||||
@ -650,6 +655,7 @@ abort_calibration:
|
||||
|
||||
if (!first_run) { show_stats(afl); }
|
||||
|
||||
update_calibration_time(afl, &calibration_start_us);
|
||||
return fault;
|
||||
|
||||
}
|
||||
@ -669,11 +675,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;
|
||||
|
||||
@ -811,7 +822,7 @@ 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);
|
||||
|
||||
@ -819,7 +830,7 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
afl->syncing_party = sd_ent->d_name;
|
||||
afl->queued_imported +=
|
||||
save_if_interesting(afl, mem, st.st_size, fault);
|
||||
save_if_interesting(afl, mem, new_len, fault);
|
||||
afl->syncing_party = 0;
|
||||
|
||||
munmap(mem, st.st_size);
|
||||
@ -861,6 +872,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 +886,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 +912,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 +931,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 +970,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 +998,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 +1012,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;
|
||||
|
||||
@ -1039,8 +1063,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;
|
||||
|
||||
}
|
||||
|
@ -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"};
|
||||
|
@ -133,6 +133,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 +181,84 @@ 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("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);
|
||||
|
||||
}
|
||||
|
||||
@ -300,6 +332,10 @@ 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"
|
||||
"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,7 +373,7 @@ 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,
|
||||
(afl->start_time /*- afl->prev_run_time*/) / 1000, cur_time / 1000,
|
||||
runtime / 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
|
||||
@ -345,7 +381,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
: ((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 -
|
||||
(afl->calibration_time_us + afl->sync_time_us + afl->trim_time_us) /
|
||||
1000) /
|
||||
1000,
|
||||
afl->calibration_time_us / 1000000, afl->sync_time_us / 1000000,
|
||||
afl->trim_time_us / 1000000, afl->fsrv.total_execs,
|
||||
afl->fsrv.total_execs / ((double)(runtime) / 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,
|
||||
@ -876,6 +918,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);
|
||||
@ -2435,3 +2481,27 @@ void show_init_stats(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
void update_calibration_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->calibration_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
void update_trim_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->trim_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
void update_sync_time(afl_state_t *afl, u64 *time) {
|
||||
|
||||
u64 cur = get_cur_time_us();
|
||||
afl->sync_time_us += cur - *time;
|
||||
*time = cur;
|
||||
|
||||
}
|
||||
|
||||
|
@ -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 "
|
||||
@ -2073,6 +2075,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 +2098,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 +2123,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 +2501,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 +2545,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 +2565,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);
|
||||
@ -2572,6 +2588,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
sync_fuzzers(afl);
|
||||
|
||||
if (!afl->queue_cycle && afl->afl_env.afl_import_first) {
|
||||
|
||||
// real start time, we reset, so this works correctly with -V
|
||||
afl->start_time = get_cur_time();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
++afl->queue_cycle;
|
||||
@ -3061,7 +3084,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);
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
@ -10,6 +10,7 @@ PROGRAMS = afl-network-client afl-network-server
|
||||
HASH=\#
|
||||
|
||||
CFLAGS += -Wno-pointer-sign
|
||||
LDFLAGS += -ldl
|
||||
|
||||
ifdef STATIC
|
||||
CFLAGS += -static
|
||||
|
Reference in New Issue
Block a user