mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 14:43:22 +00:00
Compare commits
326 Commits
Author | SHA1 | Date | |
---|---|---|---|
842cd9dec3 | |||
4b4effe343 | |||
c3bb0a3421 | |||
878a80de7f | |||
f7e1397d98 | |||
e90fa623d9 | |||
9829c5eb95 | |||
3f23f40a56 | |||
cd2cae720b | |||
65b4141cd3 | |||
58c7a0f8fe | |||
9a2f2f1ee9 | |||
c983e2c5b1 | |||
2eb88d31a4 | |||
0fb68cbbfa | |||
064cd3315c | |||
cc3bf762ec | |||
29bbe0aebe | |||
33ce5829c3 | |||
a05bd3e477 | |||
9ed4bfbca8 | |||
67b6298895 | |||
3122790295 | |||
5aa089d1b2 | |||
b0a2160c3a | |||
4f343e791a | |||
7db87ec74b | |||
8679f3d757 | |||
65bafe7192 | |||
49b3c9e0a0 | |||
e244f85c0b | |||
cc151388a1 | |||
5f0a252fae | |||
d8fb4a8e19 | |||
5e53d337db | |||
b91000fc9e | |||
ce3cd71dc0 | |||
c283487d94 | |||
fe74c68c42 | |||
a521bfdfd8 | |||
d7b6b810d1 | |||
7028c9b59d | |||
891f067051 | |||
939721e2cb | |||
6226e38451 | |||
64435284ce | |||
cf70fe0c9e | |||
7218afdd8e | |||
0627336466 | |||
2b9ad9acb6 | |||
17d364c8a0 | |||
6ccfc2df56 | |||
26d27d9121 | |||
7832daf969 | |||
860bce8a80 | |||
eb61134bed | |||
c5d4e8d0c7 | |||
201287f60f | |||
d0d0405676 | |||
42f992303e | |||
e79a4faf10 | |||
2863d6205b | |||
624f0da6c0 | |||
c3423d81d0 | |||
fc1a52b1c6 | |||
05825a888e | |||
bc6c5d6be2 | |||
6bf9855342 | |||
0db7b39e62 | |||
49c9b68e4e | |||
d40b670388 | |||
01f0af64da | |||
31f7404272 | |||
cb4a20ba6d | |||
8c841a068a | |||
f3fb1d3411 | |||
22452da2a7 | |||
cd165b18f0 | |||
7515e1edb5 | |||
a49384f23c | |||
9b39900c30 | |||
8817c66e98 | |||
2038f86016 | |||
b8b0ba004b | |||
41165c0e68 | |||
30e4e7340e | |||
aa95728c35 | |||
b262c5478c | |||
ef43a4f82e | |||
8bc0b646f0 | |||
65bee44d6d | |||
7d585059e7 | |||
d08504a667 | |||
08f2a35b9b | |||
8e64b13bc0 | |||
983abf359c | |||
233112c9b6 | |||
37dbccb674 | |||
c8524ad363 | |||
30435ee1f5 | |||
ac322253ca | |||
05bb4252bf | |||
e5326e797e | |||
ca203d413f | |||
a1e5a2e607 | |||
674fbc39f8 | |||
948a83ef9f | |||
2b0cfe1ab5 | |||
6b6aa23645 | |||
4231c49839 | |||
ef2dc98773 | |||
984faca4e8 | |||
70ad97d739 | |||
1ab2a0cce9 | |||
c19b6fb260 | |||
dbdd9dbbde | |||
a3416b1571 | |||
e12b71773d | |||
f576c87e3a | |||
c5e231a711 | |||
57334a44c1 | |||
523859f37c | |||
0894f8cf7a | |||
d8234e58a4 | |||
f6a6df7279 | |||
b0d590fef4 | |||
f8bc9b54da | |||
60c8121c1d | |||
124ec8d297 | |||
e9ed056913 | |||
99b0860835 | |||
25b435060c | |||
ba1b04be1e | |||
2ccf5323c2 | |||
891aadaaca | |||
2e07261f57 | |||
5178a0cbba | |||
8d5fded4d8 | |||
8e85b9cbf3 | |||
d4da9b805a | |||
ae4f770dad | |||
cbe38ff905 | |||
9c2e27a026 | |||
644bdd220e | |||
93a9e2daf3 | |||
b2896c79c6 | |||
8c0d247126 | |||
39dc0cca37 | |||
7f0fe3b7d2 | |||
2f209414ef | |||
ccb156c704 | |||
8a2f2e1792 | |||
79490e75be | |||
e8b576fb9f | |||
d96b27b603 | |||
c8d94e88a7 | |||
f3a23e51fa | |||
7e022a09cc | |||
b6e51a5cd6 | |||
a8f6ce5475 | |||
c96efdcb36 | |||
55ef73ed57 | |||
4b3deaf28b | |||
d8264390d2 | |||
0071e537f3 | |||
5efd936e1e | |||
c8c004d568 | |||
a9972fe559 | |||
1f7f9fa9ec | |||
a9d0cad485 | |||
f85b0d421a | |||
88384c89f3 | |||
22cfd595ef | |||
e235c02e1e | |||
02548197e8 | |||
c2ba6e4503 | |||
7f017aa724 | |||
d51719fbd9 | |||
1392a6dba7 | |||
7413ca9589 | |||
2b1e56331d | |||
cc5e69816f | |||
c59e07581d | |||
c15053d1f8 | |||
5939727b66 | |||
3ceb679465 | |||
8f188194c1 | |||
760d4991f3 | |||
613ab3ba2a | |||
9477967c54 | |||
388f4ae302 | |||
f1fbea96f6 | |||
f0aaee2044 | |||
ac7d210b6b | |||
659db7e421 | |||
cd84339bcc | |||
01d5537244 | |||
ab8fb271f7 | |||
58a18ea50b | |||
574de9ff4c | |||
9d8458bb6d | |||
b22145d0c4 | |||
99e623ef0b | |||
7a20cc2f58 | |||
8290bb3374 | |||
a3932d7f00 | |||
8082dd43bc | |||
642a756b66 | |||
f6c44a83bc | |||
b92da08ae8 | |||
499f078c37 | |||
92669e65ee | |||
7b82ef22be | |||
3ce808688f | |||
cc301c18d5 | |||
db7c990346 | |||
7c99027c31 | |||
5cb0012c83 | |||
a09cfd57a4 | |||
62d9729629 | |||
ed16281737 | |||
4d9a463297 | |||
e13fdfb2ce | |||
73cb587266 | |||
48388b9eaa | |||
61e46a636c | |||
dede2e9764 | |||
c9c7e4777e | |||
67ae54c957 | |||
14c359700b | |||
c11b8883e0 | |||
adae07d013 | |||
1c7b6a5e05 | |||
fbeba570e6 | |||
c3b2fee074 | |||
e2442f7471 | |||
b33bb0943a | |||
58fe2f2c76 | |||
664f603a31 | |||
b17afc10a2 | |||
74f7576313 | |||
e8d0ffa8b4 | |||
ceb2d99732 | |||
822a3e505a | |||
7b0ab778e3 | |||
744910ad1b | |||
7fdc7e01a5 | |||
c7c622377a | |||
ae990ce8dc | |||
7ab2e1d184 | |||
c21b78b297 | |||
94a7102d3a | |||
fce7a0c78c | |||
98b27d0c64 | |||
2d0b90b423 | |||
070ccae4dd | |||
4620d31e2a | |||
16953b5cfa | |||
cfccadcdc4 | |||
67533cf7c3 | |||
8a10f3f22f | |||
c87210820c | |||
66791a5dad | |||
ee9b2522a3 | |||
df5c7eef39 | |||
ccbb0d37b3 | |||
66f123fb66 | |||
87b599f4a8 | |||
6238df88a2 | |||
38d74f0ad5 | |||
25443918c4 | |||
8035968516 | |||
f9bf0bd90e | |||
0df37d0fa1 | |||
fbb131da73 | |||
942f8d0ec9 | |||
64fa11d204 | |||
3ad5316dd1 | |||
f8e0e9ab1f | |||
10af76a50c | |||
2fafb9f2fb | |||
4de38fe40a | |||
74df3e2491 | |||
8e41a59e2e | |||
17729ce856 | |||
cfd7b906cb | |||
a1f7de2bc3 | |||
f2b3f01759 | |||
3eaf5560be | |||
c66633ccc5 | |||
a2f911dbb1 | |||
060579b73a | |||
09c26fed20 | |||
3e9e7e1750 | |||
94548d2284 | |||
4ec4e5b394 | |||
15c920a612 | |||
e7871b2c76 | |||
644efa2905 | |||
7e9b6fe0aa | |||
b8abf27b86 | |||
e0ff20dd37 | |||
0af42727f5 | |||
b0036759fa | |||
b4b26d4207 | |||
cb7ada2e78 | |||
6e5143681c | |||
8142422257 | |||
0f03226656 | |||
297e9e3cf5 | |||
39b7f48870 | |||
b9bc81544a | |||
7d9eed0ed5 | |||
1398d8d5a6 | |||
6bc874088f | |||
3ec1baee65 | |||
374f661027 | |||
7ab11c3da9 | |||
cc2f3afdf8 | |||
9a5882a290 | |||
a033364d55 | |||
bc3ce26e0e | |||
ebea44029e | |||
4183bc35b2 | |||
4700800770 | |||
9de74cce92 |
@ -27,12 +27,15 @@ with open(".clang-format") as f:
|
||||
|
||||
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN")
|
||||
if CLANG_FORMAT_BIN is None:
|
||||
p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE)
|
||||
o, _ = p.communicate()
|
||||
o = str(o, "utf-8")
|
||||
o = o[len("clang-format version "):].strip()
|
||||
o = o[:o.find(".")]
|
||||
o = int(o)
|
||||
o = 0
|
||||
try:
|
||||
p = subprocess.Popen(["clang-format", "--version"], stdout=subprocess.PIPE)
|
||||
o, _ = p.communicate()
|
||||
o = str(o, "utf-8")
|
||||
o = o[len("clang-format version "):].strip()
|
||||
o = o[:o.find(".")]
|
||||
o = int(o)
|
||||
except: pass
|
||||
if o < 7:
|
||||
if subprocess.call(['which', 'clang-format-7'], stdout=subprocess.PIPE) == 0:
|
||||
CLANG_FORMAT_BIN = 'clang-format-7'
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -34,6 +34,4 @@ afl-whatsup.8
|
||||
qemu_mode/libcompcov/compcovtest
|
||||
as
|
||||
qemu_mode/qemu-*
|
||||
unicorn_mode/unicorn
|
||||
unicorn_mode/unicorn-*
|
||||
unicorn_mode/*.tar.gz
|
||||
core\.*
|
||||
|
50
.travis.yml
50
.travis.yml
@ -1,11 +1,49 @@
|
||||
language: c
|
||||
|
||||
branches:
|
||||
only:
|
||||
- master
|
||||
|
||||
matrix:
|
||||
include:
|
||||
- os: linux
|
||||
dist: bionic
|
||||
env: NAME="bionic-amd64" MODERN="yes" GCC="7"
|
||||
- os: linux
|
||||
dist: xenial
|
||||
env: NAME="xenial-amd64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0"
|
||||
- os: linux
|
||||
dist: trusty
|
||||
env: NAME="trusty-amd64" MODERN="no" GCC="4.8"
|
||||
- os: linux
|
||||
dist: xenial
|
||||
arch: arm64
|
||||
env: NAME="xenial-arm64" MODERN="no" GCC="5" EXTRA="libtool-bin clang-6.0" AFL_NO_X86="1" CPU_TARGET="aarch64"
|
||||
# - os: osx
|
||||
# osx_image: xcode11.2
|
||||
# env: NAME="osx" HOMEBREW_NO_ANALYTICS="1" LINK="http://releases.llvm.org/9.0.0/" NAME="clang+llvm-9.0.0-x86_64-darwin-apple"
|
||||
|
||||
jobs:
|
||||
allow_failures:
|
||||
- os: osx
|
||||
|
||||
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:
|
||||
# export LLVM_DIR=${TRAVIS_BUILD_DIR}/${LLVM_PACKAGE}
|
||||
- echo Testing on $NAME
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then wget "$LINK""$NAME".tar.xz ; export LLVM_CONFIG=`pwd`/"$NAME" ; tar xJf "$NAME".tar.xz ; fi
|
||||
- if [ "$MODERN" = "yes" ]; then sudo apt update ; sudo apt upgrade ; sudo apt install -y libtool libtool-bin automake bison libglib2.0 build-essential clang gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-"$GCC"-dev ; fi
|
||||
- if [ "$MODERN" = "no" ]; then sudo apt update ; sudo apt install -y libtool $EXTRA libpixman-1-dev automake bison libglib2.0 build-essential gcc-"$GCC" gcc-"$GCC"-plugin-dev libc++-dev ; fi
|
||||
|
||||
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
|
||||
- if [ "$TRAVIS_OS_NAME" = "osx" ]; then export LLVM_CONFIG=`pwd`/"$NAME" ; make source-only ; fi
|
||||
- if [ "$TRAVIS_OS_NAME" = "linux" -a "$TRAVIS_CPU_ARCH" = "amd64" ]; then make distrib ; fi
|
||||
- if [ "$TRAVIS_CPU_ARCH" = "arm64" ] ; then make ; cd qemu_mode && sh ./build_qemu_support.sh ; cd .. ; fi
|
||||
- make tests
|
||||
|
140
Android.bp
Normal file
140
Android.bp
Normal file
@ -0,0 +1,140 @@
|
||||
cc_defaults {
|
||||
name: "afl-defaults",
|
||||
|
||||
cflags: [
|
||||
"-funroll-loops",
|
||||
"-Wno-pointer-sign",
|
||||
"-Wno-pointer-arith",
|
||||
"-Wno-sign-compare",
|
||||
"-Wno-unused-parameter",
|
||||
"-Wno-unused-function",
|
||||
"-Wno-format",
|
||||
"-Wno-user-defined-warnings",
|
||||
"-DUSE_TRACE_PC=1",
|
||||
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
|
||||
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
|
||||
"-D__USE_GNU",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-fuzz",
|
||||
static_executable: true,
|
||||
host_supported: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-fuzz.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-showmap",
|
||||
static_executable: true,
|
||||
host_supported: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-showmap.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-tmin",
|
||||
static_executable: true,
|
||||
host_supported: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-tmin.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-analyze",
|
||||
static_executable: true,
|
||||
host_supported: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-analyze.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary {
|
||||
name: "afl-gotcpu",
|
||||
static_executable: true,
|
||||
host_supported: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"afl-gotcpu.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-clang-fast",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"llvm_mode/afl-clang-fast.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_binary_host {
|
||||
name: "afl-clang-fast++",
|
||||
static_executable: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
cflags: [
|
||||
"-D__ANDROID__",
|
||||
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"llvm_mode/afl-clang-fast.c",
|
||||
],
|
||||
}
|
||||
|
||||
cc_library_static {
|
||||
name: "afl-llvm-rt",
|
||||
compile_multilib: "both",
|
||||
vendor_available: true,
|
||||
host_supported: true,
|
||||
recovery_available: true,
|
||||
|
||||
defaults: [
|
||||
"afl-defaults",
|
||||
],
|
||||
|
||||
srcs: [
|
||||
"llvm_mode/afl-llvm-rt.o.c",
|
||||
],
|
||||
}
|
@ -6,9 +6,14 @@ Each modified source file, before merging, must be formatted.
|
||||
make code-formatter
|
||||
```
|
||||
|
||||
This should be fine if you modified one of the file already present in the
|
||||
This should be fine if you modified one of the files already present in the
|
||||
project, otherwise run:
|
||||
|
||||
```
|
||||
./.custom-format.py -i file-that-you-have-created.c
|
||||
```
|
||||
|
||||
Regarding the coding style, please follow the AFL style.
|
||||
No camel case at all and use the AFL's macros when possible (e.g. WARNF, FATAL, ...).
|
||||
|
||||
Remember that AFLplusplus has to build and run on many platforms, so generalize your Makefiles (or your patches to our pre-existing Makefiles) to be as much general as possible.
|
||||
|
32
Dockerfile
Normal file
32
Dockerfile
Normal file
@ -0,0 +1,32 @@
|
||||
FROM ubuntu:eoan
|
||||
MAINTAINER David Carlier <devnexen@gmail.com>
|
||||
LABEL "about"="AFLplusplus docker image"
|
||||
RUN apt-get update && apt-get install -y \
|
||||
--no-install-suggests --no-install-recommends \
|
||||
automake \
|
||||
bison \
|
||||
build-essential \
|
||||
clang \
|
||||
clang-9 \
|
||||
flex \
|
||||
gcc-9 \
|
||||
gcc-9-plugin-dev \
|
||||
gcc-9-multilib \
|
||||
libc++-9-dev \
|
||||
libtool \
|
||||
libtool-bin \
|
||||
libglib2.0-dev \
|
||||
llvm-9-dev \
|
||||
python-setuptools \
|
||||
python2.7-dev \
|
||||
wget \
|
||||
ca-certificates \
|
||||
libpixman-1-dev \
|
||||
&& rm -rf /var/lib/apt/lists/*
|
||||
ARG CC=gcc-9
|
||||
ARG CXX=g++-9
|
||||
ARG LLVM_CONFIG=llvm-config-9
|
||||
COPY . /app
|
||||
RUN cd /app && make clean && make distrib && \
|
||||
make install && cd .. && rm -rf /app
|
||||
WORKDIR /work
|
115
Makefile
115
Makefile
@ -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
|
||||
@ -34,12 +34,54 @@ 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
|
||||
-DAFL_PATH=\"$(HELPER_PATH)\" -DBIN_PATH=\"$(BIN_PATH)\" \
|
||||
-DDOC_PATH=\"$(DOC_PATH)\" -Wno-unused-function
|
||||
|
||||
AFL_FUZZ_FILES = $(wildcard src/afl-fuzz*.c)
|
||||
|
||||
PYTHON_INCLUDE ?= /usr/include/python2.7
|
||||
ifneq "($filter %3.7m, $(shell python3.7m-config --includes 2>/dev/null)" ""
|
||||
PYTHON_INCLUDE ?= $(shell python3.7m-config --includes)
|
||||
PYTHON_LIB ?= $(shell python3.7m-config --ldflags)
|
||||
PYTHON_VERSION = 3.7m
|
||||
else
|
||||
ifneq "($filter %3.7, $(shell python3.7-config --includes) 2> /dev/null" ""
|
||||
PYTHON_INCLUDE ?= $(shell python3.7-config --includes)
|
||||
PYTHON_LIB ?= $(shell python3.7-config --ldflags)
|
||||
PYTHON_VERSION = 3.7
|
||||
else
|
||||
ifneq "($filter %2.7, $(shell python2.7-config --includes) 2> /dev/null" ""
|
||||
PYTHON_INCLUDE ?= $(shell python2.7-config --includes)
|
||||
PYTHON_LIB ?= $(shell python2.7-config --ldflags)
|
||||
PYTHON_VERSION = 2.7
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
PYTHON_INCLUDE ?= $(shell test -e /usr/include/python3.7m && echo /usr/include/python3.7m)
|
||||
PYTHON_INCLUDE ?= $(shell test -e /usr/include/python3.7 && echo /usr/include/python3.7)
|
||||
PYTHON_INCLUDE ?= $(shell test -e /usr/include/python2.7 && echo /usr/include/python2.7)
|
||||
|
||||
ifneq "($filter %3.7m, $(PYTHON_INCLUDE))" ""
|
||||
PYTHON_VERSION ?= 3.7m
|
||||
PYTHON_LIB ?= -lpython3.7m
|
||||
else
|
||||
ifneq "($filter %3.7, $(PYTHON_INCLUDE))" ""
|
||||
PYTHON_VERSION ?= 3.7
|
||||
else
|
||||
ifneq "($filter %2.7, $(PYTHON_INCLUDE))" ""
|
||||
PYTHON_VERSION ?= 2.7
|
||||
PYTHON_LIB ?= -lpython2.7
|
||||
else
|
||||
PYTHON_VERSION ?= none
|
||||
endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifdef SOURCE_DATE_EPOCH
|
||||
BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -r "$(SOURCE_DATE_EPOCH)" -I 2>/dev/null || date -u -I)
|
||||
else
|
||||
BUILD_DATE ?= $(shell date -I)
|
||||
endif
|
||||
|
||||
ifneq "$(filter Linux GNU%,$(shell uname))" ""
|
||||
LDFLAGS += -ldl
|
||||
@ -62,9 +104,9 @@ endif
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
|
||||
|
||||
ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) -lpython2.7 2>/dev/null && echo 1 || echo 0 )" "1"
|
||||
ifeq "$(shell echo '\#include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) -x c - -o .test -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
PYTHON_OK=1
|
||||
PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) -lpython2.7
|
||||
PYFLAGS=-DUSE_PYTHON -I$(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB)
|
||||
else
|
||||
PYTHON_OK=0
|
||||
PYFLAGS=
|
||||
@ -80,7 +122,7 @@ ifdef STATIC
|
||||
LDFLAGS += -lm -lrt -lpthread -lz -lutil
|
||||
endif
|
||||
|
||||
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"
|
||||
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 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
@ -103,6 +145,7 @@ man: $(MANPAGES)
|
||||
|
||||
tests: source-only
|
||||
@cd test ; ./test.sh
|
||||
@rm -f test/errors
|
||||
|
||||
performance-tests: performance-test
|
||||
test-performance: performance-test
|
||||
@ -115,12 +158,13 @@ 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 "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa"
|
||||
@echo "source-only: everything for source code fuzzing: llvm_mode, gcc_plugin, libdislocator, libtokencap, radamsa"
|
||||
@echo "distrib: everything (for both binary-only and source code fuzzing)"
|
||||
@echo "man: creates simple man pages from the help option of the programs"
|
||||
@echo "install: installs everything you have compiled with the build option above"
|
||||
@echo "clean: cleans everything. for qemu_mode and unicorn_mode it means it deletes all downloads as well"
|
||||
@echo "clean: cleans everything. for qemu_mode it means it deletes all downloads as well"
|
||||
@echo "code-format: format the code, do this before you commit and send a PR please!"
|
||||
@echo "tests: this runs the test framework. It is more catered for the developers, but if you run into problems this helps pinpointing the problem"
|
||||
@echo "document: creates afl-fuzz-document which will only do one run and save all manipulated inputs into out/queue/mutations"
|
||||
@echo "help: shows these build options :-)"
|
||||
@ -131,6 +175,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
|
||||
@ -161,12 +207,12 @@ ifeq "$(PYTHON_OK)" "1"
|
||||
|
||||
test_python27:
|
||||
@rm -f .test 2> /dev/null
|
||||
@echo "[+] Python 2.7 support seems to be working."
|
||||
@echo "[+] Python $(PYTHON_VERSION) support seems to be working."
|
||||
|
||||
else
|
||||
|
||||
test_python27:
|
||||
@echo "[-] You seem to need to install the package python2.7-dev, but it is optional so we continue"
|
||||
@echo "[-] You seem to need to install the package python3.7-dev or python2.7-dev (and perhaps python[23]-apt), but it is optional so we continue"
|
||||
|
||||
endif
|
||||
|
||||
@ -191,6 +237,12 @@ src/afl-forkserver.o : src/afl-forkserver.c include/forkserver.h
|
||||
src/afl-sharedmem.o : src/afl-sharedmem.c include/sharedmem.h
|
||||
$(CC) $(CFLAGS) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
|
||||
radamsa: src/third_party/libradamsa/libradamsa.so
|
||||
cp src/third_party/libradamsa/libradamsa.so .
|
||||
|
||||
src/third_party/libradamsa/libradamsa.so: src/third_party/libradamsa/libradamsa.c src/third_party/libradamsa/radamsa.h
|
||||
$(MAKE) -C src/third_party/libradamsa/
|
||||
|
||||
afl-fuzz: include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
|
||||
@ -221,13 +273,16 @@ code-format:
|
||||
./.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/*.h
|
||||
./.custom-format.py -i gcc_plugin/*.cc
|
||||
./.custom-format.py -i experimental/*/*.c
|
||||
./.custom-format.py -i experimental/*/*.h
|
||||
./.custom-format.py -i qemu_mode/patches/*.h
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.c
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.cc
|
||||
./.custom-format.py -i qemu_mode/libcompcov/*.h
|
||||
./.custom-format.py -i unicorn_mode/patches/*.h
|
||||
./.custom-format.py -i qbdi_mode/*.c
|
||||
./.custom-format.py -i qbdi_mode/*.cpp
|
||||
./.custom-format.py -i *.h
|
||||
./.custom-format.py -i *.c
|
||||
|
||||
@ -236,7 +291,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
|
||||
@ -260,37 +315,45 @@ all_done: test_build
|
||||
.NOTPARALLEL: clean
|
||||
|
||||
clean:
|
||||
rm -f $(PROGS) 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
|
||||
rm -f $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 qemu_mode/qemu-3.1.1.tar.xz afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-gcc-rt.o afl-g++-fast *.so *.8
|
||||
rm -rf out_dir qemu_mode/qemu-3.1.1 *.dSYM */*.dSYM
|
||||
-$(MAKE) -C llvm_mode clean
|
||||
-$(MAKE) -C gcc_plugin clean
|
||||
$(MAKE) -C libdislocator clean
|
||||
$(MAKE) -C libtokencap clean
|
||||
$(MAKE) -C experimental/socket_fuzzing clean
|
||||
$(MAKE) -C experimental/argv_fuzzing clean
|
||||
$(MAKE) -C qemu_mode/unsigaction clean
|
||||
$(MAKE) -C qemu_mode/libcompcov clean
|
||||
$(MAKE) -C src/third_party/libradamsa/ clean
|
||||
-rm -rf unicorn_mode/unicorn
|
||||
|
||||
distrib: all
|
||||
distrib: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C experimental/socket_fuzzing
|
||||
$(MAKE) -C experimental/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
binary-only: all
|
||||
binary-only: all radamsa
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
$(MAKE) -C experimental/socket_fuzzing
|
||||
$(MAKE) -C experimental/argv_fuzzing
|
||||
cd qemu_mode && sh ./build_qemu_support.sh
|
||||
cd unicorn_mode && sh ./build_unicorn_support.sh
|
||||
|
||||
source-only: all
|
||||
source-only: all radamsa
|
||||
-$(MAKE) -C llvm_mode
|
||||
-$(MAKE) -C gcc_plugin
|
||||
$(MAKE) -C libdislocator
|
||||
$(MAKE) -C libtokencap
|
||||
|
||||
%.8: %
|
||||
@echo .TH $* 8 `date -I` "afl++" > $@
|
||||
@echo .TH $* 8 $(BUILD_DATE) "afl++" > $@
|
||||
@echo .SH NAME >> $@
|
||||
@echo .B $* >> $@
|
||||
@echo >> $@
|
||||
@ -309,7 +372,7 @@ source-only: all
|
||||
@echo Apache License Version 2.0, January 2004 >> $@
|
||||
|
||||
install: all $(MANPAGES)
|
||||
mkdir -p -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
install -d -m 755 $${DESTDIR}$(BIN_PATH) $${DESTDIR}$(HELPER_PATH) $${DESTDIR}$(DOC_PATH) $${DESTDIR}$(MISC_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-plot.sh
|
||||
install -m 755 $(PROGS) $(SH_PROGS) $${DESTDIR}$(BIN_PATH)
|
||||
rm -f $${DESTDIR}$(BIN_PATH)/afl-as
|
||||
@ -328,6 +391,10 @@ endif
|
||||
if [ -f libdislocator.so ]; then set -e; install -m 755 libdislocator.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libtokencap.so ]; then set -e; install -m 755 libtokencap.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libcompcov.so ]; then set -e; install -m 755 libcompcov.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f libradamsa.so ]; then set -e; install -m 755 libradamsa.so $${DESTDIR}$(HELPER_PATH); fi
|
||||
if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
|
||||
$(MAKE) -C experimental/socket_fuzzing install
|
||||
$(MAKE) -C experimental/argv_fuzzing install
|
||||
|
||||
set -e; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-g++
|
||||
set -e; if [ -f afl-clang-fast ] ; then ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-clang-fast $${DESTDIR}$(BIN_PATH)/afl-clang++ ; else ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang ; ln -sf afl-gcc $${DESTDIR}$(BIN_PATH)/afl-clang++; fi
|
||||
|
51
README.md
51
README.md
@ -1,8 +1,10 @@
|
||||
# american fuzzy lop plus plus (afl++)
|
||||
|
||||
Release Version: 2.58c
|
||||

