Merge pull request #534 from AFLplusplus/dev

push to stable for GSOC
This commit is contained in:
van Hauser 2020-08-31 19:04:37 +02:00 committed by GitHub
commit 2dffed1cff
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 588 additions and 300 deletions

4
.gitignore vendored
View File

@ -1,8 +1,10 @@
.test
.test2
.sync_tmp
.vscode
*.o
*.so
*.swp
*.pyc
*.dSYM
as
@ -10,6 +12,7 @@ ld
in
out
core*
compile_commands.json
afl-analyze
afl-as
afl-clang
@ -39,6 +42,7 @@ afl-cmin.8
afl-cmin.bash.8
afl-fuzz.8
afl-gcc.8
afl-g++.8
afl-gcc-fast.8
afl-g++-fast.8
afl-gotcpu.8

View File

@ -24,22 +24,21 @@ BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/man/man8
MAN_PATH = $(PREFIX)/share/man/man8
PROGNAME = afl
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
# PROGS intentionally omit afl-as, which gets installed elsewhere.
PROGS = afl-gcc afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
PROGS = afl-gcc afl-g++ afl-fuzz afl-showmap afl-tmin afl-gotcpu afl-analyze
SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
ASAN_OPTIONS=detect_leaks=0
ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
CFLAGS_FLTO ?= -flto=full
else
else
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
CFLAGS_FLTO ?= -flto=thin
else
@ -47,7 +46,7 @@ else
CFLAGS_FLTO ?= -flto
endif
endif
endif
endif
endif
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -fno-move-loop-invariants -fdisable-tree-cunrolli -x c - -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
@ -62,7 +61,10 @@ ifneq "$(shell uname)" "Darwin"
endif
endif
# OS X does not like _FORTIFY_SOURCE=2
# _FORTIFY_SOURCE=2 does not like -O0
ifndef DEBUG
CFLAGS_OPT += -D_FORTIFY_SOURCE=2
endif
endif
ifeq "$(shell uname)" "SunOS"
@ -204,7 +206,10 @@ else
endif
ifneq "$(filter Linux GNU%,$(shell uname))" ""
# _FORTIFY_SOURCE=2 does not like -O0
ifndef DEBUG
override CFLAGS += -D_FORTIFY_SOURCE=2
endif
LDFLAGS += -ldl -lrt
endif
@ -274,7 +279,7 @@ endif
all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
man: $(MANPAGES)
man: afl-gcc all $(MANPAGES)
tests: source-only
@cd test ; ./test-all.sh
@ -367,79 +372,81 @@ endif
ready:
@echo "[+] Everything seems to be working, ready to compile."
afl-g++: afl-gcc
afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(CPPFLAGS) src/$@.c -o $@ $(LDFLAGS)
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done
afl-as: src/afl-as.c include/afl-as.h $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) src/$@.c -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(CPPFLAGS) src/$@.c -o $@ $(LDFLAGS)
ln -sf afl-as as
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
$(CC) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
$(CC) $(CFLAGS) $(CPPFLAGS) -Iinclude $(SPECIAL_PERFORMANCE) -O3 -fno-unroll-loops -c src/afl-performance.c -o src/afl-performance.o
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-common.c -o src/afl-common.o
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -c src/afl-common.c -o src/afl-common.o
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-forkserver.c -o src/afl-forkserver.o
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -c src/afl-forkserver.c -o src/afl-forkserver.o
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
$(CC) $(CFLAGS) $(CFLAGS_FLTO) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CPPFLAGS) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) $(CPPFLAGS) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o -o $@ $(LDFLAGS)
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(CPPFLAGS) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
# document all mutations and only do one run (use with only one input file!)
document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) $(CPPFLAGS) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_maybe_alloc
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_hash
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_rand
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
unit_list: test/unittests/unit_list.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_list
test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
unit_preallocable: test/unittests/unit_preallocable.o
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CPPFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
./test/unittests/unit_preallocable
unit_clean:
@ -486,7 +493,7 @@ ifndef AFL_NO_X86
test_build: afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper and instrumentation output..."
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_DEBUG=1 AFL_INST_RATIO=100 AFL_AS_FORCE_INSTRUMENT=1 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) 2>&1 | grep 'afl-as' >/dev/null || (echo "Oops, afl-as did not get called from "$(TEST_CC)". This is normally achieved by "$(CC)" honoring the -B option."; exit 1 )
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@ -566,7 +573,8 @@ source-only: all
%.8: %
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
@echo .SH NAME >> $@
@echo .B $* >> $@
@echo -n ".B $* \- " >> $@
@./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> $@
@echo >> $@
@echo .SH SYNOPSIS >> $@
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@

View File

@ -1,10 +1,13 @@
# TODO list for AFL++
## Roadmap 2.67+
## Roadmap 2.68+
- AFL_MAP_SIZE for qemu_mode and unicorn_mode
- CPU affinity for many cores? There seems to be an issue > 96 cores
- afl-plot to support multiple plot_data
- afl_custom_fuzz_splice_optin()
- intel-pt tracer
- honor -O flags and -fno-unroll-loops in afl-cc
## Further down the road

View File

@ -120,6 +120,7 @@ function usage() {
"AFL_PATH: path for the afl-showmap binary\n" \
"AFL_SKIP_BIN_CHECK: skip check for target binary\n" \
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n"
"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n"
exit 1
}

View File

@ -15,14 +15,14 @@ libradamsa.a: libradamsa.c radamsa.h
@echo " ***************************************************************"
@echo " * Compiling libradamsa, wait some minutes (~3 on modern CPUs) *"
@echo " ***************************************************************"
$(CC) -fPIC $(CFLAGS) -I $(CUR_DIR) -o libradamsa.a -c libradamsa.c
$(CC) -fPIC $(CFLAGS) $(CPPFLAGS) -I $(CUR_DIR) -o libradamsa.a -c libradamsa.c
radamsa-mutator.so: radamsa-mutator.c libradamsa.a
$(CC) $(CFLAGS) -g -I. -I../../include -shared -fPIC -c radamsa-mutator.c
$(CC) $(CFLAGS) -shared -fPIC -o radamsa-mutator.so radamsa-mutator.o libradamsa.a
$(CC) $(CFLAGS) $(CPPFLAGS) -g -I. -I../../include -shared -fPIC -c radamsa-mutator.c
$(CC) $(CFLAGS) $(CPPFLAGS) -shared -fPIC -o radamsa-mutator.so radamsa-mutator.o libradamsa.a
test: libradamsa.a libradamsa-test.c
$(CC) $(CFLAGS) -I $(CUR_DIR) -o libradamsa-test libradamsa-test.c libradamsa.a
$(CC) $(CFLAGS) $(CPPFLAGS) -I $(CUR_DIR) -o libradamsa-test libradamsa-test.c libradamsa.a
./libradamsa-test libradamsa-test.c | grep "library test passed"
rm /tmp/libradamsa-*.fuzz

View File

@ -10,10 +10,18 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
### Version ++2.67d (develop)
- a few QOL changes for Apple and its outdated gmake
- afl-fuzz:
- Fix for auto dictionary entries found during fuzzing to not throw out
a -x dictionary
- added total execs done to plot file
- AFL_MAX_DET_EXTRAS env variable added to control the amount of deterministic
dict entries without recompiling.
- AFL_FORKSRV_INIT_TMOUT env variable added to control the time to wait for
the forkserver to come up without the need to increase the overall timeout.
- custom mutators:
- added afl_custom_fuzz_count/fuzz_count function to allow specifying the
number of fuzz attempts for custom_fuzz
- llvm_mode:
- Ported SanCov to LTO, and made it the default for LTO. better
instrumentation locations
@ -409,7 +417,7 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
- big code refactoring:
* all includes are now in include/
* all afl sources are now in src/ - see src/README.md
* afl-fuzz was splitted up in various individual files for including
* afl-fuzz was split up in various individual files for including
functionality in other programs (e.g. forkserver, memory map, etc.)
for better readability.
* new code indention everywhere

View File

