Merge branch 'master' into radamsa

This commit is contained in:
Andrea Fioraldi 2019-11-11 14:36:06 +01:00 committed by GitHub
commit 659db7e421
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
114 changed files with 3594 additions and 364 deletions

View File

@ -1,4 +1,19 @@
#!/usr/bin/env python3
#
# american fuzzy lop++ - custom code formatter
# --------------------------------------------
#
# Written and maintaned by Andrea Fioraldi <andreafioraldi@gmail.com>
#
# Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
# Copyright 2019 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
#
import subprocess
import sys

2
.gitignore vendored
View File

@ -23,6 +23,8 @@ afl-clang-fast.8
afl-cmin.8
afl-fuzz.8
afl-gcc.8
afl-gcc-fast.8
afl-g++-fast.8
afl-gotcpu.8
afl-plot.8
afl-showmap.8

View File

@ -1,11 +1,18 @@
dist: bionic
language: c
env:
- AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1
- AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_STOP_MANUALLY=1
# - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_EXIT_WHEN_DONE=1
# TODO: test AFL_BENCH_UNTIL_CRASH once we have a target that crashes
# - AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 AFL_NO_UI=1 AFL_BENCH_JUST_ONE=1
before_install:
- sudo apt update
- sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-7 gcc-7-plugin-dev libc++-7-dev
script:
- make
- ./afl-gcc ./test-instr.c -o test-instr
- mkdir seeds; mkdir out
- echo "" > seeds/nil_seed
- timeout --preserve-status 5s ./afl-fuzz -i seeds -o out/ -- ./test-instr
- gcc -v
- clang -v
- make distrib
- make tests

27
Dockerfile Normal file
View File

@ -0,0 +1,27 @@
FROM ubuntu:eoan
MAINTAINER David Carlier <devnexen@gmail.com>
LABEL "about"="AFLplusplus docker image"
RUN apt-get update && apt-get install -y --no-install-recommends \
automake \
bison \
build-essential \
clang \
clang-9 \
flex \
gcc-9 \
gcc-9-plugin-dev \
libc++-9-dev \
libtool \
libtool-bin \
libglib2.0-dev \
llvm-9-tools \
python-setuptools \
wget \
&& rm -fr /var/lib/apt/lists/*
RUN mkdir /app
WORKDIR ["/app"]
COPY . .
ENV CC=gcc-9
ENV CXX=g++-9
ENV LLVM_CONFIG=llvm-config-9
RUN make clean && make distrib && make install

View File

@ -2,7 +2,7 @@
# american fuzzy lop - makefile
# -----------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved.
#
@ -16,9 +16,6 @@
# For Heiko:
#TEST_MMAP=1
PROGNAME = afl
VERSION = $(shell grep '^\#define VERSION ' include/config.h | cut -d '"' -f2)
PREFIX ?= /usr/local
BIN_PATH = $(PREFIX)/bin
HELPER_PATH = $(PREFIX)/lib/afl
@ -26,6 +23,9 @@ DOC_PATH = $(PREFIX)/share/doc/afl
MISC_PATH = $(PREFIX)/share/afl
MAN_PATH = $(PREFIX)/man/man8
PROGNAME = afl
VERSION = $(shell grep '^\#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
@ -33,10 +33,9 @@ SH_PROGS = afl-plot afl-cmin afl-whatsup afl-system-config
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8)
CFLAGS ?= -O3 -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \
-I include/ \
-DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -Wno-unused-function
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
@ -100,16 +99,24 @@ all: test_x86 test_shm test_python27 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
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"
@echo "source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap"
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap"
@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"
@ -124,6 +131,8 @@ help:
ifndef AFL_NO_X86
test_x86:
@echo "[*] Checking for the default compiler cc..."
@which $(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
@ -219,6 +228,9 @@ code-format:
./.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 qemu_mode/patches/*.h
./.custom-format.py -i qemu_mode/libcompcov/*.c
./.custom-format.py -i qemu_mode/libcompcov/*.cc
@ -232,7 +244,7 @@ ifndef AFL_NO_X86
test_build: afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper and instrumentation output..."
unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; AFL_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS)
@unset AFL_USE_ASAN AFL_USE_MSAN AFL_CC; 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 )
./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@ -259,6 +271,7 @@ clean:
rm -f $(PROGS) libradamsa.so 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 *.so unicorn_mode/24f55a7973278f20f0de21b904851d99d4716263.tar.gz *.8
rm -rf out_dir qemu_mode/qemu-3.1.1 unicorn_mode/unicorn *.dSYM */*.dSYM
-$(MAKE) -C llvm_mode clean
-$(MAKE) -C gcc_plugin clean
$(MAKE) -C libdislocator clean
$(MAKE) -C libtokencap clean
$(MAKE) -C qemu_mode/unsigaction clean
@ -267,6 +280,7 @@ clean:
distrib: all
-$(MAKE) -C llvm_mode
-$(MAKE) -C gcc_plugin
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
cd qemu_mode && sh ./build_qemu_support.sh
@ -280,6 +294,7 @@ binary-only: all
source-only: all
-$(MAKE) -C llvm_mode
-$(MAKE) -C gcc_plugin
$(MAKE) -C libdislocator
$(MAKE) -C libtokencap
@ -296,7 +311,7 @@ source-only: all
@./$* -h 2>&1 | tail -n +4 >> $@
@echo >> $@
@echo .SH AUTHOR >> $@
@echo "afl++ was written by Michal \"lcamtuf\" Zalewski and is maintained by Marc \"van Hauser\" Heuse <mh@mh-sec.de>, Heiko \"hexc0der\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> $@
@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> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> $@
@echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> $@
@echo >> $@
@echo .SH LICENSE >> $@
@ -308,7 +323,7 @@ install: all $(MANPAGES)
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-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
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
else

View File

@ -1,8 +1,8 @@
# american fuzzy lop plus plus (afl++)
Release Version: 2.54c
Release Version: 2.58c
Github Version: 2.54d
Github Version: 2.58d
includes all necessary/interesting changes from Google's afl 2.56b
@ -22,7 +22,7 @@
## The enhancements compared to the original stock afl
Many improvements were made over the official afl release - which did not
get any improvements since November 2017.
get any feature improvements since November 2017.
Among other changes afl++ has a more performant llvm_mode, supports
llvm up to version 9, QEMU 3.1, more speed and crashfixes for QEMU,
@ -52,15 +52,17 @@
A more thorough list is available in the PATCHES file.
| Feature/Instrumentation | LLVM | GCC | QEMU | Unicorn |
| ----------------------- |:----:|:---:|:----:| -------:|
| laf-intel / CompCov | x | | x | x |
| NeverZero | x(1)| x | x | x |
| Persistent mode | x | | x | |
| Whitelist | x | | | |
| InsTrim | x | | | |
| Feature/Instrumentation | AFL-GCC | LLVM_MODE | GCC_PLUGIN | QEMU_MODE | Unicorn |
| ----------------------- |:-------:|:---------:|:----------:|:---------:|:-------:|
| laf-intel / CompCov | | x | | x | x |
| NeverZero | x | x(1) | (2) | x | x |
| Persistent mode | | x | x | x | |
| Whitelist | | x | x | | |
| InsTrim | | x | | | |
neverZero:
(1) only in LLVM >= 9.0 due to a bug in llvm in previous versions
(2) gcc create non-performant code, hence it is disabled in gcc_plugin
So all in all this is the best-of AFL that is currently out there :-)
@ -103,14 +105,24 @@ These build options exist:
* distrib: everything (for both binary-only and source code fuzzing)
* install: installs everything you have compiled with the build options above
* clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well
* tests: runs test cases to ensure that all features are still working as they should
* help: shows these build options
You can also build statically linked versions of the afl++ binaries by passing the STATIC=1 argument to make:
[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
afl++ binaries by passing the STATIC=1 argument to make:
```shell
$ make all STATIC=1
```
Note that afl++ is faster and better the newer the compilers used.
Hence gcc-9 and especially llvm-9 should be the compilers of choice.
If your distribution does not have them, you can use the Dockerfile:
```shell
$ docker build -t aflplusplus
```
## 1) Challenges of guided fuzzing
@ -453,7 +465,7 @@ 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
utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.md).
utility with AFL. For that, see [libtokencap/README.md](libtokencap/README.tokencap.md).
## 11) Crash triage
@ -619,7 +631,7 @@ without feedback, bug reports, or patches from:
Jonathan Gray Filipe Cabecinhas
Nico Weber Jodie Cunningham
Andrew Griffiths Parker Thompson
Jonathan Neuschfer Tyler Nighswander
Jonathan Neuschaefer Tyler Nighswander
Ben Nagy Samir Aguiar
Aidan Thornton Aleksandar Nikolich
Sam Hakim Laszlo Szekeres
@ -638,7 +650,7 @@ without feedback, bug reports, or patches from:
Austin Seipp Daniel Komaromy
Daniel Binderman Jonathan Metzman
Vegard Nossum Jan Kneschke
Kurt Roeckx Marcel Bohme
Kurt Roeckx Marcel Boehme
Van-Thuan Pham Abhik Roychoudhury
Joshua J. Drake Toby Hutton
Rene Freingruber Sergey Davidoff

13
TODO
View File

@ -1,16 +1,15 @@
Roadmap 2.55d:
==============
Roadmap 2.60:
=============
afl-fuzz:
- radamsa mutator
- radamsa mutator (via dlopen())
gcc_plugin:
- needs to be rewritten
- whitelist support
- skip over uninteresting blocks
- laf-intel
- neverZero
libdislocator:
- add a wrapper for posix_memalign
qemu_mode:
- update to 4.x (probably this will be skipped :( )

View File

@ -3,7 +3,7 @@
# american fuzzy lop - corpus minimization tool
# ---------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2014, 2015 Google Inc. All rights reserved.
#
@ -36,7 +36,7 @@
# array sizes.
#
echo "corpus minimization tool for afl-fuzz by <lcamtuf@google.com>"
echo "corpus minimization tool for afl-fuzz by Michal Zalewski"
echo
#########

View File

@ -3,7 +3,7 @@
# american fuzzy lop - Advanced Persistent Graphing
# -------------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
# Based on a design & prototype by Michael Rash.
#
# Copyright 2014, 2015 Google Inc. All rights reserved.
@ -15,7 +15,7 @@
# http://www.apache.org/licenses/LICENSE-2.0
#
echo "progress plotting utility for afl-fuzz by <lcamtuf@google.com>"
echo "progress plotting utility for afl-fuzz by Michal Zalewski"
echo
if [ ! "$#" = "2" ]; then

View File

@ -48,10 +48,10 @@ if [ "$PLATFORM" = "OpenBSD" ] ; then
echo
echo 'System security features cannot be disabled on OpenBSD.'
fi
if [ "$PLATFORM" = "FreeBSD" ] ; then
if [ "$PLATFORM" = "NetBSD" ] ; then
echo
echo It is recommended to enable unprivileged users to set cpu affinity
to be able to use afl-gotcpu meaningfully.
echo to be able to use afl-gotcpu meaningfully.
/sbin/sysctl -w security.models.extensions.user_set_cpu_affinity=1
fi
if [ "$PLATFORM" = "Darwin" ] ; then

View File

@ -3,7 +3,7 @@
# american fuzzy lop - status check tool
# --------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2015 Google Inc. All rights reserved.
#
@ -17,7 +17,7 @@
# instances of afl-fuzz.
#
echo "status check tool for afl-fuzz by <lcamtuf@google.com>"
echo "status check tool for afl-fuzz by Michal Zalewski"
echo
test "$1" = "-h" && {
echo $0

View File

@ -4,9 +4,10 @@ import os
import sys
import pefile
import shutil
import subprocess
if len(sys.argv) < 2:
print("[afl-wine-trace] usage: wine-cov binary [args...]\n")
print("[afl-wine-trace] usage: ./afl-wine-trace binary [args...]\n")
exit(1)
if os.getenv("AFL_PATH"):
@ -42,14 +43,20 @@ else:
elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]:
qemu_path += "i386"
else:
print ("[wine-cov] unsuppoted architecture\n")
print ("[afl-wine-trace] unsuppoted architecture\n")
exit(1)
qemu_path = shutil.which(qemu_path)
if os.getenv("WINECOV_WINE_PATH"):
wine_path = os.getenv("WINECOV_WINE_PATH")
wine_path = None
if os.getenv("AFL_WINE_PATH"):
wine_path = os.getenv("AFL_WINE_PATH")
else:
wine_path = "/usr/lib/wine/wine"
if not wine_path and shutil.which("wine"):
wine_path = shutil.which("wine")
if not wine_path and os.path.exists("/usr/bin/wine"):
wine_path = "/usr/bin/wine"
if not wine_path and os.path.exists("/usr/lib/wine/wine"):
wine_path = "/usr/lib/wine/wine"
if pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_AMD64"] or pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_IA64"]:
wine_path += "64"
elif pe.FILE_HEADER.Machine == pefile.MACHINE_TYPE["IMAGE_FILE_MACHINE_I386"]:
@ -58,4 +65,11 @@ else:
print ("[afl-wine-trace] unsopported architecture\n")
exit(1)
os.execve(qemu_path, [qemu_path, wine_path] + sys.argv[1:], os.environ)
argv = sys.argv[1:]
for i in range(len(argv)):
if ".cur_input" in argv[i]:
argv[i] = subprocess.run([os.path.join(os.path.dirname(wine_path), "winepath"), "--windows", argv[i]], universal_newlines=True, stdout=subprocess.PIPE).stdout
break
print("[afl-wine-trace] exec:", " ".join([qemu_path, wine_path] + argv))
os.execve(qemu_path, [qemu_path, wine_path] + argv, os.environ)

View File

@ -2,7 +2,7 @@
# AFL dictionary for GIF images
# -----------------------------
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_87a="87a"

View File

@ -5,7 +5,7 @@
# A basic collection of HTML tags likely to matter to HTML parsers. Does *not*
# include any attributes or attribute values.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
tag_a="<a>"

View File

@ -2,7 +2,7 @@
# AFL dictionary for JPEG images
# ------------------------------
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_jfif="JFIF\x00"

View File

@ -4,7 +4,7 @@
#
# Contains basic reserved keywords and syntax building blocks.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
keyword_arguments="arguments"

View File

@ -5,7 +5,7 @@
# Just the basic, standard-originating sections; does not include vendor
# extensions.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_png="\x89PNG\x0d\x0a\x1a\x0a"

244
dictionaries/regexp.dict Normal file
View File

