mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-10 17:21:33 +00:00
Merge branch 'dev' of github.com:vanhauser-thc/AFLplusplus into dev
This commit is contained in:
commit
8610b0e406
5
.gitignore
vendored
5
.gitignore
vendored
@ -16,6 +16,7 @@ afl-gcc
|
||||
afl-gcc-fast
|
||||
afl-g++-fast
|
||||
afl-gotcpu
|
||||
afl-ld
|
||||
afl-qemu-trace
|
||||
afl-showmap
|
||||
afl-tmin
|
||||
@ -39,8 +40,12 @@ afl-tmin.8
|
||||
afl-whatsup.8
|
||||
qemu_mode/libcompcov/compcovtest
|
||||
as
|
||||
ld
|
||||
qemu_mode/qemu-*
|
||||
unicorn_mode/unicornafl/
|
||||
unicorn_mode/samples/*/\.test-*
|
||||
unicorn_mode/samples/*/output/
|
||||
core\.*
|
||||
test/unittests/unit_maybe_alloc
|
||||
test/unittests/unit_preallocable
|
||||
test/unittests/unit_list
|
||||
|
@ -41,8 +41,8 @@ before_install:
|
||||
# export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE}
|
||||
- echo Testing on $NAME
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi
|
||||
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils ; fi
|
||||
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils ; fi
|
||||
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev findutils libcmocka-dev ; fi
|
||||
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev findutils libcmocka-dev ; fi
|
||||
|
||||
script:
|
||||
- gcc -v
|
||||
|
475
GNUmakefile
Normal file
475
GNUmakefile
Normal file
@ -0,0 +1,475 @@
|
||||
#
|
||||
# american fuzzy lop++ - makefile
|
||||
# -----------------------------
|
||||
#
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
# For Heiko:
|
||||
#TEST_MMAP=1
|
||||
# the hash character is treated differently in different make versions
|
||||
# so use a variable for '#'
|
||||
HASH=\#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
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
|
||||
|
||||
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
|
||||
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 "$(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
|
||||
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
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell uname)" "Darwin"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_OPT = -march=native
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell uname -m)" "x86_64"
|
||||
ifneq "$(shell uname -m)" "i386"
|
||||
ifneq "$(shell uname -m)" "amd64"
|
||||
ifneq "$(shell uname -m)" "i86pc"
|
||||
AFL_NO_X86=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT) -D_FORTIFY_SOURCE=2
|
||||
override CFLAGS += -Wall -g -Wno-pointer-sign \
|
||||
-I include/ -Werror -DAFL_PATH=\"$(HELPER_PATH)\" \
|
||||
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
|
||||
|
||||
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
|
||||
|
||||
ifneq "$(shell type python3m 2>/dev/null)" ""
|
||||
ifneq "$(shell type python3m-config 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python3m-config --includes)
|
||||
PYTHON_VERSION ?= $(strip $(shell python3m --version 2>&1))
|
||||
# Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
|
||||
ifeq "$(shell python3m-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
|
||||
PYTHON_LIB ?= $(shell python3m-config --libs --embed)
|
||||
else
|
||||
PYTHON_LIB ?= $(shell python3m-config --ldflags)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell type python3 2>/dev/null)" ""
|
||||
ifneq "$(shell type python3-config 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python3-config --includes)
|
||||
PYTHON_VERSION ?= $(strip $(shell python3 --version 2>&1))
|
||||
# Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
|
||||
ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
|
||||
PYTHON_LIB ?= $(shell python3-config --libs --embed)
|
||||
else
|
||||
PYTHON_LIB ?= $(shell python3-config --ldflags)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell type python 2>/dev/null)" ""
|
||||
ifneq "$(shell type python-config 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python-config --includes)
|
||||
PYTHON_LIB ?= $(shell python-config --ldflags)
|
||||
PYTHON_VERSION ?= $(strip $(shell python --version 2>&1))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
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")
|
||||
else
|
||||
BUILD_DATE ?= $(shell date "+%Y-%m-%d")
|
||||
endif
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
ifneq "$(findstring FreeBSD, $(shell uname))" ""
|
||||
CFLAGS += -pthread
|
||||
LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifneq "$(findstring NetBSD, $(shell uname))" ""
|
||||
CFLAGS += -pthread
|
||||
LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
TEST_CC = afl-gcc
|
||||
else
|
||||
TEST_CC = afl-clang
|
||||
endif
|
||||
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
PYTHON_OK=1
|
||||
PYFLAGS=-DUSE_PYTHON $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) -DPYTHON_VERSION="\"$(PYTHON_VERSION)\""
|
||||
else
|
||||
PYTHON_OK=0
|
||||
PYFLAGS=
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(info Compiling static version of binaries)
|
||||
# Disable python for static compilation to simplify things
|
||||
PYTHON_OK=0
|
||||
PYFLAGS=
|
||||
|
||||
CFLAGS += -static
|
||||
LDFLAGS += -lm -lpthread -lz -lutil
|
||||
endif
|
||||
|
||||
ASAN_CFLAGS=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer
|
||||
ASAN_LDFLAGS+=-fsanitize=address -fstack-protector-all -fno-omit-frame-pointer
|
||||
|
||||
ifdef ASAN_BUILD
|
||||
$(info Compiling ASAN version of binaries)
|
||||
CFLAGS+=$(ASAN_CFLAGS)
|
||||
LDFLAGS+=$(ASAN_LDFLAGS)
|
||||
endif
|
||||
|
||||
ifdef PROFILING
|
||||
$(info Compiling profiling version of binaries)
|
||||
CFLAGS+=-pg
|
||||
LDFLAGS+=-pg
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS+=-Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS+=-Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
|
||||
|
||||
man: $(MANPAGES)
|
||||
|
||||
tests: source-only
|
||||
@cd test ; ./test.sh
|
||||
@rm -f test/errors
|
||||
|
||||
performance-tests: performance-test
|
||||
test-performance: performance-test
|
||||
|
||||
performance-test: source-only
|
||||
@cd test ; ./test-performance.sh
|
||||
|
||||
|
||||
help:
|
||||
@echo "HELP --- the following make targets exist:"
|
||||
@echo "=========================================="
|
||||
@echo "all: just the main afl++ binaries"
|
||||
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa"
|
||||
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa"
|
||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||
@echo "man: creates simple man pages from the help option of the programs"
|
||||
@echo "install: installs everything you have compiled with the build option above"
|
||||
@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
|
||||
@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)"
|
||||
@echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations"
|
||||
@echo "help: shows these build options :-)"
|
||||
@echo "=========================================="
|
||||
@echo "Recommended: \"distrib\" or \"source-only\", then \"install\""
|
||||
@echo
|
||||
@echo Known build environment options:
|
||||
@echo "=========================================="
|
||||
@echo STATIC - compile AFL++ static
|
||||
@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
||||
@echo PROFILING - compile afl-fuzz with profiling information
|
||||
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||
@echo "=========================================="
|
||||
@echo e.g.: make ASAN_BUILD=1
|
||||
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
test_x86:
|
||||
@echo "[*] Checking for the default compiler cc..."
|
||||
@type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
|
||||
@echo "[*] Checking for the ability to compile x86 code..."
|
||||
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) $(CFLAGS) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
|
||||
@rm -f .test1
|
||||
|
||||
else
|
||||
|
||||
test_x86:
|
||||
@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifeq "$(PYTHON_OK)" "1"
|
||||
|
||||
test_python:
|
||||
@rm -f .test 2> /dev/null
|
||||
@echo "[+] $(PYTHON_VERSION) support seems to be working."
|
||||
|
||||
else
|
||||
|
||||
test_python:
|
||||
@echo "[-] You seem to need to install the package python3-dev or python2-dev (and perhaps python[23]-apt), but it is optional so we continue"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile."
|
||||
|
||||
afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) 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)
|
||||
ln -sf afl-as as
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
radamsa: src/third_party/libradamsa/libradamsa.so
|
||||
cp src/third_party/libradamsa/libradamsa.so .
|
||||
|
||||
src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h
|
||||
$(MAKE) -C src/third_party/libradamsa/ CFLAGS="$(CFLAGS)"
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) 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 $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) 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-forkserver.o | test_x86
|
||||
$(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
./test/unittests/unit_maybe_alloc
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
./test/unittests/unit_list
|
||||
|
||||
test/unittests/preallocable.o : $(COMM_HDR) include/afl-prealloc.h test/unittests/preallocable.c $(AFL_FUZZ_FILES)
|
||||
$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(CFLAGS_FLTO) -c test/unittests/preallocable.c -o test/unittests/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
|
||||
./test/unittests/unit_preallocable
|
||||
|
||||
unit: unit_maybe_alloc unit_preallocable unit_list
|
||||
|
||||
code-format:
|
||||
./.custom-format.py -i src/*.c
|
||||
./.custom-format.py -i include/*.h
|
||||
./.custom-format.py -i libdislocator/*.c
|
||||
./.custom-format.py -i libtokencap/*.c
|
||||
./.custom-format.py -i llvm_mode/*.c
|
||||
./.custom-format.py -i llvm_mode/*.h
|
||||
./.custom-format.py -i llvm_mode/*.cc
|
||||
./.custom-format.py -i gcc_plugin/*.c
|
||||
#./.custom-format.py -i gcc_plugin/*.h
|
||||
./.custom-format.py -i gcc_plugin/*.cc
|
||||
./.custom-format.py -i examples/*/*.c
|
||||
./.custom-format.py -i examples/*/*.h
|
||||
./.custom-format.py -i qemu_mode/patches/*.h
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.h
|
||||
./.custom-format.py -i qbdi_mode/*.c
|
||||
./.custom-format.py -i qbdi_mode/*.cpp
|
||||
./.custom-format.py -i *.h
|
||||
./.custom-format.py -i *.c
|
||||
|
||||
|
||||
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 )
|
||||
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
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
else
|
||||
|
||||
test_build: afl-gcc afl-as afl-showmap
|
||||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
all_done: test_build
|
||||
@if [ ! "`type clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.md for a faster alternative to afl-gcc."; fi
|
||||
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
|
||||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable
|
||||
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
|
||||
-$(MAKE) -C llvm_mode clean
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
$(MAKE) -C libdislocator clean
|
||||
$(MAKE) -C libtokencap clean
|
||||
$(MAKE) -C examples/socket_fuzzing clean
|
||||
$(MAKE) -C examples/argv_fuzzing clean
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
$(MAKE) -C src/third_party/libradamsa/ clean
|
||||
-rm -rf unicorn_mode/unicornafl
|
||||
|
||||
distrib: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/socket_fuzzing
|
||||
$(MAKE) -C examples/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
binary-only: all radamsa
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/socket_fuzzing
|
||||
$(MAKE) -C examples/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
source-only: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||
@echo .SH NAME >> $@
|
||||
@echo .B $* >> $@
|
||||
@echo >> $@
|
||||
@echo .SH SYNOPSIS >> $@
|
||||
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@
|
||||
@echo >> $@
|
||||
@echo .SH OPTIONS >> $@
|
||||
@echo .nf >> $@
|
||||
@./$* -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 >> $@
|
||||
@echo .SH LICENSE >> $@
|
||||
@echo Apache License Version 2.0, January 2004 >> $@
|
||||
|
||||
install: all $(MANPAGES)
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-clang-fast ]; then $(MAKE) -C llvm_mode install; fi
|
||||
if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C examples/socket_fuzzing install; fi
|
||||
if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C examples/argv_fuzzing install; fi
|
||||
|
||||
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
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
|
||||
|
||||
mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||
|
||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
|
||||
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
|
||||
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
|
||||
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
|
452
Makefile
452
Makefile
@ -1,450 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - makefile
|
||||
# -----------------------------
|
||||
#
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
# For Heiko:
|
||||
#TEST_MMAP=1
|
||||
# the hash character is treated differently in different make versions
|
||||
# so use a variable for '#'
|
||||
HASH=\#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
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
|
||||
|
||||
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
|
||||
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 "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto=full
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto=thin
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell uname)" "Darwin"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_OPT = -march=native
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell uname -m)" "x86_64"
|
||||
ifneq "$(shell uname -m)" "i386"
|
||||
ifneq "$(shell uname -m)" "amd64"
|
||||
ifneq "$(shell uname -m)" "i86pc"
|
||||
AFL_NO_X86=1
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops $(CFLAGS_OPT)
|
||||
override CFLAGS += -Wall -g -Wno-pointer-sign -I include/ \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function -fcommon
|
||||
|
||||
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
|
||||
|
||||
ifneq "$(shell type python3m 2>/dev/null)" ""
|
||||
ifneq "$(shell type python3m-config 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python3m-config --includes)
|
||||
PYTHON_VERSION ?= $(strip $(shell python3m --version 2>&1))
|
||||
# Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
|
||||
ifeq "$(shell python3m-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
|
||||
PYTHON_LIB ?= $(shell python3m-config --libs --embed)
|
||||
else
|
||||
PYTHON_LIB ?= $(shell python3m-config --ldflags)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell type python3 2>/dev/null)" ""
|
||||
ifneq "$(shell type python3-config 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python3-config --includes)
|
||||
PYTHON_VERSION ?= $(strip $(shell python3 --version 2>&1))
|
||||
# Starting with python3.8, we need to pass the `embed` flag. Earier versions didn't know this flag.
|
||||
ifeq "$(shell python3-config --embed --libs 2>/dev/null | grep -q lpython && echo 1 )" "1"
|
||||
PYTHON_LIB ?= $(shell python3-config --libs --embed)
|
||||
else
|
||||
PYTHON_LIB ?= $(shell python3-config --ldflags)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(shell type python 2>/dev/null)" ""
|
||||
ifneq "$(shell type python-config 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python-config --includes)
|
||||
PYTHON_LIB ?= $(shell python-config --ldflags)
|
||||
PYTHON_VERSION ?= $(strip $(shell python --version 2>&1))
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
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")
|
||||
else
|
||||
BUILD_DATE ?= $(shell date "+%Y-%m-%d")
|
||||
endif
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
ifneq "$(findstring FreeBSD, $(shell uname))" ""
|
||||
CFLAGS += -pthread
|
||||
LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifneq "$(findstring NetBSD, $(shell uname))" ""
|
||||
CFLAGS += -pthread
|
||||
LDFLAGS += -lpthread
|
||||
endif
|
||||
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
TEST_CC = afl-gcc
|
||||
else
|
||||
TEST_CC = afl-clang
|
||||
endif
|
||||
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
PYTHON_OK=1
|
||||
PYFLAGS=-DUSE_PYTHON $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) -DPYTHON_VERSION="\"$(PYTHON_VERSION)\""
|
||||
else
|
||||
PYTHON_OK=0
|
||||
PYFLAGS=
|
||||
endif
|
||||
|
||||
ifdef STATIC
|
||||
$(info Compiling static version of binaries)
|
||||
# Disable python for static compilation to simplify things
|
||||
PYTHON_OK=0
|
||||
PYFLAGS=
|
||||
|
||||
CFLAGS += -static
|
||||
LDFLAGS += -lm -lpthread -lz -lutil
|
||||
endif
|
||||
|
||||
ifdef ASAN_BUILD
|
||||
$(info Compiling ASAN version of binaries)
|
||||
CFLAGS+=-fsanitize=address
|
||||
LDFLAGS+=-fsanitize=address
|
||||
endif
|
||||
|
||||
ifdef PROFILING
|
||||
$(info Compiling profiling version of binaries)
|
||||
CFLAGS+=-pg
|
||||
LDFLAGS+=-pg
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS+=-Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS+=-Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
all: test_x86 test_shm test_python ready $(PROGS) afl-as test_build all_done
|
||||
|
||||
man: $(MANPAGES)
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
|
||||
tests: source-only
|
||||
@cd test ; ./test.sh
|
||||
@rm -f test/errors
|
||||
|
||||
performance-tests: performance-test
|
||||
test-performance: performance-test
|
||||
|
||||
performance-test: source-only
|
||||
@cd test ; ./test-performance.sh
|
||||
|
||||
|
||||
help:
|
||||
@echo "HELP --- the following make targets exist:"
|
||||
@echo "=========================================="
|
||||
@echo "all: just the main afl++ binaries"
|
||||
@echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa"
|
||||
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa"
|
||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||
@echo "man: creates simple man pages from the help option of the programs"
|
||||
@echo "install: installs everything you have compiled with the build option above"
|
||||
@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
|
||||
@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 "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations"
|
||||
@echo "help: shows these build options :-)"
|
||||
@echo "=========================================="
|
||||
@echo "Recommended: \"distrib\" or \"source-only\", then \"install\""
|
||||
@echo
|
||||
@echo Known build environment options:
|
||||
@echo "=========================================="
|
||||
@echo STATIC - compile AFL++ static
|
||||
@echo ASAN_BUILD - compiles with memory sanitizer for debug purposes
|
||||
@echo PROFILING - compile afl-fuzz with profiling information
|
||||
@echo AFL_NO_X86 - if compiling on non-intel/amd platforms
|
||||
@echo "=========================================="
|
||||
@echo e.g.: make ASAN_BUILD=1
|
||||
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
test_x86:
|
||||
@echo "[*] Checking for the default compiler cc..."
|
||||
@type $(CC) >/dev/null || ( echo; echo "Oops, looks like there is no compiler '"$(CC)"' in your path."; echo; echo "Don't panic! You can restart with '"$(_)" CC=<yourCcompiler>'."; echo; exit 1 )
|
||||
@echo "[*] Checking for the ability to compile x86 code..."
|
||||
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test1 || ( echo; echo "Oops, looks like your compiler can't generate x86 code."; echo; echo "Don't panic! You can use the LLVM or QEMU mode, but see docs/INSTALL first."; echo "(To ignore this error, set AFL_NO_X86=1 and try again.)"; echo; exit 1 )
|
||||
@rm -f .test1
|
||||
|
||||
else
|
||||
|
||||
test_x86:
|
||||
@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ifeq "$(PYTHON_OK)" "1"
|
||||
|
||||
test_python:
|
||||
@rm -f .test 2> /dev/null
|
||||
@echo "[+] $(PYTHON_VERSION) support seems to be working."
|
||||
|
||||
else
|
||||
|
||||
test_python:
|
||||
@echo "[-] You seem to need to install the package python3-dev or python2-dev (and perhaps python[23]-apt), but it is optional so we continue"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile."
|
||||
|
||||
afl-gcc: src/afl-gcc.c $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) 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)
|
||||
ln -sf afl-as as
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
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
|
||||
|
||||
radamsa: src/third_party/libradamsa/libradamsa.so
|
||||
cp src/third_party/libradamsa/libradamsa.so .
|
||||
|
||||
src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h
|
||||
$(MAKE) -C src/third_party/libradamsa/ CFLAGS="$(CFLAGS)"
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) 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 $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) src/$@.c src/afl-common.o src/afl-sharedmem.o -o $@ $(LDFLAGS)
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) src/$@.c -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-forkserver.o | test_x86
|
||||
$(CC) -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
|
||||
|
||||
code-format:
|
||||
./.custom-format.py -i src/*.c
|
||||
./.custom-format.py -i include/*.h
|
||||
./.custom-format.py -i libdislocator/*.c
|
||||
./.custom-format.py -i libtokencap/*.c
|
||||
./.custom-format.py -i llvm_mode/*.c
|
||||
./.custom-format.py -i llvm_mode/*.h
|
||||
./.custom-format.py -i llvm_mode/*.cc
|
||||
./.custom-format.py -i gcc_plugin/*.c
|
||||
#./.custom-format.py -i gcc_plugin/*.h
|
||||
./.custom-format.py -i gcc_plugin/*.cc
|
||||
./.custom-format.py -i examples/*/*.c
|
||||
./.custom-format.py -i examples/*/*.h
|
||||
./.custom-format.py -i qemu_mode/patches/*.h
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.h
|
||||
./.custom-format.py -i qbdi_mode/*.c
|
||||
./.custom-format.py -i qbdi_mode/*.cpp
|
||||
./.custom-format.py -i *.h
|
||||
./.custom-format.py -i *.c
|
||||
|
||||
|
||||
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 )
|
||||
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
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
else
|
||||
|
||||
test_build: afl-gcc afl-as afl-showmap
|
||||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)."
|
||||
|
||||
endif
|
||||
|
||||
|
||||
all_done: test_build
|
||||
@if [ ! "`type clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.md for a faster alternative to afl-gcc."; fi
|
||||
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
|
||||
@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
|
||||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast ld *.so *.8
|
||||
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
|
||||
-$(MAKE) -C llvm_mode clean
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
$(MAKE) -C libdislocator clean
|
||||
$(MAKE) -C libtokencap clean
|
||||
$(MAKE) -C examples/socket_fuzzing clean
|
||||
$(MAKE) -C examples/argv_fuzzing clean
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
$(MAKE) -C src/third_party/libradamsa/ clean
|
||||
-rm -rf unicorn_mode/unicornafl
|
||||
|
||||
distrib: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/socket_fuzzing
|
||||
$(MAKE) -C examples/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
binary-only: all radamsa
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C examples/socket_fuzzing
|
||||
$(MAKE) -C examples/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
source-only: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||
@echo .SH NAME >> $@
|
||||
@echo .B $* >> $@
|
||||
@echo >> $@
|
||||
@echo .SH SYNOPSIS >> $@
|
||||
@./$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> $@
|
||||
@echo >> $@
|
||||
@echo .SH OPTIONS >> $@
|
||||
@echo .nf >> $@
|
||||
@./$* -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 >> $@
|
||||
@echo .SH LICENSE >> $@
|
||||
@echo Apache License Version 2.0, January 2004 >> $@
|
||||
|
||||
install: all $(MANPAGES)
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi
|
||||
if [ -f afl-gcc-fast ]; then set e; install -m 755 afl-gcc-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-gcc-fast $${DESTDIR}$(BIN_PATH)/afl-g++-fast; install -m 755 afl-gcc-pass.so afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
$(MAKE) -C llvm_mode install
|
||||
if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
$(MAKE) -C examples/socket_fuzzing install
|
||||
$(MAKE) -C examples/argv_fuzzing install
|
||||
|
||||
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
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
|
||||
|
||||
mkdir -m 0755 -p ${DESTDIR}$(MAN_PATH)
|
||||
install -m0644 *.8 ${DESTDIR}$(MAN_PATH)
|
||||
|
||||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH)
|
||||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as
|
||||
install -m 644 docs/*.md $${DESTDIR}$(DOC_PATH)
|
||||
cp -r testcases/ $${DESTDIR}$(MISC_PATH)
|
||||
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH)
|
||||
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
41
README.md
41
README.md
@ -54,7 +54,7 @@
|
||||
|
||||
* Win32 PE binary-only fuzzing with QEMU and Wine
|
||||
|
||||
* Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly).
|
||||
* Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusively).
|
||||
|
||||
* QBDI mode to fuzz android native libraries via QBDI framework
|
||||
|
||||
@ -85,7 +85,7 @@
|
||||
|
||||
(4) Only for LLVM >= 9 and not all targets compile
|
||||
|
||||
(5) upcoming, development in branch
|
||||
(5) upcoming, development in the branch
|
||||
|
||||
(6) not compatible with LTO and InsTrim modes
|
||||
|
||||
@ -118,7 +118,7 @@
|
||||
We are happy to be part of [Google Summer of Code 2020](https://summerofcode.withgoogle.com/organizations/5100744400699392/)! :-)
|
||||
|
||||
We have several ideas we would like to see in AFL++ to make it even better.
|
||||
However we already work on so many things that we do not have the time for
|
||||
However, we already work on so many things that we do not have the time for
|
||||
all the big ideas.
|
||||
|
||||
This can be your way to support and contribute to AFL++ - extend it to
|
||||
@ -160,6 +160,7 @@ These build targets exist:
|
||||
* clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well
|
||||
* code-format: format the code, do this before you commit and send a PR please!
|
||||
* tests: runs test cases to ensure that all features are still working as they should
|
||||
* unit: perform unit tests (based on cmocka)
|
||||
* help: shows these build options
|
||||
|
||||
[Unless you are on Mac OS X](https://developer.apple.com/library/archive/qa/qa1118/_index.html) you can also build statically linked versions of the
|
||||
@ -205,9 +206,9 @@ There have been numerous attempts to solve this problem. One of the early
|
||||
approaches - pioneered by Tavis Ormandy - is corpus distillation. The method
|
||||
relies on coverage signals to select a subset of interesting seeds from a
|
||||
massive, high-quality corpus of candidate files, and then fuzz them by
|
||||
traditional means. The approach works exceptionally well, but requires such
|
||||
traditional means. The approach works exceptionally well but requires such
|
||||
a corpus to be readily available. In addition, block coverage measurements
|
||||
provide only a very simplistic understanding of program state, and are less
|
||||
provide only a very simplistic understanding of the program state and are less
|
||||
useful for guiding the fuzzing effort in the long haul.
|
||||
|
||||
Other, more sophisticated research has focused on techniques such as program
|
||||
@ -228,7 +229,7 @@ Simplifying a bit, the overall algorithm can be summed up as:
|
||||
|
||||
1) Load user-supplied initial test cases into the queue,
|
||||
|
||||
2) Take next input file from the queue,
|
||||
2) Take the next input file from the queue,
|
||||
|
||||
3) Attempt to trim the test case to the smallest size that doesn't alter
|
||||
the measured behavior of the program,
|
||||
@ -259,7 +260,7 @@ superior to blind fuzzing or coverage-only tools.
|
||||
## Instrumenting programs for use with AFL
|
||||
|
||||
PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++
|
||||
instead of afl-gcc/afl-g++ is much faster and has a few cool features.
|
||||
instead of afl-gcc/afl-g++ is much faster and has many cool features.
|
||||
See llvm_mode/ - however few code does not compile with llvm.
|
||||
We support llvm versions 3.8.0 to 11.
|
||||
|
||||
@ -295,7 +296,7 @@ Using partial instrumentation is also recommended, see
|
||||
When testing libraries, you need to find or write a simple program that reads
|
||||
data from stdin or from a file and passes it to the tested library. In such a
|
||||
case, it is essential to link this executable against a static version of the
|
||||
instrumented library, or to make sure that the correct .so file is loaded at
|
||||
instrumented library or to make sure that the correct .so file is loaded at
|
||||
runtime (usually by setting `LD_LIBRARY_PATH`). The simplest option is a static
|
||||
build, usually possible via:
|
||||
|
||||
@ -342,7 +343,7 @@ A more comprehensive description of these and other options can be found in
|
||||
|
||||
## Good examples and writeups
|
||||
|
||||
Here are some good writeups to show how to effectibly use AFL++:
|
||||
Here are some good writeups to show how to effectively use AFL++:
|
||||
|
||||
* [https://aflplus.plus/docs/tutorials/libxml2_tutorial/](https://aflplus.plus/docs/tutorials/libxml2_tutorial/)
|
||||
* [https://bananamafia.dev/post/gb-fuzz/](https://bananamafia.dev/post/gb-fuzz/)
|
||||
@ -372,7 +373,7 @@ The available schedules are:
|
||||
- mmopt (experimental)
|
||||
- rare (experimental)
|
||||
|
||||
In parallel mode (-M/-S, several instances with shared queue), we suggest to
|
||||
In parallel mode (-M/-S, several instances with the shared queue), we suggest to
|
||||
run the master using the explore or fast schedule (-p explore) and the slaves
|
||||
with a combination of cut-off-exponential (-p coe), exponential (-p fast),
|
||||
explore (-p explore) and mmopt (-p mmopt) schedules. If a schedule does
|
||||
@ -380,7 +381,7 @@ not perform well for a target, restart the slave with a different schedule.
|
||||
|
||||
In single mode, using -p fast is usually slightly more beneficial than the
|
||||
default explore mode.
|
||||
(We don't want to change the default behaviour of afl, so "fast" has not been
|
||||
(We don't want to change the default behavior of afl, so "fast" has not been
|
||||
made the default mode).
|
||||
|
||||
More details can be found in the paper published at the 23rd ACM Conference on
|
||||
@ -450,12 +451,12 @@ See the [docs/status_screen.md](docs/status_screen.md) file for information on
|
||||
how to interpret the displayed stats and monitor the health of the process. Be
|
||||
sure to consult this file especially if any UI elements are highlighted in red.
|
||||
|
||||
The fuzzing process will continue until you press Ctrl-C. At minimum, you want
|
||||
The fuzzing process will continue until you press Ctrl-C. At a minimum, you want
|
||||
to allow the fuzzer to complete one queue cycle, which may take anywhere from a
|
||||
couple of hours to a week or so.
|
||||
|
||||
There are three subdirectories created within the output directory and updated
|
||||
in real time:
|
||||
in real-time:
|
||||
|
||||
- queue/ - test cases for every distinctive execution path, plus all the
|
||||
starting files given by the user. This is the synthesized corpus
|
||||
@ -480,7 +481,7 @@ involve any state transitions not seen in previously-recorded faults. If a
|
||||
single bug can be reached in multiple ways, there will be some count inflation
|
||||
early in the process, but this should quickly taper off.
|
||||
|
||||
The file names for crashes and hangs are correlated with parent, non-faulting
|
||||
The file names for crashes and hangs are correlated with the parent, non-faulting
|
||||
queue entries. This should help with debugging.
|
||||
|
||||
When you can't reproduce a crash found by afl-fuzz, the most likely cause is
|
||||
@ -544,10 +545,10 @@ instrumentation feedback alone. This actually works in practice, say:
|
||||
PS. Even when no explicit dictionary is given, afl-fuzz will try to extract
|
||||
existing syntax tokens in the input corpus by watching the instrumentation
|
||||
very closely during deterministic byte flips. This works for some types of
|
||||
parsers and grammars, but isn't nearly as good as the -x mode.
|
||||
parsers and grammars but isn't nearly as good as the -x mode.
|
||||
|
||||
If a dictionary is really hard to come by, another option is to let AFL run
|
||||
for a while, and then use the token capture library that comes as a companion
|
||||
for a while and then use the token capture library that comes as a companion
|
||||
utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md).
|
||||
|
||||
## Crash triage
|
||||
@ -562,7 +563,7 @@ difficult to quickly evaluate for exploitability without a lot of debugging and
|
||||
code analysis work. To assist with this task, afl-fuzz supports a very unique
|
||||
"crash exploration" mode enabled with the -C flag.
|
||||
|
||||
In this mode, the fuzzer takes one or more crashing test cases as the input,
|
||||
In this mode, the fuzzer takes one or more crashing test cases as the input
|
||||
and uses its feedback-driven fuzzing strategies to very quickly enumerate all
|
||||
code paths that can be reached in the program while keeping it in the
|
||||
crashing state.
|
||||
@ -601,7 +602,7 @@ near the end of [docs/technical_details.md](docs/technical_details.md).
|
||||
|
||||
Fuzzing is a wonderful and underutilized technique for discovering non-crashing
|
||||
design and implementation errors, too. Quite a few interesting bugs have been
|
||||
found by modifying the target programs to call abort() when, say:
|
||||
found by modifying the target programs to call abort() when say:
|
||||
|
||||
- Two bignum libraries produce different outputs when given the same
|
||||
fuzzer-generated input,
|
||||
@ -623,7 +624,7 @@ shared with libfuzzer) or `#ifdef __AFL_COMPILER` (this one is just for AFL).
|
||||
## Common-sense risks
|
||||
|
||||
Please keep in mind that, similarly to many other computationally-intensive
|
||||
tasks, fuzzing may put strain on your hardware and on the OS. In particular:
|
||||
tasks, fuzzing may put a strain on your hardware and on the OS. In particular:
|
||||
|
||||
- Your CPU will run hot and will need adequate cooling. In most cases, if
|
||||
cooling is insufficient or stops working properly, CPU speeds will be
|
||||
@ -656,7 +657,7 @@ Here are some of the most important caveats for AFL:
|
||||
- AFL detects faults by checking for the first spawned process dying due to
|
||||
a signal (SIGSEGV, SIGABRT, etc). Programs that install custom handlers for
|
||||
these signals may need to have the relevant code commented out. In the same
|
||||
vein, faults in child processed spawned by the fuzzed target may evade
|
||||
vein, faults in child processes spawned by the fuzzed target may evade
|
||||
detection unless you manually add some code to catch that.
|
||||
|
||||
- As with any other brute-force tool, the fuzzer offers limited coverage if
|
||||
|
@ -122,6 +122,7 @@ fmt_duration()
|
||||
|
||||
FIRST=true
|
||||
TOTAL_WCOP=
|
||||
TOTAL_LAST_PATH=0
|
||||
|
||||
for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
|
||||
@ -171,6 +172,10 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
|
||||
TOTAL_PENDING=$((TOTAL_PENDING + pending_total))
|
||||
TOTAL_PFAV=$((TOTAL_PFAV + pending_favs))
|
||||
|
||||
if [ "$last_path" -gt "$TOTAL_LAST_PATH" ]; then
|
||||
TOTAL_LAST_PATH=$last_path
|
||||
fi
|
||||
|
||||
if [ "$SUMMARY_ONLY" = "" ]; then
|
||||
|
||||
# Warnings in red
|
||||
@ -236,6 +241,7 @@ TOTAL_DAYS=$((TOTAL_TIME / 60 / 60 / 24))
|
||||
TOTAL_HRS=$(((TOTAL_TIME / 60 / 60) % 24))
|
||||
|
||||
test -z "$TOTAL_WCOP" && TOTAL_WCOP="not available"
|
||||
fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING
|
||||
|
||||
test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
|
||||
|
||||
@ -262,6 +268,7 @@ fi
|
||||
|
||||
echo " Crashes found : $TOTAL_CRASHES locally unique"
|
||||
echo "Cycles without finds : $TOTAL_WCOP"
|
||||
echo " Time without finds : $TOTAL_LAST_PATH"
|
||||
echo
|
||||
|
||||
exit 0
|
||||
|
@ -238,362 +238,6 @@
|
||||
"\\p{Nd}"
|
||||
"\\P{Any}"
|
||||
"\\p{Changes_When_NFKC_Casefolded}"
|
||||
"L~"
|
||||
"P{scx=Greek}??"
|
||||
"Q~"
|
||||
"R??"
|
||||
"R!??oo(E=?ar)baz-"
|
||||
"Sc?Sc{?{?"
|
||||
"U~"
|
||||
"V~"
|
||||
"W~"
|
||||
"Xdtc"
|
||||
"X~"
|
||||
"X?"
|
||||
"[-123],}"
|
||||
"[-????]+,}"
|
||||
"[00011],}"
|
||||
"[011],}"
|
||||
"[0],}"
|
||||
"[1111],}"
|
||||
"[111],}"
|
||||
"[118],}"
|
||||
"[11],}"
|
||||
"[11a],}"
|
||||
"[[]{}()%^# ],}"
|
||||
"[]"
|
||||
"[],}"
|
||||
"[]{}()%^# ,}"
|
||||
"[^123],}"
|
||||
"[a-b-c],}"
|
||||
"[a-zA-Z0-9],}"
|
||||
"[b"
|
||||
"[bfoo(?!bar)baz"
|
||||
"[c!],}"
|
||||
"[c1],}"
|
||||
"[cA],}"
|
||||
"[cZ],}"
|
||||
"[c_],}"
|
||||
"[ca],}"
|
||||
"[cz],}"
|
||||
"[c~],}"
|
||||
"[c~]w"
|
||||
"[d-d],}"
|
||||
"[d-z],}"
|
||||
"[u???[11<([c?]?:u??<a>)dccc]"
|
||||
"[ud808udf45-ud809udccc],}"
|
||||
"[x"
|
||||
"[x],}"
|
||||
"[xdz],}"
|
||||
"[xyz],}"
|
||||
"[x?"
|
||||
"[x?n4n4"
|
||||
"[x??19?"
|
||||
"[z-d],}"
|
||||
"[~?"
|
||||
"[?????"
|
||||
"[?"
|
||||
"[???],}"
|
||||
"[????-????],}"
|
||||
"[????"
|
||||
"]"
|
||||
"],}"
|
||||
"]QrC[w~]Qr"
|
||||
"]}"
|
||||
"]~"
|
||||
"^?000???????????????????????????x60?"
|
||||
"^12(a(?:1(b12))2)1dyb?9"
|
||||
"^xi!q"
|
||||
"^xxx$,}"
|
||||
"abc"
|
||||
"abc60,0}?{?"
|
||||
"aic"
|
||||
"b~"
|
||||
"c"
|
||||
"c!,}"
|
||||
"c,}"
|
||||
"cA,}"
|
||||
"c_,}"
|
||||
"cjcJcicIckcK,}"
|
||||
"c~"
|
||||
"c~,}"
|
||||
"d"
|
||||
"d?"
|
||||
"d??"
|
||||
"d(?:ab[]?9}"
|
||||
"dpN?(?<a>.)?"
|
||||
"duu{123a?"
|
||||
"d{1,9"
|
||||
"d~"
|
||||
"e"
|
||||
"e~"
|
||||
"e?}"
|
||||
"f~"
|
||||
"g~"
|
||||
"h~"
|
||||
"i~"
|
||||
"j~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xx?~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxb~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxc~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxd~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxe~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxf~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxg~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxh~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxi~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxj~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxk~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxl~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxm~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxn~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxo~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxp~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxr~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxs~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxt~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxu~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxv~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxw~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxx~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxy~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxz~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xx?~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxn~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxo~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxp~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxq~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxr~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxs~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxt~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxu~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxv~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxw~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxx~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxy~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxz~"
|
||||
"k?@a(?=bbb.~"
|
||||
"k?@a(?=bbbb~"
|
||||
"k?@a(?=bbbc~"
|
||||
"k?@a(?=bbbd~"
|
||||
"k?@a(?=bbbe~"
|
||||
"k?@a(?=bbbf~"
|
||||
"k?@a(?=bbbg~"
|
||||
"k?@a(?=bbbh~"
|
||||
"k?@a(?=bbbi~"
|
||||
"k?@a(?=bbbj~"
|
||||
"k?@a(?=bbbk~"
|
||||
"k?@a(?=bbbl~"
|
||||
"k?@a(?=bbbm~"
|
||||
"k?@a(?=bbbn~"
|
||||
"k?@a(?=bbbo~"
|
||||
"k?@a(?=bbbp~"
|
||||
"k?@a(?=bbbq~"
|
||||
"k?@a(?=bbbr~"
|
||||
"k?@a(?=bbbs~"
|
||||
"k?@a(?=bbbt~"
|
||||
"k?@a(?=bbbu~"
|
||||
"k?@a(?=bbbv~"
|
||||
"k?@a(?=bbbw~"
|
||||
"k?@a(?=bbbx~"
|
||||
"k?@a(?=bbby~"
|
||||
"k?@a(?=bbbz~"
|
||||
"k?@a(?=by?bC?:!k??????????????b~"
|
||||
"k?@a(?=by?bC?:!k??????????????c~"
|
||||
"k?@a(?=by?bC?:!k??????????????d~"
|
||||
"k?@a(?=by?bC?:!k??????????????e~"
|
||||
"k?@a(?=by?bC?:!k??????????????f~"
|
||||
"k?@a(?=by?bC?:!k??????????????g~"
|
||||
"k?@a(?=by?bC?:!k??????????????h~"
|
||||
"k?@a(?=by?bC?:!k??????????????i~"
|
||||
"k?@a(?=by?bC?:!k??????????????j~"
|
||||
"k?@a(?=by?bC?:!k??????????????k~"
|
||||
"k?@a(?=by?bC?:!k??????????????l~"
|
||||
"k?@a(?=by?bC?:!k??????????????m~"
|
||||
"k?@a(?=by?bC?:!k??????????????n~"
|
||||
"k?@a(?=by?bC?:!k??????????????o~"
|
||||
"k?@a(?=by?bC?:!k??????????????p~"
|
||||
"k?@a(?=by?bC?:!k??????????????q~"
|
||||
"k?@a(?=by?bC?:!k??????????????r~"
|
||||
"k?@a(?=by?bC?:!k??????????????s~"
|
||||
"k?@a(?=by?bC?:!k??????????????t~"
|
||||
"k?@a(?=by?bC?:!k??????????????u~"
|
||||
"k?@a(?=by?bC?:!k??????????????v~"
|
||||
"k?@a(?=by?bC?:!k??????????????w~"
|
||||
"k?@a(?=by?bC?:!k??????????????x~"
|
||||
"k?@a(?=by?bC?:!k??????????????y~"
|
||||
"k?@a(?=by?bC?:!k??????????????z~"
|
||||
"k?@a(?=by?bC?:!k???????????????~"
|
||||
"k?@a(?~"
|
||||
"k?@a(b~"
|
||||
"k?@a(c~"
|
||||
"k?@a(d~"
|
||||
"k?@a(e~"
|
||||
"k?@a(f~"
|
||||
"k?@a(g~"
|
||||
"k?@a(h~"
|
||||
"k?@a(i~"
|
||||
"k?@a(j~"
|
||||
"k?@a(k~"
|
||||
"k?@a(l~"
|
||||
"k?@a(m~"
|
||||
"k?@a(n~"
|
||||
"k?@a(o~"
|
||||
"k?@a(p~"
|
||||
"k?@a(q~"
|
||||
"k?@a(r~"
|
||||
"k?@a(s~"
|
||||
"k?@a(t~"
|
||||
"k?@a(u~"
|
||||
"k?@a(v~"
|
||||
"k?@a(w~"
|
||||
"k?@a(x~"
|
||||
"k?@a(y~"
|
||||
"k?@a(z~"
|
||||
"k0X@ab~"
|
||||
"k0X@ac~"
|
||||
"k0X@ad~"
|
||||
"k0X@ae~"
|
||||
"k0X@af~"
|
||||
"k0X@ag~"
|
||||
"k0X@ah~"
|
||||
"k0X@ai~"
|
||||
"k0X@aj~"
|
||||
"k0X@ak~"
|
||||
"k0X@al~"
|
||||
"k0X@am~"
|
||||
"k0X@an~"
|
||||
"k0X@ao~"
|
||||
"k0X@ap~"
|
||||
"k0X@aq~"
|
||||
"k0X@ar~"
|
||||
"k0X@as~"
|
||||
"k0X@at~"
|
||||
"k0X@au~"
|
||||
"k0X@av~"
|
||||
"k0X@aw~"
|
||||
"k0X@ax~"
|
||||
"k0X@ay~"
|
||||
"k0X@az~"
|
||||
"k0X@a?~"
|
||||
"k~"
|
||||
"l~"
|
||||
"m~"
|
||||
"n~"
|
||||
"o~"
|
||||
"p~"
|
||||
"q,}"
|
||||
"q~"
|
||||
"r~"
|
||||
"r?[c~]"
|
||||
"s~"
|
||||
"t~"
|
||||
"u0034,}"
|
||||
"u003z,}"
|
||||
"u0060,}"
|
||||
"ud808udf45*,}"
|
||||
"u~"
|
||||
"v~"
|
||||
"w"
|
||||
"w~"
|
||||
"x3z,}"
|
||||
"x60,}"
|
||||
"xyz?9"
|
||||
"x~"
|
||||
"y~"
|
||||
"z~"
|
||||
"{"
|
||||
"{??"
|
||||
"{ ,,?"
|
||||
"{-"
|
||||
"{0,d?????!"
|
||||
"{12345}pu{234:P}?"
|
||||
"{1?5"
|
||||
"{@"
|
||||
"{M,??"
|
||||
"{M,P{scx=Greek}???sn"
|
||||
"{M,??"
|
||||
"{M,??"
|
||||
"{M,?M,??"
|
||||
"{O"
|
||||
"{r~"
|
||||
"{s~"
|
||||
"{t~"
|
||||
"{u~"
|
||||
"{v~"
|
||||
"{w~"
|
||||
"{x~"
|
||||
"{y~"
|
||||
"{z~"
|
||||
"{}"
|
||||
"{}~"
|
||||
"{??@"
|
||||
"{?~"
|
||||
"},}"
|
||||
"}}"
|
||||
"}}}}}?}!}}}}}}}}}}}}}}}}}?},}"
|
||||
"}~"
|
||||
"}?w~???"
|
||||
"~~"
|
||||
"?!~"
|
||||
"?$"
|
||||
"?*?9?nnRnnn?"
|
||||
"?.~"
|
||||
"?123222222??"
|
||||
"?:??"
|
||||
"?R"
|
||||
"?b~"
|
||||
"?c~"
|
||||
"?d~"
|
||||
"?d???"
|
||||
"?e~"
|
||||
"?f~"
|
||||
"?g~"
|
||||
"?h~"
|
||||
"?i~"
|
||||
"?j~"
|
||||
"?k~"
|
||||
"?l~"
|
||||
"?m~"
|
||||
"?n~"
|
||||
"?o~"
|
||||
"?p~"
|
||||
"?q~"
|
||||
"?r~"
|
||||
"?s~"
|
||||
"?t~"
|
||||
"?u~"
|
||||
"?v~"
|
||||
"?v~?v"
|
||||
"?w~"
|
||||
"?x~"
|
||||
"?y~"
|
||||
"?z~"
|
||||
"?}"
|
||||
"??~"
|
||||
"?????????dadi(?!bbb"
|
||||
"??~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~>>>>>>>>>>>>>>>>>>"
|
||||
"?f??123222222??"
|
||||
"?fP{gc=Decimal_Number}"
|
||||
"?f2jq?oo@ooooh??"
|
||||
"?[???],}f?"
|
||||
"?[???],}nbbc2jocom"
|
||||
"?[]"
|
||||
"?[],}?"
|
||||
"?[],}f?"
|
||||
"?[]f?"
|
||||
"?[]{}()%^#"
|
||||
"?[^123],}f?"
|
||||
"?[^123]nbbc2jocom"
|
||||
"?[a-b-c],}f?"
|
||||
"?[a-b-c]nbbc2jocom"
|
||||
"?[a-zA-Z0-9],}f?"
|
||||
"?[a-zA-Z0-9],}jocom"
|
||||
"?[a-zA-Z0-9]c2jocom"
|
||||
"?[bfoo(?!bar)bazcom"
|
||||
"?[bfoo(?!bar)bazf?"
|
||||
"(?:a?)??"
|
||||
"a?)"xyz{93}"
|
||||
"{93}"
|
||||
@ -601,3 +245,12 @@
|
||||
"[\x8f]"
|
||||
"[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\x92\xa9-\xf4\x8f\xbf\xbf]"
|
||||
"[\x92\xa9-\xf4\x8f\xbf\xbf]"
|
||||
"\\1\\2(b\\1\\2))\\2)\\1"
|
||||
"\\1\\2(a(?:\\1\\2))\\2)\\1"
|
||||
"?:\\1"
|
||||
"\\1(b\\1\\2))\\2)\\1"
|
||||
"\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1"
|
||||
"foo(?=bar)bar)baz"
|
||||
"fo(?o(?o(?o(?=bar)baz"
|
||||
"foo(?=bar)baz"
|
||||
"foo(?=bar)bar)az"
|
||||
|
@ -16,12 +16,15 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
! development and acceptance of PRs now happen only in the dev branch
|
||||
and only occasionally when everything is fine we PR to master
|
||||
- all:
|
||||
- big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn
|
||||
- big code changes to make afl-fuzz thread-safe so afl-fuzz can spawn
|
||||
multiple fuzzing threads in the future or even become a library
|
||||
- afl basic tools now report on the environment variables picked up
|
||||
- more tools get environment variable usage info in the help output
|
||||
- force all output to stdout (some OK/SAY/WARN messages were sent to
|
||||
stdout, some to stderr)
|
||||
- uninstrumented mode uses an internal forkserver ("fauxserver")
|
||||
- now builds with `-D_FORTIFY_SOURCE=2`
|
||||
- drastically reduced number of (de)allocations during fuzzing
|
||||
- afl-fuzz:
|
||||
- python mutator modules and custom mutator modules now use the same
|
||||
interface and hence the API changed
|
||||
@ -31,13 +34,14 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
the last 5 queue entries
|
||||
- rare: puts focus on queue entries that hits rare branches, also ignores
|
||||
runtime
|
||||
- llvm_mode: added Control Flow Integrity sanitizer (AFL_USE_CFISAN)
|
||||
- LTO collision free instrumented added in llvm_mode with afl-clang-lto -
|
||||
note that this mode is amazing, but quite some targets won't compile
|
||||
- Added llvm_mode NGRAM prev_loc coverage by Adrean Herrera
|
||||
(https://github.com/adrianherrera/afl-ngram-pass/), activate by setting
|
||||
AFL_LLVM_NGRAM_SIZE
|
||||
- llvm_mode InsTrim mode:
|
||||
- removed workaround for bug where paths were not instrumented and
|
||||
- removed workaround for bug where paths were not instrumented and
|
||||
imported fix by author
|
||||
- made skipping 1 block functions an option and is disable by default,
|
||||
set AFL_LLVM_INSTRIM_SKIPSINGLEBLOCK=1 to re-enable this
|
||||
@ -202,7 +206,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.src
|
||||
* all afl sources are now in src/ - see src/README.md
|
||||
* afl-fuzz was splitted up in various individual files for including
|
||||
functionality in other programs (e.g. forkserver, memory map, etc.)
|
||||
for better readability.
|
||||
|
@ -27,18 +27,16 @@ performed with the custom mutator.
|
||||
|
||||
C/C++:
|
||||
```c
|
||||
void afl_custom_init(unsigned int seed);
|
||||
size_t afl_custom_fuzz(uint8_t** buf, size_t buf_size, uint8_t* add_buf,
|
||||
size_t add_buf_size, size_t max_size);
|
||||
size_t afl_custom_pre_save(uint8_t* buf, size_t buf_size, uint8_t** out_buf);
|
||||
uint32_t afl_custom_init_trim(uint8_t* buf, size_t buf_size);
|
||||
void afl_custom_trim(uint8_t** out_buf, size_t* out_buf_size);
|
||||
uint32_t afl_custom_post_trim(uint8_t success);
|
||||
size_t afl_custom_havoc_mutation(uint8_t** buf, size_t buf_size, size_t max_size);
|
||||
uint8_t afl_custom_havoc_mutation_probability(void);
|
||||
uint8_t afl_custom_queue_get(const uint8_t* filename);
|
||||
void afl_custom_queue_new_entry(const uint8_t* filename_new_queue,
|
||||
const uint8_t* filename_orig_queue);
|
||||
void *afl_custom_init(afl_t *afl, unsigned int seed);
|
||||
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_pre_save(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);
|
||||
size_t afl_custom_trim(void *data, uint8_t **out_buf);
|
||||
int32_t afl_custom_post_trim(void *data, int success) {
|
||||
size_t afl_custom_havoc_mutation(void *data, u8 *buf, size_t buf_size, u8 **out_buf, size_t max_size);
|
||||
uint8_t afl_custom_havoc_mutation_probability(void *data);
|
||||
uint8_t afl_custom_queue_get(void *data, const uint8_t *filename); void afl_custom_queue_new_entry(void *data, const uint8_t *filename_new_queue, const uint8_t *filename_orig_queue);
|
||||
void afl_custom_deinit(void *data);
|
||||
```
|
||||
|
||||
Python:
|
||||
@ -76,9 +74,9 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
|
||||
|
||||
### Custom Mutation
|
||||
|
||||
- `init` (optional):
|
||||
- `init`:
|
||||
|
||||
This method is called when AFL++ starts up and is used to seed RNG.
|
||||
This method is called when AFL++ starts up and is used to seed RNG and set up buffers and state.
|
||||
|
||||
- `queue_get` (optional):
|
||||
|
||||
@ -110,7 +108,7 @@ def queue_new_entry(filename_new_queue, filename_orig_queue):
|
||||
|
||||
- `queue_new_entry` (optional):
|
||||
|
||||
This methods is called after adding a new test case to the queue.
|
||||
This methods is called after adding a new test case to the queue.
|
||||
|
||||
### Trimming Support
|
||||
|
||||
@ -144,7 +142,7 @@ trimmed input. Here's a quick API description:
|
||||
|
||||
This method is called for each trimming operation. It doesn't have any
|
||||
arguments because we already have the initial buffer from `init_trim` and we
|
||||
can memorize the current state in global variables. This can also save
|
||||
can memorize the current state in the data variables. This can also save
|
||||
reparsing steps for each iteration. It should return the trimmed input
|
||||
buffer, where the returned data must not exceed the initial input data in
|
||||
length. Returning anything that is larger than the original data (passed to
|
||||
@ -158,6 +156,8 @@ trimmed input. Here's a quick API description:
|
||||
In any case, this method must return the next trim iteration index (from 0
|
||||
to the maximum amount of steps you returned in `init_trim`).
|
||||
|
||||
`deinit` the last method to be called, deinitializing the state.
|
||||
|
||||
Omitting any of three methods will cause the trimming to be disabled and trigger
|
||||
a fallback to the builtin default trimming routine.
|
||||
|
||||
@ -166,7 +166,7 @@ a fallback to the builtin default trimming routine.
|
||||
Optionally, the following environment variables are supported:
|
||||
|
||||
- `AFL_CUSTOM_MUTATOR_ONLY`
|
||||
|
||||
|
||||
Disable all other mutation stages. This can prevent broken testcases
|
||||
(those that your Python module can't work with anymore) to fill up your
|
||||
queue. Best combined with a custom trimming routine (see below) because
|
||||
|
@ -31,7 +31,9 @@ tools make fairly broad use of environmental variables:
|
||||
|
||||
(You can also enable MSAN via AFL_USE_MSAN; ASAN and MSAN come with the
|
||||
same gotchas; the modes are mutually exclusive. UBSAN can be enabled
|
||||
similarly by setting the environment variable AFL_USE_UBSAN=1)
|
||||
similarly by setting the environment variable AFL_USE_UBSAN=1. Finally
|
||||
there is the Control Flow Integrity sanitizer that can be activated by
|
||||
AFL_USE_CFISAN=1)
|
||||
|
||||
- Setting AFL_CC, AFL_CXX, and AFL_AS lets you use alternate downstream
|
||||
compilation tools, rather than the default 'clang', 'gcc', or 'as' binaries
|
||||
|
@ -29,7 +29,7 @@ Note that ASAN is incompatible with -static, so be mindful of that.
|
||||
(You can also use AFL_USE_MSAN=1 to enable MSAN instead.)
|
||||
|
||||
NOTE: if you run several slaves only one should run the target compiled with
|
||||
ASAN (and UBSAN), the others should run the target with no sanitizers
|
||||
ASAN (and UBSAN, CFISAN), the others should run the target with no sanitizers
|
||||
compiled in.
|
||||
|
||||
There is also the option of generating a corpus using a non-ASAN binary, and
|
||||
|
@ -2,9 +2,7 @@
|
||||
|
||||
Here's a quick overview of the stuff you can find in this directory:
|
||||
|
||||
- custom_mutstors - An example custom mutator
|
||||
|
||||
- python_mutators - Python mutators examples
|
||||
- custom_mutators - example custom mutators in python an c
|
||||
|
||||
- argv_fuzzing - a simple wrapper to allow cmdline to be fuzzed
|
||||
(e.g., to test setuid programs).
|
||||
@ -15,8 +13,8 @@ Here's a quick overview of the stuff you can find in this directory:
|
||||
- bash_shellshock - a simple hack used to find a bunch of
|
||||
post-Shellshock bugs in bash.
|
||||
|
||||
- canvas_harness - a test harness used to find browser bugs with a
|
||||
corpus generated using simple image parsing
|
||||
- canvas_harness - a test harness used to find browser bugs with a
|
||||
corpus generated using simple image parsing
|
||||
binaries & afl-fuzz.
|
||||
|
||||
- clang_asm_normalize - a script that makes it easy to instrument
|
||||
@ -34,7 +32,7 @@ Here's a quick overview of the stuff you can find in this directory:
|
||||
mode to speed up certain fuzzing jobs.
|
||||
|
||||
- post_library - an example of how to build postprocessors for AFL.
|
||||
|
||||
|
||||
- socket_fuzzing - a LD_PRELOAD library 'redirects' a socket to stdin
|
||||
for fuzzing access with afl++
|
||||
|
||||
|
51
examples/argv_fuzzing/GNUmakefile
Normal file
51
examples/argv_fuzzing/GNUmakefile
Normal file
@ -0,0 +1,51 @@
|
||||
#
|
||||
# american fuzzy lop++ - argvfuzz
|
||||
# --------------------------------
|
||||
#
|
||||
# Copyright 2019-2020 Kjell Braden <afflux@pentabarf.de>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
CFLAGS = -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# on gcc for arm there is no -m32, but -mbe32
|
||||
M32FLAG = -m32
|
||||
M64FLAG = -m64
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
|
||||
M32FLAG = -mbe32
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
all: argvfuzz32.so argvfuzz64.so
|
||||
|
||||
argvfuzz32.so: argvfuzz.c
|
||||
-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
|
||||
|
||||
argvfuzz64.so: argvfuzz.c
|
||||
-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz64 build failure (that's fine)"
|
||||
|
||||
install: argvfuzz32.so argvfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
|
||||
clean:
|
||||
rm -f argvfuzz32.so argvfuzz64.so
|
@ -1,51 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - argvfuzz
|
||||
# --------------------------------
|
||||
#
|
||||
# Copyright 2019-2020 Kjell Braden <afflux@pentabarf.de>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
CFLAGS = -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# on gcc for arm there is no -m32, but -mbe32
|
||||
M32FLAG = -m32
|
||||
M64FLAG = -m64
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
|
||||
M32FLAG = -mbe32
|
||||
endif
|
||||
endif
|
||||
|
||||
|
||||
all: argvfuzz32.so argvfuzz64.so
|
||||
|
||||
argvfuzz32.so: argvfuzz.c
|
||||
-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
|
||||
|
||||
argvfuzz64.so: argvfuzz.c
|
||||
-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz64 build failure (that's fine)"
|
||||
|
||||
install: argvfuzz32.so argvfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
if [ -f argvfuzz64.so ]; then set -e; install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
|
||||
clean:
|
||||
rm -f argvfuzz32.so argvfuzz64.so
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
@ -1,2 +1,7 @@
|
||||
all:
|
||||
$(CC) $(CFLAGS) -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so
|
||||
all: libexamplemutator.so
|
||||
|
||||
libexamplemutator.so:
|
||||
$(CC) $(CFLAGS) -D_FORTIFY_SOURCE=2 -O3 -fPIC -shared -g -I ../../include example.c -o libexamplemutator.so
|
||||
|
||||
clean:
|
||||
rm -rf libexamplemutator.so
|
||||
|
@ -1,10 +1,10 @@
|
||||
# Examples for the custom mutator
|
||||
|
||||
These are example and helper files for the custom mutator feature.
|
||||
See [docs/python_mutators.md](../docs/custom_mutators.md) for more information
|
||||
See [docs/custom_mutators.md](../docs/custom_mutators.md) for more information
|
||||
|
||||
Note that if you compile with python3.7 you must use python3 scripts, and if
|
||||
you use pyton2.7 to compile python2 scripts!
|
||||
you use python2.7 to compile python2 scripts!
|
||||
|
||||
example.c - this is a simple example written in C and should be compiled to a
|
||||
shared library. Use make to compile it and produce libexamplemutator.so
|
||||
|
@ -5,13 +5,25 @@
|
||||
#include "types.h"
|
||||
#include <stdlib.h>
|
||||
|
||||
#define INITIAL_GROWTH_SIZE (64)
|
||||
|
||||
#define RAND_BELOW(limit) (rand() % (limit))
|
||||
|
||||
typedef struct{} afl_t;
|
||||
/* Use in a struct: creates a name_buf and a name_size variable. */
|
||||
#define BUF_VAR(type, name) \
|
||||
type * name##_buf; \
|
||||
size_t name##_size;
|
||||
/* this filles in `&structptr->something_buf, &structptr->something_size`. */
|
||||
#define BUF_PARAMS(struct, name) \
|
||||
(void **)&struct->name##_buf, &struct->name##_size
|
||||
|
||||
typedef struct {
|
||||
|
||||
} afl_t;
|
||||
|
||||
static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
|
||||
|
||||
static s8 interesting_8[] = {INTERESTING_8};
|
||||
static s8 interesting_8[] = {INTERESTING_8};
|
||||
static s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
static s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
|
||||
@ -111,8 +123,8 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
|
||||
(s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)];
|
||||
break;
|
||||
case 1:
|
||||
*(u64 *)(out_buf + byte_idx) =
|
||||
SWAP64((s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
|
||||
*(u64 *)(out_buf + byte_idx) = SWAP64(
|
||||
(s64)interesting_32[RAND_BELOW(sizeof(interesting_32) >> 2)]);
|
||||
break;
|
||||
|
||||
}
|
||||
@ -265,4 +277,66 @@ static void surgical_havoc_mutate(u8 *out_buf, s32 begin, s32 end) {
|
||||
|
||||
}
|
||||
|
||||
/* This function calculates the next power of 2 greater or equal its argument.
|
||||
@return The rounded up power of 2 (if no overflow) or 0 on overflow.
|
||||
*/
|
||||
static inline size_t next_pow2(size_t in) {
|
||||
|
||||
if (in == 0 || in > (size_t)-1)
|
||||
return 0; /* avoid undefined behaviour under-/overflow */
|
||||
size_t out = in - 1;
|
||||
out |= out >> 1;
|
||||
out |= out >> 2;
|
||||
out |= out >> 4;
|
||||
out |= out >> 8;
|
||||
out |= out >> 16;
|
||||
return out + 1;
|
||||
|
||||
}
|
||||
|
||||
/* This function makes sure *size is > size_needed after call.
|
||||
It will realloc *buf otherwise.
|
||||
*size will grow exponentially as per:
|
||||
https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
|
||||
Will return NULL and free *buf if size_needed is <1 or realloc failed.
|
||||
@return For convenience, this function returns *buf.
|
||||
*/
|
||||
static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
|
||||
|
||||
/* No need to realloc */
|
||||
if (likely(size_needed && *size >= size_needed)) return *buf;
|
||||
|
||||
/* No initial size was set */
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
|
||||
|
||||
/* grow exponentially */
|
||||
size_t next_size = next_pow2(size_needed);
|
||||
|
||||
/* handle overflow */
|
||||
if (!next_size) { next_size = size_needed; }
|
||||
|
||||
/* alloc */
|
||||
*buf = realloc(*buf, next_size);
|
||||
*size = *buf ? next_size : 0;
|
||||
|
||||
return *buf;
|
||||
|
||||
}
|
||||
|
||||
/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
|
||||
static inline void swap_bufs(void **buf1, size_t *size1, void **buf2,
|
||||
size_t *size2) {
|
||||
|
||||
void * scratch_buf = *buf1;
|
||||
size_t scratch_size = *size1;
|
||||
*buf1 = *buf2;
|
||||
*size1 = *size2;
|
||||
*buf2 = scratch_buf;
|
||||
*size2 = scratch_size;
|
||||
|
||||
}
|
||||
|
||||
#undef INITIAL_GROWTH_SIZE
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#define DATA_SIZE (100)
|
||||
|
||||
@ -23,32 +24,47 @@ static const char *commands[] = {
|
||||
|
||||
};
|
||||
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_t *afl;
|
||||
|
||||
// any additional data here!
|
||||
size_t trim_size_current;
|
||||
int trimmming_steps;
|
||||
int cur_step;
|
||||
|
||||
// Reused buffers:
|
||||
BUF_VAR(u8, fuzz);
|
||||
BUF_VAR(u8, data);
|
||||
BUF_VAR(u8, havoc);
|
||||
BUF_VAR(u8, trim);
|
||||
BUF_VAR(u8, pre_save);
|
||||
|
||||
} my_mutator_t;
|
||||
|
||||
/**
|
||||
* Initialize this custom mutator
|
||||
*
|
||||
* @param[in] afl a pointer to the internal state object. Can be ignored for now.
|
||||
* @param[in] seed A seed for this mutator - the same seed should always mutate in the same way.
|
||||
* @param[in] afl a pointer to the internal state object. Can be ignored for
|
||||
* now.
|
||||
* @param[in] seed A seed for this mutator - the same seed should always mutate
|
||||
* in the same way.
|
||||
* @return Pointer to the data object this custom mutator instance should use.
|
||||
* There may be multiple instances of this mutator in one afl-fuzz run!
|
||||
* Returns NULL on error.
|
||||
* Return NULL on error.
|
||||
*/
|
||||
my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
|
||||
|
||||
srand(seed); // needed also by surgical_havoc_mutate()
|
||||
srand(seed); // needed also by surgical_havoc_mutate()
|
||||
|
||||
my_mutator_t *data = calloc(1, sizeof(my_mutator_t));
|
||||
if (!data) {
|
||||
|
||||
perror("afl_custom_init alloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
data->afl = afl;
|
||||
|
||||
return data;
|
||||
@ -63,14 +79,16 @@ my_mutator_t *afl_custom_init(afl_t *afl, unsigned int seed) {
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[in] buf Pointer to input data to be mutated
|
||||
* @param[in] buf_size Size of input data
|
||||
* @param[out] out_buf the buffer we will work on. we can reuse *buf. NULL on
|
||||
* error.
|
||||
* @param[in] add_buf Buffer containing the additional test case
|
||||
* @param[in] add_buf_size Size of the additional test case
|
||||
* @param[in] max_size Maximum size of the mutated output. The mutation must not
|
||||
* produce data larger than max_size.
|
||||
* @return Size of the mutated output.
|
||||
*/
|
||||
size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
|
||||
uint8_t *add_buf,
|
||||
size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
u8 **out_buf, uint8_t *add_buf,
|
||||
size_t add_buf_size, // add_buf can be NULL
|
||||
size_t max_size) {
|
||||
|
||||
@ -78,9 +96,15 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
|
||||
// the fuzzer
|
||||
size_t mutated_size = DATA_SIZE <= max_size ? DATA_SIZE : max_size;
|
||||
|
||||
if (mutated_size > buf_size) *buf = realloc(*buf, mutated_size);
|
||||
// maybe_grow is optimized to be quick for reused buffers.
|
||||
u8 *mutated_out = maybe_grow(BUF_PARAMS(data, fuzz), mutated_size);
|
||||
if (!mutated_out) {
|
||||
|
||||
uint8_t *mutated_out = *buf;
|
||||
*out_buf = NULL;
|
||||
perror("custom mutator allocation (maybe_grow)");
|
||||
return 0; /* afl-fuzz will very likely error out after this. */
|
||||
|
||||
}
|
||||
|
||||
// Randomly select a command string to add as a header to the packet
|
||||
memcpy(mutated_out, commands[rand() % 3], 3);
|
||||
@ -94,6 +118,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
|
||||
|
||||
}
|
||||
|
||||
*out_buf = mutated_out;
|
||||
return mutated_size;
|
||||
|
||||
}
|
||||
@ -109,29 +134,36 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t **buf, size_t buf_size,
|
||||
* @param[in] buf Buffer containing the test case to be executed
|
||||
* @param[in] buf_size Size of the test case
|
||||
* @param[out] out_buf Pointer to the buffer containing the test case after
|
||||
* processing. External library should allocate memory for out_buf. AFL++
|
||||
* will release the memory after saving the test case.
|
||||
* @return Size of the output buffer after processing
|
||||
* processing. External library should allocate memory for out_buf.
|
||||
* The buf pointer may be reused (up to the given buf_size);
|
||||
* @return Size of the output buffer after processing or the needed amount.
|
||||
* A return of 0 indicates an error.
|
||||
*/
|
||||
size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size, uint8_t **out_buf) {
|
||||
size_t afl_custom_pre_save(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
uint8_t **out_buf) {
|
||||
|
||||
size_t out_buf_size;
|
||||
uint8_t *pre_save_buf = maybe_grow(BUF_PARAMS(data, pre_save), buf_size + 5);
|
||||
if (!pre_save_buf) {
|
||||
|
||||
out_buf_size = buf_size;
|
||||
perror("custom mutator realloc failed.");
|
||||
*out_buf = NULL;
|
||||
return 0;
|
||||
|
||||
// External mutator should allocate memory for `out_buf`
|
||||
*out_buf = malloc(out_buf_size);
|
||||
memcpy(*out_buf, buf, out_buf_size);
|
||||
}
|
||||
|
||||
return out_buf_size;
|
||||
memcpy(pre_save_buf + 5, buf, buf_size);
|
||||
pre_save_buf[0] = 'A';
|
||||
pre_save_buf[1] = 'F';
|
||||
pre_save_buf[2] = 'L';
|
||||
pre_save_buf[3] = '+';
|
||||
pre_save_buf[4] = '+';
|
||||
|
||||
*out_buf = pre_save_buf;
|
||||
|
||||
return buf_size + 5;
|
||||
|
||||
}
|
||||
|
||||
static uint8_t *trim_buf;
|
||||
static size_t trim_buf_size;
|
||||
static int trimmming_steps;
|
||||
static int cur_step;
|
||||
|
||||
/**
|
||||
* This method is called at the start of each trimming operation and receives
|
||||
* the initial buffer. It should return the amount of iteration steps possible
|
||||
@ -151,25 +183,36 @@ static int cur_step;
|
||||
* @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 possible iteration steps to trim the input
|
||||
* @return The amount of possible iteration steps to trim the input.
|
||||
* negative on error.
|
||||
*/
|
||||
int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) {
|
||||
int32_t afl_custom_init_trim(my_mutator_t *data, uint8_t *buf,
|
||||
size_t buf_size) {
|
||||
|
||||
// We simply trim once
|
||||
trimmming_steps = 1;
|
||||
data->trimmming_steps = 1;
|
||||
|
||||
cur_step = 0;
|
||||
trim_buf = buf;
|
||||
trim_buf_size = buf_size;
|
||||
data->cur_step = 0;
|
||||
|
||||
return trimmming_steps;
|
||||
if (!maybe_grow(BUF_PARAMS(data, trim), buf_size)) {
|
||||
|
||||
perror("init_trim grow");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
memcpy(data->trim_buf, buf, buf_size);
|
||||
|
||||
data->trim_size_current = buf_size;
|
||||
|
||||
return data->trimmming_steps;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is called for each trimming operation. It doesn't have any
|
||||
* arguments because we already have the initial buffer from init_trim and we
|
||||
* can memorize the current state in global variables. This can also save
|
||||
* can memorize the current state in *data. This can also save
|
||||
* reparsing steps for each iteration. It should return the trimmed input
|
||||
* buffer, where the returned data must not exceed the initial input data in
|
||||
* length. Returning anything that is larger than the original data (passed
|
||||
@ -179,18 +222,18 @@ int afl_custom_init_trim(my_mutator_t *data, uint8_t *buf, size_t buf_size) {
|
||||
*
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[out] out_buf Pointer to the buffer containing the trimmed test case.
|
||||
* External library should allocate memory for out_buf. AFL++ will release
|
||||
* the memory after saving the test case.
|
||||
* @param[out] out_buf_size Pointer to the size of the trimmed test case
|
||||
* External library should allocate memory for out_buf.
|
||||
* AFL++ will not release the memory after saving the test case.
|
||||
* Keep a ref in *data.
|
||||
* *out_buf = NULL is treated as error.
|
||||
* @return Pointer to the size of the trimmed test case
|
||||
*/
|
||||
void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, size_t *out_buf_size) {
|
||||
size_t afl_custom_trim(my_mutator_t *data, uint8_t **out_buf) {
|
||||
|
||||
*out_buf_size = trim_buf_size - 1;
|
||||
*out_buf = data->trim_buf;
|
||||
|
||||
// External mutator should allocate memory for `out_buf`
|
||||
*out_buf = malloc(*out_buf_size);
|
||||
// Remove the last byte of the trimming input
|
||||
memcpy(*out_buf, trim_buf, *out_buf_size);
|
||||
return data->trim_size_current - 1;
|
||||
|
||||
}
|
||||
|
||||
@ -204,18 +247,18 @@ void afl_custom_trim(my_mutator_t *data, uint8_t **out_buf, size_t *out_buf_size
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param success Indicates if the last trim operation was successful.
|
||||
* @return The next trim iteration index (from 0 to the maximum amount of
|
||||
* steps returned in init_trim)
|
||||
* steps returned in init_trim). negative ret on failure.
|
||||
*/
|
||||
int afl_custom_post_trim(my_mutator_t *data, int success) {
|
||||
int32_t afl_custom_post_trim(my_mutator_t *data, int success) {
|
||||
|
||||
if (success) {
|
||||
|
||||
++cur_step;
|
||||
return cur_step;
|
||||
++data->cur_step;
|
||||
return data->cur_step;
|
||||
|
||||
}
|
||||
|
||||
return trimmming_steps;
|
||||
return data->trimmming_steps;
|
||||
|
||||
}
|
||||
|
||||
@ -226,26 +269,40 @@ int afl_custom_post_trim(my_mutator_t *data, int success) {
|
||||
* (Optional)
|
||||
*
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[inout] buf Pointer to the input data to be mutated and the mutated
|
||||
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
||||
* output
|
||||
* @param[in] buf_size Size of input data
|
||||
* @param[out] out_buf The output buffer. buf can be reused, if the content
|
||||
* fits. *out_buf = NULL is treated as error.
|
||||
* @param[in] max_size Maximum size of the mutated output. The mutation must
|
||||
* not produce data larger than max_size.
|
||||
* @return Size of the mutated output.
|
||||
*/
|
||||
size_t afl_custom_havoc_mutation(my_mutator_t *data, uint8_t **buf, size_t buf_size,
|
||||
size_t max_size) {
|
||||
size_t afl_custom_havoc_mutation(my_mutator_t *data, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf, size_t max_size) {
|
||||
|
||||
if (buf_size == 0) {
|
||||
|
||||
*buf = realloc(*buf, 1);
|
||||
**buf = rand() % 256;
|
||||
*out_buf = maybe_grow(BUF_PARAMS(data, havoc), 1);
|
||||
if (!*out_buf) {
|
||||
|
||||
perror("custom havoc: maybe_grow");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
**out_buf = rand() % 256;
|
||||
buf_size = 1;
|
||||
|
||||
} else {
|
||||
|
||||
// We reuse buf here. It's legal and faster.
|
||||
*out_buf = buf;
|
||||
|
||||
}
|
||||
|
||||
size_t victim = rand() % buf_size;
|
||||
(*buf)[victim] += rand() % 10;
|
||||
(*out_buf)[victim] += rand() % 10;
|
||||
|
||||
return buf_size;
|
||||
|
||||
@ -292,7 +349,8 @@ uint8_t afl_custom_queue_get(my_mutator_t *data, const uint8_t *filename) {
|
||||
* @param filename_new_queue File name of the new queue entry
|
||||
* @param filename_orig_queue File name of the original queue entry
|
||||
*/
|
||||
void afl_custom_queue_new_entry(my_mutator_t *data, const uint8_t *filename_new_queue,
|
||||
void afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
/* Additional analysis on the original or new test case */
|
||||
@ -306,6 +364,11 @@ void afl_custom_queue_new_entry(my_mutator_t *data, const uint8_t *filename_new_
|
||||
*/
|
||||
void afl_custom_deinit(my_mutator_t *data) {
|
||||
|
||||
free(data->pre_save_buf);
|
||||
free(data->havoc_buf);
|
||||
free(data->data_buf);
|
||||
free(data->fuzz_buf);
|
||||
free(data->trim_buf);
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
@ -17,6 +17,13 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
import random
|
||||
|
||||
|
||||
COMMANDS = [
|
||||
b"GET",
|
||||
b"PUT",
|
||||
b"DEL",
|
||||
]
|
||||
|
||||
|
||||
def init(seed):
|
||||
'''
|
||||
Called once when AFLFuzz starts up. Used to seed our RNG.
|
||||
@ -27,6 +34,10 @@ def init(seed):
|
||||
random.seed(seed)
|
||||
|
||||
|
||||
def deinit():
|
||||
pass
|
||||
|
||||
|
||||
def fuzz(buf, add_buf, max_size):
|
||||
'''
|
||||
Called per fuzzing iteration.
|
||||
@ -44,8 +55,9 @@ def fuzz(buf, add_buf, max_size):
|
||||
@rtype: bytearray
|
||||
@return: A new bytearray containing the mutated data
|
||||
'''
|
||||
ret = bytearray(buf)
|
||||
# Do something interesting with ret
|
||||
ret = bytearray(100)
|
||||
|
||||
ret[:3] = random.choice(COMMANDS)
|
||||
|
||||
return ret
|
||||
|
||||
@ -164,11 +176,10 @@ def fuzz(buf, add_buf, max_size):
|
||||
# '''
|
||||
# Called after adding a new test case to the queue
|
||||
#
|
||||
# @type filename_new_queue: str
|
||||
# @type filename_new_queue: str
|
||||
# @param filename_new_queue: File name of the new queue entry
|
||||
#
|
||||
# @type filename_orig_queue: str
|
||||
# @param filename_orig_queue: File name of the original queue entry
|
||||
# '''
|
||||
# pass
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
--------------------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
Edited by Dominik Maier, 2020
|
||||
|
||||
Copyright 2015 Google Inc. All rights reserved.
|
||||
|
||||
@ -41,22 +42,23 @@
|
||||
AFL will call the afl_postprocess() function for every mutated output buffer.
|
||||
From there, you have three choices:
|
||||
|
||||
1) If you don't want to modify the test case, simply return the original
|
||||
buffer pointer ('in_buf').
|
||||
1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
|
||||
and return the original `len`.
|
||||
|
||||
2) If you want to skip this test case altogether and have AFL generate a
|
||||
new one, return NULL. Use this sparingly - it's faster than running
|
||||
the target program with patently useless inputs, but still wastes CPU
|
||||
time.
|
||||
new one, return 0 or set `*out_buf = NULL`.
|
||||
Use this sparingly - it's faster than running the target program
|
||||
with patently useless inputs, but still wastes CPU time.
|
||||
|
||||
3) If you want to modify the test case, allocate an appropriately-sized
|
||||
buffer, move the data into that buffer, make the necessary changes, and
|
||||
then return the new pointer. You can update *len if necessary, too.
|
||||
then return the new pointer as out_buf. Return an appropriate len
|
||||
afterwards.
|
||||
|
||||
Note that the buffer will *not* be freed for you. To avoid memory leaks,
|
||||
you need to free it or reuse it on subsequent calls (as shown below).
|
||||
|
||||
*** DO NOT MODIFY THE ORIGINAL 'in_buf' BUFFER. ***
|
||||
*** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
|
||||
|
||||
Aight. The example below shows a simple postprocessor that tries to make
|
||||
sure that all input files start with "GIF89a".
|
||||
@ -74,47 +76,84 @@
|
||||
|
||||
#define HEADER "GIF89a"
|
||||
|
||||
typedef struct post_state {
|
||||
|
||||
unsigned char *buf;
|
||||
size_t size;
|
||||
|
||||
} post_state_t;
|
||||
|
||||
void *afl_postprocess_init(void *afl) {
|
||||
|
||||
post_state_t *state = malloc(sizeof(post_state_t));
|
||||
if (!state) {
|
||||
|
||||
perror("malloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
state->buf = calloc(sizeof(unsigned char), 4096);
|
||||
if (!state->buf) { return NULL; }
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
/* The actual postprocessor routine called by afl-fuzz: */
|
||||
|
||||
const unsigned char *afl_postprocess(const unsigned char *in_buf,
|
||||
unsigned int * len) {
|
||||
|
||||
static unsigned char *saved_buf;
|
||||
unsigned char * new_buf;
|
||||
size_t afl_postprocess(post_state_t *data, unsigned char *in_buf,
|
||||
unsigned int len, unsigned char **out_buf) {
|
||||
|
||||
/* Skip execution altogether for buffers shorter than 6 bytes (just to
|
||||
show how it's done). We can trust *len to be sane. */
|
||||
show how it's done). We can trust len to be sane. */
|
||||
|
||||
if (*len < strlen(HEADER)) return NULL;
|
||||
if (len < strlen(HEADER)) return 0;
|
||||
|
||||
/* Do nothing for buffers that already start with the expected header. */
|
||||
|
||||
if (!memcmp(in_buf, HEADER, strlen(HEADER))) return in_buf;
|
||||
if (!memcmp(in_buf, HEADER, strlen(HEADER))) {
|
||||
|
||||
*out_buf = in_buf;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/* Allocate memory for new buffer, reusing previous allocation if
|
||||
possible. */
|
||||
|
||||
new_buf = realloc(saved_buf, *len);
|
||||
*out_buf = realloc(data->buf, len);
|
||||
|
||||
/* If we're out of memory, the most graceful thing to do is to return the
|
||||
original buffer and give up on modifying it. Let AFL handle OOM on its
|
||||
own later on. */
|
||||
|
||||
if (!new_buf) return in_buf;
|
||||
saved_buf = new_buf;
|
||||
if (!*out_buf) {
|
||||
|
||||
*out_buf = in_buf;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/* Copy the original data to the new location. */
|
||||
|
||||
memcpy(new_buf, in_buf, *len);
|
||||
memcpy(*out_buf, in_buf, len);
|
||||
|
||||
/* Insert the new header. */
|
||||
|
||||
memcpy(new_buf, HEADER, strlen(HEADER));
|
||||
memcpy(*out_buf, HEADER, strlen(HEADER));
|
||||
|
||||
/* Return modified buffer. No need to update *len in this particular case,
|
||||
as we're not changing it. */
|
||||
/* Return the new len. It hasn't changed, so it's just len. */
|
||||
|
||||
return new_buf;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/* Gets called afterwards */
|
||||
void afl_postprocess_deinit(post_state_t *data) {
|
||||
|
||||
free(data->buf);
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
||||
|
@ -5,6 +5,7 @@
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Copyright 2015 Google Inc. All rights reserved.
|
||||
Adapted to the new API, 2020 by Dominik Maier
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@ -35,11 +36,32 @@
|
||||
|
||||
#define UP4K(_i) ((((_i) >> 12) + 1) << 12)
|
||||
|
||||
const unsigned char *afl_postprocess(const unsigned char *in_buf,
|
||||
unsigned int * len) {
|
||||
typedef struct post_state {
|
||||
|
||||
static unsigned char *saved_buf;
|
||||
static unsigned int saved_len;
|
||||
unsigned char *buf;
|
||||
size_t size;
|
||||
|
||||
} post_state_t;
|
||||
|
||||
void *afl_postprocess_init(void *afl) {
|
||||
|
||||
post_state_t *state = malloc(sizeof(post_state_t));
|
||||
if (!state) {
|
||||
|
||||
perror("malloc");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
state->buf = calloc(sizeof(unsigned char), 4096);
|
||||
if (!state->buf) { return NULL; }
|
||||
|
||||
return state;
|
||||
|
||||
}
|
||||
|
||||
size_t afl_postprocess(post_state_t *data, const unsigned char *in_buf,
|
||||
unsigned int len, const unsigned char **out_buf) {
|
||||
|
||||
unsigned char *new_buf = (unsigned char *)in_buf;
|
||||
unsigned int pos = 8;
|
||||
@ -47,12 +69,17 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
|
||||
/* Don't do anything if there's not enough room for the PNG header
|
||||
(8 bytes). */
|
||||
|
||||
if (*len < 8) return in_buf;
|
||||
if (len < 8) {
|
||||
|
||||
*out_buf = in_buf;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/* Minimum size of a zero-length PNG chunk is 12 bytes; if we
|
||||
don't have that, we can bail out. */
|
||||
|
||||
while (pos + 12 <= *len) {
|
||||
while (pos + 12 <= len) {
|
||||
|
||||
unsigned int chunk_len, real_cksum, file_cksum;
|
||||
|
||||
@ -62,7 +89,7 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
|
||||
|
||||
/* Bail out if chunk size is too big or goes past EOF. */
|
||||
|
||||
if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > *len) break;
|
||||
if (chunk_len > 1024 * 1024 || pos + 12 + chunk_len > len) break;
|
||||
|
||||
/* Chunk checksum is calculated for chunk ID (dword) and the actual
|
||||
payload. */
|
||||
@ -82,17 +109,23 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
|
||||
|
||||
if (new_buf == in_buf) {
|
||||
|
||||
if (*len <= saved_len) {
|
||||
if (len <= data->size) {
|
||||
|
||||
new_buf = saved_buf;
|
||||
new_buf = data->buf;
|
||||
|
||||
} else {
|
||||
|
||||
new_buf = realloc(saved_buf, UP4K(*len));
|
||||
if (!new_buf) return in_buf;
|
||||
saved_buf = new_buf;
|
||||
saved_len = UP4K(*len);
|
||||
memcpy(new_buf, in_buf, *len);
|
||||
new_buf = realloc(data->buf, UP4K(len));
|
||||
if (!new_buf) {
|
||||
|
||||
*out_buf = in_buf;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
data->buf = new_buf;
|
||||
data->size = UP4K(len);
|
||||
memcpy(new_buf, in_buf, len);
|
||||
|
||||
}
|
||||
|
||||
@ -108,7 +141,16 @@ const unsigned char *afl_postprocess(const unsigned char *in_buf,
|
||||
|
||||
}
|
||||
|
||||
return new_buf;
|
||||
*out_buf = new_buf;
|
||||
return len;
|
||||
|
||||
}
|
||||
|
||||
/* Gets called afterwards */
|
||||
void afl_postprocess_deinit(post_state_t *data) {
|
||||
|
||||
free(data->buf);
|
||||
free(data);
|
||||
|
||||
}
|
||||
|
||||
|
48
examples/socket_fuzzing/GNUmakefile
Normal file
48
examples/socket_fuzzing/GNUmakefile
Normal file
@ -0,0 +1,48 @@
|
||||
#
|
||||
# american fuzzy lop++ - socket_fuzz
|
||||
# ----------------------------------
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
CFLAGS = -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# on gcc for arm there is no -m32, but -mbe32
|
||||
M32FLAG = -m32
|
||||
M64FLAG = -m64
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
|
||||
M32FLAG = -mbe32
|
||||
endif
|
||||
endif
|
||||
|
||||
all: socketfuzz32.so socketfuzz64.so
|
||||
|
||||
socketfuzz32.so: socketfuzz.c
|
||||
-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
|
||||
|
||||
socketfuzz64.so: socketfuzz.c
|
||||
-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz64 build failure (that's fine)"
|
||||
|
||||
install: socketfuzz32.so socketfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
if [ -f socketfuzz64.so ]; then set -e; install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
|
||||
clean:
|
||||
rm -f socketfuzz32.so socketfuzz64.so
|
@ -1,48 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - socket_fuzz
|
||||
# ----------------------------------
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
CFLAGS = -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
|
||||
# on gcc for arm there is no -m32, but -mbe32
|
||||
M32FLAG = -m32
|
||||
M64FLAG = -m64
|
||||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifneq (,$(findstring arm, "$(shell $(CC) -v 2>&1 >/dev/null)"))
|
||||
M32FLAG = -mbe32
|
||||
endif
|
||||
endif
|
||||
|
||||
all: socketfuzz32.so socketfuzz64.so
|
||||
|
||||
socketfuzz32.so: socketfuzz.c
|
||||
-$(CC) $(M32FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
|
||||
|
||||
socketfuzz64.so: socketfuzz.c
|
||||
-$(CC) $(M64FLAG) $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz64 build failure (that's fine)"
|
||||
|
||||
install: socketfuzz32.so socketfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
if [ -f socketfuzz64.so ]; then set -e; install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
|
||||
clean:
|
||||
rm -f socketfuzz32.so socketfuzz64.so
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
160
gcc_plugin/GNUmakefile
Normal file
160
gcc_plugin/GNUmakefile
Normal file
@ -0,0 +1,160 @@
|
||||
#
|
||||
# american fuzzy lop++ - GCC plugin instrumentation
|
||||
# -----------------------------------------------
|
||||
#
|
||||
# Written by Austin Seipp <aseipp@pobox.com> and
|
||||
# Laszlo Szekeres <lszekeres@google.com> and
|
||||
# Michal Zalewski and
|
||||
# Heiko Eißfeldt <heiko@hexco.de>
|
||||
#
|
||||
# GCC integration design is based on the LLVM design, which comes
|
||||
# from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH ?= $(PREFIX)/lib/afl
|
||||
BIN_PATH ?= $(PREFIX)/bin
|
||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||
MAN_PATH ?= $(PREFIX)/man/man8
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
||||
override CFLAGS = -Wall -I../include -Wno-pointer-sign \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
|
||||
-Wno-unused-function
|
||||
|
||||
CXXFLAGS ?= -O3 -g -funroll-loops -D_FORTIFY_SOURCE=2
|
||||
CXXEFLAGS := $(CXXFLAGS) -Wall
|
||||
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
|
||||
ifeq "clang" "$(CC)"
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
|
||||
ifeq "clang++" "$(CXX)"
|
||||
CC = gcc
|
||||
CXX = g++
|
||||
endif
|
||||
|
||||
PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
|
||||
HASH=\#
|
||||
|
||||
GCCVER = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
|
||||
GCCBINDIR = $(shell dirname `command -v $(CC)` 2>/dev/null )
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
PROGS = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
|
||||
|
||||
|
||||
all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
test_deps:
|
||||
@echo "[*] Checking for working '$(CC)'..."
|
||||
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||
# @echo "[*] Checking for gcc for plugin support..."
|
||||
# @$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
|
||||
@echo "[*] Checking for gcc plugin development header files..."
|
||||
@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
|
||||
@echo "[*] Checking for '../afl-showmap'..."
|
||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
afl-common.o: ../src/afl-common.c
|
||||
$(CC) $(CFLAGS) -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)
|
||||
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) -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_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
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
all_done: test_build
|
||||
@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
vpath % ..
|
||||
%.8: %
|
||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
|
||||
@echo .SH NAME >> ../$@
|
||||
@echo .B $* >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH SYNOPSIS >> ../$@
|
||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH OPTIONS >> ../$@
|
||||
@echo .nf >> ../$@
|
||||
@../$* -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 >> ../$@
|
||||
@echo .SH LICENSE >> ../$@
|
||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
||||
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
|
||||
|
||||
install: all
|
||||
install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
|
||||
install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
||||
install -m 644 -T README.whitelist.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.whitelist.md
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
||||
rm -f $(PROGS) afl-common.o ../afl-g++-fast ../afl-g*-fast.8
|
@ -1,150 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - GCC plugin instrumentation
|
||||
# -----------------------------------------------
|
||||
#
|
||||
# Written by Austin Seipp <aseipp@pobox.com> and
|
||||
# Laszlo Szekeres <lszekeres@google.com> and
|
||||
# Michal Zalewski and
|
||||
# Heiko Eißfeldt <heiko@hexco.de>
|
||||
#
|
||||
# GCC integration design is based on the LLVM design, which comes
|
||||
# from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015 Google Inc. All rights reserved.
|
||||
# Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH ?= $(PREFIX)/lib/afl
|
||||
BIN_PATH ?= $(PREFIX)/bin
|
||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||
MAN_PATH ?= $(PREFIX)/man/man8
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -g -funroll-loops
|
||||
CFLAGS += -Wall -I../include -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DGCC_VERSION=\"$(GCCVER)\" -DGCC_BINDIR=\"$(GCCBINDIR)\" \
|
||||
-Wno-unused-function
|
||||
|
||||
CXXFLAGS ?= -O3 -g -funroll-loops
|
||||
CXXEFLAGS := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2
|
||||
|
||||
CC ?= gcc
|
||||
CXX ?= g++
|
||||
|
||||
PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
|
||||
HASH=\#
|
||||
|
||||
GCCVER = $(shell $(CC) --version 2>/dev/null | awk 'NR == 1 {print $$NF}')
|
||||
GCCBINDIR = $(shell dirname `command -v $(CC)` 2>/dev/null )
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
PROGS = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
|
||||
|
||||
|
||||
all: test_shm test_deps $(PROGS) afl-gcc-fast.8 test_build all_done
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
|
||||
test_deps:
|
||||
@echo "[*] Checking for working '$(CC)'..."
|
||||
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||
# @echo "[*] Checking for gcc for plugin support..."
|
||||
# @$(CC) -v 2>&1 | grep -q -- --enable-plugin || ( echo "[-] Oops, this gcc has not been configured with plugin support."; exit 1 )
|
||||
@echo "[*] Checking for gcc plugin development header files..."
|
||||
@test -d `$(CC) -print-file-name=plugin`/include || ( echo "[-] Oops, can't find gcc header files. Be sure to install 'gcc-X-plugin-dev'."; exit 1 )
|
||||
@echo "[*] Checking for '../afl-showmap'..."
|
||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
afl-common.o: ../src/afl-common.c
|
||||
$(CC) $(CFLAGS) -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)
|
||||
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) -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_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
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
all_done: test_build
|
||||
@echo "[+] All done! You can now use '../afl-gcc-fast' to compile programs."
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
vpath % ..
|
||||
%.8: %
|
||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
|
||||
@echo .SH NAME >> ../$@
|
||||
@echo .B $* >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH SYNOPSIS >> ../$@
|
||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH OPTIONS >> ../$@
|
||||
@echo .nf >> ../$@
|
||||
@../$* -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 >> ../$@
|
||||
@echo .SH LICENSE >> ../$@
|
||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
||||
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
|
||||
|
||||
install: all
|
||||
install -m 755 ../afl-gcc-fast $${DESTDIR}$(BIN_PATH)
|
||||
install -m 755 ../afl-gcc-pass.so ../afl-gcc-rt.o $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.md
|
||||
install -m 644 -T README.whitelist.md $${DESTDIR}$(DOC_PATH)/README.gcc_plugin.whitelist.md
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
||||
rm -f $(PROGS) afl-common.o ../afl-g++-fast ../afl-g*-fast.8
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
@ -41,7 +41,6 @@ static u8 * obj_path; /* Path to runtime libraries */
|
||||
static u8 **cc_params; /* Parameters passed to the real CC */
|
||||
static u32 cc_par_cnt = 1; /* Param count, including argv0 */
|
||||
u8 use_stdin = 0; /* dummy */
|
||||
u8 be_quiet;
|
||||
|
||||
/* Try to find the runtime libraries. If that fails, abort. */
|
||||
|
||||
|
@ -239,8 +239,6 @@ enum {
|
||||
|
||||
};
|
||||
|
||||
extern u8 *doc_path; /* gath to documentation dir */
|
||||
|
||||
/* Python stuff */
|
||||
#ifdef USE_PYTHON
|
||||
|
||||
@ -290,8 +288,20 @@ typedef struct py_mutator {
|
||||
|
||||
PyObject *py_module;
|
||||
PyObject *py_functions[PY_FUNC_COUNT];
|
||||
void *afl_state;
|
||||
void *py_data;
|
||||
void * afl_state;
|
||||
void * py_data;
|
||||
|
||||
u8 * fuzz_buf;
|
||||
size_t fuzz_size;
|
||||
|
||||
u8 * pre_save_buf;
|
||||
size_t pre_save_size;
|
||||
|
||||
u8 * trim_buf;
|
||||
size_t trim_size;
|
||||
|
||||
u8 * havoc_buf;
|
||||
size_t havoc_size;
|
||||
|
||||
} py_mutator_t;
|
||||
|
||||
@ -472,11 +482,6 @@ typedef struct afl_state {
|
||||
unique_tmouts, /* Timeouts with unique signatures */
|
||||
unique_hangs, /* Hangs with unique signatures */
|
||||
total_execs, /* Total execve() calls */
|
||||
slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||
start_time, /* Unix start time (ms) */
|
||||
last_path_time, /* Time for most recent path (ms) */
|
||||
last_crash_time, /* Time for most recent crash (ms) */
|
||||
last_hang_time, /* Time for most recent hang (ms) */
|
||||
last_crash_execs, /* Exec counter at last crash */
|
||||
queue_cycle, /* Queue round counter */
|
||||
cycles_wo_finds, /* Cycles without any new paths */
|
||||
@ -484,9 +489,14 @@ typedef struct afl_state {
|
||||
bytes_trim_in, /* Bytes coming into the trimmer */
|
||||
bytes_trim_out, /* Bytes coming outa the trimmer */
|
||||
blocks_eff_total, /* Blocks subject to effector maps */
|
||||
blocks_eff_select; /* Blocks selected as fuzzable */
|
||||
blocks_eff_select, /* Blocks selected as fuzzable */
|
||||
start_time, /* Unix start time (ms) */
|
||||
last_path_time, /* Time for most recent path (ms) */
|
||||
last_crash_time, /* Time for most recent crash (ms) */
|
||||
last_hang_time; /* Time for most recent hang (ms) */
|
||||
|
||||
u32 subseq_tmouts; /* Number of timeouts in a row */
|
||||
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||
subseq_tmouts; /* Number of timeouts in a row */
|
||||
|
||||
u8 *stage_name, /* Name of the current fuzz stage */
|
||||
*stage_short, /* Short stage name */
|
||||
@ -541,7 +551,11 @@ typedef struct afl_state {
|
||||
struct extra_data *a_extras; /* Automatically selected extras */
|
||||
u32 a_extras_cnt; /* Total number of tokens available */
|
||||
|
||||
u8 *(*post_handler)(u8 *buf, u32 *len);
|
||||
/* afl_postprocess API */
|
||||
void *(*post_init)(struct afl_state *afl);
|
||||
size_t (*post_handler)(void *data, u8 *buf, u32 len, u8 **out_buf);
|
||||
void *(*post_deinit)(void *data);
|
||||
void *post_data;
|
||||
|
||||
/* CmpLog */
|
||||
|
||||
@ -550,9 +564,6 @@ typedef struct afl_state {
|
||||
|
||||
/* Custom mutators */
|
||||
struct custom_mutator *mutator;
|
||||
#ifdef USE_PYTHON
|
||||
struct custom_mutator *py_mutator;
|
||||
#endif
|
||||
|
||||
/* cmplog forkserver ids */
|
||||
s32 cmplog_fsrv_ctl_fd, cmplog_fsrv_st_fd;
|
||||
@ -580,6 +591,26 @@ typedef struct afl_state {
|
||||
u8 clean_trace_custom[MAP_SIZE];
|
||||
u8 first_trace[MAP_SIZE];
|
||||
|
||||
/*needed for afl_fuzz_one */
|
||||
// TODO: see which we can reuse
|
||||
u8 * out_buf;
|
||||
size_t out_size;
|
||||
|
||||
u8 * out_scratch_buf;
|
||||
size_t out_scratch_size;
|
||||
|
||||
u8 * eff_buf;
|
||||
size_t eff_size;
|
||||
|
||||
u8 * in_buf;
|
||||
size_t in_size;
|
||||
|
||||
u8 * in_scratch_buf;
|
||||
size_t in_scratch_size;
|
||||
|
||||
u8 * ex_buf;
|
||||
size_t ex_size;
|
||||
|
||||
} afl_state_t;
|
||||
|
||||
/* A global pointer to all instances is needed (for now) for signals to arrive
|
||||
@ -591,8 +622,10 @@ struct custom_mutator {
|
||||
|
||||
const char *name;
|
||||
void * dh;
|
||||
u8 * pre_save_buf;
|
||||
size_t pre_save_size;
|
||||
|
||||
void *data; /* custom mutator data ptr */
|
||||
void *data; /* custom mutator data ptr */
|
||||
|
||||
/* hooks for the custom mutator function */
|
||||
|
||||
@ -611,16 +644,18 @@ struct custom_mutator {
|
||||
* (Optional for now. Required in the future)
|
||||
*
|
||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[inout] buf Pointer to the input data to be mutated and the mutated
|
||||
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
||||
* output
|
||||
* @param[in] buf_size Size of the input/output data
|
||||
* @param[out] out_buf the new buffer. We may reuse *buf if large enough.
|
||||
* *out_buf = NULL is treated as FATAL.
|
||||
* @param[in] add_buf Buffer containing the additional test case
|
||||
* @param[in] add_buf_size Size of the additional test case
|
||||
* @param[in] max_size Maximum size of the mutated output. The mutation must
|
||||
* not produce data larger than max_size.
|
||||
* @return Size of the mutated output.
|
||||
*/
|
||||
size_t (*afl_custom_fuzz)(void *data, u8 **buf, size_t buf_size,
|
||||
size_t (*afl_custom_fuzz)(void *data, u8 *buf, size_t buf_size, u8 **out_buf,
|
||||
u8 *add_buf, size_t add_buf_size, size_t max_size);
|
||||
|
||||
/**
|
||||
@ -633,10 +668,10 @@ struct custom_mutator {
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[in] buf Buffer containing the test case to be executed
|
||||
* @param[in] buf_size Size of the test case
|
||||
* @param[out] out_buf Pointer to the buffer of storing the test case after
|
||||
* processing. External library should allocate memory for out_buf. AFL++
|
||||
* will release the memory after saving the test case.
|
||||
* @return Size of the output buffer after processing
|
||||
* @param[out] out_buf Pointer to the buffer storing the test case after
|
||||
* processing. External library should allocate memory for out_buf.
|
||||
* It can chose to alter buf in-place, if the space is large enough.
|
||||
* @return Size of the output buffer.
|
||||
*/
|
||||
size_t (*afl_custom_pre_save)(void *data, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf);
|
||||
@ -660,9 +695,10 @@ struct custom_mutator {
|
||||
* @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 possible iteration steps to trim the input
|
||||
* @return The amount of possible iteration steps to trim the input.
|
||||
* Negative on error.
|
||||
*/
|
||||
u32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size);
|
||||
s32 (*afl_custom_init_trim)(void *data, u8 *buf, size_t buf_size);
|
||||
|
||||
/**
|
||||
* This method is called for each trimming operation. It doesn't have any
|
||||
@ -677,11 +713,11 @@ struct custom_mutator {
|
||||
*
|
||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[out] out_buf Pointer to the buffer containing the trimmed test case.
|
||||
* External library should allocate memory for out_buf. AFL++ will release
|
||||
* the memory after saving the test case.
|
||||
* @param[out] out_buf_size Pointer to the size of the trimmed test case
|
||||
* The library can reuse a buffer for each call
|
||||
* and will have to free the buf (for example in deinit)
|
||||
* @return the size of the trimmed test case
|
||||
*/
|
||||
void (*afl_custom_trim)(void *data, u8 **out_buf, size_t *out_buf_size);
|
||||
size_t (*afl_custom_trim)(void *data, u8 **out_buf);
|
||||
|
||||
/**
|
||||
* This method is called after each trim operation to inform you if your
|
||||
@ -693,9 +729,9 @@ struct custom_mutator {
|
||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param success Indicates if the last trim operation was successful.
|
||||
* @return The next trim iteration index (from 0 to the maximum amount of
|
||||
* steps returned in init_trim)
|
||||
* steps returned in init_trim). Negative on error.
|
||||
*/
|
||||
u32 (*afl_custom_post_trim)(void *data, u8 success);
|
||||
s32 (*afl_custom_post_trim)(void *data, u8 success);
|
||||
|
||||
/**
|
||||
* Perform a single custom mutation on a given input.
|
||||
@ -703,16 +739,18 @@ struct custom_mutator {
|
||||
*
|
||||
* (Optional)
|
||||
*
|
||||
* @param data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[inout] buf Pointer to the input data to be mutated and the mutated
|
||||
* @param[in] data pointer returned in afl_custom_init for this fuzz case
|
||||
* @param[in] buf Pointer to the input data to be mutated and the mutated
|
||||
* output
|
||||
* @param[in] buf_size Size of input data
|
||||
* @param[out] out_buf The new buffer. It's legal to reuse *buf if it's <
|
||||
* buf_size.
|
||||
* @param[in] max_size Maximum size of the mutated output. The mutation must
|
||||
* not produce data larger than max_size.
|
||||
* @return Size of the mutated output.
|
||||
* @return Size of the mutated output (out_size).
|
||||
*/
|
||||
size_t (*afl_custom_havoc_mutation)(void *data, u8 **buf,
|
||||
size_t buf_size, size_t max_size);
|
||||
size_t (*afl_custom_havoc_mutation)(void *data, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf, size_t max_size);
|
||||
|
||||
/**
|
||||
* Return the probability (in percentage) that afl_custom_havoc_mutation
|
||||
@ -748,9 +786,8 @@ struct custom_mutator {
|
||||
* @param filename_orig_queue File name of the original queue entry. This
|
||||
* argument can be NULL while initializing the fuzzer
|
||||
*/
|
||||
void (*afl_custom_queue_new_entry)(void *data,
|
||||
const u8 * filename_new_queue,
|
||||
const u8 * filename_orig_queue);
|
||||
void (*afl_custom_queue_new_entry)(void *data, const u8 *filename_new_queue,
|
||||
const u8 *filename_orig_queue);
|
||||
/**
|
||||
* Deinitialize the custom mutator.
|
||||
*
|
||||
@ -777,10 +814,10 @@ u8 trim_case_custom(afl_state_t *, struct queue_entry *q, u8 *in_buf);
|
||||
void finalize_py_module(void *);
|
||||
|
||||
size_t pre_save_py(void *, u8 *, size_t, u8 **);
|
||||
u32 init_trim_py(void *, u8 *, size_t);
|
||||
u32 post_trim_py(void *, u8);
|
||||
void trim_py(void *, u8 **, size_t *);
|
||||
size_t havoc_mutation_py(void *, u8 **, size_t, size_t);
|
||||
s32 init_trim_py(void *, u8 *, size_t);
|
||||
s32 post_trim_py(void *, u8);
|
||||
size_t trim_py(void *, u8 **);
|
||||
size_t havoc_mutation_py(void *, u8 *, size_t, u8 **, size_t);
|
||||
u8 havoc_mutation_probability_py(void *);
|
||||
u8 queue_get_py(void *, const u8 *);
|
||||
void queue_new_entry_py(void *, const u8 *, const u8 *);
|
||||
@ -898,13 +935,13 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
|
||||
static inline u32 rand_below(afl_state_t *afl, u32 limit) {
|
||||
|
||||
#ifdef HAVE_ARC4RANDOM
|
||||
if (afl->fixed_seed) { return random() % limit; }
|
||||
if (unlikely(afl->fixed_seed)) { return random() % limit; }
|
||||
|
||||
/* The boundary not being necessarily a power of 2,
|
||||
we need to ensure the result uniformity. */
|
||||
return arc4random_uniform(limit);
|
||||
#else
|
||||
if (!afl->fixed_seed && unlikely(!afl->rand_cnt--)) {
|
||||
if (unlikely(!afl->rand_cnt--) && likely(!afl->fixed_seed)) {
|
||||
|
||||
ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed),
|
||||
"/dev/urandom");
|
||||
@ -920,7 +957,7 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
|
||||
|
||||
static inline u32 get_rand_seed(afl_state_t *afl) {
|
||||
|
||||
if (afl->fixed_seed) return (u32)afl->init_seed;
|
||||
if (unlikely(afl->fixed_seed)) return (u32)afl->init_seed;
|
||||
return afl->rand_seed[0];
|
||||
|
||||
}
|
||||
@ -928,7 +965,7 @@ static inline u32 get_rand_seed(afl_state_t *afl) {
|
||||
/* Find first power of two greater or equal to val (assuming val under
|
||||
2^63). */
|
||||
|
||||
static u64 next_p2(u64 val) {
|
||||
static inline u64 next_p2(u64 val) {
|
||||
|
||||
u64 ret = 1;
|
||||
while (val > ret)
|
||||
|
@ -44,9 +44,8 @@ typedef enum prealloc_status {
|
||||
|
||||
/* Adds the entry used for prealloc bookkeeping to this struct */
|
||||
|
||||
#define PREALLOCABLE \
|
||||
; \
|
||||
pre_status_t pre_status; /* prealloc status of this instance */
|
||||
/* prealloc status of this instance */
|
||||
#define PREALLOCABLE pre_status_t pre_status
|
||||
|
||||
/* allocate an element of type *el_ptr, to this variable.
|
||||
Uses (and reuses) the given prealloc_buf before hitting libc's malloc.
|
||||
|
@ -35,6 +35,9 @@
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
||||
/* Initial size used for ck_maybe_grow */
|
||||
#define INITIAL_GROWTH_SIZE (64)
|
||||
|
||||
// Be careful! _WANT_ORIGINAL_AFL_ALLOC is not compatible with custom mutators
|
||||
|
||||
#ifndef _WANT_ORIGINAL_AFL_ALLOC
|
||||
@ -764,5 +767,99 @@ static inline void TRK_ck_free(void *ptr, const char *file, const char *func,
|
||||
|
||||
#endif /* _WANT_ORIGINAL_AFL_ALLOC */
|
||||
|
||||
/* This function calculates the next power of 2 greater or equal its argument.
|
||||
@return The rounded up power of 2 (if no overflow) or 0 on overflow.
|
||||
*/
|
||||
static inline size_t next_pow2(size_t in) {
|
||||
|
||||
if (in == 0 || in > (size_t)-1)
|
||||
return 0; /* avoid undefined behaviour under-/overflow */
|
||||
size_t out = in - 1;
|
||||
out |= out >> 1;
|
||||
out |= out >> 2;
|
||||
out |= out >> 4;
|
||||
out |= out >> 8;
|
||||
out |= out >> 16;
|
||||
return out + 1;
|
||||
|
||||
}
|
||||
|
||||
/* This function makes sure *size is > size_needed after call.
|
||||
It will realloc *buf otherwise.
|
||||
*size will grow exponentially as per:
|
||||
https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
|
||||
Will return NULL and free *buf if size_needed is <1 or realloc failed.
|
||||
@return For convenience, this function returns *buf.
|
||||
*/
|
||||
static inline void *maybe_grow(void **buf, size_t *size, size_t size_needed) {
|
||||
|
||||
/* No need to realloc */
|
||||
if (likely(size_needed && *size >= size_needed)) return *buf;
|
||||
|
||||
/* No initial size was set */
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
|
||||
|
||||
/* grow exponentially */
|
||||
size_t next_size = next_pow2(size_needed);
|
||||
|
||||
/* handle overflow and zero size_needed */
|
||||
if (!next_size) { next_size = size_needed; }
|
||||
|
||||
/* alloc */
|
||||
*buf = realloc(*buf, next_size);
|
||||
*size = *buf ? next_size : 0;
|
||||
|
||||
return *buf;
|
||||
|
||||
}
|
||||
|
||||
/* This function makes sure *size is > size_needed after call.
|
||||
It will realloc *buf otherwise.
|
||||
*size will grow exponentially as per:
|
||||
https://blog.mozilla.org/nnethercote/2014/11/04/please-grow-your-buffers-exponentially/
|
||||
Will FATAL if size_needed is <1.
|
||||
@return For convenience, this function returns *buf.
|
||||
*/
|
||||
static inline void *ck_maybe_grow(void **buf, size_t *size,
|
||||
size_t size_needed) {
|
||||
|
||||
/* Oops. found a bug? */
|
||||
if (unlikely(size_needed < 1)) FATAL("cannot grow to non-positive size");
|
||||
|
||||
/* No need to realloc */
|
||||
if (likely(*size >= size_needed)) return *buf;
|
||||
|
||||
/* No initial size was set */
|
||||
if (size_needed < INITIAL_GROWTH_SIZE) size_needed = INITIAL_GROWTH_SIZE;
|
||||
|
||||
/* grow exponentially */
|
||||
size_t next_size = next_pow2(size_needed);
|
||||
|
||||
/* handle overflow */
|
||||
if (!next_size) { next_size = size_needed; }
|
||||
|
||||
/* alloc */
|
||||
*buf = ck_realloc(*buf, next_size);
|
||||
*size = next_size;
|
||||
|
||||
return *buf;
|
||||
|
||||
}
|
||||
|
||||
/* Swaps buf1 ptr and buf2 ptr, as well as their sizes */
|
||||
static inline void swap_bufs(void **buf1, size_t *size1, void **buf2,
|
||||
size_t *size2) {
|
||||
|
||||
void * scratch_buf = *buf1;
|
||||
size_t scratch_size = *size1;
|
||||
*buf1 = *buf2;
|
||||
*size1 = *size2;
|
||||
*buf2 = scratch_buf;
|
||||
*size2 = scratch_size;
|
||||
|
||||
}
|
||||
|
||||
#undef INITIAL_GROWTH_SIZE
|
||||
|
||||
#endif /* ! _HAVE_ALLOC_INL_H */
|
||||
|
||||
|
326
include/common.h
326
include/common.h
@ -29,6 +29,7 @@
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "types.h"
|
||||
#include "stdbool.h"
|
||||
@ -47,349 +48,60 @@ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
|
||||
char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
|
||||
char * get_afl_env(char *env);
|
||||
|
||||
extern u8 be_quiet;
|
||||
extern u8 *doc_path; /* path to documentation dir */
|
||||
|
||||
/* Get unix time in milliseconds */
|
||||
|
||||
static u64 get_cur_time(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
|
||||
|
||||
}
|
||||
u64 get_cur_time(void);
|
||||
|
||||
/* Get unix time in microseconds */
|
||||
|
||||
static u64 get_cur_time_us(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
|
||||
|
||||
}
|
||||
u64 get_cur_time_us(void);
|
||||
|
||||
/* Describe integer. The buf should be
|
||||
at least 6 bytes to fit all ints we randomly see.
|
||||
Will return buf for convenience. */
|
||||
|
||||
static u8 *stringify_int(u8 *buf, size_t len, u64 val) {
|
||||
|
||||
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
|
||||
do { \
|
||||
\
|
||||
if (val < (_divisor) * (_limit_mult)) { \
|
||||
\
|
||||
snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
|
||||
return buf; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1000, 99.95, "%0.01fk", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1000, 1000, "%lluk", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
|
||||
|
||||
/* 100T+ */
|
||||
strncpy(buf, "infty", len);
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
u8 *stringify_int(u8 *buf, size_t len, u64 val);
|
||||
|
||||
/* Describe float. Similar as int. */
|
||||
|
||||
static u8 *stringify_float(u8 *buf, size_t len, double val) {
|
||||
|
||||
if (val < 99.995) {
|
||||
|
||||
snprintf(buf, len, "%0.02f", val);
|
||||
|
||||
} else if (val < 999.95) {
|
||||
|
||||
snprintf(buf, len, "%0.01f", val);
|
||||
|
||||
} else {
|
||||
|
||||
stringify_int(buf, len, (u64)val);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
u8 *stringify_float(u8 *buf, size_t len, double val);
|
||||
|
||||
/* Describe integer as memory size. */
|
||||
|
||||
static u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu B", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1024, 1000, "%llu kB", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
|
||||
|
||||
#undef CHK_FORMAT
|
||||
|
||||
/* 100T+ */
|
||||
strncpy(buf, "infty", len - 1);
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
u8 *stringify_mem_size(u8 *buf, size_t len, u64 val);
|
||||
|
||||
/* Describe time delta as string.
|
||||
Returns a pointer to buf for convenience. */
|
||||
|
||||
static u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
|
||||
|
||||
u64 delta;
|
||||
s32 t_d, t_h, t_m, t_s;
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
if (!event_ms) {
|
||||
|
||||
snprintf(buf, len, "none seen yet");
|
||||
|
||||
} else {
|
||||
|
||||
delta = cur_ms - event_ms;
|
||||
|
||||
t_d = delta / 1000 / 60 / 60 / 24;
|
||||
t_h = (delta / 1000 / 60 / 60) % 24;
|
||||
t_m = (delta / 1000 / 60) % 60;
|
||||
t_s = (delta / 1000) % 60;
|
||||
|
||||
stringify_int(val_buf, sizeof(val_buf), t_d);
|
||||
snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
|
||||
t_s);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms);
|
||||
|
||||
/* Unsafe Describe integer. The buf sizes are not checked.
|
||||
This is unsafe but fast.
|
||||
Will return buf for convenience. */
|
||||
|
||||
static u8 *u_stringify_int(u8 *buf, u64 val) {
|
||||
|
||||
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
|
||||
do { \
|
||||
\
|
||||
if (val < (_divisor) * (_limit_mult)) { \
|
||||
\
|
||||
sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \
|
||||
return buf; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1000, 99.95, "%0.01fk", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1000, 1000, "%lluk", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
|
||||
|
||||
/* 100T+ */
|
||||
strcpy(buf, "infty");
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
u8 *u_stringify_int(u8 *buf, u64 val);
|
||||
|
||||
/* Unsafe describe float. Similar as unsafe int. */
|
||||
|
||||
static u8 *u_stringify_float(u8 *buf, double val) {
|
||||
|
||||
if (val < 99.995) {
|
||||
|
||||
sprintf(buf, "%0.02f", val);
|
||||
|
||||
} else if (val < 999.95) {
|
||||
|
||||
sprintf(buf, "%0.01f", val);
|
||||
|
||||
} else {
|
||||
|
||||
return u_stringify_int(buf, (u64)val);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
u8 *u_stringify_float(u8 *buf, double val);
|
||||
|
||||
/* Unsafe describe integer as memory size. */
|
||||
|
||||
static u8 *u_stringify_mem_size(u8 *buf, u64 val) {
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu B", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1024, 1000, "%llu kB", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
|
||||
|
||||
#undef CHK_FORMAT
|
||||
|
||||
/* 100T+ */
|
||||
strcpy(buf, "infty");
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
u8 *u_stringify_mem_size(u8 *buf, u64 val);
|
||||
|
||||
/* Unsafe describe time delta as string.
|
||||
Returns a pointer to buf for convenience. */
|
||||
|
||||
static u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
|
||||
u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms);
|
||||
|
||||
u64 delta;
|
||||
s32 t_d, t_h, t_m, t_s;
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
if (!event_ms) {
|
||||
|
||||
sprintf(buf, "none seen yet");
|
||||
|
||||
} else {
|
||||
|
||||
delta = cur_ms - event_ms;
|
||||
|
||||
t_d = delta / 1000 / 60 / 60 / 24;
|
||||
t_h = (delta / 1000 / 60 / 60) % 24;
|
||||
t_m = (delta / 1000 / 60) % 60;
|
||||
t_s = (delta / 1000) % 60;
|
||||
|
||||
u_stringify_int(val_buf, t_d);
|
||||
sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
/* Wrapper for select() and read(), reading exactly len bytes.
|
||||
Returns the time passed to read.
|
||||
If the wait times out, returns timeout_ms + 1;
|
||||
Returns 0 if an error occurred (fd closed, signal, ...); */
|
||||
u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -34,8 +34,8 @@
|
||||
#include "debug.h"
|
||||
#include "afl-prealloc.h"
|
||||
|
||||
#define LIST_PREALLOC_SIZE \
|
||||
(64) /* How many elements to allocate before malloc is needed */
|
||||
/* How many elements to allocate before malloc is needed */
|
||||
#define LIST_PREALLOC_SIZE (64)
|
||||
|
||||
typedef struct list_element {
|
||||
|
||||
@ -56,17 +56,18 @@ typedef struct list {
|
||||
|
||||
static inline element_t *get_head(list_t *list) {
|
||||
|
||||
return &list->element_prealloc_buf[0];
|
||||
/* The first element is the head */
|
||||
return list->element_prealloc_buf;
|
||||
|
||||
}
|
||||
|
||||
static void list_free_el(list_t *list, element_t *el) {
|
||||
static inline void list_free_el(list_t *list, element_t *el) {
|
||||
|
||||
PRE_FREE(el, list->element_prealloc_count);
|
||||
|
||||
}
|
||||
|
||||
static void list_append(list_t *list, void *el) {
|
||||
static inline void list_append(list_t *list, void *el) {
|
||||
|
||||
element_t *head = get_head(list);
|
||||
if (!head->next) {
|
||||
@ -97,23 +98,23 @@ static void list_append(list_t *list, void *el) {
|
||||
A return from this block will return from calling func.
|
||||
*/
|
||||
|
||||
#define LIST_FOREACH(list, type, block) \
|
||||
do { \
|
||||
\
|
||||
list_t * li = (list); \
|
||||
element_t *head = get_head((li)); \
|
||||
element_t *el_box = (head)->next; \
|
||||
if (!el_box) FATAL("foreach over uninitialized list"); \
|
||||
while (el_box != head) { \
|
||||
\
|
||||
type *el = (type *)((el_box)->data); \
|
||||
/* get next so el_box can be unlinked */ \
|
||||
element_t *next = el_box->next; \
|
||||
{block}; \
|
||||
el_box = next; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
#define LIST_FOREACH(list, type, block) \
|
||||
do { \
|
||||
\
|
||||
list_t * li = (list); \
|
||||
element_t *head = get_head((li)); \
|
||||
element_t *el_box = (head)->next; \
|
||||
if (!el_box) FATAL("foreach over uninitialized list"); \
|
||||
while (el_box != head) { \
|
||||
\
|
||||
__attribute__((unused)) type *el = (type *)((el_box)->data); \
|
||||
/* get next so el_box can be unlinked */ \
|
||||
element_t *next = el_box->next; \
|
||||
{block}; \
|
||||
el_box = next; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0);
|
||||
|
||||
/* In foreach: remove the current el from the list */
|
||||
@ -143,7 +144,7 @@ static void list_append(list_t *list, void *el) {
|
||||
|
||||
/* remove an item from the list */
|
||||
|
||||
static void list_remove(list_t *list, void *remove_me) {
|
||||
static inline void list_remove(list_t *list, void *remove_me) {
|
||||
|
||||
LIST_FOREACH(list, void, {
|
||||
|
||||
@ -165,7 +166,7 @@ static void list_remove(list_t *list, void *remove_me) {
|
||||
|
||||
/* Returns true if el is in list */
|
||||
|
||||
static bool list_contains(list_t *list, void *contains_me) {
|
||||
static inline bool list_contains(list_t *list, void *contains_me) {
|
||||
|
||||
LIST_FOREACH(list, void, {
|
||||
|
||||
|
@ -58,8 +58,22 @@ typedef int32_t s32;
|
||||
typedef int64_t s64;
|
||||
|
||||
#ifndef MIN
|
||||
#define MIN(_a, _b) ((_a) > (_b) ? (_b) : (_a))
|
||||
#define MAX(_a, _b) ((_a) > (_b) ? (_a) : (_b))
|
||||
#define MIN(a, b) \
|
||||
({ \
|
||||
\
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a < _b ? _a : _b; \
|
||||
\
|
||||
})
|
||||
#define MAX(a, b) \
|
||||
({ \
|
||||
\
|
||||
__typeof__(a) _a = (a); \
|
||||
__typeof__(b) _b = (b); \
|
||||
_a > _b ? _a : _b; \
|
||||
\
|
||||
})
|
||||
#endif /* !MIN */
|
||||
|
||||
#define SWAP16(_x) \
|
||||
@ -120,9 +134,13 @@ typedef int64_t s64;
|
||||
#define likely(_x) (_x)
|
||||
#define unlikely(_x) (_x)
|
||||
#else
|
||||
#ifndef likely
|
||||
#define likely(_x) __builtin_expect(!!(_x), 1)
|
||||
#endif
|
||||
#ifndef unlikely
|
||||
#define unlikely(_x) __builtin_expect(!!(_x), 0)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif /* ! _HAVE_TYPES_H */
|
||||
|
||||
|
44
libdislocator/GNUmakefile
Normal file
44
libdislocator/GNUmakefile
Normal file
@ -0,0 +1,44 @@
|
||||
#
|
||||
# american fuzzy lop++ - libdislocator
|
||||
# ----------------------------------
|
||||
#
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops
|
||||
override CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||
|
||||
ifdef USEHUGEPAGE
|
||||
CFLAGS += -DUSEHUGEPAGE
|
||||
endif
|
||||
|
||||
all: libdislocator.so
|
||||
|
||||
VPATH = ..
|
||||
libdislocator.so: libdislocator.so.c ../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
|
||||
rm -f ../libdislocator.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)
|
||||
|
@ -1,44 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - libdislocator
|
||||
# ----------------------------------
|
||||
#
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops
|
||||
CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||
|
||||
ifdef USEHUGEPAGE
|
||||
CFLAGS += -DUSEHUGEPAGE
|
||||
endif
|
||||
|
||||
all: libdislocator.so
|
||||
|
||||
VPATH = ..
|
||||
libdislocator.so: libdislocator.so.c ../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
|
||||
rm -f ../libdislocator.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)
|
||||
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
63
libtokencap/GNUmakefile
Normal file
63
libtokencap/GNUmakefile
Normal file
@ -0,0 +1,63 @@
|
||||
#
|
||||
# american fuzzy lop++ - libtokencap
|
||||
# --------------------------------
|
||||
#
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||
MAN_PATH ?= $(PREFIX)/man/man8
|
||||
|
||||
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops
|
||||
override CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||
|
||||
ifeq "$(shell uname)" "Linux"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq "$(shell uname)" "FreeBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "NetBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "DragonFly"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
all: $(TARGETS)
|
||||
|
||||
VPATH = ..
|
||||
libtokencap.so: libtokencap.so.c ../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
|
||||
rm -f ../libtokencap.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.tokencap.md
|
||||
|
@ -1,63 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - libtokencap
|
||||
# --------------------------------
|
||||
#
|
||||
# Originally written by Michal Zalewski
|
||||
#
|
||||
# Copyright 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
DOC_PATH ?= $(PREFIX)/share/doc/afl
|
||||
MAN_PATH ?= $(PREFIX)/man/man8
|
||||
|
||||
VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops
|
||||
CFLAGS += -I ../include/ -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||
|
||||
ifeq "$(shell uname)" "Linux"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq "$(shell uname)" "FreeBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "NetBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "DragonFly"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
all: $(TARGETS)
|
||||
|
||||
VPATH = ..
|
||||
libtokencap.so: libtokencap.so.c ../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]*
|
||||
rm -f ../libtokencap.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 -T README.md $${DESTDIR}$(DOC_PATH)/README.tokencap.md
|
||||
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
375
llvm_mode/GNUmakefile
Normal file
375
llvm_mode/GNUmakefile
Normal file
@ -0,0 +1,375 @@
|
||||
#
|
||||
# american fuzzy lop++ - LLVM instrumentation
|
||||
# -----------------------------------------
|
||||
#
|
||||
# Written by Laszlo Szekeres <lszekeres@google.com> and
|
||||
# Michal Zalewski
|
||||
#
|
||||
# LLVM integration design comes from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015, 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
# For Heiko:
|
||||
#TEST_MMAP=1
|
||||
HASH=\#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
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
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||
ifeq "$(HAS_OPT)" "1"
|
||||
$(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 11) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
endif
|
||||
else
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
endif
|
||||
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[2-9]' && echo 1 || echo 0 )
|
||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
|
||||
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_STDCXX = gnu++11
|
||||
LLVM_APPLE = $(shell clang -v 2>&1 | grep -iq apple && echo 1 || echo 0)
|
||||
LLVM_LTO = 0
|
||||
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning [!] llvm_mode needs llvm-config, which was not found)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_UNSUPPORTED)" "1"
|
||||
$(warning llvm_mode only supports llvm versions 3.8.0 up to 11)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_MAJOR)" "9"
|
||||
$(info [+] llvm_mode detected llvm 9, enabling neverZero implementation)
|
||||
$(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
|
||||
LLVM_LTO = 1
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_NEW_API)" "1"
|
||||
$(info [+] llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
|
||||
$(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
|
||||
LLVM_STDCXX = c++14
|
||||
LLVM_LTO = 1
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_LTO)" "0"
|
||||
$(info [+] llvm_mode detected llvm < 9, afl-clang-lto LTO will not be build.)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_APPLE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# We were using llvm-config --bindir to get the location of clang, but
|
||||
# this seems to be busted on some distros, so using the one in $PATH is
|
||||
# probably better.
|
||||
|
||||
CC = $(LLVM_BINDIR)/clang
|
||||
CXX = $(LLVM_BINDIR)/clang++
|
||||
|
||||
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
|
||||
# llvm-config --bindir may not providing a valid path, so ...
|
||||
ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1"
|
||||
# we found one in the local install directory, lets use these
|
||||
CC = $(BIN_DIR)/clang
|
||||
CXX = $(BIN_DIR)/clang++
|
||||
else
|
||||
# hope for the best
|
||||
$(warning we have trouble finding clang/clang++ - llvm-config is not helping us)
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
endif
|
||||
endif
|
||||
|
||||
# sanity check.
|
||||
# Are versions of clang --version and llvm-config --version equal?
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
CC = $(shell $(LLVM_CONFIG) --bindir)/clang
|
||||
CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
|
||||
endif
|
||||
|
||||
# After we set CC/CXX we can start makefile magic tests
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_OPT = -march=native
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto=full
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto=thin
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(AFL_REAL_LD)" ""
|
||||
AFL_REAL_LD = $(shell readlink /bin/ld 2>/dev/null)
|
||||
ifeq "$(AFL_REAL_LD)" ""
|
||||
AFL_REAL_LD = $(shell readlink /usr/bin/ld 2>/dev/null)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2
|
||||
override CFLAGS = -Wall \
|
||||
-g -Wno-pointer-sign -I ../include/ \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
|
||||
-DLLVM_VERSION=\"$(LLVMVER)\" -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
|
||||
-DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -Wno-unused-function
|
||||
ifdef AFL_TRACE_PC
|
||||
CFLAGS += -DUSE_TRACE_PC=1
|
||||
endif
|
||||
|
||||
CXXFLAGS ?= -O3 -funroll-loops -D_FORTIFY_SOURCE=2
|
||||
override CXXFLAGS += -Wall -g -I ../include/ \
|
||||
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros
|
||||
|
||||
CLANG_CFL = `$(LLVM_CONFIG) --cxxflags` -Wl,-znodelete -fno-rtti -fpic $(CXXFLAGS)
|
||||
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
|
||||
|
||||
|
||||
# User teor2345 reports that this is required to make things work on MacOS X.
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS += -DAFL_CLANG_FUSELD=1
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifndef AFL_TRACE_PC
|
||||
PROGS = ../afl-clang-fast ../afl-ld ../afl-llvm-pass.so ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
|
||||
else
|
||||
PROGS = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
|
||||
endif
|
||||
|
||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||
ifeq "$(LLVMVER)" ""
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE)" "00"
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifeq "$(NO_BUILD)" "1"
|
||||
TARGETS = no_build
|
||||
else
|
||||
TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
|
||||
endif
|
||||
|
||||
LLVM_MIN_4_0_1 = $(shell awk 'function tonum(ver, a) {split(ver,a,"."); return a[1]*1000000+a[2]*1000+a[3]} BEGIN { exit tonum(ARGV[1]) >= tonum(ARGV[2]) }' $(LLVMVER) 4.0.1; echo $$?)
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
no_build:
|
||||
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
|
||||
|
||||
test_deps:
|
||||
ifndef AFL_TRACE_PC
|
||||
@echo "[*] Checking for working 'llvm-config'..."
|
||||
ifneq "$(LLVM_APPLE)" "1"
|
||||
@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
|
||||
endif
|
||||
else
|
||||
@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
|
||||
endif
|
||||
@echo "[*] Checking for working '$(CC)'..."
|
||||
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||
@echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'"
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
@echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)"
|
||||
@echo "[!] Retrying with the clang compiler from llvm: CC=`llvm-config --bindir`/clang"
|
||||
else
|
||||
@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
|
||||
endif
|
||||
@echo "[*] Checking for '../afl-showmap'..."
|
||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
afl-common.o: ../src/afl-common.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
|
||||
|
||||
../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps
|
||||
$(CC) $(CFLAGS) $< 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"
|
||||
ln -sf afl-clang-fast ../afl-clang-lto
|
||||
ln -sf afl-clang-fast ../afl-clang-lto++
|
||||
endif
|
||||
endif
|
||||
|
||||
../afl-ld: afl-ld.c
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
ln -sf afl-ld ../ld
|
||||
@rm -f .test-instr
|
||||
@-export AFL_QUIET=1 AFL_PATH=.. PATH="..:$(PATH)" ; ../afl-clang-lto -Wl,--afl -o .test-instr ../test-instr.c && echo "[+] afl-clang-lto and afl-ld seem to work fine :)" || echo "[!] WARNING: clang seems to have a hardcoded "'/bin/ld'" - check README.lto"
|
||||
@rm -f .test-instr
|
||||
endif
|
||||
endif
|
||||
../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
|
||||
-$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
|
||||
ifeq "$(LLVM_MIN_4_0_1)" "0"
|
||||
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
|
||||
endif
|
||||
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
|
||||
endif
|
||||
|
||||
../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc MarkNodes.cc
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
|
||||
endif
|
||||
|
||||
# laf
|
||||
../split-switches-pass.so: split-switches-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
../compare-transform-pass.so: compare-transform-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
../split-compares-pass.so: split-compares-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
# /laf
|
||||
|
||||
../cmplog-routines-pass.so: cmplog-routines-pass.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
../cmplog-instructions-pass.so: cmplog-instructions-pass.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
|
||||
$(CC) $(CFLAGS) -fPIC -c $< -o $@
|
||||
|
||||
../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
|
||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
||||
@$(CC) $(CFLAGS) -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)... "
|
||||
@$(CC) $(CFLAGS) -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..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-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
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
all_done: test_build
|
||||
@echo "[+] All done! You can now use '../afl-clang-fast' to compile programs."
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
install: all
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
ifndef AFL_TRACE_PC
|
||||
if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-clang-lto -a -f afl-ld ]; then set -e; install -m 755 afl-clang-lto $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
else
|
||||
if [ -f ../afl-clang-fast -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
endif
|
||||
if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../split-compares-pass.so ]; then set -e; install -m 755 ../split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../split-switches-pass.so ]; then set -e; install -m 755 ../split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); 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
|
||||
|
||||
vpath % ..
|
||||
%.8: %
|
||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
|
||||
@echo .SH NAME >> ../$@
|
||||
@echo .B $* >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH SYNOPSIS >> ../$@
|
||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH OPTIONS >> ../$@
|
||||
@echo .nf >> ../$@
|
||||
@../$* -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 >> ../$@
|
||||
@echo .SH LICENSE >> ../$@
|
||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
||||
ln -sf afl-clang-fast.8 ../afl-clang-fast++.8
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
ln -sf afl-clang-fast.8 ../afl-clang-lto.8
|
||||
ln -sf afl-clang-fast.8 ../afl-clang-lto++.8
|
||||
endif
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
|
||||
rm -f $(PROGS) afl-common.o ../afl-clang-fast++ ../afl-clang-lto ../afl-clang-lto++ ../afl-clang*.8 ../ld
|
@ -509,10 +509,11 @@ struct InsTrim : public ModulePass {
|
||||
if (!be_quiet) {
|
||||
|
||||
char modeline[100];
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s",
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
|
||||
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
|
||||
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
|
||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||
|
||||
OKF("Instrumented %u locations (%llu, %llu) (%s mode)\n", total_instr,
|
||||
|
@ -1,370 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - LLVM instrumentation
|
||||
# -----------------------------------------
|
||||
#
|
||||
# Written by Laszlo Szekeres <lszekeres@google.com> and
|
||||
# Michal Zalewski
|
||||
#
|
||||
# LLVM integration design comes from Laszlo Szekeres.
|
||||
#
|
||||
# Copyright 2015, 2016 Google Inc. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
# For Heiko:
|
||||
#TEST_MMAP=1
|
||||
HASH=\#
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
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
|
||||
|
||||
VERSION = $(shell grep '^$(HASH)define VERSION ' ../config.h | cut -d '"' -f2)
|
||||
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||
ifeq "$(HAS_OPT)" "1"
|
||||
$(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 11) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
endif
|
||||
else
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
endif
|
||||
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[2-9]' && echo 1 || echo 0 )
|
||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
|
||||
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_STDCXX = gnu++11
|
||||
LLVM_APPLE = $(shell clang -v 2>&1 | grep -iq apple && echo 1 || echo 0)
|
||||
LLVM_LTO = 0
|
||||
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning [!] llvm_mode needs llvm-config, which was not found)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_UNSUPPORTED)" "1"
|
||||
$(warning llvm_mode only supports llvm versions 3.8.0 up to 11)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_MAJOR)" "9"
|
||||
$(info [+] llvm_mode detected llvm 9, enabling neverZero implementation)
|
||||
$(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
|
||||
LLVM_LTO = 1
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_NEW_API)" "1"
|
||||
$(info [+] llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
|
||||
$(info [+] llvm_mode detected llvm 9, enabling afl-clang-lto LTO implementation)
|
||||
LLVM_STDCXX = c++14
|
||||
LLVM_LTO = 1
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_LTO)" "0"
|
||||
$(info [+] llvm_mode detected llvm < 9, afl-clang-lto LTO will not be build.)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_APPLE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# We were using llvm-config --bindir to get the location of clang, but
|
||||
# this seems to be busted on some distros, so using the one in $PATH is
|
||||
# probably better.
|
||||
|
||||
CC = $(LLVM_BINDIR)/clang
|
||||
CXX = $(LLVM_BINDIR)/clang++
|
||||
|
||||
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
|
||||
# llvm-config --bindir may not providing a valid path, so ...
|
||||
ifeq "$(shell test -e '$(BIN_DIR)/clang' && echo 1)" "1"
|
||||
# we found one in the local install directory, lets use these
|
||||
CC = $(BIN_DIR)/clang
|
||||
CXX = $(BIN_DIR)/clang++
|
||||
else
|
||||
# hope for the best
|
||||
$(warning we have trouble finding clang/clang++ - llvm-config is not helping us)
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
endif
|
||||
endif
|
||||
|
||||
# sanity check.
|
||||
# Are versions of clang --version and llvm-config --version equal?
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
CC = $(shell $(LLVM_CONFIG) --bindir)/clang
|
||||
CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
|
||||
endif
|
||||
|
||||
# After we set CC/CXX we can start makefile magic tests
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -march=native -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_OPT = -march=native
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto=full
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto=thin -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto=thin
|
||||
else
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -flto -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FLTO ?= -flto
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(AFL_REAL_LD)" ""
|
||||
AFL_REAL_LD = $(shell readlink /bin/ld 2>/dev/null)
|
||||
ifeq "$(AFL_REAL_LD)" ""
|
||||
AFL_REAL_LD = $(shell readlink /usr/bin/ld 2>/dev/null)
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops
|
||||
override CFLAGS = -Wall \
|
||||
-D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I ../include/ \
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\" \
|
||||
-DLLVM_VERSION=\"$(LLVMVER)\" -DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" \
|
||||
-DAFL_REAL_LD=\"$(AFL_REAL_LD)\" -Wno-unused-function
|
||||
ifdef AFL_TRACE_PC
|
||||
CFLAGS += -DUSE_TRACE_PC=1
|
||||
endif
|
||||
|
||||
CXXFLAGS ?= -O3 -funroll-loops
|
||||
override CXXFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -I ../include/ \
|
||||
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros
|
||||
|
||||
CLANG_CFL = `$(LLVM_CONFIG) --cxxflags` -Wl,-znodelete -fno-rtti -fpic $(CXXFLAGS)
|
||||
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
|
||||
|
||||
|
||||
# User teor2345 reports that this is required to make things work on MacOS X.
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
|
||||
endif
|
||||
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS += -DAFL_CLANG_FUSELD=1
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <sys/ipc.h>@$(HASH)include <sys/shm.h>@int main() { int _id = shmget(IPC_PRIVATE, 65536, IPC_CREAT | IPC_EXCL | 0600); shmctl(_id, IPC_RMID, 0); return 0;}' | tr @ '\n' | $(CC) -x c - -o .test2 2>/dev/null && echo 1 || echo 0 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifeq "$(TEST_MMAP)" "1"
|
||||
SHMAT_OK=0
|
||||
CFLAGS+=-DUSEMMAP=1
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifndef AFL_TRACE_PC
|
||||
PROGS = ../afl-clang-fast ../afl-ld ../afl-llvm-pass.so ../afl-llvm-lto-whitelist.so ../afl-llvm-lto-instrumentation.so ../libLLVMInsTrim.so ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
|
||||
else
|
||||
PROGS = ../afl-clang-fast ../afl-llvm-rt.o ../afl-llvm-rt-32.o ../afl-llvm-rt-64.o ../compare-transform-pass.so ../split-compares-pass.so ../split-switches-pass.so ../cmplog-routines-pass.so ../cmplog-instructions-pass.so
|
||||
endif
|
||||
|
||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||
ifeq "$(LLVMVER)" ""
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE)" "00"
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifeq "$(NO_BUILD)" "1"
|
||||
TARGETS = no_build
|
||||
else
|
||||
TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
test_shm:
|
||||
@echo "[+] shmat seems to be working."
|
||||
@rm -f .test2
|
||||
|
||||
else
|
||||
|
||||
test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
|
||||
endif
|
||||
|
||||
no_build:
|
||||
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
|
||||
|
||||
test_deps:
|
||||
ifndef AFL_TRACE_PC
|
||||
@echo "[*] Checking for working 'llvm-config'..."
|
||||
ifneq "$(LLVM_APPLE)" "1"
|
||||
@type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
|
||||
endif
|
||||
else
|
||||
@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
|
||||
endif
|
||||
@echo "[*] Checking for working '$(CC)'..."
|
||||
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
|
||||
@echo "[*] Checking for matching versions of '$(CC)' and '$(LLVM_CONFIG)'"
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
@echo "[!] WARNING: we have llvm-config version $(LLVMVER) and a clang version $(CLANGVER)"
|
||||
@echo "[!] Retrying with the clang compiler from llvm: CC=`llvm-config --bindir`/clang"
|
||||
else
|
||||
@echo "[*] We have llvm-config version $(LLVMVER) with a clang version $(CLANGVER), good."
|
||||
endif
|
||||
@echo "[*] Checking for '../afl-showmap'..."
|
||||
@test -f ../afl-showmap || ( echo "[-] Oops, can't find '../afl-showmap'. Be sure to compile AFL first."; exit 1 )
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
afl-common.o: ../src/afl-common.c
|
||||
$(CC) $(CFLAGS) -c $< -o $@ $(LDFLAGS)
|
||||
|
||||
../afl-clang-fast: afl-clang-fast.c afl-common.o | test_deps
|
||||
$(CC) $(CFLAGS) $< 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"
|
||||
ln -sf afl-clang-fast ../afl-clang-lto
|
||||
ln -sf afl-clang-fast ../afl-clang-lto++
|
||||
endif
|
||||
endif
|
||||
|
||||
../afl-ld: afl-ld.c
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
ln -sf afl-ld ../ld
|
||||
@rm -f .test-instr
|
||||
@-export AFL_QUIET=1 AFL_PATH=.. PATH="..:$(PATH)" ; ../afl-clang-lto -Wl,--afl -o .test-instr ../test-instr.c && echo "[+] afl-clang-lto and afl-ld seem to work fine :)" || echo "[!] WARNING: clang seems to have a hardcoded "'/bin/ld'" - check README.lto"
|
||||
@rm -f .test-instr
|
||||
endif
|
||||
endif
|
||||
../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
|
||||
-$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-lto-whitelist.so: afl-llvm-lto-whitelist.so.cc
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
|
||||
endif
|
||||
|
||||
../afl-llvm-lto-instrumentation.so: afl-llvm-lto-instrumentation.so.cc MarkNodes.cc
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CFL) -Wno-writable-strings -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
|
||||
endif
|
||||
|
||||
# laf
|
||||
../split-switches-pass.so: split-switches-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
../compare-transform-pass.so: compare-transform-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
../split-compares-pass.so: split-compares-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
# /laf
|
||||
|
||||
../cmplog-routines-pass.so: cmplog-routines-pass.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
../cmplog-instructions-pass.so: cmplog-instructions-pass.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-rt.o: afl-llvm-rt.o.c | test_deps
|
||||
$(CC) $(CFLAGS) -fPIC -c $< -o $@
|
||||
|
||||
../afl-llvm-rt-32.o: afl-llvm-rt.o.c | test_deps
|
||||
@printf "[*] Building 32-bit variant of the runtime (-m32)... "
|
||||
@$(CC) $(CFLAGS) -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)... "
|
||||
@$(CC) $(CFLAGS) -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..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO; AFL_QUIET=1 AFL_PATH=. AFL_CC=$(CC) AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-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
|
||||
@rm -f test-instr
|
||||
@cmp -s .test-instr0 .test-instr1; DR="$$?"; rm -f .test-instr0 .test-instr1; if [ "$$DR" = "0" ]; then echo; echo "Oops, the instrumentation does not seem to be behaving correctly!"; echo; echo "Please post to https://github.com/AFLplusplus/AFLplusplus/issues to troubleshoot the issue."; echo; exit 1; fi
|
||||
@echo "[+] All right, the instrumentation seems to be working!"
|
||||
|
||||
all_done: test_build
|
||||
@echo "[+] All done! You can now use '../afl-clang-fast' to compile programs."
|
||||
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
install: all
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
ifndef AFL_TRACE_PC
|
||||
if [ -f ../afl-clang-fast -a -f ../libLLVMInsTrim.so -a -f ../afl-llvm-rt.o ]; then set -e; install -m 755 ../afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf ../afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 ../libLLVMInsTrim.so ../afl-llvm-pass.so ../afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-clang-lto -a -f afl-ld ]; then set -e; install -m 755 afl-clang-lto $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-lto++; install -m 755 afl-ld $${DESTDIR}$(HELPER_PATH); ln -sf afl-ld $${DESTDIR}$(HELPER_PATH)/ld; install -m 755 afl-llvm-lto-instrumentation.so $${DESTDIR}$(HELPER_PATH); install -m 755 afl-llvm-lto-whitelist.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
else
|
||||
if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
endif
|
||||
if [ -f ../afl-llvm-rt-32.o ]; then set -e; install -m 755 ../afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../afl-llvm-rt-64.o ]; then set -e; install -m 755 ../afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../compare-transform-pass.so ]; then set -e; install -m 755 ../compare-transform-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../split-compares-pass.so ]; then set -e; install -m 755 ../split-compares-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../split-switches-pass.so ]; then set -e; install -m 755 ../split-switches-pass.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f ../cmplog-instructions-pass.so ]; then set -e; install -m 755 ../cmplog-*-pass.so $${DESTDIR}$(HELPER_PATH); 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
|
||||
|
||||
vpath % ..
|
||||
%.8: %
|
||||
@echo .TH $* 8 `date "+%Y-%m-%d"` "afl++" > ../$@
|
||||
@echo .SH NAME >> ../$@
|
||||
@echo .B $* >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH SYNOPSIS >> ../$@
|
||||
@../$* -h 2>&1 | head -n 3 | tail -n 1 | sed 's/^\.\///' >> ../$@
|
||||
@echo >> ../$@
|
||||
@echo .SH OPTIONS >> ../$@
|
||||
@echo .nf >> ../$@
|
||||
@../$* -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 >> ../$@
|
||||
@echo .SH LICENSE >> ../$@
|
||||
@echo Apache License Version 2.0, January 2004 >> ../$@
|
||||
ln -sf afl-clang-fast.8 ../afl-clang-fast++.8
|
||||
ifneq "$(AFL_CLANG_FLTO)" ""
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
ln -sf afl-clang-fast.8 ../afl-clang-lto.8
|
||||
ln -sf afl-clang-fast.8 ../afl-clang-lto++.8
|
||||
endif
|
||||
endif
|
||||
|
||||
clean:
|
||||
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* .test2 test-instr .test-instr0 .test-instr1 *.dwo
|
||||
rm -f $(PROGS) afl-common.o ../afl-clang-fast++ ../afl-clang-lto ../afl-clang-lto++ ../afl-clang*.8 ../ld
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
@ -48,7 +48,6 @@ static u8 debug;
|
||||
static u8 cwd[4096];
|
||||
static u8 cmplog_mode;
|
||||
u8 use_stdin = 0; /* dummy */
|
||||
u8 be_quiet = 0;
|
||||
|
||||
u8 *getthecwd() {
|
||||
|
||||
@ -135,9 +134,9 @@ static void find_obj(u8 *argv0) {
|
||||
|
||||
/* Copy argv to cc_params, making the necessary edits. */
|
||||
|
||||
static void edit_params(u32 argc, char **argv) {
|
||||
static void edit_params(u32 argc, char **argv, char **envp) {
|
||||
|
||||
u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0;
|
||||
u8 fortify_set = 0, asan_set = 0, x_set = 0, bit_mode = 0;
|
||||
u8 has_llvm_config = 0;
|
||||
u8 *name;
|
||||
|
||||
@ -324,8 +323,6 @@ static void edit_params(u32 argc, char **argv) {
|
||||
|
||||
/* Detect stray -v calls from ./configure scripts. */
|
||||
|
||||
if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0;
|
||||
|
||||
while (--argc) {
|
||||
|
||||
u8 *cur = *(++argv);
|
||||
@ -336,16 +333,11 @@ static void edit_params(u32 argc, char **argv) {
|
||||
|
||||
if (!strcmp(cur, "-x")) x_set = 1;
|
||||
|
||||
if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E"))
|
||||
maybe_linking = 0;
|
||||
|
||||
if (!strcmp(cur, "-fsanitize=address") || !strcmp(cur, "-fsanitize=memory"))
|
||||
asan_set = 1;
|
||||
|
||||
if (strstr(cur, "FORTIFY_SOURCE")) fortify_set = 1;
|
||||
|
||||
if (!strcmp(cur, "-shared")) maybe_linking = 0;
|
||||
|
||||
if (!strcmp(cur, "-Wl,-z,defs") || !strcmp(cur, "-Wl,--no-undefined"))
|
||||
continue;
|
||||
|
||||
@ -395,6 +387,22 @@ static void edit_params(u32 argc, char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_USE_CFISAN")) {
|
||||
|
||||
if (!lto_mode) {
|
||||
|
||||
uint32_t i = 0, found = 0;
|
||||
while (envp[i] != NULL && !found)
|
||||
if (strncmp("-flto", envp[i++], 5) == 0) found = 1;
|
||||
if (!found) cc_params[cc_par_cnt++] = "-flto";
|
||||
|
||||
}
|
||||
|
||||
cc_params[cc_par_cnt++] = "-fsanitize=cfi";
|
||||
cc_params[cc_par_cnt++] = "-fvisibility=hidden";
|
||||
|
||||
}
|
||||
|
||||
#ifdef USE_TRACE_PC
|
||||
|
||||
if (getenv("USE_TRACE_PC") || getenv("AFL_USE_TRACE_PC") ||
|
||||
@ -483,44 +491,40 @@ static void edit_params(u32 argc, char **argv) {
|
||||
#endif /* ^__APPLE__ */
|
||||
"_I(); } while (0)";
|
||||
|
||||
// if (maybe_linking) {
|
||||
if (x_set) {
|
||||
|
||||
if (x_set) {
|
||||
cc_params[cc_par_cnt++] = "-x";
|
||||
cc_params[cc_par_cnt++] = "none";
|
||||
|
||||
cc_params[cc_par_cnt++] = "-x";
|
||||
cc_params[cc_par_cnt++] = "none";
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
switch (bit_mode) {
|
||||
switch (bit_mode) {
|
||||
|
||||
case 0:
|
||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path);
|
||||
break;
|
||||
case 0:
|
||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt.o", obj_path);
|
||||
break;
|
||||
|
||||
case 32:
|
||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path);
|
||||
case 32:
|
||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-32.o", obj_path);
|
||||
|
||||
if (access(cc_params[cc_par_cnt - 1], R_OK))
|
||||
FATAL("-m32 is not supported by your compiler");
|
||||
if (access(cc_params[cc_par_cnt - 1], R_OK))
|
||||
FATAL("-m32 is not supported by your compiler");
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
case 64:
|
||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path);
|
||||
case 64:
|
||||
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-llvm-rt-64.o", obj_path);
|
||||
|
||||
if (access(cc_params[cc_par_cnt - 1], R_OK))
|
||||
FATAL("-m64 is not supported by your compiler");
|
||||
if (access(cc_params[cc_par_cnt - 1], R_OK))
|
||||
FATAL("-m64 is not supported by your compiler");
|
||||
|
||||
break;
|
||||
break;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// }
|
||||
|
||||
cc_params[cc_par_cnt] = NULL;
|
||||
|
||||
}
|
||||
@ -596,6 +600,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
"AFL_USE_ASAN: activate address sanitizer\n"
|
||||
"AFL_USE_MSAN: activate memory sanitizer\n"
|
||||
"AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
|
||||
"AFL_USE_CFISAN: activate control flow sanitizer\n"
|
||||
"AFL_LLVM_WHITELIST: enable whitelisting (selective "
|
||||
"instrumentation)\n"
|
||||
"AFL_LLVM_NOT_ZERO: use cycling trace counters that skip zero\n"
|
||||
@ -685,7 +690,7 @@ int main(int argc, char **argv, char **envp) {
|
||||
find_obj(argv[0]);
|
||||
#endif
|
||||
|
||||
edit_params(argc, argv);
|
||||
edit_params(argc, argv, envp);
|
||||
|
||||
if (debug) {
|
||||
|
||||
|
@ -392,10 +392,11 @@ bool AFLLTOPass::runOnModule(Module &M) {
|
||||
else {
|
||||
|
||||
char modeline[100];
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s",
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
|
||||
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
|
||||
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
|
||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||
OKF("Instrumented %u locations with no collisions (on average %llu "
|
||||
"collisions would be in afl-gcc/afl-clang-fast) (%s mode).",
|
||||
|
@ -131,14 +131,40 @@ class AFLCoverage : public ModulePass {
|
||||
|
||||
char AFLCoverage::ID = 0;
|
||||
|
||||
/* needed up to 3.9.0 */
|
||||
#if LLVM_VERSION_MAJOR == 3 && \
|
||||
(LLVM_VERSION_MINOR < 9 || \
|
||||
(LLVM_VERSION_MINOR == 9 && LLVM_VERSION_PATCH < 1))
|
||||
uint64_t PowerOf2Ceil(unsigned in) {
|
||||
|
||||
uint64_t in64 = in - 1;
|
||||
in64 |= (in64 >> 1);
|
||||
in64 |= (in64 >> 2);
|
||||
in64 |= (in64 >> 4);
|
||||
in64 |= (in64 >> 8);
|
||||
in64 |= (in64 >> 16);
|
||||
in64 |= (in64 >> 32);
|
||||
return in64 + 1;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* #if LLVM_VERSION_STRING >= "4.0.1" */
|
||||
#if LLVM_VERSION_MAJOR >= 4 || \
|
||||
(LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
|
||||
#define AFL_HAVE_VECTOR_INTRINSICS 1
|
||||
#endif
|
||||
bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
LLVMContext &C = M.getContext();
|
||||
|
||||
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
|
||||
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
IntegerType *IntLocTy =
|
||||
IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT);
|
||||
#endif
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
u32 rand_seed;
|
||||
@ -179,27 +205,39 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
char *neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO");
|
||||
#endif
|
||||
|
||||
/* Decide previous location vector size (must be a power of two) */
|
||||
unsigned PrevLocSize;
|
||||
|
||||
char *ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
|
||||
if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
/* Decide previous location vector size (must be a power of two) */
|
||||
VectorType *PrevLocTy;
|
||||
|
||||
if (ngram_size_str)
|
||||
if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
|
||||
ngram_size > MAX_NGRAM_SIZE)
|
||||
FATAL(
|
||||
"Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE)");
|
||||
"Bad value of AFL_NGRAM_SIZE (must be between 2 and MAX_NGRAM_SIZE "
|
||||
"(%u))",
|
||||
MAX_NGRAM_SIZE);
|
||||
|
||||
unsigned PrevLocSize;
|
||||
if (ngram_size == 1) ngram_size = 0;
|
||||
if (ngram_size)
|
||||
PrevLocSize = ngram_size - 1;
|
||||
else
|
||||
#else
|
||||
if (ngram_size_str)
|
||||
FATAL(
|
||||
"Sorry, n-gram branch coverage is not supported with llvm version %s!",
|
||||
LLVM_VERSION_STRING);
|
||||
#endif
|
||||
PrevLocSize = 1;
|
||||
uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
|
||||
VectorType *PrevLocTy;
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
uint64_t PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
|
||||
if (ngram_size) PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize);
|
||||
#endif
|
||||
|
||||
/* Get globals for the SHM region and the previous location. Note that
|
||||
__afl_prev_loc is thread-local. */
|
||||
@ -209,6 +247,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
|
||||
GlobalVariable *AFLPrevLoc;
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
if (ngram_size)
|
||||
#ifdef __ANDROID__
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
@ -222,15 +261,17 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
/* AddressSpace */ 0, /* IsExternallyInitialized */ false);
|
||||
#endif
|
||||
else
|
||||
#endif
|
||||
#ifdef __ANDROID__
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
|
||||
#else
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
|
||||
GlobalVariable::GeneralDynamicTLSModel, 0, false);
|
||||
AFLPrevLoc = new GlobalVariable(
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
|
||||
GlobalVariable::GeneralDynamicTLSModel, 0, false);
|
||||
#endif
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
/* Create the vector shuffle mask for updating the previous block history.
|
||||
Note that the first element of the vector will store cur_loc, so just set
|
||||
it to undef to allow the optimizer to do its thing. */
|
||||
@ -244,6 +285,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
|
||||
|
||||
Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
|
||||
#endif
|
||||
|
||||
// other constants we need
|
||||
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
|
||||
@ -420,9 +462,11 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
ConstantInt *CurLoc;
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
if (ngram_size)
|
||||
CurLoc = ConstantInt::get(IntLocTy, cur_loc);
|
||||
else
|
||||
#endif
|
||||
CurLoc = ConstantInt::get(Int32Ty, cur_loc);
|
||||
|
||||
/* Load prev_loc */
|
||||
@ -431,6 +475,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
Value *PrevLocTrans;
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
/* "For efficiency, we propose to hash the tuple as a key into the
|
||||
hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where
|
||||
prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */
|
||||
@ -438,6 +483,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
if (ngram_size)
|
||||
PrevLocTrans = IRB.CreateXorReduce(PrevLoc);
|
||||
else
|
||||
#endif
|
||||
PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
|
||||
|
||||
/* Load SHM pointer */
|
||||
@ -446,11 +492,13 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
Value *MapPtrIdx;
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
if (ngram_size)
|
||||
MapPtrIdx = IRB.CreateGEP(
|
||||
MapPtr,
|
||||
IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, CurLoc), Int32Ty));
|
||||
else
|
||||
#endif
|
||||
MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, CurLoc));
|
||||
|
||||
/* Update bitmap */
|
||||
@ -536,6 +584,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
StoreInst *Store;
|
||||
|
||||
#ifdef AFL_HAVE_VECTOR_INTRINSICS
|
||||
if (ngram_size) {
|
||||
|
||||
Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
|
||||
@ -546,7 +595,10 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
Store = IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc);
|
||||
Store->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
} else {
|
||||
} else
|
||||
|
||||
#endif
|
||||
{
|
||||
|
||||
Store = IRB.CreateStore(ConstantInt::get(Int32Ty, cur_loc >> 1),
|
||||
AFLPrevLoc);
|
||||
@ -568,10 +620,11 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
else {
|
||||
|
||||
char modeline[100];
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s",
|
||||
snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
|
||||
getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
|
||||
getenv("AFL_USE_ASAN") ? ", ASAN" : "",
|
||||
getenv("AFL_USE_MSAN") ? ", MSAN" : "",
|
||||
getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
|
||||
getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
|
||||
OKF("Instrumented %u locations (%s mode, ratio %u%%).", inst_blocks,
|
||||
modeline, inst_ratio);
|
||||
|
@ -12,7 +12,7 @@ typedef u64 PREV_LOC_T;
|
||||
#endif
|
||||
|
||||
/* Maximum ngram size */
|
||||
#define MAX_NGRAM_SIZE 128
|
||||
#define MAX_NGRAM_SIZE 128U
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -52,6 +52,6 @@ ${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g
|
||||
echo "[+] Building afl-fuzz for Android"
|
||||
# build afl-fuzz
|
||||
cd ..
|
||||
${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-globals.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w
|
||||
${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-state.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w
|
||||
|
||||
echo "[+] All done. Enjoy!"
|
||||
|
@ -174,6 +174,8 @@ patch -p1 <../patches/configure.diff || exit 1
|
||||
patch -p1 <../patches/tcg-runtime.diff || exit 1
|
||||
patch -p1 <../patches/tcg-runtime-head.diff || exit 1
|
||||
patch -p1 <../patches/translator.diff || exit 1
|
||||
patch -p1 <../patches/__init__.py.diff || exit 1
|
||||
patch -p1 <../patches/make_strncpy_safe.diff || exit 1
|
||||
|
||||
echo "[+] Patching done."
|
||||
|
||||
|
17
qemu_mode/patches/__init__.py.diff
Normal file
17
qemu_mode/patches/__init__.py.diff
Normal file
@ -0,0 +1,17 @@
|
||||
--- a/scripts/tracetool/__init__.py 2020-03-28 13:42:21.937700726 +0100
|
||||
+++ b/scripts/tracetool/__init__.py 2020-03-28 13:41:50.991034257 +0100
|
||||
@@ -447,12 +447,12 @@
|
||||
import tracetool
|
||||
|
||||
format = str(format)
|
||||
- if len(format) is 0:
|
||||
+ if len(format) == 0:
|
||||
raise TracetoolError("format not set")
|
||||
if not tracetool.format.exists(format):
|
||||
raise TracetoolError("unknown format: %s" % format)
|
||||
|
||||
- if len(backends) is 0:
|
||||
+ if len(backends) == 0:
|
||||
raise TracetoolError("no backends specified")
|
||||
for backend in backends:
|
||||
if not tracetool.backend.exists(backend):
|
@ -413,7 +413,7 @@ void afl_forkserver(CPUState *cpu) {
|
||||
void afl_persistent_loop(void) {
|
||||
|
||||
static u32 cycle_cnt;
|
||||
static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, NULL};
|
||||
static struct afl_tsl exit_cmd_tsl = {{-1, 0, 0, 0}, '\0'};
|
||||
|
||||
if (!afl_fork_child) return;
|
||||
|
||||
|
@ -30,6 +30,7 @@
|
||||
have a look at afl-showmap.c.
|
||||
|
||||
*/
|
||||
void afl_gen_tcg_plain_call(void *func);
|
||||
|
||||
void afl_gen_tcg_plain_call(void *func) {
|
||||
|
||||
|
31
qemu_mode/patches/make_strncpy_safe.diff
Normal file
31
qemu_mode/patches/make_strncpy_safe.diff
Normal file
@ -0,0 +1,31 @@
|
||||
--- a/util/qemu-sockets.c 2020-03-28 13:55:09.511029429 +0100
|
||||
+++ b/util/qemu-sockets.c 2020-03-28 14:01:12.147693937 +0100
|
||||
@@ -877,7 +877,7 @@
|
||||
|
||||
memset(&un, 0, sizeof(un));
|
||||
un.sun_family = AF_UNIX;
|
||||
- strncpy(un.sun_path, path, sizeof(un.sun_path));
|
||||
+ strncpy(un.sun_path, path, sizeof(un.sun_path) - 1);
|
||||
|
||||
if (bind(sock, (struct sockaddr*) &un, sizeof(un)) < 0) {
|
||||
error_setg_errno(errp, errno, "Failed to bind socket to %s", path);
|
||||
@@ -922,7 +922,7 @@
|
||||
|
||||
memset(&un, 0, sizeof(un));
|
||||
un.sun_family = AF_UNIX;
|
||||
- strncpy(un.sun_path, saddr->path, sizeof(un.sun_path));
|
||||
+ strncpy(un.sun_path, saddr->path, sizeof(un.sun_path) - 1);
|
||||
|
||||
/* connect to peer */
|
||||
do {
|
||||
--- a/block/sheepdog.c 2020-03-28 14:01:57.164360270 +0100
|
||||
+++ b/block/sheepdog.c 2020-03-28 14:02:52.781026597 +0100
|
||||
@@ -1236,7 +1236,7 @@
|
||||
* don't want the send_req to read uninitialized data.
|
||||
*/
|
||||
strncpy(buf, filename, SD_MAX_VDI_LEN);
|
||||
- strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN);
|
||||
+ strncpy(buf + SD_MAX_VDI_LEN, tag, SD_MAX_VDI_TAG_LEN - 1);
|
||||
|
||||
memset(&hdr, 0, sizeof(hdr));
|
||||
if (lock) {
|
34
qemu_mode/unsigaction/GNUmakefile
Normal file
34
qemu_mode/unsigaction/GNUmakefile
Normal file
@ -0,0 +1,34 @@
|
||||
#
|
||||
# american fuzzy lop++ - unsigaction
|
||||
# --------------------------------
|
||||
#
|
||||
# Written by Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
#
|
||||
# Copyright 2019-2020 Andrea Fioraldi. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
all: lib_i386 lib_amd64
|
||||
|
||||
lib_i386:
|
||||
@$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
|
||||
|
||||
lib_amd64:
|
||||
$(CC) -fPIC -shared unsigaction.c -o unsigaction64.so
|
||||
|
||||
clean:
|
||||
rm -f unsigaction32.so unsigaction64.so
|
||||
|
||||
else
|
||||
|
||||
all:
|
||||
@echo "[!] Note: skipping compilation of unsigaction (AFL_NO_X86 set)."
|
||||
|
||||
endif
|
@ -1,34 +1,2 @@
|
||||
#
|
||||
# american fuzzy lop++ - unsigaction
|
||||
# --------------------------------
|
||||
#
|
||||
# Written by Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
#
|
||||
# Copyright 2019-2020 Andrea Fioraldi. All rights reserved.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
ifndef AFL_NO_X86
|
||||
|
||||
all: lib_i386 lib_amd64
|
||||
|
||||
lib_i386:
|
||||
@$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
|
||||
|
||||
lib_amd64:
|
||||
$(CC) -fPIC -shared unsigaction.c -o unsigaction64.so
|
||||
|
||||
clean:
|
||||
rm -f unsigaction32.so unsigaction64.so
|
||||
|
||||
else
|
||||
|
||||
all:
|
||||
@echo "[!] Note: skipping compilation of unsigaction (AFL_NO_X86 set)."
|
||||
|
||||
endif
|
||||
@echo please use GNU make, thanks!
|
||||
|
24
src/README.md
Normal file
24
src/README.md
Normal file
@ -0,0 +1,24 @@
|
||||
# Source Folder
|
||||
|
||||
Quick explanation about the files here:
|
||||
|
||||
- `afl-analyze.c` - afl-analyze binary tool
|
||||
- `afl-as.c` - afl-as binary tool
|
||||
- `afl-gotcpu.c` - afl-gotcpu binary tool
|
||||
- `afl-showmap.c` - afl-showmap binary tool
|
||||
- `afl-tmin.c` - afl-tmin binary tool
|
||||
- `afl-fuzz.c` - afl-fuzz binary tool (just main() and usage())
|
||||
- `afl-fuzz-bitmap.c` - afl-fuzz bitmap handling
|
||||
- `afl-fuzz-extras.c` - afl-fuzz the *extra* function calls
|
||||
- `afl-fuzz-state.c` - afl-fuzz state and globals
|
||||
- `afl-fuzz-init.c` - afl-fuzz initialization
|
||||
- `afl-fuzz-misc.c` - afl-fuzz misc functions
|
||||
- `afl-fuzz-one.c` - afl-fuzz fuzzer_one big loop, this is where the mutation is happening
|
||||
- `afl-fuzz-python.c` - afl-fuzz the python mutator extension
|
||||
- `afl-fuzz-queue.c` - afl-fuzz handling the queue
|
||||
- `afl-fuzz-run.c` - afl-fuzz running the target
|
||||
- `afl-fuzz-stats.c` - afl-fuzz writing the statistics file
|
||||
- `afl-gcc.c` - afl-gcc binary tool (deprecated)
|
||||
- `afl-common.c` - common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin
|
||||
- `afl-forkserver.c` - forkserver implementation, used by afl-fuzz and afl-tmin
|
||||
afl-sharedmem.c - sharedmem implementation, used by afl-fuzz and afl-tmin
|
@ -1,22 +0,0 @@
|
||||
Quick explanation about the files here:
|
||||
|
||||
afl-analyze.c - afl-analyze binary tool
|
||||
afl-as.c - afl-as binary tool
|
||||
afl-gotcpu.c - afl-gotcpu binary tool
|
||||
afl-showmap.c - afl-showmap binary tool
|
||||
afl-tmin.c - afl-tmin binary tool
|
||||
afl-fuzz.c - afl-fuzz binary tool (just main() and usage())
|
||||
afl-fuzz-bitmap.c - afl-fuzz bitmap handling
|
||||
afl-fuzz-extras.c - afl-fuzz the *extra* function calls
|
||||
afl-fuzz-globals.c - afl-fuzz global variables
|
||||
afl-fuzz-init.c - afl-fuzz initialization
|
||||
afl-fuzz-misc.c - afl-fuzz misc functions
|
||||
afl-fuzz-one.c - afl-fuzz fuzzer_one big loop, this is where the mutation is happening
|
||||
afl-fuzz-python.c - afl-fuzz the python mutator extension
|
||||
afl-fuzz-queue.c - afl-fuzz handling the queue
|
||||
afl-fuzz-run.c - afl-fuzz running the target
|
||||
afl-fuzz-stats.c - afl-fuzz writing the statistics file
|
||||
afl-gcc.c - afl-gcc binary tool (deprecated)
|
||||
afl-common.c - common functions, used by afl-analyze, afl-fuzz, afl-showmap and afl-tmin
|
||||
afl-forkserver.c - forkserver implementation, used by afl-fuzz and afl-tmin
|
||||
afl-sharedmem.c - sharedmem implementation, used by afl-fuzz and afl-tmin
|
@ -60,8 +60,7 @@ static s32 child_pid; /* PID of the tested program */
|
||||
u8 *trace_bits; /* SHM with instrumentation bitmap */
|
||||
|
||||
static u8 *in_file, /* Analyzer input test case */
|
||||
*prog_in, /* Targeted program input file */
|
||||
*doc_path; /* Path to docs */
|
||||
*prog_in; /* Targeted program input file */
|
||||
|
||||
static u8 *in_data; /* Input data for analysis */
|
||||
|
||||
@ -77,7 +76,7 @@ static s32 dev_null_fd = -1; /* FD to /dev/null */
|
||||
|
||||
u8 edges_only, /* Ignore hit counts? */
|
||||
use_hex_offsets, /* Show hex offsets? */
|
||||
be_quiet, use_stdin = 1; /* Use stdin for program input? */
|
||||
use_stdin = 1; /* Use stdin for program input? */
|
||||
|
||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
child_timed_out; /* Child timed out? */
|
||||
|
399
src/afl-common.c
399
src/afl-common.c
@ -30,6 +30,7 @@
|
||||
#include "debug.h"
|
||||
#include "alloc-inl.h"
|
||||
#include "envs.h"
|
||||
#include "common.h"
|
||||
|
||||
/* Detect @@ in args. */
|
||||
#ifndef __glibc__
|
||||
@ -37,8 +38,10 @@
|
||||
#endif
|
||||
#include <limits.h>
|
||||
|
||||
extern u8 be_quiet;
|
||||
char * afl_environment_variables[] = {
|
||||
u8 be_quiet = 0;
|
||||
u8 *doc_path = "";
|
||||
|
||||
char *afl_environment_variables[] = {
|
||||
|
||||
"AFL_ALIGNED_ALLOC", "AFL_ALLOW_TMP", "AFL_ANALYZE_HEX", "AFL_AS",
|
||||
"AFL_AUTORESUME", "AFL_AS_FORCE_INSTRUMENT", "AFL_BENCH_JUST_ONE",
|
||||
@ -73,7 +76,7 @@ char * afl_environment_variables[] = {
|
||||
"AFL_SHUFFLE_QUEUE", "AFL_SKIP_BIN_CHECK", "AFL_SKIP_CPUFREQ",
|
||||
"AFL_SKIP_CRASHES", "AFL_TMIN_EXACT", "AFL_TMPDIR", "AFL_TOKEN_FILE",
|
||||
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
|
||||
"AFL_USE_UBSAN", "AFL_WINE_PATH", NULL};
|
||||
"AFL_USE_UBSAN", "AFL_USE_CFISAN", "AFL_WINE_PATH", NULL};
|
||||
|
||||
void detect_file_args(char **argv, u8 *prog_in, u8 *use_stdin) {
|
||||
|
||||
@ -393,3 +396,393 @@ char *get_afl_env(char *env) {
|
||||
|
||||
}
|
||||
|
||||
u64 get_cur_time(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
|
||||
|
||||
}
|
||||
|
||||
/* Get unix time in microseconds */
|
||||
|
||||
u64 get_cur_time_us(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
gettimeofday(&tv, &tz);
|
||||
|
||||
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
|
||||
|
||||
}
|
||||
|
||||
/* Describe integer. The buf should be
|
||||
at least 6 bytes to fit all ints we randomly see.
|
||||
Will return buf for convenience. */
|
||||
|
||||
u8 *stringify_int(u8 *buf, size_t len, u64 val) {
|
||||
\
|
||||
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
|
||||
do { \
|
||||
\
|
||||
if (val < (_divisor) * (_limit_mult)) { \
|
||||
\
|
||||
snprintf(buf, len, _fmt, ((_cast)val) / (_divisor)); \
|
||||
return buf; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1000, 99.95, "%0.01fk", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1000, 1000, "%lluk", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
|
||||
|
||||
/* 100T+ */
|
||||
strncpy(buf, "infty", len);
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Describe float. Similar as int. */
|
||||
|
||||
u8 *stringify_float(u8 *buf, size_t len, double val) {
|
||||
|
||||
if (val < 99.995) {
|
||||
|
||||
snprintf(buf, len, "%0.02f", val);
|
||||
|
||||
} else if (val < 999.95) {
|
||||
|
||||
snprintf(buf, len, "%0.01f", val);
|
||||
|
||||
} else {
|
||||
|
||||
stringify_int(buf, len, (u64)val);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Describe integer as memory size. */
|
||||
|
||||
u8 *stringify_mem_size(u8 *buf, size_t len, u64 val) {
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu B", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1024, 1000, "%llu kB", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
|
||||
|
||||
#undef CHK_FORMAT
|
||||
|
||||
/* 100T+ */
|
||||
strncpy(buf, "infty", len - 1);
|
||||
buf[len - 1] = '\0';
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Describe time delta as string.
|
||||
Returns a pointer to buf for convenience. */
|
||||
|
||||
u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
|
||||
|
||||
u64 delta;
|
||||
s32 t_d, t_h, t_m, t_s;
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
if (!event_ms) {
|
||||
|
||||
snprintf(buf, len, "none seen yet");
|
||||
|
||||
} else {
|
||||
|
||||
delta = cur_ms - event_ms;
|
||||
|
||||
t_d = delta / 1000 / 60 / 60 / 24;
|
||||
t_h = (delta / 1000 / 60 / 60) % 24;
|
||||
t_m = (delta / 1000 / 60) % 60;
|
||||
t_s = (delta / 1000) % 60;
|
||||
|
||||
stringify_int(val_buf, sizeof(val_buf), t_d);
|
||||
snprintf(buf, len, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m,
|
||||
t_s);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Unsafe Describe integer. The buf sizes are not checked.
|
||||
This is unsafe but fast.
|
||||
Will return buf for convenience. */
|
||||
|
||||
u8 *u_stringify_int(u8 *buf, u64 val) {
|
||||
\
|
||||
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
|
||||
do { \
|
||||
\
|
||||
if (val < (_divisor) * (_limit_mult)) { \
|
||||
\
|
||||
sprintf(buf, _fmt, ((_cast)val) / (_divisor)); \
|
||||
return buf; \
|
||||
\
|
||||
} \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1000, 99.95, "%0.01fk", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1000, 1000, "%lluk", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1000 * 1000, 9.995, "%0.02fM", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1000 * 1000, 99.95, "%0.01fM", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1000 * 1000, 1000, "%lluM", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 9.995, "%0.02fG", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 99.95, "%0.01fG", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000, 1000, "%lluG", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 9.995, "%0.02fT", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1000LL * 1000 * 1000 * 1000, 99.95, "%0.01fT", double);
|
||||
|
||||
/* 100T+ */
|
||||
strcpy(buf, "infty");
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Unsafe describe float. Similar as unsafe int. */
|
||||
|
||||
u8 *u_stringify_float(u8 *buf, double val) {
|
||||
|
||||
if (val < 99.995) {
|
||||
|
||||
sprintf(buf, "%0.02f", val);
|
||||
|
||||
} else if (val < 999.95) {
|
||||
|
||||
sprintf(buf, "%0.01f", val);
|
||||
|
||||
} else {
|
||||
|
||||
return u_stringify_int(buf, (u64)val);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Unsafe describe integer as memory size. */
|
||||
|
||||
u8 *u_stringify_mem_size(u8 *buf, u64 val) {
|
||||
|
||||
/* 0-9999 */
|
||||
CHK_FORMAT(1, 10000, "%llu B", u64);
|
||||
|
||||
/* 10.0k - 99.9k */
|
||||
CHK_FORMAT(1024, 99.95, "%0.01f kB", double);
|
||||
|
||||
/* 100k - 999k */
|
||||
CHK_FORMAT(1024, 1000, "%llu kB", u64);
|
||||
|
||||
/* 1.00M - 9.99M */
|
||||
CHK_FORMAT(1024 * 1024, 9.995, "%0.02f MB", double);
|
||||
|
||||
/* 10.0M - 99.9M */
|
||||
CHK_FORMAT(1024 * 1024, 99.95, "%0.01f MB", double);
|
||||
|
||||
/* 100M - 999M */
|
||||
CHK_FORMAT(1024 * 1024, 1000, "%llu MB", u64);
|
||||
|
||||
/* 1.00G - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 9.995, "%0.02f GB", double);
|
||||
|
||||
/* 10.0G - 99.9G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 99.95, "%0.01f GB", double);
|
||||
|
||||
/* 100G - 999G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024, 1000, "%llu GB", u64);
|
||||
|
||||
/* 1.00T - 9.99G */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 9.995, "%0.02f TB", double);
|
||||
|
||||
/* 10.0T - 99.9T */
|
||||
CHK_FORMAT(1024LL * 1024 * 1024 * 1024, 99.95, "%0.01f TB", double);
|
||||
|
||||
#undef CHK_FORMAT
|
||||
|
||||
/* 100T+ */
|
||||
strcpy(buf, "infty");
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Unsafe describe time delta as string.
|
||||
Returns a pointer to buf for convenience. */
|
||||
|
||||
u8 *u_stringify_time_diff(u8 *buf, u64 cur_ms, u64 event_ms) {
|
||||
|
||||
u64 delta;
|
||||
s32 t_d, t_h, t_m, t_s;
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
if (!event_ms) {
|
||||
|
||||
sprintf(buf, "none seen yet");
|
||||
|
||||
} else {
|
||||
|
||||
delta = cur_ms - event_ms;
|
||||
|
||||
t_d = delta / 1000 / 60 / 60 / 24;
|
||||
t_h = (delta / 1000 / 60 / 60) % 24;
|
||||
t_m = (delta / 1000 / 60) % 60;
|
||||
t_s = (delta / 1000) % 60;
|
||||
|
||||
u_stringify_int(val_buf, t_d);
|
||||
sprintf(buf, "%s days, %d hrs, %d min, %d sec", val_buf, t_h, t_m, t_s);
|
||||
|
||||
}
|
||||
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
/* Wrapper for select() and read(), reading exactly len bytes.
|
||||
Returns the time passed to read.
|
||||
If the wait times out, returns timeout_ms + 1;
|
||||
Returns 0 if an error occurred (fd closed, signal, ...); */
|
||||
u32 read_timed(s32 fd, void *buf, size_t len, u32 timeout_ms) {
|
||||
|
||||
struct timeval timeout;
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fd, &readfds);
|
||||
|
||||
timeout.tv_sec = (timeout_ms / 1000);
|
||||
timeout.tv_usec = (timeout_ms % 1000) * 1000;
|
||||
|
||||
size_t read_total = 0;
|
||||
size_t len_read = 0;
|
||||
|
||||
while (len_read < len) {
|
||||
|
||||
/* set exceptfds as well to return when a child exited/closed the pipe. */
|
||||
int sret = select(fd + 1, &readfds, NULL, NULL, &timeout);
|
||||
|
||||
if (!sret) {
|
||||
|
||||
// printf("Timeout in sret.");
|
||||
return timeout_ms + 1;
|
||||
|
||||
} else if (sret < 0) {
|
||||
|
||||
// perror("sret malloc");
|
||||
// TODO: catch other (errno == EINTR) than ctrl+c?
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
len_read = read(fd, ((u8 *)buf) + len_read, len - len_read);
|
||||
if (!len_read) { return 0; }
|
||||
read_total += len_read;
|
||||
|
||||
}
|
||||
|
||||
s32 exec_ms =
|
||||
MIN(timeout_ms,
|
||||
((u64)timeout_ms - (timeout.tv_sec * 1000 + timeout.tv_usec / 1000)));
|
||||
return exec_ms > 0 ? exec_ms
|
||||
: 1; // at least 1 milli must have passed (0 is an error)
|
||||
|
||||
}
|
||||
|
||||
|
@ -49,8 +49,6 @@
|
||||
|
||||
/* Describe integer as memory size. */
|
||||
|
||||
extern u8 *doc_path;
|
||||
|
||||
list_t fsrv_list = {.element_prealloc_count = 0};
|
||||
|
||||
/* Initializes the struct */
|
||||
@ -164,10 +162,9 @@ static void afl_fauxsrv_execv(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
struct timeval timeout;
|
||||
int st_pipe[2], ctl_pipe[2];
|
||||
int status;
|
||||
s32 rlen;
|
||||
int st_pipe[2], ctl_pipe[2];
|
||||
int status;
|
||||
s32 rlen;
|
||||
|
||||
if (fsrv->use_fauxsrv) ACTF("Using Fauxserver:");
|
||||
|
||||
@ -318,26 +315,19 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv) {
|
||||
rlen = 0;
|
||||
if (fsrv->exec_tmout) {
|
||||
|
||||
fd_set readfds;
|
||||
rlen = 4;
|
||||
u32 time = read_timed(fsrv->fsrv_st_fd, &status, rlen,
|
||||
fsrv->exec_tmout * FORK_WAIT_MULT);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(fsrv->fsrv_st_fd, &readfds);
|
||||
timeout.tv_sec = ((fsrv->exec_tmout * FORK_WAIT_MULT) / 1000);
|
||||
timeout.tv_usec = ((fsrv->exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
|
||||
|
||||
int sret = select(fsrv->fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
|
||||
|
||||
if (sret == 0) {
|
||||
if (time > fsrv->exec_tmout * FORK_WAIT_MULT) {
|
||||
|
||||
fsrv->child_timed_out = 1;
|
||||
kill(fsrv->child_pid, SIGKILL);
|
||||
|
||||
} else {
|
||||
|
||||
rlen = read(fsrv->fsrv_st_fd, &status, 4);
|
||||
kill(fsrv->fsrv_pid, SIGKILL);
|
||||
|
||||
}
|
||||
|
||||
if (!time) { kill(fsrv->fsrv_pid, SIGKILL); }
|
||||
|
||||
} else {
|
||||
|
||||
rlen = read(fsrv->fsrv_st_fd, &status, 4);
|
||||
|
@ -31,13 +31,13 @@
|
||||
|
||||
void write_bitmap(afl_state_t *afl) {
|
||||
|
||||
u8 *fname;
|
||||
u8 fname[PATH_MAX];
|
||||
s32 fd;
|
||||
|
||||
if (!afl->bitmap_changed) return;
|
||||
afl->bitmap_changed = 0;
|
||||
|
||||
fname = alloc_printf("%s/fuzz_bitmap", afl->out_dir);
|
||||
snprintf(fname, PATH_MAX, "%s/fuzz_bitmap", afl->out_dir);
|
||||
fd = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", fname);
|
||||
@ -45,7 +45,6 @@ void write_bitmap(afl_state_t *afl) {
|
||||
ck_write(fd, afl->virgin_bits, MAP_SIZE, fname);
|
||||
|
||||
close(fd);
|
||||
ck_free(fname);
|
||||
|
||||
}
|
||||
|
||||
@ -462,14 +461,15 @@ u8 *describe_op(afl_state_t *afl, u8 hnb) {
|
||||
|
||||
static void write_crash_readme(afl_state_t *afl) {
|
||||
|
||||
u8 * fn = alloc_printf("%s/crashes/README.txt", afl->out_dir);
|
||||
u8 fn[PATH_MAX];
|
||||
s32 fd;
|
||||
FILE *f;
|
||||
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
|
||||
sprintf(fn, "%s/crashes/README.txt", afl->out_dir);
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
ck_free(fn);
|
||||
|
||||
/* Do not die on errors here - that would be impolite. */
|
||||
|
||||
@ -520,11 +520,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
if (unlikely(len == 0)) return 0;
|
||||
|
||||
u8 *fn = "";
|
||||
u8 *queue_fn = "";
|
||||
u8 hnb;
|
||||
s32 fd;
|
||||
u8 keeping = 0, res;
|
||||
|
||||
u8 fn[PATH_MAX];
|
||||
|
||||
/* Update path frequency. */
|
||||
u32 cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
|
||||
|
||||
@ -556,16 +558,17 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir, afl->queued_paths,
|
||||
describe_op(afl, hnb));
|
||||
queue_fn = alloc_printf("%s/queue/id:%06u,%s", afl->out_dir,
|
||||
afl->queued_paths, describe_op(afl, hnb));
|
||||
|
||||
#else
|
||||
|
||||
fn = alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
|
||||
queue_fn =
|
||||
alloc_printf("%s/queue/id_%06u", afl->out_dir, afl->queued_paths);
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
add_to_queue(afl, fn, len, 0);
|
||||
add_to_queue(afl, queue_fn, len, 0);
|
||||
|
||||
if (hnb == 2) {
|
||||
|
||||
@ -584,9 +587,9 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
if (unlikely(res == FAULT_ERROR))
|
||||
FATAL("Unable to execute target application");
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", fn);
|
||||
ck_write(fd, mem, len, fn);
|
||||
fd = open(queue_fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (unlikely(fd < 0)) PFATAL("Unable to create '%s'", queue_fn);
|
||||
ck_write(fd, mem, len, queue_fn);
|
||||
close(fd);
|
||||
|
||||
keeping = 1;
|
||||
@ -642,12 +645,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
fn = alloc_printf("%s/hangs/id:%06llu,%s", afl->out_dir,
|
||||
afl->unique_hangs, describe_op(afl, 0));
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/id:%06llu,%s", afl->out_dir,
|
||||
afl->unique_hangs, describe_op(afl, 0));
|
||||
|
||||
#else
|
||||
|
||||
fn = alloc_printf("%s/hangs/id_%06llu", afl->out_dir, afl->unique_hangs);
|
||||
snprintf(fn, PATH_MAX, "%s/hangs/id_%06llu", afl->out_dir,
|
||||
afl->unique_hangs);
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
@ -685,14 +689,13 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
|
||||
fn = alloc_printf("%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
||||
afl->unique_crashes, afl->kill_signal,
|
||||
describe_op(afl, 0));
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/id:%06llu,sig:%02u,%s", afl->out_dir,
|
||||
afl->unique_crashes, afl->kill_signal, describe_op(afl, 0));
|
||||
|
||||
#else
|
||||
|
||||
fn = alloc_printf("%s/crashes/id_%06llu_%02u", afl->out_dir,
|
||||
afl->unique_crashes, afl->kill_signal);
|
||||
snprintf(fn, PATH_MAX, "%s/crashes/id_%06llu_%02u", afl->out_dir,
|
||||
afl->unique_crashes, afl->kill_signal);
|
||||
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
@ -729,8 +732,6 @@ u8 save_if_interesting(afl_state_t *afl, void *mem, u32 len, u8 fault) {
|
||||
ck_write(fd, mem, len, fn);
|
||||
close(fd);
|
||||
|
||||
ck_free(fn);
|
||||
|
||||
return keeping;
|
||||
|
||||
}
|
||||
|
@ -31,10 +31,9 @@
|
||||
|
||||
void init_cmplog_forkserver(afl_state_t *afl) {
|
||||
|
||||
struct timeval timeout;
|
||||
int st_pipe[2], ctl_pipe[2];
|
||||
int status;
|
||||
s32 rlen;
|
||||
int st_pipe[2], ctl_pipe[2];
|
||||
int status;
|
||||
s32 rlen;
|
||||
|
||||
ACTF("Spinning up the cmplog fork server...");
|
||||
|
||||
@ -185,21 +184,19 @@ void init_cmplog_forkserver(afl_state_t *afl) {
|
||||
rlen = 0;
|
||||
if (afl->fsrv.exec_tmout) {
|
||||
|
||||
fd_set readfds;
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
|
||||
timeout.tv_sec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) / 1000);
|
||||
timeout.tv_usec = ((afl->fsrv.exec_tmout * FORK_WAIT_MULT) % 1000) * 1000;
|
||||
rlen = 4;
|
||||
u32 timeout_ms = afl->fsrv.exec_tmout * FORK_WAIT_MULT;
|
||||
/* Reuse readfds as exceptfds to see when the child closed the pipe */
|
||||
u32 exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, rlen, timeout_ms);
|
||||
|
||||
int sret =
|
||||
select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &timeout);
|
||||
if (!exec_ms) {
|
||||
|
||||
if (sret == 0) {
|
||||
PFATAL("Error in timed read");
|
||||
|
||||
} else if (exec_ms > timeout_ms) {
|
||||
|
||||
afl->fsrv.child_timed_out = 1;
|
||||
kill(afl->cmplog_fsrv_pid, SIGKILL);
|
||||
|
||||
} else {
|
||||
|
||||
rlen = read(afl->cmplog_fsrv_st_fd, &status, 4);
|
||||
|
||||
}
|
||||
@ -213,6 +210,11 @@ void init_cmplog_forkserver(afl_state_t *afl) {
|
||||
/* If we have a four-byte "hello" message from the server, we're all set.
|
||||
Otherwise, try to figure out what went wrong. */
|
||||
|
||||
if (afl->fsrv.child_timed_out)
|
||||
FATAL(
|
||||
"Timeout while initializing cmplog fork server (adjusting -t may "
|
||||
"help)");
|
||||
|
||||
if (rlen == 4) {
|
||||
|
||||
OKF("All right - fork server is up.");
|
||||
@ -220,11 +222,6 @@ void init_cmplog_forkserver(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
if (afl->fsrv.child_timed_out)
|
||||
FATAL(
|
||||
"Timeout while initializing cmplog fork server (adjusting -t may "
|
||||
"help)");
|
||||
|
||||
if (waitpid(afl->cmplog_fsrv_pid, &status, 0) <= 0)
|
||||
PFATAL("waitpid() failed");
|
||||
|
||||
@ -379,16 +376,12 @@ void init_cmplog_forkserver(afl_state_t *afl) {
|
||||
|
||||
u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
|
||||
|
||||
struct timeval it;
|
||||
int status = 0;
|
||||
int sret;
|
||||
u64 exec_ms;
|
||||
int status = 0;
|
||||
u32 exec_ms;
|
||||
|
||||
u32 tb4;
|
||||
s32 res;
|
||||
|
||||
fd_set readfds;
|
||||
|
||||
afl->fsrv.child_timed_out = 0;
|
||||
|
||||
/* After this memset, afl->fsrv.trace_bits[] are effectively volatile, so we
|
||||
@ -423,18 +416,9 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
|
||||
|
||||
/* Configure timeout, as requested by user, then wait for child to terminate.
|
||||
*/
|
||||
exec_ms = read_timed(afl->cmplog_fsrv_st_fd, &status, 4, timeout);
|
||||
|
||||
it.tv_sec = (timeout / 1000);
|
||||
it.tv_usec = (timeout % 1000) * 1000;
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(afl->cmplog_fsrv_st_fd, &readfds);
|
||||
it.tv_sec = ((timeout) / 1000);
|
||||
it.tv_usec = ((timeout) % 1000) * 1000;
|
||||
|
||||
sret = select(afl->cmplog_fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
|
||||
|
||||
if (sret == 0) {
|
||||
if (exec_ms > timeout) {
|
||||
|
||||
/* If there was no response from forkserver after timeout seconds,
|
||||
we kill the child. The forkserver should inform us afterwards */
|
||||
@ -442,9 +426,12 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
|
||||
kill(afl->cmplog_child_pid, SIGKILL);
|
||||
afl->fsrv.child_timed_out = 1;
|
||||
|
||||
/* After killing the child, the forkserver should tell us */
|
||||
if (!read(afl->cmplog_fsrv_st_fd, &status, 4)) exec_ms = 0;
|
||||
|
||||
}
|
||||
|
||||
if ((res = read(afl->cmplog_fsrv_st_fd, &status, 4)) != 4) {
|
||||
if (!exec_ms) { // Something went wrong.
|
||||
|
||||
if (afl->stop_soon) return 0;
|
||||
SAYF("\n" cLRD "[-] " cRST
|
||||
@ -467,12 +454,8 @@ u8 run_cmplog_target(afl_state_t *afl, u32 timeout) {
|
||||
|
||||
if (!WIFSTOPPED(status)) afl->cmplog_child_pid = 0;
|
||||
|
||||
exec_ms = (u64)timeout - (it.tv_sec * 1000 + it.tv_usec / 1000);
|
||||
if (afl->slowest_exec_ms < exec_ms) afl->slowest_exec_ms = exec_ms;
|
||||
|
||||
it.tv_sec = 0;
|
||||
it.tv_usec = 0;
|
||||
|
||||
++afl->total_execs;
|
||||
|
||||
/* Any subsequent operations on afl->fsrv.trace_bits must not be moved by the
|
||||
@ -527,8 +510,13 @@ u8 common_fuzz_cmplog_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
if (afl->post_handler) {
|
||||
|
||||
out_buf = afl->post_handler(out_buf, &len);
|
||||
if (!out_buf || !len) return 0;
|
||||
u8 *post_buf = NULL;
|
||||
|
||||
size_t post_len =
|
||||
afl->post_handler(afl->post_data, out_buf, len, &post_buf);
|
||||
if (!post_buf || !post_len) return 0;
|
||||
out_buf = post_buf;
|
||||
len = post_len;
|
||||
|
||||
}
|
||||
|
||||
|
@ -76,21 +76,16 @@ void bind_to_free_cpu(afl_state_t *afl) {
|
||||
|
||||
while ((de = readdir(d))) {
|
||||
|
||||
u8 * fn;
|
||||
u8 fn[PATH_MAX];
|
||||
FILE *f;
|
||||
u8 tmp[MAX_LINE];
|
||||
u8 has_vmsize = 0;
|
||||
|
||||
if (!isdigit(de->d_name[0])) continue;
|
||||
|
||||
fn = alloc_printf("/proc/%s/status", de->d_name);
|
||||
snprintf(fn, PATH_MAX, "/proc/%s/status", de->d_name);
|
||||
|
||||
if (!(f = fopen(fn, "r"))) {
|
||||
|
||||
ck_free(fn);
|
||||
continue;
|
||||
|
||||
}
|
||||
if (!(f = fopen(fn, "r"))) { continue; }
|
||||
|
||||
while (fgets(tmp, MAX_LINE, f)) {
|
||||
|
||||
@ -111,7 +106,6 @@ void bind_to_free_cpu(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
ck_free(fn);
|
||||
fclose(f);
|
||||
|
||||
}
|
||||
@ -276,7 +270,9 @@ void setup_post(afl_state_t *afl) {
|
||||
|
||||
void *dh;
|
||||
u8 * fn = afl->afl_env.afl_post_library;
|
||||
u8 tbuf[6];
|
||||
u32 tlen = 6;
|
||||
strncpy(tbuf, "hello", tlen);
|
||||
|
||||
if (!fn) return;
|
||||
|
||||
@ -287,10 +283,20 @@ void setup_post(afl_state_t *afl) {
|
||||
|
||||
afl->post_handler = dlsym(dh, "afl_postprocess");
|
||||
if (!afl->post_handler) FATAL("Symbol 'afl_postprocess' not found.");
|
||||
afl->post_init = dlsym(dh, "afl_postprocess_init");
|
||||
if (!afl->post_init) FATAL("Symbol 'afl_postprocess_init' not found.");
|
||||
afl->post_deinit = dlsym(dh, "afl_postprocess_deinit");
|
||||
if (!afl->post_deinit) FATAL("Symbol 'afl_postprocess_deinit' not found.");
|
||||
|
||||
/* Do a quick test. It's better to segfault now than later =) */
|
||||
|
||||
afl->post_handler("hello", &tlen);
|
||||
u8 *post_buf = NULL;
|
||||
afl->post_data = afl->post_init(afl);
|
||||
if (!afl->post_data) FATAL("Could not initialize post handler.");
|
||||
|
||||
size_t post_len = afl->post_handler(afl->post_data, tbuf, tlen, &post_buf);
|
||||
if (!post_len || !post_buf)
|
||||
SAYF("Empty return in test post handler for buf=\"hello\\0\".");
|
||||
|
||||
OKF("Postprocessor installed successfully.");
|
||||
|
||||
@ -369,9 +375,10 @@ void read_testcases(afl_state_t *afl) {
|
||||
|
||||
struct stat st;
|
||||
|
||||
u8 dfn[PATH_MAX];
|
||||
snprintf(dfn, PATH_MAX, "%s/.state/deterministic_done/%s", afl->in_dir,
|
||||
nl[i]->d_name);
|
||||
u8 *fn2 = alloc_printf("%s/%s", afl->in_dir, nl[i]->d_name);
|
||||
u8 *dfn = alloc_printf("%s/.state/deterministic_done/%s", afl->in_dir,
|
||||
nl[i]->d_name);
|
||||
|
||||
u8 passed_det = 0;
|
||||
|
||||
@ -385,7 +392,6 @@ void read_testcases(afl_state_t *afl) {
|
||||
if (!S_ISREG(st.st_mode) || !st.st_size || strstr(fn2, "/README.txt")) {
|
||||
|
||||
ck_free(fn2);
|
||||
ck_free(dfn);
|
||||
continue;
|
||||
|
||||
}
|
||||
@ -401,7 +407,6 @@ void read_testcases(afl_state_t *afl) {
|
||||
and probably very time-consuming. */
|
||||
|
||||
if (!access(dfn, F_OK)) passed_det = 1;
|
||||
ck_free(dfn);
|
||||
|
||||
add_to_queue(afl, fn2, st.st_size, passed_det);
|
||||
|
||||
|
@ -7,6 +7,7 @@
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
Dominik Maier <mail@dmnk.co>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2020 AFLplusplus Project. All rights reserved.
|
||||
@ -78,8 +79,15 @@ void destroy_custom_mutator(afl_state_t *afl) {
|
||||
|
||||
afl->mutator->afl_custom_deinit(afl->mutator->data);
|
||||
|
||||
if (afl->mutator->dh)
|
||||
dlclose(afl->mutator->dh);
|
||||
if (afl->mutator->dh) dlclose(afl->mutator->dh);
|
||||
|
||||
if (afl->mutator->pre_save_buf) {
|
||||
|
||||
ck_free(afl->mutator->pre_save_buf);
|
||||
afl->mutator->pre_save_buf = NULL;
|
||||
afl->mutator->pre_save_size = 0;
|
||||
|
||||
}
|
||||
|
||||
ck_free(afl->mutator);
|
||||
afl->mutator = NULL;
|
||||
@ -92,6 +100,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
|
||||
void *dh;
|
||||
afl->mutator = ck_alloc(sizeof(struct custom_mutator));
|
||||
afl->mutator->pre_save_buf = NULL;
|
||||
afl->mutator->pre_save_size = 0;
|
||||
|
||||
afl->mutator->name = fn;
|
||||
ACTF("Loading custom mutator library from '%s'...", fn);
|
||||
@ -103,11 +113,13 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
/* Mutator */
|
||||
/* "afl_custom_init", required */
|
||||
afl->mutator->afl_custom_init = dlsym(dh, "afl_custom_init");
|
||||
if (!afl->mutator->afl_custom_init) FATAL("Symbol 'afl_custom_init' not found.");
|
||||
if (!afl->mutator->afl_custom_init)
|
||||
FATAL("Symbol 'afl_custom_init' not found.");
|
||||
|
||||
/* "afl_custom_deinit", required */
|
||||
afl->mutator->afl_custom_deinit = dlsym(dh, "afl_custom_deinit");
|
||||
if (!afl->mutator->afl_custom_deinit) FATAL("Symbol 'afl_custom_deinit' not found.");
|
||||
if (!afl->mutator->afl_custom_deinit)
|
||||
FATAL("Symbol 'afl_custom_deinit' not found.");
|
||||
|
||||
/* "afl_custom_fuzz" or "afl_custom_mutator", required */
|
||||
afl->mutator->afl_custom_fuzz = dlsym(dh, "afl_custom_fuzz");
|
||||
@ -181,7 +193,8 @@ void load_custom_mutator(afl_state_t *afl, const char *fn) {
|
||||
|
||||
/* Initialize the custom mutator */
|
||||
if (afl->mutator->afl_custom_init)
|
||||
afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
|
||||
afl->mutator->data =
|
||||
afl->mutator->afl_custom_init(afl, rand_below(afl, 0xFFFFFFFF));
|
||||
|
||||
}
|
||||
|
||||
@ -198,24 +211,28 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
/* Initialize trimming in the custom mutator */
|
||||
afl->stage_cur = 0;
|
||||
afl->stage_max = afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
|
||||
|
||||
afl->stage_max =
|
||||
afl->mutator->afl_custom_init_trim(afl->mutator->data, in_buf, q->len);
|
||||
if (unlikely(afl->stage_max) < 0)
|
||||
FATAL("custom_init_trim error ret: %d", afl->stage_max);
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
SAYF("[Custom Trimming] START: Max %d iterations, %u bytes", afl->stage_max,
|
||||
q->len);
|
||||
|
||||
while (afl->stage_cur < afl->stage_max) {
|
||||
|
||||
sprintf(afl->stage_name_buf, "ptrim %s", u_stringify_int(val_buf, trim_exec));
|
||||
u8 *retbuf = NULL;
|
||||
|
||||
sprintf(afl->stage_name_buf, "ptrim %s",
|
||||
u_stringify_int(val_buf, trim_exec));
|
||||
|
||||
u32 cksum;
|
||||
|
||||
u8 * retbuf = NULL;
|
||||
size_t retlen = 0;
|
||||
size_t retlen = afl->mutator->afl_custom_trim(afl->mutator->data, &retbuf);
|
||||
|
||||
afl->mutator->afl_custom_trim(afl, &retbuf, &retlen);
|
||||
|
||||
if (retlen > orig_len)
|
||||
if (unlikely(!retbuf))
|
||||
FATAL("custom_trim failed (ret %zd)", retlen);
|
||||
else if (unlikely(retlen > orig_len))
|
||||
FATAL(
|
||||
"Trimmed data returned by custom mutator is larger than original "
|
||||
"data");
|
||||
@ -225,12 +242,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
fault = run_target(afl, afl->fsrv.exec_tmout);
|
||||
++afl->trim_execs;
|
||||
|
||||
if (afl->stop_soon || fault == FAULT_ERROR) {
|
||||
|
||||
ck_free(retbuf);
|
||||
goto abort_trimming;
|
||||
|
||||
}
|
||||
if (afl->stop_soon || fault == FAULT_ERROR) { goto abort_trimming; }
|
||||
|
||||
cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
|
||||
|
||||
@ -250,7 +262,8 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
}
|
||||
|
||||
/* Tell the custom mutator that the trimming was successful */
|
||||
afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 1);
|
||||
afl->stage_cur =
|
||||
afl->mutator->afl_custom_post_trim(afl->mutator->data, 1);
|
||||
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
SAYF("[Custom Trimming] SUCCESS: %d/%d iterations (now at %u bytes)",
|
||||
@ -259,15 +272,16 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
} else {
|
||||
|
||||
/* Tell the custom mutator that the trimming was unsuccessful */
|
||||
afl->stage_cur = afl->mutator->afl_custom_post_trim(afl, 0);
|
||||
afl->stage_cur =
|
||||
afl->mutator->afl_custom_post_trim(afl->mutator->data, 0);
|
||||
if (unlikely(afl->stage_cur < 0))
|
||||
FATAL("Error ret in custom_post_trim: %d", afl->stage_cur);
|
||||
if (afl->not_on_tty && afl->debug)
|
||||
SAYF("[Custom Trimming] FAILURE: %d/%d iterations", afl->stage_cur,
|
||||
afl->stage_max);
|
||||
|
||||
}
|
||||
|
||||
ck_free(retbuf);
|
||||
|
||||
/* Since this can be slow, update the screen every now and then. */
|
||||
|
||||
if (!(trim_exec++ % afl->stats_update_freq)) show_stats(afl);
|
||||
@ -304,3 +318,4 @@ abort_trimming:
|
||||
return fault;
|
||||
|
||||
}
|
||||
|
||||
|
@ -347,6 +347,9 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
u8 a_collect[MAX_AUTO_EXTRA];
|
||||
u32 a_len = 0;
|
||||
|
||||
/* Not pretty, but saves a lot of writing */
|
||||
#define BUF_PARAMS(name) (void **)&afl->name##_buf, &afl->name##_size
|
||||
|
||||
#ifdef IGNORE_FINDS
|
||||
|
||||
/* In IGNORE_FINDS mode, skip any entries that weren't in the
|
||||
@ -360,7 +363,8 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
/* The custom mutator will decide to skip this test case or not. */
|
||||
|
||||
if (!afl->mutator->afl_custom_queue_get(afl, afl->queue_cur->fname))
|
||||
if (!afl->mutator->afl_custom_queue_get(afl->mutator->data,
|
||||
afl->queue_cur->fname))
|
||||
return 1;
|
||||
|
||||
}
|
||||
@ -426,7 +430,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
single byte anyway, so it wouldn't give us any performance or memory usage
|
||||
benefits. */
|
||||
|
||||
out_buf = ck_alloc_nozero(len);
|
||||
out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
|
||||
|
||||
afl->subseq_tmouts = 0;
|
||||
|
||||
@ -718,7 +722,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
/* Initialize effector map for the next step (see comments below). Always
|
||||
flag first and last byte as doing something. */
|
||||
|
||||
eff_map = ck_alloc(EFF_ALEN(len));
|
||||
eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
|
||||
eff_map[0] = 1;
|
||||
|
||||
if (EFF_APOS(len - 1) != 0) {
|
||||
@ -1442,7 +1446,7 @@ skip_interest:
|
||||
|
||||
orig_hit_cnt = new_hit_cnt;
|
||||
|
||||
ex_tmp = ck_alloc(len + MAX_DICT_FILE);
|
||||
ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
|
||||
|
||||
for (i = 0; i <= len; ++i) {
|
||||
|
||||
@ -1465,7 +1469,6 @@ skip_interest:
|
||||
|
||||
if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
|
||||
|
||||
ck_free(ex_tmp);
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
@ -1479,8 +1482,6 @@ skip_interest:
|
||||
|
||||
}
|
||||
|
||||
ck_free(ex_tmp);
|
||||
|
||||
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
|
||||
afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
|
||||
@ -1606,18 +1607,23 @@ 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);
|
||||
new_buf = ck_alloc_nozero(target->len);
|
||||
|
||||
new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), target->len);
|
||||
ck_read(fd, new_buf, target->len, target->fname);
|
||||
close(fd);
|
||||
|
||||
size_t mutated_size = afl->mutator->afl_custom_fuzz(
|
||||
afl, &out_buf, len, new_buf, target->len, max_seed_size);
|
||||
u8 *mutated_buf = NULL;
|
||||
|
||||
ck_free(new_buf);
|
||||
size_t mutated_size = afl->mutator->afl_custom_fuzz(
|
||||
afl->mutator->data, out_buf, len, &mutated_buf, new_buf, target->len,
|
||||
max_seed_size);
|
||||
|
||||
if (unlikely(!mutated_buf))
|
||||
FATAL("Error in custom_fuzz. Size returned: %zd", mutated_size);
|
||||
|
||||
if (mutated_size > 0) {
|
||||
|
||||
if (common_fuzz_stuff(afl, out_buf, (u32)mutated_size)) {
|
||||
if (common_fuzz_stuff(afl, mutated_buf, (u32)mutated_size)) {
|
||||
|
||||
goto abandon_entry;
|
||||
|
||||
@ -1641,7 +1647,8 @@ custom_mutator_stage:
|
||||
|
||||
}
|
||||
|
||||
if (mutated_size < len) out_buf = ck_realloc(out_buf, len);
|
||||
/* `(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);
|
||||
|
||||
}
|
||||
@ -1702,7 +1709,7 @@ havoc_stage:
|
||||
if (stacked_custom && afl->mutator->afl_custom_havoc_mutation_probability) {
|
||||
|
||||
stacked_custom_prob =
|
||||
afl->mutator->afl_custom_havoc_mutation_probability(afl);
|
||||
afl->mutator->afl_custom_havoc_mutation_probability(afl->mutator->data);
|
||||
if (stacked_custom_prob > 100)
|
||||
FATAL(
|
||||
"The probability returned by afl_custom_havoc_mutation_propability "
|
||||
@ -1723,8 +1730,22 @@ havoc_stage:
|
||||
|
||||
if (stacked_custom && rand_below(afl, 100) < stacked_custom_prob) {
|
||||
|
||||
temp_len = afl->mutator->afl_custom_havoc_mutation(afl, &out_buf,
|
||||
temp_len, MAX_FILE);
|
||||
u8 * custom_havoc_buf = NULL;
|
||||
size_t new_len = afl->mutator->afl_custom_havoc_mutation(
|
||||
afl->mutator->data, out_buf, temp_len, &custom_havoc_buf, MAX_FILE);
|
||||
if (unlikely(!custom_havoc_buf))
|
||||
FATAL("Error in custom_havoc (return %zd)", new_len);
|
||||
if (likely(new_len > 0 && custom_havoc_buf)) {
|
||||
|
||||
temp_len = new_len;
|
||||
if (out_buf != custom_havoc_buf) {
|
||||
|
||||
ck_maybe_grow(BUF_PARAMS(out), temp_len);
|
||||
memcpy(out_buf, custom_havoc_buf, temp_len);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1954,7 +1975,8 @@ havoc_stage:
|
||||
|
||||
clone_to = rand_below(afl, temp_len);
|
||||
|
||||
new_buf = ck_alloc_nozero(temp_len + clone_len);
|
||||
new_buf =
|
||||
ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + clone_len);
|
||||
|
||||
/* Head */
|
||||
|
||||
@ -1974,8 +1996,9 @@ havoc_stage:
|
||||
memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
|
||||
temp_len - clone_to);
|
||||
|
||||
ck_free(out_buf);
|
||||
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
|
||||
out_buf = new_buf;
|
||||
new_buf = NULL;
|
||||
temp_len += clone_len;
|
||||
|
||||
}
|
||||
@ -2068,7 +2091,8 @@ havoc_stage:
|
||||
|
||||
if (temp_len + extra_len >= MAX_FILE) break;
|
||||
|
||||
new_buf = ck_alloc_nozero(temp_len + extra_len);
|
||||
new_buf =
|
||||
ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
|
||||
|
||||
/* Head */
|
||||
memcpy(new_buf, out_buf, insert_at);
|
||||
@ -2084,7 +2108,8 @@ havoc_stage:
|
||||
|
||||
if (temp_len + extra_len >= MAX_FILE) break;
|
||||
|
||||
new_buf = ck_alloc_nozero(temp_len + extra_len);
|
||||
new_buf =
|
||||
ck_maybe_grow(BUF_PARAMS(out_scratch), temp_len + extra_len);
|
||||
|
||||
/* Head */
|
||||
memcpy(new_buf, out_buf, insert_at);
|
||||
@ -2098,8 +2123,9 @@ havoc_stage:
|
||||
memcpy(new_buf + insert_at + extra_len, out_buf + insert_at,
|
||||
temp_len - insert_at);
|
||||
|
||||
ck_free(out_buf);
|
||||
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
|
||||
out_buf = new_buf;
|
||||
new_buf = NULL;
|
||||
temp_len += extra_len;
|
||||
|
||||
break;
|
||||
@ -2115,7 +2141,7 @@ havoc_stage:
|
||||
/* out_buf might have been mangled a bit, so let's restore it to its
|
||||
original size and shape. */
|
||||
|
||||
if (temp_len < len) out_buf = ck_realloc(out_buf, len);
|
||||
out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
|
||||
temp_len = len;
|
||||
memcpy(out_buf, in_buf, len);
|
||||
|
||||
@ -2177,7 +2203,6 @@ retry_splicing:
|
||||
|
||||
if (in_buf != orig_in) {
|
||||
|
||||
ck_free(in_buf);
|
||||
in_buf = orig_in;
|
||||
len = afl->queue_cur->len;
|
||||
|
||||
@ -2221,7 +2246,7 @@ retry_splicing:
|
||||
|
||||
if (unlikely(fd < 0)) PFATAL("Unable to open '%s'", target->fname);
|
||||
|
||||
new_buf = ck_alloc_nozero(target->len);
|
||||
new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
|
||||
|
||||
ck_read(fd, new_buf, target->len, target->fname);
|
||||
|
||||
@ -2233,12 +2258,7 @@ retry_splicing:
|
||||
|
||||
locate_diffs(in_buf, new_buf, MIN(len, target->len), &f_diff, &l_diff);
|
||||
|
||||
if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
|
||||
|
||||
ck_free(new_buf);
|
||||
goto retry_splicing;
|
||||
|
||||
}
|
||||
if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) { goto retry_splicing; }
|
||||
|
||||
/* Split somewhere between the first and last differing byte. */
|
||||
|
||||
@ -2248,10 +2268,10 @@ retry_splicing:
|
||||
|
||||
len = target->len;
|
||||
memcpy(new_buf, in_buf, split_at);
|
||||
swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
|
||||
in_buf = new_buf;
|
||||
|
||||
ck_free(out_buf);
|
||||
out_buf = ck_alloc_nozero(len);
|
||||
out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
|
||||
memcpy(out_buf, in_buf, len);
|
||||
|
||||
goto custom_mutator_stage;
|
||||
@ -2279,12 +2299,14 @@ radamsa_stage:
|
||||
|
||||
orig_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
|
||||
/* Read the additional testcase into a new buffer. */
|
||||
u8 *save_buf = ck_alloc_nozero(len);
|
||||
/* Read the additional testcase.
|
||||
We'll reuse in_scratch, as it is free at this point.
|
||||
*/
|
||||
u8 *save_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), len);
|
||||
memcpy(save_buf, out_buf, len);
|
||||
|
||||
u32 max_len = len + choose_block_len(afl, HAVOC_BLK_XL);
|
||||
u8 *new_buf = ck_alloc_nozero(max_len);
|
||||
u8 *new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch), max_len);
|
||||
u8 *tmp_buf;
|
||||
|
||||
for (afl->stage_cur = 0; afl->stage_cur < afl->stage_max; ++afl->stage_cur) {
|
||||
@ -2304,19 +2326,10 @@ radamsa_stage:
|
||||
|
||||
}
|
||||
|
||||
if (common_fuzz_stuff(afl, tmp_buf, temp_len)) {
|
||||
|
||||
ck_free(save_buf);
|
||||
ck_free(new_buf);
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
if (common_fuzz_stuff(afl, tmp_buf, temp_len)) { goto abandon_entry; }
|
||||
|
||||
}
|
||||
|
||||
ck_free(save_buf);
|
||||
ck_free(new_buf);
|
||||
|
||||
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
|
||||
afl->stage_finds[STAGE_RADAMSA] += new_hit_cnt - orig_hit_cnt;
|
||||
@ -2346,10 +2359,6 @@ abandon_entry:
|
||||
|
||||
munmap(orig_in, afl->queue_cur->len);
|
||||
|
||||
if (in_buf != orig_in) ck_free(in_buf);
|
||||
ck_free(out_buf);
|
||||
ck_free(eff_map);
|
||||
|
||||
return ret_val;
|
||||
|
||||
#undef FLIP_BIT
|
||||
@ -2448,7 +2457,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
|
||||
single byte anyway, so it wouldn't give us any performance or memory usage
|
||||
benefits. */
|
||||
|
||||
out_buf = ck_alloc_nozero(len);
|
||||
out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
|
||||
|
||||
afl->subseq_tmouts = 0;
|
||||
|
||||
@ -2727,7 +2736,7 @@ u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
|
||||
/* Initialize effector map for the next step (see comments below). Always
|
||||
flag first and last byte as doing something. */
|
||||
|
||||
eff_map = ck_alloc(EFF_ALEN(len));
|
||||
eff_map = ck_maybe_grow(BUF_PARAMS(eff), EFF_ALEN(len));
|
||||
eff_map[0] = 1;
|
||||
|
||||
if (EFF_APOS(len - 1) != 0) {
|
||||
@ -3451,7 +3460,7 @@ skip_interest:
|
||||
|
||||
orig_hit_cnt = new_hit_cnt;
|
||||
|
||||
ex_tmp = ck_alloc(len + MAX_DICT_FILE);
|
||||
ex_tmp = ck_maybe_grow(BUF_PARAMS(ex), len + MAX_DICT_FILE);
|
||||
|
||||
for (i = 0; i <= len; ++i) {
|
||||
|
||||
@ -3474,7 +3483,6 @@ skip_interest:
|
||||
|
||||
if (common_fuzz_stuff(afl, ex_tmp, len + afl->extras[j].len)) {
|
||||
|
||||
ck_free(ex_tmp);
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
@ -3488,8 +3496,6 @@ skip_interest:
|
||||
|
||||
} /* for i = 0; i <= len */
|
||||
|
||||
ck_free(ex_tmp);
|
||||
|
||||
new_hit_cnt = afl->queued_paths + afl->unique_crashes;
|
||||
|
||||
afl->stage_finds[STAGE_EXTRAS_UI] += new_hit_cnt - orig_hit_cnt;
|
||||
@ -3893,7 +3899,8 @@ pacemaker_fuzzing:
|
||||
|
||||
clone_to = rand_below(afl, temp_len);
|
||||
|
||||
new_buf = ck_alloc_nozero(temp_len + clone_len);
|
||||
new_buf = ck_maybe_grow(BUF_PARAMS(out_scratch),
|
||||
temp_len + clone_len);
|
||||
|
||||
/* Head */
|
||||
|
||||
@ -3914,7 +3921,7 @@ pacemaker_fuzzing:
|
||||
memcpy(new_buf + clone_to + clone_len, out_buf + clone_to,
|
||||
temp_len - clone_to);
|
||||
|
||||
ck_free(out_buf);
|
||||
swap_bufs(BUF_PARAMS(out), BUF_PARAMS(out_scratch));
|
||||
out_buf = new_buf;
|
||||
temp_len += clone_len;
|
||||
MOpt_globals.cycles_v2[STAGE_Clone75] += 1;
|
||||
@ -3967,7 +3974,7 @@ pacemaker_fuzzing:
|
||||
/* out_buf might have been mangled a bit, so let's restore it to its
|
||||
original size and shape. */
|
||||
|
||||
if (temp_len < len) out_buf = ck_realloc(out_buf, len);
|
||||
out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
|
||||
temp_len = len;
|
||||
memcpy(out_buf, in_buf, len);
|
||||
|
||||
@ -4045,7 +4052,6 @@ pacemaker_fuzzing:
|
||||
|
||||
if (in_buf != orig_in) {
|
||||
|
||||
ck_free(in_buf);
|
||||
in_buf = orig_in;
|
||||
len = afl->queue_cur->len;
|
||||
|
||||
@ -4090,7 +4096,7 @@ pacemaker_fuzzing:
|
||||
|
||||
if (fd < 0) PFATAL("Unable to open '%s'", target->fname);
|
||||
|
||||
new_buf = ck_alloc_nozero(target->len);
|
||||
new_buf = ck_maybe_grow(BUF_PARAMS(in_scratch), target->len);
|
||||
|
||||
ck_read(fd, new_buf, target->len, target->fname);
|
||||
|
||||
@ -4104,7 +4110,6 @@ pacemaker_fuzzing:
|
||||
|
||||
if (f_diff < 0 || l_diff < 2 || f_diff == l_diff) {
|
||||
|
||||
ck_free(new_buf);
|
||||
goto retry_splicing_puppet;
|
||||
|
||||
}
|
||||
@ -4117,9 +4122,9 @@ pacemaker_fuzzing:
|
||||
|
||||
len = target->len;
|
||||
memcpy(new_buf, in_buf, split_at);
|
||||
swap_bufs(BUF_PARAMS(in), BUF_PARAMS(in_scratch));
|
||||
in_buf = new_buf;
|
||||
ck_free(out_buf);
|
||||
out_buf = ck_alloc_nozero(len);
|
||||
out_buf = ck_maybe_grow(BUF_PARAMS(out), len);
|
||||
memcpy(out_buf, in_buf, len);
|
||||
|
||||
goto havoc_stage_puppet;
|
||||
@ -4154,10 +4159,6 @@ pacemaker_fuzzing:
|
||||
|
||||
munmap(orig_in, afl->queue_cur->len);
|
||||
|
||||
if (in_buf != orig_in) ck_free(in_buf);
|
||||
ck_free(out_buf);
|
||||
ck_free(eff_map);
|
||||
|
||||
if (afl->key_puppet == 1) {
|
||||
|
||||
if (unlikely(
|
||||
@ -4379,18 +4380,13 @@ u8 fuzz_one(afl_state_t *afl) {
|
||||
int key_val_lv = 0;
|
||||
|
||||
#ifdef _AFL_DOCUMENT_MUTATIONS
|
||||
|
||||
u8 path_buf[PATH_MAX];
|
||||
if (afl->do_document == 0) {
|
||||
|
||||
char *fn = alloc_printf("%s/mutations", afl->out_dir);
|
||||
if (fn) {
|
||||
|
||||
afl->do_document = mkdir(fn, 0700); // if it exists we do not care
|
||||
afl->do_document = 1;
|
||||
ck_free(fn);
|
||||
|
||||
} else
|
||||
|
||||
PFATAL("malloc()");
|
||||
snprintf(path_buf, PATH_MAX, "%s/mutations", afl->out_dir);
|
||||
afl->do_document = mkdir(path_buf, 0700); // if it exists we do not care
|
||||
afl->do_document = 1;
|
||||
|
||||
} else {
|
||||
|
||||
@ -4418,5 +4414,7 @@ u8 fuzz_one(afl_state_t *afl) {
|
||||
|
||||
return key_val_lv;
|
||||
|
||||
#undef BUF_PARAMS
|
||||
|
||||
}
|
||||
|
||||
|
@ -29,19 +29,28 @@
|
||||
#ifdef USE_PYTHON
|
||||
|
||||
static void *unsupported(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
FATAL("Python Mutator cannot be called twice yet");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf,
|
||||
size_t add_buf_size, size_t max_size) {
|
||||
/* sorry for this makro...
|
||||
it just fills in `&py_mutator->something_buf, &py_mutator->something_size`. */
|
||||
#define BUF_PARAMS(name) \
|
||||
(void **)&((py_mutator_t *)py_mutator)->name##_buf, \
|
||||
&((py_mutator_t *)py_mutator)->name##_size
|
||||
|
||||
size_t fuzz_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf,
|
||||
u8 *add_buf, size_t add_buf_size, size_t max_size) {
|
||||
|
||||
size_t mutated_size;
|
||||
PyObject *py_args, *py_value;
|
||||
py_args = PyTuple_New(3);
|
||||
py_mutator_t *py = (py_mutator_t *)py_mutator;
|
||||
|
||||
/* buf */
|
||||
py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
|
||||
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
||||
if (!py_value) {
|
||||
|
||||
Py_DECREF(py_args);
|
||||
@ -77,29 +86,29 @@ size_t fuzz_py(void *py_mutator, u8 **buf, size_t buf_size, u8 *add_buf,
|
||||
|
||||
PyTuple_SetItem(py_args, 2, py_value);
|
||||
|
||||
py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_FUZZ], py_args);
|
||||
py_value = PyObject_CallObject(py->py_functions[PY_FUNC_FUZZ], py_args);
|
||||
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
|
||||
mutated_size = PyByteArray_Size(py_value);
|
||||
if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
|
||||
|
||||
memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
|
||||
*out_buf = ck_maybe_grow(BUF_PARAMS(fuzz), mutated_size);
|
||||
|
||||
memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
|
||||
Py_DECREF(py_value);
|
||||
return mutated_size;
|
||||
|
||||
} else {
|
||||
|
||||
PyErr_Print();
|
||||
FATAL("Call failed");
|
||||
FATAL("python custom fuzz: call failed");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||
|
||||
if (!module_name) return NULL;
|
||||
@ -124,8 +133,8 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||
if (py_module != NULL) {
|
||||
|
||||
u8 py_notrim = 0, py_idx;
|
||||
/* init, required */
|
||||
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
|
||||
py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
|
||||
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
|
||||
py_functions[PY_FUNC_PRE_SAVE] =
|
||||
PyObject_GetAttrString(py_module, "pre_save");
|
||||
@ -142,6 +151,7 @@ static py_mutator_t *init_py_module(afl_state_t *afl, u8 *module_name) {
|
||||
PyObject_GetAttrString(py_module, "queue_get");
|
||||
py_functions[PY_FUNC_QUEUE_NEW_ENTRY] =
|
||||
PyObject_GetAttrString(py_module, "queue_new_entry");
|
||||
py_functions[PY_FUNC_DEINIT] = PyObject_GetAttrString(py_module, "deinit");
|
||||
|
||||
for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
|
||||
|
||||
@ -223,7 +233,8 @@ void finalize_py_module(void *py_mutator) {
|
||||
|
||||
}
|
||||
|
||||
static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int seed) {
|
||||
static void init_py(afl_state_t *afl, py_mutator_t *py_mutator,
|
||||
unsigned int seed) {
|
||||
|
||||
PyObject *py_args, *py_value;
|
||||
|
||||
@ -244,7 +255,8 @@ static void init_py(afl_state_t *afl, py_mutator_t *py_mutator, unsigned int see
|
||||
|
||||
PyTuple_SetItem(py_args, 0, py_value);
|
||||
|
||||
py_value = PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
|
||||
py_value =
|
||||
PyObject_CallObject(py_mutator->py_functions[PY_FUNC_INIT], py_args);
|
||||
|
||||
Py_DECREF(py_args);
|
||||
|
||||
@ -283,15 +295,16 @@ void deinit_py(void *py_mutator) {
|
||||
void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
|
||||
|
||||
afl->mutator = ck_alloc(sizeof(struct custom_mutator));
|
||||
afl->mutator->pre_save_buf = NULL;
|
||||
afl->mutator->pre_save_size = 0;
|
||||
|
||||
afl->mutator->name = module_name;
|
||||
ACTF("Loading Python mutator library from '%s'...", module_name);
|
||||
|
||||
py_mutator_t *py_mutator;
|
||||
py_mutator = init_py_module(afl, module_name);
|
||||
if (!py_mutator) {
|
||||
FATAL("Failed to load python mutator.");
|
||||
}
|
||||
afl->mutator->data = py_mutator;
|
||||
if (!py_mutator) { FATAL("Failed to load python mutator."); }
|
||||
|
||||
PyObject **py_functions = py_mutator->py_functions;
|
||||
|
||||
@ -334,44 +347,50 @@ void load_custom_mutator_py(afl_state_t *afl, char *module_name) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
size_t pre_save_py(void *py_mutator, u8 *buf, size_t buf_size, u8 **out_buf) {
|
||||
|
||||
size_t out_buf_size;
|
||||
PyObject *py_args, *py_value;
|
||||
size_t py_out_buf_size;
|
||||
PyObject * py_args, *py_value;
|
||||
py_mutator_t *py = (py_mutator_t *)py_mutator;
|
||||
|
||||
py_args = PyTuple_New(1);
|
||||
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
||||
if (!py_value) {
|
||||
|
||||
Py_DECREF(py_args);
|
||||
FATAL("Failed to convert arguments");
|
||||
FATAL("Failed to convert arguments in custom pre_save");
|
||||
|
||||
}
|
||||
|
||||
PyTuple_SetItem(py_args, 0, py_value);
|
||||
|
||||
py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_PRE_SAVE], py_args);
|
||||
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
|
||||
out_buf_size = PyByteArray_Size(py_value);
|
||||
*out_buf = malloc(out_buf_size);
|
||||
memcpy(*out_buf, PyByteArray_AsString(py_value), out_buf_size);
|
||||
py_out_buf_size = PyByteArray_Size(py_value);
|
||||
|
||||
ck_maybe_grow(BUF_PARAMS(pre_save), py_out_buf_size);
|
||||
|
||||
memcpy(py->pre_save_buf, PyByteArray_AsString(py_value), py_out_buf_size);
|
||||
Py_DECREF(py_value);
|
||||
return out_buf_size;
|
||||
|
||||
*out_buf = py->pre_save_buf;
|
||||
return py_out_buf_size;
|
||||
|
||||
} else {
|
||||
|
||||
PyErr_Print();
|
||||
FATAL("Call failed");
|
||||
FATAL("Python custom mutator: pre_save call failed.");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
|
||||
s32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
|
||||
|
||||
PyObject *py_args, *py_value;
|
||||
|
||||
@ -386,7 +405,8 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
|
||||
|
||||
PyTuple_SetItem(py_args, 0, py_value);
|
||||
|
||||
py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_INIT_TRIM], py_args);
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
@ -408,7 +428,7 @@ u32 init_trim_py(void *py_mutator, u8 *buf, size_t buf_size) {
|
||||
|
||||
}
|
||||
|
||||
u32 post_trim_py(void *py_mutator, u8 success) {
|
||||
s32 post_trim_py(void *py_mutator, u8 success) {
|
||||
|
||||
PyObject *py_args, *py_value;
|
||||
|
||||
@ -424,7 +444,8 @@ u32 post_trim_py(void *py_mutator, u8 success) {
|
||||
|
||||
PyTuple_SetItem(py_args, 0, py_value);
|
||||
|
||||
py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_POST_TRIM], py_args);
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
@ -446,19 +467,21 @@ u32 post_trim_py(void *py_mutator, u8 success) {
|
||||
|
||||
}
|
||||
|
||||
void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
|
||||
size_t trim_py(void *py_mutator, u8 **out_buf) {
|
||||
|
||||
PyObject *py_args, *py_value;
|
||||
size_t ret;
|
||||
|
||||
py_args = PyTuple_New(0);
|
||||
py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_TRIM], py_args);
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
|
||||
*out_buf_size = PyByteArray_Size(py_value);
|
||||
*out_buf = malloc(*out_buf_size);
|
||||
memcpy(*out_buf, PyByteArray_AsString(py_value), *out_buf_size);
|
||||
ret = PyByteArray_Size(py_value);
|
||||
*out_buf = ck_maybe_grow(BUF_PARAMS(trim), ret);
|
||||
memcpy(*out_buf, PyByteArray_AsString(py_value), ret);
|
||||
Py_DECREF(py_value);
|
||||
|
||||
} else {
|
||||
@ -468,17 +491,19 @@ void trim_py(void *py_mutator, u8 **out_buf, size_t *out_buf_size) {
|
||||
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
|
||||
size_t max_size) {
|
||||
size_t havoc_mutation_py(void *py_mutator, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf, size_t max_size) {
|
||||
|
||||
size_t mutated_size;
|
||||
PyObject *py_args, *py_value;
|
||||
py_args = PyTuple_New(2);
|
||||
|
||||
/* buf */
|
||||
py_value = PyByteArray_FromStringAndSize(*buf, buf_size);
|
||||
py_value = PyByteArray_FromStringAndSize(buf, buf_size);
|
||||
if (!py_value) {
|
||||
|
||||
Py_DECREF(py_args);
|
||||
@ -503,17 +528,28 @@ size_t havoc_mutation_py(void *py_mutator, u8 **buf, size_t buf_size,
|
||||
|
||||
PyTuple_SetItem(py_args, 1, py_value);
|
||||
|
||||
py_value =
|
||||
PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION],
|
||||
py_args);
|
||||
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
|
||||
mutated_size = PyByteArray_Size(py_value);
|
||||
if (buf_size < mutated_size) *buf = ck_realloc(*buf, mutated_size);
|
||||
if (mutated_size <= buf_size) {
|
||||
|
||||
memcpy(*buf, PyByteArray_AsString(py_value), mutated_size);
|
||||
/* We reuse the input buf here. */
|
||||
*out_buf = buf;
|
||||
|
||||
} else {
|
||||
|
||||
/* A new buf is needed... */
|
||||
*out_buf = ck_maybe_grow(BUF_PARAMS(havoc), mutated_size);
|
||||
|
||||
}
|
||||
|
||||
memcpy(*out_buf, PyByteArray_AsString(py_value), mutated_size);
|
||||
|
||||
Py_DECREF(py_value);
|
||||
return mutated_size;
|
||||
@ -533,7 +569,9 @@ u8 havoc_mutation_probability_py(void *py_mutator) {
|
||||
|
||||
py_args = PyTuple_New(0);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY], py_args);
|
||||
((py_mutator_t *)py_mutator)
|
||||
->py_functions[PY_FUNC_HAVOC_MUTATION_PROBABILITY],
|
||||
py_args);
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
@ -573,7 +611,8 @@ u8 queue_get_py(void *py_mutator, const u8 *filename) {
|
||||
PyTuple_SetItem(py_args, 0, py_value);
|
||||
|
||||
// Call Python function
|
||||
py_value = PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_GET], py_args);
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value != NULL) {
|
||||
@ -642,8 +681,9 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
|
||||
PyTuple_SetItem(py_args, 1, py_value);
|
||||
|
||||
// Call
|
||||
py_value =
|
||||
PyObject_CallObject(((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY], py_args);
|
||||
py_value = PyObject_CallObject(
|
||||
((py_mutator_t *)py_mutator)->py_functions[PY_FUNC_QUEUE_NEW_ENTRY],
|
||||
py_args);
|
||||
Py_DECREF(py_args);
|
||||
|
||||
if (py_value == NULL) {
|
||||
@ -655,5 +695,7 @@ void queue_new_entry_py(void *py_mutator, const u8 *filename_new_queue,
|
||||
|
||||
}
|
||||
|
||||
#undef BUF_PARAMS
|
||||
|
||||
#endif /* USE_PYTHON */
|
||||
|
||||
|
@ -30,18 +30,16 @@
|
||||
|
||||
void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
u8 *fn = strrchr(q->fname, '/');
|
||||
u8 fn[PATH_MAX];
|
||||
s32 fd;
|
||||
|
||||
fn = alloc_printf("%s/queue/.state/deterministic_done/%s", afl->out_dir,
|
||||
fn + 1);
|
||||
snprintf(fn, PATH_MAX, "%s/queue/.state/deterministic_done/%s", afl->out_dir,
|
||||
strrchr(q->fname, '/') + 1);
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
close(fd);
|
||||
|
||||
ck_free(fn);
|
||||
|
||||
q->passed_det = 1;
|
||||
|
||||
}
|
||||
@ -51,10 +49,13 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
u8 *fn = strrchr(q->fname, '/') + 1, *ldest;
|
||||
u8 fn[PATH_MAX];
|
||||
u8 ldest[PATH_MAX];
|
||||
|
||||
ldest = alloc_printf("../../%s", fn);
|
||||
fn = alloc_printf("%s/queue/.state/variable_behavior/%s", afl->out_dir, fn);
|
||||
u8 *fn_name = strrchr(q->fname, '/') + 1;
|
||||
|
||||
sprintf(ldest, "../../%s", fn_name);
|
||||
sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name);
|
||||
|
||||
if (symlink(ldest, fn)) {
|
||||
|
||||
@ -64,9 +65,6 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
ck_free(ldest);
|
||||
ck_free(fn);
|
||||
|
||||
q->var_behavior = 1;
|
||||
|
||||
}
|
||||
@ -76,14 +74,14 @@ void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
u8 *fn;
|
||||
u8 fn[PATH_MAX];
|
||||
|
||||
if (state == q->fs_redundant) return;
|
||||
|
||||
q->fs_redundant = state;
|
||||
|
||||
fn = strrchr(q->fname, '/');
|
||||
fn = alloc_printf("%s/queue/.state/redundant_edges/%s", afl->out_dir, fn + 1);
|
||||
sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir,
|
||||
strrchr(q->fname, '/') + 1);
|
||||
|
||||
if (state) {
|
||||
|
||||
@ -99,8 +97,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
}
|
||||
|
||||
ck_free(fn);
|
||||
|
||||
}
|
||||
|
||||
/* Append new test case to the queue. */
|
||||
@ -114,6 +110,7 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
q->depth = afl->cur_depth + 1;
|
||||
q->passed_det = passed_det;
|
||||
q->n_fuzz = 1;
|
||||
q->trace_mini = NULL;
|
||||
|
||||
if (q->depth > afl->max_depth) afl->max_depth = q->depth;
|
||||
|
||||
@ -147,7 +144,8 @@ void add_to_queue(afl_state_t *afl, u8 *fname, u32 len, u8 passed_det) {
|
||||
/* At the initialization stage, queue_cur is NULL */
|
||||
if (afl->queue_cur) fname_orig = afl->queue_cur->fname;
|
||||
|
||||
afl->mutator->afl_custom_queue_new_entry(afl, fname, fname_orig);
|
||||
afl->mutator->afl_custom_queue_new_entry(afl->mutator->data, fname,
|
||||
fname_orig);
|
||||
|
||||
}
|
||||
|
||||
@ -186,9 +184,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
u32 i;
|
||||
u64 fav_factor;
|
||||
u64 fuzz_p2 = next_p2(q->n_fuzz);
|
||||
u64 fuzz_p2 = next_pow2(q->n_fuzz);
|
||||
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE)
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed))
|
||||
fav_factor = q->len << 2;
|
||||
else
|
||||
fav_factor = q->exec_us * q->len;
|
||||
@ -203,9 +201,9 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
/* Faster-executing or smaller test cases are favored. */
|
||||
u64 top_rated_fav_factor;
|
||||
u64 top_rated_fuzz_p2 = next_p2(afl->top_rated[i]->n_fuzz);
|
||||
u64 top_rated_fuzz_p2 = next_pow2(afl->top_rated[i]->n_fuzz);
|
||||
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE)
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed))
|
||||
top_rated_fav_factor = afl->top_rated[i]->len << 2;
|
||||
else
|
||||
top_rated_fav_factor =
|
||||
@ -216,8 +214,17 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
else if (fuzz_p2 == top_rated_fuzz_p2)
|
||||
if (fav_factor > top_rated_fav_factor) continue;
|
||||
|
||||
if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
|
||||
continue;
|
||||
if (afl->schedule == MMOPT || afl->schedule == RARE || unlikely(afl->fixed_seed)) {
|
||||
|
||||
if (fav_factor > afl->top_rated[i]->len << 2)
|
||||
continue;
|
||||
|
||||
} else {
|
||||
|
||||
if (fav_factor > afl->top_rated[i]->exec_us * afl->top_rated[i]->len)
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
/* Looks like we're going to win. Decrease ref count for the
|
||||
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
|
||||
@ -332,7 +339,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
// Longer execution time means longer work on the input, the deeper in
|
||||
// coverage, the better the fuzzing, right? -mh
|
||||
|
||||
if (afl->schedule != MMOPT && afl->schedule != RARE) {
|
||||
if (afl->schedule != MMOPT && afl->schedule != RARE && likely(!afl->fixed_seed)) {
|
||||
|
||||
if (q->exec_us * 0.1 > avg_exec_us)
|
||||
perf_score = 10;
|
||||
@ -442,7 +449,7 @@ u32 calculate_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
if (q->fuzz_level < 16)
|
||||
factor = ((u32)(1 << q->fuzz_level)) / (fuzz == 0 ? 1 : fuzz);
|
||||
else
|
||||
factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_p2(fuzz));
|
||||
factor = MAX_FACTOR / (fuzz == 0 ? 1 : next_pow2(fuzz));
|
||||
break;
|
||||
|
||||
case LIN: factor = q->fuzz_level / (fuzz == 0 ? 1 : fuzz); break;
|
||||
|
@ -529,9 +529,10 @@ u8 input_to_state_stage(afl_state_t *afl, u8 *orig_buf, u8 *buf, u32 len,
|
||||
|
||||
if (!afl->shm.cmp_map->headers[k].hits) continue;
|
||||
if (afl->shm.cmp_map->headers[k].type == CMP_TYPE_INS)
|
||||
afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
|
||||
afl->stage_max += MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_H);
|
||||
else
|
||||
afl->stage_max += MIN(afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
|
||||
afl->stage_max +=
|
||||
MIN((u32)afl->shm.cmp_map->headers[k].hits, CMP_MAP_RTN_H);
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,13 +33,10 @@
|
||||
u8 run_target(afl_state_t *afl, u32 timeout) {
|
||||
|
||||
s32 res;
|
||||
int sret;
|
||||
u32 exec_ms;
|
||||
|
||||
fd_set readfds;
|
||||
|
||||
struct timeval it;
|
||||
int status = 0;
|
||||
u32 tb4;
|
||||
int status = 0;
|
||||
u32 tb4;
|
||||
|
||||
afl->fsrv.child_timed_out = 0;
|
||||
|
||||
@ -70,26 +67,20 @@ u8 run_target(afl_state_t *afl, u32 timeout) {
|
||||
|
||||
if (afl->fsrv.child_pid <= 0) FATAL("Fork server is misbehaving (OOM?)");
|
||||
|
||||
/* use select to monitor the forkserver for timeouts. */
|
||||
exec_ms = read_timed(afl->fsrv.fsrv_st_fd, &status, 4, timeout);
|
||||
|
||||
FD_ZERO(&readfds);
|
||||
FD_SET(afl->fsrv.fsrv_st_fd, &readfds);
|
||||
it.tv_sec = ((timeout) / 1000);
|
||||
it.tv_usec = ((timeout) % 1000) * 1000;
|
||||
|
||||
sret = select(afl->fsrv.fsrv_st_fd + 1, &readfds, NULL, NULL, &it);
|
||||
|
||||
if (sret == 0) {
|
||||
if (exec_ms > timeout) {
|
||||
|
||||
/* If there was no response from forkserver after timeout seconds,
|
||||
we kill the child. The forkserver should inform us afterwards */
|
||||
|
||||
kill(afl->fsrv.child_pid, SIGKILL);
|
||||
afl->fsrv.child_timed_out = 1;
|
||||
if (read(afl->fsrv.fsrv_st_fd, &status, 4) < 4) exec_ms = 0;
|
||||
|
||||
}
|
||||
|
||||
if ((res = read(afl->fsrv.fsrv_st_fd, &status, 4)) != 4) {
|
||||
if (!exec_ms) {
|
||||
|
||||
if (afl->stop_soon) return 0;
|
||||
SAYF("\n" cLRD "[-] " cRST
|
||||
@ -176,20 +167,16 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
|
||||
s32 fd = afl->fsrv.out_fd;
|
||||
|
||||
#ifdef _AFL_DOCUMENT_MUTATIONS
|
||||
s32 doc_fd;
|
||||
char *fn = alloc_printf("%s/mutations/%09u:%s", afl->out_dir,
|
||||
s32 doc_fd;
|
||||
char fn[PATH_MAX];
|
||||
snprintf(fn, PATH_MAX, ("%s/mutations/%09u:%s", afl->out_dir,
|
||||
afl->document_counter++, describe_op(afl, 0));
|
||||
if (fn != NULL) {
|
||||
|
||||
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
|
||||
if ((doc_fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600)) >= 0) {
|
||||
|
||||
if (write(doc_fd, mem, len) != len)
|
||||
PFATAL("write to mutation file failed: %s", fn);
|
||||
close(doc_fd);
|
||||
|
||||
}
|
||||
|
||||
ck_free(fn);
|
||||
if (write(doc_fd, mem, len) != len)
|
||||
PFATAL("write to mutation file failed: %s", fn);
|
||||
close(doc_fd);
|
||||
|
||||
}
|
||||
|
||||
@ -214,16 +201,22 @@ void write_to_testcase(afl_state_t *afl, void *mem, u32 len) {
|
||||
|
||||
lseek(fd, 0, SEEK_SET);
|
||||
|
||||
if (afl->mutator && afl->mutator->afl_custom_pre_save) {
|
||||
if (unlikely(afl->mutator && afl->mutator->afl_custom_pre_save)) {
|
||||
|
||||
u8 * new_data;
|
||||
size_t new_size =
|
||||
afl->mutator->afl_custom_pre_save(afl, mem, len, &new_data);
|
||||
ck_write(fd, new_data, new_size, afl->fsrv.out_file);
|
||||
ck_free(new_data);
|
||||
u8 *new_buf = NULL;
|
||||
|
||||
size_t new_size = afl->mutator->afl_custom_pre_save(afl->mutator->data, mem,
|
||||
len, &new_buf);
|
||||
|
||||
if (unlikely(!new_buf))
|
||||
FATAL("Custom_pre_save failed (ret: %lu)", (long unsigned)new_size);
|
||||
|
||||
/* everything as planned. use the new data. */
|
||||
ck_write(fd, new_buf, new_size, afl->fsrv.out_file);
|
||||
|
||||
} else {
|
||||
|
||||
/* boring uncustom. */
|
||||
ck_write(fd, mem, len, afl->fsrv.out_file);
|
||||
|
||||
}
|
||||
@ -505,8 +498,8 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
afl->stage_cur = 0;
|
||||
afl->stage_max = 0;
|
||||
|
||||
/* For every file queued by this fuzzer, parse ID and see if we have looked
|
||||
at it before; exec a test case if not. */
|
||||
/* For every file queued by this fuzzer, parse ID and see if we have
|
||||
looked at it before; exec a test case if not. */
|
||||
|
||||
while ((qd_ent = readdir(qd))) {
|
||||
|
||||
@ -615,7 +608,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
/* Select initial chunk len, starting with large steps. */
|
||||
|
||||
len_p2 = next_p2(q->len);
|
||||
len_p2 = next_pow2(q->len);
|
||||
|
||||
remove_len = MAX(len_p2 / TRIM_START_STEPS, TRIM_MIN_BYTES);
|
||||
|
||||
@ -627,8 +620,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
u32 remove_pos = remove_len;
|
||||
|
||||
sprintf(afl->stage_name_buf, "trim %s/%s",
|
||||
u_stringify_int(val_bufs[0], remove_len),
|
||||
u_stringify_int(val_bufs[1], remove_len));
|
||||
u_stringify_int(val_bufs[0], remove_len),
|
||||
u_stringify_int(val_bufs[1], remove_len));
|
||||
|
||||
afl->stage_cur = 0;
|
||||
afl->stage_max = q->len / remove_len;
|
||||
@ -645,7 +638,8 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
|
||||
if (afl->stop_soon || fault == FAULT_ERROR) goto abort_trimming;
|
||||
|
||||
/* Note that we don't keep track of crashes or hangs here; maybe TODO? */
|
||||
/* Note that we don't keep track of crashes or hangs here; maybe TODO?
|
||||
*/
|
||||
|
||||
cksum = hash32(afl->fsrv.trace_bits, MAP_SIZE, HASH_CONST);
|
||||
|
||||
@ -659,7 +653,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
u32 move_tail = q->len - remove_pos - trim_avail;
|
||||
|
||||
q->len -= trim_avail;
|
||||
len_p2 = next_p2(q->len);
|
||||
len_p2 = next_pow2(q->len);
|
||||
|
||||
memmove(in_buf + remove_pos, in_buf + remove_pos + trim_avail,
|
||||
move_tail);
|
||||
@ -734,8 +728,13 @@ u8 common_fuzz_stuff(afl_state_t *afl, u8 *out_buf, u32 len) {
|
||||
|
||||
if (afl->post_handler) {
|
||||
|
||||
out_buf = afl->post_handler(out_buf, &len);
|
||||
if (!out_buf || !len) return 0;
|
||||
u8 *post_buf = NULL;
|
||||
|
||||
size_t post_len =
|
||||
afl->post_handler(afl->post_data, out_buf, len, &post_buf);
|
||||
if (!post_buf || !post_len) return 0;
|
||||
out_buf = post_buf;
|
||||
len = post_len;
|
||||
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,6 @@ char *power_names[POWER_SCHEDULES_NUM] = {
|
||||
|
||||
"explore", "fast", "coe", "lin", "quad", "exploit", "mmopt", "rare"};
|
||||
|
||||
u8 *doc_path = NULL; /* gath to documentation dir */
|
||||
|
||||
/* Initialize MOpt "globals" for this afl state */
|
||||
|
||||
static void init_mopt_globals(afl_state_t *afl) {
|
||||
@ -79,6 +77,8 @@ list_t afl_states = {.element_prealloc_count = 0};
|
||||
|
||||
void afl_state_init(afl_state_t *afl) {
|
||||
|
||||
/* thanks to this memset, growing vars like out_buf
|
||||
and out_size are NULL/0 by default. */
|
||||
memset(afl, 0, sizeof(afl_state_t));
|
||||
|
||||
afl->w_init = 0.9;
|
||||
@ -347,6 +347,15 @@ void read_afl_environment(afl_state_t *afl, char **envp) {
|
||||
|
||||
void afl_state_deinit(afl_state_t *afl) {
|
||||
|
||||
if (afl->post_deinit) afl->post_deinit(afl->post_data);
|
||||
|
||||
free(afl->out_buf);
|
||||
free(afl->out_scratch_buf);
|
||||
free(afl->eff_buf);
|
||||
free(afl->in_buf);
|
||||
free(afl->in_scratch_buf);
|
||||
free(afl->ex_buf);
|
||||
|
||||
list_remove(&afl_states, afl);
|
||||
|
||||
}
|
@ -33,16 +33,17 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
struct rusage rus;
|
||||
|
||||
unsigned long long int cur_time = get_cur_time();
|
||||
u8 * fn = alloc_printf("%s/fuzzer_stats", afl->out_dir);
|
||||
u8 fn[PATH_MAX];
|
||||
s32 fd;
|
||||
FILE * f;
|
||||
uint32_t t_bytes = count_non_255_bytes(afl->virgin_bits);
|
||||
|
||||
snprintf(fn, PATH_MAX, "%s/fuzzer_stats", afl->out_dir);
|
||||
|
||||
fd = open(fn, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", fn);
|
||||
|
||||
ck_free(fn);
|
||||
|
||||
f = fdopen(fd, "w");
|
||||
|
||||
if (!f) PFATAL("fdopen() failed");
|
||||
@ -95,8 +96,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
"last_hang : %llu\n"
|
||||
"execs_since_crash : %llu\n"
|
||||
"exec_timeout : %u\n"
|
||||
"slowest_exec_ms : %llu\n"
|
||||
"slowest_exec_ms : %u\n"
|
||||
"peak_rss_mb : %lu\n"
|
||||
"var_byte_count : %u\n"
|
||||
"found_edges : %u\n"
|
||||
"afl_banner : %s\n"
|
||||
"afl_version : " VERSION
|
||||
"\n"
|
||||
@ -119,9 +122,10 @@ void write_stats_file(afl_state_t *afl, double bitmap_cvg, double stability,
|
||||
#else
|
||||
(unsigned long int)(rus.ru_maxrss >> 10),
|
||||
#endif
|
||||
afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
|
||||
afl->qemu_mode ? "qemu " : "", afl->dumb_mode ? " dumb " : "",
|
||||
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
|
||||
afl->var_byte_count, t_bytes, afl->use_banner,
|
||||
afl->unicorn_mode ? "unicorn" : "", afl->qemu_mode ? "qemu " : "",
|
||||
afl->dumb_mode ? " dumb " : "", afl->no_forkserver ? "no_fsrv " : "",
|
||||
afl->crash_mode ? "crash " : "",
|
||||
afl->persistent_mode ? "persistent " : "",
|
||||
afl->deferred_mode ? "deferred " : "",
|
||||
(afl->unicorn_mode || afl->qemu_mode || afl->dumb_mode ||
|
||||
@ -257,7 +261,7 @@ void show_stats(afl_state_t *afl) {
|
||||
t_byte_ratio = ((double)t_bytes * 100) / MAP_SIZE;
|
||||
|
||||
if (t_bytes)
|
||||
stab_ratio = 100 - ((double)afl->var_byte_count) * 100 / t_bytes;
|
||||
stab_ratio = 100 - (((double)afl->var_byte_count) * 100) / t_bytes;
|
||||
else
|
||||
stab_ratio = 100;
|
||||
|
||||
@ -406,8 +410,7 @@ void show_stats(afl_state_t *afl) {
|
||||
(afl->last_path_time || afl->resuming_fuzz || afl->queue_cycle == 1 ||
|
||||
afl->in_bitmap || afl->crash_mode)) {
|
||||
|
||||
u_stringify_time_diff(time_tmp, cur_ms,
|
||||
afl->last_path_time);
|
||||
u_stringify_time_diff(time_tmp, cur_ms, afl->last_path_time);
|
||||
SAYF(bV bSTOP " last new path : " cRST "%-33s ", time_tmp);
|
||||
|
||||
} else {
|
||||
@ -533,24 +536,21 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
if (afl->stats_avg_exec < 100) {
|
||||
|
||||
sprintf(tmp, "%s/sec (%s)",
|
||||
u_stringify_float(IB(0), afl->stats_avg_exec),
|
||||
afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
|
||||
sprintf(tmp, "%s/sec (%s)", u_stringify_float(IB(0), afl->stats_avg_exec),
|
||||
afl->stats_avg_exec < 20 ? "zzzz..." : "slow!");
|
||||
|
||||
SAYF(bV bSTOP " exec speed : " cLRD "%-20s ", tmp);
|
||||
|
||||
} else {
|
||||
|
||||
sprintf(tmp, "%s/sec",
|
||||
u_stringify_float(IB(0), afl->stats_avg_exec));
|
||||
sprintf(tmp, "%s/sec", u_stringify_float(IB(0), afl->stats_avg_exec));
|
||||
SAYF(bV bSTOP " exec speed : " cRST "%-20s ", tmp);
|
||||
|
||||
}
|
||||
|
||||
sprintf(tmp, "%s (%s%s unique)",
|
||||
u_stringify_int(IB(0), afl->total_tmouts),
|
||||
u_stringify_int(IB(1), afl->unique_tmouts),
|
||||
(afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
|
||||
sprintf(tmp, "%s (%s%s unique)", u_stringify_int(IB(0), afl->total_tmouts),
|
||||
u_stringify_int(IB(1), afl->unique_tmouts),
|
||||
(afl->unique_hangs >= KEEP_UNIQUE_HANG) ? "+" : "");
|
||||
|
||||
SAYF(bSTG bV bSTOP " total tmouts : " cRST "%-22s" bSTG bV "\n", tmp);
|
||||
|
||||
@ -567,12 +567,12 @@ void show_stats(afl_state_t *afl) {
|
||||
} else {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
|
||||
u_stringify_int(IB(3), afl->stage_finds[STAGE_FLIP4]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP1]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP1]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP2]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP2]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP4]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP4]));
|
||||
|
||||
}
|
||||
|
||||
@ -582,12 +582,12 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_FLIP8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_FLIP8]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_FLIP16]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_FLIP16]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_FLIP32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_FLIP32]));
|
||||
|
||||
SAYF(bV bSTOP " byte flips : " cRST "%-36s " bSTG bV bSTOP
|
||||
" pending : " cRST "%-10s" bSTG bV "\n",
|
||||
@ -595,12 +595,12 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_ARITH8]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_ARITH8]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_ARITH16]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_ARITH16]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_ARITH32]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_ARITH32]));
|
||||
|
||||
SAYF(bV bSTOP " arithmetics : " cRST "%-36s " bSTG bV bSTOP
|
||||
" pend fav : " cRST "%-10s" bSTG bV "\n",
|
||||
@ -621,25 +621,26 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
if (!afl->skip_deterministic)
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_EXTRAS_UO]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_EXTRAS_UO]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_EXTRAS_UI]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_EXTRAS_UI]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_EXTRAS_AO]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_EXTRAS_AO]));
|
||||
|
||||
SAYF(bV bSTOP " dictionary : " cRST "%-36s " bSTG bV bSTOP
|
||||
" imported : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp,
|
||||
afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported) : (u8 *)"n/a");
|
||||
afl->sync_id ? u_stringify_int(IB(0), afl->queued_imported)
|
||||
: (u8 *)"n/a");
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
|
||||
u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
|
||||
u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
|
||||
u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]),
|
||||
u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]),
|
||||
u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_HAVOC]),
|
||||
u_stringify_int(IB(2), afl->stage_cycles[STAGE_HAVOC]),
|
||||
u_stringify_int(IB(3), afl->stage_finds[STAGE_SPLICE]),
|
||||
u_stringify_int(IB(4), afl->stage_cycles[STAGE_SPLICE]),
|
||||
u_stringify_int(IB(5), afl->stage_finds[STAGE_RADAMSA]),
|
||||
u_stringify_int(IB(6), afl->stage_cycles[STAGE_RADAMSA]));
|
||||
|
||||
SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
|
||||
|
||||
@ -660,14 +661,14 @@ void show_stats(afl_state_t *afl) {
|
||||
if (afl->shm.cmplog_mode) {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
|
||||
u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
|
||||
u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]),
|
||||
u_stringify_int(IB(4), afl->stage_finds[STAGE_COLORIZATION]),
|
||||
u_stringify_int(IB(5), afl->stage_cycles[STAGE_COLORIZATION]),
|
||||
u_stringify_int(IB(6), afl->stage_finds[STAGE_ITS]),
|
||||
u_stringify_int(IB(7), afl->stage_cycles[STAGE_ITS]));
|
||||
|
||||
SAYF(bV bSTOP " custom/rq : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
|
||||
tmp);
|
||||
@ -675,10 +676,10 @@ void show_stats(afl_state_t *afl) {
|
||||
} else {
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s",
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
u_stringify_int(IB(0), afl->stage_finds[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(1), afl->stage_cycles[STAGE_PYTHON]),
|
||||
u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
|
||||
SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
|
||||
tmp);
|
||||
|
@ -25,8 +25,6 @@
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
u8 be_quiet = 0;
|
||||
|
||||
static u8 *get_libradamsa_path(u8 *own_loc) {
|
||||
|
||||
u8 *tmp, *cp, *rsl, *own_copy;
|
||||
@ -693,6 +691,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
if (afl->fixed_seed) OKF("Running with fixed seed: %u", (u32)afl->init_seed);
|
||||
srandom((u32)afl->init_seed);
|
||||
srand((u32)afl->init_seed); // in case it is a different implementation
|
||||
|
||||
if (afl->use_radamsa) {
|
||||
|
||||
@ -723,6 +722,16 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
#if defined(__SANITIZE_ADDRESS__)
|
||||
if (afl->fsrv.mem_limit) {
|
||||
|
||||
WARNF("in the ASAN build we disable all memory limits");
|
||||
afl->fsrv.mem_limit = 0;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
setup_signal_handlers();
|
||||
check_asan_opts();
|
||||
|
||||
|
@ -59,13 +59,10 @@
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
|
||||
u8 be_quiet;
|
||||
|
||||
char *stdin_file; /* stdin file */
|
||||
|
||||
u8 *in_dir, /* input folder */
|
||||
*doc_path, /* Path to docs */
|
||||
*at_file = NULL; /* Substitution string for @@ */
|
||||
*at_file = NULL; /* Substitution string for @@ */
|
||||
|
||||
static u8 *in_data; /* Input data */
|
||||
|
||||
@ -224,26 +221,6 @@ static u32 write_results(afl_forkserver_t *fsrv) {
|
||||
|
||||
}
|
||||
|
||||
/* Write output file. */
|
||||
|
||||
static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
|
||||
|
||||
s32 ret;
|
||||
|
||||
unlink(path); /* Ignore errors */
|
||||
|
||||
ret = open(path, O_RDWR | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
if (ret < 0) PFATAL("Unable to create '%s'", path);
|
||||
|
||||
ck_write(ret, mem, len, path);
|
||||
|
||||
lseek(ret, 0, SEEK_SET);
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* Write modified data to file for testing. If use_stdin is clear, the old file
|
||||
is unlinked and a new one is created. Otherwise, out_fd is rewound and
|
||||
truncated. */
|
||||
|
@ -61,8 +61,7 @@
|
||||
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
|
||||
|
||||
u8 *in_file, /* Minimizer input test case */
|
||||
*output_file, /* Minimizer output file */
|
||||
*doc_path; /* Path to docs */
|
||||
*output_file; /* Minimizer output file */
|
||||
|
||||
static u8 *in_data; /* Input data for trimming */
|
||||
|
||||
@ -77,8 +76,7 @@ u8 crash_mode, /* Crash-centric mode? */
|
||||
hang_mode, /* Minimize as long as it hangs */
|
||||
exit_crash, /* Treat non-zero exit as crash? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
exact_mode, /* Require path match for crashes? */
|
||||
be_quiet;
|
||||
exact_mode; /* Require path match for crashes? */
|
||||
|
||||
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
||||
|
||||
@ -406,17 +404,6 @@ static u8 run_target(afl_forkserver_t *fsrv, char **argv, u8 *mem, u32 len,
|
||||
|
||||
}
|
||||
|
||||
/* Find first power of two greater or equal to val. */
|
||||
|
||||
static u32 next_p2(u32 val) {
|
||||
|
||||
u32 ret = 1;
|
||||
while (val > ret)
|
||||
ret <<= 1;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
/* Actually minimize! */
|
||||
|
||||
static void minimize(afl_forkserver_t *fsrv, char **argv) {
|
||||
@ -434,7 +421,7 @@ static void minimize(afl_forkserver_t *fsrv, char **argv) {
|
||||
* BLOCK NORMALIZATION *
|
||||
***********************/
|
||||
|
||||
set_len = next_p2(in_len / TMIN_SET_STEPS);
|
||||
set_len = next_pow2(in_len / TMIN_SET_STEPS);
|
||||
set_pos = 0;
|
||||
|
||||
if (set_len < TMIN_SET_MIN_SIZE) set_len = TMIN_SET_MIN_SIZE;
|
||||
@ -484,7 +471,7 @@ next_pass:
|
||||
* BLOCK DELETION *
|
||||
******************/
|
||||
|
||||
del_len = next_p2(in_len / TRIM_START_STEPS);
|
||||
del_len = next_pow2(in_len / TRIM_START_STEPS);
|
||||
stage_o_len = in_len;
|
||||
|
||||
ACTF(cBRI "Stage #1: " cRST "Removing blocks of data...");
|
||||
|
2
src/third_party/libradamsa/libradamsa.c
vendored
2
src/third_party/libradamsa/libradamsa.c
vendored
@ -30815,7 +30815,7 @@ size_t copy_list(uint8_t *ptr, word lispval, size_t max) {
|
||||
lispval = G(lispval, 2); // list = cdr(list)
|
||||
}
|
||||
if (lispval != INULL && max == 0) {
|
||||
printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", lispval);
|
||||
printf("ERROR: lisp return value was not a proper list. Trailing %lu\n", (unsigned long)lispval);
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
19
test/test-custom-mutator.c
Normal file
19
test/test-custom-mutator.c
Normal file
@ -0,0 +1,19 @@
|
||||
/**
|
||||
* Reference: https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/blob/master/4_libprotobuf_aflpp_custom_mutator/vuln.c
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <math.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
char str[100];
|
||||
read(0, str, 100);
|
||||
if( str[6] == 'A') {
|
||||
abort();
|
||||
}
|
||||
return 0;
|
||||
}
|
134
test/test.sh
134
test/test.sh
@ -73,7 +73,7 @@ export ASAN_OPTIONS=detect_leaks=0:allocator_may_return_null=1:abort_on_error=1:
|
||||
# on OpenBSD we need to work with llvm from /usr/local/bin
|
||||
test -e /usr/local/bin/opt && {
|
||||
export PATH=/usr/local/bin:${PATH}
|
||||
}
|
||||
}
|
||||
# on MacOS X we prefer afl-clang over afl-gcc, because
|
||||
# afl-gcc does not work there
|
||||
test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && {
|
||||
@ -142,11 +142,11 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# make sure core_pattern is set to core on linux
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
@ -210,13 +210,13 @@ test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc
|
||||
unset AFL_QUIET
|
||||
}
|
||||
rm -f test-instr.plain
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
|
||||
}
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: llvm_mode, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
|
||||
test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
@ -248,7 +248,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
@ -265,11 +265,11 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
@ -373,7 +373,7 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
$ECHO "$RED[!] llvm_mode whitelist feature failed"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode whitelist feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
@ -426,7 +426,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode LTO instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
@ -447,7 +447,7 @@ test -e ../afl-clang-lto -a -e ../afl-llvm-lto-instrumentation.so && {
|
||||
# $ECHO "$RED[!] llvm_mode LTO whitelist feature failed"
|
||||
# CODE=1
|
||||
# }
|
||||
# } || {
|
||||
# } || {
|
||||
# $ECHO "$RED[!] llvm_mode LTO whitelist feature compilation failed"
|
||||
# CODE=1
|
||||
# }
|
||||
@ -483,7 +483,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
diff test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] gcc_plugin instrumentation should be different on different input but is not"
|
||||
CODE=1
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly"
|
||||
TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
|
||||
@ -516,7 +516,7 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
$ECHO "$RED[!] gcc_plugin hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
@ -552,11 +552,11 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
test -e test-compcov && {
|
||||
echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && {
|
||||
$ECHO "$GREEN[+] gcc_plugin whitelist feature works correctly"
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin whitelist feature failed"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin whitelist feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
@ -580,12 +580,12 @@ test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: shared library extensions"
|
||||
cc -o test-compcov test-compcov.c > /dev/null 2>&1
|
||||
cc $CFLAGS -o test-compcov test-compcov.c > /dev/null 2>&1
|
||||
test -e ../libtokencap.so && {
|
||||
AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1
|
||||
grep -q BUGMENOT token.out > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] libtokencap did successfully capture tokens"
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$RED[!] libtokencap did not capture tokens"
|
||||
CODE=1
|
||||
}
|
||||
@ -604,7 +604,7 @@ test -e ../libdislocator.so && {
|
||||
$ECHO "$RED[!] libdislocator did not detect the memory corruption"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
|
||||
$ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
|
||||
}
|
||||
rm -f test.out core test-compcov.core core.test-compcov
|
||||
} || {
|
||||
@ -700,7 +700,7 @@ test -e ../afl-qemu-trace && {
|
||||
test -e ../libcompcov.so && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for qemu_mode compcov, this will take approx 10 seconds"
|
||||
{
|
||||
export AFL_PRELOAD=../libcompcov.so
|
||||
export AFL_PRELOAD=../libcompcov.so
|
||||
export AFL_COMPCOV_LEVEL=2
|
||||
../afl-fuzz -m ${MEM_LIMIT} -V10 -Q -i in -o out -- ./test-compcov >>errors 2>&1
|
||||
unset AFL_PRELOAD
|
||||
@ -720,10 +720,10 @@ test -e ../afl-qemu-trace && {
|
||||
INCOMPLETE=1
|
||||
}
|
||||
rm -f errors
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] not an intel or arm platform, cannot test qemu_mode compcov"
|
||||
}
|
||||
|
||||
|
||||
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" -o "$SYS" = "i86pc" -o "$SYS" = "aarch64" -o ! "${SYS%%arm*}" && {
|
||||
$ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
|
||||
{
|
||||
@ -757,9 +757,9 @@ test -e ../afl-qemu-trace && {
|
||||
exit 1
|
||||
}
|
||||
rm -rf in out errors
|
||||
} || {
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] not an intel or arm platform, cannot test persistent qemu_mode"
|
||||
}
|
||||
}
|
||||
|
||||
test -e ../qemu_mode/unsigaction/unsigaction32.so && {
|
||||
${AFL_CC} -o test-unsigaction32 -m32 test-unsigaction.c >> errors 2>&1 && {
|
||||
@ -824,7 +824,7 @@ test -e ../afl-qemu-trace && {
|
||||
$ECHO "$RED[!] gcc compilation of test targets failed - what is going on??"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
|
||||
rm -f test-instr test-compcov
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
|
||||
@ -887,12 +887,94 @@ test -d ../unicorn_mode/unicornafl && {
|
||||
$ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: custom mutator"
|
||||
unset AFL_CC # Test case "gcc_plugin" sets AFL_CC to "gcc". We reset it to use the default compiler
|
||||
test `uname -s` = 'Darwin' && {
|
||||
CUSTOM_MUTATOR_PATH=$( realpath ../examples/custom_mutators )
|
||||
} || {
|
||||
CUSTOM_MUTATOR_PATH=$( readlink -f ../examples/custom_mutators )
|
||||
}
|
||||
test -e test-custom-mutator.c -a -e ${CUSTOM_MUTATOR_PATH}/example.c -a -e ${CUSTOM_MUTATOR_PATH}/example.py && {
|
||||
# Compile the vulnerable program
|
||||
../afl-clang-fast -o test-custom-mutator test-custom-mutator.c > /dev/null 2>&1
|
||||
# Compile the custom mutator
|
||||
make -C ../examples/custom_mutators libexamplemutator.so > /dev/null 2>&1
|
||||
test -e test-custom-mutator -a -e ${CUSTOM_MUTATOR_PATH}/libexamplemutator.so && {
|
||||
# Create input directory
|
||||
mkdir -p in
|
||||
echo "00000" > in/in
|
||||
|
||||
# Run afl-fuzz w/ the C mutator
|
||||
$ECHO "$GREY[*] running afl-fuzz for the C mutator, this will take approx 10 seconds"
|
||||
{
|
||||
AFL_CUSTOM_MUTATOR_LIBRARY=${CUSTOM_MUTATOR_PATH}/libexamplemutator.so ../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
|
||||
# Check results
|
||||
test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && { # TODO: update here
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with the C mutator"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with the C mutator"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
# Clean
|
||||
rm -rf out errors
|
||||
|
||||
# Run afl-fuzz w/ the Python mutator
|
||||
$ECHO "$GREY[*] running afl-fuzz for the Python mutator, this will take approx 10 seconds"
|
||||
{
|
||||
export PYTHONPATH=${CUSTOM_MUTATOR_PATH}
|
||||
export AFL_PYTHON_MODULE=example
|
||||
../afl-fuzz -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-custom-mutator >>errors 2>&1
|
||||
unset PYTHONPATH
|
||||
unset AFL_PYTHON_MODULE
|
||||
} >>errors 2>&1
|
||||
|
||||
# Check results
|
||||
test -n "$( ls out/crashes/id:000000* 2>/dev/null )" && { # TODO: update here
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with the Python mutator"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with the Python mutator"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
# Clean
|
||||
rm -rf in out errors
|
||||
rm -rf ${CUSTOM_MUTATOR_PATH}/__pycache__/
|
||||
} || {
|
||||
ls .
|
||||
ls ${CUSTOM_MUTATOR_PATH}
|
||||
$ECHO "$RED[!] cannot compile the test program or the custom mutator"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
#test "$CODE" = 1 && { $ECHO "$YELLOW[!] custom mutator tests currently will not fail travis" ; CODE=0 ; }
|
||||
|
||||
make -C ../examples/custom_mutators clean > /dev/null 2>&1
|
||||
rm -f test-custom-mutator
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] no custom mutators in $CUSTOM_MUTATOR_PATH, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
unset CUSTOM_MUTATOR_PATH
|
||||
|
||||
$ECHO "$BLUE[*] Execution cmocka Unit-Tests $GREY"
|
||||
unset AFL_CC
|
||||
make -C .. unit || "$CODE" = "1"
|
||||
|
||||
$ECHO "$GREY[*] all test cases completed.$RESET"
|
||||
test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed"
|
||||
test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed"
|
||||
|
128
test/unittests/unit_list.c
Normal file
128
test/unittests/unit_list.c
Normal file
@ -0,0 +1,128 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <cmocka.h>
|
||||
/* cmocka < 1.0 didn't support these features we need */
|
||||
#ifndef assert_ptr_equal
|
||||
#define assert_ptr_equal(a, b) \
|
||||
_assert_int_equal(cast_ptr_to_largest_integral_type(a), \
|
||||
cast_ptr_to_largest_integral_type(b), \
|
||||
__FILE__, __LINE__)
|
||||
#define CMUnitTest UnitTest
|
||||
#define cmocka_unit_test unit_test
|
||||
#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
|
||||
#endif
|
||||
|
||||
|
||||
extern void mock_assert(const int result, const char* const expression,
|
||||
const char * const file, const int line);
|
||||
#undef assert
|
||||
#define assert(expression) \
|
||||
mock_assert((int)(expression), #expression, __FILE__, __LINE__);
|
||||
|
||||
#include "list.h"
|
||||
|
||||
/* remap exit -> assert, then use cmocka's mock_assert
|
||||
(compile with `--wrap=exit`) */
|
||||
extern void exit(int status);
|
||||
extern void __real_exit(int status);
|
||||
void __wrap_exit(int status) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* ignore all printfs */
|
||||
extern int printf(const char *format, ...);
|
||||
extern int __real_printf(const char *format, ...);
|
||||
int __wrap_printf(const char *format, ...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
list_t testlist;
|
||||
|
||||
static void test_contains(void **state) {
|
||||
|
||||
u32 one = 1;
|
||||
u32 two = 2;
|
||||
|
||||
list_append(&testlist, &one);
|
||||
assert_true(list_contains(&testlist, &one));
|
||||
assert_false(list_contains(&testlist, &two));
|
||||
list_remove(&testlist, &one);
|
||||
assert_false(list_contains(&testlist, &one));
|
||||
}
|
||||
|
||||
static void test_foreach(void **state) {
|
||||
|
||||
u32 one = 1;
|
||||
u32 two = 2;
|
||||
u32 result = 0;
|
||||
|
||||
list_append(&testlist, &one);
|
||||
list_append(&testlist, &two);
|
||||
list_append(&testlist, &one);
|
||||
|
||||
/* The list is for pointers, so int doesn't work as type directly */
|
||||
LIST_FOREACH(&testlist, u32, {
|
||||
result += *el;
|
||||
});
|
||||
|
||||
assert_int_equal(result, 4);
|
||||
|
||||
}
|
||||
|
||||
static void test_long_list(void **state) {
|
||||
|
||||
u32 result1 = 0;
|
||||
u32 result2 = 0;
|
||||
u32 i;
|
||||
|
||||
u32 vals[100];
|
||||
|
||||
for (i = 0; i < 100; i++) {
|
||||
vals[i] = i;
|
||||
}
|
||||
|
||||
LIST_FOREACH_CLEAR(&testlist, void, {});
|
||||
for (i = 0; i < 100; i++) {
|
||||
list_append(&testlist, &vals[i]);
|
||||
}
|
||||
LIST_FOREACH(&testlist, u32, {
|
||||
result1 += *el;
|
||||
});
|
||||
printf("removing %d\n", vals[50]);
|
||||
list_remove(&testlist, &vals[50]);
|
||||
|
||||
LIST_FOREACH(&testlist, u32, {
|
||||
// printf("var: %d\n", *el);
|
||||
result2 += *el;
|
||||
});
|
||||
assert_int_not_equal(result1, result2);
|
||||
assert_int_equal(result1, result2 + 50);
|
||||
|
||||
result1 = 0;
|
||||
LIST_FOREACH_CLEAR(&testlist, u32, {
|
||||
result1 += *el;
|
||||
});
|
||||
assert_int_equal(result1, result2);
|
||||
|
||||
result1 = 0;
|
||||
LIST_FOREACH(&testlist, u32, {
|
||||
result1 += *el;
|
||||
});
|
||||
assert_int_equal(result1, 0);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_contains),
|
||||
cmocka_unit_test(test_foreach),
|
||||
cmocka_unit_test(test_long_list),
|
||||
};
|
||||
|
||||
//return cmocka_run_group_tests (tests, setup, teardown);
|
||||
return cmocka_run_group_tests (tests, NULL, NULL);
|
||||
|
||||
}
|
158
test/unittests/unit_maybe_alloc.c
Normal file
158
test/unittests/unit_maybe_alloc.c
Normal file
@ -0,0 +1,158 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <cmocka.h>
|
||||
/* cmocka < 1.0 didn't support these features we need */
|
||||
#ifndef assert_ptr_equal
|
||||
#define assert_ptr_equal(a, b) \
|
||||
_assert_int_equal(cast_ptr_to_largest_integral_type(a), \
|
||||
cast_ptr_to_largest_integral_type(b), \
|
||||
__FILE__, __LINE__)
|
||||
#define CMUnitTest UnitTest
|
||||
#define cmocka_unit_test unit_test
|
||||
#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
|
||||
#endif
|
||||
|
||||
|
||||
extern void mock_assert(const int result, const char* const expression,
|
||||
const char * const file, const int line);
|
||||
#undef assert
|
||||
#define assert(expression) \
|
||||
mock_assert((int)(expression), #expression, __FILE__, __LINE__);
|
||||
#include "alloc-inl.h"
|
||||
|
||||
/* remap exit -> assert, then use cmocka's mock_assert
|
||||
(compile with `--wrap=exit`) */
|
||||
extern void exit(int status);
|
||||
extern void __real_exit(int status);
|
||||
void __wrap_exit(int status) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* ignore all printfs */
|
||||
extern int printf(const char *format, ...);
|
||||
extern int __real_printf(const char *format, ...);
|
||||
int __wrap_printf(const char *format, ...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
#define BUF_PARAMS (void **)&buf, &size
|
||||
|
||||
/*
|
||||
static int setup(void **state) {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
static void test_null_allocs(void **state) {
|
||||
|
||||
void *buf = NULL;
|
||||
size_t size = 0;
|
||||
void *ptr = ck_maybe_grow(BUF_PARAMS, 100);
|
||||
assert_true(buf == ptr);
|
||||
assert_true(size >= 100);
|
||||
ck_free(ptr);
|
||||
|
||||
}
|
||||
|
||||
static void test_nonpow2_size(void **state) {
|
||||
|
||||
char *buf = ck_alloc(150);
|
||||
size_t size = 150;
|
||||
buf[140] = '5';
|
||||
char *ptr = ck_maybe_grow(BUF_PARAMS, 160);
|
||||
assert_ptr_equal(buf, ptr);
|
||||
assert_true(size >= 160);
|
||||
assert_true(buf[140] == '5');
|
||||
ck_free(ptr);
|
||||
|
||||
}
|
||||
|
||||
static void test_zero_size() {
|
||||
|
||||
char *buf = NULL;
|
||||
size_t size = 0;
|
||||
assert_non_null(maybe_grow(BUF_PARAMS, 0));
|
||||
free(buf);
|
||||
buf = NULL;
|
||||
size = 0;
|
||||
|
||||
char *ptr = ck_maybe_grow(BUF_PARAMS, 100);
|
||||
assert_non_null(ptr);
|
||||
assert_ptr_equal(buf, ptr);
|
||||
assert_true(size >= 100);
|
||||
|
||||
expect_assert_failure(ck_maybe_grow(BUF_PARAMS, 0));
|
||||
|
||||
ck_free(ptr);
|
||||
|
||||
}
|
||||
|
||||
static void test_unchanged_size(void **state) {
|
||||
|
||||
void *buf = ck_alloc(100);
|
||||
size_t size = 100;
|
||||
void *buf_before = buf;
|
||||
void *buf_after = ck_maybe_grow(BUF_PARAMS, 100);
|
||||
assert_ptr_equal(buf, buf_after);
|
||||
assert_ptr_equal(buf_after, buf_before);
|
||||
ck_free(buf);
|
||||
|
||||
}
|
||||
|
||||
static void test_grow_multiple(void **state) {
|
||||
|
||||
char *buf = NULL;
|
||||
size_t size = 0;
|
||||
|
||||
char *ptr = ck_maybe_grow(BUF_PARAMS, 100);
|
||||
assert_ptr_equal(ptr, buf);
|
||||
assert_true(size >= 100);
|
||||
assert_int_equal(size, next_pow2(size));
|
||||
buf[50] = '5';
|
||||
|
||||
ptr = (char *)ck_maybe_grow(BUF_PARAMS, 1000);
|
||||
assert_ptr_equal(ptr, buf);
|
||||
assert_true(size >= 100);
|
||||
assert_int_equal(size, next_pow2(size));
|
||||
buf[500] = '5';
|
||||
|
||||
ptr = (char *)ck_maybe_grow(BUF_PARAMS, 10000);
|
||||
assert_ptr_equal(ptr, buf);
|
||||
assert_true(size >= 10000);
|
||||
assert_int_equal(size, next_pow2(size));
|
||||
buf[5000] = '5';
|
||||
|
||||
assert_int_equal(buf[50], '5');
|
||||
assert_int_equal(buf[500], '5');
|
||||
assert_int_equal(buf[5000], '5');
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
static int teardown(void **state) {
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
*/
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_null_allocs),
|
||||
cmocka_unit_test(test_nonpow2_size),
|
||||
cmocka_unit_test(test_zero_size),
|
||||
cmocka_unit_test(test_unchanged_size),
|
||||
cmocka_unit_test(test_grow_multiple),
|
||||
};
|
||||
|
||||
//return cmocka_run_group_tests (tests, setup, teardown);
|
||||
return cmocka_run_group_tests (tests, NULL, NULL);
|
||||
|
||||
}
|
111
test/unittests/unit_preallocable.c
Normal file
111
test/unittests/unit_preallocable.c
Normal file
@ -0,0 +1,111 @@
|
||||
#include <stdarg.h>
|
||||
#include <stddef.h>
|
||||
#include <setjmp.h>
|
||||
#include <assert.h>
|
||||
#include <cmocka.h>
|
||||
/* cmocka < 1.0 didn't support these features we need */
|
||||
#ifndef assert_ptr_equal
|
||||
#define assert_ptr_equal(a, b) \
|
||||
_assert_int_equal(cast_ptr_to_largest_integral_type(a), \
|
||||
cast_ptr_to_largest_integral_type(b), \
|
||||
__FILE__, __LINE__)
|
||||
#define CMUnitTest UnitTest
|
||||
#define cmocka_unit_test unit_test
|
||||
#define cmocka_run_group_tests(t, setup, teardown) run_tests(t)
|
||||
#endif
|
||||
|
||||
|
||||
extern void mock_assert(const int result, const char* const expression,
|
||||
const char * const file, const int line);
|
||||
#undef assert
|
||||
#define assert(expression) \
|
||||
mock_assert((int)(expression), #expression, __FILE__, __LINE__);
|
||||
|
||||
#include "afl-prealloc.h"
|
||||
|
||||
/* remap exit -> assert, then use cmocka's mock_assert
|
||||
(compile with `--wrap=exit`) */
|
||||
extern void exit(int status);
|
||||
extern void __real_exit(int status);
|
||||
void __wrap_exit(int status) {
|
||||
assert(0);
|
||||
}
|
||||
|
||||
/* ignore all printfs */
|
||||
extern int printf(const char *format, ...);
|
||||
extern int __real_printf(const char *format, ...);
|
||||
int __wrap_printf(const char *format, ...) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
typedef struct prealloc_me
|
||||
{
|
||||
PREALLOCABLE;
|
||||
|
||||
u8 *content[128];
|
||||
|
||||
} prealloc_me_t;
|
||||
|
||||
#define PREALLOCED_BUF_SIZE (64)
|
||||
prealloc_me_t prealloc_me_buf[PREALLOCED_BUF_SIZE];
|
||||
size_t prealloc_me_size = 0;
|
||||
|
||||
static void test_alloc_free(void **state) {
|
||||
|
||||
prealloc_me_t *prealloced = NULL;
|
||||
PRE_ALLOC(prealloced, prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
|
||||
assert_non_null(prealloced);
|
||||
PRE_FREE(prealloced, prealloc_me_size);
|
||||
|
||||
}
|
||||
|
||||
static void test_prealloc_overflow(void **state) {
|
||||
|
||||
u32 i = 0;
|
||||
prealloc_me_t *prealloced[PREALLOCED_BUF_SIZE + 10];
|
||||
|
||||
for (i = 0; i < PREALLOCED_BUF_SIZE + 10; i++) {
|
||||
|
||||
PRE_ALLOC(prealloced[i], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
|
||||
assert_non_null(prealloced[i]);
|
||||
|
||||
}
|
||||
assert_int_equal(prealloced[0]->pre_status, PRE_STATUS_USED);
|
||||
assert_int_equal(prealloced[PREALLOCED_BUF_SIZE]->pre_status, PRE_STATUS_MALLOC);
|
||||
|
||||
PRE_FREE(prealloced[20], prealloc_me_size);
|
||||
PRE_ALLOC(prealloced[20], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
|
||||
assert_non_null(prealloced[20]);
|
||||
assert_int_equal(prealloced[20]->pre_status, PRE_STATUS_USED);
|
||||
|
||||
PRE_FREE(prealloced[PREALLOCED_BUF_SIZE], prealloc_me_size);
|
||||
PRE_FREE(prealloced[0], prealloc_me_size);
|
||||
PRE_ALLOC(prealloced[PREALLOCED_BUF_SIZE], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
|
||||
assert_non_null(prealloced[PREALLOCED_BUF_SIZE]);
|
||||
/* there should be space now! */
|
||||
assert_int_equal(prealloced[PREALLOCED_BUF_SIZE]->pre_status, PRE_STATUS_USED);
|
||||
|
||||
PRE_ALLOC(prealloced[0], prealloc_me_buf, PREALLOCED_BUF_SIZE, prealloc_me_size);
|
||||
assert_non_null(prealloced[0]);
|
||||
/* no more space */
|
||||
assert_int_equal(prealloced[0]->pre_status, PRE_STATUS_MALLOC);
|
||||
|
||||
for (i = 0; i < PREALLOCED_BUF_SIZE + 10; i++) {
|
||||
|
||||
PRE_FREE(prealloced[i], prealloc_me_size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
const struct CMUnitTest tests[] = {
|
||||
cmocka_unit_test(test_alloc_free),
|
||||
cmocka_unit_test(test_prealloc_overflow),
|
||||
};
|
||||
|
||||
//return cmocka_run_group_tests (tests, setup, teardown);
|
||||
return cmocka_run_group_tests (tests, NULL, NULL);
|
||||
|
||||
}
|
42
unicorn_mode/samples/c/GNUmakefile
Normal file
42
unicorn_mode/samples/c/GNUmakefile
Normal file
@ -0,0 +1,42 @@
|
||||
# UnicornAFL Usage
|
||||
# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
|
||||
# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
LIBDIR = ../../unicornafl
|
||||
BIN_EXT =
|
||||
AR_EXT = a
|
||||
|
||||
# Verbose output?
|
||||
V ?= 0
|
||||
|
||||
CFLAGS += -Wall -Werror -I../../unicornafl/include
|
||||
|
||||
LDFLAGS += -L$(LIBDIR) -lpthread -lm
|
||||
ifeq ($(UNAME_S), Linux)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifneq ($(CROSS),)
|
||||
CC = $(CROSS)gcc
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: harness
|
||||
|
||||
clean:
|
||||
rm -rf *.o harness harness-debug
|
||||
|
||||
harness.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -O3 -c $<
|
||||
|
||||
harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -g -c $< -o $@
|
||||
|
||||
harness: harness.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
|
||||
|
||||
debug: harness-debug.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
|
@ -1,42 +1,2 @@
|
||||
# UnicornAFL Usage
|
||||
# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
|
||||
# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
LIBDIR = ../../unicornafl
|
||||
BIN_EXT =
|
||||
AR_EXT = a
|
||||
|
||||
# Verbose output?
|
||||
V ?= 0
|
||||
|
||||
CFLAGS += -Wall -Werror -I../../unicornafl/include
|
||||
|
||||
LDFLAGS += -L$(LIBDIR) -lpthread -lm
|
||||
ifeq ($(UNAME_S), Linux)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifneq ($(CROSS),)
|
||||
CC = $(CROSS)gcc
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: harness
|
||||
|
||||
clean:
|
||||
rm -rf *.o harness harness-debug
|
||||
|
||||
harness.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -O3 -c $<
|
||||
|
||||
harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -g -c $< -o $@
|
||||
|
||||
harness: harness.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
|
||||
|
||||
debug: harness-debug.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
42
unicorn_mode/samples/persistent/GNUmakefile
Normal file
42
unicorn_mode/samples/persistent/GNUmakefile
Normal file
@ -0,0 +1,42 @@
|
||||
# UnicornAFL Usage
|
||||
# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
|
||||
# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
LIBDIR = ../../unicornafl
|
||||
BIN_EXT =
|
||||
AR_EXT = a
|
||||
|
||||
# Verbose output?
|
||||
V ?= 0
|
||||
|
||||
CFLAGS += -Wall -Werror -I../../unicornafl/include
|
||||
|
||||
LDFLAGS += -L$(LIBDIR) -lpthread -lm
|
||||
ifeq ($(UNAME_S), Linux)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifneq ($(CROSS),)
|
||||
CC = $(CROSS)gcc
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: harness
|
||||
|
||||
clean:
|
||||
rm -rf *.o harness harness-debug
|
||||
|
||||
harness.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -O3 -c $<
|
||||
|
||||
harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -g -c $< -o $@
|
||||
|
||||
harness: harness.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
|
||||
|
||||
debug: harness-debug.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
|
@ -1,42 +1,2 @@
|
||||
# UnicornAFL Usage
|
||||
# Original Unicorn Example Makefile by Nguyen Anh Quynh <aquynh@gmail.com>, 2015
|
||||
# Adapted for AFL++ by domenukk <domenukk@gmail.com>, 2020
|
||||
|
||||
UNAME_S := $(shell uname -s)
|
||||
|
||||
LIBDIR = ../../unicornafl
|
||||
BIN_EXT =
|
||||
AR_EXT = a
|
||||
|
||||
# Verbose output?
|
||||
V ?= 0
|
||||
|
||||
CFLAGS += -Wall -Werror -I../../unicornafl/include
|
||||
|
||||
LDFLAGS += -L$(LIBDIR) -lpthread -lm
|
||||
ifeq ($(UNAME_S), Linux)
|
||||
LDFLAGS += -lrt
|
||||
endif
|
||||
|
||||
ifneq ($(CROSS),)
|
||||
CC = $(CROSS)gcc
|
||||
endif
|
||||
|
||||
.PHONY: all clean
|
||||
|
||||
all: harness
|
||||
|
||||
clean:
|
||||
rm -rf *.o harness harness-debug
|
||||
|
||||
harness.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -O3 -c $<
|
||||
|
||||
harness-debug.o: harness.c ../../unicornafl/include/unicorn/*.h
|
||||
${CC} ${CFLAGS} -g -c $< -o $@
|
||||
|
||||
harness: harness.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o $@
|
||||
|
||||
debug: harness-debug.o
|
||||
${CC} -L${LIBDIR} $< ../../unicornafl/libunicornafl.a $(LDFLAGS) -o harness-debug
|
||||
all:
|
||||
@echo please use GNU make, thanks!
|
||||
|
Loading…
x
Reference in New Issue
Block a user