@ -6,14 +6,14 @@
However, if there is only the binary program and no source code available,
then standard `afl-fuzz -n` (non-instrumented mode) is not effective.
The following is a description of how these binaries can be fuzzed with afl++
The following is a description of how these binaries can be fuzzed with afl++.
## TL;DR:
qemu_mode in persistent mode is the fastest - if the stability is
high enough. Otherwise try retrowrite, afl-dyninst and if these
fail too then standard qemu_mode with AFL_ENTRYPOINT to where you need it.
fail too then try standard qemu_mode with AFL_ENTRYPOINT to where you need it.
If your target is a library use examples/afl_frida/.
@ -29,10 +29,10 @@
The speed decrease is at about 50%.
However various options exist to increase the speed:
- using AFL_ENTRYPOINT to move the forkserver to a later basic block in
- using AFL_ENTRYPOINT to move the forkserver entry to a later basic block in
the binary (+5-10% speed)
- using persistent mode [qemu_mode/README.persistent.md](../qemu_mode/README.persistent.md)
this will result in 150-300% overall speed - so 3-8x the original
this will result in 150-300% overall speed increase - so 3-8x the original
qemu_mode speed!
- using AFL_CODE_START/AFL_CODE_END to only instrument specific parts
@ -104,7 +104,7 @@
## RETROWRITE
If you have an x86/x86_64 binary that still has it's symbols, is compiled
If you have an x86/x86_64 binary that still has its symbols, is compiled
with position independant code (PIC/PIE) and does not use most of the C++
features then the retrowrite solution might be for you.
It decompiles to ASM files which can then be instrumented with afl-gcc.
@ -148,7 +148,7 @@
## CORESIGHT
Coresight is ARM's answer to Intel's PT.
There is no implementation so far which handle coresight and getting
There is no implementation so far which handles coresight and getting
it working on an ARM Linux is very difficult due to custom kernel building
on embedded systems is difficult. And finding one that has coresight in
the ARM chip is difficult too.

View File