@ -0,0 +1,244 @@
#
# AFL dictionary for JS regex
# ---------------------------
#
# Contains various regular expressions.
#
# Created by Yang Guo <yangguo@chromium.org>
#
# Contributed by Dhiraj Mishra <dhiraj@inputzero.io>
#
"?"
"abc"
"()"
"[]"
"abc|def"
"abc|def|ghi"
"^xxx$"
"ab\\b\\d\\bcd"
"\\w|\\d"
"a*?"
"abc+"
"abc+?"
"xyz?"
"xyz??"
"xyz{0,1}"
"xyz{0,1}?"
"xyz{93}"
"xyz{1,32}"
"xyz{1,32}?"
"xyz{1,}"
"xyz{1,}?"
"a\\fb\\nc\\rd\\te\\vf"
"a\\nb\\bc"
"/^\d*\./"
"(?:foo)"
"(?: foo )"
"foo|(bar|baz)|quux"
"foo(?=bar)baz"
"foo(?!bar)baz"
"foo(?<=bar)baz"
"foo(?<!bar)baz"
"()"
"(?=)"
"[]"
"[x]"
"[xyz]"
"[a-zA-Z0-9]"
"[-123]"
"[^123]"
"]"
"}"
"[a-b-c]"
"[x\\dz]"
"[\\d-z]"
"[\\d-\\d]"
"[z-\\d]"
"\\cj\\cJ\\ci\\cI\\ck\\cK"
"\\c!"
"\\c_"
"\\c~"
"[\\c!]"
"[\\c_]"
"[\\c~]"
"[\\ca]"
"[\\cz]"
"[\\cA]"
"[\\cZ]"
"[\\c1]"
"\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ "
"[\\[\\]\\{\\}\\(\\)\\%\\^\\#\\ ]"
"\\8"
"\\9"
"\\11"
"\\11a"
"\\011"
"\\118"
"\\111"
"\\1111"
"(x)(x)(x)\\1"
"(x)(x)(x)\\2"
"(x)(x)(x)\\3"
"(x)(x)(x)\\4"
"(x)(x)(x)\\1*"
"(x)(x)(x)\\3*"
"(x)(x)(x)\\4*"
"(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\10"
"(x)(x)(x)(x)(x)(x)(x)(x)(x)(x)\\11"
"(a)\\1"
"(a\\1)"
"(\\1a)"
"(\\2)(\\1)"
"(?=a){0,10}a"
"(?=a){1,10}a"
"(?=a){9,10}a"
"(?!a)?a"
"\\1(a)"
"(?!(a))\\1"
"(?!\\1(a\\1)\\1)\\1"
"\\1\\2(a(?:\\1(b\\1\\2))\\2)\\1"
"[\\0]"
"[\\11]"
"[\\11a]"
"[\\011]"
"[\\00011]"
"[\\118]"
"[\\111]"
"[\\1111]"
"\\x60"
"\\x3z"
"\\c"
"\\u0034"
"\\u003z"
"foo[z]*"
"\\u{12345}"
"\\u{12345}\\u{23456}"
"\\u{12345}{3}"
"\\u{12345}*"
"\\ud808\\udf45*"
"[\\ud808\\udf45-\\ud809\\udccc]"
"a"
"a|b"
"a\\n"
"a$"
"a\\b!"
"a\\Bb"
"a*?"
"a?"
"a??"
"a{0,1}?"
"a{1,2}?"
"a+?"
"(a)"
"(a)\\1"
"(\\1a)"
"\\1(a)"
"a\\s"
"a\\S"
"a\\D"
"a\\w"
"a\\W"
"a."
"a\\q"
"a[a]"
"a[^a]"
"a[a-z]"
"a(?:b)"
"a(?=b)"
"a(?!b)"
"\\x60"
"\\u0060"
"\\cA"
"\\q"
"\\1112"
"(a)\\1"
"(?!a)?a\\1"
"(?:(?=a))a\\1"
"a{}"
"a{,}"
"a{"
"a{z}"
"a{12z}"
"a{12,"
"a{12,3b"
"{}"
"{,}"
"{"
"{z}"
"{1z}"
"{12,"
"{12,3b"
"a"
"abc"
"a[bc]d"
"a|bc"
"ab|c"
"a||bc"
"(?:ab)"
"(?:ab|cde)"
"(?:ab)|cde"
"(ab)"
"(ab|cde)"
"(ab)\\1"
"(ab|cde)\\1"
"(?:ab)?"
"(?:ab)+"
"a?"
"a+"
"a??"
"a*?"
"a+?"
"(?:a?)?"
"(?:a+)?"
"(?:a?)+"
"(?:a*)+"
"(?:a+)+"
"(?:a?)*"
"(?:a*)*"
"(?:a+)*"
"a{0}"
"(?:a+){0,0}"
"a*b"
"a+b"
"a*b|c"
"a+b|c"
"(?:a{5,1000000}){3,1000000}"
"(?:ab){4,7}"
"a\\bc"
"a\\sc"
"a\\Sc"
"a(?=b)c"
"a(?=bbb|bb)c"
"a(?!bbb|bb)c"
"\xe2\x81\xa3"
"[\xe2\x81\xa3]"
"\xed\xb0\x80"
"\xed\xa0\x80"
"(\xed\xb0\x80)\x01"
"((\xed\xa0\x80))\x02"
"\xf0\x9f\x92\xa9"
"\x01"
"\x0f"
"[-\xf0\x9f\x92\xa9]+"
"[\xf0\x9f\x92\xa9-\xf4\x8f\xbf\xbf]"
"\[DataMember\((.+?)\)\]"
"/\d{1,2}\/\d{1,2}\/\d{4}/"
"a*b\+\|[0-9]\|\d{1,9}"
"(?<=)"
"(?<=a)"
"(?<!)"
"(?<!a)"
"(?<a>)"
"(?<a>.)"
"(?<a>.)\\k<a>"
"\\p{Script=Greek}"
"\\P{sc=Greek}"
"\\p{Script_Extensions=Greek}"
"\\P{scx=Greek}"
"\\p{General_Category=Decimal_Number}"
"\\P{gc=Decimal_Number}"
"\\p{gc=Nd}"
"\\P{Decimal_Number}"
"\\p{Nd}"
"\\P{Any}"
"\\p{Changes_When_NFKC_Casefolded}"

View File

@ -11,7 +11,7 @@
# standpoint, because they are usually not allowed in non-privileged
# contexts).
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
function_abs=" abs(1)"

View File

@ -5,7 +5,7 @@
# Just the basic, standard-originating sections; does not include vendor
# extensions.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_ii="II*\x00"

View File

@ -2,7 +2,7 @@
# AFL dictionary for WebP images
# ------------------------------
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
header_RIFF="RIFF"

View File

@ -4,7 +4,7 @@
#
# Several basic syntax elements and attributes, modeled on libxml2.
#
# Created by Michal Zalewski <lcamtuf@google.com>
# Created by Michal Zalewski
#
attr_encoding=" encoding=\"1\""

View File

@ -14,11 +14,41 @@ sending a mail to <afl-users+subscribe@googlegroups.com>.
----------------------
Version ++2.54d (dev):
Version ++2.58d (dev):
----------------------
- afl-analyze: added AFL_SKIP_BIN_CHECK support
- better random numbers for gcc_plugin and llvm_mode (thanks to devnexen)
- afl-fuzz: CPU affinity support for DragonFly
- llvm_mode: float splitting is now configured via AFL_LLVM_LAF_SPLIT_FLOATS
- libtokencap: support for *BSD/OSX added
- libcompcov floating point splitting support for qemu and unicorn
- Dockerfile by courtesy of devnexen
- ripped regex.dictionary from Google afl PR
- qemu and unicorn download scripts now try to download until the full
download succeeded. f*ckin travis fails downloading 40% of the time!
- removed unnecessary warnings
--------------------------
Version ++2.58c (release):
--------------------------
- reverted patch to not unlink and recreate the input file, it resulted in
performance loss of ~10%
- added test/test-performance.sh script
- (re)added gcc_plugin, fast inline instrumentation is not yet finished,
however it includes the whitelisting and persistance feature! by hexcoder-
- gcc_plugin tests added to testing framework
--------------------------------
Version ++2.54d-2.57c (release):
--------------------------------
- we jump to 2.57 instead of 2.55 to catch up with Google's versioning
- persistent mode for QEMU (see qemu_mode/README.md)
- custom mutator library is now a standard mutator, to exclusivly use it
- custom mutator library is now an additional mutator, to exclusivly use it
add AFL_CUSTOM_MUTATOR_ONLY (that will trigger the previous behaviour)
- new library qemu_mode/unsigaction which filters sigaction events
- afl-fuzz: new command line option -I to execute a command on a new crash
@ -41,6 +71,7 @@ Version ++2.54d (dev):
- updated documentation
- Wine mode to run Win32 binaries with the QEMU instrumentation (-W)
- CompareCoverage for ARM target in QEMU/Unicorn
- laf-intel in llvm_mode now also handles floating point comparisons
--------------------------

View File

@ -45,6 +45,8 @@ how to hit the ground running:
7) compile and use llvm_mode (afl-clang-fast/afl-clang-fast++) as it is way
faster and has a few cool features
8) There is a basic docker build with 'docker build -t aflplusplus .'
That's it. Sit back, relax, and - time permitting - try to skim through the
following files:

View File

@ -71,11 +71,11 @@ tools make fairly broad use of environmental variables:
- Setting AFL_CAL_FAST will speed up the initial calibration, if the
application is very slow
2) Settings for afl-clang-fast / afl-clang-fast++
-------------------------------------------------
2) Settings for afl-clang-fast / afl-clang-fast++ / afl-gcc-fast / afl-g++-fast
---------------------------------------------------------------------------------
The native LLVM instrumentation helper accepts a subset of the settings
discussed in section #1, with the exception of:
The native instrumentation helpers (llvm_mode and gcc_plugin) accept a subset
of the settings discussed in section #1, with the exception of:
- AFL_AS, since this toolchain does not directly invoke GNU as.
@ -100,7 +100,7 @@ Then there are a few specific features that are only available in llvm_mode:
- Setting AFL_LLVM_LAF_SPLIT_COMPARES will split all floating point and
64, 32 and 16 bit integer CMP instructions
See llvm_mode/README.laf-intel for more information.
See llvm_mode/README.laf-intel.md for more information.
WHITELIST
=========
@ -109,7 +109,7 @@ Then there are a few specific features that are only available in llvm_mode:
- Setting AFL_LLVM_WHITELIST with a filename will only instrument those
files that match the names listed in this file.
See llvm_mode/README.whitelist for more information.
See llvm_mode/README.whitelist.md for more information.
INSTRIM
=======
@ -122,7 +122,7 @@ Then there are a few specific features that are only available in llvm_mode:
afl-fuzz will only be able to see the path the loop took, but not how
many times it was called (unless it is a complex loop).
See llvm_mode/README.instrim
See llvm_mode/README.instrim.md
NOT_ZERO
========
@ -133,7 +133,18 @@ Then there are a few specific features that are only available in llvm_mode:
slowdown due a performance issue that is only fixed in llvm 9+.
This feature increases path discovery by a little bit.
See llvm_mode/README.neverzero
See llvm_mode/README.neverzero.md
Then there are a few specific features that are only available in the gcc_plugin:
WHITELIST
=========
This feature allows selective instrumentation of the source
- Setting AFL_GCC_WHITELIST with a filename will only instrument those
files that match the names listed in this file (one filename per line).
See gcc_plugin/README.whitelist.md for more information.
3) Settings for afl-fuzz
------------------------
@ -257,7 +268,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
- Setting AFL_COMPCOV_LEVEL enables the CompareCoverage tracing of all cmp
and sub in x86 and x86_64 and memory comparions functions (e.g. strcmp,
memcmp, ...) when libcompcov is preloaded using AFL_PRELOAD.
More info at qemu_mode/libcompcov/README.compcov.
More info at qemu_mode/libcompcov/README.md.
There are two levels at the moment, AFL_COMPCOV_LEVEL=1 that instruments
only comparisons with immediate values / read-only memory and
AFL_COMPCOV_LEVEL=2 that instruments all the comparions. Level 2 is more
@ -318,7 +329,7 @@ of decimal.
8) Settings for libdislocator.so
--------------------------------
The library honors three environmental variables:
The library honors these environmental variables:
- AFL_LD_LIMIT_MB caps the size of the maximum heap usage permitted by the
library, in megabytes. The default value is 1 GB. Once this is exceeded,

View File

@ -34,7 +34,7 @@ Note that ASAN is incompatible with -static, so be mindful of that.
There is also the option of generating a corpus using a non-ASAN binary, and
then feeding it to an ASAN-instrumented one to check for bugs. This is faster,
and can give you somewhat comparable results. You can also try using
libdislocator (see libdislocator/README.dislocator in the parent directory) as a
libdislocator (see libdislocator/README.dislocator.md in the parent directory) as a
lightweight and hassle-free (but less thorough) alternative.
2) Long version

View File

@ -50,12 +50,15 @@ Even if you don't have a lightweight harness for a particular target, remember
that you can always use another, related library to generate a corpus that will
be then manually fed to a more resource-hungry program later on.
Also note that reading the fuzzing input via stdin is faster than reading from
a file.
3) Use LLVM instrumentation
---------------------------
When fuzzing slow targets, you can gain 2x performance improvement by using
the LLVM-based instrumentation mode described in llvm_mode/README.llvm. Note
that this mode requires the use of clang and will not work with GCC.
When fuzzing slow targets, you can gain 20-100% performance improvement by
using the LLVM-based instrumentation mode described in llvm_mode/README.llvm.
Note that this mode requires the use of clang and will not work with GCC.
The LLVM mode also offers a "persistent", in-process fuzzing mode that can
work well for certain types of self-contained libraries, and for fast targets,
@ -72,6 +75,9 @@ If you are only intested in specific parts of the code being fuzzed, you can
whitelist the files that are actually relevant. This improves the speed and
accuracy of afl. See llvm_mode/README.whitelist
Also use the InsTrim mode on larger binaries, this improves performance and
coverage a lot.
4) Profile and optimize the binary
----------------------------------
@ -161,6 +167,11 @@ and not waste CPU time.
There are several OS-level factors that may affect fuzzing speed:
- If you have no risk of power loss then run your fuzzing on a tmpfs
partition. This increases the performance noticably.
Alternatively you can use AFL_TMPDIR to point to a tmpfs location to
just write the input file to a tmpfs.
- High system load. Use idle machines where possible. Kill any non-essential
CPU hogs (idle browser windows, media players, complex screensavers, etc).

View File

@ -2,7 +2,7 @@ afl++'s power schedules based on AFLfast
<a href="https://comp.nus.edu.sg/~mboehme/paper/CCS16.pdf"><img src="https://comp.nus.edu.sg/~mboehme/paper/CCS16.png" align="right" width="250"></a>
Power schedules implemented by Marcel Böhme \<marcel.boehme@acm.org\>.
AFLFast is an extension of AFL which was written by Michal Zalewski \<lcamtuf@google.com\>.
AFLFast is an extension of AFL which was written by Michal Zalewski.
AFLfast has helped in the success of Team Codejitsu at the finals of the DARPA Cyber Grand Challenge where their bot Galactica took **2nd place** in terms of #POVs proven (see red bar at https://www.cybergrandchallenge.com/event#results). AFLFast exposed several previously unreported CVEs that could not be exposed by AFL in 24 hours and otherwise exposed vulnerabilities significantly faster than AFL while generating orders of magnitude more unique crashes.

View File

@ -319,11 +319,13 @@ Fuzzer shell for SQLite (Richard Hipp)
Support for Python mutation modules (Christian Holler)
------------------------------------------------------
now integrated in AFL++, originally from here
https://github.com/choller/afl/blob/master/docs/mozilla/python_modules.txt
Support for selective instrumentation (Christian Holler)
--------------------------------------------------------
now integrated in AFL++, originally from here
https://github.com/choller/afl/blob/master/docs/mozilla/partial_instrumentation.txt
Kernel fuzzing (Dmitry Vyukov)

View File

@ -2,7 +2,7 @@
american fuzzy lop - sample argv fuzzing wrapper
------------------------------------------------
Written by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.

View File

@ -7,7 +7,7 @@
# David A. Wheeler <dwheeler@ida.org>
#
# Edits to bring the script in line with afl-cmin and other companion scripts
# by Michal Zalewski <lcamtuf@google.com>. All bugs are my fault.
# by Michal Zalewski. All bugs are my fault.
#
# Copyright 2015 Institute for Defense Analyses.
#

View File

@ -4,7 +4,7 @@
american fuzzy lop - <canvas> harness
-------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2013, 2014 Google Inc. All rights reserved.

View File

@ -3,7 +3,7 @@
# american fuzzy lop - clang assembly normalizer
# ----------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
# The idea for this wrapper comes from Ryan Govostes.
#
# Copyright 2013, 2014 Google Inc. All rights reserved.

View File

@ -3,7 +3,7 @@
# american fuzzy lop - crash triage utility
# -----------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2013, 2014, 2017 Google Inc. All rights reserved.
#
@ -22,7 +22,7 @@
# necessary.
#
echo "crash triage utility for afl-fuzz by <lcamtuf@google.com>"
echo "crash triage utility for afl-fuzz by Michal Zalewski"
echo
ulimit -v 100000 2>/dev/null

View File

@ -3,7 +3,7 @@
# american fuzzy lop - fuzzer synchronization tool
# ------------------------------------------------
#
# Written and maintained by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2014 Google Inc. All rights reserved.
#

View File

@ -2,7 +2,7 @@
american fuzzy lop - persistent mode example
--------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.

View File

@ -2,7 +2,7 @@
american fuzzy lop - postprocessor library example
--------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.

View File

@ -2,7 +2,7 @@
american fuzzy lop - postprocessor for PNG
------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2015 Google Inc. All rights reserved.

130
gcc_plugin/Makefile Normal file
View File

@ -0,0 +1,130 @@
#
# 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.
#
# 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
CFLAGS ?= -O3 -g -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -Wno-pointer-sign \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
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"
ifeq "$(shell echo '\#include <sys/ipc.h>@\#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 )" "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)'..."
@which $(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-gcc-fast: afl-gcc-fast.c | test_deps
$(CC) $(CFLAGS) $< -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)
../afl-showmap -m none -q -o .test-instr0 ./test-instr </dev/null
echo 1 | ../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/vanhauser-thc/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> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
@echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> ../$@
@echo >> ../$@
@echo .SH LICENSE >> ../$@
@echo Apache License Version 2.0, January 2004 >> ../$@
ln -sf afl-gcc-fast.8 ../afl-g++-fast.8
clean:
rm -f *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1
rm -f $(PROGS) ../afl-g++-fast ../afl-g*-fast.8

