-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
0 parents
commit 4f3278e
Showing
208 changed files
with
30,386 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
# catch objects and such | ||
*.swp | ||
*.o | ||
*.so | ||
|
||
# don't track the actual binaries | ||
afl-showmax | ||
afl-analyze | ||
afl-as | ||
afl-clang | ||
afl-clang++ | ||
afl-clang-fast | ||
afl-clang-fast++ | ||
afl-fuzz | ||
afl-g++ | ||
afl-gcc | ||
afl-gotcpu | ||
afl-showmap | ||
afl-tmin | ||
as |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,156 @@ | ||
# | ||
# american fuzzy lop - makefile | ||
# ----------------------------- | ||
# | ||
# Written and maintained by Michal Zalewski <[email protected]> | ||
# | ||
# Copyright 2013, 2014, 2015, 2016, 2017 Google Inc. All rights reserved. | ||
# | ||
# Licensed under the Apache License, Version 2.0 (the "License"); | ||
# you may not use this file except in compliance with the License. | ||
# You may obtain a copy of the License at: | ||
# | ||
# http://www.apache.org/licenses/LICENSE-2.0 | ||
# | ||
|
||
PROGNAME = afl | ||
VERSION = $(shell grep '^\#define VERSION ' config.h | cut -d '"' -f2) | ||
|
||
PREFIX ?= /usr/local | ||
BIN_PATH = $(PREFIX)/bin | ||
HELPER_PATH = $(PREFIX)/lib/afl | ||
DOC_PATH = $(PREFIX)/share/doc/afl | ||
MISC_PATH = $(PREFIX)/share/afl | ||
|
||
# PROGS intentionally omit afl-as, which gets installed elsewhere. | ||
|
||
PROGS = afl-gcc afl-fuzz afl-showmap afl-showmax afl-tmin afl-gotcpu afl-analyze | ||
SH_PROGS = afl-plot afl-cmin afl-whatsup | ||
|
||
CFLAGS ?= -O3 -funroll-loops | ||
CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign \ | ||
-DAFL_PATH=\"$(HELPER_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\" \ | ||
-DBIN_PATH=\"$(BIN_PATH)\" -Iinclude | ||
|
||
ifneq "$(filter Linux GNU%,$(shell uname))" "" | ||
LDFLAGS += -ldl | ||
endif | ||
|
||
ifeq "$(findstring clang, $(shell $(CC) --version 2>/dev/null))" "" | ||
TEST_CC = afl-gcc | ||
else | ||
TEST_CC = afl-clang | ||
endif | ||
|
||
COMM_HDR = alloc-inl.h config.h debug.h types.h | ||
|
||
all: test_x86 $(PROGS) afl-as test_build all_done | ||
|
||
ifndef AFL_NO_X86 | ||
|
||
test_x86: | ||
@echo "[*] Checking for the ability to compile x86 code..." | ||
@echo 'main() { __asm__("xorb %al, %al"); }' | $(CC) -w -x c - -o .test || ( 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 .test | ||
@echo "[+] Everything seems to be working, ready to compile." | ||
|
||
else | ||
|
||
test_x86: | ||
@echo "[!] Note: skipping x86 compilation checks (AFL_NO_X86 set)." | ||
|
||
endif | ||
|
||
afl-gcc: afl-gcc.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $$i; done | ||
|
||
afl-as: afl-as.c afl-as.h $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
ln -sf afl-as as | ||
|
||
afl-fuzz: afl-fuzz.c reducers.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $^ -o $@ $(LDFLAGS) | ||
|
||
afl-showmap: afl-showmap.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
|
||
afl-showmax: afl-showmax.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
|
||
afl-tmin: afl-tmin.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
|
||
afl-analyze: afl-analyze.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
|
||
afl-gotcpu: afl-gotcpu.c $(COMM_HDR) | test_x86 | ||
$(CC) $(CFLAGS) $@.c -o $@ $(LDFLAGS) | ||
|
||
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_QUIET=1 AFL_INST_RATIO=100 AFL_PATH=. ./$(TEST_CC) $(CFLAGS) test-instr.c -o test-instr $(LDFLAGS) | ||
echo 0 | ./afl-showmap -m none -q -o .test-instr0 ./test-instr | ||
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 ping <[email protected]> to troubleshoot the issue."; echo; exit 1; fi | ||
@echo "[+] All right, the instrumentation seems to be working!" | ||
|
||
else | ||
|
||
test_build: afl-gcc afl-as afl-showmap | ||
@echo "[!] Note: skipping build tests (you may need to use LLVM or QEMU mode)." | ||
|
||
endif | ||
|
||
all_done: test_build | ||
@if [ ! "`which clang 2>/dev/null`" = "" ]; then echo "[+] LLVM users: see llvm_mode/README.llvm for a faster alternative to afl-gcc."; fi | ||
@echo "[+] All done! Be sure to review README - it's pretty short and useful." | ||
@if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi | ||
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.txt for advice.\033[0m\n" 2>/dev/null | ||
|
||
.NOTPARALLEL: clean | ||
|
||
clean: | ||
rm -f $(PROGS) afl-as as afl-g++ afl-clang afl-clang++ *.o *~ a.out core core.[1-9][0-9]* *.stackdump test .test test-instr .test-instr0 .test-instr1 qemu_mode/qemu-2.10.0.tar.bz2 afl-qemu-trace | ||
rm -rf out_dir qemu_mode/qemu-2.10.0 | ||
$(MAKE) -C llvm_mode clean | ||
$(MAKE) -C libdislocator clean | ||
$(MAKE) -C libtokencap clean | ||
|
||
install: all | ||
mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH) | ||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh | ||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH) | ||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as | ||
if [ -f afl-qemu-trace ]; then install -m 755 afl-qemu-trace $${DESTDIR}$(BIN_PATH); fi | ||
ifndef AFL_TRACE_PC | ||
if [ -f afl-clang-fast -a -f afl-llvm-pass.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 afl-llvm-pass.so afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi | ||
else | ||
if [ -f afl-clang-fast -a -f afl-llvm-rt.o ]; then set -e; install -m 755 afl-clang-fast $${DESTDIR}$(BIN_PATH); ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang-fast++; install -m 755 afl-llvm-rt.o $${DESTDIR}$(HELPER_PATH); fi | ||
endif | ||
if [ -f afl-llvm-rt-32.o ]; then set -e; install -m 755 afl-llvm-rt-32.o $${DESTDIR}$(HELPER_PATH); fi | ||
if [ -f afl-llvm-rt-64.o ]; then set -e; install -m 755 afl-llvm-rt-64.o $${DESTDIR}$(HELPER_PATH); fi | ||
set -e; for i in afl-g++ afl-clang afl-clang++; do ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/$$i; done | ||
install -m 755 afl-as $${DESTDIR}$(HELPER_PATH) | ||
ln -sf afl-as $${DESTDIR}$(HELPER_PATH)/as | ||
install -m 644 docs/README docs/ChangeLog docs/*.txt $${DESTDIR}$(DOC_PATH) | ||
cp -r testcases/ $${DESTDIR}$(MISC_PATH) | ||
cp -r dictionaries/ $${DESTDIR}$(MISC_PATH) | ||
|
||
publish: clean | ||
test "`basename $$PWD`" = "afl" || exit 1 | ||
test -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz; if [ "$$?" = "0" ]; then echo; echo "Change program version in config.h, mmkay?"; echo; exit 1; fi | ||
cd ..; rm -rf $(PROGNAME)-$(VERSION); cp -pr $(PROGNAME) $(PROGNAME)-$(VERSION); \ | ||
tar -cvz -f ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz $(PROGNAME)-$(VERSION) | ||
chmod 644 ~/www/afl/releases/$(PROGNAME)-$(VERSION).tgz | ||
( cd ~/www/afl/releases/; ln -s -f $(PROGNAME)-$(VERSION).tgz $(PROGNAME)-latest.tgz ) | ||
cat docs/README >~/www/afl/README.txt | ||
cat docs/status_screen.txt >~/www/afl/status_screen.txt | ||
cat docs/historical_notes.txt >~/www/afl/historical_notes.txt | ||
cat docs/technical_details.txt >~/www/afl/technical_details.txt | ||
cat docs/ChangeLog >~/www/afl/ChangeLog.txt | ||
cat docs/QuickStartGuide.txt >~/www/afl/QuickStartGuide.txt | ||
echo -n "$(VERSION)" >~/www/afl/version.txt |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
===================== | ||
AFL quick start guide | ||
===================== | ||
|
||
You should read docs/README. It's pretty short. If you really can't, here's | ||
how to hit the ground running: | ||
|
||
1) Compile AFL with 'make'. If build fails, see docs/INSTALL for tips. | ||
|
||
2) Find or write a reasonably fast and simple program that takes data from | ||
a file or stdin, processes it in a test-worthy way, then exits cleanly. | ||
If testing a network service, modify it to run in the foreground and read | ||
from stdin. When fuzzing a format that uses checksums, comment out the | ||
checksum verification code, too. | ||
|
||
The program must crash properly when a fault is encountered. Watch out for | ||
custom SIGSEGV or SIGABRT handlers and background processes. For tips on | ||
detecting non-crashing flaws, see section 11 in docs/README. | ||
|
||
3) Compile the program / library to be fuzzed using afl-gcc. A common way to | ||
do this would be: | ||
|
||
CC=/path/to/afl-gcc CXX=/path/to/afl-g++ ./configure --disable-shared | ||
make clean all | ||
|
||
If program build fails, ping <[email protected]>. | ||
|
||
4) Get a small but valid input file that makes sense to the program. When | ||
fuzzing verbose syntax (SQL, HTTP, etc), create a dictionary as described in | ||
dictionaries/README.dictionaries, too. | ||
|
||
5) If the program reads from stdin, run 'afl-fuzz' like so: | ||
|
||
./afl-fuzz -i testcase_dir -o findings_dir -- \ | ||
/path/to/tested/program [...program's cmdline...] | ||
|
||
If the program takes input from a file, you can put @@ in the program's | ||
command line; AFL will put an auto-generated file name in there for you. | ||
|
||
6) Investigate anything shown in red in the fuzzer UI by promptly consulting | ||
docs/status_screen.txt. | ||
|
||
That's it. Sit back, relax, and - time permitting - try to skim through the | ||
following files: | ||
|
||
- docs/README - A general introduction to AFL, | ||
- docs/perf_tips.txt - Simple tips on how to fuzz more quickly, | ||
- docs/status_screen.txt - An explanation of the tidbits shown in the UI, | ||
- docs/parallel_fuzzing.txt - Advice on running AFL on multiple cores. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,106 @@ | ||
# FuzzFactory: Domain-Specific Fuzzing with Waypoints | ||
|
||
FuzzFactory is an extension of [AFL](https://github.com/google/AFL) that generalizes coverage-guided fuzzing to domain-specific testing goals. FuzzFactory allows users to guide the fuzzer's search process without having to modify anything in AFL's search algorithm. | ||
|
||
A paper on FuzzFactory has been [conditionally accepted to OOPSLA 2019](https://2019.splashcon.org/details/splash-2019-oopsla/57/FuzzFactory-Domain-Specific-Fuzzing-with-Waypoints). A replication package for the experimental evaluation described in the paper is available at: [![DOI](https://zenodo.org/badge/DOI/10.5281/zenodo.3364086.svg)](https://doi.org/10.5281/zenodo.3364086). | ||
|
||
## What are *Waypoints*? | ||
|
||
FuzzFactory's key abstraction is that of waypoints. Waypoints are intermediate inputs that are saved during the fuzzing loop. These inputs need not increase code coverage, but they are saved because they make some sort of domain-specific progress. For example, PerfFuzz saves inputs that increase loop execution counts, a magic-byte fuzzer may save inputs that have partially correct magic bytes, or a directed fuzzer may save inputs that are more likely to exercise a program point of interest. | ||
|
||
## How does FuzzFactory work? | ||
|
||
FuzzFactory exposes an API (see `include/waypoints.h`) between the fuzzing algorithm and the test program. The test program can provide custom domain-specific feedback from test execution as key-value pairs, and specify how such feedback should be aggregated across multiple inputs. The aggregated feedback is used to decide if a given input should be considered a waypoint. The calls to the API can be injected either by modifying a test program by hand, or by inserting appropriate instrumentation in the test program. | ||
|
||
|
||
## Documentation and Examples | ||
|
||
|
||
|
||
This section assumes some familiarity with AFL. | ||
|
||
To build FuzzFactory's custom `afl-fuzz`, run `make` in the root project directory. | ||
|
||
|
||
### LLVM-based instrumentation | ||
|
||
To build FuzzFactory's custom `afl-clang-fast`, run `make` in the `llvm` directory. | ||
|
||
FuzzFactory provides an extension mechanism to quickly implement LLVM instrumentation passes that call into the FuzzFactory API; see `llvm_mode/fuzzfactory.hpp` and the following six domain implementations in `llvm_mode`: | ||
|
||
- Domain `slow`: | ||
- `waypoints-slow-pass.cc`: Implements domain `slow` described in Table 3 of the paper. | ||
- `waypoints-slow-rt.c`: Allocates DSF map for `slow`. | ||
- Domain `perf`: | ||
- `waypoints-perf-pass.cc`: Implements domain `perf` described in Table 4 of the paper. | ||
- `waypoints-perf-rt.c`: Allocates DSF map for `perf`. | ||
- Domain `mem`: | ||
- `waypoints-mem-pass.cc`: Implements domain `mem` described in Table 5 of the paper. | ||
- `waypoints-mem-rt.c`: Allocates DSF map for `mem`. | ||
- Domain `valid`: | ||
- `waypoints-valid-pass.cc`: Implements domain `valid` described in Table 6 of the paper. | ||
- `waypoints-valid-rt.c`: Allocates DSF map for `slow` and defines the logic for when the argument to `ASSUME()` is `false`. | ||
- Domain `cmp`: | ||
- `waypoints-cmp-pass.cc`: Implements domain `cmp` described in Table 7. | ||
- `waypoints-cmp-rt.c`: Allocates DSF map for `cmp`, as well as defines all the `wrapcmp` functions that perform the common-bit-counting and update the DSF map accordingly. | ||
- Domain `diff`: | ||
- `waypoints-diff-pass.cc`: Implements domain `diff` described in Table 7. | ||
- `waypoints-diff-rt.c`: Allocates globals used by domain `diff`. | ||
|
||
|
||
### Fuzzing with FuzzFactory's LLVM-based domains | ||
|
||
|
||
The directory `demo` contains a single-file test program (`demo.c`) to illustrate the use of FuzzFactory. Please switch to this directory for the remainder of this section. | ||
``` | ||
cd demo | ||
``` | ||
|
||
Background: This is how you would compile `demo.c` with regular AFL: | ||
|
||
``` | ||
../afl/afl-clang-fast demo.c -o demo | ||
``` | ||
|
||
This is how you would compile `demo.c` with FuzzFactory using the `mem` domain: | ||
``` | ||
WAYPOINTS=mem ../fuzzfactory/afl-clang-fast demo.c -o demo | ||
``` | ||
|
||
This is how you would compile `demo.c` with FuzzFactory using the `cmp` domain: | ||
``` | ||
WAYPOINTS=cmp ../fuzzfactory/afl-clang-fast demo.c -o demo | ||
``` | ||
|
||
This is how you would compile `demo.c` with FuzzFactory using the composition of the `cmp` and `mem` domain: | ||
``` | ||
WAYPOINTS=cmp,mem ../fuzzfactory/afl-clang-fast demo.c -o demo | ||
``` | ||
|
||
Now, let's fuzz the demo program using the seed file in the `seeds` subdirectory. The same command applies regardless of what domain was used to instrument the test program: | ||
|
||
``` | ||
../fuzzfactory/afl-fuzz -p -i seeds -o results ./demo | ||
``` | ||
|
||
If you fuzzed a program that has been instrumented with `cmp`+`mem` domains, you will see the following in the AFL output before fuzzing starts: | ||
``` | ||
[+] 2 domain-specific front-end configs received | ||
DSF 0: Start=0x000000, End=0x010000, Size=65536, Cumulator=1 | ||
DSF 1: Start=0x010000, End=0x010400, Size=1024, Cumulator=1 | ||
``` | ||
|
||
This is an indication that the test program has registered two domain-specific feedback maps with FuzzFactory. | ||
|
||
The rest of the fuzzing session is similar to running [AFL as usual](http://lcamtuf.coredump.cx/afl). Press CTRL+C to stop fuzzing. During fuzzing, the following log file is created with verbose output about domain-specific feedback: `results/fuzzfactory.log`. | ||
|
||
### New Domains via LLVM Instrumentation | ||
|
||
To implement your own domain-specific instrumentation, let's call it domain `foo`, create files `waypoints-foo-pass.cc` and `waypoints-diff-rt.c`, and run `make` in the `llvm_mode` directory. Use the implementations listed above as templates. Once compiled, you can then instrument your test programs using the environment variable `WAYPOINTS=foo` when compiling with the `afl-clang-fast` built from this repo. | ||
|
||
### New Domains via Manual API Invocation | ||
|
||
*Documentation coming soon* | ||
|
||
|
||
|
Oops, something went wrong.