push to stable (#1734)

* afl++ -> AFL++

* update readme

* more debug

* slightly different weighting algo (#1719)

* better seed selection

* slightly different weighting calculation

* remove unnecessary memset

* Add "Hangs saved" to afl-whatsup (#1717)

The hangs could show long or infinite loops. This is important.

Co-authored-by: van Hauser <vh@thc.org>

* nits

* afl-showmap: Start a only a single fork server (#1718)

A forkserver is started by afl_fsrv_get_mapsize() when dynamically
finding the map size.  When an input directory option is specified a
second fork server was also started.  This commit re-arranges the inits
for several forkserver struct members so that we can re-use the server
started by the get_mapsize() call when not in coresight/qemu/unicorn
modes and just start the server otherwise.

* Source Code Coverage support for Nyx (Part 1) (#1720)

* Additional source code reformatting in afl-compiler-rt

* Add source code coverage support to afl-compiler-rt (for use with Nyx)

* doc, code format

* llvm 17 changes

* more llvm 17

* add frida mode tutorial

* fix effector map

* docs

* Should memset EFF_ALEN(len) of eff_map (#1722)

* fix reallocs

* fix afl-system-config for macos

* afl-fuzz.c: Document -i - in --help (#1725)

afl-fuzz.c: Document `-i -` in `--help`, to write that `-i` can be passed '-' to resume the prior fuzzing job. Also reference AFL_AUTORESUME so users know they can set that parameter to sidestep the issue entirely.

* tritondse custom mutator attempt

* tritondse fixes

* update libnyx (#1727)

* GNUmakefile: Update LLVM instructions (#1728)

Update LLVM instructions, because versions higher than 14 are supported and to be explicit that LLD is also required

* disable macos in the ci, works fine for me

* fix makefile

* better tritondse support

* next steps for tritondse

* qemuafl: Persistent mode for PPC32 targets

* update qemu_mode

* afl-clang-lto incomptable with -flto=thin

* add @responsefile support for afl-cc

---------

Co-authored-by: fxlb <devel.fx.lebail@orange.fr>
Co-authored-by: Nick Potenski <nick.potenski@garmin.com>
Co-authored-by: Christian Holler (:decoder) <choller@mozilla.com>
Co-authored-by: lazymio <mio@lazym.io>
Co-authored-by: Moshe Kaplan <me@moshekaplan.com>
Co-authored-by: Sergej Schumilo <sergej@schumilo.de>
Co-authored-by: Dominik Maier <domenukk@gmail.com>
This commit is contained in:
van Hauser 2023-05-15 11:51:37 +03:00 committed by GitHub
parent 74be9ab5ce
commit c4b1566ba3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
45 changed files with 1165 additions and 331 deletions

View File

@ -36,23 +36,23 @@ jobs:
run: make distrib ASAN_BUILD=1 NO_NYX=1
- name: run tests
run: sudo -E ./afl-system-config; make tests
macos:
runs-on: macOS-latest
env:
AFL_MAP_SIZE: 65536
AFL_SKIP_CPUFREQ: 1
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
steps:
- uses: actions/checkout@v3
- name: install
run: brew install make gcc llvm
- name: fix install
run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
- name: build
run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1
- name: frida
run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
- name: run tests
run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
- name: force frida test for MacOS
run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
# macos:
# runs-on: macOS-latest
# env:
# AFL_MAP_SIZE: 65536
# AFL_SKIP_CPUFREQ: 1
# AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
# steps:
# - uses: actions/checkout@v3
# - name: install
# run: brew install make gcc llvm
# - name: fix install
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
# - name: build
# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1
# - name: frida
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
# - name: run tests
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
# - name: force frida test for MacOS
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr

View File

@ -6,7 +6,7 @@
#
FROM ubuntu:22.04 AS aflplusplus
LABEL "maintainer"="afl++ team <afl@aflplus.plus>"
LABEL "maintainer"="AFL++ team <afl@aflplus.plus>"
LABEL "about"="AFLplusplus container image"
### Comment out to enable these features
@ -94,4 +94,4 @@ RUN sed -i.bak 's/^ -/ /g' GNUmakefile && \
RUN echo "set encoding=utf-8" > /root/.vimrc && \
echo ". /etc/bash_completion" >> ~/.bashrc && \
echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc && \
echo "export PS1='"'[afl++ \h] \w \$ '"'" >> ~/.bashrc
echo "export PS1='"'[AFL++ \h] \w \$ '"'" >> ~/.bashrc

View File

@ -39,7 +39,7 @@ ASAN_OPTIONS=detect_leaks=0
SYS = $(shell uname -s)
ARCH = $(shell uname -m)
$(info [*] Compiling afl++ for OS $(SYS) on ARCH $(ARCH))
$(info [*] Compiling AFL++ for OS $(SYS) on ARCH $(ARCH))
ifdef NO_SPLICING
override CFLAGS_OPT += -DNO_SPLICING
@ -316,7 +316,7 @@ all: test_x86 test_shm test_python ready $(PROGS) afl-as llvm gcc_plugin test_bu
@test -e afl-fuzz && echo "[+] afl-fuzz and supporting tools successfully built" || echo "[-] afl-fuzz could not be built, please set CC to a working compiler"
@test -e afl-llvm-pass.so && echo "[+] LLVM basic mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 or newer, see docs/INSTALL.md"
@test -e SanitizerCoveragePCGUARD.so && echo "[+] LLVM mode successfully built" || echo "[-] LLVM mode could not be built, please install at least llvm-11 and clang-11 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"
@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 and LLD 11+. 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"
endif
@ -359,7 +359,7 @@ performance-test: source-only
help:
@echo "HELP --- the following make targets exist:"
@echo "=========================================="
@echo "all: the main afl++ binaries and llvm/gcc instrumentation"
@echo "all: the main AFL++ binaries and llvm/gcc instrumentation"
@echo "binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode, qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator, libtokencap"
@echo "source-only: everything for source code fuzzing: nyx_mode, libdislocator, libtokencap"
@echo "distrib: everything (for both binary-only and source code fuzzing)"
@ -367,7 +367,7 @@ help:
@echo "install: installs everything you have compiled with the build option above"
@echo "clean: cleans everything compiled (not downloads when on a checkout)"
@echo "deepclean: cleans everything including downloads"
@echo "uninstall: uninstall afl++ from the system"
@echo "uninstall: uninstall AFL++ from the system"
@echo "code-format: format the code, do this before you commit and send a PR please!"
@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
@echo "unit: perform unit tests (based on cmocka and GNU linker)"
@ -379,6 +379,7 @@ help:
@echo Known build environment options:
@echo "=========================================="
@echo STATIC - compile AFL++ static
@echo "CODE_COVERAGE - compile the target for code coverage (see docs/instrumentation/README.llvm.md)"
@echo ASAN_BUILD - compiles AFL++ with memory sanitizer for debug purposes
@echo UBSAN_BUILD - compiles AFL++ tools with undefined behaviour sanitizer for debug purposes
@echo DEBUG - no optimization, -ggdb3, all warnings and -Werror
@ -394,7 +395,7 @@ help:
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
@echo "LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config (e.g., Debian)"
@echo "=========================================="
@echo e.g.: make ASAN_BUILD=1
@echo e.g.: make LLVM_CONFIG=llvm-config-16
.PHONY: test_x86
ifndef AFL_NO_X86
@ -749,7 +750,7 @@ endif
@echo
%.8: %
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
@echo .TH $* 8 $(BUILD_DATE) "AFL++" > $@
@echo .SH NAME >> $@
@echo .B $* >> $@
@echo >> $@
@ -761,8 +762,8 @@ endif
@./$* -hh 2>&1 | tail -n +4 >> $@
@echo >> $@
@echo .SH AUTHOR >> $@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> $@
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> $@
@echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Dominik Maier <domenukk@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com> and Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>" >> $@
@echo The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> $@
@echo >> $@
@echo .SH LICENSE >> $@
@echo Apache License Version 2.0, January 2004 >> $@

View File

@ -175,7 +175,7 @@ all_done: test_build
.NOTPARALLEL: clean
%.8: %
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ./$@
@echo .TH $* 8 `date "+%Y-%m-%d"` "AFL++" > ./$@
@echo .SH NAME >> ./$@
@echo .B $* >> ./$@
@echo >> ./$@
@ -187,8 +187,8 @@ all_done: test_build
@./$* -h 2>&1 | tail -n +4 >> ./$@
@echo >> ./$@
@echo .SH AUTHOR >> ./$@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ./$@
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
@echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Dominik Maier <domenukk@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com> and Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>" >> ./$@
@echo The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
@echo >> ./$@
@echo .SH LICENSE >> ./$@
@echo Apache License Version 2.0, January 2004 >> ./$@

View File

@ -274,6 +274,11 @@ ifndef LLVM_DEBUG
CFLAGS_SAFE += -Wno-deprecated
endif
ifdef CODE_COVERAGE
override CFLAGS_SAFE += -D__AFL_CODE_COVERAGE=1
override LDFLAGS += -ldl
endif
override CFLAGS += $(CFLAGS_SAFE)
ifdef AFL_TRACE_PC
@ -510,7 +515,7 @@ install: all
install -m 644 instrumentation/README.*.md $${DESTDIR}$(DOC_PATH)/
%.8: %
@echo .TH $* 8 $(BUILD_DATE) "afl++" > ./$@
@echo .TH $* 8 $(BUILD_DATE) "AFL++" > ./$@
@echo .SH NAME >> ./$@
@printf "%s" ".B $* \- " >> ./$@
@./$* -h 2>&1 | head -n 1 | sed -e "s/$$(printf '\e')[^m]*m//g" >> ./$@
@ -524,8 +529,8 @@ install: all
@./$* -h 2>&1 | tail -n +4 >> ./$@
@echo >> ./$@
@echo .SH AUTHOR >> ./$@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>, Andrea Fioraldi <andreafioraldi@gmail.com> and Dominik Maier <domenukk@gmail.com>" >> ./$@
@echo The homepage of afl++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
@echo "AFL++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Dominik Maier <domenukk@gmail.com>, Andrea Fioraldi <andreafioraldi@gmail.com> and Heiko \"hexcoder-\" Eissfeldt <heiko.eissfeldt@hexco.de>" >> ./$@
@echo The homepage of AFL++ is: https://github.com/AFLplusplus/AFLplusplus >> ./$@
@echo >> ./$@
@echo .SH LICENSE >> ./$@
@echo Apache License Version 2.0, January 2004 >> ./$@

View File

@ -12,9 +12,9 @@ Repository:
AFL++ is maintained by:
* Marc "van Hauser" Heuse <mh@mh-sec.de>
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>
* Andrea Fioraldi <andreafioraldi@gmail.com>
* Dominik Maier <mail@dmnk.co>
* Heiko "hexcoder-" Eißfeldt <heiko.eissfeldt@hexco.de>
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
Originally developed by Michał "lcamtuf" Zalewski.

View File

@ -149,7 +149,7 @@ BEGIN {
redirected = 0
}
print "corpus minimization tool for afl++ (awk version)\n"
print "corpus minimization tool for AFL++ (awk version)\n"
# defaults
extra_par = ""

View File

@ -110,7 +110,7 @@ if [ "$PLATFORM" = "Darwin" ] ; then
sysctl kern.sysv.shmall=131072000
echo Settings applied.
echo
if [ $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') ] ; then
if $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') ; then
echo
echo Unloading the default crash reporter
SL=/System/Library; PL=com.apple.ReportCrash
@ -119,6 +119,7 @@ if [ "$PLATFORM" = "Darwin" ] ; then
echo
fi
echo It is recommended to disable System Integrity Protection for increased performance.
echo See: https://developer.apple.com/documentation/security/disabling_and_enabling_system_integrity_protection
echo
DONE=1
fi

View File

@ -88,6 +88,7 @@ TOTAL_TIME=0
TOTAL_EXECS=0
TOTAL_EPS=0
TOTAL_CRASHES=0
TOTAL_HANGS=0
TOTAL_PFAV=0
TOTAL_PENDING=0
@ -190,6 +191,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
TOTAL_EPS=$((TOTAL_EPS + EXEC_SEC))
TOTAL_EXECS=$((TOTAL_EXECS + execs_done))
TOTAL_CRASHES=$((TOTAL_CRASHES + saved_crashes))
TOTAL_HANGS=$((TOTAL_HANGS + saved_hangs))
TOTAL_PENDING=$((TOTAL_PENDING + pending_total))
TOTAL_PFAV=$((TOTAL_PFAV + pending_favs))
@ -301,6 +303,7 @@ if [ "$ALIVE_CNT" -gt "1" ]; then
fi
echo " Crashes saved : $TOTAL_CRASHES"
echo " Hangs saved : $TOTAL_HANGS"
echo "Cycles without finds : $TOTAL_WCOP"
echo " Time without finds : $TOTAL_LAST_FIND"
echo

View File

@ -0,0 +1,17 @@
# An AFL++ custom mutator using TritonDSE
## Installing the requirements
`pip3 install tritondse`
## How to run with an example
```
../../afl-cc -o ../../test-instr ../../test-instr.c
mkdir -p in
echo aaaa > in/in
TRITON_DSE_TARGET=../../test-instr AFL_CUSTOM_MUTATOR_ONLY=1 AFL_SYNC_TIME=1 AFL_PYTHON_MODULE=aflpp_tritondse PYTHONPATH=. ../../afl-fuzz -i in -o out -- ../../test-instr
```
Note that this custom mutator works differently, new finds are synced
after 10-60 seconds to the fuzzing instance.

View File

@ -0,0 +1,148 @@
import sys
import os
import logging
import hashlib
from tritondse import CleLoader
from tritondse import CompositeData
from tritondse import Config
from tritondse import CoverageStrategy
from tritondse import ProcessState
from tritondse import Program
from tritondse import Seed
from tritondse import SeedFormat
from tritondse import SymbolicExecutor
from tritondse import SymbolicExplorator
is_debug = False
out_path = ""
input_file = None
prog = None
config = None
dse = None
cycle = 0
count = 0
hashes = set()
format = SeedFormat.RAW
def pre_exec_hook(se: SymbolicExecutor, state: ProcessState):
global count
global hashes
if se.seed.hash not in hashes:
hashes.add(se.seed.hash)
filename = out_path + "/id:" + f"{count:06}" + "," + se.seed.hash
if not os.path.exists(filename):
if is_debug:
print('Creating queue input ' + filename)
with open(filename, 'wb') as file:
if input_file:
file.write(se.seed.content.files[input_file])
else:
file.write(se.seed.content)
count += 1
#if input_file:
# if is_debug:
# print('Writing to ' + input_file + ' the content: ' + str(se.seed.content))
# with open(input_file, 'wb') as file:
# file.write(se.seed.content)
def init(seed):
global config
global dse
global format
global input_file
global is_debug
global out_path
global prog
# Load the program (LIEF-based program loader).
prog = CleLoader(os.environ['AFL_CUSTOM_INFO_PROGRAM'])
# Process other configuration environment variables.
argv = None
try:
foo = os.environ['AFL_DEBUG']
is_debug = True
except KeyError:
pass
try:
foo = os.environ['AFL_CUSTOM_INFO_OUT']
out_path = foo + '/../tritondse/queue'
except KeyError:
pass
try:
foo = os.environ['AFL_CUSTOM_INFO_PROGRAM_INPUT']
input_file = foo
except KeyError:
pass
try:
argv_list = os.environ['AFL_CUSTOM_INFO_PROGRAM_ARGV']
argv_tmp = [ os.environ['AFL_CUSTOM_INFO_PROGRAM'] ]
argv_tmp += argv_list.split()
argv = []
# now check for @@
for item in argv_tmp:
if "@@" in item:
input_file = out_path + '/../.input'
argv.append(input_file)
else:
argv.append(item)
except KeyError:
pass
# Create the output directory
os.makedirs(out_path, exist_ok=True)
# Debug
if is_debug:
print('DEBUG target: ' + os.environ['AFL_CUSTOM_INFO_PROGRAM'])
if argv:
print('DEBUG argv: ')
print(argv)
if input_file:
print('DEBUG input_file: ' + input_file)
print('DEBUG out_path: ' + out_path)
print('')
if input_file:
format = SeedFormat.COMPOSITE
# Now set up TritonDSE
config = Config(coverage_strategy = CoverageStrategy.PATH,
debug = is_debug,
pipe_stdout = is_debug,
pipe_stderr = is_debug,
execution_timeout = 1,
program_argv = argv,
smt_timeout= 50,
seed_format = format)
# Create an instance of the Symbolic Explorator
dse = SymbolicExplorator(config, prog)
# Add callbacks.
dse.callback_manager.register_pre_execution_callback(pre_exec_hook)
#def fuzz(buf, add_buf, max_size):
# return b""
def queue_new_entry(filename_new_queue, filename_orig_queue):
global cycle
global dse
# Add seed to the worklist.
with open(filename_new_queue, "rb") as file:
data = file.read()
hash = hashlib.md5(data).hexdigest()
if hash not in hashes:
hashes.add(hash)
if is_debug:
print("NEW FILE " + filename_new_queue + " hash " + hash + " count " + str(cycle))
cycle += 1
if input_file:
seed = Seed(CompositeData(files={"stdin": b"", # nothing on stdin
input_file: data}))
else:
seed = Seed(data)
dse.add_input_seed(seed)
# Start exploration!
#dse.step()
dse.explore()
pass
def splice_optout():
pass

View File

@ -11,13 +11,17 @@
- new env `AFL_IGNORE_PROBLEMS_COVERAGE` to ignore coverage from
loaded libs after forkserver initialization (required by Mozilla)
- afl-cc:
- added @responsefile support
- new env `AFL_LLVM_LTO_SKIPINIT` to support the AFL++ based WASM
(https://github.com/fgsect/WAFL) project
- error and print help if afl-clan-lto is used with lto=thin
- afl-showmap:
- added custom mutator post_process and send support
- add `-I filelist` option, an alternative to `-i in_dir`
- afl-cmin + afl-cmin.bash:
- `-T threads` parallel task support, can be a huge speedup!
- qemu_mode:
- Persistent mode +QASAN support for ppc32 tragets by @worksbutnottested
- a new grammar custom mutator atnwalk was submitted by @voidptr127 !
@ -229,7 +233,7 @@
afl-showmap and other tools.
- afl-cc:
- detect overflow reads on initial input buffer for asan
- new cmplog mode (incompatible with older afl++ versions)
- new cmplog mode (incompatible with older AFL++ versions)
- support llvm IR select instrumentation for default PCGUARD and LTO
- fix for shared linking on MacOS
- better selective instrumentation AFL_LLVM_{ALLOW|DENY}LIST

View File

@ -171,6 +171,14 @@ If you find an interesting or important question missing, submit it via
The more "unstable" edges there are, the harder it is for AFL++ to identify
valid new paths.
If you fuzz in persistent mode (`AFL_LOOP` or `LLVMFuzzerTestOneInput()`
harnesses, a large number of unstable edges can mean that the target keeps
internal state and therefore it is possible that crashes cannot be replayed.
In such a case do either **not** fuzz in persistent mode (remove `AFL_LOOP()`
from your harness or call `LLVMFuzzerTestOneInput()` harnesses with `@@`),
or set a low `AFL_LOOP` value, e.g. 100, and enable `AFL_PERSISTENT_RECORD`
in `config.h` with the same value.
A value above 90% is usually fine and a value above 80% is also still ok, and
even a value above 20% can still result in successful finds of bugs. However,
it is recommended that for values below 90% or 80% you should take

View File

@ -51,7 +51,7 @@ make source-only
These build targets exist:
* all: the main afl++ binaries and llvm/gcc instrumentation
* all: the main AFL++ binaries and llvm/gcc instrumentation
* binary-only: everything for binary-only fuzzing: frida_mode, nyx_mode,
qemu_mode, frida_mode, unicorn_mode, coresight_mode, libdislocator,
libtokencap
@ -79,22 +79,20 @@ make STATIC=1
These build options exist:
* 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
* UBSAN_BUILD - compiles AFL++ tools with undefined behaviour 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
* PROFILING - compile afl-fuzz with profiling information
* INTROSPECTION - compile afl-fuzz with mutation introspection
* NO_PYTHON - disable python support
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for
normal fuzzing
* NO_SPLICING - disables splicing mutation in afl-fuzz, not recommended for normal fuzzing
* 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
* LLVM_CONFIG - if your distro doesn't use the standard name for llvm-config
(e.g., Debian)
* 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`

View File

@ -131,6 +131,11 @@ jitter, or is a hash map function etc., then it should not be instrumented.
To be able to exclude these functions (based on AFL++'s measured stability), the
following process will allow to identify functions with variable edges.
Note that this is only useful for non-persistent targets!
If a persistent target is unstable whereas when run non-persistent is fine,
then this means that the target is keeping internal state, which is bad for
fuzzing. Fuzz such targets **without** persistent mode.
Four steps are required to do this and it also requires quite some knowledge of
coding and/or disassembly and is effectively possible only with `afl-clang-fast`
`PCGUARD` and `afl-clang-lto` `LTO` instrumentation.

View File

@ -304,6 +304,34 @@ Note: for some distributions, you might also need the package `python[3]-apt`.
In case your setup is different, set the necessary variables like this:
`PYTHON_INCLUDE=/path/to/python/include LDFLAGS=-L/path/to/python/lib make`.
### Helpers
For C/C++ custom mutators you get a pointer to `afl_state_t *afl` in the
`afl_custom_init()` which contains all information that you need.
Note that if you access it, you need to recompile your custom mutator if
you update AFL++ because the structure might have changed!
For mutators written in Python, Rust, GO, etc. there are a few environment
variables set to help you to get started:
`AFL_CUSTOM_INFO_PROGRAM` - the program name of the target that is executed.
If your custom mutator is used with modes like Qemu (`-Q`), this will still
contain the target program, not afl-qemu-trace.
`AFL_CUSTOM_INFO_PROGRAM_INPUT` - if the `-f` parameter is used with afl-fuzz
then this value is found in this environment variable.
`AFL_CUSTOM_INFO_PROGRAM_ARGV` - this contains the parameters given to the
target program and still has the `@@` identifier in there.
Note: If `AFL_CUSTOM_INFO_PROGRAM_INPUT` is empty and `AFL_CUSTOM_INFO_PROGRAM_ARGV`
is either empty or does not contain `@@` then the target gets the input via
`stdin`.
`AFL_CUSTOM_INFO_OUT` - This is the output directory for this fuzzer instance,
so if `afl-fuzz` was called with `-o out -S foobar`, then this will be set to
`out/foobar`.
### Custom Mutator Preparation
For C/C++ mutators, the source code must be compiled as a shared object:

View File

@ -20,6 +20,10 @@ training, then we can highly recommend the following:
* [https://github.com/antonio-morales/Fuzzing101](https://github.com/antonio-morales/Fuzzing101)
Here is good workflow description for frida_mode:
* [https://blog.quarkslab.com/android-greybox-fuzzing-with-afl-frida-mode.html](https://blog.quarkslab.com/android-greybox-fuzzing-with-afl-frida-mode.html)
If you are interested in fuzzing structured data (where you define what the
structure is), these links have you covered (some are outdated though):

View File

@ -7,6 +7,8 @@ variables.
In FRIDA mode, binary programs are instrumented, similarly to QEMU mode.
A tutorial can be found at [https://blog.quarkslab.com/android-greybox-fuzzing-with-afl-frida-mode.html](https://blog.quarkslab.com/android-greybox-fuzzing-with-afl-frida-mode.html)
## Current progress
As FRIDA mode is new, it is missing a lot of features. The design is such that

View File

@ -1223,7 +1223,7 @@ double rand_next_percent(afl_state_t *afl);
static inline u32 rand_below(afl_state_t *afl, u32 limit) {
if (limit <= 1) return 0;
if (unlikely(limit <= 1)) return 0;
/* The boundary not being necessarily a power of 2,
we need to ensure the result uniformity. */
@ -1256,7 +1256,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
expand havoc mode */
static inline u32 rand_below_datalen(afl_state_t *afl, u32 limit) {
if (limit <= 1) return 0;
if (unlikely(limit <= 1)) return 0;
switch (rand_below(afl, 3)) {

View File

@ -42,7 +42,7 @@
// Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators
#ifndef _WANT_ORIGINAL_AFL_ALLOC
// afl++ stuff without memory corruption checks - for speed
// AFL++ stuff without memory corruption checks - for speed
/* User-facing macro to sprintf() to a dynamically allocated buffer. */
@ -704,12 +704,11 @@ static inline void *afl_realloc(void **buf, size_t size_needed) {
*buf = NULL;
return NULL;
} else {
new_buf = newer_buf;
}
new_buf = newer_buf;
memset(((u8 *)new_buf) + current_size, 0, next_size - current_size);
new_buf->complete_size = next_size;
*buf = (void *)(new_buf->buf);
return *buf;

View File

@ -37,6 +37,10 @@ static char *afl_environment_variables[] = {
"AFL_CRASH_EXITCODE",
"AFL_CUSTOM_MUTATOR_LIBRARY",
"AFL_CUSTOM_MUTATOR_ONLY",
"AFL_CUSTOM_INFO_PROGRAM",
"AFL_CUSTOM_INFO_PROGRAM_ARGV",
"AFL_CUSTOM_INFO_PROGRAM_INPUT",
"AFL_CUSTOM_INFO_OUT",
"AFL_CXX",
"AFL_CYCLE_SCHEDULES",
"AFL_DEBUG",

View File

@ -280,3 +280,27 @@ Please note that the default counter implementations are not thread safe!
Support for thread safe counters in mode LLVM CLASSIC can be activated with
setting `AFL_LLVM_THREADSAFE_INST=1`.
## 8) Source code coverage through instrumentation
Measuring source code coverage is a common task in fuzzing, but it is very
difficut to do in some situations (e.g. when using snapshot fuzzing).
When using the `AFL_LLVM_INSTRUMENT=llvm-codecov` option, afl-cc will use
native trace-pc-guard instrumentation but additionally select options that
are required to utilize the instrumentation for source code coverage.
In particular, it will switch the instrumentation to be per basic block
instead of instrumenting edges, disable all guard pruning and enable the
experimental pc-table support that allows the runtime to gather 100% of
instrumented basic blocks at start, including their locations.
Note: You must compile AFL with the `CODE_COVERAGE=1` option to enable the
respective parts in the AFL compiler runtime. Support is currently only
implemented for Nyx, but can in theory also work without Nyx.
Note: You might have to adjust `MAP_SIZE_POW2` in include/config.h to ensure
that your coverage map is large enough to hold all basic blocks of your
target program without any collisions.
More documentation on how to utilize this with Nyx will follow.

View File

@ -1,4 +1,4 @@
/* SanitizeCoverage.cpp ported to afl++ LTO :-) */
/* SanitizeCoverage.cpp ported to AFL++ LTO :-) */
#define AFL_LLVM_PASS
@ -20,6 +20,8 @@
#if LLVM_VERSION_MAJOR < 17
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/EHPersonalities.h"
#else
#include "llvm/IR/EHPersonalities.h"
#endif
#include "llvm/Analysis/PostDominators.h"
#include "llvm/Analysis/ValueTracking.h"
@ -236,7 +238,7 @@ class ModuleSanitizerCoverageLTO
SanitizerCoverageOptions Options;
// afl++ START
// AFL++ START
// const SpecialCaseList * Allowlist;
// const SpecialCaseList * Blocklist;
uint32_t autodictionary = 1;
@ -262,7 +264,7 @@ class ModuleSanitizerCoverageLTO
Value *MapPtrFixed = NULL;
std::ofstream dFile;
size_t found = 0;
// afl++ END
// AFL++ END
};
@ -406,7 +408,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
Int8Ty = IRB.getInt8Ty();
Int1Ty = IRB.getInt1Ty();
/* afl++ START */
/* AFL++ START */
char *ptr;
LLVMContext &Ctx = M.getContext();
Ct = &Ctx;
@ -980,7 +982,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
// afl++ END
// AFL++ END
SanCovTracePCIndir =
M.getOrInsertFunction(SanCovTracePCIndirName, VoidTy, IntptrTy);
@ -1004,7 +1006,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
for (auto &F : M)
instrumentFunction(F, DTCallback, PDTCallback);
// afl++ START
// AFL++ START
if (dFile.is_open()) dFile.close();
if (!getenv("AFL_LLVM_LTO_SKIPINIT") &&
@ -1158,7 +1160,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
}
// afl++ END
// AFL++ END
// We don't reference these arrays directly in any of our runtime functions,
// so we need to prevent them from being dead stripped.
@ -1215,10 +1217,10 @@ static bool shouldInstrumentBlock(const Function &F, const BasicBlock *BB,
// (catchswitch blocks).
if (BB->getFirstInsertionPt() == BB->end()) return false;
// afl++ START
// AFL++ START
if (!Options.NoPrune && &F.getEntryBlock() == BB && F.size() > 1)
return false;
// afl++ END
// AFL++ END
if (Options.NoPrune || &F.getEntryBlock() == BB) return true;
@ -1260,10 +1262,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
// if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
// return;
// afl++ START
// AFL++ START
if (!F.size()) return;
if (!isInInstrumentList(&F, FMNAME)) return;
// afl++ END
// AFL++ END
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
SplitAllCriticalEdges(
@ -1561,7 +1563,7 @@ bool ModuleSanitizerCoverageLTO::InjectCoverage(
for (size_t i = 0, N = AllBlocks.size(); i < N; i++) {
// afl++ START
// AFL++ START
if (BlockList.size()) {
int skip = 0;
@ -1583,7 +1585,7 @@ bool ModuleSanitizerCoverageLTO::InjectCoverage(
}
// afl++ END
// AFL++ END
InjectCoverageAtBlock(F, *AllBlocks[i], i, IsLeafFunc);
@ -1649,7 +1651,7 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
if (Options.TracePCGuard) {
// afl++ START
// AFL++ START
++afl_global_id;
if (dFile.is_open()) {
@ -1713,7 +1715,7 @@ void ModuleSanitizerCoverageLTO::InjectCoverageAtBlock(Function &F,
// done :)
inst++;
// afl++ END
// AFL++ END
/*
XXXXXXXXXXXXXXXXXXX

View File

@ -16,6 +16,8 @@
#if LLVM_VERSION_MAJOR < 17
#include "llvm/ADT/Triple.h"
#include "llvm/Analysis/EHPersonalities.h"
#else
#include "llvm/IR/EHPersonalities.h"
#endif
#include "llvm/Analysis/PostDominators.h"
#include "llvm/IR/CFG.h"

View File

@ -14,6 +14,16 @@
*/
#ifdef __AFL_CODE_COVERAGE
#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#ifndef __USE_GNU
#define __USE_GNU
#endif
#include <dlfcn.h>
#endif
#ifdef __ANDROID__
#include "android-ashmem.h"
#endif
@ -105,6 +115,44 @@ u32 __afl_dictionary_len;
u64 __afl_map_addr;
u32 __afl_first_final_loc;
#ifdef __AFL_CODE_COVERAGE
typedef struct afl_module_info_t afl_module_info_t;
struct afl_module_info_t {
// A unique id starting with 0
u32 id;
// Name and base address of the module
char *name;
uintptr_t base_address;
// PC Guard start/stop
u32 start;
u32 stop;
// PC Table begin/end
const uintptr_t *pcs_beg;
const uintptr_t *pcs_end;
u8 mapped;
afl_module_info_t *next;
};
typedef struct {
uintptr_t PC, PCFlags;
} PCTableEntry;
afl_module_info_t *__afl_module_info = NULL;
u32 __afl_pcmap_size = 0;
uintptr_t *__afl_pcmap_ptr = NULL;
#endif // __AFL_CODE_COVERAGE
/* 1 if we are running in afl, and the forkserver was started, else 0 */
u32 __afl_connected = 0;
@ -499,6 +547,7 @@ static void __afl_map_shm(void) {
u8 *map_env = (u8 *)getenv("AFL_MAP_SIZE");
if (!map_env || atoi((char *)map_env) < MAP_SIZE) {
fprintf(stderr, "FS_ERROR_MAP_SIZE\n");
send_forkserver_error(FS_ERROR_MAP_SIZE);
_exit(1);
@ -678,6 +727,27 @@ static void __afl_map_shm(void) {
}
#ifdef __AFL_CODE_COVERAGE
char *pcmap_id_str = getenv("__AFL_PCMAP_SHM_ID");
if (pcmap_id_str) {
__afl_pcmap_size = __afl_map_size * sizeof(void *);
u32 shm_id = atoi(pcmap_id_str);
__afl_pcmap_ptr = (uintptr_t *)shmat(shm_id, NULL, 0);
if (__afl_debug) {
fprintf(stderr, "DEBUG: Received %p via shmat for pcmap\n",
__afl_pcmap_ptr);
}
}
#endif // __AFL_CODE_COVERAGE
}
/* unmap SHM. */
@ -686,6 +756,17 @@ static void __afl_unmap_shm(void) {
if (!__afl_already_initialized_shm) return;
#ifdef __AFL_CODE_COVERAGE
if (__afl_pcmap_size) {
shmdt((void *)__afl_pcmap_ptr);
__afl_pcmap_ptr = NULL;
__afl_pcmap_size = 0;
}
#endif // __AFL_CODE_COVERAGE
char *id_str = getenv(SHM_ENV_VAR);
if (id_str) {
@ -1507,6 +1588,102 @@ void __sanitizer_cov_trace_pc_guard(uint32_t *guard) {
}
#ifdef __AFL_CODE_COVERAGE
void __sanitizer_cov_pcs_init(const uintptr_t *pcs_beg,
const uintptr_t *pcs_end) {
if (__afl_debug) {
fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init called\n");
}
// If for whatever reason, we cannot get dlinfo here, then pc_guard_init also
// couldn't get it and we'd end up attributing to the wrong module.
Dl_info dlinfo;
if (!dladdr(__builtin_return_address(0), &dlinfo)) {
fprintf(stderr,
"WARNING: Ignoring __sanitizer_cov_pcs_init callback due to "
"missing module info\n");
return;
}
afl_module_info_t *last_module_info = __afl_module_info;
while (last_module_info && last_module_info->next) {
last_module_info = last_module_info->next;
}
if (!last_module_info) {
fprintf(stderr,
"ERROR: __sanitizer_cov_pcs_init called with no module info?!\n");
abort();
}
last_module_info->pcs_beg = pcs_beg;
last_module_info->pcs_end = pcs_end;
// Now update the pcmap. If this is the last module coming in, after all
// pre-loaded code, then this will also map all of our delayed previous
// modules.
if (!__afl_pcmap_ptr) { return; }
for (afl_module_info_t *mod_info = __afl_module_info; mod_info;
mod_info = mod_info->next) {
if (mod_info->mapped) { continue; }
PCTableEntry *start = (PCTableEntry *)(mod_info->pcs_beg);
PCTableEntry *end = (PCTableEntry *)(mod_info->pcs_end);
u32 in_module_index = 0;
while (start < end) {
if (mod_info->start + in_module_index >= __afl_map_size) {
fprintf(stderr, "ERROR: __sanitizer_cov_pcs_init out of bounds?!\n");
abort();
}
uintptr_t PC = start->PC;
// This is what `GetPreviousInstructionPc` in sanitizer runtime does
// for x86/x86-64. Needs more work for ARM and other archs.
PC = PC - 1;
// Calculate relative offset in module
PC = PC - mod_info->base_address;
__afl_pcmap_ptr[mod_info->start + in_module_index] = PC;
start++;
in_module_index++;
}
mod_info->mapped = 1;
if (__afl_debug) {
fprintf(stderr, "DEBUG: __sanitizer_cov_pcs_init initialized %u PCs\n",
in_module_index);
}
}
}
#endif // __AFL_CODE_COVERAGE
/* Init callback. Populates instrumentation IDs. Note that we're using
ID of 0 as a special value to indicate non-instrumented bits. That may
still touch the bitmap, but in a fairly harmless way. */
@ -1538,6 +1715,62 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
if (start == stop || *start) { return; }
#ifdef __AFL_CODE_COVERAGE
u32 *orig_start = start;
afl_module_info_t *mod_info = NULL;
Dl_info dlinfo;
if (dladdr(__builtin_return_address(0), &dlinfo)) {
if (__afl_already_initialized_forkserver) {
fprintf(stderr, "[pcmap] Error: Module was not preloaded: %s\n",
dlinfo.dli_fname);
} else {
afl_module_info_t *last_module_info = __afl_module_info;
while (last_module_info && last_module_info->next) {
last_module_info = last_module_info->next;
}
mod_info = malloc(sizeof(afl_module_info_t));
mod_info->id = last_module_info ? last_module_info->id + 1 : 0;
mod_info->name = strdup(dlinfo.dli_fname);
mod_info->base_address = (uintptr_t)dlinfo.dli_fbase;
mod_info->start = 0;
mod_info->stop = 0;
mod_info->pcs_beg = NULL;
mod_info->pcs_end = NULL;
mod_info->mapped = 0;
mod_info->next = NULL;
if (last_module_info) {
last_module_info->next = mod_info;
} else {
__afl_module_info = mod_info;
}
fprintf(stderr, "[pcmap] Module: %s Base Address: %p\n", dlinfo.dli_fname,
dlinfo.dli_fbase);
}
} else {
fprintf(stderr, "[pcmap] dladdr call failed\n");
}
#endif // __AFL_CODE_COVERAGE
x = getenv("AFL_INST_RATIO");
if (x) {
@ -1625,6 +1858,22 @@ void __sanitizer_cov_trace_pc_guard_init(uint32_t *start, uint32_t *stop) {
}
#ifdef __AFL_CODE_COVERAGE
if (mod_info) {
mod_info->start = *orig_start;
mod_info->stop = *(stop - 1);
if (__afl_debug) {
fprintf(stderr, "DEBUG: [pcmap] Start Index: %u Stop Index: %u\n",
mod_info->start, mod_info->stop);
}
}
#endif // __AFL_CODE_COVERAGE
if (__afl_debug) {
fprintf(stderr,

View File

@ -584,7 +584,7 @@ bool isInInstrumentList(llvm::Function *F, std::string Filename) {
}
// Calculate the number of average collisions that would occur if all
// location IDs would be assigned randomly (like normal afl/afl++).
// location IDs would be assigned randomly (like normal afl/AFL++).
// This uses the "balls in bins" algorithm.
unsigned long long int calculateCollisions(uint32_t edges) {

View File

@ -746,7 +746,7 @@ static void registerAFLdict2filePass(const PassManagerBuilder &,
}
static RegisterPass<AFLdict2filePass> X("afl-dict2file",
"afl++ dict2file instrumentation pass",
"AFL++ dict2file instrumentation pass",
false, false);
static RegisterStandardPasses RegisterAFLdict2filePass(

View File

@ -1 +1 @@
2da7f08
c8a72dc

View File

@ -1 +1 @@
0569eff8a1
a1321713c7

View File

@ -356,7 +356,7 @@ fi
if ! command -v "$CROSS" > /dev/null ; then
if [ "$CPU_TARGET" = "$(uname -m)" ] ; then
echo "[+] Building afl++ qemu support libraries with CC=$CC"
echo "[+] Building AFL++ qemu support libraries with CC=$CC"
echo "[+] Building libcompcov ..."
make -C libcompcov && echo "[+] libcompcov ready"
echo "[+] Building unsigaction ..."
@ -371,7 +371,7 @@ if ! command -v "$CROSS" > /dev/null ; then
echo "[!] Cross compiler $CROSS could not be found, cannot compile libcompcov libqasan and unsigaction"
fi
else
echo "[+] Building afl++ qemu support libraries with CC=\"$CROSS $CROSS_FLAGS\""
echo "[+] Building AFL++ qemu support libraries with CC=\"$CROSS $CROSS_FLAGS\""
echo "[+] Building libcompcov ..."
make -C libcompcov CC="$CROSS $CROSS_FLAGS" && echo "[+] libcompcov ready"
echo "[+] Building unsigaction ..."

@ -1 +1 @@
Subproject commit 0569eff8a12dec73642b96757f6b5b51a618a03a
Subproject commit a1321713c7502c152dd7527555e0f8a800d55225

View File

@ -31,6 +31,8 @@
#include <strings.h>
#include <limits.h>
#include <assert.h>
#include <ctype.h>
#include <sys/stat.h>
#if (LLVM_MAJOR - 0 == 0)
#undef LLVM_MAJOR
@ -76,6 +78,7 @@ enum {
INSTRUMENT_OPT_NGRAM = 16,
INSTRUMENT_OPT_CALLER = 32,
INSTRUMENT_OPT_CTX_K = 64,
INSTRUMENT_OPT_CODECOV = 128,
};
@ -375,15 +378,304 @@ void parse_fsanitize(char *string) {
}
static u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0,
shared_linking = 0, preprocessor_only = 0, have_unroll = 0,
have_o = 0, have_pic = 0, have_c = 0, partial_linking = 0,
non_dash = 0;
static void process_params(u32 argc, char **argv) {
if (cc_par_cnt + argc >= 1024) { FATAL("Too many command line parameters"); }
if (lto_mode && argc > 1) {
u32 idx;
for (idx = 1; idx < argc; idx++) {
if (!strncasecmp(argv[idx], "-fpic", 5)) have_pic = 1;
}
}
// for (u32 x = 0; x < argc; ++x) fprintf(stderr, "[%u] %s\n", x, argv[x]);
/* Process the argument list. */
u8 skip_next = 0;
while (--argc) {
u8 *cur = *(++argv);
if (skip_next) {
skip_next = 0;
continue;
}
if (cur[0] != '-') { non_dash = 1; }
if (!strncmp(cur, "--afl", 5)) continue;
if (lto_mode && !strncmp(cur, "-flto=thin", 10)) {
FATAL(
"afl-clang-lto cannot work with -flto=thin. Switch to -flto=full or "
"use afl-clang-fast!");
}
if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
if (!strncmp(cur, "-fno-unroll", 11)) continue;
if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
!strcmp(cur, "--no-undefined")) {
continue;
}
if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
u8 *param = *(argv + 1);
if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
skip_next = 1;
continue;
}
}
if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
!strncmp(cur, "-stdlib=", 8)) {
if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
continue;
}
if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
have_instr_list = 1;
}
if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
strchr(cur, ',')) {
parse_fsanitize(cur);
if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
} else if ((!strncmp(cur, "-fsanitize=fuzzer-",
strlen("-fsanitize=fuzzer-")) ||
!strncmp(cur, "-fsanitize-coverage",
strlen("-fsanitize-coverage"))) &&
(strncmp(cur, "sanitize-coverage-allow",
strlen("sanitize-coverage-allow")) &&
strncmp(cur, "sanitize-coverage-deny",
strlen("sanitize-coverage-deny")) &&
instrument_mode != INSTRUMENT_LLVMNATIVE)) {
if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
continue;
}
if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
u8 *afllib = find_object("libAFLDriver.a", argv[0]);
if (!be_quiet) {
OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
}
if (!afllib) {
if (!be_quiet) {
WARNF(
"Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
"the flags - this will fail!");
}
} else {
cc_params[cc_par_cnt++] = afllib;
#ifdef __APPLE__
cc_params[cc_par_cnt++] = "-undefined";
cc_params[cc_par_cnt++] = "dynamic_lookup";
#endif
}
if (need_aflpplib) {
need_aflpplib = 0;
} else {
continue;
}
}
if (!strcmp(cur, "-m32")) bit_mode = 32;
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
asan_set = 1;
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
if (!strcmp(cur, "-x")) x_set = 1;
if (!strcmp(cur, "-E")) preprocessor_only = 1;
if (!strcmp(cur, "-shared")) shared_linking = 1;
if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
if (!strcmp(cur, "-r")) partial_linking = 1;
if (!strcmp(cur, "--relocatable")) partial_linking = 1;
if (!strcmp(cur, "-c")) have_c = 1;
if (!strncmp(cur, "-O", 2)) have_o = 1;
if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
if (*cur == '@') {
// response file support.
// we have two choices - move everything to the command line or
// rewrite the response files to temporary files and delete them
// afterwards. We choose the first for easiness.
// We do *not* support quotes in the rsp files to cope with spaces in
// filenames etc! If you need that then send a patch!
u8 *filename = cur + 1;
if (debug) { DEBUGF("response file=%s\n", filename); }
FILE *f = fopen(filename, "r");
struct stat st;
// Check not found or empty? let the compiler complain if so.
if (!f || fstat(fileno(f), &st) < 0 || st.st_size < 1) {
cc_params[cc_par_cnt++] = cur;
continue;
}
u8 *tmpbuf = malloc(st.st_size + 1), *ptr;
char **args = malloc(sizeof(char *) * (st.st_size >> 1));
int count = 1, cont = 0, cont_act = 0;
while (fgets(tmpbuf, st.st_size, f)) {
ptr = tmpbuf;
// no leading whitespace
while (isspace(*ptr)) {
++ptr;
cont_act = 0;
}
// no comments, no empty lines
if (*ptr == '#' || *ptr == '\n' || !*ptr) { continue; }
// remove LF
if (ptr[strlen(ptr) - 1] == '\n') { ptr[strlen(ptr) - 1] = 0; }
// remove CR
if (*ptr && ptr[strlen(ptr) - 1] == '\r') { ptr[strlen(ptr) - 1] = 0; }
// handle \ at end of line
if (*ptr && ptr[strlen(ptr) - 1] == '\\') {
cont = 1;
ptr[strlen(ptr) - 1] = 0;
}
// remove whitespace at end
while (*ptr && isspace(ptr[strlen(ptr) - 1])) {
ptr[strlen(ptr) - 1] = 0;
cont = 0;
}
if (*ptr) {
do {
u8 *value = ptr;
while (*ptr && !isspace(*ptr)) {
++ptr;
}
while (*ptr && isspace(*ptr)) {
*ptr++ = 0;
}
if (cont_act) {
u32 len = strlen(args[count - 1]) + strlen(value) + 1;
u8 *tmp = malloc(len);
snprintf(tmp, len, "%s%s", args[count - 1], value);
free(args[count - 1]);
args[count - 1] = tmp;
cont_act = 0;
} else {
args[count++] = strdup(value);
}
} while (*ptr);
}
if (cont) {
cont_act = 1;
cont = 0;
}
}
if (count) { process_params(count, args); }
// we cannot free args[]
free(tmpbuf);
continue;
}
cc_params[cc_par_cnt++] = cur;
}
}
/* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char **argv, char **envp) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0, shared_linking = 0,
preprocessor_only = 0, have_unroll = 0, have_o = 0, have_pic = 0,
have_c = 0, partial_linking = 0;
cc_params = ck_alloc((argc + 128) * sizeof(u8 *));
cc_params = ck_alloc(1024 * sizeof(u8 *));
if (lto_mode) {
@ -642,7 +934,7 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
//#if LLVM_MAJOR >= 13
// // Use the old pass manager in LLVM 14 which the afl++ passes still
// // Use the old pass manager in LLVM 14 which the AFL++ passes still
// use. cc_params[cc_par_cnt++] = "-flegacy-pass-manager";
//#endif
@ -751,7 +1043,21 @@ static void edit_params(u32 argc, char **argv, char **envp) {
} else if (instrument_mode == INSTRUMENT_LLVMNATIVE) {
#if LLVM_MAJOR >= 4
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
if (instrument_opt_mode & INSTRUMENT_OPT_CODECOV) {
#if LLVM_MAJOR >= 6
cc_params[cc_par_cnt++] =
"-fsanitize-coverage=trace-pc-guard,bb,no-prune,pc-table";
#else
FATAL("pcguard instrumentation with pc-table requires llvm 6.0.1+");
#endif
} else {
cc_params[cc_par_cnt++] = "-fsanitize-coverage=trace-pc-guard";
}
#else
FATAL("pcguard instrumentation requires llvm 4.0.1+");
#endif
@ -816,159 +1122,15 @@ static void edit_params(u32 argc, char **argv, char **envp) {
}
if (!have_pic) cc_params[cc_par_cnt++] = "-fPIC";
}
}
/* Detect stray -v calls from ./configure scripts. */
/* Inspect the command line parameters. */
u8 skip_next = 0, non_dash = 0;
while (--argc) {
process_params(argc, argv);
u8 *cur = *(++argv);
if (skip_next) {
skip_next = 0;
continue;
}
if (cur[0] != '-') { non_dash = 1; }
if (!strncmp(cur, "--afl", 5)) continue;
if (lto_mode && !strncmp(cur, "-fuse-ld=", 9)) continue;
if (lto_mode && !strncmp(cur, "--ld-path=", 10)) continue;
if (!strncmp(cur, "-fno-unroll", 11)) continue;
if (strstr(cur, "afl-compiler-rt") || strstr(cur, "afl-llvm-rt")) continue;
if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined") ||
!strcmp(cur, "--no-undefined")) {
continue;
}
if (compiler_mode == GCC_PLUGIN && !strcmp(cur, "-pipe")) { continue; }
if (!strcmp(cur, "-z") || !strcmp(cur, "-Wl,-z")) {
u8 *param = *(argv + 1);
if (!strcmp(param, "defs") || !strcmp(param, "-Wl,defs")) {
skip_next = 1;
continue;
}
}
if ((compiler_mode == GCC || compiler_mode == GCC_PLUGIN) &&
!strncmp(cur, "-stdlib=", 8)) {
if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
continue;
}
if (!strncmp(cur, "-fsanitize-coverage-", 20) && strstr(cur, "list=")) {
have_instr_list = 1;
}
if (!strncmp(cur, "-fsanitize=", strlen("-fsanitize=")) &&
strchr(cur, ',')) {
parse_fsanitize(cur);
if (!cur || strlen(cur) <= strlen("-fsanitize=")) { continue; }
} else if ((!strncmp(cur, "-fsanitize=fuzzer-",
strlen("-fsanitize=fuzzer-")) ||
!strncmp(cur, "-fsanitize-coverage",
strlen("-fsanitize-coverage"))) &&
(strncmp(cur, "sanitize-coverage-allow",
strlen("sanitize-coverage-allow")) &&
strncmp(cur, "sanitize-coverage-deny",
strlen("sanitize-coverage-deny")) &&
instrument_mode != INSTRUMENT_LLVMNATIVE)) {
if (!be_quiet) { WARNF("Found '%s' - stripping!", cur); }
continue;
}
if (need_aflpplib || !strcmp(cur, "-fsanitize=fuzzer")) {
u8 *afllib = find_object("libAFLDriver.a", argv[0]);
if (!be_quiet) {
OKF("Found '-fsanitize=fuzzer', replacing with libAFLDriver.a");
}
if (!afllib) {
if (!be_quiet) {
WARNF(
"Cannot find 'libAFLDriver.a' to replace '-fsanitize=fuzzer' in "
"the flags - this will fail!");
}
} else {
cc_params[cc_par_cnt++] = afllib;
#ifdef __APPLE__
cc_params[cc_par_cnt++] = "-undefined";
cc_params[cc_par_cnt++] = "dynamic_lookup";
#endif
}
if (need_aflpplib) {
need_aflpplib = 0;
} else {
continue;
}
}
if (!strcmp(cur, "-m32")) bit_mode = 32;
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
if (!strcmp(cur, "-m64")) bit_mode = 64;
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
asan_set = 1;
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
if (!strcmp(cur, "-x")) x_set = 1;
if (!strcmp(cur, "-E")) preprocessor_only = 1;
if (!strcmp(cur, "-shared")) shared_linking = 1;
if (!strcmp(cur, "-dynamiclib")) shared_linking = 1;
if (!strcmp(cur, "--target=wasm32-wasi")) passthrough = 1;
if (!strcmp(cur, "-Wl,-r")) partial_linking = 1;
if (!strcmp(cur, "-Wl,-i")) partial_linking = 1;
if (!strcmp(cur, "-Wl,--relocatable")) partial_linking = 1;
if (!strcmp(cur, "-r")) partial_linking = 1;
if (!strcmp(cur, "--relocatable")) partial_linking = 1;
if (!strcmp(cur, "-c")) have_c = 1;
if (!strncmp(cur, "-O", 2)) have_o = 1;
if (!strncmp(cur, "-funroll-loop", 13)) have_unroll = 1;
cc_params[cc_par_cnt++] = cur;
}
if (!have_pic) { cc_params[cc_par_cnt++] = "-fPIC"; }
// in case LLVM is installed not via a package manager or "make install"
// e.g. compiled download or compiled from github then its ./lib directory
@ -1651,13 +1813,17 @@ int main(int argc, char **argv, char **envp) {
instrument_mode = INSTRUMENT_CLASSIC;
lto_mode = 1;
} else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL)
} else if (!instrument_mode || instrument_mode == INSTRUMENT_AFL) {
instrument_mode = INSTRUMENT_AFL;
else
} else {
FATAL("main instrumentation mode already set with %s",
instrument_mode_string[instrument_mode]);
}
}
if (strncasecmp(ptr2, "pc-guard", strlen("pc-guard")) == 0 ||
@ -1682,6 +1848,23 @@ int main(int argc, char **argv, char **envp) {
}
if (strncasecmp(ptr2, "llvmcodecov", strlen("llvmcodecov")) == 0 ||
strncasecmp(ptr2, "llvm-codecov", strlen("llvm-codecov")) == 0) {
if (!instrument_mode || instrument_mode == INSTRUMENT_LLVMNATIVE) {
instrument_mode = INSTRUMENT_LLVMNATIVE;
instrument_opt_mode |= INSTRUMENT_OPT_CODECOV;
} else {
FATAL("main instrumentation mode already set with %s",
instrument_mode_string[instrument_mode]);
}
}
if (strncasecmp(ptr2, "cfg", strlen("cfg")) == 0 ||
strncasecmp(ptr2, "instrim", strlen("instrim")) == 0) {
@ -2241,7 +2424,8 @@ int main(int argc, char **argv, char **envp) {
"(requires LLVM 11 or higher)");
#endif
if (instrument_opt_mode && instrument_mode != INSTRUMENT_CLASSIC)
if (instrument_opt_mode && instrument_opt_mode != INSTRUMENT_OPT_CODECOV &&
instrument_mode != INSTRUMENT_CLASSIC)
FATAL(
"CALLER, CTX and NGRAM instrumentation options can only be used with "
"the LLVM CLASSIC instrumentation mode.");

View File

@ -489,7 +489,7 @@ static void report_error_and_exit(int error) {
break;
case FS_ERROR_OLD_CMPLOG:
FATAL(
"the -c cmplog target was instrumented with an too old afl++ "
"the -c cmplog target was instrumented with an too old AFL++ "
"version, you need to recompile it.");
break;
case FS_ERROR_OLD_CMPLOG_QEMU:
@ -987,7 +987,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
if ((status & FS_OPT_ENABLED) == FS_OPT_ENABLED) {
// workaround for recent afl++ versions
// workaround for recent AFL++ versions
if ((status & FS_OPT_OLD_AFLPP_WORKAROUND) == FS_OPT_OLD_AFLPP_WORKAROUND)
status = (status & 0xf0ffffff);
@ -1059,7 +1059,7 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv,
FATAL(
"Target's coverage map size of %u is larger than the one this "
"afl++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
"AFL++ is set with (%u). Either set AFL_MAP_SIZE=%u and restart "
" afl-fuzz, or change MAP_SIZE_POW2 in config.h and recompile "
"afl-fuzz",
tmp_map_size, fsrv->map_size, tmp_map_size);

View File

@ -716,6 +716,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
// if (getenv("MYTEST")) afl->in_place_resume = 1;
if (nl_cnt) {
u32 done = 0;
@ -827,6 +829,8 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
}
// if (getenv("MYTEST")) afl->in_place_resume = 0;
free(nl); /* not tracked */
if (!afl->queued_items && directory == NULL) {
@ -908,8 +912,10 @@ void perform_dry_run(afl_state_t *afl) {
if (res == afl->crash_mode || res == FSRV_RUN_NOBITS) {
SAYF(cGRA " len = %u, map size = %u, exec speed = %llu us\n" cRST,
q->len, q->bitmap_size, q->exec_us);
SAYF(cGRA
" len = %u, map size = %u, exec speed = %llu us, hash = "
"%016llx\n" cRST,
q->len, q->bitmap_size, q->exec_us, q->exec_cksum);
}
@ -1164,14 +1170,14 @@ void perform_dry_run(afl_state_t *afl) {
u32 duplicates = 0, i;
for (idx = 0; idx < afl->queued_items; idx++) {
for (idx = 0; idx < afl->queued_items - 1; idx++) {
q = afl->queue_buf[idx];
if (!q || q->disabled || q->cal_failed || !q->exec_cksum) { continue; }
u32 done = 0;
for (i = idx + 1;
i < afl->queued_items && !done && likely(afl->queue_buf[i]); i++) {
likely(i < afl->queued_items && afl->queue_buf[i] && !done); ++i) {
struct queue_entry *p = afl->queue_buf[i];
if (p->disabled || p->cal_failed || !p->exec_cksum) { continue; }
@ -1194,6 +1200,13 @@ void perform_dry_run(afl_state_t *afl) {
p->disabled = 1;
p->perf_score = 0;
if (afl->debug) {
WARNF("Same coverage - %s is kept active, %s is disabled.",
q->fname, p->fname);
}
} else {
if (!q->was_fuzzed) {
@ -1207,7 +1220,14 @@ void perform_dry_run(afl_state_t *afl) {
q->disabled = 1;
q->perf_score = 0;
done = 1;
if (afl->debug) {
WARNF("Same coverage - %s is kept active, %s is disabled.",
p->fname, q->fname);
}
done = 1; // end inner loop because outer loop entry is disabled now
}

View File

@ -842,6 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
memset(eff_map, 0, EFF_ALEN(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {
@ -2047,20 +2048,22 @@ custom_mutator_stage:
afl->queue_cur->stats_mutated += afl->stage_max;
#endif
if (likely(afl->custom_only)) {
/* Skip other stages */
ret_val = 0;
goto abandon_entry;
}
/****************
* RANDOM HAVOC *
****************/
havoc_stage:
if (unlikely(afl->custom_only)) {
/* Force UI update */
show_stats(afl);
/* Skip other stages */
ret_val = 0;
goto abandon_entry;
}
afl->stage_cur_byte = -1;
/* The havoc stage mutation code is also invoked when splicing files; if the
@ -3570,6 +3573,7 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
eff_map = afl_realloc(AFL_BUF_PARAM(eff), EFF_ALEN(len));
if (unlikely(!eff_map)) { PFATAL("alloc"); }
memset(eff_map, 0, EFF_ALEN(len));
eff_map[0] = 1;
if (EFF_APOS(len - 1) != 0) {

View File

@ -49,11 +49,13 @@ inline u32 select_next_queue_entry(afl_state_t *afl) {
u32 s = rand_below(afl, afl->queued_items);
double p = rand_next_percent(afl);
/*
fprintf(stderr, "select: p=%f s=%u ... p < prob[s]=%f ? s=%u : alias[%u]=%u"
" ==> %u\n", p, s, afl->alias_probability[s], s, s, afl->alias_table[s], p <
afl->alias_probability[s] ? s : afl->alias_table[s]);
*/
return (p < afl->alias_probability[s] ? s : afl->alias_table[s]);
}
@ -87,25 +89,28 @@ double compute_weight(afl_state_t *afl, struct queue_entry *q,
void create_alias_table(afl_state_t *afl) {
u32 n = afl->queued_items, i = 0, a, g;
u32 n = afl->queued_items, i = 0, nSmall = 0, nLarge = n - 1;
double sum = 0;
double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
u32 *Small = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
u32 *Large = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
afl->alias_table =
(u32 *)afl_realloc((void **)&afl->alias_table, n * sizeof(u32));
afl->alias_probability = (double *)afl_realloc(
(void **)&afl->alias_probability, n * sizeof(double));
double *P = (double *)afl_realloc(AFL_BUF_PARAM(out), n * sizeof(double));
int *S = (int *)afl_realloc(AFL_BUF_PARAM(out_scratch), n * sizeof(u32));
int *L = (int *)afl_realloc(AFL_BUF_PARAM(in_scratch), n * sizeof(u32));
if (!P || !S || !L || !afl->alias_table || !afl->alias_probability) {
if (!P || !Small || !Large || !afl->alias_table || !afl->alias_probability) {
FATAL("could not acquire memory for alias table");
}
memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)afl->alias_probability, 0, n * sizeof(double));
memset((void *)afl->alias_table, 0, n * sizeof(u32));
memset((void *)Small, 0, n * sizeof(u32));
memset((void *)Large, 0, n * sizeof(u32));
if (likely(afl->schedule < RARE)) {
@ -166,7 +171,15 @@ void create_alias_table(afl_state_t *afl) {
for (i = 0; i < n; i++) {
// weight is always 0 for disabled entries
P[i] = (afl->queue_buf[i]->weight * n) / sum;
if (unlikely(afl->queue_buf[i]->disabled)) {
P[i] = 0;
} else {
P[i] = (afl->queue_buf[i]->weight * n) / sum;
}
}
@ -176,60 +189,81 @@ void create_alias_table(afl_state_t *afl) {
struct queue_entry *q = afl->queue_buf[i];
if (likely(!q->disabled)) { q->perf_score = calculate_score(afl, q); }
if (likely(!q->disabled)) {
sum += q->perf_score;
q->perf_score = calculate_score(afl, q);
sum += q->perf_score;
}
}
for (i = 0; i < n; i++) {
// perf_score is always 0 for disabled entries
P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
if (unlikely(afl->queue_buf[i]->disabled)) {
P[i] = 0;
} else {
P[i] = (afl->queue_buf[i]->perf_score * n) / sum;
}
}
}
int nS = 0, nL = 0, s;
for (s = (s32)n - 1; s >= 0; --s) {
// Done collecting weightings in P, now create the arrays.
if (P[s] < 1) {
for (s32 j = (s32)(n - 1); j >= 0; j--) {
S[nS++] = s;
if (P[j] < 1) {
Small[nSmall++] = (u32)j;
} else {
L[nL++] = s;
Large[nLarge--] = (u32)j;
}
}
while (nS && nL) {
while (nSmall && nLarge != n - 1) {
a = S[--nS];
g = L[--nL];
afl->alias_probability[a] = P[a];
afl->alias_table[a] = g;
P[g] = P[g] + P[a] - 1;
if (P[g] < 1) {
u32 small = Small[--nSmall];
u32 large = Large[++nLarge];
S[nS++] = g;
afl->alias_probability[small] = P[small];
afl->alias_table[small] = large;
P[large] = P[large] - (1 - P[small]);
if (P[large] < 1) {
Small[nSmall++] = large;
} else {
L[nL++] = g;
Large[nLarge--] = large;
}
}
while (nL)
afl->alias_probability[L[--nL]] = 1;
while (nSmall) {
while (nS)
afl->alias_probability[S[--nS]] = 1;
afl->alias_probability[Small[--nSmall]] = 1;
}
while (nLarge != n - 1) {
afl->alias_probability[Large[++nLarge]] = 1;
}
afl->reinit_table = 0;
@ -264,7 +298,7 @@ void create_alias_table(afl_state_t *afl) {
*/
/*
fprintf(stderr, " entry alias probability perf_score weight
filename\n"); for (u32 i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u
filename\n"); for (i = 0; i < n; ++i) fprintf(stderr, " %5u %5u %11u
%0.9f %0.9f %s\n", i, afl->alias_table[i], afl->alias_probability[i],
afl->queue_buf[i]->perf_score, afl->queue_buf[i]->weight,
afl->queue_buf[i]->fname);

View File

@ -124,7 +124,8 @@ static void usage(u8 *argv0, int more_help) {
"\n%s [ options ] -- /path/to/fuzzed_app [ ... ]\n\n"
"Required parameters:\n"
" -i dir - input directory with test cases\n"
" -i dir - input directory with test cases (or '-' to resume, "
"also see AFL_AUTORESUME)\n"
" -o dir - output directory for fuzzer findings\n\n"
"Execution control settings:\n"
@ -1280,16 +1281,16 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->fsrv.mem_limit && afl->shm.cmplog_mode) afl->fsrv.mem_limit += 260;
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
"Eißfeldt, Andrea Fioraldi and Dominik Maier");
OKF("afl++ is open source, get it at "
OKF("AFL++ is maintained by Marc \"van Hauser\" Heuse, Dominik Maier, Andrea "
"Fioraldi and Heiko \"hexcoder\" Eißfeldt");
OKF("AFL++ is open source, get it at "
"https://github.com/AFLplusplus/AFLplusplus");
OKF("NOTE: afl++ >= v3 has changed defaults and behaviours - see README.md");
OKF("NOTE: AFL++ >= v3 has changed defaults and behaviours - see README.md");
#ifdef __linux__
if (afl->fsrv.nyx_mode) {
OKF("afl++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
OKF("AFL++ Nyx mode is enabled (developed and mainted by Sergej Schumilo)");
OKF("Nyx is open source, get it at https://github.com/Nyx-Fuzz");
}
@ -1529,29 +1530,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
if (afl->custom_only) {
FATAL("Custom mutators are incompatible with MOpt (-L)");
}
u32 custom_fuzz = 0;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz) { custom_fuzz = 1; }
});
if (custom_fuzz) {
WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
}
}
if (afl->afl_env.afl_max_det_extras) {
s32 max_det_extras = atoi(afl->afl_env.afl_max_det_extras);
@ -1826,8 +1804,76 @@ int main(int argc, char **argv_orig, char **envp) {
printf("DEBUG: rand %06d is %u\n", counter, rand_below(afl, 65536));
#endif
if (!getenv("AFL_CUSTOM_INFO_PROGRAM")) {
setenv("AFL_CUSTOM_INFO_PROGRAM", argv[optind], 1);
}
if (!getenv("AFL_CUSTOM_INFO_PROGRAM_INPUT") && afl->fsrv.out_file) {
setenv("AFL_CUSTOM_INFO_PROGRAM_INPUT", afl->fsrv.out_file, 1);
}
{
u8 envbuf[8096] = "", tmpbuf[8096] = "";
for (s32 i = optind + 1; i < argc; ++i) {
strcpy(tmpbuf, envbuf);
if (strchr(argv[i], ' ') && !strchr(argv[i], '"') &&
!strchr(argv[i], '\'')) {
if (!strchr(argv[i], '\'')) {
snprintf(envbuf, sizeof(tmpbuf), "%s '%s'", tmpbuf, argv[i]);
} else {
snprintf(envbuf, sizeof(tmpbuf), "%s \"%s\"", tmpbuf, argv[i]);
}
} else {
snprintf(envbuf, sizeof(tmpbuf), "%s %s", tmpbuf, argv[i]);
}
}
setenv("AFL_CUSTOM_INFO_PROGRAM_ARGV", envbuf + 1, 1);
}
setenv("AFL_CUSTOM_INFO_OUT", afl->out_dir, 1); // same as __AFL_OUT_DIR
setup_custom_mutators(afl);
if (afl->limit_time_sig > 0 && afl->custom_mutators_count) {
if (afl->custom_only) {
FATAL("Custom mutators are incompatible with MOpt (-L)");
}
u32 custom_fuzz = 0;
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
if (el->afl_custom_fuzz) { custom_fuzz = 1; }
});
if (custom_fuzz) {
WARNF("afl_custom_fuzz is incompatible with MOpt (-L)");
}
}
write_setup_file(afl, argc, argv);
setup_cmdline_file(afl, argv + optind);
@ -1979,6 +2025,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode ||
afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) {
u32 old_map_size = map_size;
map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, map_size);
@ -1990,6 +2037,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, map_size);
if (old_map_size < map_size) {
memset(afl->var_bytes + old_map_size, 0, map_size - old_map_size);
memset(afl->top_rated + old_map_size, 0, map_size - old_map_size);
memset(afl->clean_trace + old_map_size, 0, map_size - old_map_size);
memset(afl->clean_trace_custom + old_map_size, 0,
map_size - old_map_size);
memset(afl->first_trace + old_map_size, 0, map_size - old_map_size);
memset(afl->map_tmp_buf + old_map_size, 0, map_size - old_map_size);
}
}
afl->argv = use_argv;
@ -2017,6 +2076,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Re-initializing maps to %u bytes", new_map_size);
u32 old_map_size = map_size;
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@ -2029,6 +2089,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
if (old_map_size < new_map_size) {
memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
memset(afl->clean_trace_custom + old_map_size, 0,
new_map_size - old_map_size);
memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
}
afl_fsrv_kill(&afl->fsrv);
afl_shm_deinit(&afl->shm);
afl->fsrv.map_size = new_map_size;
@ -2079,6 +2151,7 @@ int main(int argc, char **argv_orig, char **envp) {
OKF("Re-initializing maps to %u bytes due cmplog", new_map_size);
u32 old_map_size = map_size;
afl->virgin_bits = ck_realloc(afl->virgin_bits, new_map_size);
afl->virgin_tmout = ck_realloc(afl->virgin_tmout, new_map_size);
afl->virgin_crash = ck_realloc(afl->virgin_crash, new_map_size);
@ -2091,6 +2164,18 @@ int main(int argc, char **argv_orig, char **envp) {
afl->first_trace = ck_realloc(afl->first_trace, new_map_size);
afl->map_tmp_buf = ck_realloc(afl->map_tmp_buf, new_map_size);
if (old_map_size < new_map_size) {
memset(afl->var_bytes + old_map_size, 0, new_map_size - old_map_size);
memset(afl->top_rated + old_map_size, 0, new_map_size - old_map_size);
memset(afl->clean_trace + old_map_size, 0, new_map_size - old_map_size);
memset(afl->clean_trace_custom + old_map_size, 0,
new_map_size - old_map_size);
memset(afl->first_trace + old_map_size, 0, new_map_size - old_map_size);
memset(afl->map_tmp_buf + old_map_size, 0, new_map_size - old_map_size);
}
afl_fsrv_kill(&afl->fsrv);
afl_fsrv_kill(&afl->cmplog_fsrv);
afl_shm_deinit(&afl->shm);

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - wrapper for llvm 11+ lld
-----------------------------------------------
Written by Marc Heuse <mh@mh-sec.de> for afl++
Written by Marc Heuse <mh@mh-sec.de> for AFL++
Maintained by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de>
@ -210,7 +210,7 @@ static void edit_params(int argc, char **argv) {
if (strcmp(argv[i], "--afl") == 0) {
if (!be_quiet) OKF("afl++ test command line flag detected, exiting.");
if (!be_quiet) OKF("AFL++ test command line flag detected, exiting.");
exit(0);
}

View File

@ -1287,7 +1287,7 @@ int main(int argc, char **argv_orig, char **envp) {
break;
case 'Y': // fallthough
case 'Y': // fallthrough
#ifdef __linux__
case 'X': /* NYX mode */
@ -1421,6 +1421,14 @@ int main(int argc, char **argv_orig, char **envp) {
// If @@ are in the target args, replace them and also set use_stdin=false.
detect_file_args(argv + optind, stdin_file, &fsrv->use_stdin);
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
fsrv->out_file = stdin_file;
fsrv->out_fd =
open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", stdin_file); }
} else {
// If @@ are in the target args, replace them and also set use_stdin=false.
@ -1588,6 +1596,14 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->map_size = map_size;
} else {
afl_fsrv_start(fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") ||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
? 1
: 0);
}
if (in_dir || in_filelist) {
@ -1617,9 +1633,6 @@ int main(int argc, char **argv_orig, char **envp) {
if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true;
fsrv->dev_null_fd = open("/dev/null", O_RDWR);
if (fsrv->dev_null_fd < 0) { PFATAL("Unable to open /dev/null"); }
if (in_filelist) {
if (!be_quiet) ACTF("Reading from file list '%s'...", in_filelist);
@ -1666,10 +1679,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
atexit(at_exit_handler);
fsrv->out_file = stdin_file;
fsrv->out_fd =
open(stdin_file, O_RDWR | O_CREAT | O_EXCL, DEFAULT_PERMISSION);
if (fsrv->out_fd < 0) { PFATAL("Unable to create '%s'", out_file); }
if (get_afl_env("AFL_DEBUG")) {
@ -1685,12 +1694,6 @@ int main(int argc, char **argv_orig, char **envp) {
}
afl_fsrv_start(fsrv, use_argv, &stop_soon,
(get_afl_env("AFL_DEBUG_CHILD") ||
get_afl_env("AFL_DEBUG_CHILD_OUTPUT"))
? 1
: 0);
map_size = fsrv->map_size;
if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz)

View File

@ -28,7 +28,7 @@ int main(int argc, char **argv) {
}
// must use deferred forkserver as otherwise afl++ instrumentation aborts
// must use deferred forkserver as otherwise AFL++ instrumentation aborts
// because all dlopen() of instrumented libs must be before the forkserver
__AFL_INIT();

View File

@ -23,7 +23,7 @@ test -e ../afl-gcc-fast -a -e ../afl-compiler-rt.o && {
$ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine"
} || {
$ECHO "$RED[!] gcc_plugin instrumentation produces a weird numbers: $TUPLES"
$ECHO "$YELLOW[-] this is a known issue in gcc, not afl++. It is not flagged as an error because travis builds would all fail otherwise :-("
$ECHO "$YELLOW[-] this is a known issue in gcc, not AFL++. It is not flagged as an error because travis builds would all fail otherwise :-("
#CODE=1
}
test "$TUPLES" -lt 2 && SKIP=1

View File

@ -263,7 +263,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
{
mkdir -p in
echo 00000000000000000000000000000000 > in/in
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V15 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1
AFL_BENCH_UNTIL_CRASH=1 ../afl-fuzz -m none -V30 -i in -o out -c./test-cmplog -- ./test-c >>errors 2>&1
} >>errors 2>&1
test -n "$( ls out/default/crashes/id:000000* out/default/hangs/id:000000* 2>/dev/null )" && {
$ECHO "$GREEN[+] afl-fuzz is working correctly with llvm_mode cmplog"

View File

@ -7,7 +7,7 @@ FILE=$AFL_PERFORMANCE_FILE
test -z "$FILE" && FILE=.afl_performance
test -e $FILE || {
echo Warning: This script measure the performance of afl++ and saves the result for future comparisons into $FILE
echo Warning: This script measure the performance of AFL++ and saves the result for future comparisons into $FILE
echo Press ENTER to continue or CONTROL-C to abort
read IN
}
@ -74,7 +74,7 @@ afl-system-config > /dev/null 2>&1
echo Performance settings applied.
echo
$ECHO "${RESET}${GREY}[*] starting afl++ performance test framework ..."
$ECHO "${RESET}${GREY}[*] starting AFL++ performance test framework ..."
$ECHO "$BLUE[*] Testing: ${AFL_GCC}"
GCC=x

View File

@ -133,7 +133,7 @@ MEM_LIMIT=none
export PATH="${PATH}:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin"
$ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
$ECHO "${RESET}${GREY}[*] starting AFL++ test framework ..."
test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"

View File

@ -182,7 +182,7 @@ git pull
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
git checkout "$UNICORNAFL_VERSION" || exit 1
echo "[*] making sure afl++ header files match"
echo "[*] making sure AFL++ header files match"
cp "../../include/config.h" "./include" || exit 1
echo "[*] Configuring Unicorn build..."