158
gcc_plugin/README.gcc.md Normal file
View File

@ -0,0 +1,158 @@
===========================================
GCC-based instrumentation for afl-fuzz
======================================
(See ../docs/README.md for the general instruction manual.)
(See ../llvm_mode/README.md for the LLVM-based instrumentation.)
!!! TODO items are:
!!! => inline instrumentation has to work!
!!!
## 1) Introduction
The code in this directory allows you to instrument programs for AFL using
true compiler-level instrumentation, instead of the more crude
assembly-level rewriting approach taken by afl-gcc and afl-clang. This has
several interesting properties:
- The compiler can make many optimizations that are hard to pull off when
manually inserting assembly. As a result, some slow, CPU-bound programs will
run up to around faster.
The gains are less pronounced for fast binaries, where the speed is limited
chiefly by the cost of creating new processes. In such cases, the gain will
probably stay within 10%.
- The instrumentation is CPU-independent. At least in principle, you should
be able to rely on it to fuzz programs on non-x86 architectures (after
building afl-fuzz with AFL_NOX86=1).
- Because the feature relies on the internals of GCC, it is gcc-specific
and will *not* work with LLVM (see ../llvm_mode for an alternative).
Once this implementation is shown to be sufficiently robust and portable, it
will probably replace afl-gcc. For now, it can be built separately and
co-exists with the original code.
The idea and much of the implementation comes from Laszlo Szekeres.
## 2) How to use
In order to leverage this mechanism, you need to have modern enough GCC
(>= version 4.5.0) and the plugin headers installed on your system. That
should be all you need. On Debian machines, these headers can be acquired by
installing the `gcc-<VERSION>-plugin-dev` packages.
To build the instrumentation itself, type 'make'. This will generate binaries
called afl-gcc-fast and afl-g++-fast in the parent directory. Once this
is done, you can instrument third-party code in a way similar to the standard
operating mode of AFL, e.g.:
CC=/path/to/afl/afl-gcc-fast ./configure [...options...]
make
Be sure to also include CXX set to afl-g++-fast for C++ code.
The tool honors roughly the same environmental variables as afl-gcc (see
../docs/env_variables.txt). This includes AFL_INST_RATIO, AFL_USE_ASAN,
AFL_HARDEN, and AFL_DONT_OPTIMIZE.
Note: if you want the GCC plugin to be installed on your system for all
users, you need to build it before issuing 'make install' in the parent
directory.
## 3) Gotchas, feedback, bugs
This is an early-stage mechanism, so field reports are welcome. You can send bug
reports to <hexcoder-@github.com>.
## 4) Bonus feature #1: deferred initialization
AFL tries to optimize performance by executing the targeted binary just once,
stopping it just before main(), and then cloning this "master" process to get
a steady supply of targets to fuzz.
Although this approach eliminates much of the OS-, linker- and libc-level
costs of executing the program, it does not always help with binaries that
perform other time-consuming initialization steps - say, parsing a large config
file before getting to the fuzzed data.
In such cases, it's beneficial to initialize the forkserver a bit later, once
most of the initialization work is already done, but before the binary attempts
to read the fuzzed input and parse it; in some cases, this can offer a 10x+
performance gain. You can implement delayed initialization in LLVM mode in a
fairly simple way.
First, locate a suitable location in the code where the delayed cloning can
take place. This needs to be done with *extreme* care to avoid breaking the
binary. In particular, the program will probably malfunction if you select
a location after:
- The creation of any vital threads or child processes - since the forkserver
can't clone them easily.
- The initialization of timers via setitimer() or equivalent calls.
- The creation of temporary files, network sockets, offset-sensitive file
descriptors, and similar shared-state resources - but only provided that
their state meaningfully influences the behavior of the program later on.
- Any access to the fuzzed input, including reading the metadata about its
size.
With the location selected, add this code in the appropriate spot:
```
#ifdef __AFL_HAVE_MANUAL_CONTROL
__AFL_INIT();
#endif
```
You don't need the #ifdef guards, but they will make the program still work as
usual when compiled with a tool other than afl-gcc-fast/afl-clang-fast.
Finally, recompile the program with afl-gcc-fast (afl-gcc or afl-clang will
*not* generate a deferred-initialization binary) - and you should be all set!
## 5) Bonus feature #2: persistent mode
Some libraries provide APIs that are stateless, or whose state can be reset in
between processing different input files. When such a reset is performed, a
single long-lived process can be reused to try out multiple test cases,
eliminating the need for repeated fork() calls and the associated OS overhead.
The basic structure of the program that does this would be:
```
while (__AFL_LOOP(1000)) {
/* Read input data. */
/* Call library code to be fuzzed. */
/* Reset state. */
}
/* Exit normally */
```
The numerical value specified within the loop controls the maximum number
of iterations before AFL will restart the process from scratch. This minimizes
the impact of memory leaks and similar glitches; 1000 is a good starting point.
A more detailed template is shown in ../experimental/persistent_demo/.
Similarly to the previous mode, the feature works only with afl-gcc-fast or
afl-clang-fast; #ifdef guards can be used to suppress it when using other
compilers.
Note that as with the previous mode, the feature is easy to misuse; if you
do not reset the critical state fully, you may end up with false positives or
waste a whole lot of CPU power doing nothing useful at all. Be particularly
wary of memory leaks and the state of file descriptors.
When running in this mode, the execution paths will inherently vary a bit
depending on whether the input loop is being entered for the first time or
executed again. To avoid spurious warnings, the feature implies
AFL_NO_VAR_CHECK and hides the "variable path" warnings in the UI.

View File

@ -0,0 +1,73 @@
========================================
Using afl++ with partial instrumentation
========================================
This file describes how you can selectively instrument only the source files
that are interesting to you using the gcc instrumentation provided by
afl++.
Plugin by hexcoder-.
## 1) Description and purpose
When building and testing complex programs where only a part of the program is
the fuzzing target, it often helps to only instrument the necessary parts of
the program, leaving the rest uninstrumented. This helps to focus the fuzzer
on the important parts of the program, avoiding undesired noise and
disturbance by uninteresting code being exercised.
For this purpose, I have added a "partial instrumentation" support to the gcc
plugin of AFLFuzz that allows you to specify on a source file level which files
should be compiled with or without instrumentation.
## 2) Building the gcc plugin
The new code is part of the existing afl++ gcc plugin in the gcc_plugin/
subdirectory. There is nothing specifically to do :)
## 3) How to use the partial instrumentation mode
In order to build with partial instrumentation, you need to build with
afl-gcc-fast and afl-g++-fast respectively. The only required change is
that you need to set the environment variable AFL_GCC_WHITELIST when calling
the compiler.
The environment variable must point to a file containing all the filenames
that should be instrumented. For matching, the filename that is being compiled
must end in the filename entry contained in this whitelist (to avoid breaking
the matching when absolute paths are used during compilation).
For example if your source tree looks like this:
```
project/
project/feature_a/a1.cpp
project/feature_a/a2.cpp
project/feature_b/b1.cpp
project/feature_b/b2.cpp
```
and you only want to test feature_a, then create a whitelist file containing:
```
feature_a/a1.cpp
feature_a/a2.cpp
```
However if the whitelist file contains only this, it works as well:
```
a1.cpp
a2.cpp
```
but it might lead to files being unwantedly instrumented if the same filename
exists somewhere else in the project directories.
The created whitelist file is then set to AFL_GCC_WHITELIST when you compile
your program. For each file that didn't match the whitelist, the compiler will
issue a warning at the end stating that no blocks were instrumented. If you
didn't intend to instrument that file, then you can safely ignore that warning.

348
gcc_plugin/afl-gcc-fast.c Normal file
View File

@ -0,0 +1,348 @@
/*
american fuzzy lop - GCC wrapper for GCC plugin
------------------------------------------------
Written by Austin Seipp <aseipp@pobox.com> and
Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski
GCC integration design is based on the LLVM design, which comes
from Laszlo Szekeres.
Copyright 2015 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
This program is a drop-in replacement for gcc, similar in most
respects to ../afl-gcc, but with compiler instrumentation through a
plugin. It tries to figure out compilation mode, adds a bunch of
flags, and then calls the real compiler.
*/
#define AFL_MAIN
#include "../config.h"
#include "../types.h"
#include "../include/debug.h"
#include "../include/alloc-inl.h"
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
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 */
/* Try to find the runtime libraries. If that fails, abort. */
static void find_obj(u8* argv0) {
u8* afl_path = getenv("AFL_PATH");
u8 *slash, *tmp;
if (afl_path) {
tmp = alloc_printf("%s/afl-gcc-rt.o", afl_path);
if (!access(tmp, R_OK)) {
obj_path = afl_path;
ck_free(tmp);
return;
}
ck_free(tmp);
}
slash = strrchr(argv0, '/');
if (slash) {
u8* dir;
*slash = 0;
dir = ck_strdup(argv0);
*slash = '/';
tmp = alloc_printf("%s/afl-gcc-rt.o", dir);
if (!access(tmp, R_OK)) {
obj_path = dir;
ck_free(tmp);
return;
}
ck_free(tmp);
ck_free(dir);
}
if (!access(AFL_PATH "/afl-gcc-rt.o", R_OK)) {
obj_path = AFL_PATH;
return;
}
FATAL(
"Unable to find 'afl-gcc-rt.o' or 'afl-gcc-pass.so'. Please set "
"AFL_PATH");
}
/* Copy argv to cc_params, making the necessary edits. */
static void edit_params(u32 argc, char** argv) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1;
u8* name;
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
name = strrchr(argv[0], '/');
if (!name)
name = argv[0];
else
++name;
if (!strcmp(name, "afl-g++-fast")) {
u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++";
} else {
u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc";
}
char* fplugin_arg = alloc_printf("-fplugin=%s/afl-gcc-pass.so", obj_path);
cc_params[cc_par_cnt++] = fplugin_arg;
/* Detect stray -v calls from ./configure scripts. */
if (argc == 1 && !strcmp(argv[1], "-v")) maybe_linking = 0;
while (--argc) {
u8* cur = *(++argv);
#if defined(__x86_64__)
if (!strcmp(cur, "-m32")) FATAL("-m32 is not supported");
#endif
if (!strcmp(cur, "-x")) x_set = 1;
if (!strcmp(cur, "-c") || !strcmp(cur, "-S") || !strcmp(cur, "-E") ||
!strcmp(cur, "-v"))
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;
cc_params[cc_par_cnt++] = cur;
}
if (getenv("AFL_HARDEN")) {
cc_params[cc_par_cnt++] = "-fstack-protector-all";
if (!fortify_set) cc_params[cc_par_cnt++] = "-D_FORTIFY_SOURCE=2";
}
if (!asan_set) {
if (getenv("AFL_USE_ASAN")) {
if (getenv("AFL_USE_MSAN")) FATAL("ASAN and MSAN are mutually exclusive");
if (getenv("AFL_HARDEN"))
FATAL("ASAN and AFL_HARDEN are mutually exclusive");
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=address";
} else if (getenv("AFL_USE_MSAN")) {
if (getenv("AFL_USE_ASAN")) FATAL("ASAN and MSAN are mutually exclusive");
if (getenv("AFL_HARDEN"))
FATAL("MSAN and AFL_HARDEN are mutually exclusive");
cc_params[cc_par_cnt++] = "-U_FORTIFY_SOURCE";
cc_params[cc_par_cnt++] = "-fsanitize=memory";
}
}
if (!getenv("AFL_DONT_OPTIMIZE")) {
cc_params[cc_par_cnt++] = "-g";
cc_params[cc_par_cnt++] = "-O3";
cc_params[cc_par_cnt++] = "-funroll-loops";
}
if (getenv("AFL_NO_BUILTIN")) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
}
#ifdef USEMMAP
cc_params[cc_par_cnt++] = "-lrt";
#endif
cc_params[cc_par_cnt++] = "-D__AFL_HAVE_MANUAL_CONTROL=1";
cc_params[cc_par_cnt++] = "-D__AFL_COMPILER=1";
cc_params[cc_par_cnt++] = "-DFUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION=1";
/* When the user tries to use persistent or deferred forkserver modes by
appending a single line to the program, we want to reliably inject a
signature into the binary (to be picked up by afl-fuzz) and we want
to call a function from the runtime .o file. This is unnecessarily
painful for three reasons:
1) We need to convince the compiler not to optimize out the signature.
This is done with __attribute__((used)).
2) We need to convince the linker, when called with -Wl,--gc-sections,
not to do the same. This is done by forcing an assignment to a
'volatile' pointer.
3) We need to declare __afl_persistent_loop() in the global namespace,
but doing this within a method in a class is hard - :: and extern "C"
are forbidden and __attribute__((alias(...))) doesn't work. Hence the
__asm__ aliasing trick.
*/
cc_params[cc_par_cnt++] =
"-D__AFL_LOOP(_A)="
"({ static volatile char *_B __attribute__((used)); "
" _B = (char*)\"" PERSIST_SIG
"\"; "
#ifdef __APPLE__
"int _L(unsigned int) __asm__(\"___afl_persistent_loop\"); "
#else
"int _L(unsigned int) __asm__(\"__afl_persistent_loop\"); "
#endif /* ^__APPLE__ */
"_L(_A); })";
cc_params[cc_par_cnt++] =
"-D__AFL_INIT()="
"do { static volatile char *_A __attribute__((used)); "
" _A = (char*)\"" DEFER_SIG
"\"; "
#ifdef __APPLE__
"void _I(void) __asm__(\"___afl_manual_init\"); "
#else
"void _I(void) __asm__(\"__afl_manual_init\"); "
#endif /* ^__APPLE__ */
"_I(); } while (0)";
if (maybe_linking) {
if (x_set) {
cc_params[cc_par_cnt++] = "-x";
cc_params[cc_par_cnt++] = "none";
}
cc_params[cc_par_cnt++] = alloc_printf("%s/afl-gcc-rt.o", obj_path);
}
cc_params[cc_par_cnt] = NULL;
}
/* Main entry point */
int main(int argc, char** argv) {
if (argc < 2 || strcmp(argv[1], "-h") == 0) {
printf(
cCYA
"afl-gcc-fast" VERSION cRST
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n"
"\n"
"afl-gcc-fast [options]\n"
"\n"
"This is a helper application for afl-fuzz. It serves as a drop-in "
"replacement\n"
"for gcc, letting you recompile third-party code with the required "
"runtime\n"
"instrumentation. A common use pattern would be one of the "
"following:\n\n"
" CC=%s/afl-gcc-fast ./configure\n"
" CXX=%s/afl-g++-fast ./configure\n\n"
"In contrast to the traditional afl-gcc tool, this version is "
"implemented as\n"
"a GCC plugin and tends to offer improved performance with slow "
"programs\n"
"(similarly to the LLVM plugin used by afl-clang-fast).\n\n"
"You can specify custom next-stage toolchain via AFL_CC and AFL_CXX. "
"Setting\n"
"AFL_HARDEN enables hardening optimizations in the compiled code.\n\n",
BIN_PATH, BIN_PATH);
exit(1);
} else if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(cCYA "afl-gcc-fast" VERSION cRST
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n");
}
find_obj(argv[0]);
edit_params(argc, argv);
/*if (isatty(2) && !getenv("AFL_QUIET")) {
printf("Calling \"%s\" with:\n", cc_params[0]);
for(int i=1; i<cc_par_cnt; i++) printf("%s\n", cc_params[i]);
}
*/
execvp(cc_params[0], (char**)cc_params);
FATAL("Oops, failed to execute '%s' - check your PATH", cc_params[0]);
return 0;
}

View File

