mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 22:53:24 +00:00
Compare commits
192 Commits
Author | SHA1 | Date | |
---|---|---|---|
c340a022e2 | |||
06219b4d56 | |||
c5b8f4250e | |||
779cb5d942 | |||
fb1a41f5af | |||
8352f0a89f | |||
9935190c7b | |||
e3ee26262f | |||
737c13b460 | |||
9836598d65 | |||
63509fb696 | |||
d1c44e12a8 | |||
f78ed6eabc | |||
64c942d0c9 | |||
50e343a0d0 | |||
55719ab23b | |||
d12c5edd59 | |||
1b82d6b904 | |||
61201fbbb8 | |||
b9458e72e7 | |||
5045f9e615 | |||
6cd8a0168f | |||
448c6c212d | |||
05f4762894 | |||
0a06e36788 | |||
9b1f80c277 | |||
787a332a73 | |||
7d85047fd9 | |||
fa8dc2028f | |||
619aa70414 | |||
247e8241b4 | |||
0bb64e4bc9 | |||
7b84ec97e2 | |||
20a6cdabad | |||
0d286c9e19 | |||
db94ec9cad | |||
05dfb70787 | |||
7f2becba72 | |||
13b27bb59e | |||
ecdbdc3164 | |||
788e70a01a | |||
938ed60ea9 | |||
5b9d2cc38b | |||
e305bc15d3 | |||
0b12c7e0cc | |||
4bd492f212 | |||
be8393f201 | |||
aec90c7227 | |||
1960352310 | |||
03169b2b67 | |||
dee51213a7 | |||
1d2de1cb6d | |||
5ed187b517 | |||
a845852b98 | |||
9513397336 | |||
57fa87ce5e | |||
c6a2cf88bf | |||
8461f860eb | |||
7395223512 | |||
1121af301b | |||
b9c1536283 | |||
6691ce943a | |||
1dba3a276f | |||
3c8016e071 | |||
b64dd0a1ec | |||
55f758a168 | |||
bd631c73a2 | |||
6cbe58ff55 | |||
c71d487a4c | |||
939171952d | |||
161905c2fc | |||
5ff21c9aad | |||
112d90656b | |||
bc11bd7661 | |||
6b71ca7809 | |||
eb0b8b2c5c | |||
6223ddf6d2 | |||
920c7fe71a | |||
4ff2673895 | |||
891b7f48f0 | |||
5df3cdbc0b | |||
57466909e4 | |||
55c9c4ff19 | |||
fe202b5fee | |||
c5e511302f | |||
7c349b6cde | |||
fc38904e25 | |||
eee2521eb4 | |||
192d4817e0 | |||
58e4070573 | |||
2ecf28440f | |||
757184e611 | |||
27b18e6267 | |||
f1ee7bc9cd | |||
969541b54f | |||
ec07f531f8 | |||
56b5983b61 | |||
f17ea60a30 | |||
68634964ef | |||
d21804bdd1 | |||
5a527046a5 | |||
b2a8765b1f | |||
106309492c | |||
58c5e2b96c | |||
5842ba87e5 | |||
5069551778 | |||
0606d95f86 | |||
0e35e56cc9 | |||
fc860872d6 | |||
735d647e48 | |||
73ab495b5d | |||
d1cab470bb | |||
992349e48a | |||
950b90abcd | |||
f3b15d6340 | |||
0134a23046 | |||
7c296f099f | |||
919e6226d3 | |||
a85f0c0ef9 | |||
6457e2ea30 | |||
542233e1ce | |||
8e4823e7ed | |||
f27c504f29 | |||
9776e402c3 | |||
4cabb81996 | |||
42465480ef | |||
f27f109880 | |||
fa9e256e09 | |||
78952e8440 | |||
8b543df04c | |||
e64c3f8653 | |||
f590973387 | |||
36338ad08b | |||
73a36ffda3 | |||
cdf93f4d1f | |||
a0d996558b | |||
21e75d73a6 | |||
cc1d41f59d | |||
9530b4c9d4 | |||
f1998bb53b | |||
0e3c82e2ea | |||
c22b06a27d | |||
1d1aa3edec | |||
50f6b38530 | |||
0cd932c4b5 | |||
a635aa8cba | |||
00577bb32d | |||
6aaba974b6 | |||
6459707f24 | |||
870e22246a | |||
66c2bb3994 | |||
a482b817af | |||
6f433b5d73 | |||
2843b7eb02 | |||
6ed9b6d631 | |||
6f018b3d80 | |||
1318636ae7 | |||
29f48ab3e7 | |||
2c2a0471cd | |||
68f5c4811e | |||
fe6d3990ce | |||
2b143688a6 | |||
f37f0b4ee4 | |||
bd5ccc6977 | |||
e0b23dd53d | |||
54890db08e | |||
6c4b2f0c8e | |||
bed20d40b1 | |||
ea2f112016 | |||
f639668032 | |||
1709eb59a8 | |||
bbdcfb0e8e | |||
cab4609e1a | |||
feed691dc0 | |||
e4f7a4738e | |||
625df13d0e | |||
a3c038efd6 | |||
4f3812f00d | |||
887d104dae | |||
47954cd04c | |||
a441f517e7 | |||
9cb3fe98dd | |||
e6f15f02e1 | |||
65b99d25e1 | |||
7b86d735df | |||
b56b24d251 | |||
c2383761cb | |||
f87a669aa3 | |||
8489112ab1 | |||
ebd6d4b8bb | |||
125027f5bf | |||
fd780e8eba |
@ -21,12 +21,15 @@ import os
|
||||
# import re # TODO: for future use
|
||||
import shutil
|
||||
import importlib.metadata
|
||||
import hashlib
|
||||
|
||||
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
|
||||
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
|
||||
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
|
||||
|
||||
FORMAT_CACHE_DIR = '.format-cache'
|
||||
os.makedirs(FORMAT_CACHE_DIR, exist_ok=True)
|
||||
|
||||
def check_clang_format_pip_version():
|
||||
"""
|
||||
@ -69,6 +72,8 @@ to install via pip.")
|
||||
if CLANG_FORMAT_PIP:
|
||||
CLANG_FORMAT_BIN = shutil.which("clang-format")
|
||||
|
||||
CLANG_FORMAT_VERSION = subprocess.check_output([CLANG_FORMAT_BIN, '--version'])
|
||||
|
||||
COLUMN_LIMIT = 80
|
||||
for line in fmt.split("\n"):
|
||||
line = line.split(":")
|
||||
@ -86,9 +91,10 @@ def custom_format(filename):
|
||||
out = ""
|
||||
|
||||
for line in src.split("\n"):
|
||||
define_start = False
|
||||
if line.lstrip().startswith("#"):
|
||||
if line[line.find("#") + 1:].lstrip().startswith("define"):
|
||||
in_define = True
|
||||
define_start = True
|
||||
|
||||
if (
|
||||
"/*" in line
|
||||
@ -126,9 +132,7 @@ def custom_format(filename):
|
||||
and last_line.strip() != ""
|
||||
):
|
||||
line = (" " * define_padding + "\\" if in_define else "") + "\n" + line
|
||||
|
||||
if not line.endswith("\\"):
|
||||
in_define = False
|
||||
in_define = (define_start or in_define) and line.endswith("\\")
|
||||
|
||||
out += line + "\n"
|
||||
last_line = line
|
||||
@ -136,6 +140,38 @@ def custom_format(filename):
|
||||
return out
|
||||
|
||||
|
||||
def hash_code_and_formatter(code):
|
||||
hasher = hashlib.sha256()
|
||||
|
||||
hasher.update(code.encode())
|
||||
hasher.update(CLANG_FORMAT_VERSION)
|
||||
with open(__file__, 'rb') as f:
|
||||
hasher.update(f.read())
|
||||
|
||||
return hasher.hexdigest()
|
||||
|
||||
|
||||
def custom_format_cached(filename):
|
||||
filename_hash = hashlib.sha256(filename.encode()).hexdigest()
|
||||
cache_file = os.path.join(FORMAT_CACHE_DIR, filename_hash)
|
||||
|
||||
if os.path.exists(cache_file):
|
||||
with open(filename) as f:
|
||||
code = f.read()
|
||||
code_hash = hash_code_and_formatter(code)
|
||||
with open(cache_file) as f:
|
||||
if f.read() == code_hash:
|
||||
return code
|
||||
|
||||
code = custom_format(filename)
|
||||
|
||||
code_hash = hash_code_and_formatter(code)
|
||||
with open(cache_file, 'w') as f:
|
||||
f.write(code_hash)
|
||||
|
||||
return code
|
||||
|
||||
|
||||
args = sys.argv[1:]
|
||||
if len(args) == 0:
|
||||
print("Usage: ./format.py [-i] <filename>")
|
||||
@ -151,7 +187,7 @@ if args[0] == "-i":
|
||||
args = args[1:]
|
||||
|
||||
for filename in args:
|
||||
code = custom_format(filename)
|
||||
code = custom_format_cached(filename)
|
||||
if in_place:
|
||||
with open(filename, "w") as f:
|
||||
f.write(code)
|
||||
|
8
.github/workflows/ci.yml
vendored
8
.github/workflows/ci.yml
vendored
@ -14,18 +14,18 @@ jobs:
|
||||
runs-on: "${{ matrix.os }}"
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
os: [ubuntu-24.04, ubuntu-22.04, ubuntu-24.04-arm]
|
||||
env:
|
||||
AFL_SKIP_CPUFREQ: 1
|
||||
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: update
|
||||
run: sudo apt-get update && sudo apt-get upgrade -y
|
||||
- name: debug
|
||||
run: apt-cache search plugin-dev | grep gcc-; echo; apt-cache search clang-format- | grep clang-format-
|
||||
- name: install packages
|
||||
run: sudo apt-get install -y -m -f build-essential gcc-10 g++-10 git libtool libtool-bin automake flex bison libglib2.0-0 clang-12 llvm-12-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip gcc-10-plugin-dev
|
||||
run: sudo apt-get install -y -m -f build-essential gcc-12 g++-12 git libtool libtool-bin automake flex bison libglib2.0-0 clang-15 llvm-15-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build python3-pip gcc-12-plugin-dev
|
||||
- name: compiler installed
|
||||
run: gcc -v; echo; clang -v
|
||||
- name: install gcc plugin
|
||||
@ -45,7 +45,7 @@ jobs:
|
||||
- name: install
|
||||
run: brew install make gcc llvm
|
||||
# - name: fix install
|
||||
# run: cd /usr/local/bin; ln -s gcc-11 gcc; ln -s g++-11 g++; which gcc; gcc -v
|
||||
# run: cd /usr/local/bin; ln -s gcc-12 gcc; ln -s g++-12 g++; which gcc; gcc -v
|
||||
# - name: build
|
||||
# run: export PATH=/usr/local/Cellar/llvm/*/":$PATH"; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
|
||||
- name: build
|
||||
|
35
.github/workflows/container.yml
vendored
35
.github/workflows/container.yml
vendored
@ -16,11 +16,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build amd64
|
||||
uses: docker/build-push-action@v3
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
tags: aflplusplus:test-amd64
|
||||
@ -35,20 +35,41 @@ jobs:
|
||||
apt-get install -y libcmocka-dev &&
|
||||
make -i tests
|
||||
"
|
||||
build-and-test-arm64:
|
||||
name: Test arm64 image
|
||||
runs-on: ubuntu-24.04-arm
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Build arm64
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
tags: aflplusplus:test-arm64
|
||||
load: true
|
||||
cache-to: type=gha,mode=max
|
||||
build-args: |
|
||||
TEST_BUILD=1
|
||||
- name: Test arm64
|
||||
run: >
|
||||
docker run --rm aflplusplus:test-arm64 bash -c "
|
||||
apt-get update &&
|
||||
apt-get install -y libcmocka-dev &&
|
||||
make -i tests
|
||||
"
|
||||
|
||||
push:
|
||||
name: Push amd64 and arm64 images
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build-and-test-amd64
|
||||
- build-and-test-arm64
|
||||
if: ${{ github.event_name == 'push' && github.repository == 'AFLplusplus/AFLplusplus' }}
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
- name: Set up QEMU
|
||||
uses: docker/setup-qemu-action@v2
|
||||
with:
|
||||
platforms: arm64
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
- name: Login to docker.io
|
||||
|
2
.github/workflows/rust_custom_mutator.yml
vendored
2
.github/workflows/rust_custom_mutator.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
working-directory: custom_mutators/rust
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-20.04]
|
||||
os: [ubuntu-22.04]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Install Rust Toolchain
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -7,6 +7,7 @@
|
||||
*.so
|
||||
*.swp
|
||||
.DS_Store
|
||||
.format-cache
|
||||
.sync_tmp
|
||||
.test
|
||||
.test2
|
||||
@ -113,4 +114,4 @@ utils/replay_record/persistent_demo_replay_argparse
|
||||
utils/plot_ui/afl-plot-ui
|
||||
vuln_prog
|
||||
argv_fuzz_demo
|
||||
argv_fuzz_persistent_demo
|
||||
argv_fuzz_persistent_demo
|
||||
|
@ -61,6 +61,7 @@ RUN apt-get update && \
|
||||
|
||||
RUN update-alternatives --install /usr/bin/gcc gcc /usr/bin/gcc-${GCC_VERSION} 0 && \
|
||||
update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-${GCC_VERSION} 0 && \
|
||||
update-alternatives --install /usr/bin/c++ c++ /usr/bin/g++-${GCC_VERSION} 0 && \
|
||||
update-alternatives --install /usr/bin/clang clang /usr/bin/clang-${LLVM_VERSION} 0 && \
|
||||
update-alternatives --install /usr/bin/clang++ clang++ /usr/bin/clang++-${LLVM_VERSION} 0
|
||||
|
||||
|
91
GNUmakefile
91
GNUmakefile
@ -70,6 +70,11 @@ ifdef CODE_COVERAGE
|
||||
override CFLAGS += -D__AFL_CODE_COVERAGE=1
|
||||
endif
|
||||
|
||||
IS_IOS:=$(findstring ios, $(shell $(CC) --version 2>/dev/null))
|
||||
ifdef IS_IOS
|
||||
override CFLAGS += -DTARGET_OS_IPHONE -DTARGET_OS_IOS -isysroot $(IOS_SDK_PATH)
|
||||
endif
|
||||
|
||||
ifeq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" ""
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CC) $(CFLAGS) -Werror -x c - -flto=full -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
CFLAGS_FLTO ?= -flto=full
|
||||
@ -101,17 +106,19 @@ else
|
||||
SPECIAL_PERFORMANCE :=
|
||||
endif
|
||||
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
||||
# SPECIAL_PERFORMANCE += -march=native
|
||||
#endif
|
||||
#ifndef DEBUG
|
||||
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||
#endif
|
||||
else
|
||||
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
||||
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
||||
override LDFLAGS += $(SDK_LD)
|
||||
ifndef IS_IOS
|
||||
ifneq "$(SYS)" "Darwin"
|
||||
#ifeq "$(HAVE_MARCHNATIVE)" "1"
|
||||
# SPECIAL_PERFORMANCE += -march=native
|
||||
#endif
|
||||
#ifndef DEBUG
|
||||
# override CFLAGS_OPT += -D_FORTIFY_SOURCE=1
|
||||
#endif
|
||||
else
|
||||
# On some odd MacOS system configurations, the Xcode sdk path is not set correctly
|
||||
SDK_LD = -L$(shell xcrun --show-sdk-path)/usr/lib
|
||||
override LDFLAGS += $(SDK_LD)
|
||||
endif
|
||||
endif
|
||||
|
||||
COMPILER_TYPE=$(shell $(CC) --version|grep "Free Software Foundation")
|
||||
@ -282,7 +289,7 @@ ifneq "$(findstring OpenBSD, $(SYS))" ""
|
||||
override LDFLAGS += -lpthread -lm
|
||||
endif
|
||||
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h
|
||||
COMM_HDR = include/alloc-inl.h include/config.h include/debug.h include/types.h include/afl-fuzz.h include/hash.h include/sharedmem.h include/forkserver.h include/common.h include/list.h
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <Python.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -x c - -o .test $(PYTHON_INCLUDE) $(LDFLAGS) $(PYTHON_LIB) 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
PYTHON_OK=1
|
||||
@ -465,32 +472,47 @@ endif
|
||||
ready:
|
||||
@echo "[+] Everything seems to be working, ready to compile. ($(shell $(CC) --version 2>&1|head -n 1))"
|
||||
|
||||
src/afl-performance.o : $(COMM_HDR) src/afl-performance.c include/hash.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
src/afl-performance.o: $(COMM_HDR) src/afl-performance.c
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(CFLAGS_OPT) $(SPECIAL_PERFORMANCE) -Iinclude -c src/afl-performance.c -o src/afl-performance.o
|
||||
|
||||
src/afl-common.o : $(COMM_HDR) src/afl-common.c include/common.h
|
||||
src/afl-common.o: $(COMM_HDR) src/afl-common.c include/envs.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-common.c -o src/afl-common.o
|
||||
|
||||
src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
||||
src/afl-forkserver.o: $(COMM_HDR) src/afl-forkserver.c
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-forkserver.c -o src/afl-forkserver.o
|
||||
|
||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
src/afl-sharedmem.o: $(COMM_HDR) src/afl-sharedmem.c include/android-ashmem.h include/cmplog.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o | test_x86
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o include/cmplog.h include/envs.h | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
afl-showmap: src/afl-showmap.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
afl-showmap: src/afl-showmap.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-fuzz-mutators.c src/afl-fuzz-python.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o -o $@ $(LDFLAGS)
|
||||
afl-tmin: src/afl-tmin.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/afl-fuzz-python.o src/afl-fuzz-mutators.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/afl-fuzz-python.o src/afl-fuzz-mutators.o -o $@ $(PYFLAGS) $(LDFLAGS)
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
afl-analyze: src/afl-analyze.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o src/afl-sharedmem.o src/afl-performance.o src/afl-forkserver.o -o $@ $(LDFLAGS)
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
afl-gotcpu: src/afl-gotcpu.c src/afl-common.o $(COMM_HDR) | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) src/$@.c src/afl-common.o -o $@ $(LDFLAGS)
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
.PHONY: document
|
||||
document: afl-fuzz-document
|
||||
@ -498,6 +520,9 @@ document: afl-fuzz-document
|
||||
# document all mutations and only do one run (use with only one input file!)
|
||||
afl-fuzz-document: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-performance.o | test_x86
|
||||
$(CC) -D_DEBUG=\"1\" -D_AFL_DOCUMENT_MUTATIONS $(CFLAGS) $(CFLAGS_FLTO) $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.c src/afl-performance.o -o afl-fuzz-document $(PYFLAGS) $(LDFLAGS)
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_maybe_alloc.c $(AFL_FUZZ_FILES)
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_maybe_alloc.c -o test/unittests/unit_maybe_alloc.o
|
||||
@ -505,20 +530,29 @@ test/unittests/unit_maybe_alloc.o : $(COMM_HDR) include/alloc-inl.h test/unittes
|
||||
unit_maybe_alloc: test/unittests/unit_maybe_alloc.o
|
||||
@$(CC) $(CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_maybe_alloc.o -o test/unittests/unit_maybe_alloc $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_maybe_alloc
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_hash.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_hash.c -o test/unittests/unit_hash.o
|
||||
|
||||
unit_hash: test/unittests/unit_hash.o src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_hash $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_hash
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_rand.c $(AFL_FUZZ_FILES) src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -c test/unittests/unit_rand.c -o test/unittests/unit_rand.o
|
||||
|
||||
unit_rand: test/unittests/unit_rand.o src/afl-common.o src/afl-performance.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
@$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(ASAN_CFLAGS) $(SPECIAL_PERFORMANCE) -Wl,--wrap=exit -Wl,--wrap=printf $^ -o test/unittests/unit_rand $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_rand
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list.c $(AFL_FUZZ_FILES)
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_list.c -o test/unittests/unit_list.o
|
||||
@ -526,6 +560,9 @@ test/unittests/unit_list.o : $(COMM_HDR) include/list.h test/unittests/unit_list
|
||||
unit_list: test/unittests/unit_list.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_list.o -o test/unittests/unit_list $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_list
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit_preallocable.c $(AFL_FUZZ_FILES)
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -c test/unittests/unit_preallocable.c -o test/unittests/unit_preallocable.o
|
||||
@ -533,6 +570,9 @@ test/unittests/unit_preallocable.o : $(COMM_HDR) include/alloc-inl.h test/unitte
|
||||
unit_preallocable: test/unittests/unit_preallocable.o
|
||||
@$(CC) $(CFLAGS) $(ASAN_CFLAGS) -Wl,--wrap=exit -Wl,--wrap=printf test/unittests/unit_preallocable.o -o test/unittests/unit_preallocable $(LDFLAGS) $(ASAN_LDFLAGS) -lcmocka
|
||||
./test/unittests/unit_preallocable
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
.PHONY: unit_clean
|
||||
unit_clean:
|
||||
@ -644,6 +684,7 @@ deepclean: clean
|
||||
rm -rf unicorn_mode/unicornafl
|
||||
rm -rf qemu_mode/qemuafl
|
||||
rm -rf nyx_mode/libnyx nyx_mode/packer nyx_mode/QEMU-Nyx
|
||||
rm -rf .format-cache
|
||||
ifeq "$(IN_REPO)" "1"
|
||||
git checkout coresight_mode/coresight-trace
|
||||
git checkout unicorn_mode/unicornafl
|
||||
|
@ -237,20 +237,21 @@ ifeq "$(LLVM_LTO)" "1"
|
||||
ifeq "$(AFL_REAL_LD)" ""
|
||||
ifneq "$(shell readlink $(LLVM_BINDIR)/ld.lld 2>&1)" ""
|
||||
AFL_REAL_LD = $(LLVM_BINDIR)/ld.lld
|
||||
else ifneq "$(shell command -v ld.lld 2>/dev/null)" ""
|
||||
AFL_REAL_LD = $(shell command -v ld.lld)
|
||||
TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | awk '{ print $$2 }')
|
||||
ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)"
|
||||
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it)
|
||||
else
|
||||
ifneq "$(shell command -v ld.lld 2>/dev/null)" ""
|
||||
AFL_REAL_LD = $(shell command -v ld.lld)
|
||||
TMP_LDLDD_VERSION = $(shell $(AFL_REAL_LD) --version | sed -E -ne '/^.*LLD\ ([12]?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
|
||||
ifeq "$(LLVMVER)" "$(TMP_LDLDD_VERSION)"
|
||||
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)), but its the same version as LLVM so we will allow it)
|
||||
else
|
||||
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode)
|
||||
AFL_REAL_LD=
|
||||
LLVM_LTO = 0
|
||||
endif
|
||||
else
|
||||
$(warning ld.lld found in a weird location ($(AFL_REAL_LD)) and its of a different version than LLMV ($(TMP_LDLDD_VERSION) vs. $(LLVMVER)) - cannot enable LTO mode)
|
||||
AFL_REAL_LD=
|
||||
$(warning ld.lld not found, cannot enable LTO mode)
|
||||
LLVM_LTO = 0
|
||||
endif
|
||||
undefine TMP_LDLDD_VERSION
|
||||
else
|
||||
$(warning ld.lld not found, cannot enable LTO mode)
|
||||
LLVM_LTO = 0
|
||||
endif
|
||||
endif
|
||||
else
|
||||
@ -272,11 +273,7 @@ ifeq "$(LLVM_LTO)" "1"
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fdebug-prefix-map=$(CURDIR)=llvm_mode -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_DEBUG_PREFIX = -fdebug-prefix-map="$(CURDIR)=llvm_mode"
|
||||
else
|
||||
AFL_CLANG_DEBUG_PREFIX =
|
||||
endif
|
||||
IS_IOS := $(findstring ios, $(shell $(CC) --version 2>/dev/null))
|
||||
|
||||
CFLAGS ?= -O3 -funroll-loops -fPIC
|
||||
# -D_FORTIFY_SOURCE=1
|
||||
@ -288,11 +285,15 @@ CFLAGS_SAFE := -Wall -g -Wno-cast-qual -Wno-variadic-macros -Wno-pointer-sig
|
||||
-DAFL_CLANG_FLTO=\"$(AFL_CLANG_FLTO)\" -DAFL_REAL_LD=\"$(AFL_REAL_LD)\" \
|
||||
-DAFL_CLANG_LDPATH=\"$(AFL_CLANG_LDPATH)\" -DAFL_CLANG_FUSELD=\"$(AFL_CLANG_FUSELD)\" \
|
||||
-DCLANG_BIN=\"$(CLANG_BIN)\" -DCLANGPP_BIN=\"$(CLANGPP_BIN)\" -DUSE_BINDIR=$(USE_BINDIR) \
|
||||
-Wno-unused-function $(AFL_CLANG_DEBUG_PREFIX)
|
||||
-Wno-unused-function
|
||||
ifndef LLVM_DEBUG
|
||||
CFLAGS_SAFE += -Wno-deprecated
|
||||
endif
|
||||
|
||||
ifdef IOS_SDK_PATH
|
||||
override CFLAGS_SAFE += -isysroot $(IOS_SDK_PATH)
|
||||
endif
|
||||
|
||||
ifdef CODE_COVERAGE
|
||||
override CFLAGS_SAFE += -D__AFL_CODE_COVERAGE=1
|
||||
override LDFLAGS += -ldl
|
||||
@ -310,6 +311,10 @@ override CXXFLAGS += -Wall -g -I ./include/ \
|
||||
-DVERSION=\"$(VERSION)\" -Wno-variadic-macros -Wno-deprecated-copy-with-dtor \
|
||||
-DLLVM_MINOR=$(LLVM_MINOR) -DLLVM_MAJOR=$(LLVM_MAJOR)
|
||||
|
||||
ifdef IOS_SDK_PATH
|
||||
override CXXFLAGS += -isysroot $(IOS_SDK_PATH)
|
||||
endif
|
||||
|
||||
ifneq "$(shell $(LLVM_CONFIG) --includedir) 2> /dev/null" ""
|
||||
CLANG_CFL = -I$(shell $(LLVM_CONFIG) --includedir)
|
||||
endif
|
||||
@ -356,7 +361,7 @@ ifeq "$(TEST_MMAP)" "1"
|
||||
LDFLAGS += -Wno-deprecated-declarations
|
||||
endif
|
||||
|
||||
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
|
||||
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
|
||||
PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./cmplog-switches-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./SanitizerCoverageLTO.so ./injection-pass.so
|
||||
|
||||
# If prerequisites are not given, warn, do not build anything, and exit with code 0
|
||||
@ -431,29 +436,44 @@ ifeq "$(LLVM_LTO)" "1"
|
||||
@ln -sf afl-cc ./afl-lto++
|
||||
endif
|
||||
endif
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
instrumentation/afl-llvm-common.o: instrumentation/afl-llvm-common.cc instrumentation/afl-llvm-common.h
|
||||
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
||||
$(CXX) $(CFLAGS) $(CPPFLAGS) $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -c $< -o $@
|
||||
|
||||
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
ifeq "$(LLVM_MIN_4_0_1)" "0"
|
||||
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
|
||||
endif
|
||||
$(CXX) $(CLANG_CPPFL) -Wdeprecated -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
./SanitizerCoveragePCGUARD.so: instrumentation/SanitizerCoveragePCGUARD.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
ifeq "$(LLVM_13_OK)" "1"
|
||||
-$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) -Wno-deprecated-copy-dtor -Wdeprecated instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
endif
|
||||
|
||||
./afl-llvm-lto-instrumentlist.so: instrumentation/afl-llvm-lto-instrumentlist.so.cc instrumentation/afl-llvm-common.o
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CXX) $(CLANG_CPPFL) -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
endif
|
||||
|
||||
./afl-ld-lto: src/afl-ld-lto.c
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
$(CC) $(CFLAGS) $(CPPFLAGS) $< -o $@
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
endif
|
||||
|
||||
./SanitizerCoverageLTO.so: instrumentation/SanitizerCoverageLTO.so.cc instrumentation/afl-llvm-common.o
|
||||
@ -462,31 +482,58 @@ ifeq "$(LLVM_LTO)" "1"
|
||||
$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto.o
|
||||
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m64 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-64.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
|
||||
@$(CLANG_BIN) $(CFLAGS_SAFE) $(CPPFLAGS) -Wno-unused-result -O0 $(AFL_CLANG_FLTO) -m32 -fPIC -c instrumentation/afl-llvm-rt-lto.o.c -o ./afl-llvm-rt-lto-32.o 2>/dev/null; if [ "$$?" = "0" ]; then : ; fi
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
endif
|
||||
|
||||
# laf
|
||||
./split-switches-pass.so: instrumentation/split-switches-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
./compare-transform-pass.so: instrumentation/compare-transform-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
./split-compares-pass.so: instrumentation/split-compares-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
# /laf
|
||||
|
||||
./cmplog-routines-pass.so: instrumentation/cmplog-routines-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
./cmplog-instructions-pass.so: instrumentation/cmplog-instructions-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
./cmplog-switches-pass.so: instrumentation/cmplog-switches-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
afl-llvm-dict2file.so: instrumentation/afl-llvm-dict2file.so.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
./injection-pass.so: instrumentation/injection-pass.cc instrumentation/afl-llvm-common.o | test_deps
|
||||
$(CXX) $(CLANG_CPPFL) -shared $< -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
.PHONY: document
|
||||
document:
|
||||
@ -509,6 +556,9 @@ document:
|
||||
test_build: $(PROGS)
|
||||
@echo "[*] Testing the CC wrapper and instrumentation output..."
|
||||
unset AFL_USE_ASAN AFL_USE_MSAN AFL_INST_RATIO AFL_LLVM_ALLOWLIST AFL_LLVM_DENYLIST; ASAN_OPTIONS=detect_leaks=0 AFL_QUIET=1 AFL_PATH=. AFL_LLVM_LAF_ALL=1 ./afl-cc $(CFLAGS) $(CPPFLAGS) ./test-instr.c -o test-instr $(LDFLAGS)
|
||||
ifdef IS_IOS
|
||||
@ldid -Sentitlements.plist test-instr && echo "[+] Signed test-instr" || echo "[-] Failed to sign test-instr"
|
||||
endif
|
||||
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
|
||||
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
|
||||
@rm -f test-instr
|
||||
|
@ -2,9 +2,9 @@
|
||||
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250">
|
||||
|
||||
Release version: [4.31c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.32c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.31c
|
||||
GitHub version: 4.32c
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
@ -16,7 +16,6 @@ AFL++ is maintained by:
|
||||
* Andrea Fioraldi <andreafioraldi@gmail.com>
|
||||
* Heiko "hexcoder-" Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
* frida_mode is maintained by @Worksbutnottested
|
||||
* Documentation: Jana Aydinbas <jana.aydinbas@gmail.com>
|
||||
|
||||
Originally developed by Michal "lcamtuf" Zalewski.
|
||||
|
||||
@ -230,7 +229,8 @@ Thank you! (For people sending pull requests - please add yourself to this list
|
||||
Ruben ten Hove Joey Jiao
|
||||
fuzzah @intrigus-lgtm
|
||||
Yaakov Saxon Sergej Schumilo
|
||||
Ziqiao Kong
|
||||
Ziqiao Kong Ryan Berger
|
||||
Sangjun Park
|
||||
```
|
||||
|
||||
</details>
|
||||
|
4
afl-cmin
4
afl-cmin
@ -331,7 +331,7 @@ BEGIN {
|
||||
}
|
||||
|
||||
if (0 == system ( "grep -aq AFL_DUMP_MAP_SIZE " target_bin )) {
|
||||
echo "[!] Trying to obtain the map size of the target ..."
|
||||
print "[!] Trying to obtain the map size of the target ..."
|
||||
get_map_size = "AFL_DUMP_MAP_SIZE=1 " target_bin
|
||||
get_map_size | getline mapsize
|
||||
close(get_map_size)
|
||||
@ -432,7 +432,7 @@ BEGIN {
|
||||
} else {
|
||||
stat_format = "-f '%z %N'" # *BSD, MacOS
|
||||
}
|
||||
cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o -type f -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'"
|
||||
cmdline = "(cd "in_dir" && find . \\( ! -name \".*\" -a -type d \\) -o \\( -type f -a ! -name \"cmdline\" -a ! -name \"fastresume.bin\" -a ! -name \"fuzz_bitmap\" -a ! -name \"fuzzer_setup\" -a ! -name \"fuzzer_stats\" -a ! -name \"plot_data\" -a ! -name \"target_hash\" \\) -exec stat "stat_format" \\{\\} + | sort -k1n -k2r) | grep -Ev '^0'"
|
||||
#cmdline = "ls "in_dir" | (cd "in_dir" && xargs stat "stat_format" 2>/dev/null) | sort -k1n -k2r"
|
||||
#cmdline = "(cd "in_dir" && stat "stat_format" *) | sort -k1n -k2r"
|
||||
#cmdline = "(cd "in_dir" && ls | xargs stat "stat_format" ) | sort -k1n -k2r"
|
||||
|
@ -121,6 +121,7 @@ kernel.sched_child_runs_first=1
|
||||
kernel.sched_autogroup_enabled=1
|
||||
kernel.sched_migration_cost_ns=50000000
|
||||
kernel.sched_latency_ns=250000000
|
||||
vm.swappiness=10
|
||||
EOF
|
||||
}
|
||||
|
||||
@ -129,7 +130,7 @@ EOF
|
||||
if ! grep -E "^$KEY=" /etc/default/grub | grep -E -q 'noibrs pcid nopti'; then
|
||||
echo "Configuring performance boot options"
|
||||
LINE=`grep -E "^$KEY=" /etc/default/grub | sed "s/^$KEY=//" | tr -d '"'`
|
||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||
OPTIONS="$LINE ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off nokaslr no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"
|
||||
echo Setting boot options in /etc/default/grub to $KEY=\"$OPTIONS\"
|
||||
sed -i "s|^$KEY=.*|$KEY=\"$OPTIONS\"|" /etc/default/grub
|
||||
fi
|
||||
|
@ -41,6 +41,7 @@ if [ "$PLATFORM" = "Linux" ] ; then
|
||||
sysctl -w kernel.sched_autogroup_enabled=1
|
||||
sysctl -w kernel.sched_migration_cost_ns=50000000 2>/dev/null
|
||||
sysctl -w kernel.sched_latency_ns=250000000 2>/dev/null
|
||||
sysctl -w vm.swappiness=10 2>/dev/null
|
||||
echo never > /sys/kernel/mm/transparent_hugepage/enabled
|
||||
test -e /sys/devices/system/cpu/cpufreq/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/scaling_governor
|
||||
test -e /sys/devices/system/cpu/cpufreq/policy0/scaling_governor && echo performance | tee /sys/devices/system/cpu/cpufreq/policy*/scaling_governor
|
||||
@ -54,7 +55,7 @@ if [ "$PLATFORM" = "Linux" ] ; then
|
||||
echo
|
||||
dmesg | grep -E -q 'noibrs pcid nopti' || {
|
||||
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
|
||||
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
|
||||
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=off l1tf=off spec_rstack_overflow=off mds=off nokaslr no_stf_barrier noibpb noibrs pcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=on pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx=on tsx_async_abort=off mitigations=off audit=0 hardened_usercopy=off ssbd=force-off"'
|
||||
echo
|
||||
}
|
||||
echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed.
|
||||
|
@ -3,6 +3,25 @@
|
||||
This is the list of all noteworthy changes made in every public
|
||||
release of the tool. See README.md for the general instruction manual.
|
||||
|
||||
### Version ++4.32c (release)
|
||||
- Fixed a bug where after a fast restart of a full fuzzed corpus afl-fuzz
|
||||
terminates with "need at least one valid input seed that does not crash"
|
||||
- Small improvements to afl-*-config
|
||||
- afl-fuzz:
|
||||
- memory leak fixes by @kcwu - thanks!
|
||||
- many more nits and small memory saves thanks to @kcwu
|
||||
- remove deprecated files from queue/.state
|
||||
- fix bitmap update function if no current trace is present
|
||||
- fix for afl_custom_queue_get
|
||||
- various small nits
|
||||
- afl-cc:
|
||||
- fix pass support for LLVM 20 (passes were run too early)
|
||||
- dropped plugin support for LLVM 13
|
||||
- fix AFL_OLD_FORKSERVER
|
||||
- various minor fixes
|
||||
- frida_mode:
|
||||
- fixes for new MacOS + M4 hardware
|
||||
|
||||
|
||||
### Version ++4.31c (release)
|
||||
- SAND mode added (docs/SAND.md) for more effecient fuzzing with sanitizers
|
||||
@ -10,7 +29,7 @@
|
||||
- afl-fuzz:
|
||||
- splicing phase is now DISABLED by default because research showed
|
||||
it is counterproductive. New command line parameter `-u` to enable
|
||||
it. Splicing is auto-enabled if two cycles without finds happen.
|
||||
it.
|
||||
- Python 3.13+ support
|
||||
- loose file and shared memory permissions on Android and iPhone
|
||||
- afl-cc:
|
||||
@ -22,7 +41,6 @@
|
||||
- fix bug with large map sizes when multiple libraries are loaded after
|
||||
the shared memory was obtained.
|
||||
|
||||
|
||||
### Version ++4.30c (release)
|
||||
! afl-gcc and afl-clang funcionality is now removed !
|
||||
- afl-fuzz:
|
||||
|
@ -236,7 +236,7 @@ If you find an interesting or important question missing, submit it via
|
||||
[AFLFast](https://github.com/mboehme/aflfast), however, modified to be more
|
||||
effective and several more modes added.
|
||||
|
||||
The most effective modes are `-p fast` (default) and `-p explore`.
|
||||
The most effective modes are `-p explore` (default) and `-p fast`.
|
||||
|
||||
If you fuzz with several parallel afl-fuzz instances, then it is beneficial
|
||||
to assign a different schedule to each instance, however the majority should
|
||||
|
@ -169,3 +169,47 @@ and definitely don't look POSIX-compliant. This means two things:
|
||||
User emulation mode of QEMU does not appear to be supported on macOS, so
|
||||
black-box instrumentation mode (`-Q`) will not work. However, FRIDA mode (`-O`)
|
||||
works on both x86 and arm64 macOS boxes.
|
||||
|
||||
## iOS on arm64 and arm64e
|
||||
|
||||
**Option 1: Compilation on jailbroken iOS (recommended)**
|
||||
|
||||
To compile directly on a jailbroken iOS device, it is recommended to use a jailbreak that supports Procursus,
|
||||
as Procursus provides up-to-date pre-built packages for the required tools.
|
||||
|
||||
Ensure `openssh` is installed on your iOS device, then SSH into it.
|
||||
Install the following packages:
|
||||
|
||||
```shell
|
||||
sudo apt install wget git make cmake clang gawk llvm ldid coreutils build-essential xz-utils
|
||||
```
|
||||
|
||||
Configure the environment for compilation:
|
||||
|
||||
```shell
|
||||
export IOS_SDK_PATH="/usr/share/SDKs/iPhoneOS.sdk"
|
||||
export CC=clang
|
||||
export CXX=clang++
|
||||
```
|
||||
|
||||
Then build following the general Linux instructions.
|
||||
|
||||
**Option 2: Cross-Compilation on macOS for Jailbroken iOS**
|
||||
|
||||
In addition to the packages required for a macOS build, install `ldid` for signing binaries:
|
||||
|
||||
```shell
|
||||
brew install ldid-procursus
|
||||
```
|
||||
|
||||
Configure the environment for compilation:
|
||||
|
||||
```shell
|
||||
export IOS_SDK_PATH="$(xcrun --sdk iphoneos --show-sdk-path)"
|
||||
export CC="$(xcrun --sdk iphoneos -f clang) -target arm64-apple-ios14.0"
|
||||
export CXX="$(xcrun --sdk iphoneos -f clang++) -target arm64-apple-ios14.0"
|
||||
export HOST_CC=cc
|
||||
```
|
||||
|
||||
Then build following the general Linux instructions.
|
||||
Finally, transfer the binaries to your iOS device.
|
||||
|
@ -385,10 +385,6 @@ there are several things to look at:
|
||||
subsequent iterations (e.g., due to incomplete clean-up or reinitialization of
|
||||
the state) and that most of the fuzzing effort goes to waste.
|
||||
|
||||
The paths where variable behavior is detected are marked with a matching entry
|
||||
in the `<out_dir>/queue/.state/variable_behavior/` directory, so you can look
|
||||
them up easily.
|
||||
|
||||
### CPU load
|
||||
|
||||
```
|
||||
|
@ -107,6 +107,7 @@ fairly broad use of environment variables instead:
|
||||
conditions
|
||||
- `AFL_USE_UBSAN=1` - activates the undefined behavior sanitizer
|
||||
- `AFL_UBSAN_VERBOSE=1` - outputs detailed diagnostic information when undefined behavior is detected, instead of simply terminating with "Illegal Instruction"
|
||||
. `AFL_USE_RTSAN` . activates the realtime sanitizer (realtime violations in deterministic run time constraints). (clang 20 minimum)
|
||||
|
||||
- Note: both `AFL_CFISAN_VERBOSE=1` and `AFL_UBSAN_VERBOSE=1` are disabled by default as verbose output can significantly slow down fuzzing performance. Use these options only during debugging or when additional crash diagnostics are required
|
||||
|
||||
|
@ -106,6 +106,7 @@ Among others, the following features and patches have been integrated:
|
||||
* Win32 PE binary-only fuzzing with QEMU and Wine
|
||||
* AFLfast's power schedules by Marcel Böhme:
|
||||
[https://github.com/mboehme/aflfast](https://github.com/mboehme/aflfast)
|
||||
* The fast deterministic stage by Han Zheng: [https://github.com/hexhive/mendelFuzz-Artifact/](https://github.com/hexhive/mendelFuzz-Artifact/)
|
||||
* The MOpt mutator:
|
||||
[https://github.com/puppet-meteor/MOpt-AFL](https://github.com/puppet-meteor/MOpt-AFL)
|
||||
* LLVM mode Ngram coverage by Adrian Herrera
|
||||
|
@ -247,6 +247,12 @@ CFISAN. You might need to experiment which sanitizers you can combine in a
|
||||
target (which means more instances can be run without a sanitized target, which
|
||||
is more effective).
|
||||
|
||||
Note that some sanitizers (MSAN and LSAN) exit with a particular exit code
|
||||
instead of aborting. afl-fuzz treats these exit codes as a crash when these
|
||||
sanitizers are enabled. If the target uses these exit codes there could be false
|
||||
positives among the saved crashes. LSAN uses exit code 23 and MSAN uses exit
|
||||
code 86.
|
||||
|
||||
### d) Modifying the target
|
||||
|
||||
If the target has features that make fuzzing more difficult, e.g., checksums,
|
||||
@ -496,6 +502,8 @@ Note:
|
||||
protection against attacks! So set strong firewall rules and only expose SSH
|
||||
as a network service if you use these (which is highly recommended).
|
||||
|
||||
If you execute afl-fuzz in a Docker container, it is recommended to pass [`--cpuset-cpus`](https://docs.docker.com/engine/containers/resource_constraints/#configure-the-default-cfs-scheduler) option with free CPU cores to docker daemon when starting the container, or pass `AFL_NO_AFFINITY` to afl-fuzz. This is due to the fact that AFL++ will bind to a free CPU core by default, while Docker container will prevent AFL++ instance from seeing processes in other containers or host, which leads to all AFL++ instances trying to bind the same CPU core.
|
||||
|
||||
If you have an input corpus from [step 2](#2-preparing-the-fuzzing-campaign),
|
||||
then specify this directory with the `-i` option. Otherwise, create a new
|
||||
directory and create a file with any content as test data in there.
|
||||
@ -627,8 +635,8 @@ The other secondaries should be run like this:
|
||||
* 40% should run with `-P explore` and 20% with `-P exploit`
|
||||
* If you use `-a` then set 30% of the instances to not use `-a`; if you did
|
||||
not set `-a` (why??), then set 30% to `-a ascii` and 30% to `-a binary`.
|
||||
* run each with a different power schedule, recommended are: `fast` (default),
|
||||
`explore`, `coe`, `lin`, `quad`, `exploit`, and `rare` which you can set with
|
||||
* run each with a different power schedule, recommended are: `explore` (default),
|
||||
`fast`, `coe`, `lin`, `quad`, `exploit`, and `rare` which you can set with
|
||||
the `-p` option, e.g., `-p explore`. See the
|
||||
[FAQ](FAQ.md#what-are-power-schedules) for details.
|
||||
|
||||
|
29
entitlements.plist
Normal file
29
entitlements.plist
Normal file
@ -0,0 +1,29 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/ PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>research.com.apple.license-to-operate</key> <true/>
|
||||
<key>application-identifier</key> <string>aflplusplus</string>
|
||||
<key>com.apple.asl.access_as_root</key> <true/>
|
||||
<key>com.apple.backboardd.launchapplications</key> <true/>
|
||||
<key>com.apple.companionappd.connect.allow</key> <true/>
|
||||
<key>com.apple.multitasking.termination</key> <true/>
|
||||
<key>com.apple.private.security.container-required</key> <false/>
|
||||
<key>com.apple.seld.cm</key> <true/>
|
||||
<key>com.apple.sh</key> <true/>
|
||||
<key>com.apple.private.thread-set-state</key> <true/>
|
||||
<key>com.apple.private.cs.debugger</key> <true/>
|
||||
<key>com.apple.springboard.debugapplications</key> <true/>
|
||||
<key>com.apple.springboard.launchapplications</key> <true/>
|
||||
<key>com.apple.springboard.opensensitiveurl</key> <true/>
|
||||
<key>dynamic-codesigning</key> <true/>
|
||||
<key>get-task-allow</key> <true/>
|
||||
<key>platform-application</key> <true/>
|
||||
<key>run-unsigned-code</key> <true/>
|
||||
<key>task_for_pid-allow</key> <true/>
|
||||
<key>com.apple.private.skip-library-validation</key> <true/>
|
||||
<key>com.apple.private.amfi.can-load-cdhash</key> <true/>
|
||||
<key>com.apple.private.amfi.can-execute-cdhash</key> <true/>
|
||||
<key>com.apple.private.security.no-container</key> <true/>
|
||||
</dict>
|
||||
</plist>
|
@ -19,11 +19,15 @@ TARGET_CC?=$(CC)
|
||||
TARGET_CXX?=$(CXX)
|
||||
HOST_CC?=$(CC)
|
||||
HOST_CXX?=$(CXX)
|
||||
IS_ANDROID:=$(findstring android, $(shell $(TARGET_CC) --version 2>/dev/null))
|
||||
IS_x86:=$(findstring i686, $(shell $(TARGET_CC) --version 2>/dev/null))
|
||||
IS_x86_64:=$(findstring x86_64, $(shell $(TARGET_CC) --version 2>/dev/null))
|
||||
IS_ARM:=$(findstring arm, $(shell $(TARGET_CC) --version 2>/dev/null))
|
||||
IS_ARM64:=$(findstring aarch64, $(shell $(TARGET_CC) --version 2>/dev/null))
|
||||
TARGET_CC_INFO=$(shell $(TARGET_CC) --version)
|
||||
IS_IOS:=$(findstring ios, $(TARGET_CC_INFO))
|
||||
IS_SIMULATOR:=$(findstring sim, $(TARGET_CC_INFO))
|
||||
IS_ANDROID:=$(findstring android, $(TARGET_CC_INFO))
|
||||
IS_x86:=$(findstring i686, $(TARGET_CC_INFO))
|
||||
IS_x86_64:=$(findstring x86_64, $(TARGET_CC_INFO))
|
||||
IS_ARM:=$(findstring arm, $(TARGET_CC_INFO))
|
||||
IS_ARM64E:=$(findstring arm64e, $(TARGET_CC_INFO))
|
||||
IS_ARM64 := $(or $(findstring aarch64,$(TARGET_CC_INFO)), $(findstring arm64,$(TARGET_CC_INFO)))
|
||||
CFLAGS+=-fPIC \
|
||||
-D_GNU_SOURCE \
|
||||
-D_FORTIFY_SOURCE=2 \
|
||||
@ -95,7 +99,24 @@ endif
|
||||
|
||||
GUM_ARCH="-$(ARCH)"
|
||||
|
||||
ifeq "$(shell uname)" "Darwin"
|
||||
ifdef IS_IOS
|
||||
OS:=ios
|
||||
ifdef IS_SIMULATOR
|
||||
ifdef IS_x86_64
|
||||
ARCH := x86_64-simulator
|
||||
else ifdef IS_ARM64
|
||||
ARCH := arm64-simulator
|
||||
endif
|
||||
else
|
||||
ifdef IS_ARM64E
|
||||
ARCH := arm64e
|
||||
else ifdef IS_ARM64
|
||||
ARCH := arm64
|
||||
endif
|
||||
endif
|
||||
override CFLAGS += -isysroot $(IOS_SDK_PATH)
|
||||
override LDFLAGS += -L$(IOS_SDK_PATH)/usr/lib
|
||||
else ifeq "$(shell uname)" "Darwin"
|
||||
OS:=macos
|
||||
AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations
|
||||
GUM_ARCH:=""
|
||||
@ -165,10 +186,32 @@ ifndef OS
|
||||
$(error "Operating system unsupported")
|
||||
endif
|
||||
|
||||
GUM_DEVKIT_VERSION=16.0.11
|
||||
GUM_DEVKIT_VERSION=16.1.11
|
||||
GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
|
||||
GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
|
||||
|
||||
ifeq ($(OS),macos)
|
||||
# Extract the major version
|
||||
GUM_VERSION_MAJOR := $(shell echo "$(GUM_DEVKIT_VERSION)" | sed -E 's/\..*//')
|
||||
# Extract the minor version (assumes format "MAJOR.MINOR[.PATCH...]")
|
||||
GUM_VERSION_MINOR := $(shell echo "$(GUM_DEVKIT_VERSION)" | sed -E 's/^[^.]*\.//; s/\..*//')
|
||||
|
||||
# Evaluate the version condition in a separate shell call
|
||||
IS_GUM_16_6_PLUS := $(shell \
|
||||
if (( $(GUM_VERSION_MAJOR) > 16 || ( $(GUM_VERSION_MAJOR) == 16 && $(GUM_VERSION_MINOR) >= 6 ) )); then \
|
||||
echo 1; \
|
||||
fi)
|
||||
else
|
||||
IS_GUM_16_6_PLUS := $(shell VERSION="$(GUM_DEVKIT_VERSION)"; \
|
||||
MAJOR=$${VERSION%%.*}; \
|
||||
MINOR=$${VERSION#*.}; MINOR=$${MINOR%%.*}; \
|
||||
if [ $$MAJOR -gt 16 ] || { [ $$MAJOR -eq 16 ] && [ $$MINOR -ge 6 ]; }; then \
|
||||
echo 1; \
|
||||
fi)
|
||||
endif
|
||||
|
||||
CFLAGS += $(if $(IS_GUM_16_6_PLUS),-DGUM_16_6_PLUS)
|
||||
|
||||
GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
|
||||
ifdef FRIDA_SOURCE
|
||||
GUM_DEVIT_LIBRARY=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gumjs-1.0.a
|
||||
@ -373,6 +416,11 @@ $(AFL_PERFORMANCE_OBJ): $(AFL_PERFORMANCE_SRC)
|
||||
|
||||
$(BIN2C): $(BIN2C_SRC)
|
||||
$(HOST_CC) -D_GNU_SOURCE -o $@ $<
|
||||
ifdef IS_IOS
|
||||
ifeq ($(HOST_CC),$(TARGET_CC))
|
||||
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
endif
|
||||
|
||||
$(JS_SRC): $(JS) $(BIN2C)| $(BUILD_DIR)
|
||||
cd $(JS_DIR) && $(BIN2C) api_js $(JS) $@
|
||||
@ -413,8 +461,10 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL
|
||||
$(TRACE_LDFLAGS) \
|
||||
$(LDFLAGS) \
|
||||
$(LDSCRIPT) \
|
||||
-o $@ \
|
||||
|
||||
-o $@
|
||||
ifdef IS_IOS
|
||||
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
cp -v $(FRIDA_TRACE) $(ROOT)
|
||||
|
||||
$(FRIDA_TRACE_LIB): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL_COMPILER_RT_OBJ) $(AFL_PERFORMANCE_OBJ) GNUmakefile | $(BUILD_DIR)
|
||||
@ -430,9 +480,15 @@ $(FRIDA_TRACE_LIB): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $
|
||||
|
||||
$(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR)
|
||||
$(TARGET_CC) $(CFLAGS) $(LDFLAGS) -I $(FRIDA_BUILD_DIR) $< -o $@
|
||||
ifdef IS_IOS
|
||||
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
$(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR)
|
||||
$(TARGET_CC) $(CFLAGS) $(LDFLAGS) $< -o $@
|
||||
ifdef IS_IOS
|
||||
@ldid -S../entitlements.plist $@ && echo "[+] Signed $@" || { echo "[-] Failed to sign $@"; }
|
||||
endif
|
||||
|
||||
hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ)
|
||||
|
||||
|
@ -27,6 +27,27 @@ void asan_init(void) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef GUM_16_6_PLUS
|
||||
static gboolean asan_exclude_module(GumModule *module, gpointer user_data) {
|
||||
|
||||
gchar *symbol_name = (gchar *)user_data;
|
||||
GumAddress address;
|
||||
const GumMemoryRange *range = gum_module_get_range(module);
|
||||
|
||||
address = gum_module_find_export_by_name(module, symbol_name);
|
||||
if (address == 0) { return TRUE; }
|
||||
|
||||
/* If the reported address of the symbol is outside of the range of the module
|
||||
* then ignore it */
|
||||
if (address < range->base_address) { return TRUE; }
|
||||
if (address > (range->base_address + range->size)) { return TRUE; }
|
||||
|
||||
ranges_add_exclude((GumMemoryRange *)range);
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
static gboolean asan_exclude_module(const GumModuleDetails *details,
|
||||
gpointer user_data) {
|
||||
|
||||
@ -50,6 +71,8 @@ static gboolean asan_exclude_module(const GumModuleDetails *details,
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
void asan_exclude_module_by_symbol(gchar *symbol_name) {
|
||||
|
||||
gum_process_enumerate_modules(asan_exclude_module, symbol_name);
|
||||
|
@ -39,6 +39,25 @@ typedef struct {
|
||||
static guint64 text_base = 0;
|
||||
static guint64 text_limit = 0;
|
||||
|
||||
#ifdef GUM_16_6_PLUS
|
||||
static gboolean lib_find_exe(GumModule *module, gpointer user_data) {
|
||||
|
||||
lib_details_t *lib_details = (lib_details_t *)user_data;
|
||||
const gchar *name = gum_module_get_name(module);
|
||||
const gchar *path = gum_module_get_path(module);
|
||||
const GumMemoryRange *range = gum_module_get_range(module);
|
||||
|
||||
strncpy(lib_details->name, name, PATH_MAX);
|
||||
strncpy(lib_details->path, path, PATH_MAX);
|
||||
lib_details->name[PATH_MAX] = '\0';
|
||||
lib_details->path[PATH_MAX] = '\0';
|
||||
lib_details->base_address = range->base_address;
|
||||
lib_details->size = range->size;
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
static gboolean lib_find_exe(const GumModuleDetails *details,
|
||||
gpointer user_data) {
|
||||
|
||||
@ -54,6 +73,8 @@ static gboolean lib_find_exe(const GumModuleDetails *details,
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void lib_validate_hdr(Elf_Ehdr *hdr) {
|
||||
|
||||
if (hdr->e_ident[0] != ELFMAG0) FFATAL("Invalid e_ident[0]");
|
||||
|
@ -12,6 +12,25 @@ extern void gum_darwin_enumerate_modules(mach_port_t task,
|
||||
static guint64 text_base = 0;
|
||||
static guint64 text_limit = 0;
|
||||
|
||||
#ifdef GUM_16_6_PLUS
|
||||
static gboolean lib_get_main_module(GumModule *module, gpointer user_data) {
|
||||
|
||||
GumDarwinModule **ret = (GumDarwinModule **)user_data;
|
||||
const gchar *path = gum_module_get_path(module);
|
||||
const GumMemoryRange *range = gum_module_get_range(module);
|
||||
GumDarwinModule *darwin_module = gum_darwin_module_new_from_memory(
|
||||
path, mach_task_self(), range->base_address, GUM_DARWIN_MODULE_FLAGS_NONE,
|
||||
NULL);
|
||||
|
||||
FVERBOSE("Found main module: %s", darwin_module->name);
|
||||
|
||||
*ret = darwin_module;
|
||||
|
||||
return FALSE;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
static gboolean lib_get_main_module(const GumModuleDetails *details,
|
||||
gpointer user_data) {
|
||||
|
||||
@ -28,6 +47,8 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
|
||||
gpointer user_data) {
|
||||
|
||||
|
@ -295,6 +295,8 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* CALL INSTRUMENTED PERSISTENT FUNC
|
||||
* JMP loop
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
@ -302,15 +304,25 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* This is the location our epilogue should be written below */
|
||||
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
/*
|
||||
* Store a pointer to where we should return for our next iteration.
|
||||
* This is the location our epilogue should branch to
|
||||
*/
|
||||
persistent_loop = gum_arm64_writer_cur(cw);
|
||||
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
gconstpointer loop = cw->code + 1;
|
||||
gum_arm64_writer_put_label(cw, loop);
|
||||
|
||||
/*
|
||||
* call __afl_persistent_loop which will _exit if we have reached our
|
||||
* loop count. Also reset our previous_pc
|
||||
*/
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
@ -319,6 +331,27 @@ void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
|
||||
gconstpointer original = cw->code + 1;
|
||||
|
||||
/*
|
||||
* Call our original code, that way we regain control if our target
|
||||
* function returns without reaching the epilogue as an additional
|
||||
* safety net
|
||||
*/
|
||||
gum_arm64_writer_put_bl_label(cw, original);
|
||||
|
||||
/*
|
||||
* Return for our next iteration if our original function returns
|
||||
* and control hasn't reached the epilogue for some reason
|
||||
*/
|
||||
gum_arm64_writer_put_b_label(cw, loop);
|
||||
|
||||
/*
|
||||
* The original code for our target function will be emitted
|
||||
* immediately following this
|
||||
*/
|
||||
gum_arm64_writer_put_label(cw, original);
|
||||
|
||||
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
|
||||
|
||||
}
|
||||
|
@ -263,8 +263,13 @@ static int prefetch_on_fork(void) {
|
||||
|
||||
static void prefetch_hook_fork(void) {
|
||||
|
||||
#ifdef GUM_16_6_PLUS
|
||||
void *fork_addr =
|
||||
GSIZE_TO_POINTER(gum_module_find_global_export_by_name("fork"));
|
||||
#else
|
||||
void *fork_addr =
|
||||
GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork"));
|
||||
#endif
|
||||
intercept_hook(fork_addr, prefetch_on_fork, NULL);
|
||||
|
||||
}
|
||||
|
@ -116,6 +116,29 @@ static void convert_address_token(gchar *token, GumMemoryRange *range) {
|
||||
|
||||
}
|
||||
|
||||
#ifdef GUM_16_6_PLUS
|
||||
static gboolean convert_name_token_for_module(GumModule *module,
|
||||
gpointer user_data) {
|
||||
|
||||
convert_name_ctx_t *ctx = (convert_name_ctx_t *)user_data;
|
||||
const GumMemoryRange *range = gum_module_get_range(module);
|
||||
const gchar *path = gum_module_get_path(module);
|
||||
if (path == NULL) { return true; };
|
||||
|
||||
if (!g_str_has_suffix(path, ctx->suffix)) { return true; };
|
||||
|
||||
FVERBOSE("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
|
||||
"x-0x%016" G_GINT64_MODIFIER "x %s",
|
||||
ctx->suffix, range->base_address, range->base_address + range->size,
|
||||
path);
|
||||
|
||||
*ctx->range = *range;
|
||||
ctx->done = true;
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
static gboolean convert_name_token_for_module(const GumModuleDetails *details,
|
||||
gpointer user_data) {
|
||||
|
||||
@ -135,6 +158,8 @@ static gboolean convert_name_token_for_module(const GumModuleDetails *details,
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
static void convert_name_token(gchar *token, GumMemoryRange *range) {
|
||||
|
||||
gchar *suffix = g_strconcat("/", token, NULL);
|
||||
|
@ -353,6 +353,8 @@ enum {
|
||||
|
||||
};
|
||||
|
||||
#define FAST_RESUME_VERSION 0x01000000
|
||||
|
||||
/* Python stuff */
|
||||
#ifdef USE_PYTHON
|
||||
|
||||
@ -719,6 +721,8 @@ typedef struct afl_state {
|
||||
|
||||
struct queue_entry **top_rated; /* Top entries for bitmap bytes */
|
||||
|
||||
u32 **top_rated_candidates; /* Candidate IDs per bitmap index */
|
||||
|
||||
struct extra_data *extras; /* Extra tokens to fuzz with */
|
||||
u32 extras_cnt; /* Total number of tokens read */
|
||||
|
||||
@ -860,6 +864,8 @@ typedef struct afl_state {
|
||||
|
||||
struct skipdet_global *skipdet_g;
|
||||
|
||||
s64 last_scored_idx; /* Index of the last queue entry re-scored */
|
||||
|
||||
#ifdef INTROSPECTION
|
||||
char mutation[8072];
|
||||
char m_tmp[4096];
|
||||
@ -1182,13 +1188,13 @@ void deinit_py(void *);
|
||||
/* Queue */
|
||||
|
||||
void mark_as_det_done(afl_state_t *, struct queue_entry *);
|
||||
void mark_as_variable(afl_state_t *, struct queue_entry *);
|
||||
void mark_as_redundant(afl_state_t *, struct queue_entry *, u8);
|
||||
void add_to_queue(afl_state_t *, u8 *, u32, u8);
|
||||
void destroy_queue(afl_state_t *);
|
||||
void update_bitmap_score(afl_state_t *, struct queue_entry *);
|
||||
void update_bitmap_score(afl_state_t *, struct queue_entry *, bool);
|
||||
void cull_queue(afl_state_t *);
|
||||
u32 calculate_score(afl_state_t *, struct queue_entry *);
|
||||
void recalculate_all_scores(afl_state_t *);
|
||||
void update_bitmap_rescore(afl_state_t *, struct queue_entry *, u32);
|
||||
|
||||
/* Bitmap */
|
||||
|
||||
@ -1338,7 +1344,6 @@ static inline u32 rand_below(afl_state_t *afl, u32 limit) {
|
||||
|
||||
ck_read(afl->fsrv.dev_urandom_fd, &afl->rand_seed, sizeof(afl->rand_seed),
|
||||
"/dev/urandom");
|
||||
// srandom(afl->rand_seed[0]);
|
||||
afl->rand_cnt = (RESEED_RNG / 2) + (afl->rand_seed[1] % RESEED_RNG);
|
||||
|
||||
}
|
||||
@ -1452,6 +1457,18 @@ static inline int permissive_create(afl_state_t *afl, const char *fn) {
|
||||
|
||||
}
|
||||
|
||||
static inline void bitmap_set(u8 *map, u32 index) {
|
||||
|
||||
map[index / 8] |= (1u << (index % 8));
|
||||
|
||||
}
|
||||
|
||||
static inline u8 bitmap_read(u8 *map, u32 index) {
|
||||
|
||||
return (map[index / 8] >> (index % 8)) & 1;
|
||||
|
||||
}
|
||||
|
||||
#if TESTCASE_CACHE == 1
|
||||
#error define of TESTCASE_CACHE must be zero or larger than 1
|
||||
#endif
|
||||
|
@ -31,7 +31,8 @@ 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};
|
||||
unsigned int safe_length = length >= 0 ? length : 0;
|
||||
struct ashmem_pin pin = {0, safe_length};
|
||||
ret = ioctl(__shmid, ASHMEM_UNPIN, &pin);
|
||||
close(__shmid);
|
||||
|
||||
|
@ -37,11 +37,12 @@
|
||||
|
||||
enum SanitizerAbstraction {
|
||||
|
||||
SIMPLIFY_TRACE = 0, // Feed all unique trace to sanitizers, the
|
||||
// most sensitive
|
||||
UNIQUE_TRACE,
|
||||
SIMPLIFY_TRACE = 0, // Feed all simplified trace to sanitizers, moderate
|
||||
// sensitive and default for SAND. Not missing bugs.
|
||||
UNIQUE_TRACE, // Feed all unique trace to sanitizers, the most sensitive
|
||||
// and not missing bugs.
|
||||
COVERAGE_INCREASE // Feed all coverage increasing cases to sanitizers, the
|
||||
// least sensitive
|
||||
// least sensitive at a risk of missing ~20% bugs.
|
||||
|
||||
};
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, a = volatile github dev, e = experimental branch
|
||||
#define VERSION "++4.31c"
|
||||
#define VERSION "++4.32c"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -171,7 +171,8 @@
|
||||
#define EXEC_TM_ROUND 20U
|
||||
|
||||
/* 64bit arch MACRO */
|
||||
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__))
|
||||
#if (defined(__x86_64__) || defined(__arm64__) || defined(__aarch64__) || \
|
||||
(defined(__riscv) && __riscv_xlen == 64))
|
||||
#define WORD_SIZE_64 1
|
||||
#endif
|
||||
|
||||
@ -200,8 +201,8 @@
|
||||
|
||||
/* Maximum number of unique hangs or crashes to record: */
|
||||
|
||||
#define KEEP_UNIQUE_HANG 500U
|
||||
#define KEEP_UNIQUE_CRASH 10000U
|
||||
#define KEEP_UNIQUE_HANG 512U
|
||||
#define KEEP_UNIQUE_CRASH 25600U
|
||||
|
||||
/* Baseline number of random tweaks during a single 'havoc' stage: */
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#ifndef _COVERAGE_H
|
||||
|
||||
#define _COVERAGE_H
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
|
||||
#define _AFL_INTSIZEVAR u32
|
||||
|
||||
u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end);
|
||||
u32 classify_word(u32 word);
|
||||
|
||||
@ -110,3 +116,5 @@ inline u32 skim(const u32 *virgin, const u32 *current, const u32 *current_end) {
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#ifndef _COVERAGE_H
|
||||
|
||||
#define _COVERAGE_H
|
||||
|
||||
#include "config.h"
|
||||
#include "types.h"
|
||||
|
||||
#define _AFL_INTSIZEVAR u64
|
||||
|
||||
#if (defined(__AVX512F__) && defined(__AVX512DQ__)) || defined(__AVX2__)
|
||||
#include <immintrin.h>
|
||||
#endif
|
||||
@ -72,22 +78,6 @@ inline void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
}
|
||||
|
||||
inline static void classify_counts_mem(u64 *mem, u32 size) {
|
||||
|
||||
u32 i = (size >> 3);
|
||||
|
||||
while (i--) {
|
||||
|
||||
/* Optimize for sparse bitmaps. */
|
||||
|
||||
if (unlikely(*mem)) { *mem = classify_word(*mem); }
|
||||
|
||||
mem++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Updates the virgin bits, then reflects whether a new count or a new tuple is
|
||||
* seen in ret. */
|
||||
inline void discover_word(u8 *ret, u64 *current, u64 *virgin) {
|
||||
@ -134,7 +124,7 @@ inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
|
||||
/* All bytes are zero. */
|
||||
if (likely(mask == 0xff)) continue;
|
||||
|
||||
/* Look for nonzero bytes and check for new bits. */
|
||||
/* Look for nonzero bytes and check for new bits. */
|
||||
#define UNROLL(x) \
|
||||
if (unlikely(!(mask & (1 << x)) && classify_word(current[x]) & virgin[x])) \
|
||||
return 1
|
||||
@ -208,3 +198,5 @@ inline u32 skim(const u64 *virgin, const u64 *current, const u64 *current_end) {
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -331,6 +331,7 @@ static inline const char *colorfilter(const char *x) {
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
fflush(stdout); \
|
||||
abort(); \
|
||||
\
|
||||
} while (0)
|
||||
|
@ -137,6 +137,8 @@ typedef struct afl_forkserver {
|
||||
|
||||
u8 last_kill_signal; /* Signal that killed the child */
|
||||
|
||||
u8 last_exit_code; /* Child exit code if counted as a crash */
|
||||
|
||||
bool use_shmem_fuzz; /* use shared mem for test cases */
|
||||
|
||||
bool support_shmem_fuzz; /* set by afl-fuzz */
|
||||
@ -155,7 +157,7 @@ typedef struct afl_forkserver {
|
||||
|
||||
bool no_unlink; /* do not unlink cur_input */
|
||||
|
||||
bool uses_asan; /* Target uses ASAN? */
|
||||
u8 uses_asan; /* Target uses ASAN/LSAN/MSAN? (bit 0/1/2 respectively) */
|
||||
|
||||
bool debug; /* debug mode? */
|
||||
|
||||
|
@ -3169,7 +3169,7 @@ static xxh_u32 XXH32_avalanche(xxh_u32 hash) {
|
||||
*/
|
||||
static XXH_PUREF xxh_u32 XXH32_finalize(xxh_u32 hash, const xxh_u8 *ptr,
|
||||
size_t len, XXH_alignment align) {
|
||||
\
|
||||
|
||||
#define XXH_PROCESS1 \
|
||||
do { \
|
||||
\
|
||||
|
@ -79,11 +79,11 @@ LLVM 13 to 19 should be available in all current Linux repositories.
|
||||
|
||||
That part is easy.
|
||||
Just set `LLVM_CONFIG` to the llvm-config-VERSION and build AFL++, e.g. for
|
||||
LLVM 15:
|
||||
LLVM 19:
|
||||
|
||||
```
|
||||
cd ~/AFLplusplus
|
||||
export LLVM_CONFIG=llvm-config-15
|
||||
export LLVM_CONFIG=llvm-config-19
|
||||
make
|
||||
sudo make install
|
||||
```
|
||||
@ -96,7 +96,7 @@ Also, the instrument file listing (AFL_LLVM_ALLOWLIST/AFL_LLVM_DENYLIST ->
|
||||
[README.instrument_list.md](README.instrument_list.md)) and laf-intel/compcov
|
||||
(AFL_LLVM_LAF_* -> [README.laf-intel.md](README.laf-intel.md)) work.
|
||||
|
||||
Example (note that you might need to add the version, e.g. `llvm-ar-15`:
|
||||
Example (note that you might need to add the version, e.g. `llvm-ar-19`:
|
||||
|
||||
```
|
||||
CC=afl-clang-lto CXX=afl-clang-lto++ RANLIB=llvm-ranlib AR=llvm-ar AS=llvm-as ./configure
|
||||
|
@ -2005,8 +2005,11 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
|
||||
|
||||
}
|
||||
|
||||
extra_ctx_inst += inst_in_this_func * (call_counter - 1);
|
||||
afl_global_id += extra_ctx_inst;
|
||||
uint32_t extra_ctx_inst_in_this_func =
|
||||
inst_in_this_func * (call_counter - 1);
|
||||
|
||||
extra_ctx_inst += extra_ctx_inst_in_this_func;
|
||||
afl_global_id += extra_ctx_inst_in_this_func;
|
||||
|
||||
}
|
||||
|
||||
|
@ -226,20 +226,28 @@ llvmGetPassPluginInfo() {
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PB.registerOptimizerEarlyEPCallback([](ModulePassManager &MPM,
|
||||
OptimizationLevel OL
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
PB.registerPipelineStartEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
,
|
||||
ThinOrFullLTOPhase Phase
|
||||
#endif
|
||||
) {
|
||||
|
||||
MPM.addPass(ModuleSanitizerCoverageAFL());
|
||||
|
||||
});
|
||||
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
|
||||
MPM.addPass(ModuleSanitizerCoverageAFL());
|
||||
|
||||
});
|
||||
|
||||
#endif
|
||||
|
||||
}};
|
||||
|
||||
}
|
||||
|
@ -891,10 +891,10 @@ static void __afl_start_forkserver(void) {
|
||||
/* Phone home and tell the parent that we're OK. If parent isn't there,
|
||||
assume we're not running in forkserver mode and just execute program. */
|
||||
|
||||
if (!__afl_old_forkserver) {
|
||||
// return because possible non-forkserver usage
|
||||
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
|
||||
|
||||
// return because possible non-forkserver usage
|
||||
if (write(FORKSRV_FD + 1, msg, 4) != 4) { return; }
|
||||
if (!__afl_old_forkserver) {
|
||||
|
||||
if (read(FORKSRV_FD, reply, 4) != 4) { _exit(1); }
|
||||
if (tmp != status2) {
|
||||
|
@ -121,15 +121,16 @@ extern "C" LLVM_ATTRIBUTE_WEAK PassPluginLibraryInfo llvmGetPassPluginInfo() {
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
PB.registerPipelineStartEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#endif
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
,
|
||||
ThinOrFullLTOPhase Phase
|
||||
#endif
|
||||
) {
|
||||
|
||||
MPM.addPass(AFLCoverage());
|
||||
|
||||
|
@ -130,15 +130,16 @@ llvmGetPassPluginInfo() {
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
PB.registerPipelineStartEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#endif
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
,
|
||||
ThinOrFullLTOPhase Phase
|
||||
#endif
|
||||
) {
|
||||
|
||||
MPM.addPass(CompareTransform());
|
||||
|
||||
|
@ -190,15 +190,16 @@ llvmGetPassPluginInfo() {
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
PB.registerPipelineStartEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#endif
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
,
|
||||
ThinOrFullLTOPhase Phase
|
||||
#endif
|
||||
) {
|
||||
|
||||
MPM.addPass(SplitComparesTransform());
|
||||
|
||||
|
@ -138,15 +138,17 @@ llvmGetPassPluginInfo() {
|
||||
using OptimizationLevel = typename PassBuilder::OptimizationLevel;
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
PB.registerPipelineStartEPCallback(
|
||||
#else
|
||||
PB.registerOptimizerEarlyEPCallback(
|
||||
#endif
|
||||
#else
|
||||
PB.registerOptimizerLastEPCallback(
|
||||
#endif
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL) {
|
||||
[](ModulePassManager &MPM, OptimizationLevel OL
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
,
|
||||
ThinOrFullLTOPhase Phase
|
||||
#endif
|
||||
|
||||
) {
|
||||
|
||||
MPM.addPass(SplitSwitchesTransform());
|
||||
|
||||
|
@ -1 +1 @@
|
||||
4d837f06d5
|
||||
ef1cd9a8cb
|
||||
|
@ -40,7 +40,7 @@ ALPINE_ROOT=<your-alpine-sysroot-directory>
|
||||
FUZZ=<your-path-to-the-code>
|
||||
sudo systemd-nspawn -D $ALPINE_ROOT --bind=$FUZZ:/fuzz
|
||||
CC=$(which clang) CFLAGS="-g" LDSHARED="clang -shared" python3 -m pip install /fuzz
|
||||
clang $(python3-config --embed --cflags) $(python3-config --embed --ldflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c
|
||||
clang $(python3-config --embed --cflags) -o /fuzz/fuzz_harness /fuzz/fuzz_harness.c $(python3-config --embed --ldflags)
|
||||
exit
|
||||
```
|
||||
|
||||
|
Submodule qemu_mode/qemuafl updated: 4d837f06d5...ef1cd9a8cb
@ -110,8 +110,9 @@ static u8 count_class_lookup[256] = {
|
||||
|
||||
};
|
||||
|
||||
static void kill_child() {
|
||||
static void kill_child(int signal) {
|
||||
|
||||
(void)signal;
|
||||
if (fsrv.child_pid > 0) {
|
||||
|
||||
kill(fsrv.child_pid, fsrv.child_kill_signal);
|
||||
|
90
src/afl-cc.c
90
src/afl-cc.c
@ -181,15 +181,12 @@ typedef struct aflcc_state {
|
||||
have_pic, have_c, shared_linking, partial_linking, non_dash, have_fp,
|
||||
have_flto, have_hidden, have_fortify, have_fcf, have_staticasan,
|
||||
have_rust_asanrt, have_asan, have_msan, have_ubsan, have_lsan, have_tsan,
|
||||
have_cfisan;
|
||||
have_cfisan, have_rtsan;
|
||||
|
||||
// u8 *march_opt;
|
||||
u8 need_aflpplib;
|
||||
int passthrough;
|
||||
|
||||
u8 use_stdin; /* dummy */
|
||||
u8 *argvnull; /* dummy */
|
||||
|
||||
} aflcc_state_t;
|
||||
|
||||
void aflcc_state_init(aflcc_state_t *, u8 *argv0);
|
||||
@ -256,7 +253,11 @@ static inline void load_llvm_pass(aflcc_state_t *aflcc, u8 *pass) {
|
||||
|
||||
#if LLVM_MAJOR >= 11 /* use new pass manager */
|
||||
#if LLVM_MAJOR < 16
|
||||
#if LLVM_MAJOR < 15
|
||||
insert_param(aflcc, "-fno-legacy-pass-manager");
|
||||
#else
|
||||
insert_param(aflcc, "-fexperimental-new-pass-manager");
|
||||
#endif
|
||||
#endif
|
||||
insert_object(aflcc, pass, "-fpass-plugin=%s", 0);
|
||||
#else
|
||||
@ -1152,7 +1153,8 @@ void instrument_mode_by_environ(aflcc_state_t *aflcc) {
|
||||
static void instrument_opt_mode_exclude(aflcc_state_t *aflcc) {
|
||||
|
||||
if ((aflcc->instrument_opt_mode & INSTRUMENT_OPT_CTX) &&
|
||||
(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER)) {
|
||||
(aflcc->instrument_opt_mode & INSTRUMENT_OPT_CALLER) &&
|
||||
aflcc->compiler_mode != LTO) {
|
||||
|
||||
FATAL("you cannot set CTX and CALLER together");
|
||||
|
||||
@ -1536,7 +1538,8 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
|
||||
if (aflcc->plusplus_mode) {
|
||||
|
||||
insert_param(aflcc,
|
||||
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
|
||||
"-D__AFL_COVERAGE()=int __afl_selective_coverage "
|
||||
"__attribute__ ((weak)) = 1;"
|
||||
"extern \"C\" void __afl_coverage_discard();"
|
||||
"extern \"C\" void __afl_coverage_skip();"
|
||||
"extern \"C\" void __afl_coverage_on();"
|
||||
@ -1545,7 +1548,8 @@ void add_defs_selective_instr(aflcc_state_t *aflcc) {
|
||||
} else {
|
||||
|
||||
insert_param(aflcc,
|
||||
"-D__AFL_COVERAGE()=int __afl_selective_coverage = 1;"
|
||||
"-D__AFL_COVERAGE()=int __afl_selective_coverage "
|
||||
"__attribute__ ((weak)) = 1;"
|
||||
"void __afl_coverage_discard();"
|
||||
"void __afl_coverage_skip();"
|
||||
"void __afl_coverage_on();"
|
||||
@ -2031,6 +2035,13 @@ void add_sanitizers(aflcc_state_t *aflcc, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_USE_RTSAN") && !aflcc->have_rtsan) {
|
||||
|
||||
insert_param(aflcc, "-fsanitize=realtime");
|
||||
aflcc->have_rtsan = 1;
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_USE_CFISAN") || aflcc->have_cfisan) {
|
||||
|
||||
if (aflcc->compiler_mode == GCC_PLUGIN || aflcc->compiler_mode == GCC) {
|
||||
@ -2156,7 +2167,11 @@ void add_optimized_pcguard(aflcc_state_t *aflcc) {
|
||||
|
||||
/* Since LLVM_MAJOR >= 13 we use new pass manager */
|
||||
#if LLVM_MAJOR < 16
|
||||
#if LLVM_MAJOR < 15
|
||||
insert_param(aflcc, "-fno-legacy-pass-manager");
|
||||
#else
|
||||
insert_param(aflcc, "-fexperimental-new-pass-manager");
|
||||
#endif
|
||||
#endif
|
||||
insert_object(aflcc, "SanitizerCoveragePCGUARD.so", "-fpass-plugin=%s", 0);
|
||||
|
||||
@ -2971,7 +2986,8 @@ static void maybe_usage(aflcc_state_t *aflcc, int argc, char **argv) {
|
||||
" AFL_USE_MSAN: activate memory sanitizer\n"
|
||||
" AFL_USE_UBSAN: activate undefined behaviour sanitizer\n"
|
||||
" AFL_USE_TSAN: activate thread sanitizer\n"
|
||||
" AFL_USE_LSAN: activate leak-checker sanitizer\n");
|
||||
" AFL_USE_LSAN: activate leak-checker sanitizer\n"
|
||||
" AFL_USE_RTSAN: activate realtime sanitizer\n");
|
||||
|
||||
if (aflcc->have_gcc_plugin)
|
||||
SAYF(
|
||||
@ -3583,6 +3599,64 @@ int main(int argc, char **argv, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
// We only support plugins with LLVM 14 onwards
|
||||
#if LLVM_MAJOR < 14
|
||||
if (aflcc->instrument_mode != INSTRUMENT_LLVMNATIVE &&
|
||||
aflcc->compiler_mode != GCC_PLUGIN) {
|
||||
|
||||
aflcc->instrument_mode = INSTRUMENT_LLVMNATIVE;
|
||||
aflcc->compiler_mode = LLVM;
|
||||
|
||||
}
|
||||
|
||||
if (aflcc->compiler_mode == LLVM) {
|
||||
|
||||
if (aflcc->cmplog_mode) {
|
||||
|
||||
WARNF("CMPLOG support requires LLVM 14+");
|
||||
aflcc->cmplog_mode = 0;
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_LLVM_DICT2FILE")) {
|
||||
|
||||
WARNF("DICT2FILE support requires LLVM14+");
|
||||
unsetenv("AFL_LLVM_DICT2FILE");
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_LLVM_LAF_SPLIT_SWITCHES") ||
|
||||
getenv("AFL_LLVM_LAF_SPLIT_COMPARES") ||
|
||||
getenv("AFL_LLVM_LAF_SPLIT_FLOATS") ||
|
||||
getenv("AFL_LLVM_LAF_TRANSFORM_COMPARES") ||
|
||||
getenv("AFL_LLVM_LAF_ALL")) {
|
||||
|
||||
WARNF("AFL_LLVM_LAF support requires LLVM14+");
|
||||
unsetenv("AFL_LLVM_LAF_SPLIT_SWITCHES");
|
||||
unsetenv("AFL_LLVM_LAF_SPLIT_COMPARES");
|
||||
unsetenv("AFL_LLVM_LAF_SPLIT_FLOATS");
|
||||
unsetenv("AFL_LLVM_LAF_TRANSFORM_COMPARES");
|
||||
unsetenv("AFL_LLVM_LAF_ALL");
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_LLVM_INJECTIONS_ALL") ||
|
||||
getenv("AFL_LLVM_INJECTIONS_SQL") ||
|
||||
getenv("AFL_LLVM_INJECTIONS_LDAP") ||
|
||||
getenv("AFL_LLVM_INJECTIONS_XSS")) {
|
||||
|
||||
WARNF("AFL_LLVM_INJECTIONS support requires LLVM14+");
|
||||
unsetenv("AFL_LLVM_INJECTIONS_ALL");
|
||||
unsetenv("AFL_LLVM_INJECTIONS_SQL");
|
||||
unsetenv("AFL_LLVM_INJECTIONS_LDAP");
|
||||
unsetenv("AFL_LLVM_INJECTIONS_XSS");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
mode_notification(aflcc);
|
||||
|
||||
if (aflcc->debug) debugf_args(argc, argv);
|
||||
|
@ -977,11 +977,10 @@ void read_bitmap(u8 *fname, u8 *map, size_t len) {
|
||||
|
||||
inline u64 get_cur_time(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
struct timeval tv;
|
||||
|
||||
// TO NOT REPLACE WITH clock_gettime!!!
|
||||
gettimeofday(&tv, &tz);
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
return (tv.tv_sec * 1000ULL) + (tv.tv_usec / 1000);
|
||||
|
||||
@ -991,11 +990,10 @@ inline u64 get_cur_time(void) {
|
||||
|
||||
inline u64 get_cur_time_us(void) {
|
||||
|
||||
struct timeval tv;
|
||||
struct timezone tz;
|
||||
struct timeval tv;
|
||||
|
||||
// TO NOT REPLACE WITH clock_gettime!!!
|
||||
gettimeofday(&tv, &tz);
|
||||
gettimeofday(&tv, NULL);
|
||||
|
||||
return (tv.tv_sec * 1000000ULL) + tv.tv_usec;
|
||||
|
||||
@ -1006,7 +1004,7 @@ inline u64 get_cur_time_us(void) {
|
||||
Will return buf for convenience. */
|
||||
|
||||
u8 *stringify_int(u8 *buf, size_t len, u64 val) {
|
||||
\
|
||||
|
||||
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
|
||||
do { \
|
||||
\
|
||||
@ -1170,7 +1168,7 @@ u8 *stringify_time_diff(u8 *buf, size_t len, u64 cur_ms, u64 event_ms) {
|
||||
Will return buf for convenience. */
|
||||
|
||||
u8 *u_stringify_int(u8 *buf, u64 val) {
|
||||
\
|
||||
|
||||
#define CHK_FORMAT(_divisor, _limit_mult, _fmt, _cast) \
|
||||
do { \
|
||||
\
|
||||
|
@ -258,7 +258,7 @@ void afl_fsrv_init(afl_forkserver_t *fsrv) {
|
||||
fsrv->last_run_timed_out = false;
|
||||
fsrv->debug = false;
|
||||
fsrv->uses_crash_exitcode = false;
|
||||
fsrv->uses_asan = false;
|
||||
fsrv->uses_asan = 0;
|
||||
|
||||
#ifdef __AFL_CODE_COVERAGE
|
||||
fsrv->persistent_trace_bits = NULL;
|
||||
@ -2087,17 +2087,19 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
|
||||
|
||||
/* Did we crash?
|
||||
In a normal case, (abort) WIFSIGNALED(child_status) will be set.
|
||||
MSAN in uses_asan mode uses a special exit code as it doesn't support
|
||||
MSAN & LSAN in uses_asan mode use special exit codes as they doesn't support
|
||||
abort_on_error. On top, a user may specify a custom AFL_CRASH_EXITCODE.
|
||||
Handle all three cases here. */
|
||||
Handle all four cases here. */
|
||||
|
||||
if (unlikely(
|
||||
/* A normal crash/abort */
|
||||
(WIFSIGNALED(fsrv->child_status)) ||
|
||||
/* special handling for msan and lsan */
|
||||
(fsrv->uses_asan &&
|
||||
(WEXITSTATUS(fsrv->child_status) == MSAN_ERROR ||
|
||||
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR)) ||
|
||||
/* special handling for msan */
|
||||
((fsrv->uses_asan & 4) &&
|
||||
WEXITSTATUS(fsrv->child_status) == MSAN_ERROR) ||
|
||||
/* special handling for lsan */
|
||||
((fsrv->uses_asan & 2) &&
|
||||
WEXITSTATUS(fsrv->child_status) == LSAN_ERROR) ||
|
||||
/* the custom crash_exitcode was returned by the target */
|
||||
(fsrv->uses_crash_exitcode &&
|
||||
WEXITSTATUS(fsrv->child_status) == fsrv->crash_exitcode))) {
|
||||
@ -2106,6 +2108,10 @@ fsrv_run_result_t __attribute__((hot)) afl_fsrv_run_target(
|
||||
fsrv->last_kill_signal =
|
||||
WIFSIGNALED(fsrv->child_status) ? WTERMSIG(fsrv->child_status) : 0;
|
||||
|
||||
/* For a special exit code, set last_exit_code to non-zero */
|
||||
fsrv->last_exit_code =
|
||||
WIFSIGNALED(fsrv->child_status) ? 0 : WEXITSTATUS(fsrv->child_status);
|
||||
|
||||
#ifdef AFL_PERSISTENT_RECORD
|
||||
if (unlikely(fsrv->persistent_record)) {
|
||||
|
||||
|
@ -28,6 +28,45 @@
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include "asanfuzz.h"
|
||||
|
||||
u16 count_class_lookup16[65536];
|
||||
|
||||
/* Destructively simplify trace by eliminating hit count information
|
||||
and replacing it with 0x80 or 0x01 depending on whether the tuple
|
||||
is hit or not. Called on every new crash or timeout, should be
|
||||
reasonably fast. */
|
||||
static const u8 simplify_lookup[256] = {
|
||||
|
||||
[0] = 1, [1 ... 255] = 128
|
||||
|
||||
};
|
||||
|
||||
/* Destructively classify execution counts in a trace. This is used as a
|
||||
preprocessing step for any newly acquired traces. Called on every exec,
|
||||
must be fast. */
|
||||
|
||||
static const u8 count_class_lookup8[256] = {
|
||||
|
||||
[0] = 0,
|
||||
[1] = 1,
|
||||
[2] = 2,
|
||||
[3] = 4,
|
||||
[4 ... 7] = 8,
|
||||
[8 ... 15] = 16,
|
||||
[16 ... 31] = 32,
|
||||
[32 ... 127] = 64,
|
||||
[128 ... 255] = 128
|
||||
|
||||
};
|
||||
|
||||
/* Import coverage processing routines. */
|
||||
|
||||
#ifdef WORD_SIZE_64
|
||||
#include "coverage-64.h"
|
||||
#else
|
||||
#include "coverage-32.h"
|
||||
#endif
|
||||
|
||||
#if !defined NAME_MAX
|
||||
#define NAME_MAX _XOPEN_NAME_MAX
|
||||
#endif
|
||||
@ -146,36 +185,6 @@ u32 count_non_255_bytes(afl_state_t *afl, u8 *mem) {
|
||||
|
||||
}
|
||||
|
||||
/* Destructively simplify trace by eliminating hit count information
|
||||
and replacing it with 0x80 or 0x01 depending on whether the tuple
|
||||
is hit or not. Called on every new crash or timeout, should be
|
||||
reasonably fast. */
|
||||
const u8 simplify_lookup[256] = {
|
||||
|
||||
[0] = 1, [1 ... 255] = 128
|
||||
|
||||
};
|
||||
|
||||
/* Destructively classify execution counts in a trace. This is used as a
|
||||
preprocessing step for any newly acquired traces. Called on every exec,
|
||||
must be fast. */
|
||||
|
||||
const u8 count_class_lookup8[256] = {
|
||||
|
||||
[0] = 0,
|
||||
[1] = 1,
|
||||
[2] = 2,
|
||||
[3] = 4,
|
||||
[4 ... 7] = 8,
|
||||
[8 ... 15] = 16,
|
||||
[16 ... 31] = 32,
|
||||
[32 ... 127] = 64,
|
||||
[128 ... 255] = 128
|
||||
|
||||
};
|
||||
|
||||
u16 count_class_lookup16[65536];
|
||||
|
||||
void init_count_class16(void) {
|
||||
|
||||
u32 b1, b2;
|
||||
@ -193,14 +202,6 @@ void init_count_class16(void) {
|
||||
|
||||
}
|
||||
|
||||
/* Import coverage processing routines. */
|
||||
|
||||
#ifdef WORD_SIZE_64
|
||||
#include "coverage-64.h"
|
||||
#else
|
||||
#include "coverage-32.h"
|
||||
#endif
|
||||
|
||||
/* Check if the current execution path brings anything new to the table.
|
||||
Update virgin bits to reflect the finds. Returns 1 if the only change is
|
||||
the hit-count for a particular tuple; 2 if there are new tuples seen.
|
||||
@ -461,18 +462,6 @@ void write_crash_readme(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
static inline void bitmap_set(u8 *map, u32 index) {
|
||||
|
||||
map[index / 8] |= (1u << (index % 8));
|
||||
|
||||
}
|
||||
|
||||
static inline u8 bitmap_read(u8 *map, u32 index) {
|
||||
|
||||
return (map[index / 8] >> (index % 8)) & 1;
|
||||
|
||||
}
|
||||
|
||||
/* Check if the result of an execve() during routine fuzzing is interesting,
|
||||
save or queue the input test case for further analysis if so. Returns 1 if
|
||||
entry is saved, 0 otherwise. */
|
||||
@ -480,6 +469,8 @@ static inline u8 bitmap_read(u8 *map, u32 index) {
|
||||
u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
u32 len, u8 fault) {
|
||||
|
||||
u8 classified = 0;
|
||||
|
||||
if (unlikely(len == 0)) { return 0; }
|
||||
|
||||
if (unlikely(fault == FSRV_RUN_TMOUT && afl->afl_env.afl_ignore_timeouts)) {
|
||||
@ -488,6 +479,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
classify_counts(&afl->fsrv);
|
||||
u64 cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
classified = 1;
|
||||
|
||||
// Saturated increment
|
||||
if (likely(afl->n_fuzz[cksum % N_FUZZ_SIZE] < 0xFFFFFFFF))
|
||||
@ -501,8 +493,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
u8 fn[PATH_MAX];
|
||||
u8 *queue_fn = "";
|
||||
u8 new_bits = 0, keeping = 0, res, classified = 0, is_timeout = 0,
|
||||
need_hash = 1;
|
||||
u8 new_bits = 0, keeping = 0, res, is_timeout = 0, need_hash = 1;
|
||||
s32 fd;
|
||||
u64 cksum = 0;
|
||||
u32 cksum_simplified = 0, cksum_unique = 0;
|
||||
@ -519,7 +510,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
if (unlikely(afl->schedule >= FAST && afl->schedule <= RARE)) {
|
||||
|
||||
classify_counts(&afl->fsrv);
|
||||
classified = 1;
|
||||
need_hash = 0;
|
||||
|
||||
cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
@ -538,8 +528,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
memcpy(afl->san_fsrvs[0].trace_bits, afl->fsrv.trace_bits,
|
||||
afl->fsrv.map_size);
|
||||
classify_counts_mem((u64 *)afl->san_fsrvs[0].trace_bits,
|
||||
afl->fsrv.map_size);
|
||||
simplify_trace(afl, afl->san_fsrvs[0].trace_bits);
|
||||
|
||||
// Note: Original SAND implementation used XXHASH32
|
||||
@ -568,6 +556,16 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
if (unlikely(afl->san_binary_length) &&
|
||||
likely(afl->san_abstraction == UNIQUE_TRACE)) {
|
||||
|
||||
// If schedule is not FAST..RARE, we need to classify counts here
|
||||
// Note: SAND was evaluated under FAST schedule but should also work
|
||||
// with other scedules.
|
||||
if (!classified) {
|
||||
|
||||
classify_counts(&afl->fsrv);
|
||||
classified = 1;
|
||||
|
||||
}
|
||||
|
||||
cksum_unique =
|
||||
hash32(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
if (unlikely(!bitmap_read(afl->n_fuzz_dup, cksum) &&
|
||||
@ -630,7 +628,16 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
/* If we are in coverage increasing abstraction and have fed input to
|
||||
sanitizers, we are sure it has new bits.*/
|
||||
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
|
||||
if (classified) {
|
||||
|
||||
/* We could have classified the bits in SAND with UNIQUE_TRACE */
|
||||
new_bits = has_new_bits(afl, afl->virgin_bits);
|
||||
|
||||
} else {
|
||||
|
||||
new_bits = has_new_bits_unclassified(afl, afl->virgin_bits);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -645,7 +652,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
|
||||
afl->san_case_status |= NON_COV_INCREASE_BUG;
|
||||
fault = san_fault;
|
||||
classified = new_bits;
|
||||
goto may_save_fault;
|
||||
|
||||
}
|
||||
@ -653,7 +659,6 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
}
|
||||
|
||||
fault = san_fault;
|
||||
classified = new_bits;
|
||||
|
||||
save_to_queue:
|
||||
|
||||
@ -681,7 +686,7 @@ u8 __attribute__((hot)) save_if_interesting(afl_state_t *afl, void *mem,
|
||||
#else
|
||||
|
||||
queue_fn = alloc_printf(
|
||||
"%s/queue/id_%06u", afl->out_dir, afl->queued_items,
|
||||
"%s/queue/id_%06u%s%s", afl->out_dir, afl->queued_items,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
|
||||
@ -798,13 +803,6 @@ may_save_fault:
|
||||
|
||||
if (likely(!afl->non_instrumented_mode)) {
|
||||
|
||||
if (unlikely(!classified)) {
|
||||
|
||||
classify_counts(&afl->fsrv);
|
||||
classified = 1;
|
||||
|
||||
}
|
||||
|
||||
simplify_trace(afl, afl->fsrv.trace_bits);
|
||||
|
||||
if (!has_new_bits(afl, afl->virgin_tmout)) { return keeping; }
|
||||
@ -938,13 +936,6 @@ may_save_fault:
|
||||
|
||||
if (likely(!afl->non_instrumented_mode)) {
|
||||
|
||||
if (unlikely(!classified)) {
|
||||
|
||||
classify_counts(&afl->fsrv);
|
||||
classified = 1;
|
||||
|
||||
}
|
||||
|
||||
simplify_trace(afl, afl->fsrv.trace_bits);
|
||||
|
||||
if (!has_new_bits(afl, afl->virgin_crash)) { return keeping; }
|
||||
|
@ -354,6 +354,7 @@ void load_extras(afl_state_t *afl, u8 *dir) {
|
||||
"Extra '%s' is too big (%s, limit is %s)", fn,
|
||||
stringify_mem_size(val_bufs[0], sizeof(val_bufs[0]), st.st_size),
|
||||
stringify_mem_size(val_bufs[1], sizeof(val_bufs[1]), MAX_DICT_FILE));
|
||||
ck_free(fn);
|
||||
continue;
|
||||
|
||||
}
|
||||
@ -742,10 +743,8 @@ void save_auto(afl_state_t *afl) {
|
||||
|
||||
for (i = 0; i < MIN((u32)USE_AUTO_EXTRAS, afl->a_extras_cnt); ++i) {
|
||||
|
||||
u8 *fn = alloc_printf(
|
||||
"%s/queue/.state/auto_extras/auto_%06u%s%s", afl->out_dir, i,
|
||||
afl->file_extension ? "." : "",
|
||||
afl->file_extension ? (const char *)afl->file_extension : "");
|
||||
u8 *fn =
|
||||
alloc_printf("%s/queue/.state/auto_extras/auto_%06u", afl->out_dir, i);
|
||||
|
||||
s32 fd;
|
||||
|
||||
|
@ -567,6 +567,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
|
||||
}
|
||||
|
||||
free(nl);
|
||||
continue;
|
||||
|
||||
}
|
||||
@ -593,6 +594,7 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
if (unlikely(lstat(fn2, &st) || access(fn2, R_OK))) {
|
||||
|
||||
if (first) PFATAL("Unable to access '%s'", fn2);
|
||||
ck_free(fn2);
|
||||
continue;
|
||||
|
||||
}
|
||||
@ -634,19 +636,16 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
// as this could add duplicates of the startup input corpus
|
||||
|
||||
int fd = open(fn2, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
ck_free(fn2);
|
||||
|
||||
ck_free(fn2);
|
||||
continue;
|
||||
|
||||
}
|
||||
if (fd < 0) { continue; }
|
||||
|
||||
u8 fault;
|
||||
u8 *mem = mmap(0, st.st_size, PROT_READ, MAP_PRIVATE, fd, 0);
|
||||
|
||||
if (mem == MAP_FAILED) {
|
||||
|
||||
ck_free(fn2);
|
||||
close(fd);
|
||||
continue;
|
||||
|
||||
}
|
||||
@ -668,7 +667,12 @@ void read_foreign_testcases(afl_state_t *afl, int first) {
|
||||
|
||||
}
|
||||
|
||||
afl->foreign_syncs[iter].mtime = mtime_max;
|
||||
if (mtime_max > afl->foreign_syncs[iter].mtime) {
|
||||
|
||||
afl->foreign_syncs[iter].mtime = mtime_max;
|
||||
|
||||
}
|
||||
|
||||
free(nl); /* not tracked */
|
||||
|
||||
}
|
||||
@ -749,8 +753,6 @@ void read_testcases(afl_state_t *afl, u8 *directory) {
|
||||
|
||||
}
|
||||
|
||||
// if (getenv("MYTEST")) afl->in_place_resume = 1;
|
||||
|
||||
if (nl_cnt) {
|
||||
|
||||
u32 done = 0;
|
||||
@ -1042,6 +1044,47 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
|
||||
if (afl->crash_mode) { break; }
|
||||
|
||||
const u8 *msg_exit_code = "";
|
||||
|
||||
if (afl->fsrv.uses_asan && !afl->fsrv.last_kill_signal) {
|
||||
|
||||
if ((afl->fsrv.uses_asan & 4) &&
|
||||
afl->fsrv.last_exit_code == MSAN_ERROR) {
|
||||
|
||||
msg_exit_code =
|
||||
" - The test case terminated with the exit code that is "
|
||||
"used by MSAN to\n"
|
||||
" indicate an error. This is counted as a crash by "
|
||||
"afl-fuzz because you\n"
|
||||
" have compiled the target with MSAN enabled. This could "
|
||||
"be a false\n"
|
||||
" positive if the program returns this exit code under "
|
||||
"normal operation.\n"
|
||||
" In that case, either disable MSAN or change the test "
|
||||
"case or program\n"
|
||||
" to avoid generating this exit code.\n\n";
|
||||
|
||||
} else if ((afl->fsrv.uses_asan & 2) &&
|
||||
|
||||
afl->fsrv.last_exit_code == LSAN_ERROR) {
|
||||
|
||||
msg_exit_code =
|
||||
" - The test case terminated with the exit code that is "
|
||||
"used by LSAN to\n"
|
||||
" indicate an error. This is counted as a crash by "
|
||||
"afl-fuzz because you\n"
|
||||
" have compiled the target with LSAN enabled. This could "
|
||||
"be a false\n"
|
||||
" positive if the program returns this exit code under "
|
||||
"normal operation.\n"
|
||||
" In that case, either disable LSAN or change the test "
|
||||
"case or program\n"
|
||||
" to avoid generating this exit code.\n\n";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (afl->fsrv.mem_limit) {
|
||||
|
||||
u8 val_buf[STRINGIFY_VAL_SIZE_MAX];
|
||||
@ -1056,6 +1099,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
" so, please remove it. The fuzzer should be seeded with "
|
||||
"interesting\n"
|
||||
" inputs - but not ones that cause an outright crash.\n\n"
|
||||
"%s"
|
||||
|
||||
" - The current memory limit (%s) is too low for this "
|
||||
"program, causing\n"
|
||||
@ -1085,6 +1129,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
"other options\n"
|
||||
" fail, poke the Awesome Fuzzing Discord for "
|
||||
"troubleshooting tips.\n",
|
||||
msg_exit_code,
|
||||
stringify_mem_size(val_buf, sizeof(val_buf),
|
||||
afl->fsrv.mem_limit << 20),
|
||||
afl->fsrv.mem_limit - 1);
|
||||
@ -1101,6 +1146,7 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
" so, please remove it. The fuzzer should be seeded with "
|
||||
"interesting\n"
|
||||
" inputs - but not ones that cause an outright crash.\n\n"
|
||||
"%s"
|
||||
|
||||
" - In QEMU persistent mode the selected address(es) for the "
|
||||
"loop are not\n"
|
||||
@ -1113,7 +1159,8 @@ void perform_dry_run(afl_state_t *afl) {
|
||||
" - Least likely, there is a horrible bug in the fuzzer. If "
|
||||
"other options\n"
|
||||
" fail, poke the Awesome Fuzzing Discord for "
|
||||
"troubleshooting tips.\n");
|
||||
"troubleshooting tips.\n",
|
||||
msg_exit_code);
|
||||
|
||||
}
|
||||
|
||||
@ -2180,10 +2227,17 @@ int check_main_node_exists(afl_state_t *afl) {
|
||||
fn = alloc_printf("%s/%s/is_main_node", afl->sync_dir, sd_ent->d_name);
|
||||
int res = access(fn, F_OK);
|
||||
free(fn);
|
||||
if (res == 0) return 1;
|
||||
if (res == 0) {
|
||||
|
||||
closedir(sd);
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
closedir(sd);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@ -2267,18 +2321,6 @@ void setup_dirs_fds(afl_state_t *afl) {
|
||||
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
|
||||
ck_free(tmp);
|
||||
|
||||
/* The set of paths currently deemed redundant. */
|
||||
|
||||
tmp = alloc_printf("%s/queue/.state/redundant_edges/", afl->out_dir);
|
||||
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
|
||||
ck_free(tmp);
|
||||
|
||||
/* The set of paths showing variable behavior. */
|
||||
|
||||
tmp = alloc_printf("%s/queue/.state/variable_behavior/", afl->out_dir);
|
||||
if (mkdir(tmp, 0700)) { PFATAL("Unable to create '%s'", tmp); }
|
||||
ck_free(tmp);
|
||||
|
||||
/* Sync directory for keeping track of cooperating fuzzers. */
|
||||
|
||||
if (afl->sync_id) {
|
||||
@ -2601,7 +2643,7 @@ void check_cpu_governor(afl_state_t *afl) {
|
||||
" afl-fuzz. To keep things moving, run these commands as root:\n\n"
|
||||
|
||||
" cd /sys/devices/system/cpu\n"
|
||||
" echo performance | tee cpu*/cpufreq/scaling_governor\n\n"
|
||||
" echo performance | sudo tee cpu*/cpufreq/scaling_governor\n\n"
|
||||
|
||||
" You can later go back to the original state by replacing "
|
||||
"'performance'\n"
|
||||
@ -3118,11 +3160,23 @@ void check_binary(afl_state_t *afl, u8 *fname) {
|
||||
|
||||
}
|
||||
|
||||
if (afl_memmem(f_data, f_len, "__asan_init", 11) ||
|
||||
afl_memmem(f_data, f_len, "__msan_init", 11) ||
|
||||
afl_memmem(f_data, f_len, "__lsan_init", 11)) {
|
||||
afl->fsrv.uses_asan = 0;
|
||||
|
||||
afl->fsrv.uses_asan = 1;
|
||||
if (afl_memmem(f_data, f_len, "__asan_init", 11)) {
|
||||
|
||||
afl->fsrv.uses_asan |= 1;
|
||||
|
||||
}
|
||||
|
||||
if (afl_memmem(f_data, f_len, "__lsan_init", 11)) {
|
||||
|
||||
afl->fsrv.uses_asan |= 2;
|
||||
|
||||
}
|
||||
|
||||
if (afl_memmem(f_data, f_len, "__msan_init", 11)) {
|
||||
|
||||
afl->fsrv.uses_asan |= 4;
|
||||
|
||||
}
|
||||
|
||||
|
@ -636,7 +636,7 @@ u8 trim_case_custom(afl_state_t *afl, struct queue_entry *q, u8 *in_buf,
|
||||
q->len = out_len;
|
||||
|
||||
memcpy(afl->fsrv.trace_bits, afl->clean_trace_custom, afl->fsrv.map_size);
|
||||
update_bitmap_score(afl, q);
|
||||
update_bitmap_score(afl, q, true);
|
||||
|
||||
}
|
||||
|
||||
|
@ -356,7 +356,12 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
if (el->afl_custom_queue_get &&
|
||||
!el->afl_custom_queue_get(el->data, afl->queue_cur->fname)) {
|
||||
|
||||
return 1;
|
||||
/* Abandon the entry and return that we skipped it.
|
||||
If we don't do this then when the entry is smallest_favored then
|
||||
we get caught in an infinite loop calling afl_custom_queue_get
|
||||
on smallest_favored */
|
||||
ret_val = 1;
|
||||
goto abandon_entry;
|
||||
|
||||
}
|
||||
|
||||
@ -634,7 +639,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
afl->stage_cur_byte = afl->stage_cur >> 3;
|
||||
|
||||
if (!skip_eff_map[afl->stage_cur_byte]) continue;
|
||||
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -754,7 +759,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
afl->stage_cur_byte = afl->stage_cur >> 3;
|
||||
|
||||
if (!skip_eff_map[afl->stage_cur_byte]) continue;
|
||||
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -793,7 +798,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
afl->stage_cur_byte = afl->stage_cur >> 3;
|
||||
|
||||
if (!skip_eff_map[afl->stage_cur_byte]) continue;
|
||||
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -837,7 +842,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
afl->stage_cur_byte = afl->stage_cur;
|
||||
|
||||
if (!skip_eff_map[afl->stage_cur_byte]) continue;
|
||||
if (!bitmap_read(skip_eff_map, afl->stage_cur_byte)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -858,7 +863,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (skip_eff_map[i]) afl->blocks_eff_select += 1;
|
||||
if (bitmap_read(skip_eff_map, i)) afl->blocks_eff_select += 1;
|
||||
|
||||
}
|
||||
|
||||
@ -887,7 +892,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -930,7 +935,7 @@ u8 fuzz_one_original(afl_state_t *afl) {
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -983,7 +988,7 @@ skip_bitflip:
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1067,7 +1072,7 @@ skip_bitflip:
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1197,7 +1202,7 @@ skip_bitflip:
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1331,7 +1336,7 @@ skip_arith:
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1391,7 +1396,7 @@ skip_arith:
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1479,7 +1484,7 @@ skip_arith:
|
||||
|
||||
/* Let's consult the effector map... */
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1573,7 +1578,7 @@ skip_interest:
|
||||
|
||||
u32 last_len = 0;
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1642,7 +1647,7 @@ skip_interest:
|
||||
|
||||
for (i = 0; i <= (u32)len; ++i) {
|
||||
|
||||
if (!skip_eff_map[i % len]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i % len)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1708,7 +1713,7 @@ skip_user_extras:
|
||||
|
||||
u32 last_len = 0;
|
||||
|
||||
if (!skip_eff_map[i]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
@ -1768,7 +1773,7 @@ skip_user_extras:
|
||||
|
||||
for (i = 0; i <= (u32)len; ++i) {
|
||||
|
||||
if (!skip_eff_map[i % len]) continue;
|
||||
if (!bitmap_read(skip_eff_map, i % len)) continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 0)) { goto custom_mutator_stage; }
|
||||
|
||||
|
@ -440,30 +440,6 @@ void mark_as_det_done(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
/* Mark as variable. Create symlinks if possible to make it easier to examine
|
||||
the files. */
|
||||
|
||||
void mark_as_variable(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
char fn[PATH_MAX];
|
||||
char ldest[PATH_MAX];
|
||||
|
||||
char *fn_name = strrchr((char *)q->fname, '/') + 1;
|
||||
|
||||
sprintf(ldest, "../../%s", fn_name);
|
||||
sprintf(fn, "%s/queue/.state/variable_behavior/%s", afl->out_dir, fn_name);
|
||||
|
||||
if (symlink(ldest, fn)) {
|
||||
|
||||
s32 fd = permissive_create(afl, fn);
|
||||
if (fd >= 0) { close(fd); }
|
||||
|
||||
}
|
||||
|
||||
q->var_behavior = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Mark / unmark as redundant (edge-only). This is not used for restoring state,
|
||||
but may be useful for post-processing datasets. */
|
||||
|
||||
@ -471,8 +447,6 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
if (likely(state == q->fs_redundant)) { return; }
|
||||
|
||||
char fn[PATH_MAX];
|
||||
|
||||
q->fs_redundant = state;
|
||||
|
||||
if (likely(q->fs_redundant)) {
|
||||
@ -486,22 +460,9 @@ void mark_as_redundant(afl_state_t *afl, struct queue_entry *q, u8 state) {
|
||||
|
||||
}
|
||||
|
||||
sprintf(fn, "%s/queue/.state/redundant_edges/%s", afl->out_dir,
|
||||
strrchr((char *)q->fname, '/') + 1);
|
||||
|
||||
if (state) {
|
||||
|
||||
s32 fd;
|
||||
|
||||
if (unlikely(afl->afl_env.afl_disable_redundant)) { q->disabled = 1; }
|
||||
fd = permissive_create(afl, fn);
|
||||
if (fd >= 0) { close(fd); }
|
||||
|
||||
} else {
|
||||
|
||||
if (unlink(fn)) { /*PFATAL("Unable to remove '%s'", fn);*/
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -805,6 +766,7 @@ void destroy_queue(afl_state_t *afl) {
|
||||
for (i = 0; i < afl->queued_items; i++) {
|
||||
|
||||
q = afl->queue_buf[i];
|
||||
ck_free(q->testcase_buf);
|
||||
ck_free(q->fname);
|
||||
ck_free(q->trace_mini);
|
||||
if (q->skipdet_e) {
|
||||
@ -833,7 +795,8 @@ void destroy_queue(afl_state_t *afl) {
|
||||
previous contender, or if the contender has a more favorable speed x size
|
||||
factor. */
|
||||
|
||||
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q,
|
||||
bool have_trace) {
|
||||
|
||||
u32 i;
|
||||
u64 fav_factor;
|
||||
@ -863,75 +826,80 @@ void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
}
|
||||
|
||||
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
|
||||
winner, and how it compares to us. */
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i) {
|
||||
if (have_trace) {
|
||||
|
||||
if (afl->fsrv.trace_bits[i]) {
|
||||
/* For every byte set in afl->fsrv.trace_bits[], see if there is a previous
|
||||
winner, and how it compares to us. */
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i) {
|
||||
|
||||
if (afl->top_rated[i]) {
|
||||
if (afl->fsrv.trace_bits[i]) {
|
||||
|
||||
/* Faster-executing or smaller test cases are favored. */
|
||||
u64 top_rated_fav_factor;
|
||||
u64 top_rated_fuzz_p2;
|
||||
if (afl->top_rated[i]) {
|
||||
|
||||
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
|
||||
/* Faster-executing or smaller test cases are favored. */
|
||||
u64 top_rated_fav_factor;
|
||||
u64 top_rated_fuzz_p2;
|
||||
|
||||
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
|
||||
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
|
||||
|
||||
} else if (unlikely(afl->schedule == RARE)) {
|
||||
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
|
||||
|
||||
top_rated_fuzz_p2 =
|
||||
next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
|
||||
} else if (unlikely(afl->schedule == RARE)) {
|
||||
|
||||
} else {
|
||||
top_rated_fuzz_p2 =
|
||||
next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
|
||||
|
||||
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
|
||||
} else {
|
||||
|
||||
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
|
||||
|
||||
top_rated_fav_factor = afl->top_rated[i]->len << 2;
|
||||
|
||||
} else {
|
||||
|
||||
top_rated_fav_factor =
|
||||
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
|
||||
|
||||
}
|
||||
|
||||
if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; }
|
||||
|
||||
if (likely(fav_factor > top_rated_fav_factor)) { continue; }
|
||||
|
||||
/* Looks like we're going to win. Decrease ref count for the
|
||||
previous winner, discard its afl->fsrv.trace_bits[] if necessary.
|
||||
*/
|
||||
|
||||
if (!--afl->top_rated[i]->tc_ref) {
|
||||
|
||||
ck_free(afl->top_rated[i]->trace_mini);
|
||||
afl->top_rated[i]->trace_mini = NULL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
|
||||
/* Insert ourselves as the new winner. */
|
||||
|
||||
top_rated_fav_factor = afl->top_rated[i]->len << 2;
|
||||
afl->top_rated[i] = q;
|
||||
++q->tc_ref;
|
||||
|
||||
} else {
|
||||
if (!q->trace_mini) {
|
||||
|
||||
top_rated_fav_factor =
|
||||
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
|
||||
u32 len = ((afl->fsrv.map_size + 7) >> 3);
|
||||
q->trace_mini = (u8 *)ck_alloc(len);
|
||||
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
|
||||
|
||||
}
|
||||
|
||||
if (likely(fuzz_p2 > top_rated_fuzz_p2)) { continue; }
|
||||
|
||||
if (likely(fav_factor > top_rated_fav_factor)) { continue; }
|
||||
|
||||
/* Looks like we're going to win. Decrease ref count for the
|
||||
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
|
||||
|
||||
if (!--afl->top_rated[i]->tc_ref) {
|
||||
|
||||
ck_free(afl->top_rated[i]->trace_mini);
|
||||
afl->top_rated[i]->trace_mini = NULL;
|
||||
|
||||
}
|
||||
afl->score_changed = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Insert ourselves as the new winner. */
|
||||
|
||||
afl->top_rated[i] = q;
|
||||
++q->tc_ref;
|
||||
|
||||
if (!q->trace_mini) {
|
||||
|
||||
u32 len = (afl->fsrv.map_size >> 3);
|
||||
q->trace_mini = (u8 *)ck_alloc(len);
|
||||
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
|
||||
|
||||
}
|
||||
|
||||
afl->score_changed = 1;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@ -1025,6 +993,186 @@ void cull_queue(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
/* Re-selects top_rated[] entries based on the current fuzzing schedule.
|
||||
Each queued entry is executed once to collect trace_bits, and potential
|
||||
candidates for each bitmap index are stored.
|
||||
|
||||
The candidate list format is [count][id1][id2]... as a u32 array,
|
||||
where 'count' indicates how many queue IDs hit that index. */
|
||||
|
||||
void recalculate_all_scores(afl_state_t *afl) {
|
||||
|
||||
u8 *in_buf;
|
||||
u32 i;
|
||||
u32 j;
|
||||
|
||||
for (i = afl->last_scored_idx + 1; i < afl->queued_items; i++) {
|
||||
|
||||
if (likely(!afl->queue_buf[i]->disabled)) {
|
||||
|
||||
in_buf = queue_testcase_get(afl, afl->queue_buf[i]);
|
||||
(void)write_to_testcase(afl, (void **)&in_buf, afl->queue_buf[i]->len, 1);
|
||||
(void)fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
for (j = 0; j < afl->fsrv.map_size; ++j) {
|
||||
|
||||
if (afl->fsrv.trace_bits[j]) {
|
||||
|
||||
u32 *candidate_ids = afl->top_rated_candidates[j];
|
||||
u32 id = afl->queue_buf[i]->id;
|
||||
|
||||
if (!candidate_ids) {
|
||||
|
||||
// first candidate: [count][id]
|
||||
candidate_ids = ck_alloc(sizeof(u32) * 2);
|
||||
candidate_ids[0] = 1; // count = 1
|
||||
candidate_ids[1] = id; // first ID
|
||||
|
||||
} else {
|
||||
|
||||
u32 count = candidate_ids[0];
|
||||
|
||||
candidate_ids =
|
||||
ck_realloc(candidate_ids, sizeof(u32) * (count + 2));
|
||||
candidate_ids[0] = count + 1; // increment the count
|
||||
candidate_ids[count + 1] = id; // append the new ID to the end
|
||||
|
||||
// fprintf(stderr, "enroll candidate[%u][%u] %u\n", i, j, id);
|
||||
|
||||
}
|
||||
|
||||
afl->top_rated_candidates[j] = candidate_ids;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
afl->last_scored_idx = i;
|
||||
|
||||
}
|
||||
|
||||
for (i = 0; i < afl->fsrv.map_size; ++i) {
|
||||
|
||||
u32 *candidate_ids = afl->top_rated_candidates[i];
|
||||
if (candidate_ids) {
|
||||
|
||||
u32 count = candidate_ids[0];
|
||||
|
||||
for (u32 k = 0; k < count; k++) {
|
||||
|
||||
u32 id = candidate_ids[k + 1];
|
||||
struct queue_entry *entry = afl->queue_buf[id];
|
||||
update_bitmap_rescore(afl, entry, i);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Re-evaluates top-rated entries without checking trace_bits.
|
||||
Unlike update_bitmap_score(), this function assumes the trace
|
||||
information is already known and only compares entries */
|
||||
|
||||
void update_bitmap_rescore(afl_state_t *afl, struct queue_entry *q, u32 index) {
|
||||
|
||||
u32 i = index;
|
||||
u64 fav_factor;
|
||||
u64 fuzz_p2;
|
||||
|
||||
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
|
||||
|
||||
fuzz_p2 = 0; // Skip the fuzz_p2 comparison
|
||||
|
||||
} else if (unlikely(afl->schedule == RARE)) {
|
||||
|
||||
fuzz_p2 = next_pow2(afl->n_fuzz[q->n_fuzz_entry]);
|
||||
|
||||
} else {
|
||||
|
||||
fuzz_p2 = q->fuzz_level;
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
|
||||
|
||||
fav_factor = q->len << 2;
|
||||
|
||||
} else {
|
||||
|
||||
fav_factor = q->exec_us * q->len;
|
||||
|
||||
}
|
||||
|
||||
if (afl->top_rated[i]) {
|
||||
|
||||
/* Faster-executing or smaller test cases are favored. */
|
||||
u64 top_rated_fav_factor;
|
||||
u64 top_rated_fuzz_p2;
|
||||
|
||||
if (unlikely(afl->schedule >= FAST && afl->schedule < RARE)) {
|
||||
|
||||
top_rated_fuzz_p2 = 0; // Skip the fuzz_p2 comparison
|
||||
|
||||
} else if (unlikely(afl->schedule == RARE)) {
|
||||
|
||||
top_rated_fuzz_p2 =
|
||||
next_pow2(afl->n_fuzz[afl->top_rated[i]->n_fuzz_entry]);
|
||||
|
||||
} else {
|
||||
|
||||
top_rated_fuzz_p2 = afl->top_rated[i]->fuzz_level;
|
||||
|
||||
}
|
||||
|
||||
if (unlikely(afl->schedule >= RARE) || unlikely(afl->fixed_seed)) {
|
||||
|
||||
top_rated_fav_factor = afl->top_rated[i]->len << 2;
|
||||
|
||||
} else {
|
||||
|
||||
top_rated_fav_factor =
|
||||
afl->top_rated[i]->exec_us * afl->top_rated[i]->len;
|
||||
|
||||
}
|
||||
|
||||
if (likely(fuzz_p2 > top_rated_fuzz_p2)) { return; }
|
||||
|
||||
if (likely(fav_factor > top_rated_fav_factor)) { return; }
|
||||
|
||||
/* Looks like we're going to win. Decrease ref count for the
|
||||
previous winner, discard its afl->fsrv.trace_bits[] if necessary. */
|
||||
|
||||
if (!--afl->top_rated[i]->tc_ref) {
|
||||
|
||||
ck_free(afl->top_rated[i]->trace_mini);
|
||||
afl->top_rated[i]->trace_mini = NULL;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Insert ourselves as the new winner. */
|
||||
|
||||
afl->top_rated[i] = q;
|
||||
++q->tc_ref;
|
||||
|
||||
if (!q->trace_mini) {
|
||||
|
||||
u32 len = (afl->fsrv.map_size >> 3);
|
||||
q->trace_mini = (u8 *)ck_alloc(len);
|
||||
minimize_bits(afl, q->trace_mini, afl->fsrv.trace_bits);
|
||||
|
||||
}
|
||||
|
||||
afl->score_changed = 1;
|
||||
|
||||
}
|
||||
|
||||
/* Calculate case desirability score to adjust the length of havoc fuzzing.
|
||||
A helper function for fuzz_one(). Maybe some of these constants should
|
||||
go into config.h. */
|
||||
@ -1330,7 +1478,7 @@ inline void queue_testcase_retake(afl_state_t *afl, struct queue_entry *q,
|
||||
|
||||
// only realloc if necessary or useful
|
||||
// (a custom trim can make the testcase larger)
|
||||
if (unlikely(len > old_len || len < old_len + 1024)) {
|
||||
if (unlikely(len > old_len || len + 1024 < old_len)) {
|
||||
|
||||
afl->q_testcase_cache_size += len - old_len;
|
||||
q->testcase_buf = (u8 *)realloc(q->testcase_buf, len);
|
||||
@ -1364,7 +1512,7 @@ inline void queue_testcase_retake_mem(afl_state_t *afl, struct queue_entry *q,
|
||||
if (likely(in != q->testcase_buf)) {
|
||||
|
||||
// only realloc if we save memory
|
||||
if (unlikely(len < old_len + 1024)) {
|
||||
if (unlikely(len + 1024 < old_len)) {
|
||||
|
||||
u8 *ptr = (u8 *)realloc(q->testcase_buf, len);
|
||||
|
||||
|
@ -592,11 +592,11 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
// note: from_queue seems to only be set during initialization
|
||||
if (afl->afl_env.afl_no_ui || from_queue) {
|
||||
|
||||
WARNF("instability detected during calibration");
|
||||
WARNF("instability detected during calibration: %s", q->fname);
|
||||
|
||||
} else if (afl->debug) {
|
||||
|
||||
DEBUGF("instability detected during calibration\n");
|
||||
DEBUGF("instability detected during calibration: %s\n", q->fname);
|
||||
|
||||
}
|
||||
|
||||
@ -652,7 +652,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem,
|
||||
afl->total_bitmap_size += q->bitmap_size;
|
||||
++afl->total_bitmap_entries;
|
||||
|
||||
update_bitmap_score(afl, q);
|
||||
update_bitmap_score(afl, q, true);
|
||||
|
||||
/* If this case didn't result in new output from the instrumentation, tell
|
||||
parent. This is a non-critical problem, but something to warn the user
|
||||
@ -682,12 +682,7 @@ abort_calibration:
|
||||
|
||||
afl->var_byte_count = count_bytes(afl, afl->var_bytes);
|
||||
|
||||
if (!q->var_behavior) {
|
||||
|
||||
mark_as_variable(afl, q);
|
||||
++afl->queued_variable;
|
||||
|
||||
}
|
||||
if (!q->var_behavior) { ++afl->queued_variable; }
|
||||
|
||||
}
|
||||
|
||||
@ -872,7 +867,14 @@ void sync_fuzzers(afl_state_t *afl) {
|
||||
|
||||
fault = fuzz_run_target(afl, &afl->fsrv, afl->fsrv.exec_tmout);
|
||||
|
||||
if (afl->stop_soon) { goto close_sync; }
|
||||
if (afl->stop_soon) {
|
||||
|
||||
munmap(mem, st.st_size);
|
||||
close(fd);
|
||||
|
||||
goto close_sync;
|
||||
|
||||
}
|
||||
|
||||
afl->syncing_party = sd_ent->d_name;
|
||||
afl->queued_imported += save_if_interesting(afl, mem, new_len, fault);
|
||||
@ -1166,7 +1168,7 @@ u8 trim_case(afl_state_t *afl, struct queue_entry *q, u8 *in_buf) {
|
||||
queue_testcase_retake_mem(afl, q, in_buf, q->len, orig_len);
|
||||
|
||||
memcpy(afl->fsrv.trace_bits, afl->clean_trace, afl->fsrv.map_size);
|
||||
update_bitmap_score(afl, q);
|
||||
update_bitmap_score(afl, q, true);
|
||||
|
||||
}
|
||||
|
||||
|
@ -154,7 +154,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
|
||||
flip_range(out_buf, pos, flip_block_size);
|
||||
|
||||
if (common_fuzz_stuff(afl, out_buf, len)) return 0;
|
||||
if (common_fuzz_stuff(afl, out_buf, len)) { return 0; }
|
||||
|
||||
flip_range(out_buf, pos, flip_block_size);
|
||||
|
||||
@ -237,26 +237,26 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
|
||||
if (!skip_eff_map) {
|
||||
|
||||
skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * len);
|
||||
skip_eff_map = (u8 *)ck_alloc(sizeof(u8) * (len + 7) / 8);
|
||||
afl->queue_cur->skipdet_e->skip_eff_map = skip_eff_map;
|
||||
|
||||
} else {
|
||||
|
||||
memset(skip_eff_map, 0, sizeof(u8) * len);
|
||||
memset(skip_eff_map, 0, sizeof(u8) * (len + 7) / 8);
|
||||
|
||||
}
|
||||
|
||||
/* restore the starting point */
|
||||
if (!done_inf_map) {
|
||||
|
||||
done_inf_map = (u8 *)ck_alloc(sizeof(u8) * len);
|
||||
done_inf_map = (u8 *)ck_alloc(sizeof(u8) * (len + 7) / 8);
|
||||
afl->queue_cur->skipdet_e->done_inf_map = done_inf_map;
|
||||
|
||||
} else {
|
||||
|
||||
for (afl->stage_cur = 0; afl->stage_cur < len; afl->stage_cur++) {
|
||||
|
||||
if (done_inf_map[afl->stage_cur] == 0) break;
|
||||
if (bitmap_read(done_inf_map, afl->stage_cur) == 0) break;
|
||||
|
||||
}
|
||||
|
||||
@ -278,7 +278,13 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
non_eff_bytes = (u8 *)ck_alloc(sizeof(u8) * len);
|
||||
|
||||
// clean exec cksum
|
||||
if (common_fuzz_stuff(afl, out_buf, len)) { return 0; }
|
||||
if (common_fuzz_stuff(afl, out_buf, len)) {
|
||||
|
||||
ck_free(non_eff_bytes);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
prev_cksum = hash64(afl->fsrv.trace_bits, afl->fsrv.map_size, HASH_CONST);
|
||||
|
||||
}
|
||||
@ -294,7 +300,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
afl->stage_cur_byte = afl->stage_cur;
|
||||
|
||||
if (!inf_eff_map[afl->stage_cur_byte] ||
|
||||
skip_eff_map[afl->stage_cur_byte])
|
||||
bitmap_read(skip_eff_map, afl->stage_cur_byte))
|
||||
continue;
|
||||
|
||||
if (is_det_timeout(before_det_time, 1)) { goto cleanup_skipdet; }
|
||||
@ -311,7 +317,12 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
|
||||
before_skip_inf = afl->queued_items;
|
||||
|
||||
if (common_fuzz_stuff(afl, out_buf, len)) { return 0; }
|
||||
if (common_fuzz_stuff(afl, out_buf, len)) {
|
||||
|
||||
ck_free(non_eff_bytes);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
out_buf[afl->stage_cur_byte] = orig;
|
||||
|
||||
@ -328,7 +339,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
|
||||
if (afl->queued_items != before_skip_inf) {
|
||||
|
||||
skip_eff_map[afl->stage_cur_byte] = 1;
|
||||
bitmap_set(skip_eff_map, afl->stage_cur_byte);
|
||||
afl->queue_cur->skipdet_e->quick_eff_bytes += 1;
|
||||
|
||||
if (afl->stage_max < MAXIMUM_QUICK_EFF_EXECS) { afl->stage_max *= 2; }
|
||||
@ -338,7 +349,7 @@ u8 skip_deterministic_stage(afl_state_t *afl, u8 *orig_buf, u8 *out_buf,
|
||||
|
||||
}
|
||||
|
||||
done_inf_map[afl->stage_cur_byte] = 1;
|
||||
bitmap_set(done_inf_map, afl->stage_cur_byte);
|
||||
|
||||
}
|
||||
|
||||
@ -364,7 +375,7 @@ cleanup_skipdet:
|
||||
while (i < len) {
|
||||
|
||||
// assume DWORD size, from i - 3 -> i + 3
|
||||
if (skip_eff_map[i]) {
|
||||
if (bitmap_read(skip_eff_map, i)) {
|
||||
|
||||
u32 fill_length = (i + 3 < len) ? 7 : len - i + 2;
|
||||
memset(nearby_bytes + i - 3, 1, fill_length);
|
||||
@ -378,7 +389,7 @@ cleanup_skipdet:
|
||||
|
||||
for (i = 0; i < len; i++) {
|
||||
|
||||
if (nearby_bytes[i] && !non_eff_bytes[i]) skip_eff_map[i] = 1;
|
||||
if (nearby_bytes[i] && !non_eff_bytes[i]) bitmap_set(skip_eff_map, i);
|
||||
|
||||
}
|
||||
|
||||
|
@ -106,6 +106,7 @@ void afl_state_init(afl_state_t *afl, uint32_t map_size) {
|
||||
afl->switch_fuzz_mode = STRATEGY_SWITCH_TIME * 1000;
|
||||
afl->q_testcase_max_cache_size = TESTCASE_CACHE_SIZE * 1048576UL;
|
||||
afl->q_testcase_max_cache_entries = 64 * 1024;
|
||||
afl->last_scored_idx = -1;
|
||||
|
||||
#ifdef HAVE_AFFINITY
|
||||
afl->cpu_aff = -1; /* Selected CPU core */
|
||||
@ -738,6 +739,21 @@ void afl_state_deinit(afl_state_t *afl) {
|
||||
if (afl->pass_stats) { ck_free(afl->pass_stats); }
|
||||
if (afl->orig_cmp_map) { ck_free(afl->orig_cmp_map); }
|
||||
if (afl->cmplog_binary) { ck_free(afl->cmplog_binary); }
|
||||
if (afl->cycle_schedules) {
|
||||
|
||||
for (u32 i = 0; i < afl->fsrv.map_size; i++) {
|
||||
|
||||
if (afl->top_rated_candidates[i]) {
|
||||
|
||||
ck_free(afl->top_rated_candidates[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ck_free(afl->top_rated_candidates);
|
||||
|
||||
}
|
||||
|
||||
afl_free(afl->queue_buf);
|
||||
afl_free(afl->out_buf);
|
||||
@ -746,6 +762,8 @@ void afl_state_deinit(afl_state_t *afl) {
|
||||
afl_free(afl->in_buf);
|
||||
afl_free(afl->in_scratch_buf);
|
||||
afl_free(afl->ex_buf);
|
||||
afl_free(afl->alias_table);
|
||||
afl_free(afl->alias_probability);
|
||||
|
||||
ck_free(afl->virgin_bits);
|
||||
ck_free(afl->virgin_tmout);
|
||||
@ -757,6 +775,11 @@ void afl_state_deinit(afl_state_t *afl) {
|
||||
ck_free(afl->first_trace);
|
||||
ck_free(afl->map_tmp_buf);
|
||||
|
||||
ck_free(afl->skipdet_g->inf_prof);
|
||||
ck_free(afl->skipdet_g->virgin_det_bits);
|
||||
ck_free(afl->skipdet_g);
|
||||
ck_free(afl->havoc_prof);
|
||||
|
||||
list_remove(&afl_states, afl);
|
||||
|
||||
}
|
||||
|
@ -604,6 +604,8 @@ void maybe_update_plot_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
|
||||
|
||||
void plot_profile_data(afl_state_t *afl, struct queue_entry *q) {
|
||||
|
||||
if (afl->skip_deterministic) { return; }
|
||||
|
||||
u64 current_ms = get_cur_time() - afl->start_time;
|
||||
|
||||
u32 current_edges = count_non_255_bytes(afl, afl->virgin_bits);
|
||||
|
@ -612,11 +612,11 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
afl->shmem_testcase_mode = 1; // we always try to perform shmem fuzzing
|
||||
|
||||
// still available: HjJkKqruvwz
|
||||
// still available: HjJkKqrv
|
||||
while (
|
||||
(opt = getopt(argc, argv,
|
||||
"+aw:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:"
|
||||
"T:uUV:WXx:YzZ")) > 0) {
|
||||
"+a:Ab:B:c:CdDe:E:f:F:g:G:hi:I:l:L:m:M:nNo:Op:P:QRs:S:t:T:"
|
||||
"uUV:w:WXx:YzZ")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
@ -1555,13 +1555,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
#endif
|
||||
|
||||
// silently disable deterministic mutation if custom mutators are used
|
||||
if (!afl->skip_deterministic && afl->afl_env.afl_custom_mutator_only) {
|
||||
|
||||
afl->skip_deterministic = 1;
|
||||
|
||||
}
|
||||
|
||||
if (afl->fixed_seed) {
|
||||
|
||||
OKF("Running with fixed seed: %u", (u32)afl->init_seed);
|
||||
@ -1750,8 +1743,27 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
}
|
||||
|
||||
afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
|
||||
afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
|
||||
if (afl->cycle_schedules) {
|
||||
|
||||
afl->top_rated_candidates = ck_alloc(map_size * sizeof(u32));
|
||||
|
||||
}
|
||||
|
||||
if (afl->san_binary_length) {
|
||||
|
||||
if (afl->san_abstraction == UNIQUE_TRACE) {
|
||||
|
||||
afl->n_fuzz_dup = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
|
||||
|
||||
}
|
||||
|
||||
if (afl->san_abstraction == SIMPLIFY_TRACE) {
|
||||
|
||||
afl->simplified_n_fuzz = ck_alloc(N_FUZZ_SIZE_BITMAP * sizeof(u8));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (get_afl_env("AFL_NO_FORKSRV")) { afl->no_forkserver = 1; }
|
||||
if (get_afl_env("AFL_NO_CPU_RED")) { afl->no_cpu_meter_red = 1; }
|
||||
@ -1759,16 +1771,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
if (get_afl_env("AFL_SHUFFLE_QUEUE")) { afl->shuffle_queue = 1; }
|
||||
if (get_afl_env("AFL_EXPAND_HAVOC_NOW")) { afl->expand_havoc = 1; }
|
||||
|
||||
if (afl->afl_env.afl_autoresume) {
|
||||
|
||||
afl->autoresume = 1;
|
||||
if (afl->in_place_resume) {
|
||||
|
||||
SAYF("AFL_AUTORESUME has no effect for '-i -'");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
if (afl->afl_env.afl_autoresume) { afl->autoresume = 1; }
|
||||
|
||||
if (afl->afl_env.afl_hang_tmout) {
|
||||
|
||||
@ -2326,8 +2329,8 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
u8 ver_string[8];
|
||||
u64 *ver = (u64 *)ver_string;
|
||||
u64 expect_ver =
|
||||
afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
|
||||
u64 expect_ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode +
|
||||
(sizeof(struct queue_entry) << 1);
|
||||
|
||||
if (NZLIBREAD(fr_fd, ver_string, sizeof(ver_string)) !=
|
||||
sizeof(ver_string))
|
||||
@ -2605,7 +2608,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
} else {
|
||||
|
||||
WARNF("Unknown abstraction: %s, fallback to unique trace.\n",
|
||||
WARNF("Unknown abstraction: %s, fallback to simplified trace.\n",
|
||||
san_abstraction);
|
||||
afl->san_abstraction = SIMPLIFY_TRACE;
|
||||
|
||||
@ -2843,12 +2846,13 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
|
||||
u32 r = 8 + afl->fsrv.map_size * 4;
|
||||
u32 q_len = o_end - o_start;
|
||||
u32 m_len = (afl->fsrv.map_size >> 3);
|
||||
u32 m_len = ((afl->fsrv.map_size + 7) >> 3);
|
||||
struct queue_entry *q;
|
||||
|
||||
for (u32 i = 0; i < afl->queued_items; i++) {
|
||||
|
||||
q = afl->queue_buf[i];
|
||||
// this is very dirty and assumes nice memory :-)
|
||||
ZLIBREAD(fr_fd, (u8 *)&(q->colorized), q_len, "queue data");
|
||||
ZLIBREAD(fr_fd, res, 1, "check map");
|
||||
if (res[0]) {
|
||||
@ -2865,7 +2869,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
afl->total_bitmap_size += q->bitmap_size;
|
||||
++afl->total_bitmap_entries;
|
||||
update_bitmap_score(afl, q);
|
||||
update_bitmap_score(afl, q, false);
|
||||
|
||||
if (q->was_fuzzed) { --afl->pending_not_fuzzed; }
|
||||
|
||||
@ -2943,7 +2947,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
for (entry = 0; entry < afl->queued_items; ++entry)
|
||||
if (!afl->queue_buf[entry]->disabled) { ++valid_seeds; }
|
||||
|
||||
if (!afl->pending_not_fuzzed || !valid_seeds) {
|
||||
if (!valid_seeds) {
|
||||
|
||||
FATAL("We need at least one valid input seed that does not crash!");
|
||||
|
||||
@ -3235,15 +3239,7 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
}
|
||||
|
||||
// we must recalculate the scores of all queue entries
|
||||
for (u32 i = 0; i < afl->queued_items; i++) {
|
||||
|
||||
if (likely(!afl->queue_buf[i]->disabled)) {
|
||||
|
||||
update_bitmap_score(afl, afl->queue_buf[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
recalculate_all_scores(afl);
|
||||
|
||||
}
|
||||
|
||||
@ -3545,7 +3541,8 @@ stop_fuzzing:
|
||||
u8 ver_string[8];
|
||||
u32 w = 0;
|
||||
u64 *ver = (u64 *)ver_string;
|
||||
*ver = afl->shm.cmplog_mode + (sizeof(struct queue_entry) << 1);
|
||||
*ver = FAST_RESUME_VERSION + afl->shm.cmplog_mode +
|
||||
(sizeof(struct queue_entry) << 1);
|
||||
|
||||
ZLIBWRITE(fr_fd, ver_string, sizeof(ver_string), "ver_string");
|
||||
ZLIBWRITE(fr_fd, afl->virgin_bits, afl->fsrv.map_size, "virgin_bits");
|
||||
@ -3558,7 +3555,7 @@ stop_fuzzing:
|
||||
u8 *o_start = (u8 *)&(afl->queue_buf[0]->colorized);
|
||||
u8 *o_end = (u8 *)&(afl->queue_buf[0]->mother);
|
||||
u32 q_len = o_end - o_start;
|
||||
u32 m_len = (afl->fsrv.map_size >> 3);
|
||||
u32 m_len = ((afl->fsrv.map_size + 7) >> 3);
|
||||
struct queue_entry *q;
|
||||
|
||||
afl->pending_not_fuzzed = afl->queued_items;
|
||||
@ -3625,6 +3622,10 @@ stop_fuzzing:
|
||||
|
||||
}
|
||||
|
||||
ck_free(afl->n_fuzz);
|
||||
ck_free(afl->n_fuzz_dup);
|
||||
ck_free(afl->simplified_n_fuzz);
|
||||
|
||||
if (afl->orig_cmdline) { ck_free(afl->orig_cmdline); }
|
||||
ck_free(afl->fsrv.target_path);
|
||||
ck_free(afl->fsrv.out_file);
|
||||
|
@ -131,8 +131,9 @@ static const u8 count_class_binary[256] = {
|
||||
|
||||
};
|
||||
|
||||
static void kill_child() {
|
||||
static void kill_child(int signal) {
|
||||
|
||||
(void)signal;
|
||||
timed_out = 1;
|
||||
if (fsrv->child_pid > 0) {
|
||||
|
||||
@ -158,10 +159,11 @@ void show_stats(afl_state_t *afl) {
|
||||
|
||||
}
|
||||
|
||||
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q) {
|
||||
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q, bool x) {
|
||||
|
||||
(void)afl;
|
||||
(void)q;
|
||||
(void)x;
|
||||
|
||||
}
|
||||
|
||||
@ -1259,8 +1261,6 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
break;
|
||||
|
||||
/* FIXME: We want to use -P for consistency, but it is already unused for
|
||||
* undocumenetd feature "Another afl-cmin specific feature." */
|
||||
case 'A': /* CoreSight mode */
|
||||
|
||||
#if !defined(__aarch64__) || !defined(__linux__)
|
||||
|
300
src/afl-tmin.c
300
src/afl-tmin.c
@ -37,6 +37,8 @@
|
||||
#include "forkserver.h"
|
||||
#include "sharedmem.h"
|
||||
#include "common.h"
|
||||
#include "afl-fuzz.h"
|
||||
#include "list.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
@ -48,6 +50,7 @@
|
||||
#include <dirent.h>
|
||||
#include <fcntl.h>
|
||||
#include <limits.h>
|
||||
#include <libgen.h>
|
||||
|
||||
#include <sys/wait.h>
|
||||
#include <sys/time.h>
|
||||
@ -57,8 +60,30 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/resource.h>
|
||||
#ifdef USE_PYTHON
|
||||
#include <Python.h>
|
||||
#endif
|
||||
|
||||
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
|
||||
extern void destroy_custom_mutators(afl_state_t *);
|
||||
void list_init(list_t *list) {
|
||||
|
||||
if (list) {
|
||||
|
||||
list->element_prealloc_count = 0;
|
||||
memset(list->element_prealloc_buf, 0, sizeof(list->element_prealloc_buf));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void setup_custom_mutators(afl_state_t *);
|
||||
struct custom_mutator *load_custom_mutator(afl_state_t *, const char *);
|
||||
#ifdef USE_PYTHON
|
||||
struct custom_mutator *load_custom_mutator_py(afl_state_t *, char *);
|
||||
#endif
|
||||
|
||||
static afl_state_t *afl; /* State for custom mutators */
|
||||
static u8 *mask_bitmap; /* Mask for trace bits (-B) */
|
||||
|
||||
static u8 *in_file, /* Minimizer input test case */
|
||||
*out_file, *output_file; /* Minimizer output file */
|
||||
@ -111,8 +136,9 @@ static const u8 count_class_lookup[256] = {
|
||||
|
||||
};
|
||||
|
||||
static void kill_child() {
|
||||
static void kill_child(int signal) {
|
||||
|
||||
(void)signal;
|
||||
if (fsrv->child_pid > 0) {
|
||||
|
||||
kill(fsrv->child_pid, fsrv->child_kill_signal);
|
||||
@ -134,6 +160,52 @@ static sharedmem_t *deinit_shmem(afl_forkserver_t *fsrv,
|
||||
|
||||
}
|
||||
|
||||
/* dummy functions */
|
||||
u32 write_to_testcase(afl_state_t *afl, void **mem, u32 a, u32 b) {
|
||||
|
||||
(void)afl;
|
||||
(void)mem;
|
||||
return a + b;
|
||||
|
||||
}
|
||||
|
||||
void show_stats(afl_state_t *afl) {
|
||||
|
||||
(void)afl;
|
||||
|
||||
}
|
||||
|
||||
void update_bitmap_score(afl_state_t *afl, struct queue_entry *q,
|
||||
bool add_to_queue) {
|
||||
|
||||
(void)afl;
|
||||
(void)q;
|
||||
(void)add_to_queue;
|
||||
|
||||
}
|
||||
|
||||
fsrv_run_result_t fuzz_run_target(afl_state_t *afl, afl_forkserver_t *fsrv,
|
||||
u32 i) {
|
||||
|
||||
(void)afl;
|
||||
(void)fsrv;
|
||||
(void)i;
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
#ifndef USE_PYTHON
|
||||
struct custom_mutator *load_custom_mutator_py(afl_state_t *afl, char *module) {
|
||||
|
||||
(void)afl;
|
||||
(void)module;
|
||||
FATAL("Python support not available in this build");
|
||||
return NULL;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* Apply mask to classified bitmap (if set). */
|
||||
|
||||
static void apply_mask(u32 *mem, u32 *mask) {
|
||||
@ -152,7 +224,7 @@ static void apply_mask(u32 *mem, u32 *mask) {
|
||||
|
||||
}
|
||||
|
||||
static void classify_counts(afl_forkserver_t *fsrv) {
|
||||
void classify_counts(afl_forkserver_t *fsrv) {
|
||||
|
||||
u8 *mem = fsrv->trace_bits;
|
||||
u32 i = map_size;
|
||||
@ -208,6 +280,13 @@ static void at_exit_handler(void) {
|
||||
afl_fsrv_killall();
|
||||
if (remove_out_file) unlink(out_file);
|
||||
|
||||
if (afl) {
|
||||
|
||||
destroy_custom_mutators(afl);
|
||||
ck_free(afl);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Read initial file. */
|
||||
@ -258,14 +337,72 @@ static s32 write_to_file(u8 *path, u8 *mem, u32 len) {
|
||||
|
||||
}
|
||||
|
||||
/* Helper function to handle custom mutators for testcase writing */
|
||||
static void pre_afl_fsrv_write_to_testcase(afl_forkserver_t *fsrv, u8 *mem,
|
||||
u32 len) {
|
||||
|
||||
static u8 buf[MAX_FILE];
|
||||
u32 sent = 0;
|
||||
|
||||
if (afl && afl->custom_mutators_count) {
|
||||
|
||||
ssize_t new_size = len;
|
||||
u8 *new_mem = mem;
|
||||
u8 *new_buf = NULL;
|
||||
|
||||
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
|
||||
|
||||
if (el->afl_custom_post_process) {
|
||||
|
||||
new_size =
|
||||
el->afl_custom_post_process(el->data, new_mem, new_size, &new_buf);
|
||||
|
||||
if (!new_buf || new_size <= 0) {
|
||||
|
||||
return;
|
||||
|
||||
} else {
|
||||
|
||||
new_mem = new_buf;
|
||||
len = new_size;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
if (new_mem != mem && new_mem != NULL) {
|
||||
|
||||
mem = buf;
|
||||
memcpy(mem, new_mem, new_size);
|
||||
|
||||
}
|
||||
|
||||
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
|
||||
|
||||
if (el->afl_custom_fuzz_send) {
|
||||
|
||||
el->afl_custom_fuzz_send(el->data, mem, len);
|
||||
sent = 1;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
if (!sent) { afl_fsrv_write_to_testcase(fsrv, mem, len); }
|
||||
|
||||
}
|
||||
|
||||
/* Execute target application. Returns 0 if the changes are a dud, or
|
||||
1 if they should be kept. */
|
||||
|
||||
static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
|
||||
u8 first_run) {
|
||||
|
||||
afl_fsrv_write_to_testcase(fsrv, mem, len);
|
||||
|
||||
pre_afl_fsrv_write_to_testcase(fsrv, mem, len);
|
||||
fsrv_run_result_t ret =
|
||||
afl_fsrv_run_target(fsrv, fsrv->exec_tmout, &stop_soon);
|
||||
|
||||
@ -356,14 +493,132 @@ static u8 tmin_run_target(afl_forkserver_t *fsrv, u8 *mem, u32 len,
|
||||
static void minimize(afl_forkserver_t *fsrv) {
|
||||
|
||||
static u32 alpha_map[256];
|
||||
|
||||
u8 *tmp_buf = ck_alloc_nozero(in_len);
|
||||
u32 orig_len = in_len, stage_o_len;
|
||||
|
||||
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
|
||||
u8 *tmp_buf = ck_alloc_nozero(in_len);
|
||||
u32 orig_len = in_len, stage_o_len;
|
||||
u32 del_len, set_len, del_pos, set_pos, i, alpha_size, cur_pass = 0;
|
||||
u32 syms_removed, alpha_del0 = 0, alpha_del1, alpha_del2, alpha_d_total = 0;
|
||||
u8 changed_any, prev_del;
|
||||
|
||||
#ifdef USE_PYTHON
|
||||
// Try to load python module
|
||||
char *py_module = getenv("AFL_PYTHON_MODULE");
|
||||
if (py_module) {
|
||||
|
||||
// We cannot use Python custom mutators in tmin
|
||||
if (debug) WARNF("Python custom mutator support not available in afl-tmin");
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
// Custom mutator trimming
|
||||
if (afl && afl->custom_mutators_count) {
|
||||
|
||||
LIST_FOREACH(&afl->custom_mutator_list, struct custom_mutator, {
|
||||
|
||||
if (el->afl_custom_init_trim && el->afl_custom_trim &&
|
||||
el->afl_custom_post_trim) {
|
||||
|
||||
ACTF("Performing custom trim with %s...", el->name);
|
||||
|
||||
// Initialize the trimmer
|
||||
s32 initial_steps = el->afl_custom_init_trim(el->data, in_data, in_len);
|
||||
|
||||
if (initial_steps <= 0) {
|
||||
|
||||
WARNF("Custom trimmer %s returned %d, skipping", el->name,
|
||||
initial_steps);
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
ACTF("Custom trimmer initialized, %d steps planned", initial_steps);
|
||||
|
||||
u32 trim_rounds = 0;
|
||||
u32 trimmed_successfully = 0;
|
||||
|
||||
// Trim loop
|
||||
s32 cur_step = 0;
|
||||
while (cur_step < initial_steps) {
|
||||
|
||||
u8 *trimmed_buf = NULL;
|
||||
size_t trimmed_size;
|
||||
|
||||
u8 *retbuf = NULL;
|
||||
trimmed_size = el->afl_custom_trim(el->data, &retbuf);
|
||||
|
||||
// If trimmed_size equals or exceeds original size, skip
|
||||
if (trimmed_size >= in_len) {
|
||||
|
||||
SAYF("[Custom trim] Round %u: no improvements over %u bytes.\n",
|
||||
trim_rounds, in_len);
|
||||
el->afl_custom_post_trim(el->data, 0);
|
||||
cur_step++;
|
||||
trim_rounds++;
|
||||
continue;
|
||||
|
||||
}
|
||||
|
||||
trimmed_buf = retbuf;
|
||||
|
||||
// Test if the trimmed case still works
|
||||
if (!tmin_run_target(fsrv, trimmed_buf, trimmed_size, 0)) {
|
||||
|
||||
SAYF(
|
||||
"[Custom trim] But the testcase no longer reproduces - "
|
||||
"skipping this reduction.\n");
|
||||
el->afl_custom_post_trim(el->data, 0);
|
||||
if (trimmed_buf != in_data) { ck_free(trimmed_buf); }
|
||||
|
||||
} else {
|
||||
|
||||
// Accept the reduction
|
||||
u8 *old_in_data = in_data;
|
||||
in_data = trimmed_buf;
|
||||
in_len = trimmed_size;
|
||||
|
||||
trimmed_successfully = 1;
|
||||
el->afl_custom_post_trim(el->data, 1);
|
||||
|
||||
SAYF("[Custom trim] Successful reduction to %u bytes\n", in_len);
|
||||
|
||||
if (old_in_data != in_data && old_in_data != trimmed_buf) {
|
||||
|
||||
ck_free(old_in_data);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
cur_step++;
|
||||
trim_rounds++;
|
||||
|
||||
}
|
||||
|
||||
ACTF("Custom trimming with %s complete after %u rounds, reduced: %s",
|
||||
el->name, trim_rounds, trimmed_successfully ? "yes" : "no");
|
||||
|
||||
if (trimmed_successfully) {
|
||||
|
||||
if (tmp_buf) { ck_free(tmp_buf); }
|
||||
return; // Skip standard minimization if successful
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
// Skip built-in minimization if in_len is too small
|
||||
if (in_len <= 1) {
|
||||
|
||||
if (tmp_buf) { ck_free(tmp_buf); }
|
||||
return;
|
||||
|
||||
}
|
||||
|
||||
/***********************
|
||||
* BLOCK NORMALIZATION *
|
||||
***********************/
|
||||
@ -746,7 +1001,7 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
|
||||
|
||||
/* Setup signal handlers, duh. */
|
||||
|
||||
static void setup_signal_handlers(void) {
|
||||
void setup_signal_handlers(void) {
|
||||
|
||||
struct sigaction sa;
|
||||
|
||||
@ -1242,6 +1497,29 @@ int main(int argc, char **argv_orig, char **envp) {
|
||||
|
||||
read_initial_file();
|
||||
|
||||
// Initialize AFL state for custom mutators
|
||||
afl = calloc(1, sizeof(afl_state_t));
|
||||
if (afl) {
|
||||
|
||||
list_init(&afl->custom_mutator_list);
|
||||
afl->custom_mutators_count = 0;
|
||||
|
||||
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
|
||||
|
||||
afl->afl_env.afl_custom_mutator_library =
|
||||
getenv("AFL_CUSTOM_MUTATOR_LIBRARY");
|
||||
afl->afl_env.afl_python_module = getenv("AFL_PYTHON_MODULE");
|
||||
|
||||
afl->shm = shm;
|
||||
afl->out_dir = dirname(in_file);
|
||||
|
||||
memcpy(&afl->fsrv, fsrv, sizeof(afl_forkserver_t));
|
||||
|
||||
setup_custom_mutators(afl);
|
||||
|
||||
}
|
||||
|
||||
#ifdef __linux__
|
||||
if (!fsrv->nyx_mode) { (void)check_binary_signatures(fsrv->target_path); }
|
||||
#else
|
||||
|
@ -114,6 +114,7 @@ def main():
|
||||
# ---------------------------------------------------
|
||||
# Load the binary to emulate and map it into memory
|
||||
|
||||
# Load the binary to emulate
|
||||
print("Loading data input from {}".format(args.input_file))
|
||||
binary_file = open(BINARY_FILE, "rb")
|
||||
binary_code = binary_file.read()
|
||||
@ -124,7 +125,7 @@ def main():
|
||||
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
|
||||
return
|
||||
|
||||
# Write the mutated command into the data buffer
|
||||
# Map the binary into memory
|
||||
uc.mem_map(CODE_ADDRESS, CODE_SIZE_MAX)
|
||||
uc.mem_write(CODE_ADDRESS, binary_code)
|
||||
|
||||
|
@ -142,6 +142,7 @@ def main():
|
||||
# ---------------------------------------------------
|
||||
# Load the binary to emulate and map it into memory
|
||||
|
||||
# Load the binary to emulate
|
||||
print("Loading data input from {}".format(args.input_file))
|
||||
binary_file = open(BINARY_FILE, "rb")
|
||||
binary_code = binary_file.read()
|
||||
@ -152,7 +153,7 @@ def main():
|
||||
print("Binary code is too large (> {} bytes)".format(CODE_SIZE_MAX))
|
||||
return
|
||||
|
||||
# Write the mutated command into the data buffer
|
||||
# Map the binary into memory
|
||||
uc.mem_map(CODE_ADDRESS, CODE_SIZE_MAX)
|
||||
uc.mem_write(CODE_ADDRESS, binary_code)
|
||||
|
||||
|
@ -20,6 +20,10 @@ endif
|
||||
|
||||
CFLAGS := -O3 -funroll-loops -g -fPIC
|
||||
|
||||
ifdef IOS_SDK_PATH
|
||||
CFLAGS += -isysroot $(IOS_SDK_PATH)
|
||||
endif
|
||||
|
||||
all: libAFLDriver.a libAFLQemuDriver.a aflpp_qemu_driver_hook.so
|
||||
|
||||
aflpp_driver.o: aflpp_driver.c
|
||||
|
@ -106,12 +106,16 @@ __attribute__((weak)) void __asan_unpoison_memory_region(
|
||||
__attribute__((weak)) void *__asan_region_is_poisoned(void *beg, size_t size);
|
||||
|
||||
// Notify AFL about persistent mode.
|
||||
static volatile char AFL_PERSISTENT[] = "##SIG_AFL_PERSISTENT##";
|
||||
int __afl_persistent_loop(unsigned int);
|
||||
__attribute__((section(".rodata"), used,
|
||||
retain)) static const char AFL_PERSISTENT[] =
|
||||
"##SIG_AFL_PERSISTENT##";
|
||||
int __afl_persistent_loop(unsigned int);
|
||||
|
||||
// Notify AFL about deferred forkserver.
|
||||
static volatile char AFL_DEFER_FORKSVR[] = "##SIG_AFL_DEFER_FORKSRV##";
|
||||
void __afl_manual_init();
|
||||
__attribute__((section(".rodata"), used,
|
||||
retain)) static const char AFL_DEFER_FORKSVR[] =
|
||||
"##SIG_AFL_DEFER_FORKSRV##";
|
||||
void __afl_manual_init();
|
||||
|
||||
// Use this optionally defined function to output sanitizer messages even if
|
||||
// user asks to close stderr.
|
||||
@ -350,11 +354,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
|
||||
|
||||
// Do any other expensive one-time initialization here.
|
||||
|
||||
uint8_t dummy_input[64] = {0};
|
||||
memcpy(dummy_input, (void *)AFL_PERSISTENT, sizeof(AFL_PERSISTENT));
|
||||
memcpy(dummy_input + 32, (void *)AFL_DEFER_FORKSVR,
|
||||
sizeof(AFL_DEFER_FORKSVR));
|
||||
|
||||
int N = INT_MAX;
|
||||
|
||||
if (!in_afl && argc == 2 && !strcmp(argv[1], "-")) {
|
||||
@ -392,10 +391,6 @@ __attribute__((weak)) int LLVMFuzzerRunDriver(
|
||||
|
||||
__afl_manual_init();
|
||||
|
||||
// Call LLVMFuzzerTestOneInput here so that coverage caused by initialization
|
||||
// on the first execution of LLVMFuzzerTestOneInput is ignored.
|
||||
callback(dummy_input, 4);
|
||||
|
||||
__asan_poison_memory_region(__afl_fuzz_ptr, MAX_FILE);
|
||||
size_t prev_length = 0;
|
||||
|
||||
|
@ -11,12 +11,12 @@
|
||||
#include <dlfcn.h>
|
||||
|
||||
#ifdef __ANDROID__
|
||||
#include "../include/android-ashmem.h"
|
||||
#include "../../include/android-ashmem.h"
|
||||
#endif
|
||||
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include "../config.h"
|
||||
#include "../../config.h"
|
||||
|
||||
#include <QBDI.h>
|
||||
|
||||
@ -80,8 +80,8 @@ static void afl_forkserver() {
|
||||
|
||||
while (1) {
|
||||
|
||||
int status;
|
||||
u32 was_killed;
|
||||
int status;
|
||||
unsigned int was_killed;
|
||||
// wait for afl-fuzz
|
||||
if (read(FORKSRV_FD, &was_killed, 4) != 4) exit(2);
|
||||
|
||||
|
Reference in New Issue
Block a user