|
||||
|
||||
Github Version: 2.58d
|
||||
Release Version: 2.59c
|
||||
|
||||
Github Version: 2.59d
|
||||
|
||||
includes all necessary/interesting changes from Google's afl 2.56b
|
||||
|
||||
@ -25,10 +27,10 @@
|
||||
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,
|
||||
llvm up to version 10, QEMU 3.1, more speed and crashfixes for QEMU,
|
||||
better *BSD and Android support and much, much more.
|
||||
|
||||
Additionally the following patches have been integrated:
|
||||
Additionally the following features and patches have been integrated:
|
||||
|
||||
* AFLfast's power schedules by Marcel Böhme: [https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
||||
|
||||
@ -50,18 +52,26 @@
|
||||
|
||||
* Win32 PE binary-only fuzzing with QEMU and Wine
|
||||
|
||||
* Radamsa mutator (enable with `-R` to add or `-RR` to run it exclusivly).
|
||||
|
||||
* qbdi_mode: fuzz android native libraries via QBDI framework
|
||||
|
||||
|
||||
A more thorough list is available in the PATCHES file.
|
||||
|
||||
| Feature/Instrumentation | AFL-GCC | LLVM_MODE | GCC_PLUGIN | QEMU_MODE | Unicorn |
|
||||
| ----------------------- |:-------:|:---------:|:----------:|:---------:|:-------:|
|
||||
| laf-intel / CompCov | | x | | x | x |
|
||||
| NeverZero | X | x(1) | | x | x |
|
||||
| Persistent mode | | x | X | x | |
|
||||
| Whitelist | | x | X | | |
|
||||
| InsTrim | | x | | | |
|
||||
| Feature/Instrumentation | afl-gcc | llvm_mode | gcc_plugin | qemu_mode | unicorn_mode |
|
||||
| ----------------------- |:-------:|:---------:|:----------:|:---------:|:------------:|
|
||||
| laf-intel / CompCov | | x | | x86/arm | x86/arm |
|
||||
| NeverZero | x | x(1) | (2) | x | x |
|
||||
| Persistent mode | | x | x | x86 | 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 :-)
|
||||
|
||||
@ -98,11 +108,12 @@ is what you should choose.
|
||||
These build options exist:
|
||||
|
||||
* all: just the main afl++ binaries
|
||||
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap
|
||||
* source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap
|
||||
* binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap, radamsa
|
||||
* source-only: everything for source code fuzzing: llvm_mode, libdislocator, libtokencap, radamsa
|
||||
* 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
|
||||
* code-format: format the code, do this before you commit and send a PR please!
|
||||
* tests: runs test cases to ensure that all features are still working as they should
|
||||
* help: shows these build options
|
||||
|
||||
@ -113,6 +124,14 @@ afl++ binaries by passing the STATIC=1 argument to make:
|
||||
$ make all STATIC=1
|
||||
```
|
||||
|
||||
Note that afl++ is faster and better the newer the compilers used are.
|
||||
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
|
||||
|
||||
@ -185,7 +204,7 @@ superior to blind fuzzing or coverage-only tools.
|
||||
PLEASE NOTE: llvm_mode compilation with afl-clang-fast/afl-clang-fast++
|
||||
instead of afl-gcc/afl-g++ is much faster and has a few cool features.
|
||||
See llvm_mode/ - however few code does not compile with llvm.
|
||||
We support llvm versions 3.8.0 to 9.
|
||||
We support llvm versions 3.8.0 to 10.
|
||||
|
||||
When source code is available, instrumentation can be injected by a companion
|
||||
tool that works as a drop-in replacement for gcc or clang in any standard build
|
||||
@ -208,7 +227,7 @@ For C++ programs, you'd would also want to set `CXX=/path/to/afl/afl-g++`.
|
||||
The clang wrappers (afl-clang and afl-clang++) can be used in the same way;
|
||||
clang users may also opt to leverage a higher-performance instrumentation mode,
|
||||
as described in [llvm_mode/README.md](llvm_mode/README.md).
|
||||
Clang/LLVM has a much better performance and works with LLVM version 3.8.0 to 9.
|
||||
Clang/LLVM has a much better performance and works with LLVM version 3.8.0 to 10.
|
||||
|
||||
Using the LAF Intel performance enhancements are also recommended, see
|
||||
[llvm_mode/README.laf-intel.md](llvm_mode/README.laf-intel.md)
|
||||
@ -455,7 +474,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
|
||||
|
7
TODO
7
TODO
@ -3,13 +3,14 @@ Roadmap 2.60:
|
||||
=============
|
||||
|
||||
afl-fuzz:
|
||||
- radamsa mutator
|
||||
- test the libmutator actually works and does not run infinite (need an example though)
|
||||
- radamsa mutator (via dlopen())
|
||||
|
||||
gcc_plugin:
|
||||
- neverZero
|
||||
- laf-intel
|
||||
|
||||
libdislocator:
|
||||
- add a wrapper for posix_memalign
|
||||
|
||||
qemu_mode:
|
||||
- update to 4.x (probably this will be skipped :( )
|
||||
- instrim for QEMU mode via static analysis (with r2pipe? or angr?)
|
||||
|
@ -61,7 +61,7 @@ fi
|
||||
|
||||
CUR_TIME=`date +%s`
|
||||
|
||||
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
|
||||
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
|
||||
|
||||
ALIVE_CNT=0
|
||||
DEAD_CNT=0
|
||||
|
@ -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)
|
||||
|
596
dictionaries/regexp.dict
Normal file
596
dictionaries/regexp.dict
Normal file
@ -0,0 +1,596 @@
|
||||
#
|
||||
# AFL dictionary for 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"
|
||||
"(?: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]"
|
||||
"(?<=)"
|
||||
"(?<=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}"
|
||||
"L~"
|
||||
"P{scx=Greek}??"
|
||||
"Q~"
|
||||
"R??"
|
||||
"R!??oo(E=?ar)baz-"
|
||||
"Sc?Sc{?{?"
|
||||
"U~"
|
||||
"V~"
|
||||
"W~"
|
||||
"Xdtc"
|
||||
"X~"
|
||||
"X?"
|
||||
"[-123],}"
|
||||
"[-????]+,}"
|
||||
"[00011],}"
|
||||
"[011],}"
|
||||
"[0],}"
|
||||
"[1111],}"
|
||||
"[111],}"
|
||||
"[118],}"
|
||||
"[11],}"
|
||||
"[11a],}"
|
||||
"[[]{}()%^# ],}"
|
||||
"[]"
|
||||
"[],}"
|
||||
"[]{}()%^# ,}"
|
||||
"[^123],}"
|
||||
"[a-b-c],}"
|
||||
"[a-zA-Z0-9],}"
|
||||
"[b"
|
||||
"[bfoo(?!bar)baz"
|
||||
"[c!],}"
|
||||
"[c1],}"
|
||||
"[cA],}"
|
||||
"[cZ],}"
|
||||
"[c_],}"
|
||||
"[ca],}"
|
||||
"[cz],}"
|
||||
"[c~],}"
|
||||
"[c~]w"
|
||||
"[d-d],}"
|
||||
"[d-z],}"
|
||||
"[u???[11<([c?]?:u??<a>)dccc]"
|
||||
"[ud808udf45-ud809udccc],}"
|
||||
"[x"
|
||||
"[x],}"
|
||||
"[xdz],}"
|
||||
"[xyz],}"
|
||||
"[x?"
|
||||
"[x?n4n4"
|
||||
"[x??19?"
|
||||
"[z-d],}"
|
||||
"[~?"
|
||||
"[?????"
|
||||
"[?"
|
||||
"[???],}"
|
||||
"[????-????],}"
|
||||
"[????"
|
||||
"]"
|
||||
"],}"
|
||||
"]QrC[w~]Qr"
|
||||
"]}"
|
||||
"]~"
|
||||
"^?000???????????????????????????x60?"
|
||||
"^12(a(?:1(b12))2)1dyb?9"
|
||||
"^xi!q"
|
||||
"^xxx$,}"
|
||||
"abc"
|
||||
"abc60,0}?{?"
|
||||
"aic"
|
||||
"b~"
|
||||
"c"
|
||||
"c!,}"
|
||||
"c,}"
|
||||
"cA,}"
|
||||
"c_,}"
|
||||
"cjcJcicIckcK,}"
|
||||
"c~"
|
||||
"c~,}"
|
||||
"d"
|
||||
"d?"
|
||||
"d??"
|
||||
"d(?:ab[]?9}"
|
||||
"dpN?(?<a>.)?"
|
||||
"duu{123a?"
|
||||
"d{1,9"
|
||||
"d~"
|
||||
"e"
|
||||
"e~"
|
||||
"e?}"
|
||||
"f~"
|
||||
"g~"
|
||||
"h~"
|
||||
"i~"
|
||||
"j~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xx?~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxb~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxc~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxd~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxe~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxf~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxg~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxh~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxi~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxj~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxk~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxl~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxm~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxn~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxo~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxp~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxr~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxs~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxt~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxu~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxv~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxw~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxx~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxy~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxz~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xx?~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxn~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxo~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxp~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxq~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxr~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxs~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxt~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxu~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxv~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxw~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxx~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxy~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@??@a(P=b@??s@xxz~"
|
||||
"k?@a(?=bbb.~"
|
||||
"k?@a(?=bbbb~"
|
||||
"k?@a(?=bbbc~"
|
||||
"k?@a(?=bbbd~"
|
||||
"k?@a(?=bbbe~"
|
||||
"k?@a(?=bbbf~"
|
||||
"k?@a(?=bbbg~"
|
||||
"k?@a(?=bbbh~"
|
||||
"k?@a(?=bbbi~"
|
||||
"k?@a(?=bbbj~"
|
||||
"k?@a(?=bbbk~"
|
||||
"k?@a(?=bbbl~"
|
||||
"k?@a(?=bbbm~"
|
||||
"k?@a(?=bbbn~"
|
||||
"k?@a(?=bbbo~"
|
||||
"k?@a(?=bbbp~"
|
||||
"k?@a(?=bbbq~"
|
||||
"k?@a(?=bbbr~"
|
||||
"k?@a(?=bbbs~"
|
||||
"k?@a(?=bbbt~"
|
||||
"k?@a(?=bbbu~"
|
||||
"k?@a(?=bbbv~"
|
||||
"k?@a(?=bbbw~"
|
||||
"k?@a(?=bbbx~"
|
||||
"k?@a(?=bbby~"
|
||||
"k?@a(?=bbbz~"
|
||||
"k?@a(?=by?bC?:!k??????????????b~"
|
||||
"k?@a(?=by?bC?:!k??????????????c~"
|
||||
"k?@a(?=by?bC?:!k??????????????d~"
|
||||
"k?@a(?=by?bC?:!k??????????????e~"
|
||||
"k?@a(?=by?bC?:!k??????????????f~"
|
||||
"k?@a(?=by?bC?:!k??????????????g~"
|
||||
"k?@a(?=by?bC?:!k??????????????h~"
|
||||
"k?@a(?=by?bC?:!k??????????????i~"
|
||||
"k?@a(?=by?bC?:!k??????????????j~"
|
||||
"k?@a(?=by?bC?:!k??????????????k~"
|
||||
"k?@a(?=by?bC?:!k??????????????l~"
|
||||
"k?@a(?=by?bC?:!k??????????????m~"
|
||||
"k?@a(?=by?bC?:!k??????????????n~"
|
||||
"k?@a(?=by?bC?:!k??????????????o~"
|
||||
"k?@a(?=by?bC?:!k??????????????p~"
|
||||
"k?@a(?=by?bC?:!k??????????????q~"
|
||||
"k?@a(?=by?bC?:!k??????????????r~"
|
||||
"k?@a(?=by?bC?:!k??????????????s~"
|
||||
"k?@a(?=by?bC?:!k??????????????t~"
|
||||
"k?@a(?=by?bC?:!k??????????????u~"
|
||||
"k?@a(?=by?bC?:!k??????????????v~"
|
||||
"k?@a(?=by?bC?:!k??????????????w~"
|
||||
"k?@a(?=by?bC?:!k??????????????x~"
|
||||
"k?@a(?=by?bC?:!k??????????????y~"
|
||||
"k?@a(?=by?bC?:!k??????????????z~"
|
||||
"k?@a(?=by?bC?:!k???????????????~"
|
||||
"k?@a(?~"
|
||||
"k?@a(b~"
|
||||
"k?@a(c~"
|
||||
"k?@a(d~"
|
||||
"k?@a(e~"
|
||||
"k?@a(f~"
|
||||
"k?@a(g~"
|
||||
"k?@a(h~"
|
||||
"k?@a(i~"
|
||||
"k?@a(j~"
|
||||
"k?@a(k~"
|
||||
"k?@a(l~"
|
||||
"k?@a(m~"
|
||||
"k?@a(n~"
|
||||
"k?@a(o~"
|
||||
"k?@a(p~"
|
||||
"k?@a(q~"
|
||||
"k?@a(r~"
|
||||
"k?@a(s~"
|
||||
"k?@a(t~"
|
||||
"k?@a(u~"
|
||||
"k?@a(v~"
|
||||
"k?@a(w~"
|
||||
"k?@a(x~"
|
||||
"k?@a(y~"
|
||||
"k?@a(z~"
|
||||
"k0X@ab~"
|
||||
"k0X@ac~"
|
||||
"k0X@ad~"
|
||||
"k0X@ae~"
|
||||
"k0X@af~"
|
||||
"k0X@ag~"
|
||||
"k0X@ah~"
|
||||
"k0X@ai~"
|
||||
"k0X@aj~"
|
||||
"k0X@ak~"
|
||||
"k0X@al~"
|
||||
"k0X@am~"
|
||||
"k0X@an~"
|
||||
"k0X@ao~"
|
||||
"k0X@ap~"
|
||||
"k0X@aq~"
|
||||
"k0X@ar~"
|
||||
"k0X@as~"
|
||||
"k0X@at~"
|
||||
"k0X@au~"
|
||||
"k0X@av~"
|
||||
"k0X@aw~"
|
||||
"k0X@ax~"
|
||||
"k0X@ay~"
|
||||
"k0X@az~"
|
||||
"k0X@a?~"
|
||||
"k~"
|
||||
"l~"
|
||||
"m~"
|
||||
"n~"
|
||||
"o~"
|
||||
"p~"
|
||||
"q,}"
|
||||
"q~"
|
||||
"r~"
|
||||
"r?[c~]"
|
||||
"s~"
|
||||
"t~"
|
||||
"u0034,}"
|
||||
"u003z,}"
|
||||
"u0060,}"
|
||||
"ud808udf45*,}"
|
||||
"u~"
|
||||
"v~"
|
||||
"w"
|
||||
"w~"
|
||||
"x3z,}"
|
||||
"x60,}"
|
||||
"xyz?9"
|
||||
"x~"
|
||||
"y~"
|
||||
"z~"
|
||||
"{"
|
||||
"{??"
|
||||
"{ ,,?"
|
||||
"{-"
|
||||
"{0,d?????!"
|
||||
"{12345}pu{234:P}?"
|
||||
"{1?5"
|
||||
"{@"
|
||||
"{M,??"
|
||||
"{M,P{scx=Greek}???sn"
|
||||
"{M,??"
|
||||
"{M,??"
|
||||
"{M,?M,??"
|
||||
"{O"
|
||||
"{r~"
|
||||
"{s~"
|
||||
"{t~"
|
||||
"{u~"
|
||||
"{v~"
|
||||
"{w~"
|
||||
"{x~"
|
||||
"{y~"
|
||||
"{z~"
|
||||
"{}"
|
||||
"{}~"
|
||||
"{??@"
|
||||
"{?~"
|
||||
"},}"
|
||||
"}}"
|
||||
"}}}}}?}!}}}}}}}}}}}}}}}}}?},}"
|
||||
"}~"
|
||||
"}?w~???"
|
||||
"~~"
|
||||
"?!~"
|
||||
"?$"
|
||||
"?*?9?nnRnnn?"
|
||||
"?.~"
|
||||
"?123222222??"
|
||||
"?:??"
|
||||
"?R"
|
||||
"?b~"
|
||||
"?c~"
|
||||
"?d~"
|
||||
"?d???"
|
||||
"?e~"
|
||||
"?f~"
|
||||
"?g~"
|
||||
"?h~"
|
||||
"?i~"
|
||||
"?j~"
|
||||
"?k~"
|
||||
"?l~"
|
||||
"?m~"
|
||||
"?n~"
|
||||
"?o~"
|
||||
"?p~"
|
||||
"?q~"
|
||||
"?r~"
|
||||
"?s~"
|
||||
"?t~"
|
||||
"?u~"
|
||||
"?v~"
|
||||
"?v~?v"
|
||||
"?w~"
|
||||
"?x~"
|
||||
"?y~"
|
||||
"?z~"
|
||||
"?}"
|
||||
"??~"
|
||||
"?????????dadi(?!bbb"
|
||||
"??~"
|
||||
"k?@a??=bbC?:!k?x!k0}??@???@a(P=b@??s@xxq~>>>>>>>>>>>>>>>>>>"
|
||||
"?f??123222222??"
|
||||
"?fP{gc=Decimal_Number}"
|
||||
"?f2jq?oo@ooooh??"
|
||||
"?[???],}f?"
|
||||
"?[???],}nbbc2jocom"
|
||||
"?[]"
|
||||
"?[],}?"
|
||||
"?[],}f?"
|
||||
"?[]f?"
|
||||
"?[]{}()%^#"
|
||||
"?[^123],}f?"
|
||||
"?[^123]nbbc2jocom"
|
||||
"?[a-b-c],}f?"
|
||||
"?[a-b-c]nbbc2jocom"
|
||||
"?[a-zA-Z0-9],}f?"
|
||||
"?[a-zA-Z0-9],}jocom"
|
||||
"?[a-zA-Z0-9]c2jocom"
|
||||
"?[bfoo(?!bar)bazcom"
|
||||
"?[bfoo(?!bar)bazf?"
|
@ -13,6 +13,54 @@ Want to stay in the loop on major new features? Join our mailing list by
|
||||
sending a mail to <afl-users+subscribe@googlegroups.com>.
|
||||
|
||||
|
||||
--------------------------
|
||||
Version ++2.59d (develop):
|
||||
--------------------------
|
||||
|
||||
- fixed a critical bug in afl-tmin that was introduced during ++2.53d
|
||||
- added test cases for afl-cmin and afl-tmin to test/test.sh
|
||||
- added ./experimental/argv_fuzzing ld_preload library by Kjell Braden
|
||||
- added preeny's desock_dup ld_preload library as
|
||||
./experimental/socket_fuzzing for network fuzzing
|
||||
- added AFL_AS_FORCE_INSTRUMENT environment variable for afl-as - this is
|
||||
for the retrorewrite project
|
||||
- we now set QEMU_SET_ENV from AFL_PRELOAD when qemu_mode is used
|
||||
|
||||
|
||||
--------------------------
|
||||
Version ++2.59c (release):
|
||||
--------------------------
|
||||
|
||||
- qbdi_mode: fuzz android native libraries via QBDI framework
|
||||
- unicorn_mode: switched to the new unicornafl, thanks domenukk
|
||||
(see https://github.com/vanhauser-thc/unicorn)
|
||||
- afl-fuzz:
|
||||
- added radamsa as (an optional) mutator stage (-R[R])
|
||||
- added -u command line option to not unlink the fuzz input file
|
||||
- Python3 support (autodetect)
|
||||
- AFL_DISABLE_TRIM env var to disable the trim stage
|
||||
- CPU affinity support for DragonFly
|
||||
- llvm_mode:
|
||||
- float splitting is now configured via AFL_LLVM_LAF_SPLIT_FLOATS
|
||||
- support for llvm 10 included now (thanks to devnexen)
|
||||
- libtokencap:
|
||||
- support for *BSD/OSX/Dragonfly added
|
||||
- hook common *cmp functions from widely used libraries
|
||||
- compcov:
|
||||
- hook common *cmp functions from widely used libraries
|
||||
- floating point splitting support for QEMU on x86 targets
|
||||
- qemu_mode: AFL_QEMU_DISABLE_CACHE env to disable QEMU TranslationBlocks caching
|
||||
- afl-analyze: added AFL_SKIP_BIN_CHECK support
|
||||
- better random numbers for gcc_plugin and llvm_mode (thanks to devnexen)
|
||||
- Dockerfile by courtesy of devnexen
|
||||
- added regex.dictionary
|
||||
- qemu and unicorn download scripts now try to download until the full
|
||||
download succeeded. f*ckin travis fails downloading 40% of the time!
|
||||
- more support for Android (please test!)
|
||||
- added the few Android stuff we didnt have already from Google afl repository
|
||||
- removed unnecessary warnings
|
||||
|
||||
|
||||
--------------------------
|
||||
Version ++2.58c (release):
|
||||
--------------------------
|
||||
|
@ -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:
|
||||
|
||||
|
1
docs/README.radamsa.md
Symbolic link
1
docs/README.radamsa.md
Symbolic link
@ -0,0 +1 @@
|
||||
../src/third_party/libradamsa/README.md
|
@ -65,6 +65,10 @@ tools make fairly broad use of environmental variables:
|
||||
mkdir assembly_here
|
||||
TMPDIR=$PWD/assembly_here AFL_KEEP_ASSEMBLY=1 make clean all
|
||||
|
||||
- If you are a weird person that wants to compile and instrument asm
|
||||
text files then use the AFL_AS_FORCE_INSTRUMENT variable:
|
||||
AFL_AS_FORCE_INSTRUMENT=1 afl-gcc foo.s -o foo
|
||||
|
||||
- Setting AFL_QUIET will prevent afl-cc and afl-as banners from being
|
||||
displayed during compilation, in case you find them distracting.
|
||||
|
||||
|
@ -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
|
||||
|
@ -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).
|
||||
|
||||
|
@ -9,8 +9,9 @@ Adding custom mutators to AFL using Python modules
|
||||
|
||||
Implemented by Christian Holler (:decoder) <choller@mozilla.com>.
|
||||
|
||||
NOTE: This is for Python 2.7 !
|
||||
Anyone who wants to add Python 3.7 support is happily welcome :)
|
||||
NOTE: Python 3.7 and 2.7 are supported so far (3.8 upcomming).
|
||||
Depending on with which version afl-fuzz was compiled, you must use
|
||||
python2 or python3 syntax in your scripts!
|
||||
|
||||
For an example and a template see ../python_mutators/
|
||||
|
||||
@ -56,16 +57,20 @@ further information about this feature.
|
||||
3) How to compile AFLFuzz with Python support
|
||||
---------------------------------------------
|
||||
|
||||
You must install the python 2.7 development package of your Linux distribution
|
||||
before this will work. On Debian/Ubuntu/Kali this can be done with:
|
||||
You must install the python 3.7 or 2.7 development package of your Linux
|
||||
distribution before this will work. On Debian/Ubuntu/Kali this can be done
|
||||
with either:
|
||||
apt install python3.7-dev
|
||||
or
|
||||
apt install python2.7-dev
|
||||
Note that for some distributions you might also need the package python[23]-apt
|
||||
|
||||
A prerequisite for using this mode is to compile AFLFuzz with Python support.
|
||||
|
||||
The afl Makefile performs some magic and detects Python 2.7 if it is in the
|
||||
default path and compiles afl-fuzz with the feature if available (which is
|
||||
/usr/include/python2.7 for the Python.h include and /usr/lib/x86_64-linux-gnu
|
||||
for the libpython2.7.a library)
|
||||
The afl Makefile performs some magic and detects Python 3.7 and 2.7 if it is
|
||||
in the default path and compiles afl-fuzz with the feature if available (which
|
||||
is /usr/include/python2.7 for the Python.h include and
|
||||
/usr/lib/x86_64-linux-gnu for the libpython2.7.a library)
|
||||
|
||||
In case your setup is different set the necessary variables like this:
|
||||
PYTHON_INCLUDE=/path/to/python2.7/include LDFLAGS=-L/path/to/python2.7/lib make
|
||||
|
@ -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)
|
||||
|
@ -165,7 +165,7 @@ of new tuples, and the remainder is associated with changes in hit counts.
|
||||
|
||||
The following table compares the relative ability to discover file syntax and
|
||||
explore program states when using several different approaches to guided
|
||||
fuzzing. The instrumented target was GNU patch 2.7.3 compiled with -O3 and
|
||||
fuzzing. The instrumented target was GNU patch 2.7k.3 compiled with -O3 and
|
||||
seeded with a dummy text file; the session consisted of a single pass over the
|
||||
input queue with afl-fuzz:
|
||||
|
||||
|
37
experimental/argv_fuzzing/Makefile
Normal file
37
experimental/argv_fuzzing/Makefile
Normal file
@ -0,0 +1,37 @@
|
||||
#
|
||||
# american fuzzy lop - argvfuzz
|
||||
# --------------------------------
|
||||
#
|
||||
# Copyright 2019 Kjell Braden <afflux@pentabarf.de>
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
CFLAGS = -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared -ldl
|
||||
|
||||
all: argvfuzz32.so argvfuzz64.so
|
||||
|
||||
argvfuzz32.so: argvfuzz.c
|
||||
-$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "argvfuzz32 build failure (that's fine)"
|
||||
|
||||
argvfuzz64.so: argvfuzz.c
|
||||
-$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
install: argvfuzz32.so argvfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f argvfuzz32.so ]; then set -e; install -m 755 argvfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
install -m 755 argvfuzz64.so $(DESTDIR)$(HELPER_PATH)/
|
||||
|
||||
clean:
|
||||
rm -f argvfuzz32.so argvfuzz64.so
|
16
experimental/argv_fuzzing/README.md
Normal file
16
experimental/argv_fuzzing/README.md
Normal file
@ -0,0 +1,16 @@
|
||||
# argvfuzz
|
||||
|
||||
afl supports fuzzing file inputs or stdin. When source is available,
|
||||
`argv-fuzz-inl.h` can be used to change `main()` to build argv from stdin.
|
||||
|
||||
`argvfuzz` tries to provide the same functionality for binaries. When loaded
|
||||
using `LD_PRELOAD`, it will hook the call to `__libc_start_main` and replace
|
||||
argv using the same logic of `argv-fuzz-inl.h`.
|
||||
|
||||
A few conditions need to be fulfilled for this mechanism to work correctly:
|
||||
|
||||
1. As it relies on hooking the loader, it cannot work on static binaries.
|
||||
2. If the target binary does not use the default libc's `_start` implementation
|
||||
(crt1.o), the hook may not run.
|
||||
3. The hook will replace argv with pointers to `.data` of `argvfuzz.so`. If the
|
||||
target binary expects argv to be living on the stack, things may go wrong.
|
@ -17,7 +17,7 @@
|
||||
|
||||
#include "/path/to/argv-fuzz-inl.h"
|
||||
|
||||
...to the file containing main(), ideally placing it after all the
|
||||
...to the file containing main(), ideally placing it after all the
|
||||
standard includes. Next, put AFL_INIT_ARGV(); near the very beginning of
|
||||
main().
|
||||
|
||||
@ -36,12 +36,20 @@
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
#define AFL_INIT_ARGV() do { argv = afl_init_argv(&argc); } while (0)
|
||||
|
||||
#define AFL_INIT_SET0(_p) do { \
|
||||
#define AFL_INIT_ARGV() \
|
||||
do { \
|
||||
\
|
||||
argv = afl_init_argv(&argc); \
|
||||
argv[0] = (_p); \
|
||||
if (!argc) argc = 1; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define AFL_INIT_SET0(_p) \
|
||||
do { \
|
||||
\
|
||||
argv = afl_init_argv(&argc); \
|
||||
argv[0] = (_p); \
|
||||
if (!argc) argc = 1; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#define MAX_CMDLINE_LEN 100000
|
||||
@ -53,9 +61,9 @@ static char** afl_init_argv(int* argc) {
|
||||
static char* ret[MAX_CMDLINE_PAR];
|
||||
|
||||
char* ptr = in_buf;
|
||||
int rc = 0;
|
||||
int rc = 0;
|
||||
|
||||
if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0);
|
||||
if (read(0, in_buf, MAX_CMDLINE_LEN - 2) < 0) {}
|
||||
|
||||
while (*ptr) {
|
||||
|
||||
@ -63,7 +71,8 @@ static char** afl_init_argv(int* argc) {
|
||||
if (ret[rc][0] == 0x02 && !ret[rc][1]) ret[rc]++;
|
||||
rc++;
|
||||
|
||||
while (*ptr) ptr++;
|
||||
while (*ptr)
|
||||
ptr++;
|
||||
ptr++;
|
||||
|
||||
}
|
||||
@ -77,4 +86,5 @@ static char** afl_init_argv(int* argc) {
|
||||
#undef MAX_CMDLINE_LEN
|
||||
#undef MAX_CMDLINE_PAR
|
||||
|
||||
#endif /* !_HAVE_ARGV_FUZZ_INL */
|
||||
#endif /* !_HAVE_ARGV_FUZZ_INL */
|
||||
|
||||
|
49
experimental/argv_fuzzing/argvfuzz.c
Normal file
49
experimental/argv_fuzzing/argvfuzz.c
Normal file
@ -0,0 +1,49 @@
|
||||
/*
|
||||
american fuzzy lop - LD_PRELOAD for fuzzing argv in binaries
|
||||
------------------------------------------------------------
|
||||
|
||||
Copyright 2019 Kjell Braden <afflux@pentabarf.de>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE /* for RTLD_NEXT */
|
||||
#include <dlfcn.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include "argv-fuzz-inl.h"
|
||||
|
||||
int __libc_start_main(int (*main)(int, char **, char **), int argc, char **argv,
|
||||
void (*init)(void), void (*fini)(void),
|
||||
void (*rtld_fini)(void), void *stack_end) {
|
||||
|
||||
int (*orig)(int (*main)(int, char **, char **), int argc, char **argv,
|
||||
void (*init)(void), void (*fini)(void), void (*rtld_fini)(void),
|
||||
void *stack_end);
|
||||
int sub_argc;
|
||||
char **sub_argv;
|
||||
|
||||
(void)argc;
|
||||
(void)argv;
|
||||
|
||||
orig = dlsym(RTLD_NEXT, __func__);
|
||||
|
||||
if (!orig) {
|
||||
|
||||
fprintf(stderr, "hook did not find original %s: %s\n", __func__, dlerror());
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
||||
sub_argv = afl_init_argv(&sub_argc);
|
||||
|
||||
return orig(main, sub_argc, sub_argv, init, fini, rtld_fini, stack_end);
|
||||
|
||||
}
|
||||
|
@ -28,12 +28,11 @@
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
/* Main entry point. */
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
ssize_t len; /* how much input did we read? */
|
||||
ssize_t len; /* how much input did we read? */
|
||||
char buf[100]; /* Example-only buffer, you'd replace it with other global or
|
||||
local variables appropriate for your use case. */
|
||||
|
||||
@ -64,21 +63,28 @@ int main(int argc, char** argv) {
|
||||
We just have some trivial inline code that faults on 'foo!'. */
|
||||
|
||||
/* do we have enough data? */
|
||||
if (len < 4)
|
||||
return 0;
|
||||
if (len < 4) return 0;
|
||||
|
||||
if (buf[0] == 'f') {
|
||||
|
||||
printf("one\n");
|
||||
if (buf[1] == 'o') {
|
||||
|
||||
printf("two\n");
|
||||
if (buf[2] == 'o') {
|
||||
|
||||
printf("three\n");
|
||||
if (buf[3] == '!') {
|
||||
|
||||
printf("four\n");
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/*** END PLACEHOLDER CODE ***/
|
||||
@ -92,3 +98,4 @@ int main(int argc, char** argv) {
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -21,9 +21,9 @@
|
||||
in the targeted binary (as shown in ../libpng_no_checksum/). One possible
|
||||
exception is the process of fuzzing binary-only software in QEMU mode.
|
||||
|
||||
2) The use of postprocessors for anything other than checksums is questionable
|
||||
and may cause more harm than good. AFL is normally pretty good about
|
||||
dealing with length fields, magic values, etc.
|
||||
2) The use of postprocessors for anything other than checksums is
|
||||
questionable and may cause more harm than good. AFL is normally pretty good
|
||||
about dealing with length fields, magic values, etc.
|
||||
|
||||
3) Postprocessors that do anything non-trivial must be extremely robust to
|
||||
gracefully handle malformed data and other error conditions - otherwise,
|
||||
@ -77,10 +77,10 @@
|
||||
/* The actual postprocessor routine called by afl-fuzz: */
|
||||
|
||||
const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
unsigned int* len) {
|
||||
unsigned int* len) {
|
||||
|
||||
static unsigned char* saved_buf;
|
||||
unsigned char* new_buf;
|
||||
unsigned char* new_buf;
|
||||
|
||||
/* Skip execution altogether for buffers shorter than 6 bytes (just to
|
||||
show how it's done). We can trust *len to be sane. */
|
||||
@ -117,3 +117,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
return new_buf;
|
||||
|
||||
}
|
||||
|
||||
|
@ -36,13 +36,13 @@
|
||||
#define UP4K(_i) ((((_i) >> 12) + 1) << 12)
|
||||
|
||||
const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
unsigned int* len) {
|
||||
unsigned int* len) {
|
||||
|
||||
static unsigned char* saved_buf;
|
||||
static unsigned int saved_len;
|
||||
|
||||
unsigned char* new_buf = (unsigned char*)in_buf;
|
||||
unsigned int pos = 8;
|
||||
unsigned int pos = 8;
|
||||
|
||||
/* Don't do anything if there's not enough room for the PNG header
|
||||
(8 bytes). */
|
||||
@ -111,3 +111,4 @@ const unsigned char* afl_postprocess(const unsigned char* in_buf,
|
||||
return new_buf;
|
||||
|
||||
}
|
||||
|
||||
|
35
experimental/socket_fuzzing/Makefile
Normal file
35
experimental/socket_fuzzing/Makefile
Normal file
@ -0,0 +1,35 @@
|
||||
#
|
||||
# american fuzzy lop++ - socket_fuzz
|
||||
# ----------------------------------
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at:
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
|
||||
.PHONY: all install clean
|
||||
|
||||
PREFIX ?= /usr/local
|
||||
BIN_PATH = $(PREFIX)/bin
|
||||
HELPER_PATH = $(PREFIX)/lib/afl
|
||||
|
||||
CFLAGS = -fPIC -Wall -Wextra
|
||||
LDFLAGS = -shared -ldl
|
||||
|
||||
all: socketfuzz32.so socketfuzz64.so
|
||||
|
||||
socketfuzz32.so: socketfuzz.c
|
||||
-$(CC) -m32 $(CFLAGS) $^ $(LDFLAGS) -o $@ || echo "socketfuzz32 build failure (that's fine)"
|
||||
|
||||
socketfuzz64.so: socketfuzz.c
|
||||
-$(CC) $(CFLAGS) $^ $(LDFLAGS) -o $@
|
||||
|
||||
install: socketfuzz32.so socketfuzz64.so
|
||||
install -d -m 755 $(DESTDIR)$(HELPER_PATH)/
|
||||
if [ -f socketfuzz32.so ]; then set -e; install -m 755 socketfuzz32.so $(DESTDIR)$(HELPER_PATH)/; fi
|
||||
install -m 755 socketfuzz64.so $(DESTDIR)$(HELPER_PATH)/
|
||||
|
||||
clean:
|
||||
rm -f socketfuzz32.so socketfuzz64.so
|
11
experimental/socket_fuzzing/README.md
Normal file
11
experimental/socket_fuzzing/README.md
Normal file
@ -0,0 +1,11 @@
|
||||
# socketfuzz
|
||||
|
||||
when you want to fuzz a network service and you can not/do not want to modify
|
||||
the source (or just have a binary), then this LD_PRELOAD library will allow
|
||||
for sending input to stdin which the target binary will think is coming from
|
||||
a network socket.
|
||||
|
||||
This is desock_dup.c from the amazing preeny project
|
||||
https://github.com/zardus/preeny
|
||||
|
||||
It is packaged in afl++ to have it at hand if needed
|
110
experimental/socket_fuzzing/socketfuzz.c
Normal file
110
experimental/socket_fuzzing/socketfuzz.c
Normal file
@ -0,0 +1,110 @@
|
||||
/*
|
||||
* This is desock_dup.c from the amazing preeny project
|
||||
* https://github.com/zardus/preeny
|
||||
*
|
||||
* It is packaged in afl++ to have it at hand if needed
|
||||
*
|
||||
*/
|
||||
|
||||
#define _GNU_SOURCE
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <sys/types.h> //
|
||||
#include <sys/socket.h> //
|
||||
#include <sys/stat.h> //
|
||||
#include <fcntl.h> //
|
||||
#include <netinet/in.h>
|
||||
#include <pthread.h>
|
||||
#include <signal.h>
|
||||
#include <dlfcn.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#include <poll.h>
|
||||
//#include "logging.h" // switche from preeny_info() to fprintf(stderr, "Info: "
|
||||
|
||||
//
|
||||
// originals
|
||||
//
|
||||
int (*original_close)(int);
|
||||
int (*original_dup2)(int, int);
|
||||
__attribute__((constructor)) void preeny_desock_dup_orig() {
|
||||
|
||||
original_close = dlsym(RTLD_NEXT, "close");
|
||||
original_dup2 = dlsym(RTLD_NEXT, "dup2");
|
||||
|
||||
}
|
||||
|
||||
int close(int sockfd) {
|
||||
|
||||
if (sockfd <= 2) {
|
||||
|
||||
fprintf(stderr, "Info: Disabling close on %d\n", sockfd);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
return original_close(sockfd);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int dup2(int old, int new) {
|
||||
|
||||
if (new <= 2) {
|
||||
|
||||
fprintf(stderr, "Info: Disabling dup from %d to %d\n", old, new);
|
||||
return 0;
|
||||
|
||||
} else {
|
||||
|
||||
return original_dup2(old, new);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)addr;
|
||||
(void)addrlen;
|
||||
fprintf(stderr, "Info: Emulating accept on %d\n", sockfd);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)addr;
|
||||
(void)addrlen;
|
||||
fprintf(stderr, "Info: Emulating bind on port %d\n",
|
||||
ntohs(((struct sockaddr_in *)addr)->sin_port));
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int listen(int sockfd, int backlog) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)backlog;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int setsockopt(int sockfd, int level, int optid, const void *optdata,
|
||||
socklen_t optdatalen) {
|
||||
|
||||
(void)sockfd;
|
||||
(void)level;
|
||||
(void)optid;
|
||||
(void)optdata;
|
||||
(void)optdatalen;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -27,7 +27,7 @@ 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
|
||||
CXXFLAGS ?= -O3 -g -funroll-loops
|
||||
CXXEFLAGS := $(CXXFLAGS) -Wall -D_FORTIFY_SOURCE=2
|
||||
|
||||
CC ?= gcc
|
||||
@ -35,9 +35,7 @@ CXX ?= g++
|
||||
|
||||
PLUGIN_FLAGS = -fPIC -fno-rtti -I"$(shell $(CC) -print-file-name=plugin)/include"
|
||||
|
||||
PROGS = ../afl-gcc-fast ../afl-gcc-pass.so ../afl-gcc-rt.o
|
||||
|
||||
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"
|
||||
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 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
@ -51,6 +49,8 @@ ifeq "$(TEST_MMAP)" "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
|
||||
|
||||
@ -71,8 +71,8 @@ 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 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'..."
|
||||
@ -80,7 +80,7 @@ test_deps:
|
||||
@echo "[+] All set and ready to build."
|
||||
|
||||
../afl-gcc-fast: afl-gcc-fast.c | test_deps
|
||||
$(CC) $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
$(CC) -DAFL_GCC_CC=\"$(CC)\" -DAFL_GCC_CXX=\"$(CXX)\" $(CFLAGS) $< -o $@ $(LDFLAGS)
|
||||
ln -sf afl-gcc-fast ../afl-g++-fast
|
||||
|
||||
../afl-gcc-pass.so: afl-gcc-pass.so.cc | test_deps
|
||||
@ -126,5 +126,5 @@ vpath % ..
|
||||
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 *.o *.so *~ a.out core core.[1-9][0-9]* test-instr .test-instr0 .test-instr1 .test2
|
||||
rm -f $(PROGS) ../afl-g++-fast ../afl-g*-fast.8
|
||||
|
@ -46,9 +46,11 @@ 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.:
|
||||
called afl-gcc-fast and afl-g++-fast in the parent directory.
|
||||
If the CC/CXX have been overridden, those compilers will be used from
|
||||
those wrappers without using AFL_CXX/AFL_CC settings.
|
||||
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
|
||||
|
@ -108,7 +108,7 @@ 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 + 64) * sizeof(u8*));
|
||||
cc_params = ck_alloc((argc + 128) * sizeof(u8*));
|
||||
|
||||
name = strrchr(argv[0], '/');
|
||||
if (!name)
|
||||
@ -119,12 +119,12 @@ static void edit_params(u32 argc, char** argv) {
|
||||
if (!strcmp(name, "afl-g++-fast")) {
|
||||
|
||||
u8* alt_cxx = getenv("AFL_CXX");
|
||||
cc_params[0] = alt_cxx ? alt_cxx : (u8*)"g++";
|
||||
cc_params[0] = alt_cxx ? alt_cxx : (u8*)AFL_GCC_CXX;
|
||||
|
||||
} else {
|
||||
|
||||
u8* alt_cc = getenv("AFL_CC");
|
||||
cc_params[0] = alt_cc ? alt_cc : (u8*)"gcc";
|
||||
cc_params[0] = alt_cc ? alt_cc : (u8*)AFL_GCC_CC;
|
||||
|
||||
}
|
||||
|
||||
@ -202,6 +202,19 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
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
|
||||
@ -282,6 +295,8 @@ int main(int argc, char** argv) {
|
||||
"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 "
|
||||
@ -310,6 +325,15 @@ int main(int argc, char** argv) {
|
||||
SAYF(cCYA "afl-gcc-fast" VERSION cRST
|
||||
" initially by <aseipp@pobox.com>, maintainer: hexcoder-\n");
|
||||
|
||||
if (getenv("AFL_GCC_WHITELIST") == NULL) {
|
||||
|
||||
SAYF(cYEL "Warning:" cRST
|
||||
" using afl-gcc-fast without using AFL_GCC_WHITELIST currently "
|
||||
"produces worse results than afl-gcc. Even better, use "
|
||||
"llvm_mode for now.\n");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
find_obj(argv[0]);
|
||||
|
@ -128,6 +128,7 @@ static unsigned int ext_call_instrument(function *fun) {
|
||||
int more_than_one = -1;
|
||||
edge ep;
|
||||
edge_iterator eip;
|
||||
|
||||
FOR_EACH_EDGE(ep, eip, bb->preds) {
|
||||
|
||||
int count = 0;
|
||||
@ -165,7 +166,7 @@ static unsigned int ext_call_instrument(function *fun) {
|
||||
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 */
|
||||
*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 */
|
||||
@ -201,6 +202,8 @@ static unsigned int inline_instrument(function *fun) {
|
||||
basic_block bb;
|
||||
unsigned finst_blocks = 0;
|
||||
unsigned fcnt_blocks = 0;
|
||||
tree one = build_int_cst(unsigned_char_type_node, 1);
|
||||
// tree zero = build_int_cst(unsigned_char_type_node, 0);
|
||||
|
||||
/* Set up global type declarations */
|
||||
tree map_type = build_pointer_type(unsigned_char_type_node);
|
||||
@ -222,6 +225,7 @@ static unsigned int inline_instrument(function *fun) {
|
||||
DECL_EXTERNAL(prev_loc_g) = 1; /* External linkage */
|
||||
DECL_PRESERVE_P(prev_loc_g) = 1;
|
||||
DECL_ARTIFICIAL(prev_loc_g) = 1; /* Injected by compiler */
|
||||
set_decl_tls_model(prev_loc_g, TLS_MODEL_REAL); /* TLS attribute */
|
||||
rest_of_decl_compilation(prev_loc_g, 1, 0);
|
||||
|
||||
FOR_EACH_BB_FN(bb, fun) {
|
||||
@ -282,9 +286,6 @@ static unsigned int inline_instrument(function *fun) {
|
||||
|
||||
/* 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");
|
||||
@ -293,6 +294,7 @@ static unsigned int inline_instrument(function *fun) {
|
||||
gimple_seq_add_stmt(&seq, g); // map_ptr = __afl_area_ptr
|
||||
update_stmt(g);
|
||||
|
||||
#if 1
|
||||
#if 0
|
||||
tree addr = build2(ADDR_EXPR, map_type, map_ptr, area_off);
|
||||
g = gimple_build_assign(map_ptr2, MODIFY_EXPR, addr);
|
||||
@ -303,12 +305,21 @@ static unsigned int inline_instrument(function *fun) {
|
||||
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);
|
||||
|
||||
#else
|
||||
tree atIndex = build2(PLUS_EXPR, uint32_type_node, map_ptr, area_off);
|
||||
tree array_address = build1(ADDR_EXPR, map_type, atIndex);
|
||||
tree array_access = build1(INDIRECT_REF, map_type, array_address);
|
||||
tree tmp1 = create_tmp_var(unsigned_char_type_node, "tmp1");
|
||||
g = gimple_build_assign(tmp1, array_access);
|
||||
gimple_seq_add_stmt(&seq, g); // tmp1 = *(map_ptr + area_off)
|
||||
update_stmt(g);
|
||||
#endif
|
||||
// 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);
|
||||
@ -320,8 +331,8 @@ static unsigned int inline_instrument(function *fun) {
|
||||
|
||||
// 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
|
||||
g = gimple_build_assign(map_ptr2, INDIRECT_REF, tmp2);
|
||||
gimple_seq_add_stmt(&seq, g); // *map_ptr2 = tmp2
|
||||
update_stmt(g);
|
||||
|
||||
/* Set prev_loc to cur_loc >> 1 */
|
||||
@ -401,11 +412,13 @@ class afl_pass : public gimple_opt_pass {
|
||||
|
||||
}
|
||||
|
||||
virtual unsigned int execute(function *fun) {
|
||||
unsigned int execute(function *fun) override {
|
||||
|
||||
if (!myWhitelist.empty()) {
|
||||
|
||||
bool instrumentBlock = false;
|
||||
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,
|
||||
@ -417,7 +430,8 @@ class afl_pass : public gimple_opt_pass {
|
||||
if (0 != strncmp("<internal>", fname, 10) &&
|
||||
0 != strncmp("<built-in>", fname, 10)) {
|
||||
|
||||
std::string instFilename(fname);
|
||||
instFilename = fname;
|
||||
instLine = DECL_SOURCE_LINE(fun->decl);
|
||||
|
||||
/* Continue only if we know where we actually are */
|
||||
if (!instFilename.empty()) {
|
||||
@ -449,7 +463,21 @@ class afl_pass : public gimple_opt_pass {
|
||||
|
||||
/* Either we couldn't figure out our location or the location is
|
||||
* not whitelisted, so we skip instrumentation. */
|
||||
if (!instrumentBlock) return 0;
|
||||
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;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -490,7 +518,7 @@ int plugin_init(struct plugin_name_args * plugin_info,
|
||||
/* Setup random() so we get Actually Random(TM) outputs from R() */
|
||||
gettimeofday(&tv, &tz);
|
||||
rand_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
||||
srandom(rand_seed);
|
||||
SR(rand_seed);
|
||||
|
||||
/* Pass information */
|
||||
afl_pass_info.pass = make_afl_pass(inst_ext, g);
|
||||
|
@ -9,8 +9,6 @@
|
||||
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:
|
||||
@ -21,12 +19,16 @@
|
||||
|
||||
*/
|
||||
|
||||
#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>
|
||||
@ -34,29 +36,41 @@
|
||||
#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;
|
||||
|
||||
/* Running in persistent mode? */
|
||||
|
||||
static u8 is_persistent;
|
||||
#else
|
||||
__thread u32 __afl_prev_loc;
|
||||
#endif
|
||||
|
||||
/* Trace a basic block with some ID */
|
||||
void __afl_trace(u32 x) {
|
||||
void __afl_trace(const u32 x) {
|
||||
|
||||
#if 1 /* enable for neverZero feature. */
|
||||
__afl_area_ptr[__afl_prev_loc ^ x] +=
|
||||
1 + ((u8)(1 + __afl_area_ptr[__afl_prev_loc ^ x]) == 0);
|
||||
#else
|
||||
++__afl_area_ptr[__afl_prev_loc ^ x];
|
||||
#endif
|
||||
|
||||
u32 l = __afl_prev_loc;
|
||||
u32 n = l ^ x;
|
||||
*(__afl_area_ptr + n) += 1;
|
||||
__afl_prev_loc = (x >> 1);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/* Running in persistent mode? */
|
||||
|
||||
static u8 is_persistent;
|
||||
|
||||
/* SHM setup. */
|
||||
|
||||
static void __afl_map_shm(void) {
|
||||
@ -69,9 +83,38 @@ static void __afl_map_shm(void) {
|
||||
|
||||
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. */
|
||||
|
||||
@ -95,6 +138,8 @@ static void __afl_start_forkserver(void) {
|
||||
|
||||
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. */
|
||||
|
||||
@ -131,6 +176,8 @@ static void __afl_start_forkserver(void) {
|
||||
|
||||
if (!child_pid) {
|
||||
|
||||
signal(SIGCHLD, old_sigchld_handler);
|
||||
|
||||
close(FORKSRV_FD);
|
||||
close(FORKSRV_FD + 1);
|
||||
return;
|
||||
@ -176,20 +223,49 @@ int __afl_persistent_loop(unsigned int max_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 && --cycle_cnt) {
|
||||
if (is_persistent) {
|
||||
|
||||
raise(SIGSTOP);
|
||||
return 1;
|
||||
if (--cycle_cnt) {
|
||||
|
||||
} else
|
||||
raise(SIGSTOP);
|
||||
|
||||
return 0;
|
||||
__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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -72,18 +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__)
|
||||
#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>
|
||||
@ -93,6 +96,10 @@
|
||||
#endif
|
||||
#endif /* __linux__ */
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#ifndef SIMPLE_FILES
|
||||
#define CASE_PREFIX "id:"
|
||||
#else
|
||||
@ -160,7 +167,8 @@ enum {
|
||||
/* 15 */ STAGE_HAVOC,
|
||||
/* 16 */ STAGE_SPLICE,
|
||||
/* 17 */ STAGE_PYTHON,
|
||||
/* 18 */ STAGE_CUSTOM_MUTATOR
|
||||
/* 18 */ STAGE_RADAMSA,
|
||||
/* 19 */ STAGE_CUSTOM_MUTATOR
|
||||
|
||||
};
|
||||
|
||||
@ -261,7 +269,10 @@ extern u32 hang_tmout; /* Timeout used for hang det (ms) */
|
||||
extern u64 mem_limit; /* Memory cap for child (MB) */
|
||||
|
||||
extern u8 cal_cycles, /* Calibration cycles defaults */
|
||||
cal_cycles_long, debug, /* Debug mode */
|
||||
cal_cycles_long, /* Calibration cycles defaults */
|
||||
no_unlink, /* do not unlink cur_input */
|
||||
use_stdin, /* use stdin for sending data */
|
||||
debug, /* Debug mode */
|
||||
custom_only, /* Custom mutator only mode */
|
||||
python_only; /* Python-only mode */
|
||||
|
||||
@ -285,6 +296,9 @@ extern char* power_names[POWER_SCHEDULES_NUM];
|
||||
extern u8 schedule; /* Power schedule (default: EXPLORE)*/
|
||||
extern u8 havoc_max_mult;
|
||||
|
||||
extern u8 use_radamsa;
|
||||
extern size_t (*radamsa_mutate_ptr)(u8*, size_t, u8*, size_t, u32);
|
||||
|
||||
extern u8 skip_deterministic, /* Skip deterministic stages? */
|
||||
force_deterministic, /* Force deterministic stages? */
|
||||
use_splicing, /* Recombine input files? */
|
||||
@ -312,7 +326,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
|
||||
@ -400,6 +415,9 @@ extern u64 stage_finds[32], /* Patterns found per fuzz stage */
|
||||
extern u32 rand_cnt; /* Random number counter */
|
||||
#endif
|
||||
|
||||
extern u32 rand_seed[2];
|
||||
extern s64 init_seed;
|
||||
|
||||
extern u64 total_cal_us, /* Total calibration time (us) */
|
||||
total_cal_cycles; /* Total calibration cycles */
|
||||
|
||||
@ -541,7 +559,7 @@ u8 has_new_bits(u8*);
|
||||
u32 count_bits(u8*);
|
||||
u32 count_bytes(u8*);
|
||||
u32 count_non_255_bytes(u8*);
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
void simplify_trace(u64*);
|
||||
void classify_counts(u64*);
|
||||
#else
|
||||
@ -643,11 +661,9 @@ static inline u32 UR(u32 limit) {
|
||||
#else
|
||||
if (!fixed_seed && unlikely(!rand_cnt--)) {
|
||||
|
||||
u32 seed[2];
|
||||
|
||||
ck_read(dev_urandom_fd, &seed, sizeof(seed), "/dev/urandom");
|
||||
srandom(seed[0]);
|
||||
rand_cnt = (RESEED_RNG / 2) + (seed[1] % RESEED_RNG);
|
||||
ck_read(dev_urandom_fd, &rand_seed, sizeof(rand_seed), "/dev/urandom");
|
||||
srandom(rand_seed[0]);
|
||||
rand_cnt = (RESEED_RNG / 2) + (rand_seed[1] % RESEED_RNG);
|
||||
|
||||
}
|
||||
|
||||
@ -656,6 +672,13 @@ static inline u32 UR(u32 limit) {
|
||||
|
||||
}
|
||||
|
||||
static inline u32 get_rand_seed() {
|
||||
|
||||
if (fixed_seed) return (u32)init_seed;
|
||||
return rand_seed[0];
|
||||
|
||||
}
|
||||
|
||||
/* Find first power of two greater or equal to val (assuming val under
|
||||
2^63). */
|
||||
|
||||
|
4
include/android-ashmem.h
Normal file → Executable file
4
include/android-ashmem.h
Normal file → Executable file
@ -52,7 +52,7 @@ static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
|
||||
if (__cmd == IPC_RMID) {
|
||||
|
||||
int length = ioctl(__shmid, ASHMEM_GET_SIZE, NULL);
|
||||
struct ashmem_pin pin = {0, length};
|
||||
struct ashmem_pin pin = {0, (unsigned int)length};
|
||||
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
|
||||
close(__shmid);
|
||||
|
||||
@ -64,6 +64,7 @@ static inline int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
|
||||
|
||||
static inline int shmget(key_t __key, size_t __size, int __shmflg) {
|
||||
|
||||
(void)__shmflg;
|
||||
int fd, ret;
|
||||
char ourkey[11];
|
||||
|
||||
@ -87,6 +88,7 @@ error:
|
||||
|
||||
static inline void *shmat(int __shmid, const void *__shmaddr, int __shmflg) {
|
||||
|
||||
(void)__shmflg;
|
||||
int size;
|
||||
void *ptr;
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
|
||||
/* Version string: */
|
||||
|
||||
#define VERSION "++2.58c" // c = release, d = volatile github dev
|
||||
#define VERSION "++2.59d" // c = release, d = volatile github dev
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -41,7 +41,9 @@
|
||||
|
||||
/* Comment out to disable fancy ANSI boxes and use poor man's 7-bit UI: */
|
||||
|
||||
#ifndef ANDROID_DISABLE_FANCY // Fancy boxes are ugly from adb
|
||||
#define FANCY_BOXES
|
||||
#endif
|
||||
|
||||
/* Default timeout for fuzzed code (milliseconds). This is the upper bound,
|
||||
also used for detecting hangs; the actual value is auto-scaled: */
|
||||
@ -52,13 +54,18 @@
|
||||
|
||||
#define EXEC_TM_ROUND 20
|
||||
|
||||
/* 64bit arch MACRO */
|
||||
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
|
||||
#define WORD_SIZE_64 1
|
||||
#endif
|
||||
|
||||
/* Default memory limit for child process (MB): */
|
||||
|
||||
#ifndef __x86_64__
|
||||
#ifndef WORD_SIZE_64
|
||||
#define MEM_LIMIT 25
|
||||
#else
|
||||
#define MEM_LIMIT 50
|
||||
#endif /* ^!__x86_64__ */
|
||||
#endif /* ^!WORD_SIZE_64 */
|
||||
|
||||
/* Default memory limit when running in QEMU mode (MB): */
|
||||
|
||||
|
@ -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) ((void)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) ((void)s)
|
||||
#define R(x) (arc4random_uniform(x))
|
||||
#endif
|
||||
#endif /* ^AFL_LLVM_PASS */
|
||||
|
||||
#define STRINGIFY_INTERNAL(x) #x
|
||||
|
@ -21,8 +21,13 @@ 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
|
||||
|
||||
VPATH = ..
|
||||
libdislocator.so: libdislocator.so.c ../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
|
||||
|
||||
@ -33,6 +38,7 @@ clean:
|
||||
rm -f ../libdislocator.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 755 ../libdislocator.so $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 README.dislocator $${DESTDIR}$(HELPER_PATH)
|
||||
install -m 644 README.dislocator.md $${DESTDIR}$(HELPER_PATH)
|
||||
|
||||
|
@ -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
|
@ -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,41 @@
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
#include <sys/mman.h>
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <mach/vm_statistics.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
#include <unistd.h>
|
||||
#include <sys/syscall.h>
|
||||
#ifdef __NR_getrandom
|
||||
#define arc4random_buf(p, l) \
|
||||
do { \
|
||||
\
|
||||
ssize_t rd = syscall(__NR_getrandom, p, l, 0); \
|
||||
if (rd != l) DEBUGF("getrandom failed"); \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#else
|
||||
#include <time.h>
|
||||
#define arc4random_buf(p, l) \
|
||||
do { \
|
||||
\
|
||||
srand(time(NULL)); \
|
||||
u32 i; \
|
||||
u8* ptr = (u8*)p; \
|
||||
for (i = 0; i < l; i++) \
|
||||
ptr[i] = rand() % INT_MAX; \
|
||||
\
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
|
||||
@ -36,6 +69,8 @@
|
||||
#define MAP_ANONYMOUS MAP_ANON
|
||||
#endif /* !MAP_ANONYMOUS */
|
||||
|
||||
#define SUPER_PAGE_SIZE 1 << 21
|
||||
|
||||
/* Error / message handling: */
|
||||
|
||||
#define DEBUGF(_x...) \
|
||||
@ -88,13 +123,14 @@ static u8 alloc_verbose, /* Additional debug messages */
|
||||
hard_fail, /* abort() when max_mem exceeded? */
|
||||
no_calloc_over; /* abort() on calloc() overflows? */
|
||||
|
||||
#ifdef __OpenBSD__
|
||||
#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() */
|
||||
static u32 alloc_canary;
|
||||
|
||||
/* This is the main alloc function. It allocates one page more than necessary,
|
||||
sets that tailing page to PROT_NONE, and then increments the return address
|
||||
@ -103,7 +139,9 @@ static __thread u32 call_depth; /* To avoid recursion via fprintf() */
|
||||
|
||||
static void* __dislocator_alloc(size_t len) {
|
||||
|
||||
void* ret;
|
||||
void* ret;
|
||||
size_t tlen;
|
||||
int flags, fd, sp;
|
||||
|
||||
if (total_mem + len > max_mem || total_mem + len < total_mem) {
|
||||
|
||||
@ -115,13 +153,45 @@ 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 (ret == (void*)-1) {
|
||||
#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 == MAP_FAILED) {
|
||||
|
||||
if (hard_fail) FATAL("mmap() failed on alloc (OOM?)");
|
||||
|
||||
@ -146,7 +216,7 @@ static void* __dislocator_alloc(size_t len) {
|
||||
ret += 8;
|
||||
|
||||
PTR_L(ret) = len;
|
||||
PTR_C(ret) = ALLOC_CANARY;
|
||||
PTR_C(ret) = alloc_canary;
|
||||
|
||||
total_mem += len;
|
||||
|
||||
@ -188,6 +258,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). */
|
||||
@ -218,7 +292,7 @@ void free(void* ptr) {
|
||||
|
||||
if (!ptr) return;
|
||||
|
||||
if (PTR_C(ptr) != ALLOC_CANARY) FATAL("bad allocator canary on free()");
|
||||
if (PTR_C(ptr) != alloc_canary) FATAL("bad allocator canary on free()");
|
||||
|
||||
len = PTR_L(ptr);
|
||||
|
||||
@ -247,7 +321,7 @@ void* realloc(void* ptr, size_t len) {
|
||||
|
||||
if (ret && ptr) {
|
||||
|
||||
if (PTR_C(ptr) != ALLOC_CANARY) FATAL("bad allocator canary on realloc()");
|
||||
if (PTR_C(ptr) != alloc_canary) FATAL("bad allocator canary on realloc()");
|
||||
|
||||
memcpy(ret, ptr, MIN(len, PTR_L(ptr)));
|
||||
free(ptr);
|
||||
@ -260,17 +334,86 @@ 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; // (andrea) Why? I comment it out for now
|
||||
if ((align % 2) || (align % sizeof(void*))) return EINVAL;
|
||||
if (len == 0) {
|
||||
|
||||
*ptr = NULL;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
size_t rem = len % align;
|
||||
if (rem) len += align - rem;
|
||||
|
||||
*ptr = __dislocator_alloc(len);
|
||||
|
||||
if (*ptr && len) memset(*ptr, ALLOC_CLOBBER, len);
|
||||
|
||||
DEBUGF("posix_memalign(%p %zu, %zu) [*ptr = %p]", ptr, align, len, *ptr);
|
||||
|
||||
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;
|
||||
if (!max_mem) FATAL("Bad value for AFL_LD_LIMIT_MB");
|
||||
u8* tok;
|
||||
s32 mmem = (s32)strtol((char*)tmp, (char**)&tok, 10);
|
||||
if (*tok != '\0' || errno == ERANGE) FATAL("Bad value for AFL_LD_LIMIT_MB");
|
||||
max_mem = mmem * 1024 * 1024;
|
||||
|
||||
}
|
||||
|
||||
alloc_canary = ALLOC_CANARY;
|
||||
tmp = (u8*)getenv("AFL_RANDOM_ALLOC_CANARY");
|
||||
|
||||
if (tmp) arc4random_buf(&alloc_canary, sizeof(alloc_canary));
|
||||
|
||||
alloc_verbose = !!getenv("AFL_LD_VERBOSE");
|
||||
hard_fail = !!getenv("AFL_LD_HARD_FAIL");
|
||||
no_calloc_over = !!getenv("AFL_LD_NO_CALLOC_OVER");
|
||||
|
@ -23,9 +23,28 @@ CFLAGS += -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||
|
||||
ifeq "$(shell uname)" "Linux"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
ifeq "$(shell uname)" "FreeBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "OpenBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "NetBSD"
|
||||
TARGETS = libtokencap.so
|
||||
endif
|
||||
ifeq "$(shell uname)" "DragonFly"
|
||||
TARGETS = libtokencap.so
|
||||
LDFLAGS += -ldl
|
||||
endif
|
||||
all: $(TARGETS)
|
||||
|
||||
VPATH = ..
|
||||
libtokencap.so: libtokencap.so.c ../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../$@ $(LDFLAGS)
|
||||
|
||||
@ -36,6 +55,7 @@ clean:
|
||||
rm -f ../libtokencap.so
|
||||
|
||||
install: all
|
||||
install -m 755 -d $${DESTDIR}$(HELPER_PATH)
|
||||
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)
|
||||
|
||||
|
@ -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)
|
||||
|
@ -15,20 +15,55 @@
|
||||
|
||||
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.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <stdbool.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__ && !defined __DragonFly__
|
||||
#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
|
||||
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
/* The libc functions are a magnitude faster than our replacements.
|
||||
Use them when RTLD_NEXT is available. */
|
||||
int (*__libc_strcmp)(const char* str1, const char* str2);
|
||||
int (*__libc_strncmp)(const char* str1, const char* str2, size_t len);
|
||||
int (*__libc_strcasecmp)(const char* str1, const char* str2);
|
||||
int (*__libc_strncasecmp)(const char* str1, const char* str2, size_t len);
|
||||
int (*__libc_memcmp)(const void* mem1, const void* mem2, size_t len);
|
||||
int (*__libc_bcmp)(const void* mem1, const void* mem2, size_t len);
|
||||
char* (*__libc_strstr)(const char* haystack, const char* needle);
|
||||
char* (*__libc_strcasestr)(const char* haystack, const char* needle);
|
||||
void* (*__libc_memmem)(const void* haystack, size_t haystack_len,
|
||||
const void* needle, size_t needle_len);
|
||||
#endif
|
||||
|
||||
/* Mapping data and such */
|
||||
|
||||
@ -38,7 +73,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 +82,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 +108,124 @@ 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)®ion,
|
||||
&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 +252,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 +278,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));
|
||||
|
||||
}
|
||||
|
||||
@ -136,9 +294,13 @@ int strcmp(const char* str1, const char* str2) {
|
||||
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1);
|
||||
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_strcmp) return __libc_strcmp(str1, str2);
|
||||
#endif
|
||||
|
||||
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;
|
||||
@ -156,6 +318,10 @@ int strncmp(const char* str1, const char* str2, size_t len) {
|
||||
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
|
||||
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_strncmp) return __libc_strncmp(str1, str2, len);
|
||||
#endif
|
||||
|
||||
while (len--) {
|
||||
|
||||
unsigned char c1 = *str1, c2 = *str2;
|
||||
@ -178,9 +344,13 @@ int strcasecmp(const char* str1, const char* str2) {
|
||||
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, strlen(str1), 1);
|
||||
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, strlen(str2), 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_strcasecmp) return __libc_strcasecmp(str1, str2);
|
||||
#endif
|
||||
|
||||
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;
|
||||
@ -198,9 +368,13 @@ int strncasecmp(const char* str1, const char* str2, size_t len) {
|
||||
if (__tokencap_is_ro(str1)) __tokencap_dump(str1, len, 1);
|
||||
if (__tokencap_is_ro(str2)) __tokencap_dump(str2, len, 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_strncasecmp) return __libc_strncasecmp(str1, str2, len);
|
||||
#endif
|
||||
|
||||
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 +394,46 @@ 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);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_memcmp) return __libc_memcmp(mem1, mem2, len);
|
||||
#endif
|
||||
|
||||
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++;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#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);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_bcmp) return __libc_bcmp(mem1, mem2, len);
|
||||
#endif
|
||||
|
||||
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++;
|
||||
|
||||
}
|
||||
|
||||
@ -242,6 +450,10 @@ char* strstr(const char* haystack, const char* needle) {
|
||||
|
||||
if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_strstr) return __libc_strstr(haystack, needle);
|
||||
#endif
|
||||
|
||||
do {
|
||||
|
||||
const char* n = needle;
|
||||
@ -267,6 +479,10 @@ char* strcasestr(const char* haystack, const char* needle) {
|
||||
|
||||
if (__tokencap_is_ro(needle)) __tokencap_dump(needle, strlen(needle), 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_strcasestr) return __libc_strcasestr(haystack, needle);
|
||||
#endif
|
||||
|
||||
do {
|
||||
|
||||
const char* n = needle;
|
||||
@ -283,13 +499,235 @@ char* strcasestr(const char* haystack, const char* needle) {
|
||||
|
||||
}
|
||||
|
||||
#undef memmem
|
||||
|
||||
void* memmem(const void* haystack, size_t haystack_len, const void* needle,
|
||||
size_t needle_len) {
|
||||
|
||||
if (__tokencap_is_ro(haystack)) __tokencap_dump(haystack, haystack_len, 1);
|
||||
|
||||
if (__tokencap_is_ro(needle)) __tokencap_dump(needle, needle_len, 1);
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
if (__libc_memmem)
|
||||
return __libc_memmem(haystack, haystack_len, needle, needle_len);
|
||||
#endif
|
||||
|
||||
const char* n = (const char*)needle;
|
||||
const char* h = (const char*)haystack;
|
||||
if (haystack_len < needle_len) return 0;
|
||||
if (needle_len == 0) return (void*)haystack;
|
||||
if (needle_len == 1) return memchr(haystack, *n, haystack_len);
|
||||
|
||||
const char* end = h + (haystack_len - needle_len);
|
||||
|
||||
do {
|
||||
|
||||
if (*h == *n) {
|
||||
|
||||
if (memcmp(h, n, needle_len) == 0) return (void*)h;
|
||||
|
||||
}
|
||||
|
||||
} while (h++ <= end);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
/* Common libraries wrappers (from honggfuzz) */
|
||||
|
||||
/*
|
||||
* Apache's httpd wrappers
|
||||
*/
|
||||
int ap_cstr_casecmp(const char* s1, const char* s2) {
|
||||
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int ap_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
|
||||
|
||||
return strncasecmp(s1, s2, n);
|
||||
|
||||
}
|
||||
|
||||
const char* ap_strcasestr(const char* s1, const char* s2) {
|
||||
|
||||
return strcasestr(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int apr_cstr_casecmp(const char* s1, const char* s2) {
|
||||
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int apr_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
|
||||
|
||||
return strncasecmp(s1, s2, n);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* *SSL wrappers
|
||||
*/
|
||||
int CRYPTO_memcmp(const void* m1, const void* m2, size_t len) {
|
||||
|
||||
return memcmp(m1, m2, len);
|
||||
|
||||
}
|
||||
|
||||
int OPENSSL_memcmp(const void* m1, const void* m2, size_t len) {
|
||||
|
||||
return memcmp(m1, m2, len);
|
||||
|
||||
}
|
||||
|
||||
int OPENSSL_strcasecmp(const char* s1, const char* s2) {
|
||||
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int OPENSSL_strncasecmp(const char* s1, const char* s2, size_t len) {
|
||||
|
||||
return strncasecmp(s1, s2, len);
|
||||
|
||||
}
|
||||
|
||||
int32_t memcmpct(const void* s1, const void* s2, size_t len) {
|
||||
|
||||
return memcmp(s1, s2, len);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* libXML wrappers
|
||||
*/
|
||||
int xmlStrncmp(const char* s1, const char* s2, int len) {
|
||||
|
||||
if (len <= 0) { return 0; }
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strncmp(s1, s2, (size_t)len);
|
||||
|
||||
}
|
||||
|
||||
int xmlStrcmp(const char* s1, const char* s2) {
|
||||
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strcmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int xmlStrEqual(const char* s1, const char* s2) {
|
||||
|
||||
if (s1 == s2) { return 1; }
|
||||
if (s1 == NULL) { return 0; }
|
||||
if (s2 == NULL) { return 0; }
|
||||
if (strcmp(s1, s2) == 0) { return 1; }
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int xmlStrcasecmp(const char* s1, const char* s2) {
|
||||
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int xmlStrncasecmp(const char* s1, const char* s2, int len) {
|
||||
|
||||
if (len <= 0) { return 0; }
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strncasecmp(s1, s2, (size_t)len);
|
||||
|
||||
}
|
||||
|
||||
const char* xmlStrstr(const char* haystack, const char* needle) {
|
||||
|
||||
if (haystack == NULL) { return NULL; }
|
||||
if (needle == NULL) { return NULL; }
|
||||
return strstr(haystack, needle);
|
||||
|
||||
}
|
||||
|
||||
const char* xmlStrcasestr(const char* haystack, const char* needle) {
|
||||
|
||||
if (haystack == NULL) { return NULL; }
|
||||
if (needle == NULL) { return NULL; }
|
||||
return strcasestr(haystack, needle);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Samba wrappers
|
||||
*/
|
||||
int memcmp_const_time(const void* s1, const void* s2, size_t n) {
|
||||
|
||||
return memcmp(s1, s2, n);
|
||||
|
||||
}
|
||||
|
||||
bool strcsequal(const void* s1, const void* s2) {
|
||||
|
||||
if (s1 == s2) { return true; }
|
||||
if (!s1 || !s2) { return false; }
|
||||
return (strcmp(s1, s2) == 0);
|
||||
|
||||
}
|
||||
|
||||
/* bcmp/memcmp BSD flavors, similar to CRYPTO_memcmp */
|
||||
|
||||
int timingsafe_bcmp(const void* mem1, const void* mem2, size_t len) {
|
||||
|
||||
return bcmp(mem1, mem2, len);
|
||||
|
||||
}
|
||||
|
||||
int timingsafe_memcmp(const void* mem1, const void* mem2, size_t len) {
|
||||
|
||||
return memcmp(mem1, mem2, len);
|
||||
|
||||
}
|
||||
|
||||
/* Init code to open the output file (or default to stderr). */
|
||||
|
||||
__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();
|
||||
|
||||
#ifdef RTLD_NEXT
|
||||
__libc_strcmp = dlsym(RTLD_NEXT, "strcmp");
|
||||
__libc_strncmp = dlsym(RTLD_NEXT, "strncmp");
|
||||
__libc_strcasecmp = dlsym(RTLD_NEXT, "strcasecmp");
|
||||
__libc_strncasecmp = dlsym(RTLD_NEXT, "strncasecmp");
|
||||
__libc_memcmp = dlsym(RTLD_NEXT, "memcmp");
|
||||
__libc_bcmp = dlsym(RTLD_NEXT, "bcmp");
|
||||
__libc_strstr = dlsym(RTLD_NEXT, "strstr");
|
||||
__libc_strcasestr = dlsym(RTLD_NEXT, "strcasestr");
|
||||
__libc_memmem = dlsym(RTLD_NEXT, "memmem");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* 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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Support/CommandLine.h"
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
@ -146,6 +147,9 @@ struct InsTrim : public ModulePass {
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
|
||||
GlobalVariable::GeneralDynamicTLSModel, 0, false);
|
||||
|
||||
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
|
||||
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
|
||||
|
||||
u64 total_rs = 0;
|
||||
u64 total_hs = 0;
|
||||
|
||||
@ -155,9 +159,10 @@ struct InsTrim : public ModulePass {
|
||||
|
||||
if (!myWhitelist.empty()) {
|
||||
|
||||
bool instrumentBlock = false;
|
||||
DebugLoc Loc;
|
||||
StringRef instFilename;
|
||||
bool instrumentBlock = false;
|
||||
DebugLoc Loc;
|
||||
StringRef instFilename;
|
||||
unsigned int instLine = 0;
|
||||
|
||||
for (auto &BB : F) {
|
||||
|
||||
@ -171,7 +176,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 +222,18 @@ 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;
|
||||
|
||||
}
|
||||
@ -365,7 +377,7 @@ struct InsTrim : public ModulePass {
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
if (neverZero_counters_str !=
|
||||
@ -387,7 +399,7 @@ struct InsTrim : public ModulePass {
|
||||
* Counter + 1 -> {Counter, OverflowFlag}
|
||||
* Counter + OverflowFlag -> Counter
|
||||
*/
|
||||
auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
|
||||
|
@ -29,30 +29,45 @@ ifeq "$(shell uname)" "OpenBSD"
|
||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||
ifeq "$(HAS_OPT)" "1"
|
||||
$(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 9) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
$(error llvm_mode needs a complete llvm installation (versions 3.8.0 up to 10) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
endif
|
||||
else
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
endif
|
||||
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null)
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^[12]|^3\.0|^1[0-9]' && echo 1 || echo 0 )
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null )
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-7]|^1[1-9]' && echo 1 || echo 0 )
|
||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//')
|
||||
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_STDCXX = gnu++11
|
||||
LLVM_APPLE = $(shell clang -v 2>&1 | grep -iq apple && echo 1 || echo 0)
|
||||
|
||||
ifeq "$(LLVM_UNSUPPORTED)" "1"
|
||||
$(warn llvm_mode only supports versions 3.8.0 up to 9)
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning llvm_mode needs llvm-config, which was not found)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_UNSUPPORTED)" "1"
|
||||
$(warning llvm_mode only supports llvm versions 3.8.0 up to 10)
|
||||
endif
|
||||
|
||||
# this is not visible yet:
|
||||
ifeq "$(LLVM_MAJOR)" "9"
|
||||
$(info llvm_mode detected llvm 9, enabling neverZero implementation)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_NEW_API)" "1"
|
||||
$(info llvm_mode detected llvm 10+, enabling neverZero implementation and c++14)
|
||||
LLVM_STDCXX = c++14
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_APPLE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
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
|
||||
@ -89,7 +104,7 @@ ifeq "$(shell test -e $(CC) || echo 1 )" "1"
|
||||
CXX = $(BIN_DIR)/clang++
|
||||
else
|
||||
# hope for the best
|
||||
$(warn we have trouble finding clang/clang++ - llvm-config is not helping us)
|
||||
$(warning we have trouble finding clang/clang++ - llvm-config is not helping us)
|
||||
CC = clang
|
||||
CXX = clang++
|
||||
endif
|
||||
@ -100,7 +115,7 @@ endif
|
||||
CLANGVER = $(shell $(CC) --version | sed -E -ne '/^.*version\ ([0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
|
||||
|
||||
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"
|
||||
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 ; rm -f .test2 )" "1"
|
||||
SHMAT_OK=1
|
||||
else
|
||||
SHMAT_OK=0
|
||||
@ -121,12 +136,26 @@ else
|
||||
endif
|
||||
|
||||
ifneq "$(CLANGVER)" "$(LLVMVER)"
|
||||
CC = $(shell llvm-config --bindir)/clang
|
||||
CXX = $(shell llvm-config --bindir)/clang++
|
||||
CC = $(shell $(LLVM_CONFIG) --bindir)/clang
|
||||
CXX = $(shell $(LLVM_CONFIG) --bindir)/clang++
|
||||
endif
|
||||
|
||||
all: test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
|
||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||
ifeq "$(LLVMVER)" ""
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifneq "$(LLVM_UNSUPPORTED)$(LLVM_APPLE)" "00"
|
||||
NO_BUILD = 1
|
||||
endif
|
||||
|
||||
ifeq "$(NO_BUILD)" "1"
|
||||
TARGETS = no_build
|
||||
else
|
||||
TARGETS = test_shm test_deps $(PROGS) afl-clang-fast.8 test_build all_done
|
||||
endif
|
||||
|
||||
all: $(TARGETS)
|
||||
|
||||
ifeq "$(SHMAT_OK)" "1"
|
||||
|
||||
@ -141,11 +170,15 @@ test_shm:
|
||||
|
||||
endif
|
||||
|
||||
no_build:
|
||||
@printf "%b\\n" "\\033[0;31mPrerequisites are not met, skipping build llvm_mode\\033[0m"
|
||||
|
||||
test_deps:
|
||||
ifndef AFL_TRACE_PC
|
||||
@echo "[*] Checking for working 'llvm-config'..."
|
||||
ifneq "$(LLVM_APPLE)" "1"
|
||||
@which $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
|
||||
endif
|
||||
else
|
||||
@echo "[!] Note: using -fsanitize=trace-pc mode (this will fail with older LLVM)."
|
||||
endif
|
||||
@ -167,10 +200,10 @@ endif
|
||||
ln -sf afl-clang-fast ../afl-clang-fast++
|
||||
|
||||
../libLLVMInsTrim.so: LLVMInsTrim.so.cc MarkNodes.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=gnu++11 -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
|
||||
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< MarkNodes.cc -o $@ $(CLANG_LFL)
|
||||
|
||||
../afl-llvm-pass.so: afl-llvm-pass.so.cc | test_deps
|
||||
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=gnu++11 -shared $< -o $@ $(CLANG_LFL)
|
||||
$(CXX) $(CLANG_CFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL)
|
||||
|
||||
# laf
|
||||
../split-switches-pass.so: split-switches-pass.so.cc | test_deps
|
||||
|
@ -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.
|
||||
|
@ -5,7 +5,7 @@
|
||||
|
||||
## 1) Introduction
|
||||
|
||||
! llvm_mode works with llvm versions 3.8.0 up to 9 !
|
||||
! llvm_mode works with llvm versions 3.8.0 up to 10 !
|
||||
|
||||
The code in this directory allows you to instrument programs for AFL using
|
||||
true compiler-level instrumentation, instead of the more crude
|
||||
|
@ -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. */
|
||||
|
||||
@ -47,7 +49,11 @@ static void find_obj(u8* argv0) {
|
||||
|
||||
if (afl_path) {
|
||||
|
||||
#ifdef __ANDROID__
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.so", afl_path);
|
||||
#else
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.o", afl_path);
|
||||
#endif
|
||||
|
||||
if (!access(tmp, R_OK)) {
|
||||
|
||||
@ -71,7 +77,11 @@ static void find_obj(u8* argv0) {
|
||||
dir = ck_strdup(argv0);
|
||||
*slash = '/';
|
||||
|
||||
#ifdef __ANDROID__
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.so", afl_path);
|
||||
#else
|
||||
tmp = alloc_printf("%s/afl-llvm-rt.o", dir);
|
||||
#endif
|
||||
|
||||
if (!access(tmp, R_OK)) {
|
||||
|
||||
@ -86,8 +96,14 @@ static void find_obj(u8* argv0) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef __ANDROID__
|
||||
if (!access(AFL_PATH "/afl-llvm-rt.so", R_OK)) {
|
||||
|
||||
#else
|
||||
if (!access(AFL_PATH "/afl-llvm-rt.o", R_OK)) {
|
||||
|
||||
#endif
|
||||
|
||||
obj_path = AFL_PATH;
|
||||
return;
|
||||
|
||||
@ -104,6 +120,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*));
|
||||
@ -114,15 +131,25 @@ static void edit_params(u32 argc, char** argv) {
|
||||
else
|
||||
++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;
|
||||
|
||||
}
|
||||
|
||||
@ -196,6 +223,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
u8* cur = *(++argv);
|
||||
|
||||
if (!strcmp(cur, "-m32")) bit_mode = 32;
|
||||
if (!strcmp(cur, "armv7a-linux-androideabi")) bit_mode = 32;
|
||||
if (!strcmp(cur, "-m64")) bit_mode = 64;
|
||||
|
||||
if (!strcmp(cur, "-x")) x_set = 1;
|
||||
@ -273,6 +301,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";
|
||||
|
||||
}
|
||||
|
||||
@ -341,6 +372,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
switch (bit_mode) {
|
||||
|
||||
case 0:
|
||||
@ -365,6 +397,8 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
cc_params[cc_par_cnt] = NULL;
|
||||
@ -424,7 +458,9 @@ int main(int argc, char** argv) {
|
||||
|
||||
}
|
||||
|
||||
#ifndef __ANDROID__
|
||||
find_obj(argv[0]);
|
||||
#endif
|
||||
|
||||
edit_params(argc, argv);
|
||||
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include <list>
|
||||
#include <string>
|
||||
#include <fstream>
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
#include "llvm/IR/BasicBlock.h"
|
||||
@ -93,9 +94,17 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
LLVMContext &C = M.getContext();
|
||||
|
||||
IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
|
||||
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
|
||||
unsigned int cur_loc = 0;
|
||||
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 */
|
||||
|
||||
@ -141,6 +150,8 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
|
||||
GlobalVariable::GeneralDynamicTLSModel, 0, false);
|
||||
#endif
|
||||
ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
|
||||
ConstantInt *One = ConstantInt::get(Int8Ty, 1);
|
||||
|
||||
/* Instrument all the things! */
|
||||
|
||||
@ -181,6 +192,8 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
(void)instLine;
|
||||
|
||||
/* Continue only if we know where we actually are */
|
||||
if (!instFilename.str().empty()) {
|
||||
|
||||
@ -276,7 +289,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
|
||||
Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
|
||||
Value *Incr = IRB.CreateAdd(Counter, ConstantInt::get(Int8Ty, 1));
|
||||
Value *Incr = IRB.CreateAdd(Counter, One);
|
||||
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
if (neverZero_counters_str !=
|
||||
@ -320,7 +333,7 @@ bool AFLCoverage::runOnModule(Module &M) {
|
||||
*/
|
||||
// this is the solution we choose because llvm9 should do the right
|
||||
// thing here
|
||||
auto cf = IRB.CreateICmpEQ(Incr, ConstantInt::get(Int8Ty, 0));
|
||||
auto cf = IRB.CreateICmpEQ(Incr, Zero);
|
||||
auto carry = IRB.CreateZExt(cf, Int8Ty);
|
||||
Incr = IRB.CreateAdd(Incr, carry);
|
||||
/*
|
||||
|
@ -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) {
|
||||
|
@ -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 ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULE) {
|
||||
if (enableFPSplit &&
|
||||
(selectcmpInst->getPredicate() == CmpInst::FCMP_OGE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLE ||
|
||||
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);
|
||||
|
||||
}
|
||||
@ -465,7 +470,9 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
if (selectcmpInst->getPredicate() == CmpInst::FCMP_OEQ ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_ONE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_UNE ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_UGT ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_OGT ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_ULT ||
|
||||
selectcmpInst->getPredicate() == CmpInst::FCMP_OLT) {
|
||||
|
||||
auto op0 = selectcmpInst->getOperand(0);
|
||||
@ -476,6 +483,8 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
|
||||
if (TyOp0 != TyOp1) { continue; }
|
||||
|
||||
if (TyOp0->isArrayTy() || TyOp0->isVectorTy()) { continue; }
|
||||
|
||||
fcomps.push_back(selectcmpInst);
|
||||
|
||||
}
|
||||
@ -648,6 +657,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, m_e0, m_e1);
|
||||
break;
|
||||
case CmpInst::FCMP_OGT:
|
||||
case CmpInst::FCMP_UGT:
|
||||
Instruction *icmp_exponent;
|
||||
icmp_exponent =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, m_e0, m_e1);
|
||||
@ -657,6 +667,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
BinaryOperator::Create(Instruction::Xor, icmp_exponent, t_s0);
|
||||
break;
|
||||
case CmpInst::FCMP_OLT:
|
||||
case CmpInst::FCMP_ULT:
|
||||
icmp_exponent =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, m_e0, m_e1);
|
||||
signequal_bb->getInstList().insert(
|
||||
@ -748,6 +759,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_NE, t_f0, t_f1);
|
||||
break;
|
||||
case CmpInst::FCMP_OGT:
|
||||
case CmpInst::FCMP_UGT:
|
||||
Instruction *icmp_fraction;
|
||||
icmp_fraction =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_UGT, t_f0, t_f1);
|
||||
@ -757,6 +769,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
BinaryOperator::Create(Instruction::Xor, icmp_fraction, t_s0);
|
||||
break;
|
||||
case CmpInst::FCMP_OLT:
|
||||
case CmpInst::FCMP_ULT:
|
||||
icmp_fraction =
|
||||
CmpInst::Create(Instruction::ICmp, CmpInst::ICMP_ULT, t_f0, t_f1);
|
||||
middle_bb->getInstList().insert(
|
||||
@ -795,6 +808,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
PN->addIncoming(icmp_fraction_result, middle_bb);
|
||||
break;
|
||||
case CmpInst::FCMP_OGT:
|
||||
case CmpInst::FCMP_UGT:
|
||||
/* if op1 is negative goto true branch,
|
||||
else go on comparing */
|
||||
PN->addIncoming(t_s1, bb);
|
||||
@ -802,6 +816,7 @@ size_t SplitComparesTransform::splitFPCompares(Module &M) {
|
||||
PN->addIncoming(icmp_fraction_result, middle_bb);
|
||||
break;
|
||||
case CmpInst::FCMP_OLT:
|
||||
case CmpInst::FCMP_ULT:
|
||||
/* if op0 is negative goto true branch,
|
||||
else go on comparing */
|
||||
PN->addIncoming(t_s0, bb);
|
||||
@ -1040,6 +1055,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 +1065,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) {
|
||||
|
||||
|
@ -1,6 +1,9 @@
|
||||
These are example and helper files for the AFL_PYTHON_MODULE feature.
|
||||
See docs/python_mutators.txt for more information
|
||||
|
||||
Note that if you compile with python3.7 you must use python3 scripts, and if
|
||||
you use pyton2.7 to compile python2 scripts!
|
||||
|
||||
|
||||
example.py - this is the template you can use, the functions are there
|
||||
but they are empty
|
||||
|
199
qbdi_mode/README.md
Executable file
199
qbdi_mode/README.md
Executable file
@ -0,0 +1,199 @@
|
||||
# qbdi-based binary-only instrumentation for afl-fuzz
|
||||
|
||||
## 1) Introduction
|
||||
|
||||
The code in ./qbdi_mode allows you to build a standalone feature that
|
||||
using the QBDI framework to fuzz android native library.
|
||||
|
||||
|
||||
## 2) Build
|
||||
|
||||
First download the Android NDK
|
||||
|
||||
```
|
||||
https://developer.android.com/ndk/downloads
|
||||
https://dl.google.com/android/repository/android-ndk-r20-linux-x86_64.zip
|
||||
```
|
||||
|
||||
Then unzip it and build the standalone-toolchain
|
||||
For x86_64 standalone-toolchain
|
||||
|
||||
```
|
||||
unzip android-ndk-r20-linux-x86_64.zip
|
||||
cd android-ndk-r20/
|
||||
./build/tools/make_standalone_toolchain.py --arch x86_64 --api 21 --install-dir ../android-standalone-toolchain-x86_64
|
||||
```
|
||||
|
||||
For x86 standalone-toolchain
|
||||
|
||||
```
|
||||
./build/tools/make_standalone_toolchain.py --arch x86 --api 21 --install-dir ../android-standalone-toolchain-x86
|
||||
```
|
||||
|
||||
In alternative you can also use the prebuilt toolchain, in that case make sure to set the proper CC and CXX env variables because there are many different compilers for each API version in the prebuilt toolchain.
|
||||
|
||||
For example:
|
||||
|
||||
```
|
||||
export STANDALONE_TOOLCHAIN_PATH=~/Android/Sdk/ndk/20.1.5948944/toolchains/llvm/prebuilt/linux-x86_64/
|
||||
export CC=x86_64-linux-android21-clang
|
||||
export CXX=x86_64-linux-android21-clang++
|
||||
```
|
||||
|
||||
Then download the QBDI SDK from website
|
||||
|
||||
```
|
||||
https://qbdi.quarkslab.com/
|
||||
```
|
||||
|
||||
For Android x86_64
|
||||
```
|
||||
https://github.com/QBDI/QBDI/releases/download/v0.7.0/QBDI-0.7.0-android-X86_64.tar.gz
|
||||
```
|
||||
|
||||
Then decompress the sdk
|
||||
|
||||
```
|
||||
mkdir android-qbdi-sdk-x86_64
|
||||
cp QBDI-0.7.0-android-X86_64.tar.gz android-qbdi-sdk-x86_64/
|
||||
cd android-qbdi-sdk-x86_64/
|
||||
tar xvf QBDI-0.7.0-android-X86_64.tar.gz
|
||||
```
|
||||
|
||||
Now set the `STANDALONE_TOOLCHAIN_PATH` to the path of standalone-toolchain
|
||||
|
||||
```
|
||||
export STANDALONE_TOOLCHAIN_PATH=/home/hac425/workspace/android-standalone-toolchain-x86_64
|
||||
```
|
||||
|
||||
set the `QBDI_SDK_PATH` to the path of QBDI SDK
|
||||
|
||||
```
|
||||
export QBDI_SDK_PATH=/home/hac425/workspace/AFLplusplus/qbdi_mode/android-qbdi-sdk-x86_64/
|
||||
```
|
||||
|
||||
Then run the build.sh
|
||||
|
||||
```
|
||||
./build.sh x86_64
|
||||
```
|
||||
|
||||
this could build the afl-fuzz and also the qbdi template for android x86_64
|
||||
|
||||
|
||||
### Example
|
||||
|
||||
The demo-so.c is an vulnerable library, it has a function for test
|
||||
|
||||
```c
|
||||
int target_func(char *buf, int size) {
|
||||
|
||||
printf("buffer:%p, size:%p\n", buf, size);
|
||||
switch (buf[0]) {
|
||||
|
||||
case 1:
|
||||
puts("222");
|
||||
if (buf[1] == '\x44') {
|
||||
|
||||
puts("null ptr deference");
|
||||
*(char *)(0) = 1;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case 0xff:
|
||||
if (buf[2] == '\xff') {
|
||||
|
||||
if (buf[1] == '\x44') {
|
||||
|
||||
puts("crash....");
|
||||
*(char *)(0xdeadbeef) = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
default: puts("default action"); break;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
This could be build to `libdemo.so`.
|
||||
|
||||
Then we should load the library in template.cpp and find the `target` function address.
|
||||
```c
|
||||
void *handle = dlopen(lib_path, RTLD_LAZY);
|
||||
..........................................
|
||||
..........................................
|
||||
..........................................
|
||||
p_target_func = (target_func)dlsym(handle, "target_func");
|
||||
```
|
||||
|
||||
then we read the data from file and call the function in `fuzz_func`
|
||||
|
||||
```c
|
||||
QBDI_NOINLINE int fuzz_func() {
|
||||
|
||||
if (afl_setup()) { afl_forkserver(); }
|
||||
|
||||
/* Read the input from file */
|
||||
unsigned long len = 0;
|
||||
char * data = read_file(input_pathname, &len);
|
||||
|
||||
/* Call the target function with the input data */
|
||||
p_target_func(data, len);
|
||||
return 1;
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
Just compile it
|
||||
```
|
||||
./build.sh x86_64
|
||||
```
|
||||
|
||||
Then push the `afl-fuzz`, `loader`, `libdemo.so`, the `libQBDI.so` from the QBDI SDK and the `libc++_shared.so` from android-standalone-toolchain to android device
|
||||
|
||||
```
|
||||
adb push afl-fuzz /data/local/tmp
|
||||
adb push libdemo.so /data/local/tmp
|
||||
adb push loader /data/local/tmp
|
||||
adb push android-qbdi-sdk-x86_64/usr/local/lib/libQBDI.so /data/local/tmp
|
||||
adb push ../../android-standalone-toolchain-x86_64/sysroot/usr/lib/x86_64-linux-android/libc++_shared.so
|
||||
/data/local/tmp
|
||||
```
|
||||
|
||||
In android adb shell, run the loader to test if it runs
|
||||
```
|
||||
cd /data/local/tmp
|
||||
export LD_LIBRARY_PATH=/data/local/tmp
|
||||
mkdir in
|
||||
echo 0000 > in/1
|
||||
./loader libdemo.so in/1
|
||||
p_target_func:0x716d96a98600
|
||||
offset:0x600
|
||||
offset:0x580
|
||||
buffer:0x716d96609050, size:0x5
|
||||
offset:0x628
|
||||
offset:0x646
|
||||
offset:0x64b
|
||||
offset:0x65c
|
||||
offset:0x6df
|
||||
offset:0x590
|
||||
default action
|
||||
offset:0x6eb
|
||||
```
|
||||
|
||||
Now run `afl-fuzz` to fuzz the demo library
|
||||
|
||||
```
|
||||
./afl-fuzz -i in -o out -- ./loader /data/local/tmp/libdemo.so @@
|
||||
```
|
||||
|
||||

|
||||
|
BIN
qbdi_mode/assets/screen1.png
Normal file
BIN
qbdi_mode/assets/screen1.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 86 KiB |
57
qbdi_mode/build.sh
Executable file
57
qbdi_mode/build.sh
Executable file
@ -0,0 +1,57 @@
|
||||
|
||||
if [ -z ${STANDALONE_TOOLCHAIN_PATH} ]; then
|
||||
echo "please set the android-standalone-toolchain path in STANDALONE_TOOLCHAIN_PATH environmental variable"
|
||||
echo "for example: "
|
||||
echo " export STANDALONE_TOOLCHAIN_PATH=/home/android-standalone-toolchain-21/"
|
||||
exit
|
||||
fi
|
||||
|
||||
if [ -z ${QBDI_SDK_PATH} ]; then
|
||||
echo "please set the qbdi sdk path in QBDI_SDK_PATH environmental variable"
|
||||
echo "for example: "
|
||||
echo " export QBDI_SDK_PATH=/home/QBDI-Android/"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
|
||||
if [ "$1" = "x86" ]; then
|
||||
echo "build x86 qbdi"
|
||||
compiler_prefix="${STANDALONE_TOOLCHAIN_PATH}/bin/"
|
||||
if [ -z ${CC} ]; then
|
||||
export CC=i686-linux-android-gcc
|
||||
fi
|
||||
if [ -z ${CXX} ]; then
|
||||
export CXX=i686-linux-android-g++
|
||||
fi
|
||||
elif [ "$1" = "x86_64" ]; then
|
||||
echo "build x86_64 qbdi"
|
||||
compiler_prefix="${STANDALONE_TOOLCHAIN_PATH}/bin/"
|
||||
if [ -z ${CC} ]; then
|
||||
export CC=x86_64-linux-android-gcc
|
||||
fi
|
||||
if [ -z ${CXX} ]; then
|
||||
export CXX=x86_64-linux-android-g++
|
||||
fi
|
||||
else
|
||||
echo "usage: ./build.sh arch[x86, x86_64]"
|
||||
exit
|
||||
fi
|
||||
|
||||
|
||||
CFLAGS="-I${QBDI_SDK_PATH}/usr/local/include/ -L${QBDI_SDK_PATH}/usr/local/lib/"
|
||||
|
||||
echo "[+] Building the QBDI template"
|
||||
# build the qbdi template
|
||||
${compiler_prefix}${CXX} -o loader template.cpp -lQBDI -ldl -w -g ${CFLAGS}
|
||||
|
||||
echo "[+] Building the demo library"
|
||||
# build the demo share library
|
||||
${compiler_prefix}${CC} -shared -o libdemo.so demo-so.c -w -g
|
||||
|
||||
echo "[+] Building afl-fuzz for Android"
|
||||
# build afl-fuzz
|
||||
cd ..
|
||||
${compiler_prefix}${CC} -DANDROID_DISABLE_FANCY=1 -O3 -funroll-loops -Wall -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign -I include/ -DAFL_PATH=\"/usr/local/lib/afl\" -DBIN_PATH=\"/usr/local/bin\" -DDOC_PATH=\"/usr/local/share/doc/afl\" -Wno-unused-function src/afl-fuzz-misc.c src/afl-fuzz-extras.c src/afl-fuzz-queue.c src/afl-fuzz-one.c src/afl-fuzz-python.c src/afl-fuzz-stats.c src/afl-fuzz-init.c src/afl-fuzz.c src/afl-fuzz-bitmap.c src/afl-fuzz-run.c src/afl-fuzz-globals.c src/afl-common.c src/afl-sharedmem.c src/afl-forkserver.c -o qbdi_mode/afl-fuzz -ldl -w
|
||||
|
||||
echo "[+] All done. Enjoy!"
|
39
qbdi_mode/demo-so.c
Executable file
39
qbdi_mode/demo-so.c
Executable file
@ -0,0 +1,39 @@
|
||||
#include <stdio.h>
|
||||
|
||||
// gcc -shared -o libdemo.so demo-so.c -w
|
||||
int target_func(char *buf, int size) {
|
||||
|
||||
printf("buffer:%p, size:%p\n", buf, size);
|
||||
switch (buf[0]) {
|
||||
|
||||
case 1:
|
||||
puts("222");
|
||||
if (buf[1] == '\x44') {
|
||||
|
||||
puts("null ptr deference");
|
||||
*(char *)(0) = 1;
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
case 0xff:
|
||||
if (buf[2] == '\xff') {
|
||||
|
||||
if (buf[1] == '\x44') {
|
||||
|
||||
puts("crash....");
|
||||
*(char *)(0xdeadbeef) = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
break;
|
||||
default: puts("default action"); break;
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
251
qbdi_mode/template.cpp
Executable file
251
qbdi_mode/template.cpp
Executable file
@ -0,0 +1,251 @@
|
||||
#include <iostream>
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/wait.h>
|
||||
#include <fcntl.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "../include/android-ashmem.h"
|
||||
#endif
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include "../config.h"
|
||||
|
||||
#include <QBDI.h>
|
||||
|
||||
/* NeverZero */
|
||||
|
||||
#if (defined(__x86_64__) || defined(__i386__)) && defined(AFL_QEMU_NOT_ZERO)
|
||||
#define INC_AFL_AREA(loc) \
|
||||
asm volatile( \
|
||||
"incb (%0, %1, 1)\n" \
|
||||
"adcb $0, (%0, %1, 1)\n" \
|
||||
: /* no out */ \
|
||||
: "r"(afl_area_ptr), "r"(loc) \
|
||||
: "memory", "eax")
|
||||
#else
|
||||
#define INC_AFL_AREA(loc) afl_area_ptr[loc]++
|
||||
#endif
|
||||
|
||||
using namespace QBDI;
|
||||
|
||||
typedef int (*target_func)(char *buf, int size);
|
||||
|
||||
static const size_t STACK_SIZE = 0x100000; // 1MB
|
||||
static const QBDI::rword FAKE_RET_ADDR = 0x40000;
|
||||
target_func p_target_func = NULL;
|
||||
rword module_base = 0;
|
||||
rword module_end = 0;
|
||||
static unsigned char
|
||||
dummy[MAP_SIZE]; /* costs MAP_SIZE but saves a few instructions */
|
||||
unsigned char *afl_area_ptr = NULL; /* Exported for afl_gen_trace */
|
||||
|
||||
unsigned long afl_prev_loc = 0;
|
||||
|
||||
char input_pathname[PATH_MAX];
|
||||
|
||||
/* Set up SHM region and initialize other stuff. */
|
||||
|
||||
int afl_setup(void) {
|
||||
|
||||
char *id_str = getenv(SHM_ENV_VAR);
|
||||
int shm_id;
|
||||
if (id_str) {
|
||||
|
||||
shm_id = atoi(id_str);
|
||||
afl_area_ptr = (unsigned char *)shmat(shm_id, NULL, 0);
|
||||
if (afl_area_ptr == (void *)-1) return 0;
|
||||
memset(afl_area_ptr, 0, MAP_SIZE);
|
||||
|
||||
}
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
/* Fork server logic, invoked once we hit _start. */
|
||||
static void afl_forkserver() {
|
||||
|
||||
static unsigned char tmp[4];
|
||||
pid_t child_pid;
|
||||
|
||||
if (write(FORKSRV_FD + 1, tmp, 4) != 4) return;
|
||||
|
||||
while (1) {
|
||||
|
||||
int status;
|
||||
u32 was_killed;
|
||||
// wait for afl-fuzz
|
||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
|
||||
|
||||
child_pid = fork();
|
||||
if (child_pid < 0) exit(4);
|
||||
|
||||
if (!child_pid) {
|
||||
|
||||
// child return to execute code
|
||||
close(FORKSRV_FD);
|
||||
close(FORKSRV_FD + 1);
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
// write child pid to afl-fuzz
|
||||
if (write(FORKSRV_FD + 1, &child_pid, 4) != 4) exit(5);
|
||||
|
||||
// wait child stop
|
||||
if (waitpid(child_pid, &status, 0) < 0) exit(6);
|
||||
|
||||
// send child stop status to afl-fuzz
|
||||
if (write(FORKSRV_FD + 1, &status, 4) != 4) exit(7);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void afl_maybe_log(unsigned long cur_loc) {
|
||||
|
||||
if (afl_area_ptr == NULL) { return; }
|
||||
unsigned long afl_idx = cur_loc ^ afl_prev_loc;
|
||||
afl_idx &= MAP_SIZE - 1;
|
||||
INC_AFL_AREA(afl_idx);
|
||||
afl_prev_loc = cur_loc >> 1;
|
||||
|
||||
}
|
||||
|
||||
char *read_file(char *path, unsigned long *length) {
|
||||
|
||||
unsigned long len;
|
||||
char * buf;
|
||||
|
||||
FILE *fp = fopen(path, "rb");
|
||||
fseek(fp, 0, SEEK_END);
|
||||
len = ftell(fp);
|
||||
buf = (char *)malloc(len);
|
||||
rewind(fp);
|
||||
fread(buf, 1, len, fp);
|
||||
fclose(fp);
|
||||
*length = len;
|
||||
return buf;
|
||||
|
||||
}
|
||||
|
||||
QBDI_NOINLINE int fuzz_func() {
|
||||
|
||||
if (afl_setup()) { afl_forkserver(); }
|
||||
|
||||
unsigned long len = 0;
|
||||
char * data = read_file(input_pathname, &len);
|
||||
|
||||
// printf("In fuzz_func\n");
|
||||
p_target_func(data, len);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
static QBDI::VMAction bbcallback(QBDI::VMInstanceRef vm,
|
||||
const QBDI::VMState *state,
|
||||
QBDI::GPRState * gprState,
|
||||
QBDI::FPRState *fprState, void *data) {
|
||||
|
||||
// errno = SAVED_ERRNO;
|
||||
|
||||
#ifdef __x86_64__
|
||||
unsigned long pc = gprState->rip;
|
||||
#elif defined(i386)
|
||||
unsigned long pc = gprState->eip;
|
||||
#elif defined(__arm__)
|
||||
unsigned long pc = gprState->pc;
|
||||
#endif
|
||||
|
||||
// just log the module path
|
||||
if (pc >= module_base && pc <= module_end) {
|
||||
|
||||
unsigned long offset = pc - module_base;
|
||||
printf("\toffset:%p\n", offset);
|
||||
afl_maybe_log(offset);
|
||||
|
||||
}
|
||||
|
||||
return QBDI::VMAction::CONTINUE;
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
if (argc < 3) {
|
||||
|
||||
puts("usage: ./loader library_path input_file_path");
|
||||
exit(0);
|
||||
|
||||
}
|
||||
|
||||
const char *lib_path;
|
||||
lib_path = argv[1];
|
||||
strcpy(input_pathname, argv[2]);
|
||||
void *handle = dlopen(lib_path, RTLD_LAZY);
|
||||
|
||||
if (handle == nullptr) {
|
||||
|
||||
perror("Cannot load library");
|
||||
exit(EXIT_FAILURE);
|
||||
|
||||
}
|
||||
|
||||
const char *lib_name = lib_path;
|
||||
if (strrchr(lib_name, '/') != nullptr) lib_name = strrchr(lib_name, '/') + 1;
|
||||
|
||||
// printf("library name:%s\n", lib_name);
|
||||
// load library module address for log path
|
||||
for (MemoryMap &map : getCurrentProcessMaps()) {
|
||||
|
||||
// printf("module:%s\n", map.name.c_str());
|
||||
if ((map.permission & PF_EXEC) &&
|
||||
strstr(map.name.c_str(), lib_name) != NULL) {
|
||||
|
||||
module_base = map.range.start;
|
||||
module_end = map.range.end;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (module_base == 0) {
|
||||
|
||||
std::cerr << "Fail to find base address" << std::endl;
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
// printf("module base:%p, module end:%p\n", module_base, module_end);
|
||||
p_target_func = (target_func)dlsym(handle, "target_func");
|
||||
// p_target_func = (target_func)(module_base + 0x61a);
|
||||
printf("p_target_func:%p\n", p_target_func);
|
||||
|
||||
VM vm;
|
||||
uint8_t *fakestack = nullptr;
|
||||
|
||||
GPRState *state = vm.getGPRState();
|
||||
allocateVirtualStack(state, STACK_SIZE, &fakestack);
|
||||
vm.addInstrumentedModuleFromAddr(module_base);
|
||||
vm.addInstrumentedModuleFromAddr((rword)&main);
|
||||
|
||||
vm.addVMEventCB(BASIC_BLOCK_ENTRY, bbcallback, nullptr);
|
||||
|
||||
// QBDI::simulateCall(state, FAKE_RET_ADDR);
|
||||
// vm.run((rword)&fuzz_func, (rword)FAKE_RET_ADDR);
|
||||
|
||||
rword ret;
|
||||
vm.call(&ret, (rword)&fuzz_func, {});
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
@ -46,10 +46,18 @@ You can also compile statically-linked binaries by setting STATIC=1. This
|
||||
can be useful when compiling QEMU on a different system than the one you're
|
||||
planning to run the fuzzer on and is most often used with the HOST variable.
|
||||
|
||||
Note: when targetting the i386 architecture, on some bianries the forkserver
|
||||
handshake may fail due to the lack of reversed memory. Fix it with
|
||||
|
||||
export QEMU_RESERVED_VA=0x1000000
|
||||
|
||||
Note: if you want the QEMU helper to be installed on your system for all
|
||||
users, you need to build it before issuing 'make install' in the parent
|
||||
directory.
|
||||
|
||||
If you want to specify a different path for libraries (e.g. to run an arm64
|
||||
binary on x86_64) use QEMU_LD_PREFIX.
|
||||
|
||||
## 3) Bonus feature #1: deferred initialization
|
||||
|
||||
As for LLVM mode (refer to its README for mode details) QEMU mode supports
|
||||
@ -100,7 +108,11 @@ 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
|
||||
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.
|
||||
|
@ -44,7 +44,7 @@ echo "[*] Performing basic sanity checks..."
|
||||
if [ ! "`uname -s`" = "Linux" ]; then
|
||||
|
||||
echo "[-] Error: QEMU instrumentation is supported only on Linux."
|
||||
exit 1
|
||||
exit 0
|
||||
|
||||
fi
|
||||
|
||||
@ -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,13 +153,16 @@ 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."
|
||||
|
||||
if [ "$STATIC" = "1" ]; then
|
||||
|
||||
CFLAGS="-O3 -ggdb" ./configure --disable-bsd-user --disable-guest-agent --disable-strip --disable-werror \
|
||||
--disable-gcrypt --disable-debug-info --disable-debug-tcg --enable-docs --disable-tcg-interpreter \
|
||||
--disable-gcrypt --disable-debug-info --disable-debug-tcg --disable-tcg-interpreter \
|
||||
--enable-attr --disable-brlapi --disable-linux-aio --disable-bzip2 --disable-bluez --disable-cap-ng \
|
||||
--disable-curl --disable-fdt --disable-glusterfs --disable-gnutls --disable-nettle --disable-gtk \
|
||||
--disable-rdma --disable-libiscsi --disable-vnc-jpeg --enable-kvm --disable-lzo --disable-curses \
|
||||
@ -237,10 +243,9 @@ else
|
||||
fi
|
||||
|
||||
echo "[+] Building libcompcov ..."
|
||||
make -C libcompcov
|
||||
make -C libcompcov && echo "[+] libcompcov ready"
|
||||
echo "[+] Building unsigaction ..."
|
||||
make -C unsigaction
|
||||
echo "[+] libcompcov ready"
|
||||
make -C unsigaction && echo "[+] unsigaction ready"
|
||||
echo "[+] All done for qemu_mode, enjoy!"
|
||||
|
||||
exit 0
|
||||
|
@ -22,7 +22,7 @@ CFLAGS ?= -O3 -funroll-loops -I ../../include/
|
||||
CFLAGS += -Wall -Wno-unused-result -D_FORTIFY_SOURCE=2 -g -Wno-pointer-sign
|
||||
LDFLAGS += -ldl
|
||||
|
||||
all: libcompcov.so compcovtest
|
||||
all: libcompcov.so
|
||||
|
||||
libcompcov.so: libcompcov.so.c ../../config.h
|
||||
$(CC) $(CFLAGS) -shared -fPIC $< -o ../../$@ $(LDFLAGS)
|
||||
@ -34,7 +34,7 @@ clean:
|
||||
rm -f ../../libcompcov.so compcovtest
|
||||
|
||||
compcovtest: compcovtest.cc
|
||||
$(CXX) $< -o $@
|
||||
$(CXX) -std=c++11 $< -o $@
|
||||
|
||||
install: all
|
||||
install -m 755 ../../libcompcov.so $${DESTDIR}$(HELPER_PATH)
|
||||
|
@ -19,13 +19,16 @@
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _GNU_SOURCE
|
||||
#define _GNU_SOURCE
|
||||
#endif
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/shm.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "config.h"
|
||||
@ -335,6 +338,146 @@ int memcmp(const void* mem1, const void* mem2, size_t len) {
|
||||
|
||||
}
|
||||
|
||||
// TODO bcmp
|
||||
|
||||
/* Common libraries wrappers (from honggfuzz) */
|
||||
|
||||
/*
|
||||
* Apache's httpd wrappers
|
||||
*/
|
||||
int ap_cstr_casecmp(const char* s1, const char* s2) {
|
||||
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int ap_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
|
||||
|
||||
return strncasecmp(s1, s2, n);
|
||||
|
||||
}
|
||||
|
||||
int apr_cstr_casecmp(const char* s1, const char* s2) {
|
||||
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int apr_cstr_casecmpn(const char* s1, const char* s2, size_t n) {
|
||||
|
||||
return strncasecmp(s1, s2, n);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* *SSL wrappers
|
||||
*/
|
||||
int CRYPTO_memcmp(const void* m1, const void* m2, size_t len) {
|
||||
|
||||
return memcmp(m1, m2, len);
|
||||
|
||||
}
|
||||
|
||||
int OPENSSL_memcmp(const void* m1, const void* m2, size_t len) {
|
||||
|
||||
return memcmp(m1, m2, len);
|
||||
|
||||
}
|
||||
|
||||
int OPENSSL_strcasecmp(const char* s1, const char* s2) {
|
||||
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int OPENSSL_strncasecmp(const char* s1, const char* s2, size_t len) {
|
||||
|
||||
return strncasecmp(s1, s2, len);
|
||||
|
||||
}
|
||||
|
||||
int32_t memcmpct(const void* s1, const void* s2, size_t len) {
|
||||
|
||||
return memcmp(s1, s2, len);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* libXML wrappers
|
||||
*/
|
||||
int xmlStrncmp(const char* s1, const char* s2, int len) {
|
||||
|
||||
if (len <= 0) { return 0; }
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strncmp(s1, s2, (size_t)len);
|
||||
|
||||
}
|
||||
|
||||
int xmlStrcmp(const char* s1, const char* s2) {
|
||||
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strcmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int xmlStrEqual(const char* s1, const char* s2) {
|
||||
|
||||
if (s1 == s2) { return 1; }
|
||||
if (s1 == NULL) { return 0; }
|
||||
if (s2 == NULL) { return 0; }
|
||||
if (strcmp(s1, s2) == 0) { return 1; }
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
int xmlStrcasecmp(const char* s1, const char* s2) {
|
||||
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strcasecmp(s1, s2);
|
||||
|
||||
}
|
||||
|
||||
int xmlStrncasecmp(const char* s1, const char* s2, int len) {
|
||||
|
||||
if (len <= 0) { return 0; }
|
||||
if (s1 == s2) { return 0; }
|
||||
if (s1 == NULL) { return -1; }
|
||||
if (s2 == NULL) { return 1; }
|
||||
return strncasecmp(s1, s2, (size_t)len);
|
||||
|
||||
}
|
||||
|
||||
const char* xmlStrcasestr(const char* haystack, const char* needle) {
|
||||
|
||||
if (haystack == NULL) { return NULL; }
|
||||
if (needle == NULL) { return NULL; }
|
||||
return strcasestr(haystack, needle);
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
* Samba wrappers
|
||||
*/
|
||||
int memcmp_const_time(const void* s1, const void* s2, size_t n) {
|
||||
|
||||
return memcmp(s1, s2, n);
|
||||
|
||||
}
|
||||
|
||||
bool strcsequal(const void* s1, const void* s2) {
|
||||
|
||||
if (s1 == s2) { return true; }
|
||||
if (!s1 || !s2) { return false; }
|
||||
return (strcmp(s1, s2) == 0);
|
||||
|
||||
}
|
||||
|
||||
/* Init code to open init the library. */
|
||||
|
||||
__attribute__((constructor)) void __compcov_init(void) {
|
||||
|
@ -31,6 +31,9 @@
|
||||
|
||||
*/
|
||||
|
||||
#ifndef __AFL_QEMU_COMMON
|
||||
#define __AFL_QEMU_COMMON
|
||||
|
||||
#include "../../config.h"
|
||||
|
||||
#ifndef CPU_NB_REGS
|
||||
@ -76,8 +79,35 @@ void afl_debug_dump_saved_regs();
|
||||
void afl_persistent_loop();
|
||||
|
||||
void tcg_gen_afl_call0(void *func);
|
||||
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
|
||||
TCGv_i64 arg1, TCGv_i64 arg2);
|
||||
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc, TCGv arg1,
|
||||
TCGv arg2);
|
||||
|
||||
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
|
||||
|
||||
|
@ -83,7 +83,9 @@ __thread abi_ulong afl_prev_loc;
|
||||
|
||||
/* Set in the child process in forkserver mode: */
|
||||
|
||||
static int forkserver_installed = 0;
|
||||
static int forkserver_installed = 0;
|
||||
static int disable_caching = 0;
|
||||
|
||||
unsigned char afl_fork_child;
|
||||
unsigned int afl_forksrv_pid;
|
||||
unsigned char is_persistent;
|
||||
@ -206,6 +208,8 @@ static void afl_setup(void) {
|
||||
|
||||
rcu_disable_atfork();
|
||||
|
||||
disable_caching = getenv("AFL_QEMU_DISABLE_CACHE") != NULL;
|
||||
|
||||
is_persistent = getenv("AFL_QEMU_PERSISTENT_ADDR") != NULL;
|
||||
|
||||
if (is_persistent) {
|
||||
@ -422,6 +426,8 @@ static void afl_request_tsl(target_ulong pc, target_ulong cb, uint32_t flags,
|
||||
uint32_t cf_mask, TranslationBlock *last_tb,
|
||||
int tb_exit) {
|
||||
|
||||
if (disable_caching) return;
|
||||
|
||||
struct afl_tsl t;
|
||||
struct afl_chain c;
|
||||
|
||||
@ -451,24 +457,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. */
|
||||
|
||||
|
223
qemu_mode/patches/afl-qemu-floats.h
Normal file
223
qemu_mode/patches/afl-qemu-floats.h
Normal file
@ -0,0 +1,223 @@
|
||||
/*
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -42,10 +42,15 @@ void tcg_gen_afl_maybe_log_call(target_ulong cur_loc) {
|
||||
unsigned sizemask, flags;
|
||||
TCGOp * op;
|
||||
|
||||
#if TARGET_LONG_BITS == 64
|
||||
TCGTemp *arg = tcgv_i64_temp(tcg_const_tl(cur_loc));
|
||||
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1);
|
||||
#else
|
||||
TCGTemp *arg = tcgv_i32_temp(tcg_const_tl(cur_loc));
|
||||
sizemask = dh_sizemask(void, 0) | dh_sizemask(i32, 1);
|
||||
#endif
|
||||
|
||||
flags = 0;
|
||||
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1);
|
||||
|
||||
#if defined(__sparc__) && !defined(__arch64__) && \
|
||||
!defined(CONFIG_TCG_INTERPRETER)
|
||||
@ -371,20 +376,27 @@ void tcg_gen_afl_call0(void *func) {
|
||||
|
||||
}
|
||||
|
||||
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc,
|
||||
TCGv_i64 arg1, TCGv_i64 arg2) {
|
||||
void tcg_gen_afl_compcov_log_call(void *func, target_ulong cur_loc, TCGv arg1,
|
||||
TCGv arg2) {
|
||||
|
||||
int i, real_args, nb_rets, pi;
|
||||
unsigned sizemask, flags;
|
||||
TCGOp * op;
|
||||
|
||||
const int nargs = 3;
|
||||
#if TARGET_LONG_BITS == 64
|
||||
TCGTemp *args[3] = {tcgv_i64_temp(tcg_const_tl(cur_loc)), tcgv_i64_temp(arg1),
|
||||
tcgv_i64_temp(arg2)};
|
||||
|
||||
flags = 0;
|
||||
sizemask = dh_sizemask(void, 0) | dh_sizemask(i64, 1) | dh_sizemask(i64, 2) |
|
||||
dh_sizemask(i64, 3);
|
||||
#else
|
||||
TCGTemp *args[3] = {tcgv_i32_temp(tcg_const_tl(cur_loc)), tcgv_i32_temp(arg1),
|
||||
tcgv_i32_temp(arg2)};
|
||||
sizemask = dh_sizemask(void, 0) | dh_sizemask(i32, 1) | dh_sizemask(i32, 2) |
|
||||
dh_sizemask(i32, 3);
|
||||
#endif
|
||||
|
||||
flags = 0;
|
||||
|
||||
#if defined(__sparc__) && !defined(__arch64__) && \
|
||||
!defined(CONFIG_TCG_INTERPRETER)
|
||||
|
54
qemu_mode/patches/i386-fpu_helper.diff
Normal file
54
qemu_mode/patches/i386-fpu_helper.diff
Normal 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];
|
61
qemu_mode/patches/i386-ops_sse.diff
Normal file
61
qemu_mode/patches/i386-ops_sse.diff
Normal 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];
|
||||
}
|
10
qemu_mode/patches/softfloat.diff
Normal file
10
qemu_mode/patches/softfloat.diff
Normal 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"
|
@ -18,7 +18,7 @@ ifndef AFL_NO_X86
|
||||
all: lib_i386 lib_amd64
|
||||
|
||||
lib_i386:
|
||||
$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so
|
||||
@$(CC) -m32 -fPIC -shared unsigaction.c -o unsigaction32.so 2>/dev/null ; if [ "$$?" = "0" ]; then echo "unsigaction32 build success"; else echo "unsigaction32 build failure (that's fine)"; fi
|
||||
|
||||
lib_amd64:
|
||||
$(CC) -fPIC -shared unsigaction.c -o unsigaction64.so
|
||||
|
@ -75,13 +75,15 @@ static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
||||
|
||||
static s32 dev_null_fd = -1; /* FD to /dev/null */
|
||||
|
||||
static u8 edges_only, /* Ignore hit counts? */
|
||||
u8 edges_only, /* Ignore hit counts? */
|
||||
use_hex_offsets, /* Show hex offsets? */
|
||||
use_stdin = 1; /* Use stdin for program input? */
|
||||
|
||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
child_timed_out; /* Child timed out? */
|
||||
|
||||
static u8 qemu_mode;
|
||||
|
||||
/* Constants used for describing byte behavior. */
|
||||
|
||||
#define RESP_NONE 0x00 /* Changing byte is a no-op. */
|
||||
@ -709,8 +711,37 @@ static void set_up_environment(void) {
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -834,9 +865,8 @@ static void find_binary(u8* fname) {
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0,
|
||||
use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
char** use_argv;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
@ -987,7 +1017,8 @@ 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);
|
||||
|
||||
|
12
src/afl-as.c
12
src/afl-as.c
@ -71,7 +71,7 @@ static u32 inst_ratio = 100, /* Instrumentation probability (%) */
|
||||
instrumentation for whichever mode we were compiled with. This is not
|
||||
perfect, but should do the trick for almost all use cases. */
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
|
||||
static u8 use_64bit = 1;
|
||||
|
||||
@ -83,7 +83,7 @@ static u8 use_64bit = 0;
|
||||
#error "Sorry, 32-bit Apple platforms are not supported."
|
||||
#endif /* __APPLE__ */
|
||||
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
/* Examine and modify parameters to pass to 'as'. Note that the file name
|
||||
is always the last parameter passed by GCC, so we exploit this property
|
||||
@ -208,8 +208,12 @@ static void edit_params(int argc, char** argv) {
|
||||
NSS. */
|
||||
|
||||
if (strncmp(input_file, tmp_dir, strlen(tmp_dir)) &&
|
||||
strncmp(input_file, "/var/tmp/", 9) && strncmp(input_file, "/tmp/", 5))
|
||||
strncmp(input_file, "/var/tmp/", 9) &&
|
||||
strncmp(input_file, "/tmp/", 5) &&
|
||||
getenv("AFL_AS_FORCE_INSTRUMENT") == NULL)
|
||||
pass_thru = 1;
|
||||
else if (getenv("AFL_AS_FORCE_INSTRUMENT"))
|
||||
unsetenv("AFL_AS_FORCE_INSTRUMENT");
|
||||
|
||||
}
|
||||
|
||||
@ -499,7 +503,7 @@ 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 Michal Zalewski\n");
|
||||
|
||||
|
@ -35,7 +35,8 @@
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
u8* target_path; /* Path to target binary */
|
||||
u8* target_path; /* Path to target binary */
|
||||
extern u8 use_stdin;
|
||||
|
||||
void detect_file_args(char** argv, u8* prog_in) {
|
||||
|
||||
@ -78,6 +79,8 @@ void detect_file_args(char** argv, u8* prog_in) {
|
||||
else
|
||||
aa_subst = alloc_printf("%s/%s", cwd, prog_in);
|
||||
|
||||
use_stdin = 0;
|
||||
|
||||
/* Construct a replacement argv value. */
|
||||
|
||||
*aa_loc = 0;
|
||||
|
@ -43,6 +43,8 @@
|
||||
/* a program that includes afl-forkserver needs to define these */
|
||||
extern u8 uses_asan;
|
||||
extern u8 *trace_bits;
|
||||
extern u8 use_stdin;
|
||||
|
||||
extern s32 forksrv_pid, child_pid, fsrv_ctl_fd, fsrv_st_fd;
|
||||
extern s32 out_fd, out_dir_fd, dev_null_fd; /* initialize these with -1 */
|
||||
#ifndef HAVE_ARC4RANDOM
|
||||
@ -211,7 +213,7 @@ void init_forkserver(char **argv) {
|
||||
|
||||
}
|
||||
|
||||
if (out_file) {
|
||||
if (!use_stdin) {
|
||||
|
||||
dup2(dev_null_fd, 0);
|
||||
|
||||
@ -249,6 +251,7 @@ void init_forkserver(char **argv) {
|
||||
setenv("ASAN_OPTIONS",
|
||||
"abort_on_error=1:"
|
||||
"detect_leaks=0:"
|
||||
"malloc_context_size=0:"
|
||||
"symbolize=0:"
|
||||
"allocator_may_return_null=1",
|
||||
0);
|
||||
@ -258,10 +261,11 @@ void init_forkserver(char **argv) {
|
||||
|
||||
setenv("MSAN_OPTIONS",
|
||||
"exit_code=" STRINGIFY(MSAN_ERROR) ":"
|
||||
"symbolize=0:"
|
||||
"abort_on_error=1:"
|
||||
"allocator_may_return_null=1:"
|
||||
"msan_track_origins=0",
|
||||
"symbolize=0:"
|
||||
"abort_on_error=1:"
|
||||
"malloc_context_size=0:"
|
||||
"allocator_may_return_null=1:"
|
||||
"msan_track_origins=0",
|
||||
0);
|
||||
|
||||
execv(target_path, argv);
|
||||
|
@ -73,7 +73,7 @@ void read_bitmap(u8* fname) {
|
||||
|
||||
u8 has_new_bits(u8* virgin_map) {
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
|
||||
u64* current = (u64*)trace_bits;
|
||||
u64* virgin = (u64*)virgin_map;
|
||||
@ -87,7 +87,7 @@ u8 has_new_bits(u8* virgin_map) {
|
||||
|
||||
u32 i = (MAP_SIZE >> 2);
|
||||
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
u8 ret = 0;
|
||||
|
||||
@ -107,7 +107,7 @@ u8 has_new_bits(u8* virgin_map) {
|
||||
/* Looks like we have not found any new bytes yet; see if any non-zero
|
||||
bytes in current[] are pristine in virgin[]. */
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
|
||||
if ((cur[0] && vir[0] == 0xff) || (cur[1] && vir[1] == 0xff) ||
|
||||
(cur[2] && vir[2] == 0xff) || (cur[3] && vir[3] == 0xff) ||
|
||||
@ -125,7 +125,7 @@ u8 has_new_bits(u8* virgin_map) {
|
||||
else
|
||||
ret = 1;
|
||||
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
}
|
||||
|
||||
@ -244,7 +244,7 @@ const u8 simplify_lookup[256] = {
|
||||
|
||||
};
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
|
||||
void simplify_trace(u64* mem) {
|
||||
|
||||
@ -306,7 +306,7 @@ void simplify_trace(u32* mem) {
|
||||
|
||||
}
|
||||
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
/* Destructively classify execution counts in a trace. This is used as a
|
||||
preprocessing step for any newly acquired traces. Called on every exec,
|
||||
@ -339,7 +339,7 @@ void init_count_class16(void) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
|
||||
void classify_counts(u64* mem) {
|
||||
|
||||
@ -391,7 +391,7 @@ void classify_counts(u32* mem) {
|
||||
|
||||
}
|
||||
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
/* Compact trace bytes into a smaller bitmap. We effectively just drop the
|
||||
count information here. This is called only sporadically, for some
|
||||
@ -595,11 +595,11 @@ u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) {
|
||||
|
||||
if (!dumb_mode) {
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
simplify_trace((u64*)trace_bits);
|
||||
#else
|
||||
simplify_trace((u32*)trace_bits);
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
if (!has_new_bits(virgin_tmout)) return keeping;
|
||||
|
||||
@ -658,11 +658,11 @@ u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) {
|
||||
|
||||
if (!dumb_mode) {
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
simplify_trace((u64*)trace_bits);
|
||||
#else
|
||||
simplify_trace((u32*)trace_bits);
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
if (!has_new_bits(virgin_crash)) return keeping;
|
||||
|
||||
@ -683,12 +683,17 @@ u8 save_if_interesting(char** argv, void* mem, u32 len, u8 fault) {
|
||||
#endif /* ^!SIMPLE_FILES */
|
||||
|
||||
++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
|
||||
#if !TARGET_OS_IPHONE
|
||||
// that
|
||||
if (system(infoexec) == -1)
|
||||
hnb += 0; // we dont care if system errors, but we dont want a
|
||||
// compiler warning either
|
||||
#else
|
||||
WARNF("command execution unsupported");
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
last_crash_time = get_cur_time();
|
||||
last_crash_execs = total_execs;
|
||||
|
@ -83,7 +83,10 @@ u32 hang_tmout = EXEC_TIMEOUT; /* Timeout used for hang det (ms) */
|
||||
u64 mem_limit = MEM_LIMIT; /* Memory cap for child (MB) */
|
||||
|
||||
u8 cal_cycles = CAL_CYCLES, /* Calibration cycles defaults */
|
||||
cal_cycles_long = CAL_CYCLES_LONG, debug, /* Debug mode */
|
||||
cal_cycles_long = CAL_CYCLES_LONG, /* Calibration cycles defaults */
|
||||
debug, /* Debug mode */
|
||||
no_unlink, /* do not unlink cur_input */
|
||||
use_stdin = 1, /* use stdin for sending data */
|
||||
custom_only, /* Custom mutator only mode */
|
||||
python_only; /* Python-only mode */
|
||||
|
||||
@ -95,6 +98,9 @@ char *power_names[POWER_SCHEDULES_NUM] = {"explore", "fast", "coe",
|
||||
u8 schedule = EXPLORE; /* Power schedule (default: EXPLORE)*/
|
||||
u8 havoc_max_mult = HAVOC_MAX_MULT;
|
||||
|
||||
u8 use_radamsa;
|
||||
size_t (*radamsa_mutate_ptr)(u8 *, size_t, u8 *, size_t, u32);
|
||||
|
||||
u8 skip_deterministic, /* Skip deterministic stages? */
|
||||
force_deterministic, /* Force deterministic stages? */
|
||||
use_splicing, /* Recombine input files? */
|
||||
@ -122,7 +128,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
|
||||
@ -210,6 +217,9 @@ u64 stage_finds[32], /* Patterns found per fuzz stage */
|
||||
u32 rand_cnt; /* Random number counter */
|
||||
#endif
|
||||
|
||||
u32 rand_seed[2];
|
||||
s64 init_seed;
|
||||
|
||||
u64 total_cal_us, /* Total calibration time (us) */
|
||||
total_cal_cycles; /* Total calibration cycles */
|
||||
|
||||
|
@ -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,8 +138,14 @@ void bind_to_free_cpu(void) {
|
||||
|
||||
for (i = 0; i < proccount; i++) {
|
||||
|
||||
if (procs[i].ki_oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 2)
|
||||
#if defined(__FreeBSD__)
|
||||
if (procs[i].ki_oncpu < sizeof(cpu_used) && procs[i].ki_pctcpu > 60)
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
@ -200,7 +206,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__)
|
||||
@ -212,7 +218,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__)
|
||||
@ -729,7 +735,8 @@ 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
|
||||
|
||||
@ -871,7 +878,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
|
||||
@ -1419,6 +1426,7 @@ void check_crash_handling(void) {
|
||||
until I get a box to test the code. So, for now, we check for crash
|
||||
reporting the awful way. */
|
||||
|
||||
#if !TARGET_OS_IPHONE
|
||||
if (system("launchctl list 2>/dev/null | grep -q '\\.ReportCrash$'")) return;
|
||||
|
||||
SAYF(
|
||||
@ -1436,6 +1444,7 @@ void check_crash_handling(void) {
|
||||
" launchctl unload -w ${SL}/LaunchAgents/${PL}.plist\n"
|
||||
" sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist\n");
|
||||
|
||||
#endif
|
||||
if (!getenv("AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES"))
|
||||
FATAL("Crash reporter detected");
|
||||
|
||||
@ -1557,11 +1566,12 @@ void check_cpu_governor(void) {
|
||||
" echo performance | tee cpu*/cpufreq/scaling_governor\n\n"
|
||||
|
||||
" You can later go back to the original state by replacing "
|
||||
"'performance' with\n"
|
||||
" 'ondemand'. If you don't want to change the settings, set "
|
||||
"AFL_SKIP_CPUFREQ\n"
|
||||
" to make afl-fuzz skip this check - but expect some performance "
|
||||
"drop.\n",
|
||||
"'performance'\n"
|
||||
" with 'ondemand' or 'powersave'. If you don't want to change the "
|
||||
"settings,\n"
|
||||
" set AFL_SKIP_CPUFREQ to make afl-fuzz skip this check - but expect "
|
||||
"some\n"
|
||||
" performance drop.\n",
|
||||
min / 1024, max / 1024);
|
||||
FATAL("Suboptimal CPU scaling governor");
|
||||
|
||||
@ -1605,7 +1615,8 @@ 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);
|
||||
|
||||
@ -1651,7 +1662,8 @@ 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. */
|
||||
|
||||
@ -1893,8 +1905,10 @@ void check_binary(u8* fname) {
|
||||
#else
|
||||
|
||||
#if !defined(__arm__) && !defined(__arm64__)
|
||||
if (f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED)
|
||||
FATAL("Program '%s' is not a 64-bit Mach-O binary", target_path);
|
||||
if ((f_data[0] != 0xCF || f_data[1] != 0xFA || f_data[2] != 0xED) &&
|
||||
(f_data[0] != 0xCA || f_data[1] != 0xFE || f_data[2] != 0xBA))
|
||||
FATAL("Program '%s' is not a 64-bit or universal Mach-O binary",
|
||||
target_path);
|
||||
#endif
|
||||
|
||||
#endif /* ^!__APPLE__ */
|
||||
|
@ -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);
|
||||
|
||||
@ -480,6 +480,8 @@ u8 fuzz_one_original(char** argv) {
|
||||
|
||||
if (perf_score == 0) goto abandon_entry;
|
||||
|
||||
if (use_radamsa > 1) goto radamsa_stage;
|
||||
|
||||
if (custom_mutator) {
|
||||
|
||||
stage_short = "custom";
|
||||
@ -537,23 +539,35 @@ u8 fuzz_one_original(char** argv) {
|
||||
perf_score < (queue_cur->depth * 30 <= havoc_max_mult * 100
|
||||
? queue_cur->depth * 30
|
||||
: havoc_max_mult * 100)) ||
|
||||
queue_cur->passed_det)
|
||||
queue_cur->passed_det) {
|
||||
|
||||
if (use_radamsa > 1)
|
||||
goto radamsa_stage;
|
||||
else
|
||||
#ifdef USE_PYTHON
|
||||
goto python_stage;
|
||||
goto python_stage;
|
||||
#else
|
||||
goto havoc_stage;
|
||||
goto havoc_stage;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/* Skip deterministic fuzzing if exec path checksum puts this out of scope
|
||||
for this master instance. */
|
||||
|
||||
if (master_max && (queue_cur->exec_cksum % master_max) != master_id - 1)
|
||||
if (master_max && (queue_cur->exec_cksum % master_max) != master_id - 1) {
|
||||
|
||||
if (use_radamsa > 1)
|
||||
goto radamsa_stage;
|
||||
else
|
||||
#ifdef USE_PYTHON
|
||||
goto python_stage;
|
||||
goto python_stage;
|
||||
#else
|
||||
goto havoc_stage;
|
||||
goto havoc_stage;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
doing_det = 1;
|
||||
|
||||
/*********************************************
|
||||
@ -2252,10 +2266,13 @@ retry_splicing:
|
||||
out_buf = ck_alloc_nozero(len);
|
||||
memcpy(out_buf, in_buf, len);
|
||||
|
||||
if (use_radamsa > 1)
|
||||
goto radamsa_stage;
|
||||
else
|
||||
#ifdef USE_PYTHON
|
||||
goto python_stage;
|
||||
goto python_stage;
|
||||
#else
|
||||
goto havoc_stage;
|
||||
goto havoc_stage;
|
||||
#endif
|
||||
|
||||
}
|
||||
@ -2263,7 +2280,67 @@ retry_splicing:
|
||||
#endif /* !IGNORE_FINDS */
|
||||
|
||||
ret_val = 0;
|
||||
goto radamsa_stage;
|
||||
|
||||
radamsa_stage:
|
||||
|
||||
if (!use_radamsa || !radamsa_mutate_ptr) goto abandon_entry;
|
||||
|
||||
stage_name = "radamsa";
|
||||
stage_short = "radamsa";
|
||||
stage_max = (HAVOC_CYCLES * perf_score / havoc_div / 100) << use_radamsa;
|
||||
|
||||
if (stage_max < HAVOC_MIN) stage_max = HAVOC_MIN;
|
||||
|
||||
orig_hit_cnt = queued_paths + unique_crashes;
|
||||
|
||||
/* Read the additional testcase into a new buffer. */
|
||||
u8* save_buf = ck_alloc_nozero(len);
|
||||
memcpy(save_buf, out_buf, len);
|
||||
|
||||
u32 max_len = len + choose_block_len(HAVOC_BLK_XL);
|
||||
u8* new_buf = ck_alloc_nozero(max_len);
|
||||
u8* tmp_buf;
|
||||
|
||||
for (stage_cur = 0; stage_cur < stage_max; ++stage_cur) {
|
||||
|
||||
u32 new_len =
|
||||
radamsa_mutate_ptr(save_buf, len, new_buf, max_len, get_rand_seed());
|
||||
|
||||
if (new_len) {
|
||||
|
||||
temp_len = new_len;
|
||||
tmp_buf = new_buf;
|
||||
|
||||
} else {
|
||||
|
||||
tmp_buf = save_buf; // nope but I dont care
|
||||
temp_len = len;
|
||||
|
||||
}
|
||||
|
||||
if (common_fuzz_stuff(argv, tmp_buf, temp_len)) {
|
||||
|
||||
ck_free(save_buf);
|
||||
ck_free(new_buf);
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ck_free(save_buf);
|
||||
ck_free(new_buf);
|
||||
|
||||
new_hit_cnt = queued_paths + unique_crashes;
|
||||
|
||||
stage_finds[STAGE_RADAMSA] += new_hit_cnt - orig_hit_cnt;
|
||||
stage_cycles[STAGE_RADAMSA] += stage_max;
|
||||
|
||||
ret_val = 0;
|
||||
goto abandon_entry;
|
||||
|
||||
/* we are through with this queue entry - for this iteration */
|
||||
abandon_entry:
|
||||
|
||||
splicing_with = -1;
|
||||
|
@ -35,14 +35,18 @@ int init_py() {
|
||||
|
||||
if (module_name) {
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
PyObject* py_name = PyUnicode_FromString(module_name);
|
||||
#else
|
||||
PyObject* py_name = PyString_FromString(module_name);
|
||||
#endif
|
||||
|
||||
py_module = PyImport_Import(py_name);
|
||||
Py_DECREF(py_name);
|
||||
|
||||
if (py_module != NULL) {
|
||||
|
||||
u8 py_notrim = 0;
|
||||
u8 py_notrim = 0, py_idx;
|
||||
py_functions[PY_FUNC_INIT] = PyObject_GetAttrString(py_module, "init");
|
||||
py_functions[PY_FUNC_FUZZ] = PyObject_GetAttrString(py_module, "fuzz");
|
||||
py_functions[PY_FUNC_INIT_TRIM] =
|
||||
@ -51,7 +55,7 @@ int init_py() {
|
||||
PyObject_GetAttrString(py_module, "post_trim");
|
||||
py_functions[PY_FUNC_TRIM] = PyObject_GetAttrString(py_module, "trim");
|
||||
|
||||
for (u8 py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
|
||||
for (py_idx = 0; py_idx < PY_FUNC_COUNT; ++py_idx) {
|
||||
|
||||
if (!py_functions[py_idx] || !PyCallable_Check(py_functions[py_idx])) {
|
||||
|
||||
@ -91,7 +95,12 @@ int init_py() {
|
||||
|
||||
/* Provide the init function a seed for the Python RNG */
|
||||
py_args = PyTuple_New(1);
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
py_value = PyLong_FromLong(UR(0xFFFFFFFF));
|
||||
#else
|
||||
py_value = PyInt_FromLong(UR(0xFFFFFFFF));
|
||||
#endif
|
||||
|
||||
if (!py_value) {
|
||||
|
||||
Py_DECREF(py_args);
|
||||
@ -216,7 +225,11 @@ u32 init_trim_py(char* buf, size_t buflen) {
|
||||
|
||||
if (py_value != NULL) {
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
u32 retcnt = (u32)PyLong_AsLong(py_value);
|
||||
#else
|
||||
u32 retcnt = PyInt_AsLong(py_value);
|
||||
#endif
|
||||
Py_DECREF(py_value);
|
||||
return retcnt;
|
||||
|
||||
@ -250,7 +263,11 @@ u32 post_trim_py(char success) {
|
||||
|
||||
if (py_value != NULL) {
|
||||
|
||||
#if PY_MAJOR_VERSION >= 3
|
||||
u32 retcnt = (u32)PyLong_AsLong(py_value);
|
||||
#else
|
||||
u32 retcnt = PyInt_AsLong(py_value);
|
||||
#endif
|
||||
Py_DECREF(py_value);
|
||||
return retcnt;
|
||||
|
||||
@ -328,7 +345,12 @@ u8 trim_case_python(char** argv, struct queue_entry* q, u8* in_buf) {
|
||||
fault = run_target(argv, exec_tmout);
|
||||
++trim_execs;
|
||||
|
||||
if (stop_soon || fault == FAULT_ERROR) goto abort_trimming;
|
||||
if (stop_soon || fault == FAULT_ERROR) {
|
||||
|
||||
free(retbuf);
|
||||
goto abort_trimming;
|
||||
|
||||
}
|
||||
|
||||
cksum = hash32(trace_bits, MAP_SIZE, HASH_CONST);
|
||||
|
||||
@ -364,6 +386,8 @@ u8 trim_case_python(char** argv, struct queue_entry* q, u8* in_buf) {
|
||||
|
||||
}
|
||||
|
||||
free(retbuf);
|
||||
|
||||
/* Since this can be slow, update the screen every now and then. */
|
||||
|
||||
if (!(trim_exec++ % stats_update_freq)) show_stats();
|
||||
|
@ -221,11 +221,11 @@ u8 run_target(char** argv, u32 timeout) {
|
||||
|
||||
tb4 = *(u32*)trace_bits;
|
||||
|
||||
#ifdef __x86_64__
|
||||
#ifdef WORD_SIZE_64
|
||||
classify_counts((u64*)trace_bits);
|
||||
#else
|
||||
classify_counts((u32*)trace_bits);
|
||||
#endif /* ^__x86_64__ */
|
||||
#endif /* ^WORD_SIZE_64 */
|
||||
|
||||
prev_timed_out = child_timed_out;
|
||||
|
||||
@ -288,9 +288,16 @@ void write_to_testcase(void* mem, u32 len) {
|
||||
|
||||
if (out_file) {
|
||||
|
||||
unlink(out_file); /* Ignore errors. */
|
||||
if (no_unlink) {
|
||||
|
||||
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
} else {
|
||||
|
||||
unlink(out_file); /* Ignore errors. */
|
||||
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", out_file);
|
||||
|
||||
@ -330,9 +337,16 @@ void write_with_gap(void* mem, u32 len, u32 skip_at, u32 skip_len) {
|
||||
|
||||
if (out_file) {
|
||||
|
||||
unlink(out_file); /* Ignore errors. */
|
||||
if (no_unlink) {
|
||||
|
||||
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
fd = open(out_file, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
} else {
|
||||
|
||||
unlink(out_file); /* Ignore errors. */
|
||||
fd = open(out_file, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", out_file);
|
||||
|
||||
@ -760,9 +774,16 @@ u8 trim_case(char** argv, struct queue_entry* q, u8* in_buf) {
|
||||
|
||||
s32 fd;
|
||||
|
||||
unlink(q->fname); /* ignore errors */
|
||||
if (no_unlink) {
|
||||
|
||||
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
fd = open(q->fname, O_WRONLY | O_CREAT | O_TRUNC, 0600);
|
||||
|
||||
} else {
|
||||
|
||||
unlink(q->fname); /* ignore errors */
|
||||
fd = open(q->fname, O_WRONLY | O_CREAT | O_EXCL, 0600);
|
||||
|
||||
}
|
||||
|
||||
if (fd < 0) PFATAL("Unable to create '%s'", q->fname);
|
||||
|
||||
|
@ -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");
|
||||
|
||||
@ -576,13 +576,12 @@ void show_stats(void) {
|
||||
" imported : " cRST "%-10s" bSTG bV "\n",
|
||||
tmp, sync_id ? DI(queued_imported) : (u8*)"n/a");
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s, %s/%s", DI(stage_finds[STAGE_HAVOC]),
|
||||
sprintf(tmp, "%s/%s, %s/%s, %s/%s", DI(stage_finds[STAGE_HAVOC]),
|
||||
DI(stage_cycles[STAGE_HAVOC]), DI(stage_finds[STAGE_SPLICE]),
|
||||
DI(stage_cycles[STAGE_SPLICE]), DI(stage_finds[STAGE_PYTHON]),
|
||||
DI(stage_cycles[STAGE_PYTHON]), DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
DI(stage_cycles[STAGE_SPLICE]), DI(stage_finds[STAGE_RADAMSA]),
|
||||
DI(stage_cycles[STAGE_RADAMSA]));
|
||||
|
||||
SAYF(bV bSTOP "havoc/custom : " cRST "%-36s " bSTG bV bSTOP, tmp);
|
||||
SAYF(bV bSTOP " havoc/rad : " cRST "%-36s " bSTG bV bSTOP, tmp);
|
||||
|
||||
if (t_bytes)
|
||||
sprintf(tmp, "%0.02f%%", stab_ratio);
|
||||
@ -597,6 +596,13 @@ void show_stats(void) {
|
||||
: cRST),
|
||||
tmp);
|
||||
|
||||
sprintf(tmp, "%s/%s, %s/%s", DI(stage_finds[STAGE_PYTHON]),
|
||||
DI(stage_cycles[STAGE_PYTHON]), DI(stage_finds[STAGE_CUSTOM_MUTATOR]),
|
||||
DI(stage_cycles[STAGE_CUSTOM_MUTATOR]));
|
||||
|
||||
SAYF(bV bSTOP " py/custom : " cRST "%-36s " bSTG bVR bH20 bH2 bH bRB "\n",
|
||||
tmp);
|
||||
|
||||
if (!bytes_trim_out) {
|
||||
|
||||
sprintf(tmp, "n/a, ");
|
||||
@ -632,15 +638,11 @@ 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,
|
||||
tmp);
|
||||
SAYF(bV bSTOP " custom mut. : " cRST "%-36s " bSTG bV 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,
|
||||
tmp);
|
||||
SAYF(bV bSTOP " trim : " cRST "%-36s " bSTG bV RESET_G1, tmp);
|
||||
|
||||
}
|
||||
|
||||
@ -687,6 +689,9 @@ void show_stats(void) {
|
||||
|
||||
SAYF("\r");
|
||||
|
||||
/* Last line */
|
||||
SAYF(SET_G1 "\n" bSTG bLB bH30 bH20 bH2 bRB bSTOP cRST RESET_G1);
|
||||
|
||||
/* Hallelujah! */
|
||||
|
||||
fflush(0);
|
||||
|
182
src/afl-fuzz.c
182
src/afl-fuzz.c
@ -25,6 +25,61 @@
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
static u8* get_libradamsa_path(u8* own_loc) {
|
||||
|
||||
u8 *tmp, *cp, *rsl, *own_copy;
|
||||
|
||||
tmp = getenv("AFL_PATH");
|
||||
|
||||
if (tmp) {
|
||||
|
||||
cp = alloc_printf("%s/libradamsa.so", tmp);
|
||||
|
||||
if (access(cp, X_OK)) FATAL("Unable to find '%s'", cp);
|
||||
|
||||
return cp;
|
||||
|
||||
}
|
||||
|
||||
own_copy = ck_strdup(own_loc);
|
||||
rsl = strrchr(own_copy, '/');
|
||||
|
||||
if (rsl) {
|
||||
|
||||
*rsl = 0;
|
||||
|
||||
cp = alloc_printf("%s/libradamsa.so", own_copy);
|
||||
ck_free(own_copy);
|
||||
|
||||
if (!access(cp, X_OK)) return cp;
|
||||
|
||||
} else
|
||||
|
||||
ck_free(own_copy);
|
||||
|
||||
if (!access(AFL_PATH "/libradamsa.so", X_OK)) {
|
||||
|
||||
return ck_strdup(AFL_PATH "/libradamsa.so");
|
||||
|
||||
}
|
||||
|
||||
if (!access(BIN_PATH "/libradamsa.so", X_OK)) {
|
||||
|
||||
return ck_strdup(BIN_PATH "/libradamsa.so");
|
||||
|
||||
}
|
||||
|
||||
SAYF(
|
||||
"\n" cLRD "[-] " cRST
|
||||
"Oops, unable to find the 'libradamsa.so' binary. The binary must be "
|
||||
"built\n"
|
||||
" separately using 'make radamsa'. If you already have the binary "
|
||||
"installed,\n you may need to specify AFL_PATH in the environment.\n");
|
||||
|
||||
FATAL("Failed to locate 'libradamsa.so'.");
|
||||
|
||||
}
|
||||
|
||||
/* Display usage hints. */
|
||||
|
||||
static void usage(u8* argv0) {
|
||||
@ -54,7 +109,12 @@ static void usage(u8* argv0) {
|
||||
" -m megs - memory limit for child process (%d MB)\n"
|
||||
" -Q - use binary-only instrumentation (QEMU mode)\n"
|
||||
" -U - use unicorn-based instrumentation (Unicorn mode)\n"
|
||||
" -W - use qemu-based instrumentation with Wine (Wine mode)\n"
|
||||
" -W - use qemu-based instrumentation with Wine (Wine "
|
||||
"mode)\n\n"
|
||||
|
||||
"Mutator settings:\n"
|
||||
" -R[R] - add Radamsa as mutator, add another -R to exclusivly "
|
||||
"run it\n"
|
||||
" -L minutes - use MOpt(imize) mode and set the limit time for "
|
||||
"entering the\n"
|
||||
" pacemaker mode (minutes of no new paths, 0 = "
|
||||
@ -62,16 +122,20 @@ static void usage(u8* argv0) {
|
||||
" a recommended value is 10-60. see docs/README.MOpt\n\n"
|
||||
|
||||
"Fuzzing behavior settings:\n"
|
||||
" -N - do not unlink the fuzzing input file\n"
|
||||
" -d - quick & dirty mode (skips deterministic steps)\n"
|
||||
" -n - fuzz without instrumentation (dumb mode)\n"
|
||||
" -x dir - optional fuzzer dictionary (see README)\n\n"
|
||||
" -x dir - optional fuzzer dictionary (see README, its really "
|
||||
"good!)\n\n"
|
||||
|
||||
"Testing settings:\n"
|
||||
" -s seed - use a fixed seed for the RNG\n"
|
||||
" -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"
|
||||
@ -120,14 +184,12 @@ int main(int argc, char** argv) {
|
||||
u8 mem_limit_given = 0;
|
||||
u8 exit_1 = !!getenv("AFL_BENCH_JUST_ONE");
|
||||
char** use_argv;
|
||||
s64 init_seed;
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
|
||||
SAYF(cCYA
|
||||
"afl-fuzz" VERSION cRST
|
||||
" based on afl by Michal Zalewski and a big online community\n");
|
||||
SAYF(cCYA "afl-fuzz" VERSION cRST
|
||||
" based on afl by Michal Zalewski and a big online community\n");
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
||||
@ -135,7 +197,7 @@ int main(int argc, char** argv) {
|
||||
init_seed = tv.tv_sec ^ tv.tv_usec ^ getpid();
|
||||
|
||||
while ((opt = getopt(argc, argv,
|
||||
"+i:I:o:f:m:t:T:dnCB:S:M:x:QUWe:p:s:V:E:L:h")) > 0)
|
||||
"+i:I:o:f:m:t:T:dnCB:S:M:x:QNUWe:p:s:V:E:L:hR")) > 0)
|
||||
|
||||
switch (opt) {
|
||||
|
||||
@ -242,6 +304,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (out_file) FATAL("Multiple -f options not supported");
|
||||
out_file = optarg;
|
||||
use_stdin = 0;
|
||||
break;
|
||||
|
||||
case 'x': /* dictionary */
|
||||
@ -366,6 +429,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
break;
|
||||
|
||||
case 'N': /* Unicorn mode */
|
||||
|
||||
if (no_unlink) FATAL("Multiple -N options not supported");
|
||||
no_unlink = 1;
|
||||
|
||||
break;
|
||||
|
||||
case 'U': /* Unicorn mode */
|
||||
|
||||
if (unicorn_mode) FATAL("Multiple -U options not supported");
|
||||
@ -510,14 +580,56 @@ int main(int argc, char** argv) {
|
||||
return -1;
|
||||
break; // not needed
|
||||
|
||||
case 'R':
|
||||
|
||||
if (use_radamsa)
|
||||
use_radamsa = 2;
|
||||
else
|
||||
use_radamsa = 1;
|
||||
|
||||
break;
|
||||
|
||||
default: usage(argv[0]);
|
||||
|
||||
}
|
||||
|
||||
if (optind == argc || !in_dir || !out_dir) usage(argv[0]);
|
||||
|
||||
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
|
||||
"Eissfeldt and Andrea Fioraldi");
|
||||
OKF("afl++ is open source, get it at "
|
||||
"https://github.com/vanhauser-thc/AFLplusplus");
|
||||
OKF("Power schedules from github.com/mboehme/aflfast");
|
||||
OKF("Python Mutator and llvm_mode whitelisting from github.com/choller/afl");
|
||||
OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL");
|
||||
OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL");
|
||||
|
||||
if (fixed_seed) OKF("Running with fixed seed: %u", (u32)init_seed);
|
||||
srandom((u32)init_seed);
|
||||
|
||||
if (use_radamsa) {
|
||||
|
||||
OKF("Using Radamsa add-on");
|
||||
|
||||
u8* libradamsa_path = get_libradamsa_path(argv[0]);
|
||||
void* handle = dlopen(libradamsa_path, RTLD_NOW);
|
||||
ck_free(libradamsa_path);
|
||||
|
||||
if (!handle) FATAL("Failed to dlopen() libradamsa");
|
||||
|
||||
void (*radamsa_init_ptr)(void) = dlsym(handle, "radamsa_init");
|
||||
radamsa_mutate_ptr = dlsym(handle, "radamsa");
|
||||
|
||||
if (!radamsa_init_ptr || !radamsa_mutate_ptr)
|
||||
FATAL("Failed to dlsym() libradamsa");
|
||||
|
||||
/* randamsa_init installs some signal hadlers, call it before
|
||||
setup_signal_handlers so that AFL++ can then replace those signal
|
||||
handlers */
|
||||
radamsa_init_ptr();
|
||||
|
||||
}
|
||||
|
||||
setup_signal_handlers();
|
||||
check_asan_opts();
|
||||
|
||||
@ -549,23 +661,17 @@ 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",
|
||||
argv[optind]);
|
||||
|
||||
OKF("afl++ is maintained by Marc \"van Hauser\" Heuse, Heiko \"hexcoder\" "
|
||||
"Eissfeldt and Andrea Fioraldi");
|
||||
OKF("afl++ is open source, get it at "
|
||||
"https://github.com/vanhauser-thc/AFLplusplus");
|
||||
OKF("Power schedules from github.com/mboehme/aflfast");
|
||||
OKF("Python Mutator and llvm_mode whitelisting from github.com/choller/afl");
|
||||
OKF("afl-tmin fork server patch from github.com/nccgroup/TriforceAFL");
|
||||
OKF("MOpt Mutator from github.com/puppet-meteor/MOpt-AFL");
|
||||
ACTF("Getting to work...");
|
||||
|
||||
switch (schedule) {
|
||||
@ -600,10 +706,44 @@ int main(int argc, char** argv) {
|
||||
if (dumb_mode == 2 && no_forkserver)
|
||||
FATAL("AFL_DUMB_FORKSRV and AFL_NO_FORKSRV are mutually exclusive");
|
||||
|
||||
if (getenv("LD_PRELOAD"))
|
||||
WARNF(
|
||||
"LD_PRELOAD is set, are you sure that is want to you want to do "
|
||||
"instead of using AFL_PRELOAD?");
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -697,6 +837,8 @@ int main(int argc, char** argv) {
|
||||
|
||||
if (aa_loc && !out_file) {
|
||||
|
||||
use_stdin = 0;
|
||||
|
||||
if (file_extension) {
|
||||
|
||||
out_file = alloc_printf("%s/.cur_input.%s", out_dir, file_extension);
|
||||
@ -744,6 +886,7 @@ int main(int argc, char** argv) {
|
||||
seek_to = find_start_position();
|
||||
|
||||
write_stats_file(0, 0, 0);
|
||||
maybe_update_plot_file(0, 0);
|
||||
save_auto();
|
||||
|
||||
if (stop_soon) goto stop_fuzzing;
|
||||
@ -876,6 +1019,7 @@ int main(int argc, char** argv) {
|
||||
|
||||
write_bitmap();
|
||||
write_stats_file(0, 0, 0);
|
||||
maybe_update_plot_file(0, 0);
|
||||
save_auto();
|
||||
|
||||
stop_fuzzing:
|
||||
|
@ -121,7 +121,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
u8 fortify_set = 0, asan_set = 0;
|
||||
u8* name;
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__x86_64__)
|
||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
||||
u8 m32_set = 0;
|
||||
#endif
|
||||
|
||||
@ -228,7 +228,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
if (!strcmp(cur, "-pipe")) continue;
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__x86_64__)
|
||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
||||
if (!strcmp(cur, "-m32")) m32_set = 1;
|
||||
#endif
|
||||
|
||||
@ -288,7 +288,7 @@ static void edit_params(u32 argc, char** argv) {
|
||||
|
||||
if (!getenv("AFL_DONT_OPTIMIZE")) {
|
||||
|
||||
#if defined(__FreeBSD__) && defined(__x86_64__)
|
||||
#if defined(__FreeBSD__) && defined(WORD_SIZE_64)
|
||||
|
||||
/* On 64-bit FreeBSD systems, clang -g -m32 is broken, but -m32 itself
|
||||
works OK. This has nothing to do with us, but let's avoid triggering
|
||||
@ -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";
|
||||
|
||||
|
@ -52,12 +52,15 @@
|
||||
#include "types.h"
|
||||
#include "debug.h"
|
||||
|
||||
#if defined(__linux__) || defined(__FreeBSD__) || defined(__NetBSD__) || defined(__APPLE__)
|
||||
#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>
|
||||
@ -67,7 +70,7 @@
|
||||
#include <mach/thread_act.h>
|
||||
#include <mach/thread_policy.h>
|
||||
#endif
|
||||
#endif /* __linux__ || __FreeBSD__ || __NetBSD__ || __APPLE__ */
|
||||
#endif /* __linux__ || __FreeBSD__ || __NetBSD__ || __APPLE__ */
|
||||
|
||||
/* Get unix time in microseconds. */
|
||||
|
||||
@ -168,7 +171,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);
|
||||
@ -181,14 +184,14 @@ int main(int argc, char** argv) {
|
||||
|
||||
cpuset_set(i, c);
|
||||
#elif defined(__APPLE__)
|
||||
thread_affinity_policy_data_t c = { i };
|
||||
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");
|
||||
(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
|
||||
@ -202,14 +205,14 @@ int main(int argc, char** argv) {
|
||||
|
||||
#if defined(__linux__)
|
||||
if (sched_setaffinity(0, sizeof(c), &c))
|
||||
PFATAL("sched_setaffinity failed");
|
||||
PFATAL("sched_setaffinity failed for cpu %d", i);
|
||||
#endif
|
||||
|
||||
util_perc = measure_preemption(CTEST_CORE_TRG_MS);
|
||||
|
||||
if (util_perc < 110) {
|
||||
|
||||
SAYF(" Core #%u: " cLGN "AVAILABLE\n" cRST, i);
|
||||
SAYF(" Core #%u: " cLGN "AVAILABLE" cRST "(%u%%)\n", i, util_perc);
|
||||
exit(0);
|
||||
|
||||
} else if (util_perc < 250) {
|
||||
|
@ -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
|
||||
|
@ -72,17 +72,20 @@ static u32 total, highest; /* tuple content information */
|
||||
|
||||
static u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
||||
|
||||
static u8 quiet_mode, /* Hide non-essential messages? */
|
||||
u8 quiet_mode, /* Hide non-essential messages? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
raw_instr_output, /* Do not apply AFL filters */
|
||||
cmin_mode, /* Generate output in afl-cmin mode? */
|
||||
binary_mode, /* Write output as a binary map */
|
||||
use_stdin = 1, /* use stdin - unused here */
|
||||
keep_cores; /* Allow coredumps? */
|
||||
|
||||
static volatile u8 stop_soon, /* Ctrl-C pressed? */
|
||||
child_timed_out, /* Child timed out? */
|
||||
child_crashed; /* Child crashed? */
|
||||
|
||||
static u8 qemu_mode;
|
||||
|
||||
/* Classify tuple counts. Instead of mapping to individual bits, as in
|
||||
afl-fuzz.c, we map to more user-friendly numbers between 1 and 8. */
|
||||
|
||||
@ -358,8 +361,37 @@ static void set_up_environment(void) {
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -497,15 +529,14 @@ static void find_binary(u8* fname) {
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0,
|
||||
use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
u32 tcnt = 0;
|
||||
char** use_argv;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
||||
while ((opt = getopt(argc, argv, "+o:m:t:A:eqZQUWbcrh")) > 0)
|
||||
while ((opt = getopt(argc, argv, "+o:f:m:t:A:eqZQUWbcrh")) > 0)
|
||||
|
||||
switch (opt) {
|
||||
|
||||
@ -553,6 +584,13 @@ int main(int argc, char** argv) {
|
||||
|
||||
break;
|
||||
|
||||
case 'f': // only in here to avoid a compiler warning for use_stdin
|
||||
|
||||
use_stdin = 0;
|
||||
FATAL("Option -f is not supported in afl-showmap");
|
||||
|
||||
break;
|
||||
|
||||
case 't':
|
||||
|
||||
if (timeout_given) FATAL("Multiple -t options not supported");
|
||||
|
@ -88,7 +88,7 @@ u64 mem_limit = MEM_LIMIT; /* Memory limit (MB) */
|
||||
|
||||
s32 dev_null_fd = -1; /* FD to /dev/null */
|
||||
|
||||
static u8 crash_mode, /* Crash-centric mode? */
|
||||
u8 crash_mode, /* Crash-centric mode? */
|
||||
exit_crash, /* Treat non-zero exit as crash? */
|
||||
edges_only, /* Ignore hit counts? */
|
||||
exact_mode, /* Require path match for crashes? */
|
||||
@ -96,6 +96,8 @@ static u8 crash_mode, /* Crash-centric mode? */
|
||||
|
||||
static volatile u8 stop_soon; /* Ctrl-C pressed? */
|
||||
|
||||
static u8 qemu_mode;
|
||||
|
||||
/*
|
||||
* forkserver section
|
||||
*/
|
||||
@ -882,8 +884,37 @@ static void set_up_environment(void) {
|
||||
|
||||
if (getenv("AFL_PRELOAD")) {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
if (qemu_mode) {
|
||||
|
||||
u8* qemu_preload = getenv("QEMU_SET_ENV");
|
||||
u8* afl_preload = getenv("AFL_PRELOAD");
|
||||
u8* buf;
|
||||
|
||||
s32 i, afl_preload_size = strlen(afl_preload);
|
||||
for (i = 0; i < afl_preload_size; ++i) {
|
||||
|
||||
if (afl_preload[i] == ',')
|
||||
PFATAL(
|
||||
"Comma (',') is not allowed in AFL_PRELOAD when -Q is "
|
||||
"specified!");
|
||||
|
||||
}
|
||||
|
||||
if (qemu_preload)
|
||||
buf = alloc_printf("%s,LD_PRELOAD=%s", qemu_preload, afl_preload);
|
||||
else
|
||||
buf = alloc_printf("LD_PRELOAD=%s", afl_preload);
|
||||
|
||||
setenv("QEMU_SET_ENV", buf, 1);
|
||||
|
||||
ck_free(buf);
|
||||
|
||||
} else {
|
||||
|
||||
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
|
||||
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -1025,9 +1056,8 @@ static void read_bitmap(u8* fname) {
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, qemu_mode = 0, unicorn_mode = 0,
|
||||
use_wine = 0;
|
||||
s32 opt;
|
||||
u8 mem_limit_given = 0, timeout_given = 0, unicorn_mode = 0, use_wine = 0;
|
||||
char** use_argv;
|
||||
|
||||
doc_path = access(DOC_PATH, F_OK) ? "docs" : DOC_PATH;
|
||||
|
3
src/third_party/libradamsa/.gitignore
vendored
Normal file
3
src/third_party/libradamsa/.gitignore
vendored
Normal file
@ -0,0 +1,3 @@
|
||||
*.a
|
||||
*.o
|
||||
libradamsa-test
|
19
src/third_party/libradamsa/LICENSE
vendored
Normal file
19
src/third_party/libradamsa/LICENSE
vendored
Normal file
@ -0,0 +1,19 @@
|
||||
Copyright (c) 2013 Aki Helin
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
20
src/third_party/libradamsa/Makefile
vendored
Normal file
20
src/third_party/libradamsa/Makefile
vendored
Normal file
@ -0,0 +1,20 @@
|
||||
CUR_DIR := $(shell dirname $(realpath $(lastword $(MAKEFILE_LIST))))
|
||||
|
||||
all: libradamsa.so
|
||||
|
||||
libradamsa.so: libradamsa.a
|
||||
$(CC) -O3 -shared libradamsa.a -o libradamsa.so
|
||||
|
||||
libradamsa.a: libradamsa.c radamsa.h
|
||||
@echo " ***************************************************************"
|
||||
@echo " * Compiling libradamsa, wait some minutes (~3 on modern CPUs) *"
|
||||
@echo " ***************************************************************"
|
||||
$(CC) -fPIC -O3 -I $(CUR_DIR) -o libradamsa.a -c libradamsa.c
|
||||
|
||||
test: libradamsa.a libradamsa-test.c
|
||||
cc -O3 -I $(CUR_DIR) -o libradamsa-test libradamsa-test.c libradamsa.a
|
||||
./libradamsa-test libradamsa-test.c | grep "library test passed"
|
||||
rm /tmp/libradamsa-*.fuzz
|
||||
|
||||
clean:
|
||||
rm -f libradamsa.a libradamsa.so libradamsa-test
|
9
src/third_party/libradamsa/README.md
vendored
Normal file
9
src/third_party/libradamsa/README.md
vendored
Normal file
@ -0,0 +1,9 @@
|
||||
# libradamsa
|
||||
|
||||
Pretranslated radamsa library. This code belongs to the radamsa author.
|
||||
|
||||
> Original repository: https://gitlab.com/akihe/radamsa
|
||||
|
||||
> Source commit: 7b2cc2d0
|
||||
|
||||
> The code here is adapted for AFL++ with minor changes respect the original version
|
75
src/third_party/libradamsa/libradamsa-test.c
vendored
Normal file
75
src/third_party/libradamsa/libradamsa-test.c
vendored
Normal file
@ -0,0 +1,75 @@
|
||||
#include <radamsa.h>
|
||||
#include <stdio.h>
|
||||
#include <inttypes.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
size_t filesize(char* filename) {
|
||||
struct stat st;
|
||||
stat(filename, &st);
|
||||
return st.st_size;
|
||||
}
|
||||
|
||||
#define BUFSIZE 1024*1024
|
||||
|
||||
void fail(char *why) {
|
||||
printf("fail: %s\n", why);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void write_output(char *data, size_t len, int num) {
|
||||
char path[32];
|
||||
int fd;
|
||||
int wrote;
|
||||
sprintf(path, "/tmp/libradamsa-%d.fuzz", num);
|
||||
fd = open(path, O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);
|
||||
printf("Opened %s -> %d\n", path, fd);
|
||||
if (fd < 0) {
|
||||
fail("failed to open output file");
|
||||
}
|
||||
wrote = write(fd, data, len);
|
||||
printf("wrote %d of %zu bytes\n", wrote, len);
|
||||
if (wrote != len) {
|
||||
fail("failed to write all of output at once");
|
||||
}
|
||||
close(fd);
|
||||
printf("Wrote %zu bytes to %s\n", len, path);
|
||||
}
|
||||
|
||||
int main(int nargs, char **argv) {
|
||||
char *spath = argv[1];
|
||||
int fd = open(spath, O_RDONLY, 0);
|
||||
size_t len;
|
||||
char *input;
|
||||
char *output;
|
||||
int seed = 0;
|
||||
if (fd < 0) {
|
||||
fail("cannot open input file");
|
||||
}
|
||||
len = filesize(spath);
|
||||
input = malloc(len);
|
||||
output = malloc(BUFSIZE);
|
||||
if (!input || !output) {
|
||||
fail("failed to allocate buffers\n");
|
||||
}
|
||||
init();
|
||||
if (len != read(fd, input, len)) {
|
||||
fail("failed to read the entire sample at once");
|
||||
}
|
||||
while(seed++ < 100) {
|
||||
size_t n;
|
||||
n = radamsa((uint8_t *) input, len, (uint8_t *) output, BUFSIZE, seed);
|
||||
write_output(output, n, seed);
|
||||
printf("Fuzzed %zu -> %zu bytes\n", len, n);
|
||||
}
|
||||
printf("library test passed\n");
|
||||
free(output);
|
||||
free(input);
|
||||
return 0;
|
||||
}
|
||||
|
30840
src/third_party/libradamsa/libradamsa.c
vendored
Normal file
30840
src/third_party/libradamsa/libradamsa.c
vendored
Normal file
File diff suppressed because it is too large
Load Diff
15
src/third_party/libradamsa/radamsa.h
vendored
Normal file
15
src/third_party/libradamsa/radamsa.h
vendored
Normal file
@ -0,0 +1,15 @@
|
||||
#include <inttypes.h>
|
||||
#include <stddef.h>
|
||||
|
||||
extern void radamsa_init();
|
||||
|
||||
extern size_t radamsa(uint8_t *ptr, size_t len,
|
||||
uint8_t *target, size_t max,
|
||||
unsigned int seed);
|
||||
|
||||
extern size_t radamsa_inplace(uint8_t *ptr,
|
||||
size_t len,
|
||||
size_t max,
|
||||
unsigned int seed);
|
||||
|
||||
|
@ -27,6 +27,7 @@ int main(int argc, char** argv) {
|
||||
if (argc > 1) {
|
||||
|
||||
buf = argv[1];
|
||||
printf("Input %s - ", buf);
|
||||
|
||||
} else if (read(0, buf, sizeof(buf)) < 1) {
|
||||
|
||||
|
@ -1,6 +1,10 @@
|
||||
#!/bin/bash
|
||||
|
||||
FILE=~/.afl_performance
|
||||
# if you want a specific performance file (e.g. to compare features to another)
|
||||
# you can set the AFL_PERFORMANCE_FILE environment variable:
|
||||
FILE=$AFL_PERFORMANCE_FILE
|
||||
# otherwise we use ~/.afl_performance
|
||||
test -z "$FILE" && FILE=~/.afl_performance
|
||||
|
||||
test -e $FILE || {
|
||||
echo Warning: This script measure the performance of afl++ and saves the result for future comparisons into $FILE
|
||||
@ -17,6 +21,7 @@ unset AFL_USE_ASAN
|
||||
unset AFL_USE_MSAN
|
||||
unset AFL_CC
|
||||
unset AFL_PRELOAD
|
||||
unset AFL_GCC_WHITELIST
|
||||
unset AFL_LLVM_WHITELIST
|
||||
unset AFL_LLVM_INSTRIM
|
||||
unset AFL_LLVM_LAF_SPLIT_SWITCHES
|
||||
|
392
test/test.sh
392
test/test.sh
@ -24,8 +24,12 @@ $ECHO \\101 2>&1 | grep -qE '^A' || {
|
||||
}
|
||||
test -z "$ECHO" && { printf Error: printf command does not support octal character codes ; exit 1 ; }
|
||||
|
||||
CODE=0
|
||||
INCOMPLETE=0
|
||||
|
||||
export AFL_EXIT_WHEN_DONE=1
|
||||
export AFL_SKIP_CPUFREQ=1
|
||||
export AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
|
||||
unset AFL_QUIET
|
||||
unset AFL_DEBUG
|
||||
unset AFL_HARDEN
|
||||
@ -33,6 +37,7 @@ unset AFL_USE_ASAN
|
||||
unset AFL_USE_MSAN
|
||||
unset AFL_CC
|
||||
unset AFL_PRELOAD
|
||||
unset AFL_GCC_WHITELIST
|
||||
unset AFL_LLVM_WHITELIST
|
||||
unset AFL_LLVM_INSTRIM
|
||||
unset AFL_LLVM_LAF_SPLIT_SWITCHES
|
||||
@ -50,6 +55,7 @@ test `uname -s` = 'Darwin' -o `uname -s` = 'FreeBSD' && {
|
||||
} || {
|
||||
AFL_GCC=afl-gcc
|
||||
}
|
||||
SYS=`uname -m`
|
||||
|
||||
GREY="\\033[1;90m"
|
||||
BLUE="\\033[1;94m"
|
||||
@ -60,10 +66,15 @@ RESET="\\033[0m"
|
||||
|
||||
MEM_LIMIT=150
|
||||
|
||||
export PATH=$PATH:/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/usr/local/bin
|
||||
|
||||
$ECHO "${RESET}${GREY}[*] starting afl++ test framework ..."
|
||||
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap and afl-fuzz"
|
||||
test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
test -z "$SYS" && $ECHO "$YELLOW[-] uname -m did not succeed"
|
||||
|
||||
$ECHO "$BLUE[*] Testing: ${AFL_GCC}, afl-showmap, afl-fuzz, afl-cmin and afl-tmin"
|
||||
test "$SYS" = "i686" -o "$SYS" = "x86_64" -o "$SYS" = "amd64" && {
|
||||
test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
../${AFL_GCC} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
AFL_HARDEN=1 ../${AFL_GCC} -o test-compcov.harden test-compcov.c > /dev/null 2>&1
|
||||
test -e test-instr.plain && {
|
||||
@ -73,20 +84,46 @@ test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
test -e test-instr.plain.0 -a -e test-instr.plain.1 && {
|
||||
diff -q test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] ${AFL_GCC} instrumentation should be different on different input but is not"
|
||||
} || $ECHO "$GREEN[+] ${AFL_GCC} instrumentation present and working correctly"
|
||||
} || $ECHO "$RED[!] ${AFL_GCC} instrumentation failed"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} instrumentation present and working correctly"
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-instr.plain.0 test-instr.plain.1
|
||||
} || $ECHO "$RED[!] ${AFL_GCC} failed"
|
||||
TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} run reported $TUPLES instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} produces weird instrumentation numbers: $TUPLES"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} failed"
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
uname -a
|
||||
../${AFL_GCC} -o test-instr.plain ../test-instr.c
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
CODE=1
|
||||
}
|
||||
test -e test-compcov.harden && {
|
||||
grep -Eqa 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] ${AFL_GCC} hardened mode succeeded and is working"
|
||||
} || $ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} hardened mode is not hardened"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden
|
||||
} || $ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] ${AFL_GCC} hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
# make sure core_pattern is set to core on linux
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$RED[!] we cannot run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) ||
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
@ -107,14 +144,37 @@ test -e ../${AFL_GCC} -a -e ../afl-showmap -a -e ../afl-fuzz && {
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with ${AFL_GCC}"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors
|
||||
echo 000000000000000000000000 > in/in2
|
||||
mkdir -p in2
|
||||
../afl-cmin -i in -o in2 -- ./test-instr.plain > /dev/null 2>&1
|
||||
CNT=`ls in2/ | wc -l`
|
||||
test "$CNT" = 1 && $ECHO "$GREEN[+] afl-cmin correctly minimized testcase numbers"
|
||||
test "$CNT" = 1 || {
|
||||
$ECHO "$RED[!] afl-cmin did not correctly minimize testcase numbers"
|
||||
CODE=1
|
||||
}
|
||||
../afl-tmin -i in/in2 -o in2/in2 -- ./test-instr.plain > /dev/null 2>&1
|
||||
SIZE=`ls -l in2/in2 2> /dev/null | awk '{print$5}'`
|
||||
test "$SIZE" = 1 && $ECHO "$GREEN[+] afl-tmin correctly minimized the testcase"
|
||||
test "$SIZE" = 1 || {
|
||||
$ECHO "$RED[!] afl-tmin did incorrectly minimize the testcase to $SIZE"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors in2
|
||||
}
|
||||
rm -f test-instr.plain
|
||||
} || $ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] afl is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] not an intel platform, cannot test afl-gcc"
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: llvm_mode"
|
||||
test -e ../afl-clang-fast && {
|
||||
test -e ../afl-clang-fast -a -e ../split-switches-pass.so && {
|
||||
# on FreeBSD need to set AFL_CC
|
||||
if which clang >/dev/null; then
|
||||
export AFL_CC=`which clang`
|
||||
@ -130,24 +190,47 @@ test -e ../afl-clang-fast && {
|
||||
test -e test-instr.plain.0 -a -e test-instr.plain.1 && {
|
||||
diff -q test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] llvm_mode instrumentation should be different on different input but is not"
|
||||
} || $ECHO "$GREEN[+] llvm_mode instrumentation present and working correctly"
|
||||
} || $ECHO "$RED[!] llvm_mode instrumentation failed"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] llvm_mode instrumentation present and working correctly"
|
||||
TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 3 -a "$TUPLES" -lt 6 && {
|
||||
$ECHO "$GREEN[+] llvm_mode run reported $TUPLES instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode instrumentation produces weird numbers: $TUPLES"
|
||||
CODE=1
|
||||
}
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-instr.plain.0 test-instr.plain.1
|
||||
} || $ECHO "$RED[!] llvm_mode failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode failed"
|
||||
CODE=1
|
||||
}
|
||||
test -e test-compcov.harden && {
|
||||
grep -Eqa 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] llvm_mode hardened mode succeeded and is working"
|
||||
} || $ECHO "$RED[!] llvm_mode hardened mode is not hardened"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode hardened mode is not hardened"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden
|
||||
} || $ECHO "$RED[!] llvm_mode hardened mode compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$RED[!] we cannot run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) ||
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
(test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
|
||||
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"
|
||||
CODE=1
|
||||
true
|
||||
}) || {
|
||||
mkdir -p in
|
||||
@ -163,6 +246,7 @@ test -e ../afl-clang-fast && {
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with llvm_mode"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors
|
||||
}
|
||||
@ -173,36 +257,63 @@ test -e ../afl-clang-fast && {
|
||||
test -e test-compcov.instrim && {
|
||||
grep -Eq " [1-3] location" test.out && {
|
||||
$ECHO "$GREEN[+] llvm_mode InsTrim feature works correctly"
|
||||
} || $ECHO "$RED[!] llvm_mode InsTrim feature failed"
|
||||
} || $ECHO "$RED[!] llvm_mode InsTrim feature compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode InsTrim feature failed"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode InsTrim feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.instrim test.out
|
||||
AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > /dev/null 2> test.out
|
||||
test -e test-compcov.compcov && {
|
||||
grep -Eq " [3-9][0-9] location" test.out && {
|
||||
$ECHO "$GREEN[+] llvm_mode laf-intel/compcov feature works correctly"
|
||||
} || $ECHO "$RED[!] llvm_mode laf-intel/compcov feature failed"
|
||||
} || $ECHO "$RED[!] llvm_mode laf-intel/compcov feature compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode laf-intel/compcov feature failed"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode laf-intel/compcov feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.compcov test.out
|
||||
echo foobar.c > whitelist.txt
|
||||
AFL_LLVM_WHITELIST=whitelist.txt ../afl-clang-fast -o test-compcov test-compcov.c > test.out 2>&1
|
||||
test -e test-compcov && {
|
||||
grep -q "No instrumentation targets found" test.out && {
|
||||
$ECHO "$GREEN[+] llvm_mode whitelist feature works correctly"
|
||||
} || $ECHO "$RED[!] llvm_mode whitelist feature failed"
|
||||
} || $ECHO "$RED[!] llvm_mode whitelist feature compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode whitelist feature failed"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode whitelist feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov test.out whitelist.txt
|
||||
../afl-clang-fast -o test-persistent ../experimental/persistent_demo/persistent_demo.c > /dev/null 2>&1
|
||||
test -e test-persistent && {
|
||||
echo foo | ../afl-showmap -o /dev/null -q -r ./test-persistent && {
|
||||
$ECHO "$GREEN[+] llvm_mode persistent mode feature works correctly"
|
||||
} || $ECHO "$RED[!] llvm_mode persistent mode feature failed to work"
|
||||
} || $ECHO "$RED[!] llvm_mode persistent mode feature compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode persistent mode feature failed to work"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] llvm_mode persistent mode feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-persistent
|
||||
} || $ECHO "$YELLOW[-] llvm_mode not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] llvm_mode not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: gcc_plugin"
|
||||
export AFL_CC=`which gcc`
|
||||
test -e ../afl-gcc-fast && {
|
||||
test -e ../afl-gcc-fast -a -e ../afl-gcc-rt.o && {
|
||||
../afl-gcc-fast -o test-instr.plain.gccpi ../test-instr.c > /dev/null 2>&1
|
||||
AFL_HARDEN=1 ../afl-gcc-fast -o test-compcov.harden.gccpi test-compcov.c > /dev/null 2>&1
|
||||
test -e test-instr.plain.gccpi && {
|
||||
@ -212,25 +323,49 @@ test -e ../afl-gcc-fast && {
|
||||
test -e test-instr.plain.0 -a -e test-instr.plain.1 && {
|
||||
diff -q test-instr.plain.0 test-instr.plain.1 > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] gcc_plugin instrumentation should be different on different input but is not"
|
||||
} || $ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly"
|
||||
} || $ECHO "$RED[!] gcc_plugin instrumentation failed"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] gcc_plugin instrumentation present and working correctly"
|
||||
TUPLES=`echo 0|../afl-showmap -m ${MEM_LIMIT} -o /dev/null -- ./test-instr.plain.gccpi 2>&1 | grep Captur | awk '{print$3}'`
|
||||
test "$TUPLES" -gt 3 -a "$TUPLES" -lt 7 && {
|
||||
$ECHO "$GREEN[+] gcc_plugin run reported $TUPLES instrumented locations which is fine"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin instrumentation produces a weird number of instrumented locations: $TUPLES"
|
||||
$ECHO "$YELLOW[-] the gcc_plugin instrumentation issue is not flagged as an error because travis builds would all fail otherwise :-("
|
||||
#CODE=1
|
||||
}
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin instrumentation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-instr.plain.0 test-instr.plain.1
|
||||
} || $ECHO "$RED[!] gcc_plugin failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin failed"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
test -e test-compcov.harden.gccpi && {
|
||||
grep -Eqa 'stack_chk_fail|fstack-protector-all|fortified' test-compcov.harden.gccpi > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] gcc_plugin hardened mode succeeded and is working"
|
||||
} || $ECHO "$RED[!] gcc_plugin hardened mode is not hardened"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin hardened mode is not hardened"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov.harden.gccpi
|
||||
} || $ECHO "$RED[!] gcc_plugin hardened mode compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin hardened mode compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
# now we want to be sure that afl-fuzz is working
|
||||
(test "$(uname -s)" = "Linux" && test "$(sysctl kernel.core_pattern)" != "kernel.core_pattern = core" && {
|
||||
$ECHO "$RED[!] we cannot run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
$ECHO "$YELLOW[-] we should not run afl-fuzz with enabled core dumps. Run 'sudo sh afl-system-config'.$RESET"
|
||||
true
|
||||
}) ||
|
||||
# make sure crash reporter is disabled on Mac OS X
|
||||
(test "$(uname -s)" = "Darwin" && test $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') && {
|
||||
$ECHO "$RED[!] we cannot run afl-fuzz with enabled crash reporter. Run 'sudo sh afl-system-config'.$RESET"
|
||||
CODE=1
|
||||
true
|
||||
}) || {
|
||||
mkdir -p in
|
||||
@ -246,6 +381,7 @@ test -e ../afl-gcc-fast && {
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with gcc_plugin"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors
|
||||
}
|
||||
@ -257,43 +393,99 @@ test -e ../afl-gcc-fast && {
|
||||
test -e test-compcov && {
|
||||
echo 1 | ../afl-showmap -m ${MEM_LIMIT} -o - -r -- ./test-compcov 2>&1 | grep -q "Captured 1 tuples" && {
|
||||
$ECHO "$GREEN[+] gcc_plugin whitelist feature works correctly"
|
||||
} || $ECHO "$RED[!] gcc_plugin whitelist feature failed"
|
||||
} || $ECHO "$RED[!] gcc_plugin whitelist feature compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin whitelist feature failed"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin whitelist feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-compcov test.out whitelist.txt
|
||||
../afl-gcc-fast -o test-persistent ../experimental/persistent_demo/persistent_demo.c > /dev/null 2>&1
|
||||
test -e test-persistent && {
|
||||
echo foo | ../afl-showmap -o /dev/null -q -r ./test-persistent && {
|
||||
$ECHO "$GREEN[+] gcc_plugin persistent mode feature works correctly"
|
||||
} || $ECHO "$RED[!] gcc_plugin persistent mode feature failed to work"
|
||||
} || $ECHO "$RED[!] gcc_plugin persistent mode feature compilation failed"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin persistent mode feature failed to work"
|
||||
CODE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc_plugin persistent mode feature compilation failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -f test-persistent
|
||||
} || $ECHO "$YELLOW[-] gcc_plugin not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] gcc_plugin not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: shared library extensions"
|
||||
gcc -o test-compcov test-compcov.c > /dev/null 2>&1
|
||||
cc -o test-compcov test-compcov.c > /dev/null 2>&1
|
||||
test -e ../libtokencap.so && {
|
||||
AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so ./test-compcov foobar > /dev/null 2>&1
|
||||
AFL_TOKEN_FILE=token.out LD_PRELOAD=../libtokencap.so DYLD_INSERT_LIBRARIES=../libtokencap.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov foobar > /dev/null 2>&1
|
||||
grep -q BUGMENOT token.out > /dev/null 2>&1 && {
|
||||
$ECHO "$GREEN[+] libtokencap did successfully capture tokens"
|
||||
} || $ECHO "$RED[!] libtokencap did not capture tokens"
|
||||
} || {
|
||||
$ECHO "$RED[!] libtokencap did not capture tokens"
|
||||
CODE=1
|
||||
}
|
||||
rm -f token.out
|
||||
} || $ECHO "$YELLOW[-] libtokencap is not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] libtokencap is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
test -e ../libdislocator.so && {
|
||||
{
|
||||
ulimit -c 1
|
||||
# DYLD_INSERT_LIBRARIES is used on Darwin/MacOSX
|
||||
LD_PRELOAD=../libdislocator.so DYLD_INSERT_LIBRARIES=../libdislocator.so ./test-compcov BUFFEROVERFLOW > test.out 2> /dev/null
|
||||
# DYLD_INSERT_LIBRARIES and DYLD_FORCE_FLAT_NAMESPACE is used on Darwin/MacOSX
|
||||
LD_PRELOAD=../libdislocator.so DYLD_INSERT_LIBRARIES=../libdislocator.so DYLD_FORCE_FLAT_NAMESPACE=1 ./test-compcov BUFFEROVERFLOW > test.out 2> /dev/null
|
||||
} > /dev/null 2>&1
|
||||
grep -q BUFFEROVERFLOW test.out > /dev/null 2>&1 && {
|
||||
$ECHO "$RED[!] libdislocator did not detect the memory corruption"
|
||||
} || $ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
|
||||
CODE=1
|
||||
} || {
|
||||
$ECHO "$GREEN[+] libdislocator did successfully detect the memory corruption"
|
||||
}
|
||||
rm -f test.out core test-compcov.core core.test-compcov
|
||||
} || $ECHO "$YELLOW[-] libdislocator is not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] libdislocator is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
rm -f test-compcov
|
||||
test -e ../libradamsa.so && {
|
||||
test -e test-instr.plain || ../afl-clang-fast -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
test -e test-instr.plain || ../afl-gcc-fast -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
test -e test-instr.plain || ../${AFL_GCC} -o test-instr.plain ../test-instr.c > /dev/null 2>&1
|
||||
test -e test-instr.plain && {
|
||||
mkdir -p in
|
||||
printf 1 > in/in
|
||||
$ECHO "$GREY[*] running afl-fuzz with radamsa, this will take approx 10 seconds"
|
||||
{
|
||||
../afl-fuzz -RR -V10 -m ${MEM_LIMIT} -i in -o out -- ./test-instr.plain
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
|
||||
$ECHO "$GREEN[+] libradamsa performs good - and very slow - mutations"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] libradamsa failed"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors test-instr.plain
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] compilation of test target failed, cannot test libradamsa"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] libradamsa is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: qemu_mode"
|
||||
test -e ../afl-qemu-trace && {
|
||||
gcc -no-pie -o test-instr ../test-instr.c
|
||||
gcc -o test-instr ../test-instr.c
|
||||
gcc -o test-compcov test-compcov.c
|
||||
test -e test-instr -a -e test-compcov && {
|
||||
{
|
||||
@ -311,6 +503,7 @@ test -e ../afl-qemu-trace && {
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode"
|
||||
CODE=1
|
||||
}
|
||||
rm -f errors
|
||||
|
||||
@ -328,8 +521,12 @@ test -e ../afl-qemu-trace && {
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with qemu_mode libcompcov"
|
||||
CODE=1
|
||||
}
|
||||
} || $ECHO "$YELLOW[-] we cannot test qemu_mode libcompcov because it is not present"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] we cannot test qemu_mode libcompcov because it is not present"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
rm -f errors
|
||||
|
||||
$ECHO "$GREY[*] running afl-fuzz for persistent qemu_mode, this will take approx 10 seconds"
|
||||
@ -347,64 +544,97 @@ test -e ../afl-qemu-trace && {
|
||||
test "$SLOW" -lt "$FAST" && {
|
||||
$ECHO "$GREEN[+] persistent qemu_mode was noticeable faster than standard qemu_mode"
|
||||
} || {
|
||||
$ECHO "$YELLOW[?] persistent qemu_mode was not noticeable faster than standard qemu_mode"
|
||||
$ECHO "$YELLOW[-] persistent qemu_mode was not noticeable faster than standard qemu_mode"
|
||||
}
|
||||
} || {
|
||||
$ECHO "$YELLOW[?] we got no data on executions performed? weird!"
|
||||
$ECHO "$YELLOW[-] we got no data on executions performed? weird!"
|
||||
}
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with persistent qemu_mode"
|
||||
CODE=1
|
||||
exit 1
|
||||
}
|
||||
$ECHO "$YELLOW[?] we need a test case for qemu_mode unsigaction library"
|
||||
$ECHO "$YELLOW[-] we need a test case for qemu_mode unsigaction library"
|
||||
rm -rf in out errors
|
||||
}
|
||||
} || $ECHO "$RED[-] gcc compilation of test targets failed - what is going on??"
|
||||
} || {
|
||||
$ECHO "$RED[!] gcc compilation of test targets failed - what is going on??"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
rm -f test-instr test-compcov
|
||||
} || $ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] qemu_mode is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$BLUE[*] Testing: unicorn_mode"
|
||||
test -d ../unicorn_mode/unicorn && {
|
||||
test -e ../unicorn_mode/samples/simple/simple_target.bin -a -e ../unicorn_mode/samples/compcov_x64/compcov_target.bin && {
|
||||
{
|
||||
# travis workaround
|
||||
PY=`which python`
|
||||
test "$PY" = "/opt/pyenv/shims/python" -a -x /usr/bin/python && PY=/usr/bin/python
|
||||
mkdir -p in
|
||||
echo 0 > in/in
|
||||
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode, this will take approx 20 seconds"
|
||||
$ECHO "$GREY[*] Using python binary $PY"
|
||||
if ! $PY -c 'import unicornafl' 2> /dev/null ; then
|
||||
$ECHO "$YELLOW[-] we cannot test unicorn_mode because it is not present"
|
||||
INCOMPLETE=1
|
||||
else
|
||||
{
|
||||
../afl-fuzz -V20 -U -i in -o out -d -- python ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode"
|
||||
}
|
||||
rm -f errors
|
||||
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode, this will take approx 25 seconds"
|
||||
{
|
||||
../afl-fuzz -V25 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/simple/simple_test_harness.py @@ >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/queue/id:000002* 2> /dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode"
|
||||
CODE=1
|
||||
}
|
||||
rm -f errors
|
||||
|
||||
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode compcov, this will take approx 25 seconds"
|
||||
{
|
||||
export AFL_COMPCOV_LEVEL=2
|
||||
../afl-fuzz -V25 -U -i in -o out -d -- python ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode compcov"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode compcov"
|
||||
printf '\x01\x01' > in/in
|
||||
# This seed is close to the first byte of the comparison.
|
||||
# If CompCov works, a new tuple will appear in the map => new input in queue
|
||||
$ECHO "$GREY[*] running afl-fuzz for unicorn_mode compcov, this will take approx 35 seconds"
|
||||
{
|
||||
export AFL_COMPCOV_LEVEL=2
|
||||
../afl-fuzz -V35 -U -i in -o out -d -- "$PY" ../unicorn_mode/samples/compcov_x64/compcov_test_harness.py @@ >>errors 2>&1
|
||||
} >>errors 2>&1
|
||||
test -n "$( ls out/queue/id:000001* 2> /dev/null )" && {
|
||||
$ECHO "$GREEN[+] afl-fuzz is working correctly with unicorn_mode compcov"
|
||||
} || {
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
cat errors
|
||||
echo CUT------------------------------------------------------------------CUT
|
||||
$ECHO "$RED[!] afl-fuzz is not working correctly with unicorn_mode compcov"
|
||||
CODE=1
|
||||
}
|
||||
rm -rf in out errors
|
||||
}
|
||||
rm -rf in out errors
|
||||
fi
|
||||
}
|
||||
} || $ECHO "$RED[-] missing sample binaries in unicorn_mode/samples/ - what is going on??"
|
||||
} || {
|
||||
$ECHO "$RED[!] missing sample binaries in unicorn_mode/samples/ - what is going on??"
|
||||
CODE=1
|
||||
}
|
||||
|
||||
} || $ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
|
||||
} || {
|
||||
$ECHO "$YELLOW[-] unicorn_mode is not compiled, cannot test"
|
||||
INCOMPLETE=1
|
||||
}
|
||||
|
||||
$ECHO "$GREY[*] all test cases completed.$RESET"
|
||||
|
||||
test "$INCOMPLETE" = "0" && $ECHO "$GREEN[+] all test cases executed"
|
||||
test "$INCOMPLETE" = "1" && $ECHO "$YELLOW[-] not all test cases were executed"
|
||||
test "$CODE" = "0" && $ECHO "$GREEN[+] all tests were successful :-)$RESET"
|
||||
test "$CODE" = "0" || $ECHO "$RED[!] failure in tests :-($RESET"
|
||||
exit $CODE
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
The idea and much of the original implementation comes from Nathan Voss <njvoss299@gmail.com>.
|
||||
|
||||
The port to afl++ if by Dominik Maier <mail@dmnk.co>.
|
||||
The port to afl++ is by Dominik Maier <mail@dmnk.co>.
|
||||
|
||||
The CompareCoverage and NeverZero counters features by Andrea Fioraldi <andreafioraldi@gmail.com>.
|
||||
The CompareCoverage and NeverZero counters features are by Andrea Fioraldi <andreafioraldi@gmail.com>.
|
||||
|
||||
## 1) Introduction
|
||||
|
||||
@ -16,13 +16,13 @@ with afl-gcc or used in QEMU mode, or with other extensions such as
|
||||
TriforceAFL.
|
||||
|
||||
There is a significant performance penalty compared to native AFL,
|
||||
but at least we're able to use AFL on these binaries, right?
|
||||
but at least we're able to use AFL++ on these binaries, right?
|
||||
|
||||
## 2) How to use
|
||||
|
||||
Requirements: you need an installed python2 environment.
|
||||
Requirements: you need an installed python environment.
|
||||
|
||||
### Building AFL's Unicorn Mode
|
||||
### Building AFL++'s Unicorn Mode
|
||||
|
||||
First, make afl++ as usual.
|
||||
Once that completes successfully you need to build and add in the Unicorn Mode
|
||||
@ -31,14 +31,11 @@ features:
|
||||
$ cd unicorn_mode
|
||||
$ ./build_unicorn_support.sh
|
||||
|
||||
NOTE: This script downloads a Unicorn Engine commit that has been tested
|
||||
and is stable-ish from the Unicorn github page. If you are offline, you'll need
|
||||
to hack up this script a little bit and supply your own copy of Unicorn's latest
|
||||
stable release. It's not very hard, just check out the beginning of the
|
||||
build_unicorn_support.sh script and adjust as necessary.
|
||||
NOTE: This script checks out a Unicorn Engine fork as submodule that has been tested
|
||||
and is stable-ish, based on the unicorn engine master.
|
||||
|
||||
Building Unicorn will take a little bit (~5-10 minutes). Once it completes
|
||||
it automatically compiles a sample application and verify that it works.
|
||||
it automatically compiles a sample application and verifies that it works.
|
||||
|
||||
### Fuzzing with Unicorn Mode
|
||||
|
||||
@ -51,11 +48,10 @@ To really use unicorn-mode effectively you need to prepare the following:
|
||||
+ Quality/speed of results will depend greatly on quality of starting
|
||||
samples
|
||||
+ See AFL's guidance on how to create a sample corpus
|
||||
* Unicorn-based test harness which:
|
||||
* Unicornafl-based test harness which:
|
||||
+ Adds memory map regions
|
||||
+ Loads binary code into memory
|
||||
+ Emulates at least one instruction*
|
||||
+ Yeah, this is lame. See 'Gotchas' section below for more info
|
||||
+ Calls uc.afl_fuzz() / uc.afl_start_forkserver
|
||||
+ Loads and verifies data to fuzz from a command-line specified file
|
||||
+ AFL will provide mutated inputs by changing the file passed to
|
||||
the test harness
|
||||
@ -87,7 +83,7 @@ The 'helper_scripts' directory also contains several helper scripts that allow y
|
||||
to dump context from a running process, load it, and hook heap allocations. For details
|
||||
on how to use this check out the follow-up blog post to the one linked above.
|
||||
|
||||
A example use of AFL-Unicorn mode is discussed in the Paper Unicorefuzz:
|
||||
A example use of AFL-Unicorn mode is discussed in the paper Unicorefuzz:
|
||||
https://www.usenix.org/conference/woot19/presentation/maier
|
||||
|
||||
## 3) Options
|
||||
@ -95,7 +91,7 @@ https://www.usenix.org/conference/woot19/presentation/maier
|
||||
As for the QEMU-based instrumentation, the afl-unicorn twist of afl++
|
||||
comes with a sub-instruction based instrumentation similar in purpose to laf-intel.
|
||||
|
||||
The options that enables Unicorn CompareCoverage are the same used for QEMU.
|
||||
The options that enable Unicorn CompareCoverage are the same used for QEMU.
|
||||
AFL_COMPCOV_LEVEL=1 is to instrument comparisons with only immediate
|
||||
values. QEMU_COMPCOV_LEVEL=2 instruments all
|
||||
comparison instructions. Comparison instructions are currently instrumented only
|
||||
@ -103,16 +99,20 @@ for the x86, x86_64 and ARM targets.
|
||||
|
||||
## 4) Gotchas, feedback, bugs
|
||||
|
||||
To make sure that AFL's fork server starts up correctly the Unicorn test
|
||||
harness script must emulate at least one instruction before loading the
|
||||
data that will be fuzzed from the input file. It doesn't matter what the
|
||||
instruction is, nor if it is valid. This is an artifact of how the fork-server
|
||||
is started and could likely be fixed with some clever re-arranging of the
|
||||
patches applied to Unicorn.
|
||||
Running the build script builds Unicornafl and its python bindings and installs
|
||||
them on your system.
|
||||
This installation will leave any existing Unicorn installations untouched.
|
||||
If you want to use unicornafl instead of unicorn in a script,
|
||||
replace all `unicorn` imports with `unicornafl` inputs, everything else should "just work".
|
||||
If you use 3rd party code depending on unicorn, you can use unicornafl monkeypatching:
|
||||
Before importing anything that depends on unicorn, do:
|
||||
|
||||
Running the build script builds Unicorn and its python bindings and installs
|
||||
them on your system. This installation will supersede any existing Unicorn
|
||||
installation with the patched afl-unicorn version.
|
||||
```python
|
||||
import unicornafl
|
||||
unicornafl.monkeypatch()
|
||||
```
|
||||
|
||||
This will replace all unicorn imports with unicornafl inputs.
|
||||
|
||||
Refer to the unicorn_mode/samples/arm_example/arm_tester.c for an example
|
||||
of how to do this properly! If you don't get this right, AFL will not
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user