@ -0,0 +1,578 @@
//
// There are some TODOs in this file:
// - fix instrumentation via external call
// - fix inline instrumentation
// - implement whitelist feature
// - dont instrument blocks that are uninteresting
// - implement neverZero
//
/*
american fuzzy lop - GCC instrumentation pass
---------------------------------------------
Written by Austin Seipp <aseipp@pobox.com> with bits from
Emese Revfy <re.emese@gmail.com>
Fixed by Heiko Eißfeldt 2019 for AFL++
GCC integration design is based on the LLVM design, which comes
from Laszlo Szekeres. Some of the boilerplate code below for
afl_pass to adapt to different GCC versions was taken from Emese
Revfy's Size Overflow plugin for GCC, licensed under the GPLv2/v3.
(NOTE: this plugin code is under GPLv3, in order to comply with the
GCC runtime library exception, which states that you may distribute
"Target Code" from the compiler under a license of your choice, as
long as the "Compilation Process" is "Eligible", and contains no
GPL-incompatible software in GCC "during the process of
transforming high level code to target code". In this case, the
plugin will be used to generate "Target Code" during the
"Compilation Process", and thus it must be GPLv3 to be "eligible".)
Copyright (C) 2015 Austin Seipp
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#define BUILD_INLINE_INST
#include "../config.h"
#include "../include/debug.h"
/* clear helper AFL types pulls in, which intervene with gcc-plugin geaders from
* GCC-8 */
#ifdef likely
#undef likely
#endif
#ifdef unlikely
#undef unlikely
#endif
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <list>
#include <string>
#include <fstream>
#include <gcc-plugin.h>
#include <plugin-version.h>
#include <diagnostic.h>
#include <tree.h>
#include <tree-ssa.h>
#include <tree-pass.h>
#include <tree-ssa-alias.h>
#include <basic-block.h>
#include <gimple-expr.h>
#include <gimple.h>
#include <gimple-iterator.h>
#include <gimple-ssa.h>
#include <version.h>
#include <toplev.h>
#include <intl.h>
#include <context.h>
#include <stringpool.h>
#include <cgraph.h>
#include <cfgloop.h>
/* -------------------------------------------------------------------------- */
/* -- AFL instrumentation pass ---------------------------------------------- */
static int be_quiet = 0;
static unsigned int inst_ratio = 100;
static bool inst_ext = true;
static std::list<std::string> myWhitelist;
static unsigned int ext_call_instrument(function *fun) {
/* Instrument all the things! */
basic_block bb;
unsigned finst_blocks = 0;
unsigned fcnt_blocks = 0;
tree fntype = build_function_type_list(void_type_node, /* return */
uint32_type_node, /* args */
NULL_TREE); /* done */
tree fndecl = build_fn_decl("__afl_trace", fntype);
TREE_STATIC(fndecl) = 1; /* Defined elsewhere */
TREE_PUBLIC(fndecl) = 1; /* Public */
DECL_EXTERNAL(fndecl) = 1; /* External linkage */
DECL_ARTIFICIAL(fndecl) = 1; /* Injected by compiler */
FOR_EACH_BB_FN(bb, fun) {
gimple_seq fcall;
gimple_seq seq = NULL;
gimple_stmt_iterator bentry;
++fcnt_blocks;
// only instrument if this basic block is the destination of a previous
// basic block that has multiple successors
// this gets rid of ~5-10% of instrumentations that are unnecessary
// result: a little more speed and less map pollution
int more_than_one = -1;
edge ep;
edge_iterator eip;
FOR_EACH_EDGE(ep, eip, bb->preds) {
int count = 0;
if (more_than_one == -1) more_than_one = 0;
basic_block Pred = ep->src;
edge es;
edge_iterator eis;
FOR_EACH_EDGE(es, eis, Pred->succs) {
basic_block Succ = es->dest;
if (Succ != NULL) count++;
}
if (count > 1) more_than_one = 1;
}
if (more_than_one != 1) continue;
/* Bail on this block if we trip the specified ratio */
if (R(100) >= inst_ratio) continue;
/* Make up cur_loc */
unsigned int rand_loc = R(MAP_SIZE);
tree cur_loc = build_int_cst(uint32_type_node, rand_loc);
/* Update bitmap via external call */
/* to quote:
* /+ Trace a basic block with some ID +/
* void __afl_trace(u32 x);
*/
fcall = gimple_build_call(
fndecl, 1,
cur_loc); /* generate the function _call_ to above built reference, with
*1* parameter -> the random const for the location */
gimple_seq_add_stmt(&seq, fcall); /* and insert into a sequence */
/* Done - grab the entry to the block and insert sequence */
bentry = gsi_after_labels(bb);
gsi_insert_seq_before(&bentry, seq, GSI_SAME_STMT);
++finst_blocks;
}
/* Say something nice. */
if (!be_quiet) {
if (!finst_blocks)
WARNF(G_("No instrumentation targets found in " cBRI "%s" cRST),
function_name(fun));
else if (finst_blocks < fcnt_blocks)
OKF(G_("Instrumented %2u /%2u locations in " cBRI "%s" cRST),
finst_blocks, fcnt_blocks, function_name(fun));
else
OKF(G_("Instrumented %2u locations in " cBRI "%s" cRST), finst_blocks,
function_name(fun));
}
return 0;
}
static unsigned int inline_instrument(function *fun) {
/* Instrument all the things! */
basic_block bb;
unsigned finst_blocks = 0;
unsigned fcnt_blocks = 0;
/* Set up global type declarations */
tree map_type = build_pointer_type(unsigned_char_type_node);
tree map_ptr_g =
build_decl(UNKNOWN_LOCATION, VAR_DECL,
get_identifier_with_length("__afl_area_ptr", 14), map_type);
TREE_USED(map_ptr_g) = 1;
TREE_STATIC(map_ptr_g) = 1; /* Defined elsewhere */
DECL_EXTERNAL(map_ptr_g) = 1; /* External linkage */
DECL_PRESERVE_P(map_ptr_g) = 1;
DECL_ARTIFICIAL(map_ptr_g) = 1; /* Injected by compiler */
rest_of_decl_compilation(map_ptr_g, 1, 0);
tree prev_loc_g = build_decl(UNKNOWN_LOCATION, VAR_DECL,
get_identifier_with_length("__afl_prev_loc", 14),
uint32_type_node);
TREE_USED(prev_loc_g) = 1;
TREE_STATIC(prev_loc_g) = 1; /* Defined elsewhere */
DECL_EXTERNAL(prev_loc_g) = 1; /* External linkage */
DECL_PRESERVE_P(prev_loc_g) = 1;
DECL_ARTIFICIAL(prev_loc_g) = 1; /* Injected by compiler */
rest_of_decl_compilation(prev_loc_g, 1, 0);
FOR_EACH_BB_FN(bb, fun) {
gimple_seq seq = NULL;
gimple_stmt_iterator bentry;
++fcnt_blocks;
// only instrument if this basic block is the destination of a previous
// basic block that has multiple successors
// this gets rid of ~5-10% of instrumentations that are unnecessary
// result: a little more speed and less map pollution
int more_than_one = -1;
edge ep;
edge_iterator eip;
FOR_EACH_EDGE(ep, eip, bb->preds) {
int count = 0;
if (more_than_one == -1) more_than_one = 0;
basic_block Pred = ep->src;
edge es;
edge_iterator eis;
FOR_EACH_EDGE(es, eis, Pred->succs) {
basic_block Succ = es->dest;
if (Succ != NULL) count++;
}
if (count > 1) more_than_one = 1;
}
if (more_than_one != 1) continue;
/* Bail on this block if we trip the specified ratio */
if (R(100) >= inst_ratio) continue;
/* Make up cur_loc */
unsigned int rand_loc = R(MAP_SIZE);
tree cur_loc = build_int_cst(uint32_type_node, rand_loc);
/* Load prev_loc, xor with cur_loc */
// gimple_assign <var_decl, prev_loc.0_1, prev_loc, NULL, NULL>
tree prev_loc = create_tmp_var_raw(uint32_type_node, "prev_loc");
gassign *g = gimple_build_assign(prev_loc, VAR_DECL, prev_loc_g);
gimple_seq_add_stmt(&seq, g); // load prev_loc
update_stmt(g);
// gimple_assign <bit_xor_expr, _2, prev_loc.0_1, 47231, NULL>
tree area_off = create_tmp_var_raw(uint32_type_node, "area_off");
g = gimple_build_assign(area_off, BIT_XOR_EXPR, prev_loc, cur_loc);
gimple_seq_add_stmt(&seq, g); // area_off = prev_loc ^ cur_loc
update_stmt(g);
/* Update bitmap */
tree one = build_int_cst(unsigned_char_type_node, 1);
// tree zero = build_int_cst(unsigned_char_type_node, 0);
// gimple_assign <addr_expr, p_6, &map[_2], NULL, NULL>
tree map_ptr = create_tmp_var(map_type, "map_ptr");
tree map_ptr2 = create_tmp_var(map_type, "map_ptr2");
g = gimple_build_assign(map_ptr, map_ptr_g);
gimple_seq_add_stmt(&seq, g); // map_ptr = __afl_area_ptr
update_stmt(g);
#if 0
tree addr = build2(ADDR_EXPR, map_type, map_ptr, area_off);
g = gimple_build_assign(map_ptr2, MODIFY_EXPR, addr);
gimple_seq_add_stmt(&seq, g); // map_ptr2 = map_ptr + area_off
update_stmt(g);
#else
g = gimple_build_assign(map_ptr2, PLUS_EXPR, map_ptr, area_off);
gimple_seq_add_stmt(&seq, g); // map_ptr2 = map_ptr + area_off
update_stmt(g);
#endif
// gimple_assign <mem_ref, _3, *p_6, NULL, NULL>
tree tmp1 = create_tmp_var_raw(unsigned_char_type_node, "tmp1");
g = gimple_build_assign(tmp1, MEM_REF, map_ptr2);
gimple_seq_add_stmt(&seq, g); // tmp1 = *map_ptr2
update_stmt(g);
// gimple_assign <plus_expr, _4, _3, 1, NULL>
tree tmp2 = create_tmp_var_raw(unsigned_char_type_node, "tmp2");
g = gimple_build_assign(tmp2, PLUS_EXPR, tmp1, one);
gimple_seq_add_stmt(&seq, g); // tmp2 = tmp1 + 1
update_stmt(g);
// TODO: neverZero: here we have to check if tmp3 == 0
// and add 1 if so
// gimple_assign <ssa_name, *p_6, _4, NULL, NULL>
// tree map_ptr3 = create_tmp_var_raw(map_type, "map_ptr3");
g = gimple_build_assign(map_ptr_g, INDIRECT_REF, tmp2);
gimple_seq_add_stmt(&seq, g); // *map_ptr3 = tmp2
update_stmt(g);
/* Set prev_loc to cur_loc >> 1 */
// gimple_assign <integer_cst, prev_loc, 23615, NULL, NULL>
tree shifted_loc = build_int_cst(TREE_TYPE(prev_loc_g), rand_loc >> 1);
tree prev_loc2 = create_tmp_var_raw(uint32_type_node, "prev_loc2");
g = gimple_build_assign(prev_loc2, shifted_loc);
gimple_seq_add_stmt(&seq, g); // __afl_prev_loc = cur_loc >> 1
update_stmt(g);
g = gimple_build_assign(prev_loc_g, prev_loc2);
gimple_seq_add_stmt(&seq, g); // __afl_prev_loc = cur_loc >> 1
update_stmt(g);
/* Done - grab the entry to the block and insert sequence */
bentry = gsi_after_labels(bb);
gsi_insert_seq_before(&bentry, seq, GSI_NEW_STMT);
++finst_blocks;
}
/* Say something nice. */
if (!be_quiet) {
if (!finst_blocks)
WARNF(G_("No instrumentation targets found in " cBRI "%s" cRST),
function_name(fun));
else if (finst_blocks < fcnt_blocks)
OKF(G_("Instrumented %2u /%2u locations in " cBRI "%s" cRST),
finst_blocks, fcnt_blocks, function_name(fun));
else
OKF(G_("Instrumented %2u locations in " cBRI "%s" cRST), finst_blocks,
function_name(fun));
}
return 0;
}
/* -------------------------------------------------------------------------- */
/* -- Boilerplate and initialization ---------------------------------------- */
static const struct pass_data afl_pass_data = {
.type = GIMPLE_PASS,
.name = "afl-inst",
.optinfo_flags = OPTGROUP_NONE,
.tv_id = TV_NONE,
.properties_required = 0,
.properties_provided = 0,
.properties_destroyed = 0,
.todo_flags_start = 0,
// NOTE(aseipp): it's very, very important to include
// at least 'TODO_update_ssa' here so that GCC will
// properly update the resulting SSA form, e.g., to
// include new PHI nodes for newly added symbols or
// names. Do not remove this. Do not taunt Happy Fun
// Ball.
.todo_flags_finish = TODO_update_ssa | TODO_verify_il | TODO_cleanup_cfg,
};
namespace {
class afl_pass : public gimple_opt_pass {
private:
bool do_ext_call;
public:
afl_pass(bool ext_call, gcc::context *g)
: gimple_opt_pass(afl_pass_data, g), do_ext_call(ext_call) {
}
unsigned int execute(function *fun) override {
if (!myWhitelist.empty()) {
bool instrumentBlock = false;
std::string instFilename;
unsigned int instLine = 0;
/* EXPR_FILENAME
This macro returns the name of the file in which the entity was declared,
as a char*. For an entity declared implicitly by the compiler (like
__builtin_ memcpy), this will be the string "<internal>".
*/
const char *fname = DECL_SOURCE_FILE(fun->decl);
if (0 != strncmp("<internal>", fname, 10) &&
0 != strncmp("<built-in>", fname, 10)) {
instFilename = fname;
instLine = DECL_SOURCE_LINE(fun->decl);
/* Continue only if we know where we actually are */
if (!instFilename.empty()) {
for (std::list<std::string>::iterator it = myWhitelist.begin();
it != myWhitelist.end(); ++it) {
/* We don't check for filename equality here because
* filenames might actually be full paths. Instead we
* check that the actual filename ends in the filename
* specified in the list. */
if (instFilename.length() >= it->length()) {
if (instFilename.compare(instFilename.length() - it->length(),
it->length(), *it) == 0) {
instrumentBlock = true;
break;
}
}
}
}
}
/* Either we couldn't figure out our location or the location is
* not whitelisted, so we skip instrumentation. */
if (!instrumentBlock) {
if (!be_quiet) {
if (!instFilename.empty())
SAYF(cYEL "[!] " cBRI "Not in whitelist, skipping %s line %u...\n",
instFilename.c_str(), instLine);
else
SAYF(cYEL "[!] " cBRI "No filename information found, skipping it");
}
return 0;
}
}
return do_ext_call ? ext_call_instrument(fun) : inline_instrument(fun);
}
}; /* class afl_pass */
} // namespace
static struct opt_pass *make_afl_pass(bool ext_call, gcc::context *ctxt) {
return new afl_pass(ext_call, ctxt);
}
/* -------------------------------------------------------------------------- */
/* -- Initialization -------------------------------------------------------- */
int plugin_is_GPL_compatible = 1;
static struct plugin_info afl_plugin_info = {
.version = "20191015",
.help = "AFL++ gcc plugin\n",
};
int plugin_init(struct plugin_name_args * plugin_info,
struct plugin_gcc_version *version) {
struct register_pass_info afl_pass_info;
struct timeval tv;
struct timezone tz;
u32 rand_seed;
/* Setup random() so we get Actually Random(TM) outputs from R() */
gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
SR(rand_seed);
/* Pass information */
afl_pass_info.pass = make_afl_pass(inst_ext, g);
afl_pass_info.reference_pass_name = "ssa";
afl_pass_info.ref_pass_instance_number = 1;
afl_pass_info.pos_op = PASS_POS_INSERT_AFTER;
if (!plugin_default_version_check(version, &gcc_version)) {
FATAL(G_("Incompatible gcc/plugin versions!"));
}
/* Show a banner */
if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(G_(cCYA "afl-gcc-pass" VERSION cRST
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n"));
} else
be_quiet = 1;
/* Decide instrumentation ratio */
char *inst_ratio_str = getenv("AFL_INST_RATIO");
if (inst_ratio_str) {
if (sscanf(inst_ratio_str, "%u", &inst_ratio) != 1 || !inst_ratio ||
inst_ratio > 100)
FATAL(G_("Bad value of AFL_INST_RATIO (must be between 1 and 100)"));
else {
if (!be_quiet)
ACTF(G_("%s instrumentation at ratio of %u%% in %s mode."),
inst_ext ? G_("Call-based") : G_("Inline"), inst_ratio,
getenv("AFL_HARDEN") ? G_("hardened") : G_("non-hardened"));
}
}
char *instWhiteListFilename = getenv("AFL_GCC_WHITELIST");
if (instWhiteListFilename) {
std::string line;
std::ifstream fileStream;
fileStream.open(instWhiteListFilename);
if (!fileStream) fatal_error(0, "Unable to open AFL_GCC_WHITELIST");
getline(fileStream, line);
while (fileStream) {
myWhitelist.push_back(line);
getline(fileStream, line);
}
} else if (!be_quiet && getenv("AFL_LLVM_WHITELIST"))
SAYF(cYEL "[-] " cRST
"AFL_LLVM_WHITELIST environment variable detected - did you mean "
"AFL_GCC_WHITELIST?\n");
/* Go go gadget */
register_callback(plugin_info->base_name, PLUGIN_INFO, NULL,
&afl_plugin_info);
register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP, NULL,
&afl_pass_info);
return 0;
}

