mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 22:53:24 +00:00
Compare commits
134 Commits
Author | SHA1 | Date | |
---|---|---|---|
4217d6a9f8 | |||
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 | |||
f1ee7bc9cd | |||
969541b54f | |||
ec07f531f8 | |||
56b5983b61 | |||
f17ea60a30 | |||
68634964ef | |||
d21804bdd1 | |||
5a527046a5 | |||
b2a8765b1f | |||
106309492c | |||
58c5e2b96c | |||
5842ba87e5 | |||
5069551778 | |||
0606d95f86 | |||
0e35e56cc9 | |||
fc860872d6 | |||
735d647e48 | |||
73ab495b5d | |||
d1cab470bb | |||
992349e48a | |||
950b90abcd | |||
7c296f099f | |||
919e6226d3 | |||
a85f0c0ef9 | |||
6457e2ea30 | |||
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 |
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
|
||||
|
@ -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
|
||||
|
||||
|
62
GNUmakefile
62
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")
|
||||
@ -479,18 +486,33 @@ src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
|
||||
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
|
||||
$(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
|
||||
$(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)
|
||||
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,6 +530,9 @@ 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
|
||||
@ -512,6 +540,9 @@ test/unittests/unit_hash.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit
|
||||
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
|
||||
./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
|
||||
@ -519,6 +550,9 @@ test/unittests/unit_rand.o : $(COMM_HDR) include/alloc-inl.h test/unittests/unit
|
||||
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
|
||||
./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:
|
||||
|
@ -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 | 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
|
||||
$(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
|
||||
|
@ -4,7 +4,7 @@
|
||||
|
||||
Release version: [4.31c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.31c
|
||||
GitHub version: 4.32a
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
2
afl-cmin
2
afl-cmin
@ -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,18 @@
|
||||
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.32a (dev)
|
||||
- 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!
|
||||
- some 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
|
||||
- frida_mode:
|
||||
- fixes for new MacOS + M4 hardware
|
||||
|
||||
|
||||
### Version ++4.31c (release)
|
||||
- SAND mode added (docs/SAND.md) for more effecient fuzzing with sanitizers
|
||||
@ -22,7 +34,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 */
|
||||
|
||||
@ -1452,6 +1458,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.32a"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -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? */
|
||||
|
||||
|
@ -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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1 +1 @@
|
||||
4d837f06d5
|
||||
ef1cd9a8cb
|
||||
|
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);
|
||||
|
18
src/afl-cc.c
18
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);
|
||||
@ -1152,7 +1149,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");
|
||||
|
||||
@ -2031,6 +2029,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) {
|
||||
@ -2971,7 +2976,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(
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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:
|
||||
|
||||
@ -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);
|
||||
|
||||
}
|
||||
|
||||
@ -2267,18 +2314,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 +2636,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 +3153,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);
|
||||
|
||||
}
|
||||
|
||||
|
@ -634,7 +634,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 +754,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 +793,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 +837,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 +858,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 +887,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 +930,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 +983,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 +1067,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 +1197,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 +1331,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 +1391,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 +1479,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 +1573,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 +1642,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 +1708,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 +1768,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; }
|
||||
|
||||
@ -3655,18 +3655,18 @@ static u8 mopt_common_fuzzing(afl_state_t *afl, MOpt_globals_t MOpt_globals) {
|
||||
}
|
||||
|
||||
/* Go to pacemker fuzzing if MOpt is doing well */
|
||||
|
||||
/*
|
||||
cur_ms_lv = get_cur_time();
|
||||
if (!(afl->key_puppet == 0 &&
|
||||
((cur_ms_lv - afl->last_find_time < (u32)afl->limit_time_puppet) ||
|
||||
(afl->last_crash_time != 0 &&
|
||||
cur_ms_lv - afl->last_crash_time < (u32)afl->limit_time_puppet) ||
|
||||
afl->last_find_time == 0))) {
|
||||
|
||||
*/
|
||||
afl->key_puppet = 1;
|
||||
goto pacemaker_fuzzing;
|
||||
|
||||
}
|
||||
// }
|
||||
|
||||
/* Skip right away if -d is given, if we have done deterministic fuzzing on
|
||||
this entry ourselves (was_fuzzed), or if it has gone through deterministic
|
||||
|
@ -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, 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);
|
||||
|
||||
|
@ -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; }
|
||||
|
||||
}
|
||||
|
||||
@ -1166,7 +1161,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);
|
||||
@ -757,6 +773,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) {
|
||||
|
||||
@ -1750,8 +1750,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 +1778,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 +2336,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 +2615,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 +2853,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 +2876,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 +2954,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 +3246,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 +3548,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 +3562,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 +3629,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;
|
||||
|
||||
}
|
||||
|
||||
|
@ -111,8 +111,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);
|
||||
|
@ -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