@ -32,6 +32,7 @@ performed with the custom mutator.
C/C++:
```c
void *afl_custom_init(afl_t *afl, unsigned int seed);
uint32_t afl_custom_fuzz_count(void *data, const u8 *buf, size_t buf_size);
size_t afl_custom_fuzz(void *data, uint8_t *buf, size_t buf_size, u8 **out_buf, uint8_t *add_buf, size_t add_buf_size, size_t max_size);
size_t afl_custom_post_process(void *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf);
int32_t afl_custom_init_trim(void *data, uint8_t *buf, size_t buf_size);
@ -49,6 +50,9 @@ Python:
def init(seed):
pass
def fuzz_count(buf, add_buf, max_size):
return cnt
def fuzz(buf, add_buf, max_size):
return mutated_out
@ -88,6 +92,14 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
This method determines whether the custom fuzzer should fuzz the current
queue entry or not
- `fuzz_count` (optional):
When a queue entry is selected to be fuzzed, afl-fuzz selects the number
of fuzzing attempts with this input based on a few factors.
If however the custom mutator wants to set this number instead on how often
it is called for a specific queue entry, use this function.
This function in mostly useful if **not** `AFL_CUSTOM_MUTATOR_ONLY` is used.
- `fuzz` (optional):
This method performs custom mutations on a given input. It also accepts an

View File

@ -10,8 +10,8 @@
Because they can't directly accept command-line options, the compile-time
tools make fairly broad use of environmental variables:
- Most afl tools do not print any ouput if stout/stderr are redirected.
If you want to have the output into a file then set the AFL_DEBUG
- Most afl tools do not print any output if stdout/stderr are redirected.
If you want to save the output in a file then set the AFL_DEBUG
environment variable.
This is sadly necessary for various build processes which fail otherwise.
@ -44,7 +44,7 @@ tools make fairly broad use of environmental variables:
you instrument hand-written assembly when compiling clang code by plugging
a normalizer into the chain. (There is no equivalent feature for GCC.)
- Setting AFL_INST_RATIO to a percentage between 0 and 100% controls the
- Setting AFL_INST_RATIO to a percentage between 0% and 100% controls the
probability of instrumenting every branch. This is (very rarely) useful
when dealing with exceptionally complex programs that saturate the output
bitmap. Examples include v8, ffmpeg, and perl.
@ -88,7 +88,7 @@ of the settings discussed in section #1, with the exception of:
- TMPDIR and AFL_KEEP_ASSEMBLY, since no temporary assembly files are
created.
- AFL_INST_RATIO, as we by default collision free instrumentation is used.
- AFL_INST_RATIO, as we by default use collision free instrumentation.
Then there are a few specific features that are only available in llvm_mode:
@ -121,7 +121,7 @@ Then there are a few specific features that are only available in llvm_mode:
None of the following options are necessary to be used and are rather for
manual use (which only ever the author of this LTO implementation will use).
These are used if several seperated instrumentation are performed which
These are used if several seperated instrumentations are performed which
are then later combined.
- AFL_LLVM_DOCUMENT_IDS=file will document to a file which edge ID was given
@ -200,7 +200,7 @@ Then there are a few specific features that are only available in llvm_mode:
### INSTRUMENT LIST (selectively instrument files and functions)
This feature allows selectively instrumentation of the source
This feature allows selective instrumentation of the source
- Setting AFL_LLVM_ALLOWLIST or AFL_LLVM_DENYLIST with a filenames and/or
function will only instrument (or skip) those files that match the names
@ -278,6 +278,14 @@ checks or alter some of the more exotic semantics of the tool:
don't want AFL to spend too much time classifying that stuff and just
rapidly put all timeouts in that bin.
- Setting AFL_FORKSRV_INIT_TMOUT allows yout to specify a different timeout
to wait for the forkserver to spin up. The default is the `-t` value times
`FORK_WAIT_MULT` from `config.h` (usually 10), so for a `-t 100`, the
default would wait `1000` milis. Setting a different time here is useful
if the target has a very slow startup time, for example when doing
full-system fuzzing or emulation, but you don't want the actual runs
to wait too long for timeouts.
- AFL_NO_ARITH causes AFL to skip most of the deterministic arithmetics.
This can be useful to speed up the fuzzing of text-based file formats.
@ -370,6 +378,16 @@ checks or alter some of the more exotic semantics of the tool:
normally done when starting up the forkserver and causes a pretty
significant performance drop.
- Setting AFL_MAX_DET_EXTRAS changes the count of dictionary entries/extras
(default 200), after which the entries will be used probabilistically.
So, if the dict/extras file (`-x`) contains more tokens than this threshold,
not all of the tokens will be used in each fuzzing step, every time.
Instead, there is a chance that the entry will be skipped during fuzzing.
This makes sure that the fuzzer doesn't spend all its time only inserting
the extras, but will still do other mutations. However, it decreases the
likelihood for each token to be inserted, before the next queue entry is fuzzed.
Either way, all tokens will be used eventually, in a longer fuzzing campaign.
- Outdated environment variables that are that not supported anymore:
AFL_DEFER_FORKSRV
AFL_PERSISTENT

View File

@ -10,8 +10,8 @@ n-core system, you can almost always run around n concurrent fuzzing jobs with
virtually no performance hit (you can use the afl-gotcpu tool to make sure).
In fact, if you rely on just a single job on a multi-core system, you will
be underutilizing the hardware. So, parallelization is usually the right
way to go.
be underutilizing the hardware. So, parallelization is always the right way to
go.
When targeting multiple unrelated binaries or using the tool in
"non-instrumented" (-n) mode, it is perfectly fine to just start up several
@ -65,22 +65,7 @@ still perform deterministic checks; while the secondary instances will
proceed straight to random tweaks.
Note that you must always have one -M main instance!
Note that running multiple -M instances is wasteful, although there is an
experimental support for parallelizing the deterministic checks. To leverage
that, you need to create -M instances like so:
```
./afl-fuzz -i testcase_dir -o sync_dir -M mainA:1/3 [...]
./afl-fuzz -i testcase_dir -o sync_dir -M mainB:2/3 [...]
./afl-fuzz -i testcase_dir -o sync_dir -M mainC:3/3 [...]
```
...where the first value after ':' is the sequential ID of a particular main
instance (starting at 1), and the second value is the total number of fuzzers to
distribute the deterministic fuzzing across. Note that if you boot up fewer
fuzzers than indicated by the second number passed to -M, you may end up with
poor coverage.
Running multiple -M instances is wasteful!
You can also monitor the progress of your jobs from the command line with the
provided afl-whatsup tool. When the instances are no longer finding new paths,
@ -99,61 +84,88 @@ example may be:
This is not a concern if you use @@ without -f and let afl-fuzz come up with the
file name.
## 3) Syncing with non-afl fuzzers or independant instances
## 3) Multiple -M mains
There is support for parallelizing the deterministic checks.
This is only needed where
1. many new paths are found fast over a long time and it looks unlikely that
main node will ever catch up, and
2. deterministic fuzzing is actively helping path discovery (you can see this
in the main node for the first for lines in the "fuzzing strategy yields"
section. If the ration `found/attemps` is high, then it is effective. It
most commonly isn't.)
Only if both are true it is beneficial to have more than one main.
You can leverage this by creating -M instances like so:
```
./afl-fuzz -i testcase_dir -o sync_dir -M mainA:1/3 [...]
./afl-fuzz -i testcase_dir -o sync_dir -M mainB:2/3 [...]
./afl-fuzz -i testcase_dir -o sync_dir -M mainC:3/3 [...]
```
... where the first value after ':' is the sequential ID of a particular main
instance (starting at 1), and the second value is the total number of fuzzers to
distribute the deterministic fuzzing across. Note that if you boot up fewer
fuzzers than indicated by the second number passed to -M, you may end up with
poor coverage.
## 4) Syncing with non-afl fuzzers or independant instances
A -M main node can be told with the `-F other_fuzzer_queue_directory` option
to sync results from other fuzzers, e.g. libfuzzer or honggfuzz.
Only the specified directory will by synced into afl, not subdirectories.
The specified directories do not need to exist yet at the start of afl.
The specified directory does not need to exist yet at the start of afl.
## 4) Multi-system parallelization
The `-F` option can be passed to the main node several times.
## 5) Multi-system parallelization
The basic operating principle for multi-system parallelization is similar to
the mechanism explained in section 2. The key difference is that you need to
write a simple script that performs two actions:
- Uses SSH with authorized_keys to connect to every machine and retrieve
a tar archive of the /path/to/sync_dir/<fuzzer_id>/queue/ directories for
every <fuzzer_id> local to the machine. It's best to use a naming scheme
that includes host name in the fuzzer ID, so that you can do something
like:
a tar archive of the /path/to/sync_dir/<main_node(s)> directory local to
the machine.
It is best to use a naming scheme that includes host name and it's being
a main node (e.g. main1, main2) in the fuzzer ID, so that you can do
something like:
```sh
for s in {1..10}; do
ssh user@host${s} "tar -czf - sync/host${s}_fuzzid*/[qf]*" >host${s}.tgz
for host in `cat HOSTLIST`; do
ssh user@$host "tar -czf - sync/$host_main*/" > $host.tgz
done
```
- Distributes and unpacks these files on all the remaining machines, e.g.:
```sh
for s in {1..10}; do
for d in {1..10}; do
test "$s" = "$d" && continue
ssh user@host${d} 'tar -kxzf -' <host${s}.tgz
for srchost in `cat HOSTLIST`; do
for dsthost in `cat HOSTLIST`; do
test "$srchost" = "$dsthost" && continue
ssh user@$srchost 'tar -kxzf -' < $dsthost.tgz
done
done
```
There is an example of such a script in examples/distributed_fuzzing/;
you can also find a more featured, experimental tool developed by
Martijn Bogaard at:
There is an example of such a script in examples/distributed_fuzzing/.
https://github.com/MartijnB/disfuzz-afl
There are other (older) more featured, experimental tools:
* https://github.com/richo/roving
* https://github.com/MartijnB/disfuzz-afl
Another client-server implementation from Richo Healey is:
https://github.com/richo/roving
Note that these third-party tools are unsafe to run on systems exposed to the
Internet or to untrusted users.
However these do not support syncing just main nodes (yet).
When developing custom test case sync code, there are several optimizations
to keep in mind:
- The synchronization does not have to happen very often; running the
task every 30 minutes or so may be perfectly fine.
task every 60 minutes or even less often at later fuzzing stages is
fine
- There is no need to synchronize crashes/ or hangs/; you only need to
copy over queue/* (and ideally, also fuzzer_stats).
@ -180,18 +192,23 @@ to keep in mind:
run them all with -S, and just designate a single process somewhere within
the fleet to run with -M.
- Syncing is only necessary for the main nodes on a system. It is possible
to run main-less with only secondaries. However then you need to find out
which secondary took over the temporary role to be the main node. Look for
the `is_main_node` file in the fuzzer directories, eg. `sync-dir/hostname-*/is_main_node`
It is *not* advisable to skip the synchronization script and run the fuzzers
directly on a network filesystem; unexpected latency and unkillable processes
in I/O wait state can mess things up.
## 5) Remote monitoring and data collection
## 6) Remote monitoring and data collection
You can use screen, nohup, tmux, or something equivalent to run remote
instances of afl-fuzz. If you redirect the program's output to a file, it will
automatically switch from a fancy UI to more limited status reports. There is
also basic machine-readable information always written to the fuzzer_stats file
in the output directory. Locally, that information can be interpreted with
afl-whatsup.
also basic machine-readable information which is always written to the
fuzzer_stats file in the output directory. Locally, that information can be
interpreted with afl-whatsup.
In principle, you can use the status screen of the main (-M) instance to
monitor the overall fuzzing progress and decide when to stop. In this
@ -208,7 +225,7 @@ Keep in mind that crashing inputs are *not* automatically propagated to the
main instance, so you may still want to monitor for crashes fleet-wide
from within your synchronization or health checking scripts (see afl-whatsup).
## 6) Asymmetric setups
## 7) Asymmetric setups
It is perhaps worth noting that all of the following is permitted:
@ -224,7 +241,7 @@ It is perhaps worth noting that all of the following is permitted:
the discovered test cases can have synergistic effects and improve the
overall coverage.
(In this case, running one -M instance per each binary is a good plan.)
(In this case, running one -M instance per target is necessary.)
- Having some of the fuzzers invoke the binary in different ways.
For example, 'djpeg' supports several DCT modes, configurable with

View File

@ -74,6 +74,7 @@ static u8 *in_data; /* Input data for trimming */
static u8 *buf2;
static s32 in_len;
static s32 buf2_len;
static u32 map_size = MAP_SIZE;
static volatile u8 stop_soon; /* Ctrl-C pressed? */
@ -381,6 +382,7 @@ int recv_testcase(int s, void **buf) {
if (clen < 1)
FATAL("did not receive valid compressed len information: %u", clen);
buf2 = afl_realloc((void **)&buf2, clen);
buf2_len = clen;
if (unlikely(!buf2)) { PFATAL("Alloc"); }
received = 0;
while (received < clen &&
@ -641,6 +643,7 @@ int main(int argc, char **argv_orig, char **envp) {
compressor = libdeflate_alloc_compressor(1);
decompressor = libdeflate_alloc_decompressor();
buf2 = afl_realloc((void **)&buf2, map_size + 16);
buf2_len = map_size + 16;
if (unlikely(!buf2)) { PFATAL("alloc"); }
lenptr = (u32 *)(buf2 + 4);
fprintf(stderr, "Compiled with compression support\n");

View File

@ -39,8 +39,11 @@ FUZZ_USER=bob
# Directory to synchronize
SYNC_DIR='/home/bob/sync_dir'
# Interval (seconds) between sync attempts
SYNC_INTERVAL=$((30 * 60))
# We only capture -M main nodes, set the name to your chosen naming scheme
MAIN_NAME='main'
# Interval (seconds) between sync attempts (eg one hour)
SYNC_INTERVAL=$((60 * 60))
if [ "$AFL_ALLOW_TMP" = "" ]; then
@ -63,7 +66,7 @@ while :; do
echo "[*] Retrieving data from ${host}.${FUZZ_DOMAIN}..."
ssh -o 'passwordauthentication no' ${FUZZ_USER}@${host}.$FUZZ_DOMAIN \
"cd '$SYNC_DIR' && tar -czf - ${host}_*/[qf]*" >".sync_tmp/${host}.tgz"
"cd '$SYNC_DIR' && tar -czf - ${host}_${MAIN_NAME}*/" > ".sync_tmp/${host}.tgz"
done
@ -80,7 +83,7 @@ while :; do
echo " Sending fuzzer data from ${src_host}.${FUZZ_DOMAIN}..."
ssh -o 'passwordauthentication no' ${FUZZ_USER}@$dst_host \
"cd '$SYNC_DIR' && tar -xkzf -" <".sync_tmp/${src_host}.tgz"
"cd '$SYNC_DIR' && tar -xkzf - " < ".sync_tmp/${src_host}.tgz"
done

View File

@ -24,7 +24,7 @@ PREFIX ?= /usr/local
HELPER_PATH ?= $(PREFIX)/lib/afl
BIN_PATH ?= $(PREFIX)/bin
DOC_PATH ?= $(PREFIX)/share/doc/afl
MAN_PATH ?= $(PREFIX)/man/man8
MAN_PATH ?= $(PREFIX)/share/man/man8
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
@ -111,21 +111,21 @@ test_deps:
@echo "[+] All set and ready to build."
afl-common.o: ../src/afl-common.c
$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
../afl-gcc-fast: afl-gcc-fast.c afl-common.o | test_deps
$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS)
$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $(CPPFLAGS) $< afl-common.o -o $@ $(LDFLAGS)
ln -sf afl-gcc-fast ../afl-g++-fast
../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps
$(CXX) $(CXXEFLAGS) $(PLUGIN_FLAGS) -shared $< -o $@
../afl-gcc-rt.o: afl-gcc-rt.o.c | test_deps
$(CC) $(CFLAGS_SAFE) -fPIC -c $< -o $@
$(CC) $(CFLAGS_SAFE) $(CPPFLAGS) -fPIC -c $< -o $@
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
unset AFL_USE_ASAN AFL_USE_MSAN; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) $(CPPFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
# unset AFL_USE_ASAN AFL_USE_MSAN; AFL_INST_RATIO=100 AFL_PATH=. AFL_CC=$(CC) ../afl-gcc-fast $(CFLAGS) ../test-instr.c -o test-instr $(LDFLAGS)
ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ../afl-showmap -m none -q -o .test-instr1 ./test-instr

View File

@ -24,7 +24,7 @@ PREFIX ?= /usr/local
HELPER_PATH ?= $(PREFIX)/lib/afl
BIN_PATH ?= $(PREFIX)/bin
DOC_PATH ?= $(PREFIX)/share/doc/afl
MAN_PATH ?= $(PREFIX)/man/man8
MAN_PATH ?= $(PREFIX)/share/man/man8
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
VERSION:sh= grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2

View File

@ -288,16 +288,19 @@ enum {
enum {
/* 00 */ PY_FUNC_INIT,
/* 01 */ PY_FUNC_FUZZ,
/* 02 */ PY_FUNC_POST_PROCESS,
/* 03 */ PY_FUNC_INIT_TRIM,
/* 04 */ PY_FUNC_POST_TRIM,
/* 05 */ PY_FUNC_TRIM,
/* 06 */ PY_FUNC_HAVOC_MUTATION,
/* 07 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY,
/* 08 */ PY_FUNC_QUEUE_GET,
/* 09 */ PY_FUNC_QUEUE_NEW_ENTRY,
/* 10 */ PY_FUNC_DEINIT,
/* 01 */ PY_FUNC_DEINIT,
/* FROM HERE ON BELOW ALL ARE OPTIONAL */
/* 02 */ PY_OPTIONAL = 2,
/* 02 */ PY_FUNC_FUZZ = 2,
/* 03 */ PY_FUNC_FUZZ_COUNT,
/* 04 */ PY_FUNC_POST_PROCESS,
/* 05 */ PY_FUNC_INIT_TRIM,
/* 06 */ PY_FUNC_POST_TRIM,
/* 07 */ PY_FUNC_TRIM,
/* 08 */ PY_FUNC_HAVOC_MUTATION,
/* 09 */ PY_FUNC_HAVOC_MUTATION_PROBABILITY,
/* 10 */ PY_FUNC_QUEUE_GET,
/* 11 */ PY_FUNC_QUEUE_NEW_ENTRY,
PY_FUNC_COUNT
};
@ -353,7 +356,8 @@ typedef struct afl_env_vars {
afl_cal_fast, afl_cycle_schedules, afl_expand_havoc;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
*afl_hang_tmout, *afl_skip_crashes, *afl_preload;
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
*afl_max_det_extras;
} afl_env_vars_t;
@ -506,7 +510,8 @@ typedef struct afl_state {
useless_at_start, /* Number of useless starting paths */
var_byte_count, /* Bitmap bytes with var behavior */
current_entry, /* Current queue entry ID */
havoc_div; /* Cycle count divisor for havoc */
havoc_div, /* Cycle count divisor for havoc */
max_det_extras; /* deterministic extra count (dicts)*/
u64 total_crashes, /* Total number of crashes */
unique_crashes, /* Crashes with unique signatures */
@ -677,6 +682,24 @@ struct custom_mutator {
*/
void *(*afl_custom_init)(afl_state_t *afl, unsigned int seed);
/**
* This method is called just before fuzzing a queue entry with the custom
* mutator, and receives the initial buffer. It should return the number of
* fuzzes to perform.
*
* A value of 0 means no fuzzing of this queue entry.
*
* The function is now allowed to change the data.
*
* (Optional)
*
* @param data pointer returned in afl_custom_init for this fuzz case
* @param buf Buffer containing the test case
* @param buf_size Size of the test case
* @return The amount of fuzzes to perform on this queue entry, 0 = skip
*/
u32 (*afl_custom_fuzz_count)(void *data, const u8 *buf, size_t buf_size);
/**
* Perform custom mutations on a given input
*
@ -865,6 +888,7 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf,
struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
void finalize_py_module(void *);
u32 fuzz_count_py(void *, const u8 *, size_t);
size_t post_process_py(void *, u8 *, size_t, u8 **);
s32 init_trim_py(void *, u8 *, size_t);
s32 post_trim_py(void *, u8);
@ -1003,7 +1027,18 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
}
return rand_next(afl) % limit;
/* Modulo is biased - we don't want our fuzzing to be biased so let's do it
right. See:
https://stackoverflow.com/questions/10984974/why-do-people-say-there-is-modulo-bias-when-using-a-random-number-generator
*/
u64 unbiased_rnd;
do {
unbiased_rnd = rand_next(afl);
} while (unlikely(unbiased_rnd >= (UINT64_MAX - (UINT64_MAX % limit))));
return unbiased_rnd % limit;
}

View File

@ -48,6 +48,7 @@ static char *afl_environment_variables[] = {
"AFL_GCC_INSTRUMENT_FILE",
"AFL_GCJ",
"AFL_HANG_TMOUT",
"AFL_FORKSRV_INIT_TMOUT",
"AFL_HARDEN",
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES",
"AFL_IMPORT_FIRST",
@ -102,6 +103,7 @@ static char *afl_environment_variables[] = {
"AFL_NO_X86", // not really an env but we dont want to warn on it
"AFL_MAP_SIZE",
"AFL_MAPSIZE",
"AFL_MAX_DET_EXTRAS",
"AFL_PATH",
"AFL_PERFORMANCE_FILE",
"AFL_PRELOAD",

View File

@ -56,6 +56,7 @@ typedef struct afl_forkserver {
u8 no_unlink; /* do not unlink cur_input */
u32 exec_tmout; /* Configurable exec timeout (ms) */
u32 init_tmout; /* Configurable init timeout (ms) */
u32 map_size; /* map size used by the target */
u32 snapshot; /* is snapshot feature used */
u64 mem_limit; /* Memory cap for child (MB) */

View File

@ -28,7 +28,7 @@ all: libdislocator.so
VPATH = ..
libdislocator.so: libdislocator.so.c ../config.h
$(CC) $(CFLAGS) -shared -fPIC libdislocator.so.c -o ../$@ $(LDFLAGS)
$(CC) $(CFLAGS) $(CPPFLAGS) -shared -fPIC libdislocator.so.c -o ../$@ $(LDFLAGS)
.NOTPARALLEL: clean

View File

@ -16,7 +16,7 @@
PREFIX ?= /usr/local
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH ?= $(PREFIX)/share/doc/afl
MAN_PATH ?= $(PREFIX)/man/man8
MAN_PATH ?= $(PREFIX)/share/man/man8
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
@ -70,7 +70,7 @@ all: $(TARGETS)
VPATH = ..
libtokencap.so: libtokencap.so.c ../config.h
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
$(CC) $(CFLAGS) $(CPPFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
.NOTPARALLEL: clean

View File

@ -275,8 +275,8 @@ static void __tokencap_load_mappings(void) {
for (c = map; r > 0; c++, r -= sizeof(prmap_t)) {
__tokencap_ro[__tokencap_ro_cnt].st = c->pr_vaddr;
__tokencap_ro[__tokencap_ro_cnt].en = c->pr_vaddr + c->pr_size;
__tokencap_ro[__tokencap_ro_cnt].st = (void *)c->pr_vaddr;
__tokencap_ro[__tokencap_ro_cnt].en = (void *)(c->pr_vaddr + c->pr_size);
if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;

View File

@ -24,10 +24,12 @@ HELPER_PATH ?= $(PREFIX)/lib/afl
BIN_PATH ?= $(PREFIX)/bin
DOC_PATH ?= $(PREFIX)/share/doc/afl
MISC_PATH ?= $(PREFIX)/share/afl
MAN_PATH ?= $(PREFIX)/man/man8
MAN_PATH ?= $(PREFIX)/share/man/man8
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/null || date -u "+%Y-%m-%d")
ifeq "$(shell uname)" "OpenBSD"
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
@ -224,7 +226,8 @@ CFLAGS_SAFE := -Wall -g -Wno-pointer-sign -I ../include/ \
-DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \
-DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" \
-DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) -Wno-unused-function \
-fdebug-prefix-map="$(CURDIR)=llvm_mode"
override CFLAGS += $(CFLAGS_SAFE)
ifdef AFL_TRACE_PC
@ -329,10 +332,10 @@ endif
@echo "[+] All set and ready to build."
afl-common.o: ../src/afl-common.c
$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
$(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@ $(LDFLAGS)
../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps
$(CC) $(CLANG_CFL) $(CFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
$(CC) $(CLANG_CFL) $(CFLAGS) $(CPPFLAGS) $< afl-common.o -o $@ $(LDFLAGS) -DCFLAGS_OPT=\"$(CFLAGS_OPT)\"
ln -sf afl-clang-fast ../afl-clang-fast++
ifneq "$(AFL_CLANG_FLTO)" ""
ifeq "$(LLVM_LTO)" "1"
@ -342,7 +345,7 @@ endif
endif
afl-llvm-common.o: afl-llvm-common.cc afl-llvm-common.h
$(CXX) $(CFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
$(CXX) $(CFLAGS) $(CPPFLAGS) `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc afl-llvm-common.o | test_deps
-$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL) afl-llvm-common.o
@ -360,7 +363,7 @@ endif
../afl-ld-lto: afl-ld-lto.c
ifeq "$(LLVM_LTO)" "1"
$(CC) $(CFLAGS) $< -o $@
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
endif
../SanitizerCoverageLTO.so: SanitizerCoverageLTO.so.cc
@ -371,9 +374,9 @@ endif
../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc afl-llvm-common.o
ifeq "$(LLVM_LTO)" "1"
$(CXX) $(CLANG_CPPFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
$(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o
@$(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
@$(CLANG_BIN) $(CFLAGS_SAFE) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto.o
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c afl-llvm-rt-lto.o.c -o ../afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
endif
# laf
@ -392,20 +395,20 @@ endif
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) afl-llvm-common.o
document:
$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt.o
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m32 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-32.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
@$(CLANG_BIN) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS_SAFE) $(CPPFLAGS) $(CLANG_CFL) -O3 -Wno-unused-result -m64 -fPIC -c afl-llvm-rt.o.c -o ../afl-llvm-rt-64.o 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -fPIC -c $< -o $@
$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -fPIC -c $< -o $@
../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m32 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
../afl-llvm-rt-64.o: afl-llvm-rt.o.c | test_deps
@printf "[*] Building 64-bit variant of the runtime (-m64)... "
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
@$(CLANG_BIN) $(CLANG_CFL) $(CFLAGS_SAFE) $(CPPFLAGS) -O3 -Wno-unused-result -m64 -fPIC -c $< -o $@ 2>/dev/null; if [ "$$?" = "0" ]; then echo "success!"; else echo "failed (that's fine)"; fi
test_build: $(PROGS)
@echo "[*] Testing the CC wrapper and instrumentation output..."
@ -434,15 +437,16 @@ install: all
if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); fi
if [ -f ../SanitizerCoverageLTO.so ]; then set -e; install -m 755 ../SanitizerCoverageLTO.so $${DESTDIR}$(HELPER_PATH); fi
set -e; install -m 644 ../dynamic_list.txt $${DESTDIR}$(HELPER_PATH)
set -e; if [ -f ../afl-clang-fast ] ; then ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf ../afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
set -e; if [ -f ../afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
install -m 644 README.*.md $${DESTDIR}$(DOC_PATH)/
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md
install -m 644 README.md $${DESTDIR}$(DOC_PATH)/README.llvm_mode.md
vpath % ..
%.8: %
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
@echo .TH $* 8 $(BUILD_DATE) "afl++" > ../$@
@echo .SH NAME >> ../$@
@echo .B $* >> ../$@
@echo -n ".B $* \- " >> ../$@
@../$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ../$@
@echo >> ../$@
@echo .SH SYNOPSIS >> ../$@
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@

View File

@ -243,7 +243,7 @@ struct InsTrim : public ModulePass {
for (unsigned I = 0; I < PrevLocSize - 1; ++I)
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
for (unsigned I = PrevLocSize; I < PrevLocVecSize; ++I)
for (int I = PrevLocSize; I < PrevLocVecSize; ++I)
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);

View File

@ -437,8 +437,6 @@ bool ModuleSanitizerCoverage::instrumentModule(
if ((afl_global_id = atoi(ptr)) < 0)
FATAL("AFL_LLVM_LTO_STARTID value of \"%s\" is negative\n", ptr);
if (getenv("AFL_LLVM_CMPLOG")) autodictionary = 0;
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
if ((documentFile = fopen(ptr, "a")) == NULL)

View File

@ -670,9 +670,11 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
#ifndef __APPLE__
if (!shared_linking)
cc_params[cc_par_cnt++] =
alloc_printf("-Wl,--dynamic-list=%s/dynamic_list.txt", obj_path);
#endif
#endif
@ -811,13 +813,25 @@ int main(int argc, char **argv, char **envp) {
if (strncasecmp(ptr, "ngram", strlen("ngram")) == 0) {
ptr += strlen("ngram");
while (*ptr && (*ptr < '0' || *ptr > '9'))
while (*ptr && (*ptr < '0' || *ptr > '9')) {
ptr++;
if (!*ptr)
if ((ptr = getenv("AFL_LLVM_NGRAM_SIZE")) != NULL)
}
if (!*ptr) {
ptr = getenv("AFL_LLVM_NGRAM_SIZE");
if (!ptr || !*ptr) {
FATAL(
"you must set the NGRAM size with (e.g. for value 2) "
"AFL_LLVM_INSTRUMENT=ngram-2");
}
}
ngram_size = atoi(ptr);
if (ngram_size < 2 || ngram_size > NGRAM_SIZE_MAX)
FATAL(

View File

@ -344,9 +344,10 @@ static std::string getSourceName(llvm::Function *F) {
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR >= 7)
if (Loc) {
StringRef instFilename;
DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
StringRef instFilename = cDILoc->getFilename();
if (cDILoc) { instFilename = cDILoc->getFilename(); }
if (instFilename.str().empty()) {

View File

@ -87,7 +87,7 @@ class AFLLTOPass : public ModulePass {
bool runOnModule(Module &M) override;
protected:
int afl_global_id = 1, autodictionary = 0;
int afl_global_id = 1, autodictionary = 1;
uint32_t function_minimum_size = 1;
uint32_t inst_blocks = 0, inst_funcs = 0, total_instr = 0;
uint64_t map_addr = 0x10000;
@ -128,8 +128,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
be_quiet = 1;
if (getenv("AFL_LLVM_CMPLOG")) autodictionary = 0;
if ((ptr = getenv("AFL_LLVM_DOCUMENT_IDS")) != NULL) {
if ((documentFile = fopen(ptr, "a")) == NULL)
@ -137,8 +135,6 @@ bool AFLLTOPass::runOnModule(Module &M) {
}
if (getenv("AFL_LLVM_LTO_AUTODICTIONARY")) autodictionary = 1;
// we make this the default as the fixed map has problems with
// defered forkserver, early constructors, ifuncs and maybe more
/*if (getenv("AFL_LLVM_MAP_DYNAMIC"))*/
@ -378,16 +374,29 @@ bool AFLLTOPass::runOnModule(Module &M) {
std::string Str1, Str2;
StringRef TmpStr;
bool HasStr1 = getConstantStringInfo(Str1P, TmpStr);
if (TmpStr.empty())
if (TmpStr.empty()) {
HasStr1 = false;
else
} else {
HasStr1 = true;
Str1 = TmpStr.str();
}
bool HasStr2 = getConstantStringInfo(Str2P, TmpStr);
if (TmpStr.empty())
if (TmpStr.empty()) {
HasStr2 = false;
else
} else {
HasStr2 = true;
Str2 = TmpStr.str();
}
if (debug)
fprintf(stderr, "F:%s %p(%s)->\"%s\"(%s) %p(%s)->\"%s\"(%s)\n",
FuncName.c_str(), Str1P, Str1P->getName().str().c_str(),

View File

@ -284,7 +284,7 @@ bool AFLCoverage::runOnModule(Module &M) {
for (unsigned I = 0; I < PrevLocSize - 1; ++I)
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
for (unsigned I = PrevLocSize; I < PrevLocVecSize; ++I)
for (int I = PrevLocSize; I < PrevLocVecSize; ++I)
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);

View File

@ -339,7 +339,7 @@ static void __afl_map_shm(void) {
if (__afl_area_ptr == MAP_FAILED) {
fprintf(stderr, "can not aquire mmap for address %p\n",
fprintf(stderr, "can not acquire mmap for address %p\n",
(void *)__afl_map_addr);
exit(1);

View File

@ -1272,7 +1272,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
if (!be_quiet) {
errs() << "Split-floatingpoint-compare-pass: " << count
<< " FP comparisons splitted\n";
<< " FP comparisons split\n";
}
@ -1290,7 +1290,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
count = splitIntCompares(M, bitw);
if (!be_quiet)
errs() << "Split-integer-compare-pass " << bitw << "bit: " << count
<< " splitted\n";
<< " split\n";
bitw >>= 1;
#if LLVM_VERSION_MAJOR > 3 || \
@ -1301,7 +1301,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
count = splitIntCompares(M, bitw);
if (!be_quiet)
errs() << "Split-integer-compare-pass " << bitw << "bit: " << count
<< " splitted\n";
<< " split\n";
bitw >>= 1;
#if LLVM_VERSION_MAJOR > 3 || \
@ -1312,7 +1312,7 @@ bool SplitComparesTransform::runOnModule(Module &M) {
count = splitIntCompares(M, bitw);
if (!be_quiet)
errs() << "Split-integer-compare-pass " << bitw << "bit: " << count
<< " splitted\n";
<< " split\n";
bitw >>= 1;
break;

View File

@ -16,7 +16,7 @@
PREFIX ?= /usr/local
HELPER_PATH = $(PREFIX)/lib/afl
DOC_PATH ?= $(PREFIX)/share/doc/afl
MAN_PATH ?= $(PREFIX)/man/man8
MAN_PATH ?= $(PREFIX)/share/man/man8
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)

View File

@ -152,7 +152,7 @@ static void edit_params(int argc, char **argv) {
/* The Apple case is a bit different... */
if (!strcmp(argv[i], "-arch") && i + 1 < argc) {
if (!strcmp(argv[i], "-arch") && i + 1 < (u32)argc) {
if (!strcmp(argv[i + 1], "x86_64"))
use_64bit = 1;

View File

@ -79,6 +79,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
fsrv->use_stdin = 1;
fsrv->no_unlink = 0;
fsrv->exec_tmout = EXEC_TIMEOUT;
fsrv->init_tmout = EXEC_TIMEOUT * FORK_WAIT_MULT;
fsrv->mem_limit = MEM_LIMIT;
fsrv->out_file = NULL;
@ -101,6 +102,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->out_fd = from->out_fd;
fsrv_to->dev_null_fd = from->dev_null_fd;
fsrv_to->exec_tmout = from->exec_tmout;
fsrv_to->init_tmout = from->init_tmout;
fsrv_to->mem_limit = from->mem_limit;
fsrv_to->map_size = from->map_size;
fsrv_to->support_shmem_fuzz = from->support_shmem_fuzz;
@ -115,6 +117,7 @@ void afl_fsrv_init_dup(afl_forkserver_t *fsrv_to, afl_forkserver_t *from) {
fsrv_to->out_file = NULL;
fsrv_to->init_child_func = fsrv_exec_child;
// Note: do not copy ->add_extra_func
list_append(&fsrv_list, fsrv_to);
@ -516,15 +519,14 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
rlen = 0;
if (fsrv->exec_tmout) {
u32 time_ms =
read_s32_timed(fsrv->fsrv_st_fd, &status,
fsrv->exec_tmout * FORK_WAIT_MULT, stop_soon_p);
u32 time_ms = read_s32_timed(fsrv->fsrv_st_fd, &status, fsrv->init_tmout,
stop_soon_p);
if (!time_ms) {
kill(fsrv->fsrv_pid, SIGKILL);
} else if (time_ms > fsrv->exec_tmout * FORK_WAIT_MULT) {
} else if (time_ms > fsrv->init_tmout) {
fsrv->last_run_timed_out = 1;
kill(fsrv->fsrv_pid, SIGKILL);
@ -632,7 +634,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if (fsrv->add_extra_func == NULL || fsrv->afl_ptr == NULL) {
// this is not afl-fuzz - we deny and return
// this is not afl-fuzz - or it is cmplog - we deny and return
if (fsrv->use_shmem_fuzz) {
status = (FS_OPT_ENABLED | FS_OPT_SHDMEM_FUZZ);
@ -939,7 +941,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
s32 fd = fsrv->out_fd;
if (fsrv->out_file) {
if (!fsrv->use_stdin) {
if (fsrv->no_unlink) {
@ -962,7 +964,7 @@ void afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *buf, size_t len) {
ck_write(fd, buf, len, fsrv->out_file);
if (!fsrv->out_file) {
if (fsrv->use_stdin) {
if (ftruncate(fd, len)) { PFATAL("ftruncate() failed"); }
lseek(fd, 0, SEEK_SET);

View File

@ -248,10 +248,10 @@ static void extras_check_and_sort(afl_state_t *afl, u32 min_len, u32 max_len,
}
if (afl->extras_cnt > MAX_DET_EXTRAS) {
if (afl->extras_cnt > afl->max_det_extras) {
WARNF("More than %d tokens - will use them probabilistically.",
MAX_DET_EXTRAS);
OKF("More than %d tokens - will use them probabilistically.",
afl->max_det_extras);
}
@ -319,8 +319,8 @@ void load_extras(afl_state_t *afl, u8 *dir) {
if (st.st_size > MAX_DICT_FILE) {
FATAL(
"Extra '%s' is too big (%s, limit is %s)", fn,
WARNF(
"Extra '%s' is very big (%s, limit is %s)", fn,
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
@ -370,14 +370,14 @@ static inline u8 memcmp_nocase(u8 *m1, u8 *m2, u32 len) {
}
/* Adds a new extra / dict entry. */
/* Adds a new extra / dict entry. Used for LTO autodict. */
void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
u8 val_bufs[2][STRINGIFY_VAL_SIZE_MAX];
if (len > MAX_DICT_FILE) {
FATAL("Extra '%.*s' is too big (%s, limit is %s)", (int)len, mem,
WARNF("Extra '%.*s' is very big (%s, limit is %s)", (int)len, mem,
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), len),
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
@ -403,10 +403,10 @@ void add_extra(afl_state_t *afl, u8 *mem, u32 len) {
/* We only want to print this once */
if (afl->extras_cnt == MAX_DET_EXTRAS + 1) {
if (afl->extras_cnt == afl->max_det_extras + 1) {
WARNF("More than %d tokens - will use them probabilistically.",
MAX_DET_EXTRAS);
OKF("More than %d tokens - will use them probabilistically.",
afl->max_det_extras);
}

View File

@ -256,18 +256,18 @@ void bind_to_free_cpu(afl_state_t *afl) {
}
for (i = 0; i < proccount; i++) {
for (i = 0; i < (s32)proccount; i++) {
#if defined(__FreeBSD__)
if (!strcmp(procs[i].ki_comm, "idle")) continue;
// fix when ki_oncpu = -1
int oncpu;
s32 oncpu;
oncpu = procs[i].ki_oncpu;
if (oncpu == -1) oncpu = procs[i].ki_lastcpu;
if (oncpu != -1 && oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
if (oncpu != -1 && oncpu < (s32)sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
cpu_used[oncpu] = 1;
#elif defined(__DragonFly__)
@ -1841,24 +1841,26 @@ void setup_cmdline_file(afl_state_t *afl, char **argv) {
void setup_stdio_file(afl_state_t *afl) {
u8 *fn;
if (afl->file_extension) {
fn = alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
afl->fsrv.out_file =
alloc_printf("%s/.cur_input.%s", afl->tmp_dir, afl->file_extension);
} else {
fn = alloc_printf("%s/.cur_input", afl->tmp_dir);
afl->fsrv.out_file = alloc_printf("%s/.cur_input", afl->tmp_dir);
}
unlink(fn); /* Ignore errors */
unlink(afl->fsrv.out_file); /* Ignore errors */
afl->fsrv.out_fd = open(fn, O_RDWR | O_CREAT | O_EXCL, 0600);
afl->fsrv.out_fd = open(afl->fsrv.out_file, O_RDWR | O_CREAT | O_EXCL, 0600);
if (afl->fsrv.out_fd < 0) { PFATAL("Unable to create '%s'", fn); }
if (afl->fsrv.out_fd < 0) {
ck_free(fn);
PFATAL("Unable to create '%s'", afl->fsrv.out_file);
}
}

View File

@ -166,6 +166,11 @@ struct custom_mutator *load_custom_mutator(afl_state_t *afl, const char *fn) {
}
/* "afl_custom_fuzz_count", optional */
mutator->afl_custom_fuzz_count = dlsym(dh, "afl_custom_fuzz_count");
if (!mutator->afl_custom_fuzz_count)
ACTF("optional symbol 'afl_custom_fuzz_count' not found.");
/* "afl_custom_deinit", optional for backward compatibility */
mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
if (!mutator->afl_custom_deinit)

View File

@ -1509,13 +1509,13 @@ skip_interest:
for (j = 0; j < afl->extras_cnt; ++j) {
/* Skip extras probabilistically if afl->extras_cnt > MAX_DET_EXTRAS. Also
skip them if there's no room to insert the payload, if the token
/* Skip extras probabilistically if afl->extras_cnt > AFL_MAX_DET_EXTRAS.
Also skip them if there's no room to insert the payload, if the token
is redundant, or if its entire span has no bytes set in the effector
map. */
if ((afl->extras_cnt > MAX_DET_EXTRAS &&
rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
if ((afl->extras_cnt > afl->max_det_extras &&
rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) ||
afl->extras[j].len > len - i ||
!memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
!memchr(eff_map + EFF_APOS(i), 1,
@ -1672,7 +1672,7 @@ custom_mutator_stage:
if (afl->stage_max < HAVOC_MIN) { afl->stage_max = HAVOC_MIN; }
const u32 max_seed_size = MAX_FILE;
const u32 max_seed_size = MAX_FILE, saved_max = afl->stage_max;
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
@ -1680,10 +1680,17 @@ custom_mutator_stage:
if (el->afl_custom_fuzz) {
if (el->afl_custom_fuzz_count)
afl->stage_max = el->afl_custom_fuzz_count(el->data, out_buf, len);
else
afl->stage_max = saved_max;
has_custom_fuzz = true;
afl->stage_short = el->name_short;
if (afl->stage_max) {
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max;
++afl->stage_cur) {
@ -1729,7 +1736,11 @@ custom_mutator_stage:
/* Read the additional testcase into a new buffer. */
fd = open(target->fname, O_RDONLY);
if (unlikely(fd < 0)) { PFATAL("Unable to open '%s'", target->fname); }
if (unlikely(fd < 0)) {
PFATAL("Unable to open '%s'", target->fname);
}
new_buf = afl_realloc(AFL_BUF_PARAM(out_scratch), target->len);
if (unlikely(!new_buf)) { PFATAL("alloc"); }
@ -1756,6 +1767,8 @@ custom_mutator_stage:
}
if (!el->afl_custom_fuzz_count) {
/* If we're finding new stuff, let's run for a bit longer, limits
permitting. */
@ -1774,8 +1787,12 @@ custom_mutator_stage:
}
/* `(afl->)out_buf` may have been changed by the call to custom_fuzz */
/* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs Memcpy.
}
/* `(afl->)out_buf` may have been changed by the call to custom_fuzz
*/
/* TODO: Only do this when `mutated_buf` == `out_buf`? Branch vs
* Memcpy.
*/
memcpy(out_buf, in_buf, len);
@ -1783,6 +1800,8 @@ custom_mutator_stage:
}
}
});
if (!has_custom_fuzz) goto havoc_stage;
@ -3722,13 +3741,13 @@ skip_interest:
for (j = 0; j < afl->extras_cnt; ++j) {
/* Skip extras probabilistically if afl->extras_cnt > MAX_DET_EXTRAS. Also
skip them if there's no room to insert the payload, if the token
/* Skip extras probabilistically if afl->extras_cnt > AFL_MAX_DET_EXTRAS.
Also skip them if there's no room to insert the payload, if the token
is redundant, or if its entire span has no bytes set in the effector
map. */
if ((afl->extras_cnt > MAX_DET_EXTRAS &&
rand_below(afl, afl->extras_cnt) >= MAX_DET_EXTRAS) ||
if ((afl->extras_cnt > afl->max_det_extras &&
rand_below(afl, afl->extras_cnt) >= afl->max_det_extras) ||
afl->extras[j].len > len - i ||
!memcmp(afl->extras[j].data, out_buf + i, afl->extras[j].len) ||
!memchr(eff_map + EFF_APOS(i), 1,

View File

@ -144,6 +144,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
if (!py_functions[PY_FUNC_FUZZ])
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "mutate");
py_functions[PY_FUNC_FUZZ_COUNT] =
PyObject_GetAttrString(py_module, "fuzz_count");
if (!py_functions[PY_FUNC_FUZZ])
WARNF("fuzz function not found in python module");
py_functions[PY_FUNC_POST_PROCESS] =
@ -169,27 +171,20 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
if (py_idx == PY_FUNC_POST_PROCESS) {
// Implenting the post_process API is optional for now
if (PyErr_Occurred()) { PyErr_Print(); }
} else if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
if (py_idx >= PY_FUNC_INIT_TRIM && py_idx <= PY_FUNC_TRIM) {
// Implementing the trim API is optional for now
if (PyErr_Occurred()) { PyErr_Print(); }
py_notrim = 1;
} else if ((py_idx >= PY_FUNC_HAVOC_MUTATION) &&
} else if (py_idx >= PY_OPTIONAL) {
(py_idx <= PY_FUNC_QUEUE_NEW_ENTRY)) {
// Only _init and _deinit are not optional currently
// Implenting the havoc and queue API is optional for now
if (PyErr_Occurred()) { PyErr_Print(); }
} else {
if (PyErr_Occurred()) { PyErr_Print(); }
fprintf(stderr,
"Cannot find/call function with index %d in external "
"Python module.\n",
@ -347,6 +342,12 @@ struct custom_mutator *load_custom_mutator_py(afl_state_t *afl,
}
if (py_functions[PY_FUNC_FUZZ_COUNT]) {
mutator->afl_custom_fuzz_count = fuzz_count_py;
}
if (py_functions[PY_FUNC_POST_TRIM]) {
mutator->afl_custom_post_trim = post_trim_py;
@ -477,6 +478,44 @@ s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
}
u32 fuzz_count_py(void *py_mutator, const u8 *buf, size_t buf_size) {
PyObject *py_args, *py_value;
py_args = PyTuple_New(1);
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
if (!py_value) {
Py_DECREF(py_args);
FATAL("Failed to convert arguments");
}
PyTuple_SetItem(py_args, 0, py_value);
py_value = PyObject_CallObject(
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ_COUNT], py_args);
Py_DECREF(py_args);
if (py_value != NULL) {
#if PY_MAJOR_VERSION >= 3
u32 retcnt = (u32)PyLong_AsLong(py_value);
#else
u32 retcnt = PyInt_AsLong(py_value);
#endif
Py_DECREF(py_value);
return retcnt;
} else {
PyErr_Print();
FATAL("Call failed");
}
}
s32 post_trim_py(void *py_mutator, u8 success) {
PyObject *py_args, *py_value;

View File

@ -349,6 +349,20 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
afl->afl_env.afl_preload =
(u8 *)get_afl_env(afl_environment_variables[i]);
} else if (!strncmp(env, "AFL_MAX_DET_EXTRAS",
afl_environment_variable_len)) {
afl->afl_env.afl_max_det_extras =
(u8 *)get_afl_env(afl_environment_variables[i]);
} else if (!strncmp(env, "AFL_FORKSRV_INIT_TMOUT",
afl_environment_variable_len)) {
afl->afl_env.afl_forksrv_init_tmout =
(u8 *)get_afl_env(afl_environment_variables[i]);
}
} else {

View File

@ -173,10 +173,14 @@ static void usage(u8 *argv0, int more_help) {
"AFL_FAST_CAL: limit the calibration stage to three cycles for speedup\n"
"AFL_FORCE_UI: force showing the status screen (for virtual consoles)\n"
"AFL_HANG_TMOUT: override timeout value (in milliseconds)\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
"AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: don't warn about core dump handlers\n"
"AFL_IMPORT_FIRST: sync and import test cases from other fuzzer instances first\n"
"AFL_MAP_SIZE: the shared memory size for that target. must be >= the size\n"
" the target was compiled for\n"
"AFL_MAX_DET_EXTRAS: if more entries are in the dictionary list than this value\n"
" then they are randomly selected instead all of them being\n"
" used. Defaults to 200.\n"
"AFL_NO_AFFINITY: do not check for an unused cpu core to use for fuzzing\n"
"AFL_NO_ARITH: skip arithmetic mutations in deterministic stage\n"
"AFL_NO_CPU_RED: avoid red color for showing very high cpu usage\n"
@ -188,7 +192,7 @@ static void usage(u8 *argv0, int more_help) {
"AFL_QUIET: suppress forkserver status messages\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_SHUFFLE_QUEUE: reorder the input queue randomly on startup\n"
"AFL_SKIP_BIN_CHECK: skip the check, if the target is an excutable\n"
"AFL_SKIP_BIN_CHECK: skip the check, if the target is an executable\n"
"AFL_SKIP_CPUFREQ: do not warn about variable cpu clocking\n"
"AFL_SKIP_CRASHES: during initial dry run do not terminate for crashing inputs\n"
"AFL_TMPDIR: directory to use for input file generation (ramdisk recommended)\n"
@ -949,8 +953,36 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->afl_env.afl_hang_tmout) {
afl->hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
if (!afl->hang_tmout) { FATAL("Invalid value of AFL_HANG_TMOUT"); }
s32 hang_tmout = atoi(afl->afl_env.afl_hang_tmout);
if (hang_tmout < 1) { FATAL("Invalid value for AFL_HANG_TMOUT"); }
afl->hang_tmout = (u32)hang_tmout;
}
if (afl->afl_env.afl_max_det_extras) {
s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
if (max_det_extras < 1) { FATAL("Invalid value for AFL_MAX_DET_EXTRAS"); }
afl->max_det_extras = (u32)max_det_extras;
} else {
afl->max_det_extras = MAX_DET_EXTRAS;
}
if (afl->afl_env.afl_forksrv_init_tmout) {
afl->fsrv.init_tmout = atoi(afl->afl_env.afl_forksrv_init_tmout);
if (!afl->fsrv.init_tmout) {
FATAL("Invalid value of AFL_FORKSRV_INIT_TMOUT");
}
} else {
afl->fsrv.init_tmout = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
}

View File

@ -415,7 +415,7 @@ int main(int argc, char **argv) {
"AFL_KEEP_ASSEMBLY: leave instrumented assembly files\n"
"AFL_AS_FORCE_INSTRUMENT: force instrumentation for asm sources\n";
if (argc == 2 && strcmp(argv[1], "-h") == 0) {
if (argc == 2 && strncmp(argv[1], "-h", 2) == 0) {
printf("afl-cc" VERSION " by Michal Zalewski\n\n");
printf("%s \n\n", argv[0]);

View File

@ -72,12 +72,12 @@ void jump(afl_state_t *afl) {
static const uint64_t JUMP[] = {0x180ec6d33cfd0aba, 0xd5a61266f0c9392c,
0xa9582618e03fc9aa, 0x39abdc4529b1661c};
int i, b;
size_t i, b;
uint64_t s0 = 0;
uint64_t s1 = 0;
uint64_t s2 = 0;
uint64_t s3 = 0;
for (i = 0; i < sizeof JUMP / sizeof *JUMP; i++)
for (i = 0; i < (sizeof(JUMP) / sizeof(*JUMP)); i++)
for (b = 0; b < 64; b++) {
if (JUMP[i] & UINT64_C(1) << b) {
@ -110,12 +110,12 @@ void long_jump(afl_state_t *afl) {
static const uint64_t LONG_JUMP[] = {0x76e15d3efefdcbbf, 0xc5004e441c522fb3,
0x77710069854ee241, 0x39109bb02acbe635};
int i, b;
size_t i, b;
uint64_t s0 = 0;
uint64_t s1 = 0;
uint64_t s2 = 0;
uint64_t s3 = 0;
for (i = 0; i < sizeof LONG_JUMP / sizeof *LONG_JUMP; i++)
for (i = 0; i < (sizeof(LONG_JUMP) / sizeof(*LONG_JUMP)); i++)
for (b = 0; b < 64; b++) {
if (LONG_JUMP[i] & UINT64_C(1) << b) {
@ -145,7 +145,7 @@ void long_jump(afl_state_t *afl) {
u32 hash32(u8 *key, u32 len, u32 seed) {
#else
u32 inline hash32(u8 *key, u32 len, u32 seed) {
inline u32 hash32(u8 *key, u32 len, u32 seed) {
#endif
@ -157,7 +157,7 @@ u32 inline hash32(u8 *key, u32 len, u32 seed) {
u64 hash64(u8 *key, u32 len, u64 seed) {
#else
u64 inline hash64(u8 *key, u32 len, u64 seed) {
inline u64 hash64(u8 *key, u32 len, u64 seed) {
#endif

View File

@ -636,6 +636,8 @@ static void usage(u8 *argv0) {
"size\n"
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during "
"startup (in milliseconds)\n"
"AFL_QUIET: do not print extra informational output\n",
argv0, MEM_LIMIT, doc_path);
@ -1036,6 +1038,19 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
if (forksrv_init_tmout < 1) {
FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
}
fsrv->init_tmout = (u32)forksrv_init_tmout;
}
afl_fsrv_start(fsrv, use_argv, &stop_soon,
get_afl_env("AFL_DEBUG_CHILD_OUTPUT") ? 1 : 0);
map_size = fsrv->map_size;

View File

@ -846,6 +846,7 @@ static void usage(u8 *argv0) {
" the target was compiled for\n"
"AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n"
"AFL_TMIN_EXACT: require execution paths to match for crashing inputs\n"
"AFL_FORKSRV_INIT_TMOUT: time spent waiting for forkserver during startup (in milliseconds)\n"
, argv0, EXEC_TIMEOUT, MEM_LIMIT, doc_path);
@ -1104,6 +1105,19 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF("\n");
if (getenv("AFL_FORKSRV_INIT_TMOUT")) {
s32 forksrv_init_tmout = atoi(getenv("AFL_FORKSRV_INIT_TMOUT"));
if (forksrv_init_tmout < 1) {
FATAL("Bad value specified for AFL_FORKSRV_INIT_TMOUT");
}
fsrv->init_tmout = (u32)forksrv_init_tmout;
}
shm_fuzz = ck_alloc(sizeof(sharedmem_t));
/* initialize cmplog_mode */

View File

@ -70,6 +70,11 @@ MAKECMD=make
TARCMD=tar
if [ "$PLT" = "Linux" ]; then
MUSL=`ldd --version 2>&1 | head -n 1 | cut -f 1 -d " "`
if [ "musl" = $MUSL ]; then
echo "[-] Error: Unicorn instrumentation is unsupported with the musl's libc."
exit 1
fi
CORES=`nproc`
fi