304
gcc_plugin/afl-gcc-rt.o.c Normal file
View File

@ -0,0 +1,304 @@
/*
american fuzzy lop - GCC plugin instrumentation bootstrap
---------------------------------------------------------
Written by Austin Seipp <aseipp@pobox.com> and
Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski
GCC integration design is based on the LLVM design, which comes
from Laszlo Szekeres.
Copyright 2015 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
This code is the rewrite of afl-as.h's main_payload.
*/
#ifdef __ANDROID__
#include "android-ashmem.h"
#endif
#include "../config.h"
#include "../types.h"
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
#include <string.h>
#include <assert.h>
#include <sys/mman.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <fcntl.h>
/* Globals needed by the injected instrumentation. The __afl_area_initial region
is used for instrumentation output before __afl_map_shm() has a chance to
run. It will end up as .comm, so it shouldn't be too wasteful. */
u8 __afl_area_initial[MAP_SIZE];
u8 *__afl_area_ptr = __afl_area_initial;
#ifdef __ANDROID__
u32 __afl_prev_loc;
#else
__thread u32 __afl_prev_loc;
#endif
/* Trace a basic block with some ID */
void __afl_trace(u32 x) {
u32 l = __afl_prev_loc;
#if 0 /* enable for neverZero feature. By default disabled since too inefficient :-( */
/* @Marc: avoid conditional jumps here */
__afl_area_ptr[l ^ x] += 1 + (__afl_area_ptr[l ^ x] == (u8)~0);
#else
++__afl_area_ptr[l ^ x];
#endif
__afl_prev_loc = (x >> 1);
return;
}
/* Running in persistent mode? */
static u8 is_persistent;
/* SHM setup. */
static void __afl_map_shm(void) {
u8 *id_str = getenv(SHM_ENV_VAR);
/* If we're running under AFL, attach to the appropriate region, replacing the
early-stage __afl_area_initial region that is needed to allow some really
hacky .init code to work correctly in projects such as OpenSSL. */
if (id_str) {
#ifdef USEMMAP
const char* shm_file_path = id_str;
int shm_fd = -1;
unsigned char* shm_base = NULL;
/* create the shared memory segment as if it was a file */
shm_fd = shm_open(shm_file_path, O_RDWR, 0600);
if (shm_fd == -1) {
printf("shm_open() failed\n");
exit(1);
}
/* map the shared memory segment to the address space of the process */
shm_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED, shm_fd, 0);
if (shm_base == MAP_FAILED) {
close(shm_fd);
shm_fd = -1;
printf("mmap() failed\n");
exit(2);
}
__afl_area_ptr = shm_base;
#else
u32 shm_id = atoi(id_str);
__afl_area_ptr = shmat(shm_id, NULL, 0);
#endif
/* Whooooops. */
if (__afl_area_ptr == (void *)-1) exit(1);
/* Write something into the bitmap so that even with low AFL_INST_RATIO,
our parent doesn't give up on us. */
__afl_area_ptr[0] = 1;
}
}
/* Fork server logic. */
static void __afl_start_forkserver(void) {
static u8 tmp[4];
s32 child_pid;
u8 child_stopped = 0;
void (*old_sigchld_handler)(int) = signal(SIGCHLD, SIG_DFL);
/* Phone home and tell the parent that we're OK. If parent isn't there,
assume we're not running in forkserver mode and just execute program. */
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
while (1) {
u32 was_killed;
int status;
/* Wait for parent by reading from the pipe. Abort if read fails. */
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(1);
/* If we stopped the child in persistent mode, but there was a race
condition and afl-fuzz already issued SIGKILL, write off the old
process. */
if (child_stopped && was_killed) {
child_stopped = 0;
if (waitpid(child_pid, &status, 0) < 0) exit(1);
}
if (!child_stopped) {
/* Once woken up, create a clone of our process. */
child_pid = fork();
if (child_pid < 0) exit(1);
/* In child process: close fds, resume execution. */
if (!child_pid) {
signal(SIGCHLD, old_sigchld_handler);
close(FORKSRV_FD);
close(FORKSRV_FD + 1);
return;
}
} else {
/* Special handling for persistent mode: if the child is alive but
currently stopped, simply restart it with SIGCONT. */
kill(child_pid, SIGCONT);
child_stopped = 0;
}
/* In parent process: write PID to pipe, then wait for child. */
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(1);
if (waitpid(child_pid, &status, is_persistent ? WUNTRACED : 0) < 0) exit(1);
/* In persistent mode, the child stops itself with SIGSTOP to indicate
a successful run. In this case, we want to wake it up without forking
again. */
if (WIFSTOPPED(status)) child_stopped = 1;
/* Relay wait status to pipe, then loop back. */
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(1);
}
}
/* A simplified persistent mode handler, used as explained in README.llvm. */
int __afl_persistent_loop(unsigned int max_cnt) {
static u8 first_pass = 1;
static u32 cycle_cnt;
if (first_pass) {
/* Make sure that every iteration of __AFL_LOOP() starts with a clean slate.
On subsequent calls, the parent will take care of that, but on the first
iteration, it's our job to erase any trace of whatever happened
before the loop. */
if (is_persistent) {
memset(__afl_area_ptr, 0, MAP_SIZE);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
}
cycle_cnt = max_cnt;
first_pass = 0;
return 1;
}
if (is_persistent) {
if (--cycle_cnt) {
raise(SIGSTOP);
__afl_area_ptr[0] = 1;
__afl_prev_loc = 0;
return 1;
} else {
/* When exiting __AFL_LOOP(), make sure that the subsequent code that
follows the loop is not traced. We do that by pivoting back to the
dummy output region. */
__afl_area_ptr = __afl_area_initial;
}
}
return 0;
}
/* This one can be called from user code when deferred forkserver mode
is enabled. */
void __afl_manual_init(void) {
static u8 init_done;
if (!init_done) {
__afl_map_shm();
__afl_start_forkserver();
init_done = 1;
}
}
/* Proper initialization routine. */
__attribute__((constructor(101))) void __afl_auto_init(void) {
is_persistent = !!getenv(PERSIST_ENV_VAR);
if (getenv(DEFER_ENV_VAR)) return;
__afl_manual_init();
}

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - injectable parts
---------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - fuzzer header
------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -72,17 +72,21 @@
#include <sys/file.h>
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
defined(__NetBSD__)
defined(__NetBSD__) || defined(__DragonFly__)
#include <sys/sysctl.h>
#endif /* __APPLE__ || __FreeBSD__ || __OpenBSD__ */
/* For systems that have sched_setaffinity; right now just Linux, but one
can hope... */
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || \
defined(__DragonFly__)
#define HAVE_AFFINITY 1
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <sys/param.h>
#if defined(__FreeBSD__)
#include <sys/cpuset.h>
#endif
#include <sys/user.h>
#include <pthread.h>
#include <pthread_np.h>
@ -252,7 +256,7 @@ extern u8 *in_dir, /* Input directory with test cases */
*file_extension, /* File extension */
*orig_cmdline, /* Original command line */
*doc_path, /* Path to documentation dir */
*infoexec, /* Command to execute on a new crash */
*infoexec, /* Command to execute on a new crash */
*out_file; /* File to fuzz, if any */
extern u32 exec_tmout; /* Configurable exec timeout (ms) */
@ -315,7 +319,8 @@ extern u8 skip_deterministic, /* Skip deterministic stages? */
deferred_mode, /* Deferred forkserver mode? */
fixed_seed, /* do not reseed */
fast_cal, /* Try to calibrate faster? */
uses_asan; /* Target uses ASAN? */
uses_asan, /* Target uses ASAN? */
disable_trim; /* Never trim in fuzz_one */
extern s32 out_fd, /* Persistent fd for out_file */
#ifndef HAVE_ARC4RANDOM

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - error-checking, memory-zeroing alloc routines
--------------------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - android shared memory compatibility layer
----------------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - common routines header
---------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - vaguely configurable bits
------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -26,7 +26,7 @@
/* Version string: */
#define VERSION "++2.54d" // c = release, d = volatile github dev
#define VERSION "++2.58d" // c = release, d = volatile github dev
/******************************************************
* *

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - debug / error handling macros
----------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - forkserver header
----------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>

View File

@ -12,7 +12,7 @@
Austin's original code is public domain.
Other code written and maintained by Michal Zalewski <lcamtuf@google.com>
Other code written by Michal Zalewski
Copyright 2016 Google Inc. All rights reserved.

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - shared memory related header
---------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - type definitions and minor macros
--------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -79,9 +79,21 @@ typedef int64_t s64;
})
#ifdef AFL_LLVM_PASS
#if defined(__linux__)
#define AFL_SR(s) (srandom(s))
#define AFL_R(x) (random() % (x))
#else
#define AFL_SR(s)
#define AFL_R(x) (arc4random_uniform(x))
#endif
#else
#if defined(__linux__)
#define SR(s) (srandom(s))
#define R(x) (random() % (x))
#else
#define SR(s)
#define R(x) (arc4random_uniform(x))
#endif
#endif /* ^AFL_LLVM_PASS */
#define STRINGIFY_INTERNAL(x) #x

View File

@ -2,7 +2,7 @@
# american fuzzy lop - libdislocator
# ----------------------------------
#
# Written by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2016 Google Inc. All rights reserved.
#
@ -21,6 +21,10 @@ VERSION = $(shell grep '^\#define VERSION ' ../config.h | cut -d '"' -f2)
CFLAGS ?= -O3 -funroll-loops -I ../include/
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
ifdef USEHUGEPAGE
CFLAGS += -DUSEHUGEPAGE
endif
all: libdislocator.so
libdislocator.so: libdislocator.so.c ../config.h
@ -34,5 +38,5 @@ clean:
install: all
install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
install -m 644 README.dislocator $${DESTDIR}$(HELPER_PATH)
install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)

View File

@ -25,6 +25,8 @@ heap-related security bugs in several ways:
- It checks for calloc() overflows and can cause soft or hard failures
of alloc requests past a configurable memory limit (AFL_LD_LIMIT_MB,
AFL_LD_HARD_FAIL).
- Optionally, in platforms supporting it, huge pages can be used by passing
USEHUGEPAGE=1 to make.
Basically, it is inspired by some of the non-default options available for the
OpenBSD allocator - see malloc.conf(5) on that platform for reference. It is

View File

@ -3,7 +3,7 @@
american fuzzy lop - dislocator, an abusive allocator
-----------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2016 Google Inc. All rights reserved.
@ -14,7 +14,7 @@
http://www.apache.org/licenses/LICENSE-2.0
This is a companion library that can be used as a drop-in replacement
for the libc allocator in the fuzzed binaries. See README.dislocator for
for the libc allocator in the fuzzed binaries. See README.dislocator.md for
more info.
*/
@ -23,8 +23,13 @@
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <errno.h>
#include <sys/mman.h>
#ifdef __APPLE__
#include <mach/vm_statistics.h>
#endif
#include "config.h"
#include "types.h"
@ -36,6 +41,8 @@
#define MAP_ANONYMOUS MAP_ANON
#endif /* !MAP_ANONYMOUS */
#define SUPER_PAGE_SIZE 1<<21
/* Error / message handling: */
#define DEBUGF(_x...) \
@ -88,6 +95,10 @@ static u8 alloc_verbose, /* Additional debug messages */
hard_fail, /* abort() when max_mem exceeded? */
no_calloc_over; /* abort() on calloc() overflows? */
#if defined __OpenBSD__ || defined __APPLE__
#define __thread
#warning no thread support available
#endif
static __thread size_t total_mem; /* Currently allocated mem */
static __thread u32 call_depth; /* To avoid recursion via fprintf() */
@ -100,6 +111,8 @@ static __thread u32 call_depth; /* To avoid recursion via fprintf() */
static void* __dislocator_alloc(size_t len) {
void* ret;
size_t tlen;
int flags, fd, sp;
if (total_mem + len > max_mem || total_mem + len < total_mem) {
@ -111,13 +124,44 @@ static void* __dislocator_alloc(size_t len) {
}
tlen = (1 + PG_COUNT(len + 8)) * PAGE_SIZE;
flags = MAP_PRIVATE | MAP_ANONYMOUS;
fd = -1;
#if defined(USEHUGEPAGE)
sp = (len >= SUPER_PAGE_SIZE && !(len % SUPER_PAGE_SIZE));
#if defined(__APPLE__)
if (sp) fd = VM_FLAGS_SUPERPAGE_SIZE_2MB;
#elif defined(__linux__)
if (sp) flags |= MAP_HUGETLB;
#elif defined(__FreeBSD__)
if (sp) flags |= MAP_ALIGNED_SUPER;
#endif
#else
(void)sp;
#endif
/* We will also store buffer length and a canary below the actual buffer, so
let's add 8 bytes for that. */
ret = mmap(NULL, (1 + PG_COUNT(len + 8)) * PAGE_SIZE, PROT_READ | PROT_WRITE,
MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
ret = mmap(NULL, tlen, PROT_READ | PROT_WRITE,
flags, fd, 0);
#if defined(USEHUGEPAGE)
/* We try one more time with regular call */
if (ret == MAP_FAILED) {
#if defined(__APPLE__)
fd = -1;
#elif defined(__linux__)
flags &= -MAP_HUGETLB;
#elif defined(__FreeBSD__)
flags &= -MAP_ALIGNED_SUPER;
#endif
ret = mmap(NULL, tlen, PROT_READ | PROT_WRITE,
flags, fd, 0);
}
#endif
if (ret == (void*)-1) {
if (ret == MAP_FAILED) {
if (hard_fail) FATAL("mmap() failed on alloc (OOM?)");
@ -184,6 +228,10 @@ void* calloc(size_t elem_len, size_t elem_cnt) {
}
/* TODO: add a wrapper for posix_memalign, otherwise apps who use it,
will fail when freeing the memory.
*/
/* The wrapper for malloc(). Roughly the same, also clobbers the returned
memory (unlike calloc(), malloc() is not guaranteed to return zeroed
memory). */
@ -256,13 +304,61 @@ void* realloc(void* ptr, size_t len) {
}
/* posix_memalign we mainly check the proper alignment argument
if the requested size fits within the alignment we do
a normal request */
int posix_memalign(void** ptr, size_t align, size_t len) {
if (*ptr == NULL)
return EINVAL;
if ((align % 2) || (align % sizeof(void *)))
return EINVAL;
if (len == 0) {
*ptr = NULL;
return 0;
}
if (align >= 4 * sizeof(size_t)) len += align -1;
*ptr = malloc(len);
DEBUGF("posix_memalign(%p %zu, %zu)", ptr, align, len);
return 0;
}
/* just the non-posix fashion */
void *memalign(size_t align, size_t len) {
void* ret = NULL;
if (posix_memalign(&ret, align, len)) {
DEBUGF("memalign(%zu, %zu) failed", align, len);
}
return ret;
}
/* sort of C11 alias of memalign only more severe, alignment-wise */
void *aligned_alloc(size_t align, size_t len) {
void *ret = NULL;
if ((len % align)) return NULL;
if (posix_memalign(&ret, align, len)) {
DEBUGF("aligned_alloc(%zu, %zu) failed", align, len);
}
return ret;
}
__attribute__((constructor)) void __dislocator_init(void) {
u8* tmp = getenv("AFL_LD_LIMIT_MB");
u8* tmp = (u8 *)getenv("AFL_LD_LIMIT_MB");
if (tmp) {
max_mem = atoi(tmp) * 1024 * 1024;
max_mem = atoi((char *)tmp) * 1024 * 1024;
if (!max_mem) FATAL("Bad value for AFL_LD_LIMIT_MB");
}

View File

@ -2,7 +2,7 @@
# american fuzzy lop - libtokencap
# --------------------------------
#
# Written by Michal Zalewski <lcamtuf@google.com>
# Written by Michal Zalewski
#
# Copyright 2016 Google Inc. All rights reserved.
#
@ -24,6 +24,18 @@ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
ifeq "$(shell uname)" "Linux"
TARGETS = libtokencap.so
endif
ifeq "$(shell uname)" "Darwin"
TARGETS = libtokencap.so
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
all: $(TARGETS)
libtokencap.so: libtokencap.so.c ../config.h
@ -37,5 +49,5 @@ clean:
install: all
install -m 755 ../libtokencap.so $${DESTDIR}$(HELPER_PATH)
install -m 644 README.tokencap $${DESTDIR}$(HELPER_PATH)
install -m 644 README.tokencap.md $${DESTDIR}$(HELPER_PATH)

View File

@ -2,7 +2,7 @@
(See ../docs/README for the general instruction manual.)
This Linux-only companion library allows you to instrument `strcmp()`, `memcmp()`,
This companion library allows you to instrument `strcmp()`, `memcmp()`,
and related functions to automatically extract syntax tokens passed to any of
these libcalls. The resulting list of tokens may be then given as a starting
dictionary to afl-fuzz (the -x option) to improve coverage on subsequent
@ -55,9 +55,10 @@ If you don't get any results, the target library is probably not using strcmp()
and memcmp() to parse input; or you haven't compiled it with -fno-builtin; or
the whole thing isn't dynamically linked, and LD_PRELOAD is having no effect.
PS. The library is Linux-only because there is probably no particularly portable
and non-invasive way to distinguish between read-only and read-write memory
mappings. The `__tokencap_load_mappings()` function is the only thing that would
need to be changed for other OSes. Porting to platforms with /proc/<pid>/maps
(e.g., FreeBSD) should be trivial.
Portability hints: There is probably no particularly portable and non-invasive
way to distinguish between read-only and read-write memory mappings.
The `__tokencap_load_mappings()` function is the only thing that would
need to be changed for other OSes.
Current supported OSes are: Linux, Darwin, FreeBSD (thanks to @devnexen)

View File

@ -3,7 +3,7 @@
american fuzzy lop - extract tokens passed to strcmp / memcmp
-------------------------------------------------------------
Written and maintained by Michal Zalewski <lcamtuf@google.com>
Written by Michal Zalewski
Copyright 2016 Google Inc. All rights reserved.
@ -15,20 +15,32 @@
This Linux-only companion library allows you to instrument strcmp(),
memcmp(), and related functions to automatically extract tokens.
See README.tokencap for more info.
See README.tokencap.md for more info.
*/
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <unistd.h>
#include <fcntl.h>
#include "../types.h"
#include "../config.h"
#ifndef __linux__
#error "Sorry, this library is Linux-specific for now!"
#endif /* !__linux__ */
#if !defined __linux__ && !defined __APPLE__ && !defined __FreeBSD__ && !defined __OpenBSD__ && !defined __NetBSD__
# error "Sorry, this library is unsupported in this platform for now!"
#endif /* !__linux__ && !__APPLE__ && ! __FreeBSD__ && ! __OpenBSD__ && !__NetBSD__*/
#if defined __APPLE__
# include <mach/vm_map.h>
# include <mach/mach_init.h>
#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
# include <sys/types.h>
# include <sys/sysctl.h>
# include <sys/user.h>
# include <sys/mman.h>
#endif
/* Mapping data and such */
@ -38,7 +50,8 @@ static struct mapping { void *st, *en; } __tokencap_ro[MAX_MAPPINGS];
static u32 __tokencap_ro_cnt;
static u8 __tokencap_ro_loaded;
static FILE* __tokencap_out_file;
static int __tokencap_out_file = -1;
static pid_t __tokencap_pid = -1;
/* Identify read-only regions in memory. Only parameters that fall into these
ranges are worth dumping when passed to strcmp() and so on. Read-write
@ -46,6 +59,8 @@ static FILE* __tokencap_out_file;
static void __tokencap_load_mappings(void) {
#if defined __linux__
u8 buf[MAX_LINE];
FILE* f = fopen("/proc/self/maps", "r");
@ -70,6 +85,106 @@ static void __tokencap_load_mappings(void) {
fclose(f);
#elif defined __APPLE__
struct vm_region_submap_info_64 region;
mach_msg_type_number_t cnt = VM_REGION_SUBMAP_INFO_COUNT_64;
vm_address_t base = 0;
vm_size_t size = 0;
natural_t depth = 0;
__tokencap_ro_loaded = 1;
while (1) {
if (vm_region_recurse_64(mach_task_self(), &base, &size, &depth,
(vm_region_info_64_t)&region, &cnt) != KERN_SUCCESS) break;
if (region.is_submap) {
depth++;
} else {
/* We only care of main map addresses and the read only kinds */
if ((region.protection & VM_PROT_READ) && !(region.protection & VM_PROT_WRITE)) {
__tokencap_ro[__tokencap_ro_cnt].st = (void *)base;
__tokencap_ro[__tokencap_ro_cnt].en = (void *)(base + size);
if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
}
}
}
#elif defined __FreeBSD__ || defined __OpenBSD__ || defined __NetBSD__
#if defined __FreeBSD__
int mib[] = {CTL_KERN, KERN_PROC, KERN_PROC_VMMAP, __tokencap_pid};
#elif defined __OpenBSD__
int mib[] = {CTL_KERN, KERN_PROC_VMMAP, __tokencap_pid};
#elif defined __NetBSD__
int mib[] = {CTL_VM, VM_PROC, VM_PROC_MAP, __tokencap_pid, sizeof(struct kinfo_vmentry)};
#endif
char *buf, *low, *high;
size_t miblen = sizeof(mib)/sizeof(mib[0]);
size_t len;
if (sysctl(mib, miblen, NULL, &len, NULL, 0) == -1) return;
#if defined __FreeBSD__ || defined __NetBSD__
len = len * 4 / 3;
#elif defined __OpenBSD__
len -= len % sizeof(struct kinfo_vmentry);
#endif
buf = mmap(NULL, len, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_ANON, -1, 0);
if (buf == MAP_FAILED) return;
if (sysctl(mib, miblen, buf, &len, NULL, 0) == -1) {
munmap(buf, len);
return;
}
low = buf;
high = low + len;
__tokencap_ro_loaded = 1;
while (low < high) {
struct kinfo_vmentry *region = (struct kinfo_vmentry *)low;
#if defined __FreeBSD__ || defined __NetBSD__
#if defined __FreeBSD__
size_t size = region->kve_structsize;
if (size == 0) break;
#elif defined __NetBSD__
size_t size = sizeof (*region);
#endif
/* We go through the whole mapping of the process and track read-only addresses */
if ((region->kve_protection & KVME_PROT_READ) &&
!(region->kve_protection & KVME_PROT_WRITE)) {
#elif defined __OpenBSD__
size_t size = sizeof (*region);
/* We go through the whole mapping of the process and track read-only addresses */
if ((region->kve_protection & KVE_PROT_READ) &&
!(region->kve_protection & KVE_PROT_WRITE)) {
#endif
__tokencap_ro[__tokencap_ro_cnt].st = (void *)region->kve_start;
__tokencap_ro[__tokencap_ro_cnt].en = (void *)region->kve_end;
if (++__tokencap_ro_cnt == MAX_MAPPINGS) break;
}
low += size;
}
munmap(buf, len);
#endif
}
/* Check an address against the list of read-only mappings. */
@ -96,7 +211,7 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
u32 i;
u32 pos = 0;
if (len < MIN_AUTO_EXTRA || len > MAX_AUTO_EXTRA || !__tokencap_out_file)
if (len < MIN_AUTO_EXTRA || len > MAX_AUTO_EXTRA || __tokencap_out_file == -1)
return;
for (i = 0; i < len; i++) {
@ -122,7 +237,9 @@ static void __tokencap_dump(const u8* ptr, size_t len, u8 is_text) {
buf[pos] = 0;
fprintf(__tokencap_out_file, "\"%s\"\n", buf);
int wrt_ok = ( 1 == write(__tokencap_out_file, "\"", 1));
wrt_ok &= (pos == write(__tokencap_out_file, buf, pos));
wrt_ok &= (2 == write(__tokencap_out_file, "\"\n", 2));
}
@ -138,7 +255,7 @@ int strcmp(const char* str1, const char* str2) {
while (1) {
unsigned char c1 = *str1, c2 = *str2;
const unsigned char c1 = *str1, c2 = *str2;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
if (!c1) return 0;
@ -180,7 +297,7 @@ int strcasecmp(const char* str1, const char* str2) {
while (1) {
unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
if (c1 != c2) return (c1 > c2) ? 1 : -1;
if (!c1) return 0;
@ -200,7 +317,7 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
while (len--) {
unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
const unsigned char c1 = tolower(*str1), c2 = tolower(*str2);
if (!c1) return 0;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
@ -220,12 +337,15 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
const char *strmem1 = (const char *)mem1;
const char *strmem2 = (const char *)mem2;
while (len--) {
unsigned char c1 = *(const char*)mem1, c2 = *(const char*)mem2;
const unsigned char c1 = *strmem1, c2 = *strmem2;
if (c1 != c2) return (c1 > c2) ? 1 : -1;
mem1++;
mem2++;
strmem1++;
strmem2++;
}
@ -233,6 +353,28 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
}
#undef bcmp
int bcmp(const void* mem1, const void* mem2, size_t len) {
if (__tokencap_is_ro(mem1)) __tokencap_dump(mem1, len, 0);
if (__tokencap_is_ro(mem2)) __tokencap_dump(mem2, len, 0);
const char *strmem1 = (const char *)mem1;
const char *strmem2 = (const char *)mem2;
while (len--) {
int diff = *strmem1 ^ *strmem2;
if (diff != 0) return 1;
strmem1++;
strmem2++;
}
return 0;
}
#undef strstr
char* strstr(const char* haystack, const char* needle) {
@ -288,8 +430,14 @@ char* strcasestr(const char* haystack, const char* needle) {
__attribute__((constructor)) void __tokencap_init(void) {
u8* fn = getenv("AFL_TOKEN_FILE");
if (fn) __tokencap_out_file = fopen(fn, "a");
if (!__tokencap_out_file) __tokencap_out_file = stderr;
if (fn) __tokencap_out_file = open(fn, O_RDWR | O_CREAT | O_APPEND, 0655);
if (__tokencap_out_file == -1) __tokencap_out_file = STDERR_FILENO;
__tokencap_pid = getpid();
}
/* closing as best as we can the tokens file */
__attribute__((destructor)) void __tokencap_shutdown(void) {
if (__tokencap_out_file != STDERR_FILENO) close(__tokencap_out_file);
}

View File

@ -158,6 +158,7 @@ struct InsTrim : public ModulePass {
bool instrumentBlock = false;
DebugLoc Loc;
StringRef instFilename;
unsigned int instLine = 0;
for (auto &BB : F) {
@ -171,7 +172,7 @@ struct InsTrim : public ModulePass {
DILocation *cDILoc = dyn_cast<DILocation>(Loc.getAsMDNode());
unsigned int instLine = cDILoc->getLine();
instLine = cDILoc->getLine();
instFilename = cDILoc->getFilename();
if (instFilename.str().empty()) {
@ -217,11 +218,13 @@ struct InsTrim : public ModulePass {
* not whitelisted, so we skip instrumentation. */
if (!instrumentBlock) {
if (!instFilename.str().empty())
SAYF(cYEL "[!] " cBRI "Not in whitelist, skipping %s ...\n",
instFilename.str().c_str());
else
SAYF(cYEL "[!] " cBRI "No filename information found, skipping it");
if (!be_quiet) {
if (!instFilename.str().empty())
SAYF(cYEL "[!] " cBRI "Not in whitelist, skipping %s line %u...\n",
instFilename.str().c_str(), instLine);
else
SAYF(cYEL "[!] " cBRI "No filename information found, skipping it");
}
continue;
}

View File

@ -3,7 +3,7 @@
# -----------------------------------------
#
# Written by Laszlo Szekeres <lszekeres@google.com> and
# Michal Zalewski <lcamtuf@google.com>
# Michal Zalewski
#
# LLVM integration design comes from Laszlo Szekeres.
#
@ -52,7 +52,7 @@ endif
CFLAGS ?= -O3 -funroll-loops
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I ../include/ \
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
-DVERSION=\"$(VERSION)\"
-DLLVM_BINDIR=\"$(LLVM_BINDIR)\" -DVERSION=\"$(VERSION)\"
ifdef AFL_TRACE_PC
CFLAGS += -DUSE_TRACE_PC=1
endif
@ -220,7 +220,7 @@ vpath % ..
@../$* -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 \"hexc0der\" Eissfeldt <heiko.eissfeldt@hexco.de> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
@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> and Andrea Fioraldi <andreafioraldi@gmail.com>" >> ../$@
@echo The homepage of afl++ is: https://github.com/vanhauser-thc/AFLplusplus >> ../$@
@echo >> ../$@
@echo .SH LICENSE >> ../$@

View File

@ -35,4 +35,5 @@ bit_width may be 64, 32 or 16.
A new experimental feature is splitting floating point comparisons into a
series of sign, exponent and mantissa comparisons followed by splitting each
of them into 8 bit comparisons when necessary.
It is activated with the `AFL_LLVM_LAF_SPLIT_COMPARES` setting.
It is activated with the `AFL_LLVM_LAF_SPLIT_FLOATS` setting, available only
when `AFL_LLVM_LAF_SPLIT_COMPARES` is set.

View File

@ -64,7 +64,7 @@ a2.cpp
but it might lead to files being unwantedly instrumented if the same filename
exists somewhere else in the project directories.
The created whitelist file is then set to AFL_INST_WHITELIST when you compile
The created whitelist file is then set to AFL_LLVM_WHITELIST when you compile
your program. For each file that didn't match the whitelist, the compiler will
issue a warning at the end stating that no blocks were instrumented. If you
didn't intend to instrument that file, then you can safely ignore that warning.

View File

@ -3,7 +3,7 @@
------------------------------------------------
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres.
@ -32,11 +32,13 @@
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <limits.h>
#include <assert.h>
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 */
static u8 llvm_fullpath[PATH_MAX];
/* Try to find the runtime libraries. If that fails, abort. */
@ -104,6 +106,7 @@ static void find_obj(u8* argv0) {
static void edit_params(u32 argc, char** argv) {
u8 fortify_set = 0, asan_set = 0, x_set = 0, maybe_linking = 1, bit_mode = 0;
u8 has_llvm_config = 0;
u8* name;
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
@ -112,23 +115,29 @@ static void edit_params(u32 argc, char** argv) {
if (!name)
name = argv[0];
else
name++;
++name;
has_llvm_config = (strlen(LLVM_BINDIR) > 0);
if (!strcmp(name, "afl-clang-fast++")) {
u8* alt_cxx = getenv("AFL_CXX");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"clang++";
if (has_llvm_config) snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang++", LLVM_BINDIR);
else sprintf(llvm_fullpath, "clang++");
cc_params[0] = alt_cxx ? alt_cxx : (u8*)llvm_fullpath;
} else {
u8* alt_cc = getenv("AFL_CC");
cc_params[0] = alt_cc ? alt_cc : (u8*)"clang";
if (has_llvm_config) snprintf(llvm_fullpath, sizeof(llvm_fullpath), "%s/clang", LLVM_BINDIR);
else sprintf(llvm_fullpath, "clang");
cc_params[0] = alt_cc ? alt_cc : (u8*)llvm_fullpath;
}
/* There are three ways to compile with afl-clang-fast. In the traditional
mode, we use afl-llvm-pass.so, then there is libLLVMInsTrim.so which is
much faster but has less coverage. Finally tere is the experimental
much faster but has less coverage. Finally there is the experimental
'trace-pc-guard' mode, we use native LLVM instrumentation callbacks
instead. For trace-pc-guard see:
http://clang.llvm.org/docs/SanitizerCoverage.html#tracing-pcs-with-guards
@ -273,6 +282,9 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
}

View File

@ -3,7 +3,7 @@
---------------------------------------------------
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres. C bits copied-and-pasted
from afl-as.c are Michal's fault.
@ -34,6 +34,7 @@
#include <list>
#include <string>
#include <fstream>
#include <sys/time.h>
#include "llvm/IR/DebugInfo.h"
#include "llvm/IR/BasicBlock.h"
@ -95,8 +96,16 @@ bool AFLCoverage::runOnModule(Module &M) {
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
struct timeval tv;
struct timezone tz;
u32 rand_seed;
unsigned int cur_loc = 0;
/* Setup random() so we get Actually Random(TM) outputs from AFL_R() */
gettimeofday(&tv, &tz);
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
AFL_SR(rand_seed);
/* Show a banner */
char be_quiet = 0;
@ -181,6 +190,8 @@ bool AFLCoverage::runOnModule(Module &M) {
}
(void)instLine;
/* Continue only if we know where we actually are */
if (!instFilename.str().empty()) {

View File

@ -3,7 +3,7 @@
---------------------------------------------------
Written by Laszlo Szekeres <lszekeres@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
LLVM integration design comes from Laszlo Szekeres.

View File

@ -234,6 +234,10 @@ bool CompareTransform::transformCmps(Module &M, const bool processStrcmp,
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
sizedLen = ilen->getZExtValue();
} else {
sizedLen = 0;
}
if (HasStr1) {

View File

@ -50,6 +50,8 @@ class SplitComparesTransform : public ModulePass {
}
private:
int enableFPSplit;
size_t splitIntCompares(Module &M, unsigned bitw);
size_t splitFPCompares(Module &M);
bool simplifyCompares(Module &M);
@ -101,10 +103,11 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
}
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
if (enableFPSplit && (
selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULE) {
selectcmpInst->getPredicate() == CmpInst::FCMP_ULE)) {
auto op0 = selectcmpInst->getOperand(0);
auto op1 = selectcmpInst->getOperand(1);
@ -115,6 +118,8 @@ bool SplitComparesTransform::simplifyCompares(Module &M) {
/* this is probably not needed but we do it anyway */
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
fcomps.push_back(selectcmpInst);
}
@ -476,6 +481,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
if (TyOp0 != TyOp1) { continue; }
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
fcomps.push_back(selectcmpInst);
}
@ -1040,6 +1047,8 @@ bool SplitComparesTransform::runOnModule(Module &M) {
if (!bitw_env) bitw_env = getenv("AFL_LLVM_LAF_SPLIT_COMPARES_BITW");
if (bitw_env) { bitw = atoi(bitw_env); }
enableFPSplit = getenv("AFL_LLVM_LAF_SPLIT_FLOATS") != NULL;
simplifyCompares(M);
simplifyIntSignedness(M);
@ -1048,8 +1057,9 @@ bool SplitComparesTransform::runOnModule(Module &M) {
errs() << "Split-compare-pass by laf.intel@gmail.com, extended by "
"heiko@hexco.de\n";
errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M)
<< " FP comparisons splitted\n";
if (enableFPSplit)
errs() << "Split-floatingpoint-compare-pass: " << splitFPCompares(M)
<< " FP comparisons splitted\n";
switch (bitw) {

View File

@ -100,8 +100,12 @@ afl-fuzz).
AFL_COMPCOV_LEVEL=1 is to instrument comparisons with only immediate
values / read-only memory. AFL_COMPCOV_LEVEL=2 instruments all
comparison instructions and memory comparison functions when libcompcov
is preloaded. Comparison instructions are currently instrumented only
on the x86 and x86_64 targets.
is preloaded.
AFL_COMPCOV_LEVEL=3 has the same effects of AFL_COMPCOV_LEVEL=2 but enables also
the instrumentation of the floating-point comparisons on x86 and x86_64 (experimental).
Integer comparison instructions are currently instrumented only
on the x86, x86_64 and ARM targets.
Highly recommended.

View File

@ -4,7 +4,7 @@
# --------------------------------------
#
# Originally written by Andrew Griffiths <agriffiths@google.com> and
# Michal Zalewski <lcamtuf@google.com>
# Michal Zalewski
#
# TCG instrumentation and block chaining support by Andrea Biondo
# <andrea.biondo965@gmail.com>
@ -100,7 +100,10 @@ if [ ! "$CKSUM" = "$QEMU_SHA384" ]; then
echo "[*] Downloading QEMU ${VERSION} from the web..."
rm -f "$ARCHIVE"
wget -O "$ARCHIVE" -- "$QEMU_URL" || exit 1
OK=
while [ -z "$OK" ]; do
wget -c -O "$ARCHIVE" -- "$QEMU_URL" && OK=1
done
CKSUM=`sha384sum -- "$ARCHIVE" 2>/dev/null | cut -d' ' -f1`
@ -150,6 +153,9 @@ patch -p1 <../patches/translate-all.diff || exit 1
patch -p1 <../patches/tcg.diff || exit 1
patch -p1 <../patches/i386-translate.diff || exit 1
patch -p1 <../patches/arm-translate.diff || exit 1
patch -p1 <../patches/i386-ops_sse.diff || exit 1
patch -p1 <../patches/i386-fpu_helper.diff || exit 1
patch -p1 <../patches/softfloat.diff || exit 1
echo "[+] Patching done."

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
@ -31,6 +31,9 @@
*/
#ifndef __AFL_QEMU_COMMON
#define __AFL_QEMU_COMMON
#include "../../config.h"
#ifndef CPU_NB_REGS
@ -81,3 +84,30 @@ void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
void tcg_gen_afl_maybe_log_call(target_ulong cur_loc);
void afl_float_compcov_log_32(target_ulong cur_loc, float32 arg1, float32 arg2,
void *status);
void afl_float_compcov_log_64(target_ulong cur_loc, float64 arg1, float64 arg2,
void *status);
void afl_float_compcov_log_80(target_ulong cur_loc, floatx80 arg1,
floatx80 arg2);
/* Check if an address is valid in the current mapping */
static inline int is_valid_addr(target_ulong addr) {
int l, flags;
target_ulong page;
void * p;
page = addr & TARGET_PAGE_MASK;
l = (page + TARGET_PAGE_SIZE) - addr;
flags = page_get_flags(page);
if (!(flags & PAGE_VALID) || !(flags & PAGE_READ)) return 0;
return 1;
}
#endif

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
@ -451,24 +451,6 @@ static void afl_request_tsl(target_ulong pc, target_ulong cb, uint32_t flags,
}
/* Check if an address is valid in the current mapping */
static inline int is_valid_addr(target_ulong addr) {
int l, flags;
target_ulong page;
void * p;
page = addr & TARGET_PAGE_MASK;
l = (page + TARGET_PAGE_SIZE) - addr;
flags = page_get_flags(page);
if (!(flags & PAGE_VALID) || !(flags & PAGE_READ)) return 0;
return 1;
}
/* This is the other side of the same channel. Since timeouts are handled by
afl-fuzz simply killing the child, we can just wait until the pipe breaks. */

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>

View File

@ -0,0 +1,217 @@
/*
american fuzzy lop++ - high-performance binary-only instrumentation
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>
QEMU 3.1.1 port, TCG thread-safety, CompareCoverage and NeverZero
counters by Andrea Fioraldi <andreafioraldi@gmail.com>
Copyright 2015, 2016, 2017 Google Inc. All rights reserved.
Copyright 2019 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
This code is a shim patched into the separately-distributed source
code of QEMU 3.1.0. It leverages the built-in QEMU tracing functionality
to implement AFL-style instrumentation and to take care of the remaining
parts of the AFL fork server logic.
The resulting QEMU binary is essentially a standalone instrumentation
tool; for an example of how to leverage it for other purposes, you can
have a look at afl-showmap.c.
*/
#include "tcg.h"
#include "afl-qemu-common.h"
union afl_float32 {
float32 f;
struct {
u64 sign : 1;
u64 exp : 7;
u64 frac : 24;
};
};
union afl_float64 {
float64 f;
struct {
u64 sign : 1;
u64 exp : 11;
u64 frac : 52;
};
};
// TODO 16 and 128 bits floats
// TODO figure out why float*_unpack_canonical does not work
void afl_float_compcov_log_32(target_ulong cur_loc, float32 arg1, float32 arg2,
void* status) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= afl_inst_rms) return;
//float_status* s = (float_status*)status;
//FloatParts a = float32_unpack_canonical(arg1, s);
//FloatParts b = float32_unpack_canonical(arg2, s);
union afl_float32 a = { .f = arg1 };
union afl_float32 b = { .f = arg2 };
// if (is_nan(a.cls) || is_nan(b.cls)) return;
register uintptr_t idx = cur_loc;
if (a.sign != b.sign) return;
INC_AFL_AREA(idx);
if (a.exp != b.exp) return;
INC_AFL_AREA(idx + 1);
if ((a.frac & 0xff0000) == (b.frac & 0xff0000)) {
INC_AFL_AREA(idx + 2);
if ((a.frac & 0xff00) == (b.frac & 0xff00)) { INC_AFL_AREA(idx + 3); }
}
}
void afl_float_compcov_log_64(target_ulong cur_loc, float64 arg1, float64 arg2,
void* status) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= afl_inst_rms) return;
//float_status* s = (float_status*)status;
//FloatParts a = float64_unpack_canonical(arg1, s);
//FloatParts b = float64_unpack_canonical(arg2, s);
union afl_float64 a = { .f = arg1 };
union afl_float64 b = { .f = arg2 };
// if (is_nan(a.cls) || is_nan(b.cls)) return;
register uintptr_t idx = cur_loc;
if (a.sign == b.sign) INC_AFL_AREA(idx);
if ((a.exp & 0xff00) == (b.exp & 0xff00)) {
INC_AFL_AREA(idx + 1);
if ((a.exp & 0xff) == (b.exp & 0xff)) INC_AFL_AREA(idx + 2);
}
if ((a.frac & 0xff000000000000) == (b.frac & 0xff000000000000)) {
INC_AFL_AREA(idx + 3);
if ((a.frac & 0xff0000000000) == (b.frac & 0xff0000000000)) {
INC_AFL_AREA(idx + 4);
if ((a.frac & 0xff00000000) == (b.frac & 0xff00000000)) {
INC_AFL_AREA(idx + 5);
if ((a.frac & 0xff000000) == (b.frac & 0xff000000)) {
INC_AFL_AREA(idx + 6);
if ((a.frac & 0xff0000) == (b.frac & 0xff0000)) {
INC_AFL_AREA(idx + 7);
if ((a.frac & 0xff00) == (b.frac & 0xff00)) INC_AFL_AREA(idx + 8);
}
}
}
}
}
}
void afl_float_compcov_log_80(target_ulong cur_loc, floatx80 arg1,
floatx80 arg2) {
cur_loc = (cur_loc >> 4) ^ (cur_loc << 8);
cur_loc &= MAP_SIZE - 7;
if (cur_loc >= afl_inst_rms) return;
if (floatx80_invalid_encoding(arg1) || floatx80_invalid_encoding(arg2))
return;
flag a_sign = extractFloatx80Sign(arg1);
flag b_sign = extractFloatx80Sign(arg2);
/*if (((extractFloatx80Exp(arg1) == 0x7fff) &&
(extractFloatx80Frac(arg1) << 1)) ||
((extractFloatx80Exp(arg2) == 0x7fff) &&
(extractFloatx80Frac(arg2) << 1)))
return;*/
register uintptr_t idx = cur_loc;
if (a_sign == b_sign) INC_AFL_AREA(idx);
if ((arg1.high & 0x7f00) == (arg2.high & 0x7f00)) {
INC_AFL_AREA(idx + 1);
if ((arg1.high & 0xff) == (arg2.high & 0xff)) INC_AFL_AREA(idx + 2);
}
if ((arg1.low & 0xff00000000000000) == (arg2.low & 0xff00000000000000)) {
INC_AFL_AREA(idx + 3);
if ((arg1.low & 0xff000000000000) == (arg2.low & 0xff000000000000)) {
INC_AFL_AREA(idx + 4);
if ((arg1.low & 0xff0000000000) == (arg2.low & 0xff0000000000)) {
INC_AFL_AREA(idx + 5);
if ((arg1.low & 0xff00000000) == (arg2.low & 0xff00000000)) {
INC_AFL_AREA(idx + 6);
if ((arg1.low & 0xff000000) == (arg2.low & 0xff000000)) {
INC_AFL_AREA(idx + 7);
if ((arg1.low & 0xff0000) == (arg2.low & 0xff0000)) {
INC_AFL_AREA(idx + 8);
if ((arg1.low & 0xff00) == (arg2.low & 0xff00)) {
INC_AFL_AREA(idx + 9);
//if ((arg1.low & 0xff) == (arg2.low & 0xff))
// INC_AFL_AREA(idx + 10);
}
}
}
}
}
}
}
}

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>

View File

@ -3,7 +3,7 @@
-------------------------------------------------------------------
Originally written by Andrew Griffiths <agriffiths@google.com> and
Michal Zalewski <lcamtuf@google.com>
Michal Zalewski
TCG instrumentation and block chaining support by Andrea Biondo
<andrea.biondo965@gmail.com>

View File

@ -0,0 +1,54 @@
diff --git a/target/i386/fpu_helper.c b/target/i386/fpu_helper.c
index ea5a0c48..89901315 100644
--- a/target/i386/fpu_helper.c
+++ b/target/i386/fpu_helper.c
@@ -384,10 +384,16 @@ void helper_fxchg_ST0_STN(CPUX86State *env, int st_index)
static const int fcom_ccval[4] = {0x0100, 0x4000, 0x0000, 0x4500};
+#include "../patches/afl-qemu-common.h"
+
void helper_fcom_ST0_FT0(CPUX86State *env)
{
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
}
@@ -396,6 +402,10 @@ void helper_fucom_ST0_FT0(CPUX86State *env)
{
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
env->fpus = (env->fpus & ~0x4500) | fcom_ccval[ret + 1];
}
@@ -407,6 +417,10 @@ void helper_fcomi_ST0_FT0(CPUX86State *env)
int eflags;
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare(ST0, FT0, &env->fp_status);
eflags = cpu_cc_compute_all(env, CC_OP);
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];
@@ -418,6 +432,10 @@ void helper_fucomi_ST0_FT0(CPUX86State *env)
int eflags;
int ret;
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_80(env->eip, ST0, FT0);
+
ret = floatx80_compare_quiet(ST0, FT0, &env->fp_status);
eflags = cpu_cc_compute_all(env, CC_OP);
eflags = (eflags & ~(CC_Z | CC_P | CC_C)) | fcomi_ccval[ret + 1];

View File

@ -0,0 +1,61 @@
diff --git a/target/i386/ops_sse.h b/target/i386/ops_sse.h
index ed059897..a5296caa 100644
--- a/target/i386/ops_sse.h
+++ b/target/i386/ops_sse.h
@@ -997,6 +997,8 @@ SSE_HELPER_CMP(cmpord, FPU_CMPORD)
static const int comis_eflags[4] = {CC_C, CC_Z, 0, CC_Z | CC_P | CC_C};
+#include "../patches/afl-qemu-common.h"
+
void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
{
int ret;
@@ -1004,6 +1006,11 @@ void helper_ucomiss(CPUX86State *env, Reg *d, Reg *s)
s0 = d->ZMM_S(0);
s1 = s->ZMM_S(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_32(env->eip, s0, s1, &env->sse_status);
+
ret = float32_compare_quiet(s0, s1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}
@@ -1015,6 +1022,11 @@ void helper_comiss(CPUX86State *env, Reg *d, Reg *s)
s0 = d->ZMM_S(0);
s1 = s->ZMM_S(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_32(env->eip, s0, s1, &env->sse_status);
+
ret = float32_compare(s0, s1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}
@@ -1026,6 +1038,11 @@ void helper_ucomisd(CPUX86State *env, Reg *d, Reg *s)
d0 = d->ZMM_D(0);
d1 = s->ZMM_D(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_64(env->eip, d0, d1, &env->sse_status);
+
ret = float64_compare_quiet(d0, d1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}
@@ -1037,6 +1054,11 @@ void helper_comisd(CPUX86State *env, Reg *d, Reg *s)
d0 = d->ZMM_D(0);
d1 = s->ZMM_D(0);
+
+ if (afl_compcov_level > 2 && env->eip < afl_end_code &&
+ env->eip >= afl_start_code)
+ afl_float_compcov_log_64(env->eip, d0, d1, &env->sse_status);
+
ret = float64_compare(d0, d1, &env->sse_status);
CC_SRC = comis_eflags[ret + 1];
}

View File

@ -0,0 +1,10 @@
diff --git a/fpu/softfloat.c b/fpu/softfloat.c
index e1eef954..2f8d0d62 100644
--- a/fpu/softfloat.c
+++ b/fpu/softfloat.c
@@ -7205,3 +7205,5 @@ float128 float128_scalbn(float128 a, int n, float_status *status)
, status);
}
+
+#include "../../patches/afl-qemu-floats.h"

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - file format analyzer
-------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -841,7 +841,7 @@ int main(int argc, char** argv) {
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
SAYF(cCYA "afl-analyze" VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n");
while ((opt = getopt(argc, argv, "+i:f:m:t:eQUWh")) > 0)
@ -987,7 +987,7 @@ int main(int argc, char** argv) {
if (child_timed_out)
FATAL("Target binary times out (adjusting -t may help).");
if (!anything_set()) FATAL("No instrumentation detected.");
if (getenv("AFL_SKIP_BIN_CHECK") == NULL && !anything_set()) FATAL("No instrumentation detected.");
analyze(use_argv);

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - wrapper for GNU as
-----------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -499,9 +499,9 @@ int main(int argc, char** argv) {
clang_mode = !!getenv(CLANG_ENV_VAR);
if (isatty(2) && !getenv("AFL_QUIET")) {
if (!getenv("AFL_QUIET")) {
SAYF(cCYA "afl-as" VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-as" VERSION cRST " by Michal Zalewski\n");
} else

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - common routines
--------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - forkserver code
--------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - bitmap related routines
----------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -684,9 +684,11 @@ u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) {
++unique_crashes;
if (infoexec) // if the user wants to be informed on new crashes - do that
if (infoexec) // if the user wants to be informed on new crashes - do
// that
if (system(infoexec) == -1)
hnb += 0; // we dont care if system errors, but we dont want a compiler warning either
hnb += 0; // we dont care if system errors, but we dont want a
// compiler warning either
last_crash_time = get_cur_time();
last_crash_execs = total_execs;

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - extras relates routines
----------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - globals declarations
-------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -74,8 +74,8 @@ u8 *in_dir, /* Input directory with test cases */
*file_extension, /* File extension */
*orig_cmdline; /* Original command line */
u8 *doc_path, /* Path to documentation dir */
*infoexec, /* Command to execute on a new crash */
*out_file; /* File to fuzz, if any */
*infoexec, /* Command to execute on a new crash */
*out_file; /* File to fuzz, if any */
u32 exec_tmout = EXEC_TIMEOUT; /* Configurable exec timeout (ms) */
u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */
@ -125,7 +125,8 @@ u8 skip_deterministic, /* Skip deterministic stages? */
deferred_mode, /* Deferred forkserver mode? */
fixed_seed, /* do not reseed */
fast_cal, /* Try to calibrate faster? */
uses_asan; /* Target uses ASAN? */
uses_asan, /* Target uses ASAN? */
disable_trim; /* Never trim in fuzz_one */
s32 out_fd, /* Persistent fd for out_file */
#ifndef HAVE_ARC4RANDOM

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - initialization related routines
------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -32,7 +32,7 @@
void bind_to_free_cpu(void) {
#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
cpu_set_t c;
#elif defined(__NetBSD__)
cpuset_t* c;
@ -117,7 +117,7 @@ void bind_to_free_cpu(void) {
}
closedir(d);
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__DragonFly__)
struct kinfo_proc* procs;
size_t nprocs;
size_t proccount;
@ -138,7 +138,13 @@ void bind_to_free_cpu(void) {
for (i = 0; i < proccount; i++) {
if (procs[i].ki_oncpu < sizeof(cpu_used)) cpu_used[procs[i].ki_oncpu] = 1;
#if defined(__FreeBSD__)
if (procs[i].ki_oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 10)
cpu_used[procs[i].ki_oncpu] = 1;
#elif defined(__DragonFly__)
if (procs[i].kp_lwp.kl_cpuid < sizeof(cpu_used) && procs[i].kp_lwp.kl_pctcpu > 10)
cpu_used[procs[i].kp_lwp.kl_cpuid] = 1;
#endif
}
@ -166,7 +172,8 @@ void bind_to_free_cpu(void) {
for (i = 0; i < proccount; i++) {
if (procs[i].p_cpuid < sizeof(cpu_used)) cpu_used[procs[i].p_cpuid] = 1;
if (procs[i].p_cpuid < sizeof(cpu_used) && procs[i].p_pctcpu > 0)
cpu_used[procs[i].p_cpuid] = 1;
}
@ -198,7 +205,7 @@ void bind_to_free_cpu(void) {
cpu_aff = i;
#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
CPU_ZERO(&c);
CPU_SET(i, &c);
#elif defined(__NetBSD__)
@ -210,7 +217,7 @@ void bind_to_free_cpu(void) {
#if defined(__linux__)
if (sched_setaffinity(0, sizeof(c), &c)) PFATAL("sched_setaffinity failed");
#elif defined(__FreeBSD__)
#elif defined(__FreeBSD__) || defined(__DragonFly__)
if (pthread_setaffinity_np(pthread_self(), sizeof(c), &c))
PFATAL("pthread_setaffinity failed");
#elif defined(__NetBSD__)
@ -727,7 +734,7 @@ void pivot_inputs(void) {
use_name += 6;
else
use_name = rsl;
nfn = alloc_printf("%s/queue/id:%06u,orig:%s", out_dir, id, use_name);
nfn = alloc_printf("%s/queue/id:%06u,time:0,orig:%s", out_dir, id, use_name);
#else
@ -869,7 +876,7 @@ double get_runnable_processes(void) {
static double res;
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || \
defined(__NetBSD__)
defined(__NetBSD__) || defined(__DragonFly__)
/* I don't see any portable sysctl or so that would quickly give us the
number of runnable processes; the 1-minute load average can be a
@ -1603,7 +1610,7 @@ void check_cpu_governor(void) {
void get_core_count(void) {
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
size_t s = sizeof(cpu_core_count);
@ -1649,7 +1656,7 @@ void get_core_count(void) {
cur_runnable = (u32)get_runnable_processes();
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__)
#if defined(__APPLE__) || defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__DragonFly__)
/* Add ourselves, since the 1-minute average doesn't include that yet. */

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - misc stuffs from Mordor
----------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - fuzze_one routines in different flavours
---------------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -449,7 +449,7 @@ u8 fuzz_one_original(char** argv) {
* TRIMMING *
************/
if (!dumb_mode && !queue_cur->trim_done && !custom_mutator) {
if (!dumb_mode && !queue_cur->trim_done && !custom_mutator && !disable_trim) {
u8 res = trim_case(argv, queue_cur, in_buf);

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - python extension routines
------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - queue relates routines
---------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - target execution related routines
--------------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -288,10 +288,9 @@ void write_to_testcase(void* mem, u32 len) {
if (out_file) {
// unlink(out_file); /* Ignore errors.
// */
unlink(out_file); /* Ignore errors. */
fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", out_file);
@ -331,10 +330,9 @@ void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) {
if (out_file) {
// unlink(out_file); /* Ignore errors.
// */
unlink(out_file); /* Ignore errors. */
fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
if (fd < 0) PFATAL("Unable to create '%s'", out_file);

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - stats related routines
---------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -334,9 +334,9 @@ void show_stats(void) {
/* Lord, forgive me this. */
SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
SAYF(SET_G1 bSTG bLT bH bSTOP cCYA
" process timing " bSTG bH30 bH5 bH bHB bH bSTOP cCYA
" overall results " bSTG bH2 bH2 bRT "\n");
" overall results " bSTG bH2 bH2 bRT "\n");
if (dumb_mode) {
@ -413,9 +413,9 @@ void show_stats(void) {
" uniq hangs : " cRST "%-6s" bSTG bV "\n",
DTD(cur_ms, last_hang_time), tmp);
SAYF(bVR bH bSTOP cCYA
SAYF(bVR bH bSTOP cCYA
" cycle progress " bSTG bH10 bH5 bH2 bH2 bHB bH bSTOP cCYA
" map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
" map coverage " bSTG bH bHT bH20 bH2 bVL "\n");
/* This gets funny because we want to print several variable-length variables
together, but then cram them into a fixed-width field - so we need to
@ -443,9 +443,9 @@ void show_stats(void) {
SAYF(bSTOP " count coverage : " cRST "%-21s" bSTG bV "\n", tmp);
SAYF(bVR bH bSTOP cCYA
SAYF(bVR bH bSTOP cCYA
" stage progress " bSTG bH10 bH5 bH2 bH2 bX bH bSTOP cCYA
" findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
" findings in depth " bSTG bH10 bH5 bH2 bH2 bVL "\n");
sprintf(tmp, "%s (%0.02f%%)", DI(queued_favored),
((double)queued_favored) * 100 / queued_paths);
@ -514,7 +514,7 @@ void show_stats(void) {
/* Aaaalmost there... hold on! */
SAYF(bVR bH cCYA bSTOP
SAYF(bVR bH cCYA bSTOP
" fuzzing strategy yields " bSTG bH10 bHT bH10 bH5 bHB bH bSTOP cCYA
" path geometry " bSTG bH5 bH2 bVL "\n");
@ -634,13 +634,13 @@ void show_stats(void) {
sprintf(tmp, "%s/%s", DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB
"\n" bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1,
"\n" bLB bH30 bH20 bH2 bH bRB bSTOP cRST RESET_G1,
tmp);
} else {
SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB
"\n" bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1,
"\n" bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1,
tmp);
}

View File

@ -2,7 +2,7 @@
american fuzzy lop - fuzzer code
--------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -126,12 +126,15 @@ static void usage(u8* argv0) {
" -V seconds - fuzz for a maximum total time of seconds then "
"terminate\n"
" -E execs - fuzz for a maximum number of total executions then "
"terminate\n\n"
"terminate\n"
" Note: -V/-E are not precise, they are checked after a queue entry "
"is done\n which can be many minutes/execs later\n\n"
"Other stuff:\n"
" -T text - text banner to show on the screen\n"
" -M / -S id - distributed mode (see parallel_fuzzing.txt)\n"
" -I command - execute this command/script when a new crash is found\n"
" -I command - execute this command/script when a new crash is "
"found\n"
" -B bitmap.txt - mutate a specific test case, use the out/fuzz_bitmap "
"file\n"
" -C - crash exploration mode (the peruvian rabbit thing)\n"
@ -180,7 +183,7 @@ int main(int argc, char** argv) {
SAYF(cCYA
"afl-fuzz" VERSION cRST
" based on afl by <lcamtuf@google.com> and a big online community\n");
" based on afl by Michal Zalewski and a big online community\n");
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
@ -192,10 +195,7 @@ int main(int argc, char** argv) {
switch (opt) {
case 'I':
infoexec = optarg;
break;
case 'I': infoexec = optarg; break;
case 's': {
@ -645,10 +645,13 @@ int main(int argc, char** argv) {
}
if (getenv("AFL_DISABLE_TRIM"))
disable_trim = 1;
if (getenv("AFL_NO_UI") && getenv("AFL_FORCE_UI"))
FATAL("AFL_NO_UI and AFL_FORCE_UI are mutually exclusive");
if (strchr(argv[optind], '/') == NULL)
if (strchr(argv[optind], '/') == NULL && !unicorn_mode)
WARNF(cLRD
"Target binary called without a prefixed path, make sure you are "
"fuzzing the right binary: " cRST "%s",

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - wrapper for GCC and clang
------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -131,7 +131,7 @@ static void edit_params(u32 argc, char** argv) {
if (!name)
name = argv[0];
else
name++;
++name;
if (!strncmp(name, "afl-clang", 9)) {
@ -320,6 +320,7 @@ static void edit_params(u32 argc, char** argv) {
cc_params[cc_par_cnt++] = "-fno-builtin-strcasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strncasecmp";
cc_params[cc_par_cnt++] = "-fno-builtin-memcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-bcmp";
cc_params[cc_par_cnt++] = "-fno-builtin-strstr";
cc_params[cc_par_cnt++] = "-fno-builtin-strcasestr";
@ -335,7 +336,7 @@ int main(int argc, char** argv) {
if (argc == 2 && strcmp(argv[1], "-h") == 0) {
printf("afl-cc" VERSION " by <lcamtuf@google.com>\n\n");
printf("afl-cc" VERSION " by Michal Zalewski\n\n");
printf("%s \n\n", argv[0]);
printf("afl-gcc has no command line options\n");
printf(
@ -347,7 +348,7 @@ int main(int argc, char** argv) {
if (isatty(2) && !getenv("AFL_QUIET")) {
SAYF(cCYA "afl-cc" VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-cc" VERSION cRST " by Michal Zalewski\n");
SAYF(cYEL "[!] " cBRI "NOTE: " cRST
"afl-gcc is deprecated, llvm_mode is much faster and has more "
"options\n");

View File

@ -2,7 +2,7 @@
american fuzzy lop - free CPU gizmo
-----------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Now maintained by by Marc Heuse <mh@mh-sec.de>,
Heiko Eißfeldt <heiko.eissfeldt@hexco.de> and
@ -52,18 +52,24 @@
#include "types.h"
#include "debug.h"
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__) || defined(__DragonFly__)
#define HAVE_AFFINITY 1
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__DragonFly__)
#include <pthread.h>
#include <pthread_np.h>
#if defined(__FreeBSD__)
#include <sys/cpuset.h>
#endif
#define cpu_set_t cpuset_t
#elif defined(__NetBSD__)
#include <pthread.h>
#include <sched.h>
#elif defined(__APPLE__)
#include <pthread.h>
#include <mach/thread_act.h>
#include <mach/thread_policy.h>
#endif
#endif /* __linux__ || __FreeBSD__ || __NetBSD__ */
#endif /* __linux__ || __FreeBSD__ || __NetBSD__ || __APPLE__ */
/* Get unix time in microseconds. */
@ -138,7 +144,7 @@ int main(int argc, char** argv) {
if (argc > 1) {
printf("afl-gotcpu" VERSION " by <lcamtuf@google.com>\n");
printf("afl-gotcpu" VERSION " by Michal Zalewski\n");
printf("\n%s \n\n", argv[0]);
printf("afl-gotcpu does not have command line options\n");
printf("afl-gotcpu prints out which CPUs are available\n");
@ -150,7 +156,7 @@ int main(int argc, char** argv) {
u32 cpu_cnt = sysconf(_SC_NPROCESSORS_ONLN), idle_cpus = 0, maybe_cpus = 0, i;
SAYF(cCYA "afl-gotcpu" VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-gotcpu" VERSION cRST " by Michal Zalewski\n");
ACTF("Measuring per-core preemption rate (this will take %0.02f sec)...",
((double)CTEST_CORE_TRG_MS) / 1000);
@ -164,7 +170,7 @@ int main(int argc, char** argv) {
if (!fr) {
u32 util_perc;
#if defined(__linux__) || defined(__FreeBSD__)
#if defined(__linux__) || defined(__FreeBSD__) || defined(__DragonFly__)
cpu_set_t c;
CPU_ZERO(&c);
@ -176,9 +182,15 @@ int main(int argc, char** argv) {
if (c == NULL) PFATAL("cpuset_create failed");
cpuset_set(i, c);
#elif defined(__APPLE__)
thread_affinity_policy_data_t c = { i };
thread_port_t native_thread = pthread_mach_thread_np(pthread_self());
if (thread_policy_set(native_thread, THREAD_AFFINITY_POLICY,
(thread_policy_t)&c, 1) != KERN_SUCCESS)
PFATAL("thread_policy_set failed");
#endif
#if defined(__FreeBSD__)
#if defined(__FreeBSD__) || defined(__DragonFly__)
if (pthread_setaffinity_np(pthread_self(), sizeof(c), &c))
PFATAL("pthread_setaffinity_np failed");
#endif
@ -265,7 +277,7 @@ int main(int argc, char** argv) {
u32 util_perc;
SAYF(cCYA "afl-gotcpu" VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-gotcpu" VERSION cRST " by Michal Zalewski\n");
/* Run a busy loop for CTEST_TARGET_MS. */

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - shared memory related code
-------------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>
@ -153,8 +153,6 @@ void setup_shm(unsigned char dumb_mode) {
shm_str = alloc_printf("%d", shm_id);
setenv(SHM_ENV_VAR, shm_str, 1);
/* If somebody is asking us to fuzz instrumented binaries in dumb mode,
we don't want them to detect instrumentation, since we won't be sending
fork server commands. This should be replaced with better auto-detection

View File

@ -2,7 +2,7 @@
american fuzzy lop++ - map display utility
------------------------------------------
Originally written by Michal Zalewski <lcamtuf@google.com>
Originally written by Michal Zalewski
Forkserver design by Jann Horn <jannhorn@googlemail.com>
@ -395,7 +395,7 @@ static void setup_signal_handlers(void) {
static void show_banner(void) {
SAYF(cCYA "afl-showmap" VERSION cRST " by <lcamtuf@google.com>\n");
SAYF(cCYA "afl-showmap" VERSION cRST " by Michal Zalewski\n");
}

Some files were not shown because too many files have changed in this diff Show More