mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 22:53:24 +00:00
Compare commits
180 Commits
Author | SHA1 | Date | |
---|---|---|---|
e8caa32b0e | |||
be276eb425 | |||
f9a8b60b3b | |||
4a1cf0b9af | |||
d6a2edb42a | |||
5e8e233755 | |||
31ed850c4b | |||
994ac55878 | |||
cb5a61d8a1 | |||
146e535f7b | |||
b88f132975 | |||
12271064f8 | |||
55b67f1372 | |||
595cc3aadd | |||
d21fb1a558 | |||
2e6c74f9b9 | |||
2a4281ce8d | |||
9cd702e75d | |||
8b35dd49be | |||
703fd0b610 | |||
db172473b5 | |||
1f335b0d82 | |||
60620d4c81 | |||
0ee028cfae | |||
1d09b242a9 | |||
5b44067e9c | |||
8531928fa4 | |||
804c98a1e8 | |||
1792ce2825 | |||
1d6cd5dd19 | |||
7e9abf1bba | |||
6a28502191 | |||
fc7c95e9f4 | |||
4086b93ad7 | |||
837a9693ab | |||
60d3ecab63 | |||
d0f39849c2 | |||
8820bf4758 | |||
75d8c47a6b | |||
3ec794c806 | |||
bf46ff8823 | |||
6f61fca15a | |||
b8cb35fa8c | |||
dfc9b3dba0 | |||
ab5f95e17a | |||
fe66a95d96 | |||
72a24e6439 | |||
088dd6476c | |||
30df52cd8c | |||
74d262c7b5 | |||
d7c99007ff | |||
bdb5622bd4 | |||
cf2ddf437b | |||
2b7aae66b6 | |||
598a3c6b5e | |||
0978283915 | |||
f27cbdb793 | |||
1689a8e053 | |||
6edc3b51ba | |||
93fb1d1a24 | |||
bf7a6d69cf | |||
6ddd5ecf4a | |||
e2099114aa | |||
db84f75a81 | |||
9111035495 | |||
d78a8698e4 | |||
7b2f983bf3 | |||
1910b0ad42 | |||
9a04df5d97 | |||
4f03f380ea | |||
e3b08d430c | |||
4f35c30371 | |||
9df9064549 | |||
256bc6ab42 | |||
614c5127ca | |||
5bb894f1ee | |||
8d72f41e20 | |||
b928303dd0 | |||
76b26ac2c6 | |||
dd16be405a | |||
2e57d86576 | |||
4369d6209f | |||
26ae4124f3 | |||
25945d51a4 | |||
db23931e7c | |||
6e37f9b237 | |||
2f2ddbbd79 | |||
ba7c012427 | |||
5bfe0c1a15 | |||
bb72cc752a | |||
8c4ecd90a8 | |||
c0d53a1aa7 | |||
31a1fbae33 | |||
09f1854cd1 | |||
4a6b751b93 | |||
bbcb3dd53e | |||
eac53afe7b | |||
19ca7b3761 | |||
55a2362348 | |||
8afb60d2f9 | |||
69a596c089 | |||
ccb952dde8 | |||
7c380a6612 | |||
88e2affe73 | |||
3f26818d97 | |||
bd83eb0f42 | |||
c5acf3f137 | |||
ea42feb06a | |||
a09720665d | |||
6f394842be | |||
02f4f75526 | |||
43f462c91b | |||
77bad3ad23 | |||
835a4b6497 | |||
d1a7b6988c | |||
365129d811 | |||
b840ac91dc | |||
dcd2f9ac77 | |||
37d9afc5cc | |||
62b3a1e800 | |||
9c54be6cf1 | |||
53409530b3 | |||
43014cd465 | |||
e27e3622d4 | |||
b169629dbd | |||
8fbeeb1439 | |||
2a489f844b | |||
a161aac7c1 | |||
a7f928ac31 | |||
50ae95cee4 | |||
f6bfa96a96 | |||
e86dcc9f18 | |||
9d33580aac | |||
77cfd504cf | |||
f7bbd467b5 | |||
8993ba4305 | |||
ba7313b521 | |||
e2d30641be | |||
2248773566 | |||
5f43d0ad42 | |||
af47531745 | |||
e80bd2d30c | |||
ac5815d994 | |||
540d741df0 | |||
ecb5854be0 | |||
25b650f59d | |||
ed6f19d3d8 | |||
aecd157244 | |||
43a98b0ec2 | |||
3b00cee858 | |||
2fbc0aefb1 | |||
2276a2f5c3 | |||
8fcca6fb41 | |||
b8568034f0 | |||
3ebf41ba34 | |||
304e84502d | |||
a6e42d98d9 | |||
de176a10bc | |||
e3183f7cda | |||
b5e0fff6b9 | |||
36db3428ab | |||
e7da8b9d6b | |||
c134df30db | |||
b5e6c2d6e2 | |||
b6f8509234 | |||
d45cd63583 | |||
0c9b460cc4 | |||
dd762726dc | |||
e68d57feec | |||
0c9d8e5929 | |||
75c3fa91dc | |||
a37c7e1246 | |||
392dcd57c6 | |||
1369cf7176 | |||
eccd0985a0 | |||
0617b8898a | |||
fbcdeb8439 | |||
6ed0a2b4aa | |||
8e50c0c103 | |||
f2cd5e1d8e |
@ -24,7 +24,7 @@ import importlib.metadata
|
||||
|
||||
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
|
||||
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 17)
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
|
||||
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
|
||||
|
||||
|
||||
|
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
@ -34,23 +34,25 @@ jobs:
|
||||
run: export NO_NYX=1; export ASAN_BUILD=1; export LLVM_CONFIG=llvm-config-12; make ASAN_BUILD=1 NO_NYX=1 LLVM_CONFIG=llvm-config-12 distrib
|
||||
- name: run tests
|
||||
run: sudo -E ./afl-system-config; make tests
|
||||
# macos:
|
||||
# runs-on: macOS-latest
|
||||
# env:
|
||||
# AFL_MAP_SIZE: 65536
|
||||
# AFL_SKIP_CPUFREQ: 1
|
||||
# AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
# steps:
|
||||
# - uses: actions/checkout@v3
|
||||
# - 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
|
||||
# - 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
|
||||
# - name: frida
|
||||
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
|
||||
# - name: run tests
|
||||
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
|
||||
# - name: force frida test for MacOS
|
||||
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
|
||||
macos:
|
||||
runs-on: macOS-latest
|
||||
env:
|
||||
AFL_MAP_SIZE: 65536
|
||||
AFL_SKIP_CPUFREQ: 1
|
||||
AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES: 1
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- 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
|
||||
# - 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
|
||||
run: sudo -E ./afl-system-config; gmake ASAN_BUILD=1 afl-fuzz
|
||||
# - name: frida
|
||||
# run: export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; cd frida_mode; gmake
|
||||
# - name: run tests
|
||||
# run: sudo -E ./afl-system-config; export CC=/usr/local/Cellar/llvm/*/bin/clang; export CXX="$CC"++; export PATH=/usr/local/Cellar/llvm/*/":/usr/local/bin:$PATH"; export LLVM_CONFIG=/usr/local/Cellar/llvm/*/bin/llvm-config; gmake tests
|
||||
# - name: force frida test for MacOS
|
||||
# run: export AFL_PATH=`pwd`; /usr/local/bin/gcc -o test-instr test-instr.c; mkdir in; echo > in/in; AFL_NO_UI=1 ./afl-fuzz -O -i in -o out -V 5 -- ./test-instr
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,6 +6,7 @@
|
||||
*.pyc
|
||||
*.so
|
||||
*.swp
|
||||
.DS_Store
|
||||
.sync_tmp
|
||||
.test
|
||||
.test2
|
||||
@ -111,3 +112,5 @@ utils/replay_record/persistent_demo_replay_compat
|
||||
utils/replay_record/persistent_demo_replay_argparse
|
||||
utils/plot_ui/afl-plot-ui
|
||||
vuln_prog
|
||||
argv_fuzz_demo
|
||||
argv_fuzz_persistent_demo
|
@ -34,6 +34,7 @@ file in one the following folders:
|
||||
* [docs/](docs/) (this is where you can find most of our docs content)
|
||||
* [frida_mode/](frida_mode/)
|
||||
* [instrumentation/](instrumentation/)
|
||||
* [nyx_mode/](nyx_mode/)
|
||||
* [qemu_mode/](qemu_mode/)
|
||||
* [unicorn_mode/](unicorn_mode/)
|
||||
|
||||
@ -47,7 +48,7 @@ When working on the docs, please keep the following guidelines in mind:
|
||||
* Don't: fuzzing-network-service.md
|
||||
* Use a maximum of 80 characters per line to make reading in a console easier.
|
||||
* Make all pull requests against `dev`, see
|
||||
[#how-to-submit-a-pull-request-to-afl](#how-to-submit-a-pull-request-to-afl).
|
||||
[#how-to-submit-a-pull-request](#how-to-submit-a-pull-request).
|
||||
|
||||
And finally, here are some best practices for writing docs content:
|
||||
|
||||
@ -56,4 +57,4 @@ And finally, here are some best practices for writing docs content:
|
||||
* Use bulleted lists to present similar content in a way that makes it easy to
|
||||
scan.
|
||||
* Use numbered lists for procedures or prioritizing.
|
||||
* Link to related content, for example, prerequisites or in-depth discussions.
|
||||
* Link to related content, for example, prerequisites or in-depth discussions.
|
||||
|
12
GNUmakefile
12
GNUmakefile
@ -441,6 +441,14 @@ test_shm:
|
||||
@echo "[-] shmat seems not to be working, switching to mmap implementation"
|
||||
endif
|
||||
|
||||
ifeq "$(shell echo '$(HASH)include <zlib.h>@int main() {return 0; }' | tr @ '\n' | $(CC) $(CFLAGS) -Werror -x c - -lz -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
override SPECIAL_PERFORMANCE += -DHAVE_ZLIB
|
||||
override LDFLAGS += -lz
|
||||
$(info [+] ZLIB detected)
|
||||
else
|
||||
$(info [!] Warning: no ZLIB detected)
|
||||
endif
|
||||
|
||||
.PHONY: test_python
|
||||
ifeq "$(PYTHON_OK)" "1"
|
||||
test_python:
|
||||
@ -471,8 +479,8 @@ src/afl-forkserver.o : $(COMM_HDR) src/afl-forkserver.c include/forkserver.h
|
||||
src/afl-sharedmem.o : $(COMM_HDR) src/afl-sharedmem.c include/sharedmem.h
|
||||
$(CC) $(CFLAGS) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -c src/afl-sharedmem.c -o src/afl-sharedmem.o
|
||||
|
||||
afl-fuzz: $(COMM_HDR) include/afl-fuzz.h $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c | test_x86
|
||||
$(CC) $(CFLAGS) $(COMPILE_STATIC) $(CFLAGS_FLTO) $(SPECIAL_PERFORMANCE) -Wno-shift-count-overflow $(AFL_FUZZ_FILES) src/afl-common.o src/afl-sharedmem.o src/afl-forkserver.o src/afl-performance.o src/hashmap.c -o $@ $(PYFLAGS) $(LDFLAGS) -lm
|
||||
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
|
||||
|
||||
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)
|
||||
|
@ -32,6 +32,9 @@ VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2
|
||||
|
||||
SYS = $(shell uname -s)
|
||||
|
||||
override LLVM_TOO_NEW_DEFAULT := 18
|
||||
override LLVM_TOO_OLD_DEFAULT := 13
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
|
||||
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
|
||||
@ -39,24 +42,36 @@ ifeq "$(SYS)" "OpenBSD"
|
||||
$(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 13) -> e.g. "pkg_add llvm-7.0.1p9")
|
||||
endif
|
||||
else
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
# Small function to use Bash to detect the latest available clang and clang++ binaries, if using them by that name fails
|
||||
override _CLANG_VERSIONS_TO_TEST := $(patsubst %,-%,$(shell seq $(LLVM_TOO_NEW_DEFAULT) -1 $(LLVM_TOO_OLD_DEFAULT)))
|
||||
detect_newest=$(shell for v in "" $(_CLANG_VERSIONS_TO_TEST); do test -n "$$(command -v -- $1$$v)" && { echo "$1$$v"; break; }; done)
|
||||
LLVM_CONFIG ?= $(call detect_newest,llvm-config)
|
||||
endif
|
||||
|
||||
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
|
||||
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
|
||||
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' | sed 's/rc.*//' )
|
||||
LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[0-2]\.|^3.[0-8]\.' && echo 1 || echo 0 )
|
||||
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^19|^2[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_TOO_OLD = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^[1-9]\.|^1[012]\.' && echo 1 || echo 0 )
|
||||
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[0-9]' && echo 1 || echo 0 )
|
||||
LLVM_NEWER_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[6-9]' && echo 1 || echo 0 )
|
||||
LLVM_13_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[3-9]' && echo 1 || echo 0 )
|
||||
LLVM_HAVE_LTO = $(shell $(LLVM_CONFIG) --version 2>/dev/null | grep -E -q '^1[2-9]' && echo 1 || echo 0 )
|
||||
LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
|
||||
LLVM_STDCXX = gnu++11
|
||||
LLVM_APPLE_XCODE = $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
|
||||
LLVM_LTO = 0
|
||||
ifneq "$(LLVM_CONFIG)" ""
|
||||
override LLVM_RAW_VER := $(shell $(LLVM_CONFIG) --version 2>/dev/null)
|
||||
LLVMVER := $(subst svn,,$(subst git,,$(LLVM_RAW_VER)))
|
||||
|
||||
LLVM_BINDIR := $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)
|
||||
LLVM_LIBDIR := $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
|
||||
endif
|
||||
|
||||
ifneq "$(LLVMVER)" ""
|
||||
LLVM_MAJOR := $(firstword $(subst ., ,$(LLVMVER)))
|
||||
LLVM_MINOR := $(firstword $(subst ., ,$(subst $(LLVM_MAJOR).,,$(LLVMVER))))
|
||||
LLVM_TOO_NEW := $(shell test $(LLVM_MAJOR) -gt $(LLVM_TOO_NEW_DEFAULT) && echo 1 || echo 0)
|
||||
LLVM_TOO_OLD := $(shell test $(LLVM_MAJOR) -lt $(LLVM_TOO_OLD_DEFAULT) && echo 1 || echo 0)
|
||||
LLVM_NEW_API := $(shell test $(LLVM_MAJOR) -ge 10 && echo 1 || echo 0)
|
||||
LLVM_NEWER_API := $(shell test $(LLVM_MAJOR) -ge 16 && echo 1 || echo 0)
|
||||
LLVM_13_OK := $(shell test $(LLVM_MAJOR) -ge 13 && echo 1 || echo 0)
|
||||
LLVM_HAVE_LTO := $(shell test $(LLVM_MAJOR) -ge 12 && echo 1 || echo 0)
|
||||
endif
|
||||
|
||||
LLVM_STDCXX := gnu++11
|
||||
LLVM_LTO := 0
|
||||
LLVM_UNSUPPORTED := $(shell echo "$(LLVMVER)" | grep -E -q '^[0-2]\.|^3\.[0-8]\.' && echo 1 || echo 0)
|
||||
# Uncomment to see the values assigned above
|
||||
# $(foreach var,LLVM_CONFIG LLVMVER LLVM_MAJOR LLVM_MINOR LLVM_TOO_NEW LLVM_TOO_OLD LLVM_TOO_NEW_DEFAULT LLVM_TOO_OLD_DEFAULT LLVM_NEW_API LLVM_NEWER_API LLVM_13_OK LLVM_HAVE_LTO LLVM_BINDIR LLVM_LIBDIR LLVM_STDCXX LLVM_APPLE_XCODE LLVM_LTO LLVM_UNSUPPORTED,$(warning $(var) = $($(var))))
|
||||
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
|
||||
@ -103,10 +118,6 @@ ifeq "$(LLVM_LTO)" "0"
|
||||
$(info [+] llvm_mode detected llvm < 12, afl-lto LTO will not be build.)
|
||||
endif
|
||||
|
||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# We were using llvm-config --bindir to get the location of clang, but
|
||||
# this seems to be busted on some distros, so using the one in $PATH is
|
||||
# probably better.
|
||||
@ -114,6 +125,11 @@ endif
|
||||
CC = $(LLVM_BINDIR)/clang
|
||||
CXX = $(LLVM_BINDIR)/clang++
|
||||
|
||||
LLVM_APPLE_XCODE := $(shell $(CC) -v 2>&1 | grep -q Apple && echo 1 || echo 0)
|
||||
ifeq "$(LLVM_APPLE_XCODE)" "1"
|
||||
$(warning llvm_mode will not compile with Xcode clang...)
|
||||
endif
|
||||
|
||||
# llvm-config --bindir may not providing a valid path, so ...
|
||||
ifeq "$(shell test -e $(CC) || echo 1 )" "1"
|
||||
# however we must ensure that this is not a "CC=gcc make"
|
||||
@ -245,7 +261,7 @@ endif
|
||||
|
||||
AFL_CLANG_FUSELD=
|
||||
ifeq "$(LLVM_LTO)" "1"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=`command -v ld` -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=$$(command -v ld) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_FUSELD=1
|
||||
ifeq "$(shell echo 'int main() {return 0; }' | $(CLANG_BIN) -x c - -fuse-ld=ld.lld --ld-path=$(AFL_REAL_LD) -o .test 2>/dev/null && echo 1 || echo 0 ; rm -f .test )" "1"
|
||||
AFL_CLANG_LDPATH=1
|
||||
@ -300,8 +316,8 @@ endif
|
||||
ifneq "$(LLVM_CONFIG)" ""
|
||||
CLANG_CFL += -I$(shell dirname $(LLVM_CONFIG))/../include
|
||||
endif
|
||||
CLANG_CPPFL = `$(LLVM_CONFIG) --cxxflags` -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
|
||||
CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
|
||||
CLANG_CPPFL = $$($(LLVM_CONFIG) --cxxflags) -fno-rtti -fno-exceptions -fPIC $(CXXFLAGS) $(CPPFLAGS) -Wno-deprecated-declarations
|
||||
CLANG_LFL = $$($(LLVM_CONFIG) --ldflags) $(LDFLAGS)
|
||||
|
||||
# wasm fuzzing: disable thread-local storage and unset LLVM debug flag
|
||||
ifdef WAFL_MODE
|
||||
@ -311,7 +327,7 @@ endif
|
||||
|
||||
# User teor2345 reports that this is required to make things work on MacOS X.
|
||||
ifeq "$(SYS)" "Darwin"
|
||||
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
|
||||
CLANG_LFL += -Wl,-undefined,dynamic_lookup
|
||||
override LLVM_HAVE_LTO := 0
|
||||
override LLVM_LTO := 0
|
||||
else
|
||||
@ -319,7 +335,7 @@ else
|
||||
endif
|
||||
|
||||
ifeq "$(SYS)" "OpenBSD"
|
||||
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
|
||||
CLANG_LFL += $$($(LLVM_CONFIG) --libdir)/libLLVM.so
|
||||
CLANG_CPPFL += -mno-retpoline
|
||||
CFLAGS += -mno-retpoline
|
||||
# Needed for unwind symbols
|
||||
@ -417,7 +433,7 @@ endif
|
||||
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"
|
||||
|
@ -1,10 +1,10 @@
|
||||
# American Fuzzy Lop plus plus (AFL++)
|
||||
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" height="250">
|
||||
|
||||
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.21c
|
||||
GitHub version: 4.22a
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
2
TODO.md
2
TODO.md
@ -2,7 +2,7 @@
|
||||
|
||||
## Must
|
||||
|
||||
- fast restart of afl-fuzz if cmdline + target hash is the same
|
||||
- ijon support?
|
||||
- check for null ptr for xml/curl/g_ string transform functions
|
||||
- hardened_usercopy=0 page_alloc.shuffle=0
|
||||
- add value_profile but only enable after 15 minutes without finds
|
||||
|
@ -112,12 +112,12 @@ if [ -z "$NO_COLOR" ]; then
|
||||
fi
|
||||
|
||||
PLATFORM=`uname -s`
|
||||
if [ "$PLATFORM" = "Linux" ] ; then
|
||||
CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
|
||||
else
|
||||
#if [ "$PLATFORM" = "Linux" ] ; then
|
||||
# CUR_TIME=`cat /proc/uptime | awk '{printf "%.0f\n", $1}'`
|
||||
#else
|
||||
# This will lead to inacurate results but will prevent the script from breaking on platforms other than Linux
|
||||
CUR_TIME=`date +%s`
|
||||
fi
|
||||
#fi
|
||||
|
||||
TMP=`mktemp -t .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || TMP=`mktemp -p /data/local/tmp .afl-whatsup-XXXXXXXX` || exit 1
|
||||
trap "rm -f $TMP" 1 2 3 13 15
|
||||
|
@ -11,3 +11,4 @@
|
||||
|AMD Ryzen 9 6900HS with Radeon Graphics | 4745 | 16 | 135501 | 991133 | both |
|
||||
|AMD Ryzen 9 7950X3D 16-Core Processor | 5400 | 32 | 71566 | 1566279 | system |
|
||||
|AMD Ryzen 9 7950X3D 16-Core Processor | 5478 | 32 | 161960 | 2173959 | both |
|
||||
|Ampere Altra Q80-30 | 0 | 80 | 54477 | 1604482 | system |
|
||||
|
@ -48,7 +48,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
u8 *ptr = realloc(data->buf, max_size);
|
||||
|
||||
if (ptr) {
|
||||
if (!ptr) {
|
||||
|
||||
return 0;
|
||||
|
||||
|
@ -4,7 +4,7 @@ CFLAGS = -O3 -funroll-loops -fPIC
|
||||
all: aflpp-standalone
|
||||
|
||||
aflpp-standalone: aflpp-standalone.c
|
||||
$(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.c ../../../src/afl-fuzz-extras.c ../../../src/afl-common.c
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ aflpp-standalone core
|
||||
|
@ -5,6 +5,6 @@ this is the AFL++ havoc mutator as a standalone mutator
|
||||
just type `make` to build.
|
||||
|
||||
```
|
||||
aflpp-standalone inputfile outputfile [splicefile]
|
||||
aflpp-standalone -h # to see all parameteres
|
||||
cat file | aflpp-standalone -m 4 -x foo.dict - outputfile splicefile # example
|
||||
```
|
||||
|
||||
|
@ -1,6 +1,12 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int max_havoc = 16, verbose;
|
||||
static unsigned char *dict;
|
||||
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
@ -21,14 +27,14 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
}
|
||||
|
||||
if ((data->buf = malloc(1024*1024)) == NULL) {
|
||||
if ((data->buf = malloc(1024 * 1024)) == NULL) {
|
||||
|
||||
perror("afl_custom_init alloc");
|
||||
return NULL;
|
||||
|
||||
} else {
|
||||
|
||||
data->buf_size = 1024*1024;
|
||||
data->buf_size = 1024 * 1024;
|
||||
|
||||
}
|
||||
|
||||
@ -36,9 +42,23 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
data->afl = calloc(1, sizeof(afl_state_t));
|
||||
data->afl->queue_cycle = 1;
|
||||
data->afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (data->afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
|
||||
if (data->afl->fsrv.dev_urandom_fd < 0) {
|
||||
|
||||
PFATAL("Unable to open /dev/urandom");
|
||||
|
||||
}
|
||||
|
||||
rand_set_seed(data->afl, getpid());
|
||||
|
||||
if (dict) {
|
||||
|
||||
load_extras(data->afl, dict);
|
||||
if (verbose)
|
||||
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
|
||||
data->afl->extras_cnt);
|
||||
|
||||
}
|
||||
|
||||
return data;
|
||||
|
||||
}
|
||||
@ -53,7 +73,7 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
u8 *ptr = realloc(data->buf, max_size);
|
||||
|
||||
if (ptr) {
|
||||
if (!ptr) {
|
||||
|
||||
return 0;
|
||||
|
||||
@ -66,14 +86,20 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
}
|
||||
|
||||
u32 havoc_steps = 1 + rand_below(data->afl, 16);
|
||||
u32 havoc_steps = 1 + rand_below(data->afl, max_havoc);
|
||||
if (verbose) fprintf(stderr, "Havoc steps: %u\n", havoc_steps);
|
||||
|
||||
/* set everything up, costly ... :( */
|
||||
memcpy(data->buf, buf, buf_size);
|
||||
|
||||
/* the mutation */
|
||||
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
|
||||
false, true, add_buf, add_buf_size, max_size);
|
||||
u32 out_buf_len;
|
||||
do {
|
||||
|
||||
out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps, false,
|
||||
true, add_buf, add_buf_size, max_size);
|
||||
|
||||
} while (out_buf_len == buf_size && memcmp(buf, data->buf, buf_size) == 0);
|
||||
|
||||
/* return size of mutated data */
|
||||
*out_buf = data->buf;
|
||||
@ -84,80 +110,143 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
|
||||
printf("Syntax: %s [-v] [inputfile [outputfile [splicefile]]]\n\n", argv[0]);
|
||||
printf("Reads a testcase from stdin when no input file (or '-') is specified,\n");
|
||||
printf("mutates according to AFL++'s mutation engine, and write to stdout when '-' or\n");
|
||||
printf("no output filename is given. As an optional third parameter you can give a file\n");
|
||||
|
||||
printf(
|
||||
"Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
|
||||
"[splicefile]]]\n\n",
|
||||
argv[0]);
|
||||
printf(
|
||||
"Reads a testcase from stdin when no input file (or '-') is "
|
||||
"specified,\n");
|
||||
printf(
|
||||
"mutates according to AFL++'s mutation engine, and write to stdout "
|
||||
"when '-' or\n");
|
||||
printf(
|
||||
"no output filename is given. As an optional third parameter you can "
|
||||
"give a file\n");
|
||||
printf("for splicing. Maximum input and output length is 1MB.\n");
|
||||
printf("The -v verbose option prints debug output to stderr.\n");
|
||||
printf("Options:\n");
|
||||
printf(" -v verbose debug output to stderr.\n");
|
||||
printf(" -m val max mutations (1-val, val default is 16)\n");
|
||||
printf(" -x file dictionary file (AFL++ format)\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL;
|
||||
int verbose = 0, splicelen = 0;
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
|
||||
int splicelen = 0, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'm':
|
||||
max_havoc = atoi(optarg);
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'x':
|
||||
dict = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (max_havoc < 1) {
|
||||
|
||||
fprintf(stderr, "Error: illegal -m value\n");
|
||||
exit(-1);
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-v") == 0) {
|
||||
verbose = 1;
|
||||
argc--;
|
||||
argv++;
|
||||
fprintf(stderr, "Verbose active\n");
|
||||
}
|
||||
|
||||
my_mutator_t *data = afl_custom_init(NULL, 0);
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-") != 0) {
|
||||
if ((in = fopen(argv[1], "r")) == NULL) {
|
||||
if (argc > optind && strcmp(argv[optind], "-") != 0) {
|
||||
|
||||
if ((in = fopen(argv[optind], "r")) == NULL) {
|
||||
|
||||
perror(argv[1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[1]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
|
||||
|
||||
}
|
||||
|
||||
size_t inlen = fread(inbuf, 1, 1024*1024, in);
|
||||
|
||||
size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
|
||||
|
||||
if (!inlen) {
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin");
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n",
|
||||
argv[optind] ? argv[optind] : "stdin");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (argc > 2 && strcmp(argv[2], "-") != 0) {
|
||||
if ((out = fopen(argv[2], "w")) == NULL) {
|
||||
perror(argv[2]);
|
||||
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
|
||||
|
||||
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
|
||||
|
||||
perror(argv[optind + 1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[2]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
|
||||
|
||||
}
|
||||
|
||||
if (argc > 3) {
|
||||
if ((splice = fopen(argv[3], "r")) == NULL) {
|
||||
perror(argv[3]);
|
||||
if (argc > optind + 2) {
|
||||
|
||||
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
|
||||
|
||||
perror(argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
if (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
|
||||
splicebuf = malloc(1024*1024);
|
||||
size_t splicelen = fread(splicebuf, 1, 1024*1024, splice);
|
||||
|
||||
if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
|
||||
splicebuf = malloc(1024 * 1024);
|
||||
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
|
||||
if (!splicelen) {
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[3]);
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
|
||||
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf, splicelen, 1024*1024);
|
||||
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
|
||||
splicelen, 1024 * 1024);
|
||||
|
||||
if (outlen == 0 || !outbuf) {
|
||||
|
||||
fprintf(stderr, "Error: no mutation data returned.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
|
||||
|
||||
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
||||
|
||||
fprintf(stderr, "Warning: incomplete write.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -13,7 +13,7 @@ Just type `make` to build `atnwalk.so`.
|
||||
**NOTE:** The commands below just demonstrate an example how running ATNwalk looks like and require a working [testbed](https://github.com/atnwalk/testbed)
|
||||
|
||||
```bash
|
||||
# create the required a random seed first
|
||||
# create the required random seed first
|
||||
mkdir -p ~/campaign/example/seeds
|
||||
cd ~/campaign/example/seeds
|
||||
head -c1 /dev/urandom | ~/atnwalk/build/javascript/bin/decode -wb > seed.decoded 2> seed.encoded
|
||||
|
@ -180,7 +180,8 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
|
||||
|
||||
if (fd_socket != -1) { close(fd_socket); }
|
||||
*out_buf = NULL;
|
||||
return 0;
|
||||
fprintf(stderr, "atnwalk.socket not found in current directory!\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,7 @@ extern "C" {
|
||||
#ifndef AFL_TXT_MAX_LEN
|
||||
#define AFL_TXT_MAX_LEN 65535
|
||||
#endif
|
||||
#define AUTOTOKENS_TXT_MIN_LEN 1
|
||||
|
||||
#if AUTOTOKENS_SPLICE_MIN >= AUTOTOKENS_SIZE_MIN
|
||||
#error SPLICE_MIN must be lower than SIZE_MIN
|
||||
@ -57,8 +58,9 @@ typedef struct my_mutator {
|
||||
if (unlikely(debug)) fprintf
|
||||
#define IFDEBUG if (unlikely(debug))
|
||||
|
||||
int module_disabled = 0;
|
||||
|
||||
static afl_state *afl_ptr;
|
||||
static int module_disabled = 0;
|
||||
static int auto_disable = AUTOTOKENS_AUTO_DISABLE;
|
||||
static int debug = AUTOTOKENS_DEBUG;
|
||||
static int only_fav = AUTOTOKENS_ONLY_FAV;
|
||||
@ -104,9 +106,9 @@ static void first_run(void *data) {
|
||||
if (afl_ptr->custom_only || !auto_disable) { return; }
|
||||
|
||||
if (unlikely(afl_ptr->active_items == 1 &&
|
||||
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN)) {
|
||||
afl_ptr->queue_cur->len < AUTOTOKENS_TXT_MIN_LEN)) {
|
||||
|
||||
if (afl_ptr->extras_cnt > 8) {
|
||||
if (afl_ptr->extras_cnt) {
|
||||
|
||||
u32 valid = 0;
|
||||
|
||||
@ -237,7 +239,7 @@ extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf,
|
||||
|
||||
}
|
||||
|
||||
extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size,
|
||||
extern "C" size_t afl_custom_fuzz(void *data, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf, u8 *add_buf,
|
||||
size_t add_buf_size, size_t max_size) {
|
||||
|
||||
@ -655,6 +657,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
if (current_id > whitespace_ids + 6 && afl_ptr->active_items == 1 &&
|
||||
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN) {
|
||||
|
||||
retry_thin_air:
|
||||
DEBUGF(stderr, "Creating an entry from thin air...\n");
|
||||
structure = new vector<u32>();
|
||||
u32 item, prev, cnt = current_id >> 1;
|
||||
@ -684,8 +687,6 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
}
|
||||
|
||||
create_from_thin_air = 0;
|
||||
|
||||
}
|
||||
|
||||
if (entry == file_mapping.end()) {
|
||||
@ -693,7 +694,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
// this input file was not analyzed for tokens yet, so let's do it!
|
||||
size_t len = afl_ptr->queue_cur->len;
|
||||
|
||||
if (len < AFL_TXT_MIN_LEN) {
|
||||
if (len < AUTOTOKENS_TXT_MIN_LEN) {
|
||||
|
||||
file_mapping[fn] = structure; // NULL ptr so we don't read the file again
|
||||
s = NULL;
|
||||
@ -895,6 +896,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
if (tokens.size() < AUTOTOKENS_SIZE_MIN) {
|
||||
|
||||
if (create_from_thin_air) { goto retry_thin_air; }
|
||||
file_mapping[fn] = NULL;
|
||||
s = NULL;
|
||||
DEBUGF(stderr, "too few tokens\n");
|
||||
@ -955,7 +957,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
}
|
||||
|
||||
extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
|
||||
extern "C" void *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
(void)(seed);
|
||||
my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t));
|
||||
@ -1070,7 +1072,7 @@ extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
|
||||
id_to_token[current_id] = "'";
|
||||
++current_id;
|
||||
|
||||
return data;
|
||||
return (void *)data;
|
||||
|
||||
}
|
||||
|
||||
|
19
custom_mutators/autotokens/standalone/Makefile
Normal file
19
custom_mutators/autotokens/standalone/Makefile
Normal file
@ -0,0 +1,19 @@
|
||||
|
||||
CFLAGS = -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1 -Wno-implicit-function-declaration
|
||||
CXXFLAGS= -g -O3 -funroll-loops -fPIC -D_STANDALONE_MODULE=1
|
||||
|
||||
all: autotokens-standalone
|
||||
|
||||
autotokens.o: ../autotokens.cpp
|
||||
$(CXX) $(CXXFLAGS) -I../../../include -I. -I../.. -c ../autotokens.cpp
|
||||
|
||||
autotokens-standalone: autotokens-standalone.c autotokens.o
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c autotokens-standalone.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-performance.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-extras.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-fuzz-queue.c
|
||||
$(CC) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -c ../../../src/afl-common.c
|
||||
$(CXX) $(CFLAGS) -DBIN_PATH=\"foo\" -I../../../include -I. -o autotokens-standalone *.o
|
||||
|
||||
clean:
|
||||
rm -f *.o *~ autotokens-standalone core
|
12
custom_mutators/autotokens/standalone/README.md
Normal file
12
custom_mutators/autotokens/standalone/README.md
Normal file
@ -0,0 +1,12 @@
|
||||
# Autotokens standalone mutator
|
||||
|
||||
this is a standalone version of the AFL++ autotokens custom mutator.
|
||||
|
||||
just type `make` to build.
|
||||
|
||||
You *MUST* use a dictionary file to have an effective grammarless grammar fuzzer!
|
||||
|
||||
```
|
||||
autotokens-standalone -h # to see all parameteres
|
||||
autotokens-standalone -x foo.dict inputfile outputfile # example
|
||||
```
|
192
custom_mutators/autotokens/standalone/autotokens-standalone.c
Normal file
192
custom_mutators/autotokens/standalone/autotokens-standalone.c
Normal file
@ -0,0 +1,192 @@
|
||||
#include "afl-fuzz.h"
|
||||
#include "afl-mutations.h"
|
||||
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
|
||||
static int max_havoc = 16, verbose;
|
||||
static unsigned char *dict, *mh = "16";
|
||||
|
||||
extern int module_disabled;
|
||||
|
||||
void *afl_custom_init(afl_state_t *, unsigned int);
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
|
||||
if (argc > 1 && strncmp(argv[1], "-h", 2) == 0) {
|
||||
|
||||
printf(
|
||||
"Syntax: %s [-v] [-m maxmutations] [-x dict] [inputfile [outputfile "
|
||||
"[splicefile]]]\n\n",
|
||||
argv[0]);
|
||||
printf("Reads a testcase from a file (not stdin!),\n");
|
||||
printf("writes to stdout when '-' or\n");
|
||||
printf(
|
||||
"no output filename is given. As an optional third parameter you can "
|
||||
"give a file\n");
|
||||
printf("for splicing. Maximum input and output length is 1MB.\n");
|
||||
printf("Options:\n");
|
||||
printf(" -v verbose debug output to stderr.\n");
|
||||
printf(" -m val max mutations (1-val, val default is 16)\n");
|
||||
printf(" -x file dictionary file (AFL++ format)\n");
|
||||
printf("You can set the following environment variable parameters:\n");
|
||||
printf("AUTOTOKENS_COMMENT` - what character or string starts a comment which will be\n");
|
||||
printf(" removed. Default: \"/* ... */\"\n");
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf = NULL, *splicebuf = NULL;
|
||||
int splicelen = 0, opt;
|
||||
|
||||
while ((opt = getopt(argc, argv, "vm:x:")) > 0) {
|
||||
|
||||
switch (opt) {
|
||||
|
||||
case 'm':
|
||||
max_havoc = atoi(optarg);
|
||||
mh = optarg;
|
||||
break;
|
||||
case 'v':
|
||||
verbose = 1;
|
||||
break;
|
||||
case 'x':
|
||||
dict = optarg;
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr, "Error: unknown parameter -%c\n", opt);
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (max_havoc < 1) {
|
||||
|
||||
fprintf(stderr, "Error: illegal -m value\n");
|
||||
exit(-1);
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind && strcmp(argv[optind], "-") != 0) {
|
||||
|
||||
if ((in = fopen(argv[optind], "r")) == NULL) {
|
||||
|
||||
perror(argv[1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
|
||||
|
||||
}
|
||||
|
||||
size_t inlen = fread(inbuf, 1, 1024 * 1024, in);
|
||||
|
||||
if (!inlen) {
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n",
|
||||
argv[optind] ? argv[optind] : "stdin");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
|
||||
|
||||
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
|
||||
|
||||
perror(argv[optind + 1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind + 2) {
|
||||
|
||||
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
|
||||
|
||||
perror(argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Splice: %s\n", argv[optind + 2]);
|
||||
splicebuf = malloc(1024 * 1024);
|
||||
size_t splicelen = fread(splicebuf, 1, 1024 * 1024, splice);
|
||||
if (!splicelen) {
|
||||
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[optind + 2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation splice length: %zu\n", splicelen);
|
||||
|
||||
}
|
||||
|
||||
/* configure autotokens */
|
||||
setenv("AUTOTOKENS_LEARN_DICT", "1", 0);
|
||||
setenv("AUTOTOKENS_CREATE_FROM_THIN_AIR", "1", 0);
|
||||
setenv("AUTOTOKENS_CHANGE_MAX", mh, 0);
|
||||
|
||||
/* fake AFL++ state */
|
||||
afl_state_t *afl = (afl_state_t *)calloc(1, sizeof(afl_state_t));
|
||||
afl->queue_cycle = afl->havoc_div = afl->active_items = afl->queued_items = 1;
|
||||
afl->shm.cmplog_mode = 0;
|
||||
afl->fsrv.dev_urandom_fd = open("/dev/urandom", O_RDONLY);
|
||||
if (afl->fsrv.dev_urandom_fd < 0) { PFATAL("Unable to open /dev/urandom"); }
|
||||
|
||||
rand_set_seed(afl, getpid());
|
||||
|
||||
if (dict) {
|
||||
|
||||
load_extras(afl, dict);
|
||||
if (verbose)
|
||||
fprintf(stderr, "Loaded dictionary: %s (%u entries)\n", dict,
|
||||
afl->extras_cnt);
|
||||
|
||||
}
|
||||
|
||||
// setup a fake queue entry
|
||||
afl->queue_buf = malloc(64);
|
||||
afl->queue_buf[0] = afl->queue_cur =
|
||||
(struct queue_entry *)malloc(sizeof(struct queue_entry));
|
||||
afl->queue_cur->testcase_buf = inbuf;
|
||||
afl->queue_cur->fname = (u8 *)argv[optind];
|
||||
afl->queue_cur->len = inlen;
|
||||
afl->queue_cur->perf_score = 100;
|
||||
afl->queue_cur->favored = afl->queue_cur->is_ascii = 1;
|
||||
// afl->custom_only = 1;
|
||||
|
||||
void *data = (void *)afl_custom_init(afl, (u32)0);
|
||||
|
||||
u8 res = afl_custom_queue_get(inbuf, (u8 *)argv[optind]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation input length: %zu\n", inlen);
|
||||
unsigned int outlen = afl_custom_fuzz(data, inbuf, inlen, &outbuf, splicebuf,
|
||||
splicelen, 1024 * 1024);
|
||||
|
||||
if (outlen == 0 || !outbuf) {
|
||||
|
||||
fprintf(stderr, "Error: no mutation data returned.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Mutation output length: %u\n", outlen);
|
||||
|
||||
if (fwrite(outbuf, 1, outlen, out) != outlen) {
|
||||
|
||||
fprintf(stderr, "Warning: incomplete write.\n");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
7
custom_mutators/custom_send_tcp/Makefile
Normal file
7
custom_mutators/custom_send_tcp/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
all: custom_send_tcp.so
|
||||
|
||||
custom_send_tcp.so:
|
||||
$(CC) -Wno-unused-result -g -O3 -shared -fPIC -o custom_send_tcp.so -I../../include custom_send_tcp.c
|
||||
|
||||
clean:
|
||||
rm -f custom_send_tcp.so *.o *~ core
|
13
custom_mutators/custom_send_tcp/README.md
Normal file
13
custom_mutators/custom_send_tcp/README.md
Normal file
@ -0,0 +1,13 @@
|
||||
# Send testcases via TCP custom mutator
|
||||
|
||||
This custom mutator sends the fuzzing testcases via TCP.
|
||||
|
||||
`AFL_CUSTOM_MUTATOR_LATE_SEND` - MUST be set!
|
||||
`CUSTOM_SEND_IP` - the IP address to send to (basically only 127.0.0.1 makes sense)
|
||||
`CUSTOM_SEND_PORT` - the TCP port to send to
|
||||
`CUSTOM_SEND_READ` - if the custom mutator should wait for a reply from the target
|
||||
|
||||
Example:
|
||||
```
|
||||
CUSTOM_SEND_IP=127.0.0.1 CUSTOM_SEND_PORT=8000 CUSTOM_SEND_READ=1 AFL_CUSTOM_MUTATOR_LATE_SEND=1 AFL_CUSTOM_MUTATOR_LIBRARY=custom_send_tcp.so ./afl-fuzz ...
|
||||
```
|
113
custom_mutators/custom_send_tcp/custom_send_tcp.c
Normal file
113
custom_mutators/custom_send_tcp/custom_send_tcp.c
Normal file
@ -0,0 +1,113 @@
|
||||
#include <time.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#include "afl-fuzz.h"
|
||||
|
||||
static int my_debug = 0;
|
||||
static int my_read = 0;
|
||||
|
||||
#define DEBUG(...) if (my_debug) printf(__VA_ARGS__)
|
||||
|
||||
typedef struct tcp_send_mutator {
|
||||
afl_state_t* afl;
|
||||
struct sockaddr_in server_addr;
|
||||
} tcp_send_mutator_t;
|
||||
|
||||
void *afl_custom_init(afl_state_t* afl, uint32_t seed) {
|
||||
const char* ip = getenv("CUSTOM_SEND_IP");
|
||||
const char* port = getenv("CUSTOM_SEND_PORT");
|
||||
|
||||
if (getenv("AFL_DEBUG")) my_debug = 1;
|
||||
if (getenv("CUSTOM_SEND_READ")) my_read = 1;
|
||||
|
||||
if (!ip || !port) {
|
||||
fprintf(stderr, "You forgot to set CUSTOM_SEND_IP and/or CUSTOM_SEND_PORT\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
tcp_send_mutator_t* mutator = calloc(1, sizeof(tcp_send_mutator_t));
|
||||
if (!mutator) {
|
||||
fprintf(stderr, "Failed to allocate mutator struct\n");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
mutator->afl = afl;
|
||||
|
||||
bzero(&mutator->server_addr, sizeof(mutator->server_addr));
|
||||
mutator->server_addr.sin_family = AF_INET;
|
||||
if (inet_pton(AF_INET, ip, &mutator->server_addr.sin_addr) <= 0) {
|
||||
fprintf(stderr, "Could not convert target ip address!\n");
|
||||
exit(1);
|
||||
}
|
||||
mutator->server_addr.sin_port = htons(atoi(port));
|
||||
|
||||
printf("[+] Custom tcp send mutator setup ready to go!\n");
|
||||
|
||||
return mutator;
|
||||
}
|
||||
|
||||
int try_connect(tcp_send_mutator_t *mutator, int sock, int max_attempts) {
|
||||
while (max_attempts > 0) {
|
||||
if (connect(sock, (struct sockaddr*)&mutator->server_addr, sizeof(mutator->server_addr)) == 0) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Even with AFL_CUSTOM_LATE_SEND=1, there is a race between the
|
||||
// application under test having started to listen for connections and
|
||||
// afl_custom_fuzz_send being called. To address this race, we attempt
|
||||
// to connect N times and sleep a short period of time in between
|
||||
// connection attempts.
|
||||
struct timespec t;
|
||||
t.tv_sec = 0;
|
||||
t.tv_nsec = 100;
|
||||
nanosleep(&t, NULL);
|
||||
--max_attempts;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
void afl_custom_fuzz_send(tcp_send_mutator_t *mutator, uint8_t *buf, size_t buf_size) {
|
||||
int sock = socket(AF_INET, SOCK_STREAM, 0);
|
||||
|
||||
int written = 0;
|
||||
if (sock >= 0 && try_connect(mutator, sock, 10000) == 0) {
|
||||
DEBUG("connected, write()\n");
|
||||
written = write(sock, buf, buf_size);
|
||||
} else {
|
||||
DEBUG("socket() or connect() error: %d\n", errno);
|
||||
}
|
||||
|
||||
if (written < 0) {
|
||||
DEBUG("write() error: %d\n", errno);
|
||||
} else if (my_read) {
|
||||
struct timeval timeout;
|
||||
timeout.tv_sec = 1;
|
||||
timeout.tv_usec = 0;
|
||||
|
||||
fd_set set;
|
||||
FD_ZERO(&set);
|
||||
FD_SET(sock, &set);
|
||||
|
||||
int select_res = select(sock + 1, &set, NULL, NULL, &timeout);
|
||||
if (select_res == -1) {
|
||||
DEBUG("select() error: %d\n", errno);
|
||||
} else if (select_res == 0) {
|
||||
DEBUG("read() timeout!\n");
|
||||
} else {
|
||||
uint8_t buf[64];
|
||||
(void)read(sock, buf, sizeof(buf));
|
||||
}
|
||||
}
|
||||
|
||||
close(sock);
|
||||
}
|
||||
|
||||
void afl_custom_deinit(tcp_send_mutator_t* mutator) {
|
||||
free(mutator);
|
||||
}
|
Submodule custom_mutators/gramatron/json-c updated: 11546bfd07...af8dd4a307
@ -1 +1 @@
|
||||
95a6857
|
||||
05d8f53
|
||||
|
Submodule custom_mutators/grammar_mutator/grammar_mutator updated: 95a685773e...05d8f537f8
@ -3707,7 +3707,7 @@ typedef intptr_t wdiff;
|
||||
1024 * 1024 * 8 /* static malloc'd heap size if used as a library */
|
||||
#define FBITS 24 /* bits in fixnum, on the way to 24 and beyond */
|
||||
#define FMAX \
|
||||
((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
|
||||
((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
|
||||
*/
|
||||
#define MAXOBJ 0xffff /* max words in tuple including header */
|
||||
#define MAXPAYL \
|
||||
|
5713
dictionaries/ruby.dict
Normal file
5713
dictionaries/ruby.dict
Normal file
File diff suppressed because it is too large
Load Diff
@ -3,6 +3,43 @@
|
||||
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.22a (dev)
|
||||
- afl-fuzz:
|
||||
- fastresume feature added. if you abort fuzzing and resume fuzzing
|
||||
with `-i -` or `AFL_AUTORESUME=1` and the target binary has not changed
|
||||
then a dump will be loaded and the calibration phase skipped.
|
||||
to disable this feature set `AFL_NO_FASTRESUME=1`
|
||||
zlib compression is used if zlib is found at compile time
|
||||
- improved seed selection algorithm
|
||||
- added `AFL_CUSTOM_MUTATOR_LATE_SEND=1` to call the custom send()
|
||||
function after the target has been restarted.
|
||||
- because of bad math and undefined behaviour fixes we have to change
|
||||
the CMPLOG map. **YOU NEED TO RECOMPILE CMPLOG TARGETS**
|
||||
- fixed custom_post_process for calibration
|
||||
- frida_mode:
|
||||
- AFL_FRIDA_PERSISTENT_ADDR can now be be any reachable address not just
|
||||
a function entry
|
||||
- AFL_DEBUG is now the same as AFL_FRIDA_VERBOSE
|
||||
- AFL_FRIDA_DEBUG_MAPS now works as expected
|
||||
- qemu_mode:
|
||||
- new hooks supported (optional), see qemu_mode/hooking_bridge - thanks to
|
||||
@CowBoy4mH3LL
|
||||
- unicorn_mode:
|
||||
- fix install and forkserver (thanks aarnav!)
|
||||
- nyx_mode:
|
||||
- bugfixes
|
||||
- custom mutators:
|
||||
- custom_send_tcp custom mutator added, thanks to @dergoegge
|
||||
- afl-cc
|
||||
- fix to support pointless changes in LLVM 20
|
||||
- new runtime (!) variable: `AFL_OLD_FORKSERVER` to use the old vanilla
|
||||
AFL type forkserver. Useful for symcc/symqemu/nautilus/etc. with
|
||||
AFL_LLVM_INSTRUMENT=CLASSIC
|
||||
- code formatting updated to llvm 18
|
||||
- improved custom_mutators/aflpp/standalone/aflpp-standalone
|
||||
- added custom_mutators/autotokens/standalone/autotokens-standalone
|
||||
|
||||
|
||||
### Version ++4.21c (release)
|
||||
* afl-fuzz
|
||||
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
|
||||
@ -42,7 +79,6 @@
|
||||
* Fixed a shmem mmap bug (that rarely came up on MacOS)
|
||||
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
|
||||
|
||||
|
||||
### Version ++4.20c (release)
|
||||
! A new forkserver communication model is now introduced. afl-fuzz is
|
||||
backward compatible to old compiled targets if they are not built
|
||||
|
@ -30,6 +30,9 @@ sudo apt-get install -y build-essential python3-dev automake cmake git flex biso
|
||||
sudo apt-get install -y lld-14 llvm-14 llvm-14-dev clang-14 || sudo apt-get install -y lld llvm llvm-dev clang
|
||||
sudo apt-get install -y gcc-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-plugin-dev libstdc++-$(gcc --version|head -n1|sed 's/\..*//'|sed 's/.* //')-dev
|
||||
sudo apt-get install -y ninja-build # for QEMU mode
|
||||
sudo apt-get install -y cpio libcapstone-dev # for Nyx mode
|
||||
sudo apt-get install -y wget curl # for Frida mode
|
||||
sudo apt-get install -y python3-pip # for Unicorn mode
|
||||
git clone https://github.com/AFLplusplus/AFLplusplus
|
||||
cd AFLplusplus
|
||||
make distrib
|
||||
|
@ -198,6 +198,11 @@ def deinit(): # optional for Python
|
||||
This method can be used if you want to send data to the target yourself,
|
||||
e.g. via IPC. This replaces some usage of utils/afl_proxy but requires
|
||||
that you start the target with afl-fuzz.
|
||||
|
||||
Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
|
||||
function after the target has been restarted. (This is needed for e.g. TCP
|
||||
services.)
|
||||
|
||||
Example: [custom_mutators/examples/custom_send.c](../custom_mutators/examples/custom_send.c)
|
||||
|
||||
- `queue_new_entry` (optional):
|
||||
|
@ -331,7 +331,26 @@ mode.
|
||||
the target performs only a few loops, then this will give a small
|
||||
performance boost.
|
||||
|
||||
## 4) Settings for afl-fuzz
|
||||
## 4) Runtime settings
|
||||
|
||||
The following environment variables are for a compiled AFL++ target.
|
||||
|
||||
- Setting `AFL_DUMP_MAP_SIZE` when executing the target directly will
|
||||
dump the map size of the target and exit.
|
||||
|
||||
- Setting `AFL_OLD_FORKSERVER` will use the old AFL vanilla forkserver.
|
||||
This makes only sense when you
|
||||
a) compile in a classic colliding coverage mode (e.g.
|
||||
AFL_LLVM_INSTRUMENT=CLASSIC) or if the map size of the target is
|
||||
below MAP_SIZE (65536 by default), AND
|
||||
b) you want to use this compiled AFL++ target with a different tool
|
||||
that expects vanilla AFL behaviour, e.g. symcc, symqemu, nautilus, etc.
|
||||
You would use this option together with the target fuzzing application.
|
||||
|
||||
- Setting `AFL_DISABLE_LLVM_INSTRUMENTATION` will disable collecting
|
||||
instrumentation. (More of an internal option.)
|
||||
|
||||
## 5) Settings for afl-fuzz
|
||||
|
||||
The main fuzzer binary accepts several options that disable a couple of sanity
|
||||
checks or alter some of the more exotic semantics of the tool:
|
||||
@ -368,6 +387,10 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
XML or other highly flexible structured input. For details, see
|
||||
[custom_mutators.md](custom_mutators.md).
|
||||
|
||||
- Setting `AFL_CUSTOM_MUTATOR_LATE_SEND` will call the afl_custom_fuzz_send()
|
||||
function after the target has been restarted. (This is needed for e.g. TCP
|
||||
services.)
|
||||
|
||||
- Setting `AFL_CYCLE_SCHEDULES` will switch to a different schedule every time
|
||||
a cycle is finished.
|
||||
|
||||
@ -514,6 +537,8 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
- `AFL_NO_SNAPSHOT` will advise afl-fuzz not to use the snapshot feature if
|
||||
the snapshot lkm is loaded.
|
||||
|
||||
- `AFL_NO_FASTRESUME` will not try to read or write a fast resume file.
|
||||
|
||||
- Setting `AFL_NO_UI` inhibits the UI altogether and just periodically prints
|
||||
some basic stats. This behavior is also automatically triggered when the
|
||||
output from afl-fuzz is redirected to a file or to a pipe.
|
||||
@ -585,7 +610,7 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
see [rpc_statsd.md](rpc_statsd.md).
|
||||
|
||||
- `AFL_SYNC_TIME` allows you to specify a different minimal time (in minutes)
|
||||
between fuzzing instances synchronization. Default sync time is 30 minutes,
|
||||
between fuzzing instances synchronization. Default sync time is 20 minutes,
|
||||
note that time is halved for -M main nodes.
|
||||
|
||||
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
|
||||
@ -636,7 +661,7 @@ checks or alter some of the more exotic semantics of the tool:
|
||||
Note that will not be exact and with slow targets it can take seconds
|
||||
until there is a slice for the time test.
|
||||
|
||||
## 5) Settings for afl-qemu-trace
|
||||
## 6) Settings for afl-qemu-trace
|
||||
|
||||
The QEMU wrapper used to instrument binary-only code supports several settings:
|
||||
|
||||
@ -708,7 +733,7 @@ The QEMU wrapper used to instrument binary-only code supports several settings:
|
||||
crash is found. Setting `AFL_NO_CRASH_README` will prevent this. Useful when
|
||||
counting crashes based on a file count in that directory.
|
||||
|
||||
## 7) Settings for afl-frida-trace
|
||||
## 8) Settings for afl-frida-trace
|
||||
|
||||
The FRIDA wrapper used to instrument binary-only code supports many of the same
|
||||
options as `afl-qemu-trace`, but also has a number of additional advanced
|
||||
@ -798,7 +823,7 @@ support.
|
||||
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
|
||||
killing the process whilst it is being dumped.
|
||||
|
||||
## 8) Settings for afl-cmin
|
||||
## 9) Settings for afl-cmin
|
||||
|
||||
The corpus minimization script offers very little customization:
|
||||
|
||||
@ -816,7 +841,7 @@ The corpus minimization script offers very little customization:
|
||||
- `AFL_PRINT_FILENAMES` prints each filename to stdout, as it gets processed.
|
||||
This can help when embedding `afl-cmin` or `afl-showmap` in other scripts.
|
||||
|
||||
## 9) Settings for afl-tmin
|
||||
## 10) Settings for afl-tmin
|
||||
|
||||
Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be
|
||||
searched for afl-qemu-trace. In addition to this, `TMPDIR` may be used if a
|
||||
@ -827,12 +852,12 @@ to match when minimizing crashes. This will make minimization less useful, but
|
||||
may prevent the tool from "jumping" from one crashing condition to another in
|
||||
very buggy software. You probably want to combine it with the `-e` flag.
|
||||
|
||||
## 10) Settings for afl-analyze
|
||||
## 11) Settings for afl-analyze
|
||||
|
||||
You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead
|
||||
of decimal.
|
||||
|
||||
## 11) Settings for libdislocator
|
||||
## 12) Settings for libdislocator
|
||||
|
||||
The library honors these environment variables:
|
||||
|
||||
@ -854,12 +879,12 @@ The library honors these environment variables:
|
||||
- `AFL_LD_VERBOSE` causes the library to output some diagnostic messages that
|
||||
may be useful for pinpointing the cause of any observed issues.
|
||||
|
||||
## 11) Settings for libtokencap
|
||||
## 13) Settings for libtokencap
|
||||
|
||||
This library accepts `AFL_TOKEN_FILE` to indicate the location to which the
|
||||
discovered tokens should be written.
|
||||
|
||||
## 12) Third-party variables set by afl-fuzz & other tools
|
||||
## 14) Third-party variables set by afl-fuzz & other tools
|
||||
|
||||
Several variables are not directly interpreted by afl-fuzz, but are set to
|
||||
optimal values if not already present in the environment:
|
||||
|
@ -632,7 +632,7 @@ crash or timeout during startup.
|
||||
|
||||
Also, it is recommended to set `export AFL_IMPORT_FIRST=1` to load test cases
|
||||
from other fuzzers in the campaign first. But note that can slow down the start
|
||||
of the first fuzz by quite a lot of you have many fuzzers and/or many seeds.
|
||||
of the first fuzz by quite a lot if you have many fuzzers and/or many seeds.
|
||||
|
||||
If you have a large corpus, a corpus from a previous run or are fuzzing in a CI,
|
||||
then also set `export AFL_CMPLOG_ONLY_NEW=1` and `export AFL_FAST_CAL=1`.
|
||||
|
@ -214,6 +214,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE
|
||||
arm:
|
||||
CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all
|
||||
|
||||
arm64:
|
||||
ARCH="arm64" TARGET_CC=aarch64-linux-gnu-gcc TARGET_CXX=aarch64-linux-gnu-g++ make all
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $(BUILD_DIR)
|
||||
|
||||
|
@ -6,34 +6,39 @@
|
||||
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
UNUSED_PARAMETER (size);
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
||||
|
||||
ElfW(Addr) * base = data;
|
||||
UNUSED_PARAMETER(size);
|
||||
|
||||
ElfW(Addr) *base = data;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main (int argc, char** argv, char** envp) {
|
||||
UNUSED_PARAMETER (argc);
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
|
||||
ElfW(Addr) base = 0;
|
||||
UNUSED_PARAMETER(argc);
|
||||
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
ElfW(Addr) base = 0;
|
||||
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
}
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
|
||||
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
|
||||
dl_iterate_phdr(phdr_callback, &base);
|
||||
}
|
||||
|
||||
printf("%p\n", (void *)base);
|
||||
if (base == 0) { return 1; }
|
||||
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||
|
||||
dl_iterate_phdr(phdr_callback, &base);
|
||||
|
||||
printf("%p\n", (void *)base);
|
||||
if (base == 0) { return 1; }
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -45,6 +45,7 @@
|
||||
js_api_set_stdout;
|
||||
js_api_set_traceable;
|
||||
js_api_set_verbose;
|
||||
js_api_ijon_set;
|
||||
|
||||
local:
|
||||
*;
|
||||
|
@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
|
||||
// do a length check matching the target!
|
||||
|
||||
void **esp = (void **)regs->esp;
|
||||
void *arg1 = esp[0];
|
||||
void **arg2 = &esp[1];
|
||||
void *arg1 = esp[1];
|
||||
void **arg2 = &esp[2];
|
||||
memcpy(arg1, input_buf, input_buf_len);
|
||||
*arg2 = (void *)input_buf_len;
|
||||
|
||||
|
@ -36,7 +36,7 @@ struct x86_64_regs {
|
||||
void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
|
||||
uint8_t *input_buf, uint32_t input_buf_len) {
|
||||
|
||||
(void)guest_base; /* unused */
|
||||
(void)guest_base; /* unused */
|
||||
memcpy((void *)regs->rdi, input_buf, input_buf_len);
|
||||
regs->rsi = input_buf_len;
|
||||
|
||||
@ -76,14 +76,15 @@ struct x86_regs {
|
||||
void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
|
||||
uint8_t *input_buf, uint32_t input_buf_len) {
|
||||
|
||||
(void)guest_base; /* unused */
|
||||
(void)guest_base; /* unused */
|
||||
void **esp = (void **)regs->esp;
|
||||
void * arg1 = esp[1];
|
||||
void *arg1 = esp[1];
|
||||
void **arg2 = &esp[2];
|
||||
memcpy(arg1, input_buf, input_buf_len);
|
||||
*arg2 = (void *)input_buf_len;
|
||||
|
||||
}
|
||||
|
||||
#elif defined(__aarch64__)
|
||||
|
||||
struct arm64_regs {
|
||||
@ -177,9 +178,10 @@ struct arm64_regs {
|
||||
void afl_persistent_hook(struct arm64_regs *regs, uint64_t guest_base,
|
||||
uint8_t *input_buf, uint32_t input_buf_len) {
|
||||
|
||||
(void)guest_base; /* unused */
|
||||
(void)guest_base; /* unused */
|
||||
memcpy((void *)regs->x0, input_buf, input_buf_len);
|
||||
regs->x1 = input_buf_len;
|
||||
|
||||
}
|
||||
|
||||
#else
|
||||
@ -193,3 +195,4 @@ int afl_persistent_hook_init(void) {
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,6 +22,7 @@ extern guint64 instrument_fixed_seed;
|
||||
|
||||
extern uint8_t *__afl_area_ptr;
|
||||
extern uint32_t __afl_map_size;
|
||||
extern void __afl_coverage_interesting(uint8_t, uint32_t);
|
||||
|
||||
extern __thread guint64 *instrument_previous_pc_addr;
|
||||
|
||||
@ -72,5 +73,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output);
|
||||
void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data);
|
||||
void instrument_regs_format(int fd, char *format, ...);
|
||||
|
||||
void ijon_set(uint32_t edge);
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -39,18 +39,18 @@ static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
|
||||
|
||||
address = base + index + mem->disp;
|
||||
|
||||
if ((operand->access & CS_AC_READ) == CS_AC_READ) {
|
||||
|
||||
asan_loadN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) {
|
||||
|
||||
asan_storeN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
if ((operand->access & CS_AC_READ) == CS_AC_READ) {
|
||||
|
||||
asan_loadN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
|
||||
|
@ -449,3 +449,9 @@ void instrument_regs_format(int fd, char *format, ...) {
|
||||
|
||||
}
|
||||
|
||||
void ijon_set(uint32_t edge) {
|
||||
|
||||
__afl_coverage_interesting(1, edge);
|
||||
|
||||
}
|
||||
|
||||
|
@ -818,6 +818,9 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
|
||||
GDir *dir = g_dir_open(fds_name, 0, NULL);
|
||||
|
||||
gchar *path_tmp = getenv("AFL_CUSTOM_INFO_OUT");
|
||||
gchar *instance_name = g_path_get_basename(path_tmp);
|
||||
|
||||
FVERBOSE("Coverage Unstable - fds: %s", fds_name);
|
||||
|
||||
for (const gchar *filename = g_dir_read_name(dir); filename != NULL;
|
||||
@ -829,7 +832,7 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
if (link == NULL) { FFATAL("Failed to read link: %s", fullname); }
|
||||
|
||||
gchar *basename = g_path_get_basename(link);
|
||||
if (g_strcmp0(basename, "default") != 0) {
|
||||
if (g_strcmp0(basename, instance_name) != 0) {
|
||||
|
||||
g_free(basename);
|
||||
g_free(link);
|
||||
@ -874,6 +877,7 @@ void instrument_coverage_unstable_find_output(void) {
|
||||
}
|
||||
|
||||
g_dir_close(dir);
|
||||
g_free(instance_name);
|
||||
g_free(fds_name);
|
||||
|
||||
if (unstable_coverage_fuzzer_stats == NULL) {
|
||||
|
@ -326,6 +326,12 @@ class Afl {
|
||||
static jsApiGetSymbol(name) {
|
||||
return Afl.module.getExportByName(name);
|
||||
}
|
||||
|
||||
static IJON = class {
|
||||
static set(addr, val) {
|
||||
Afl.jsApiIjonSet((addr ^ val) & 0xffffffff);
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Field containing the `Module` object for `afl-frida-trace.so` (the FRIDA mode
|
||||
@ -377,3 +383,4 @@ Afl.jsApiSetVerbose = Afl.jsApiGetFunction("js_api_set_verbose", "void", []);
|
||||
Afl.jsApiWrite = new NativeFunction(
|
||||
/* tslint:disable-next-line:no-null-keyword */
|
||||
Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]);
|
||||
Afl.jsApiIjonSet = Afl.jsApiGetFunction("js_api_ijon_set", "void", ["uint32"]);
|
||||
|
@ -316,3 +316,9 @@ __attribute__((visibility("default"))) void js_api_set_verbose(void) {
|
||||
|
||||
}
|
||||
|
||||
__attribute__((visibility("default"))) void js_api_ijon_set(uint32_t edge) {
|
||||
|
||||
ijon_set(edge);
|
||||
|
||||
}
|
||||
|
||||
|
@ -33,7 +33,7 @@
|
||||
// r15 - pc
|
||||
|
||||
static GumCpuContext saved_regs = {0};
|
||||
static gpointer saved_lr = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -141,17 +141,10 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumArmWriter *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0);
|
||||
gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1,
|
||||
GUM_ARG_REGISTER, ARM_REG_R0);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -159,7 +152,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -203,7 +195,8 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
|
||||
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
|
||||
GUM_RED_ZONE_SIZE);
|
||||
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0);
|
||||
|
||||
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
|
||||
@ -214,65 +207,35 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumArmWriter *cw = output->writer.arm;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_arm_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_arm_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0);
|
||||
gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
|
||||
gum_arm_writer_put_bl_label(cw, original);
|
||||
|
||||
/* jmp loop */
|
||||
gum_arm_writer_put_b_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_arm_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_arm_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_lr(cw);
|
||||
|
||||
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
|
||||
|
||||
@ -284,7 +247,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
|
||||
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
|
||||
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
|
||||
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0);
|
||||
|
||||
|
@ -16,7 +16,7 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
static gpointer saved_lr = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -216,17 +216,10 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumArm64Writer *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
|
||||
gum_arm64_writer_put_call_address_with_arguments(
|
||||
cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -234,7 +227,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -284,7 +276,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
|
||||
GUM_INDEX_PRE_ADJUST);
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
|
||||
GUM_ADDRESS(&saved_lr));
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
|
||||
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0);
|
||||
|
||||
@ -297,65 +289,35 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumArm64Writer *cw = output->writer.arm64;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_arm64_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_arm64_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
|
||||
gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
|
||||
gum_arm64_writer_put_bl_label(cw, original);
|
||||
|
||||
/* jmp loop */
|
||||
gum_arm64_writer_put_b_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_arm64_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_arm64_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_lr(cw);
|
||||
|
||||
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
|
||||
|
||||
@ -368,7 +330,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
|
||||
GUM_ADDRESS(&saved_lr));
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
|
||||
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0);
|
||||
|
||||
|
@ -17,7 +17,7 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
static gpointer saved_ret = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -162,17 +162,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumX86Writer *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(_exit));
|
||||
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0);
|
||||
gum_x86_writer_put_call_reg(cw, GUM_X86_RAX);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -180,7 +173,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -190,7 +182,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
|
||||
-(GUM_RED_ZONE_SIZE));
|
||||
gum_x86_writer_put_call_address_with_arguments(
|
||||
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
|
||||
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX);
|
||||
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
|
||||
(GUM_RED_ZONE_SIZE));
|
||||
@ -235,7 +226,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_RAX);
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP,
|
||||
offset);
|
||||
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX);
|
||||
@ -252,70 +244,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumX86Writer *cw = output->writer.x86;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8);
|
||||
/*
|
||||
* If we haven't set persistent_ret, then assume that we are dealing with a
|
||||
* function and we should loop when that function returns.
|
||||
*/
|
||||
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_x86_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_x86_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
|
||||
gum_x86_writer_put_call_near_label(cw, original);
|
||||
|
||||
/* jmp loop */
|
||||
gum_x86_writer_put_jmp_near_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_x86_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_x86_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_ret(cw);
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
/* The original instrumented code is emitted here. */
|
||||
|
||||
}
|
||||
|
||||
void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
@ -331,7 +297,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8);
|
||||
gum_x86_writer_put_label(cw, zero);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
|
||||
|
||||
}
|
||||
|
@ -16,8 +16,7 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
|
||||
static gpointer saved_ret = NULL;
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -118,18 +117,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_exit(GumX86Writer *cw) {
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(_exit));
|
||||
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_EDI, 0);
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_EDI);
|
||||
gum_x86_writer_put_call_reg(cw, GUM_X86_EAX);
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
|
||||
|
||||
}
|
||||
|
||||
static int instrument_afl_persistent_loop_func(void) {
|
||||
|
||||
int ret = __afl_persistent_loop(persistent_count);
|
||||
if (instrument_previous_pc_addr == NULL) {
|
||||
|
||||
FATAL("instrument_previous_pc_addr uninitialized");
|
||||
@ -137,7 +128,6 @@ static int instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -145,7 +135,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
|
||||
|
||||
gum_x86_writer_put_call_address_with_arguments(
|
||||
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
|
||||
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX);
|
||||
|
||||
}
|
||||
|
||||
@ -179,7 +168,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_EAX);
|
||||
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
|
||||
GUM_ADDRESS(&persistent_ret));
|
||||
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP,
|
||||
offset);
|
||||
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX);
|
||||
@ -193,68 +183,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
|
||||
void persistent_prologue_arch(GumStalkerOutput *output) {
|
||||
|
||||
/*
|
||||
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
|
||||
* SAVE REGS
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* call hook (optionally)
|
||||
* CALL hook (optionally)
|
||||
* RESTORE REGS
|
||||
* call original
|
||||
* jmp loop:
|
||||
*
|
||||
* end:
|
||||
* JMP SAVED RET
|
||||
*
|
||||
* original:
|
||||
* INSTRUMENTED PERSISTENT FUNC
|
||||
*/
|
||||
|
||||
GumX86Writer *cw = output->writer.x86;
|
||||
|
||||
gconstpointer loop = cw->code + 1;
|
||||
|
||||
FVERBOSE("Persistent loop reached");
|
||||
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4);
|
||||
/*
|
||||
* If we haven't set persistent_ret, then assume that we are dealing with a
|
||||
* function and we should loop when that function returns.
|
||||
*/
|
||||
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* loop: */
|
||||
gum_x86_writer_put_label(cw, loop);
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_x86_writer_cur(cw);
|
||||
|
||||
/* call instrument_prologue_func */
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
instrument_afl_persistent_loop(cw);
|
||||
|
||||
/* jz done */
|
||||
gconstpointer done = cw->code + 1;
|
||||
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
|
||||
|
||||
/* Optionally call the persistent hook */
|
||||
persistent_prologue_hook(cw, &saved_regs);
|
||||
|
||||
/* Restore our CPU context before we continue execution */
|
||||
instrument_persitent_restore_regs(cw, &saved_regs);
|
||||
gconstpointer original = cw->code + 1;
|
||||
/* call original */
|
||||
gum_x86_writer_put_call_near_label(cw, original);
|
||||
/* jmp loop */
|
||||
gum_x86_writer_put_jmp_near_label(cw, loop);
|
||||
|
||||
/* done: */
|
||||
gum_x86_writer_put_label(cw, done);
|
||||
|
||||
instrument_exit(cw);
|
||||
|
||||
/* original: */
|
||||
gum_x86_writer_put_label(cw, original);
|
||||
|
||||
instrument_persitent_save_ret(cw);
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
/* The original instrumented code is emitted here. */
|
||||
|
||||
}
|
||||
|
||||
void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
@ -263,7 +229,12 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
|
||||
/* The stack should be aligned when we re-enter our loop */
|
||||
gum_x86_writer_put_and_reg_u32(cw, GUM_X86_ESP, 0xfffffff0);
|
||||
gum_x86_writer_put_sub_reg_imm(cw, GUM_X86_ESP, 0x4);
|
||||
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
|
||||
GUM_ADDRESS(&persistent_loop));
|
||||
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
|
||||
|
||||
}
|
||||
|
@ -110,7 +110,11 @@ gboolean util_verbose_enabled(void) {
|
||||
if (!initialized) {
|
||||
|
||||
initialized = TRUE;
|
||||
if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; }
|
||||
if (getenv("AFL_FRIDA_VERBOSE") || getenv("AFL_DEBUG")) {
|
||||
|
||||
util_verbose = TRUE;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
69
frida_mode/test/cache/cache.c
vendored
69
frida_mode/test/cache/cache.c
vendored
@ -6,46 +6,45 @@
|
||||
|
||||
void LLVMFuzzerTestOneInput(char *buf, int len);
|
||||
|
||||
__asm__ (
|
||||
"LLVMFuzzerTestOneInput:\n"
|
||||
".func LLVMFuzzerTestOneInput\n"
|
||||
".global LLVMFuzzerTestOneInput\n"
|
||||
" jmpq *jmp_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"call_target:\n"
|
||||
" ret\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"jmp_target:\n"
|
||||
" callq *call_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" leaq rax_offset(%rip), %rax\n"
|
||||
" jmp (%rax)\n"
|
||||
" nop\n"
|
||||
" ud2\n"
|
||||
" nop\n"
|
||||
"rax_target:\n"
|
||||
" ret\n"
|
||||
"\n"
|
||||
"\n"
|
||||
".global jmp_offset\n"
|
||||
".p2align 3\n"
|
||||
"jmp_offset:\n"
|
||||
" .quad jmp_target\n"
|
||||
"call_offset:\n"
|
||||
" .quad call_target\n"
|
||||
"rax_offset:\n"
|
||||
" .quad rax_target\n"
|
||||
);
|
||||
__asm__(
|
||||
"LLVMFuzzerTestOneInput:\n"
|
||||
".func LLVMFuzzerTestOneInput\n"
|
||||
".global LLVMFuzzerTestOneInput\n"
|
||||
" jmpq *jmp_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"call_target:\n"
|
||||
" ret\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
"jmp_target:\n"
|
||||
" callq *call_offset(%rip)\n"
|
||||
" nop\n"
|
||||
" nop\n"
|
||||
" leaq rax_offset(%rip), %rax\n"
|
||||
" jmp (%rax)\n"
|
||||
" nop\n"
|
||||
" ud2\n"
|
||||
" nop\n"
|
||||
"rax_target:\n"
|
||||
" ret\n"
|
||||
"\n"
|
||||
"\n"
|
||||
".global jmp_offset\n"
|
||||
".p2align 3\n"
|
||||
"jmp_offset:\n"
|
||||
" .quad jmp_target\n"
|
||||
"call_offset:\n"
|
||||
" .quad call_target\n"
|
||||
"rax_offset:\n"
|
||||
" .quad rax_target\n");
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -6,8 +6,8 @@
|
||||
|
||||
static bool cmov_test(char *x, char *y, size_t len) {
|
||||
|
||||
register char * __rdi __asm__("rdi") = x;
|
||||
register char * __rsi __asm__("rsi") = y;
|
||||
register char *__rdi __asm__("rdi") = x;
|
||||
register char *__rsi __asm__("rsi") = y;
|
||||
register size_t __rcx __asm__("rcx") = len;
|
||||
|
||||
register long __rax __asm__("rax");
|
||||
@ -49,10 +49,10 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -41,7 +41,7 @@ int run(char *file) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
@ -51,6 +51,7 @@ int run(char *file) {
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
||||
perror("open");
|
||||
break;
|
||||
|
||||
@ -110,8 +111,10 @@ void slow() {
|
||||
|
||||
}
|
||||
|
||||
TESTINSTR_SECTION int do_run(char * file) {
|
||||
TESTINSTR_SECTION int do_run(char *file) {
|
||||
|
||||
return run(file);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
@ -19,32 +19,40 @@
|
||||
typedef void (*fntestinstrlib)(char *buf, int len);
|
||||
|
||||
void testinstr(char *buf, int len) {
|
||||
|
||||
void *lib = dlopen("testinstrlib.so", RTLD_NOW);
|
||||
if (lib == NULL) {
|
||||
|
||||
puts("Library not found");
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
fntestinstrlib fn = (fntestinstrlib)(dlsym(lib, "testinstrlib"));
|
||||
if (fn == NULL) {
|
||||
|
||||
puts("Function not found");
|
||||
abort();
|
||||
|
||||
}
|
||||
|
||||
fn(buf, len);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
char * file;
|
||||
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
if (argc != 2) { return 1; }
|
||||
|
||||
do {
|
||||
|
||||
file = argv[1];
|
||||
printf("file: %s\n", file);
|
||||
|
||||
@ -52,33 +60,43 @@ int main(int argc, char **argv) {
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
||||
perror("open");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
len = lseek(fd, 0, SEEK_END);
|
||||
if (len < 0) {
|
||||
|
||||
perror("lseek (SEEK_END)");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
if (lseek(fd, 0, SEEK_SET) != 0) {
|
||||
|
||||
perror("lseek (SEEK_SET)");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
printf("len: %ld\n", len);
|
||||
|
||||
buf = malloc(len);
|
||||
if (buf == NULL) {
|
||||
|
||||
perror("malloc");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
n_read = read(fd, buf, len);
|
||||
if (n_read != len) {
|
||||
|
||||
perror("read");
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read);
|
||||
@ -95,4 +113,6 @@ int main(int argc, char **argv) {
|
||||
if (fd != -1) { close(fd); }
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void testinstrlib(char *buf, int len) {
|
||||
|
||||
if (len < 1) return;
|
||||
buf[len] = 0;
|
||||
|
||||
@ -11,4 +12,6 @@ void testinstrlib(char *buf, int len) {
|
||||
printf("Pretty sure that is a one!\n");
|
||||
else
|
||||
printf("Neither one or zero? How quaint!\n");
|
||||
|
||||
}
|
||||
|
||||
|
@ -41,7 +41,7 @@ int run(char *file) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
|
||||
|
||||
TESTINSTR_SECTION int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -35,7 +35,7 @@ int run(char *file) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -22,60 +22,60 @@
|
||||
#define IGNORED_RETURN(x) (void)!(x)
|
||||
|
||||
const uint32_t crc32_tab[] = {
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d
|
||||
};
|
||||
|
||||
uint32_t
|
||||
crc32(const void *buf, size_t size)
|
||||
{
|
||||
const uint8_t *p = buf;
|
||||
uint32_t crc;
|
||||
crc = ~0U;
|
||||
while (size--)
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
return crc ^ ~0U;
|
||||
0x00000000, 0x77073096, 0xee0e612c, 0x990951ba, 0x076dc419, 0x706af48f,
|
||||
0xe963a535, 0x9e6495a3, 0x0edb8832, 0x79dcb8a4, 0xe0d5e91e, 0x97d2d988,
|
||||
0x09b64c2b, 0x7eb17cbd, 0xe7b82d07, 0x90bf1d91, 0x1db71064, 0x6ab020f2,
|
||||
0xf3b97148, 0x84be41de, 0x1adad47d, 0x6ddde4eb, 0xf4d4b551, 0x83d385c7,
|
||||
0x136c9856, 0x646ba8c0, 0xfd62f97a, 0x8a65c9ec, 0x14015c4f, 0x63066cd9,
|
||||
0xfa0f3d63, 0x8d080df5, 0x3b6e20c8, 0x4c69105e, 0xd56041e4, 0xa2677172,
|
||||
0x3c03e4d1, 0x4b04d447, 0xd20d85fd, 0xa50ab56b, 0x35b5a8fa, 0x42b2986c,
|
||||
0xdbbbc9d6, 0xacbcf940, 0x32d86ce3, 0x45df5c75, 0xdcd60dcf, 0xabd13d59,
|
||||
0x26d930ac, 0x51de003a, 0xc8d75180, 0xbfd06116, 0x21b4f4b5, 0x56b3c423,
|
||||
0xcfba9599, 0xb8bda50f, 0x2802b89e, 0x5f058808, 0xc60cd9b2, 0xb10be924,
|
||||
0x2f6f7c87, 0x58684c11, 0xc1611dab, 0xb6662d3d, 0x76dc4190, 0x01db7106,
|
||||
0x98d220bc, 0xefd5102a, 0x71b18589, 0x06b6b51f, 0x9fbfe4a5, 0xe8b8d433,
|
||||
0x7807c9a2, 0x0f00f934, 0x9609a88e, 0xe10e9818, 0x7f6a0dbb, 0x086d3d2d,
|
||||
0x91646c97, 0xe6635c01, 0x6b6b51f4, 0x1c6c6162, 0x856530d8, 0xf262004e,
|
||||
0x6c0695ed, 0x1b01a57b, 0x8208f4c1, 0xf50fc457, 0x65b0d9c6, 0x12b7e950,
|
||||
0x8bbeb8ea, 0xfcb9887c, 0x62dd1ddf, 0x15da2d49, 0x8cd37cf3, 0xfbd44c65,
|
||||
0x4db26158, 0x3ab551ce, 0xa3bc0074, 0xd4bb30e2, 0x4adfa541, 0x3dd895d7,
|
||||
0xa4d1c46d, 0xd3d6f4fb, 0x4369e96a, 0x346ed9fc, 0xad678846, 0xda60b8d0,
|
||||
0x44042d73, 0x33031de5, 0xaa0a4c5f, 0xdd0d7cc9, 0x5005713c, 0x270241aa,
|
||||
0xbe0b1010, 0xc90c2086, 0x5768b525, 0x206f85b3, 0xb966d409, 0xce61e49f,
|
||||
0x5edef90e, 0x29d9c998, 0xb0d09822, 0xc7d7a8b4, 0x59b33d17, 0x2eb40d81,
|
||||
0xb7bd5c3b, 0xc0ba6cad, 0xedb88320, 0x9abfb3b6, 0x03b6e20c, 0x74b1d29a,
|
||||
0xead54739, 0x9dd277af, 0x04db2615, 0x73dc1683, 0xe3630b12, 0x94643b84,
|
||||
0x0d6d6a3e, 0x7a6a5aa8, 0xe40ecf0b, 0x9309ff9d, 0x0a00ae27, 0x7d079eb1,
|
||||
0xf00f9344, 0x8708a3d2, 0x1e01f268, 0x6906c2fe, 0xf762575d, 0x806567cb,
|
||||
0x196c3671, 0x6e6b06e7, 0xfed41b76, 0x89d32be0, 0x10da7a5a, 0x67dd4acc,
|
||||
0xf9b9df6f, 0x8ebeeff9, 0x17b7be43, 0x60b08ed5, 0xd6d6a3e8, 0xa1d1937e,
|
||||
0x38d8c2c4, 0x4fdff252, 0xd1bb67f1, 0xa6bc5767, 0x3fb506dd, 0x48b2364b,
|
||||
0xd80d2bda, 0xaf0a1b4c, 0x36034af6, 0x41047a60, 0xdf60efc3, 0xa867df55,
|
||||
0x316e8eef, 0x4669be79, 0xcb61b38c, 0xbc66831a, 0x256fd2a0, 0x5268e236,
|
||||
0xcc0c7795, 0xbb0b4703, 0x220216b9, 0x5505262f, 0xc5ba3bbe, 0xb2bd0b28,
|
||||
0x2bb45a92, 0x5cb36a04, 0xc2d7ffa7, 0xb5d0cf31, 0x2cd99e8b, 0x5bdeae1d,
|
||||
0x9b64c2b0, 0xec63f226, 0x756aa39c, 0x026d930a, 0x9c0906a9, 0xeb0e363f,
|
||||
0x72076785, 0x05005713, 0x95bf4a82, 0xe2b87a14, 0x7bb12bae, 0x0cb61b38,
|
||||
0x92d28e9b, 0xe5d5be0d, 0x7cdcefb7, 0x0bdbdf21, 0x86d3d2d4, 0xf1d4e242,
|
||||
0x68ddb3f8, 0x1fda836e, 0x81be16cd, 0xf6b9265b, 0x6fb077e1, 0x18b74777,
|
||||
0x88085ae6, 0xff0f6a70, 0x66063bca, 0x11010b5c, 0x8f659eff, 0xf862ae69,
|
||||
0x616bffd3, 0x166ccf45, 0xa00ae278, 0xd70dd2ee, 0x4e048354, 0x3903b3c2,
|
||||
0xa7672661, 0xd06016f7, 0x4969474d, 0x3e6e77db, 0xaed16a4a, 0xd9d65adc,
|
||||
0x40df0b66, 0x37d83bf0, 0xa9bcae53, 0xdebb9ec5, 0x47b2cf7f, 0x30b5ffe9,
|
||||
0xbdbdf21c, 0xcabac28a, 0x53b39330, 0x24b4a3a6, 0xbad03605, 0xcdd70693,
|
||||
0x54de5729, 0x23d967bf, 0xb3667a2e, 0xc4614ab8, 0x5d681b02, 0x2a6f2b94,
|
||||
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d};
|
||||
|
||||
uint32_t crc32(const void *buf, size_t size) {
|
||||
|
||||
const uint8_t *p = buf;
|
||||
uint32_t crc;
|
||||
crc = ~0U;
|
||||
while (size--)
|
||||
crc = crc32_tab[(crc ^ *p++) & 0xFF] ^ (crc >> 8);
|
||||
return crc ^ ~0U;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -83,11 +83,13 @@ crc32(const void *buf, size_t size)
|
||||
* FRIDA to patch this function out and always return success. Otherwise, we
|
||||
* could change it to actually correct the checksum.
|
||||
*/
|
||||
int crc32_check (char * buf, int len) {
|
||||
int crc32_check(char *buf, int len) {
|
||||
|
||||
if (len < sizeof(uint32_t)) { return 0; }
|
||||
uint32_t expected = *(uint32_t *)&buf[len - sizeof(uint32_t)];
|
||||
uint32_t calculated = crc32(buf, len - sizeof(uint32_t));
|
||||
return expected == calculated;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -97,27 +99,31 @@ int crc32_check (char * buf, int len) {
|
||||
* cloud your output unnecessarily. Again, we can use FRIDA to patch it out.
|
||||
*/
|
||||
void some_boring_bug(char c) {
|
||||
|
||||
switch (c) {
|
||||
case 'A'...'Z':
|
||||
case 'a'...'z':
|
||||
|
||||
case 'A' ... 'Z':
|
||||
case 'a' ... 'z':
|
||||
__builtin_trap();
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
extern void some_boring_bug2(char c);
|
||||
|
||||
__asm__ (
|
||||
".text \n"
|
||||
"some_boring_bug2: \n"
|
||||
".global some_boring_bug2 \n"
|
||||
".type some_boring_bug2, @function \n"
|
||||
"mov %edi, %eax \n"
|
||||
"cmp $0xb4, %al \n"
|
||||
"jne ok \n"
|
||||
"ud2 \n"
|
||||
"ok: \n"
|
||||
"ret \n");
|
||||
__asm__(
|
||||
".text \n"
|
||||
"some_boring_bug2: \n"
|
||||
".global some_boring_bug2 \n"
|
||||
".type some_boring_bug2, @function \n"
|
||||
"mov %edi, %eax \n"
|
||||
"cmp $0xb4, %al \n"
|
||||
"jne ok \n"
|
||||
"ud2 \n"
|
||||
"ok: \n"
|
||||
"ret \n");
|
||||
|
||||
void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
@ -127,16 +133,20 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
some_boring_bug2(buf[0]);
|
||||
|
||||
if (buf[0] == '0') {
|
||||
|
||||
printf("Looks like a zero to me!\n");
|
||||
}
|
||||
else if (buf[0] == '1') {
|
||||
|
||||
} else if (buf[0] == '1') {
|
||||
|
||||
printf("Pretty sure that is a one!\n");
|
||||
}
|
||||
else if (buf[0] == '2') {
|
||||
|
||||
} else if (buf[0] == '2') {
|
||||
|
||||
printf("Oh we, weren't expecting that!");
|
||||
__builtin_trap();
|
||||
}
|
||||
else
|
||||
|
||||
} else
|
||||
|
||||
printf("Neither one or zero? How quaint!\n");
|
||||
|
||||
}
|
||||
@ -145,7 +155,7 @@ int main(int argc, char **argv) {
|
||||
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
@ -173,5 +183,6 @@ int main(int argc, char **argv) {
|
||||
printf("Done: %s: (%zd bytes)\n", argv[1], n_read);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,66 +4,68 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
//typedef for our exported target function.
|
||||
// typedef for our exported target function.
|
||||
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
|
||||
|
||||
//globals
|
||||
// globals
|
||||
CRASHME fpn_crashme = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
|
||||
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
}
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor()))
|
||||
void constructor(void) {
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
__attribute__((constructor())) void constructor(void) {
|
||||
|
||||
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
|
||||
if (dylib == NULL)
|
||||
{
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
|
||||
if (dylib == NULL) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
|
||||
printf("[+] Resolve function\n");
|
||||
}
|
||||
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme)
|
||||
{
|
||||
printf("[+] Resolve function\n");
|
||||
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
|
@ -4,66 +4,68 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
//typedef for our exported target function.
|
||||
// typedef for our exported target function.
|
||||
typedef void (*CRASHME)(const uint8_t *Data, size_t Size);
|
||||
|
||||
//globals
|
||||
// globals
|
||||
CRASHME fpn_crashme = NULL;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
|
||||
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
|
||||
fpn_crashme(data, size);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
}
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
__attribute__((constructor()))
|
||||
void constructor(void) {
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
__attribute__((constructor())) void constructor(void) {
|
||||
|
||||
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
|
||||
if (dylib == NULL)
|
||||
{
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
|
||||
if (dylib == NULL) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
|
||||
printf("[+] Resolve function\n");
|
||||
}
|
||||
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme)
|
||||
{
|
||||
printf("[+] Resolve function\n");
|
||||
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme) {
|
||||
|
||||
}
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
|
@ -4,37 +4,42 @@
|
||||
#include <stdlib.h>
|
||||
#include <dlfcn.h>
|
||||
|
||||
|
||||
extern void crashme(const uint8_t *Data, size_t Size);
|
||||
|
||||
int LLVMFuzzerTestOneInput(const unsigned char* data, size_t size){
|
||||
crashme(data, size);
|
||||
return 0;
|
||||
int LLVMFuzzerTestOneInput(const unsigned char *data, size_t size) {
|
||||
|
||||
crashme(data, size);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
void run (int argc, const char * argv[])
|
||||
{
|
||||
for (int i = 1; i < argc; i++) {
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
}
|
||||
void run(int argc, const char *argv[]) {
|
||||
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", argv[i]);
|
||||
FILE *f = fopen(argv[i], "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", argv[i], n_read);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, const char * argv[])
|
||||
{
|
||||
int main(int argc, const char *argv[]) {
|
||||
|
||||
run(argc, argv);
|
||||
run(argc, argv);
|
||||
|
||||
return 0;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,7 +2,6 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (Size < 5) return;
|
||||
@ -13,5 +12,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
if (Data[3] == '$')
|
||||
if (Data[4] == '$') abort();
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -3,7 +3,6 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (Size < 1) return;
|
||||
@ -56,6 +55,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
|
||||
|
||||
TESTINSTR_SECTION int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -20,22 +20,32 @@ void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
int ret = 0;
|
||||
for (int i = 0; i < 1000; i++) {
|
||||
switch(buf[i]) {
|
||||
case 'A': ret += 2; break;
|
||||
case '1': ret += 3; break;
|
||||
default: ret++;
|
||||
|
||||
switch (buf[i]) {
|
||||
|
||||
case 'A':
|
||||
ret += 2;
|
||||
break;
|
||||
case '1':
|
||||
ret += 3;
|
||||
break;
|
||||
default:
|
||||
ret++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
printf("ret: %d\n", ret);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
void LLVMFuzzerTestOneInput(char *buf, int len) {
|
||||
|
||||
printf (">>> LLVMFuzzerTestOneInput >>>\n");
|
||||
printf(">>> LLVMFuzzerTestOneInput >>>\n");
|
||||
if (len < 1) return;
|
||||
buf[len] = 0;
|
||||
|
||||
@ -40,10 +40,10 @@ void slow() {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -48,7 +48,7 @@ all: $(TEST_BIN)
|
||||
CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN)
|
||||
|
||||
arm:
|
||||
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN)
|
||||
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" PNG_ARCH="arm" make $(TEST_BIN)
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR)
|
||||
cd $(LIBZ_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -fPIC" \
|
||||
./configure \
|
||||
--static \
|
||||
--archs="$(ARCH)"
|
||||
--static
|
||||
|
||||
$(LIBZ_LIB): | $(LIBZ_PC)
|
||||
CFLAGS="$(CFLAGS) -fPIC" \
|
||||
@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
|
||||
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
|
||||
LDFLAGS="-L$(LIBZ_DIR)" \
|
||||
./configure \
|
||||
--host="$(ARCH)"
|
||||
--host="$(PNG_ARCH)"
|
||||
|
||||
$(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
|
||||
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
|
||||
|
@ -39,10 +39,10 @@ void testinstr(char *buf, int len) {
|
||||
|
||||
TESTINSTR_SECTION int main(int argc, char **argv) {
|
||||
|
||||
char * file;
|
||||
char *file;
|
||||
int fd = -1;
|
||||
off_t len;
|
||||
char * buf = NULL;
|
||||
char *buf = NULL;
|
||||
size_t n_read;
|
||||
int result = -1;
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#define TESTINSTR_SECTION __attribute__((section(".testinstr")))
|
||||
#endif
|
||||
|
||||
void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
void LLVMFuzzerTestOneInput(const uint8_t *data, size_t size) {
|
||||
|
||||
if (size < 1) return;
|
||||
|
||||
@ -30,9 +30,13 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
if (gettimeofday(&tv, NULL) < 0) return;
|
||||
|
||||
if ((tv.tv_usec % 2) == 0) {
|
||||
printf ("Hooray all even\n");
|
||||
|
||||
printf("Hooray all even\n");
|
||||
|
||||
} else {
|
||||
printf ("Hmm that's odd\n");
|
||||
|
||||
printf("Hmm that's odd\n");
|
||||
|
||||
}
|
||||
|
||||
// we support three input cases
|
||||
@ -45,26 +49,33 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) {
|
||||
|
||||
}
|
||||
|
||||
void run_test(char * file) {
|
||||
void run_test(char *file) {
|
||||
|
||||
fprintf(stderr, "Running: %s\n", file);
|
||||
FILE *f = fopen(file, "r");
|
||||
assert(f);
|
||||
fseek(f, 0, SEEK_END);
|
||||
size_t len = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
unsigned char *buf = (unsigned char*)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
unsigned char *buf = (unsigned char *)malloc(len);
|
||||
size_t n_read = fread(buf, 1, len, f);
|
||||
fclose(f);
|
||||
assert(n_read == len);
|
||||
LLVMFuzzerTestOneInput(buf, len);
|
||||
free(buf);
|
||||
fprintf(stderr, "Done: %s: (%zd bytes)\n", file, n_read);
|
||||
|
||||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
|
||||
srand(1);
|
||||
fprintf(stderr, "StandaloneFuzzTargetMain: running %d inputs\n", argc - 1);
|
||||
for (int i = 1; i < argc; i++) {
|
||||
|
||||
run_test(argv[i]);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
@ -42,6 +42,7 @@
|
||||
#include "debug.h"
|
||||
#include "alloc-inl.h"
|
||||
#include "hash.h"
|
||||
#include "valueprofile.h"
|
||||
#include "sharedmem.h"
|
||||
#include "forkserver.h"
|
||||
#include "common.h"
|
||||
@ -116,6 +117,10 @@
|
||||
#include <TargetConditionals.h>
|
||||
#endif
|
||||
|
||||
#ifndef __has_builtin
|
||||
#define __has_builtin(x) 0
|
||||
#endif
|
||||
|
||||
#undef LIST_FOREACH /* clashes with FreeBSD */
|
||||
#include "list.h"
|
||||
#ifndef SIMPLE_FILES
|
||||
@ -206,7 +211,8 @@ struct queue_entry {
|
||||
u32 id; /* entry number in queue_buf */
|
||||
|
||||
u8 colorized, /* Do not run redqueen stage again */
|
||||
cal_failed; /* Calibration failed? */
|
||||
cal_failed, /* Calibration failed? */
|
||||
really_interesting; /* really has coverage (VP) */
|
||||
|
||||
bool trim_done, /* Trimmed? */
|
||||
was_fuzzed, /* historical, but needed for MOpt */
|
||||
@ -236,7 +242,6 @@ struct queue_entry {
|
||||
custom, /* Marker for custom mutators */
|
||||
stats_mutated; /* stats: # of mutations performed */
|
||||
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u32 tc_ref; /* Trace bytes ref count */
|
||||
|
||||
#ifdef INTROSPECTION
|
||||
@ -246,13 +251,11 @@ struct queue_entry {
|
||||
double perf_score, /* performance score */
|
||||
weight;
|
||||
|
||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||
|
||||
u8 *cmplog_colorinput; /* the result buf of colorization */
|
||||
struct tainted *taint; /* Taint information from CmpLog */
|
||||
|
||||
struct queue_entry *mother; /* queue entry this based on */
|
||||
|
||||
struct queue_entry *mother; /* queue entry this based on */
|
||||
u8 *trace_mini; /* Trace bytes, if kept */
|
||||
u8 *testcase_buf; /* The testcase buffer, if loaded. */
|
||||
u8 *cmplog_colorinput; /* the result buf of colorization */
|
||||
struct tainted *taint; /* Taint information from CmpLog */
|
||||
struct skipdet_entry *skipdet_e;
|
||||
|
||||
};
|
||||
@ -448,8 +451,9 @@ extern char *power_names[POWER_SCHEDULES_NUM];
|
||||
typedef struct afl_env_vars {
|
||||
|
||||
u8 afl_skip_cpufreq, afl_exit_when_done, afl_no_affinity, afl_skip_bin_check,
|
||||
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only, afl_no_ui,
|
||||
afl_force_ui, afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
|
||||
afl_dumb_forksrv, afl_import_first, afl_custom_mutator_only,
|
||||
afl_custom_mutator_late_send, afl_no_ui, afl_force_ui,
|
||||
afl_i_dont_care_about_missing_crashes, afl_bench_just_one,
|
||||
afl_bench_until_crash, afl_debug_child, afl_autoresume, afl_cal_fast,
|
||||
afl_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
|
||||
afl_exit_on_seed_issues, afl_try_affinity, afl_ignore_problems,
|
||||
@ -457,7 +461,7 @@ typedef struct afl_env_vars {
|
||||
afl_no_startup_calibration, afl_no_warn_instability,
|
||||
afl_post_process_keep_original, afl_crashing_seeds_as_new_crash,
|
||||
afl_final_sync, afl_ignore_seed_problems, afl_disable_redundant,
|
||||
afl_sha1_filenames, afl_no_sync;
|
||||
afl_sha1_filenames, afl_no_sync, afl_no_fastresume;
|
||||
|
||||
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
|
||||
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
|
||||
@ -853,6 +857,8 @@ typedef struct afl_state {
|
||||
u32 bitsmap_size;
|
||||
#endif
|
||||
|
||||
u32 vp_ptr[VP_MAP_SIZE];
|
||||
|
||||
} afl_state_t;
|
||||
|
||||
struct custom_mutator {
|
||||
@ -1191,7 +1197,7 @@ void discover_word(u8 *ret, u32 *current, u32 *virgin);
|
||||
void init_count_class16(void);
|
||||
void minimize_bits(afl_state_t *, u8 *, u8 *);
|
||||
#ifndef SIMPLE_FILES
|
||||
u8 *describe_op(afl_state_t *, u8, size_t);
|
||||
u8 *describe_op(afl_state_t *, u8, size_t, u8);
|
||||
#endif
|
||||
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
||||
u8 has_new_bits(afl_state_t *, u8 *);
|
||||
|
@ -53,21 +53,24 @@ struct cmp_header { // 16 bit = 2 bytes
|
||||
struct cmp_operands {
|
||||
|
||||
u64 v0;
|
||||
u64 v1;
|
||||
u64 v0_128;
|
||||
u64 v0_256_0; // u256 is unsupported by any compiler for now, so future use
|
||||
u64 v0_256_1;
|
||||
u64 v1;
|
||||
u64 v1_128;
|
||||
u64 unused;
|
||||
u8 unused1;
|
||||
u8 unused2;
|
||||
u64 v1_256_0;
|
||||
u64 v1_256_1;
|
||||
u8 unused[8];
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cmpfn_operands {
|
||||
|
||||
u8 v0[32];
|
||||
u8 v0_len;
|
||||
u8 v1[32];
|
||||
u8 v0_len;
|
||||
u8 v1_len;
|
||||
u8 unused[6];
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
|
@ -26,7 +26,7 @@
|
||||
/* Version string: */
|
||||
|
||||
// c = release, a = volatile github dev, e = experimental branch
|
||||
#define VERSION "++4.21c"
|
||||
#define VERSION "++4.22a"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
|
@ -314,8 +314,8 @@ static inline const char *colorfilter(const char *x) {
|
||||
#define FATAL(x...) \
|
||||
do { \
|
||||
\
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(cLRD "\n Location : " cRST "%s(), %s:%u\n\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
exit(1); \
|
||||
@ -327,8 +327,8 @@ static inline const char *colorfilter(const char *x) {
|
||||
#define ABORT(x...) \
|
||||
do { \
|
||||
\
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] PROGRAM ABORT : " cRST x); \
|
||||
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
abort(); \
|
||||
@ -341,8 +341,8 @@ static inline const char *colorfilter(const char *x) {
|
||||
do { \
|
||||
\
|
||||
fflush(stdout); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] SYSTEM ERROR : " cRST x); \
|
||||
SAYF(bSTOP RESET_G1 CURSOR_SHOW cRST cLRD \
|
||||
"\n[-] SYSTEM ERROR : " cRST x); \
|
||||
SAYF(cLRD "\n Stop location : " cRST "%s(), %s:%u\n", __func__, \
|
||||
__FILE__, (u32)__LINE__); \
|
||||
SAYF(cLRD " OS message : " cRST "%s\n", strerror(errno)); \
|
||||
|
@ -24,23 +24,23 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_DUMP_CYCLOMATIC_COMPLEXITY", "AFL_CMPLOG_MAX_LEN", "AFL_COMPCOV_LEVEL",
|
||||
"AFL_CRASH_EXITCODE", "AFL_CRASHING_SEEDS_AS_NEW_CRASH",
|
||||
"AFL_CUSTOM_MUTATOR_LIBRARY", "AFL_CUSTOM_MUTATOR_ONLY",
|
||||
"AFL_CUSTOM_INFO_PROGRAM", "AFL_CUSTOM_INFO_PROGRAM_ARGV",
|
||||
"AFL_CUSTOM_INFO_PROGRAM_INPUT", "AFL_CUSTOM_INFO_OUT", "AFL_CXX",
|
||||
"AFL_CYCLE_SCHEDULES", "AFL_DEBUG", "AFL_DEBUG_CHILD", "AFL_DEBUG_GDB",
|
||||
"AFL_DEBUG_UNICORN", "AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT",
|
||||
"AFL_DISABLE_TRIM", "AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION",
|
||||
"AFL_DONT_OPTIMIZE", "AFL_DRIVER_STDERR_DUPLICATE_FILENAME",
|
||||
"AFL_DUMB_FORKSRV", "AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT",
|
||||
"AFL_EXIT_WHEN_DONE", "AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES",
|
||||
"AFL_FAST_CAL", "AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
|
||||
"AFL_CUSTOM_MUTATOR_LATE_SEND", "AFL_CUSTOM_INFO_PROGRAM",
|
||||
"AFL_CUSTOM_INFO_PROGRAM_ARGV", "AFL_CUSTOM_INFO_PROGRAM_INPUT",
|
||||
"AFL_CUSTOM_INFO_OUT", "AFL_CXX", "AFL_CYCLE_SCHEDULES", "AFL_DEBUG",
|
||||
"AFL_DEBUG_CHILD", "AFL_DEBUG_GDB", "AFL_DEBUG_UNICORN",
|
||||
"AFL_DISABLE_REDUNDANT", "AFL_NO_REDUNDANT", "AFL_DISABLE_TRIM",
|
||||
"AFL_NO_TRIM", "AFL_DISABLE_LLVM_INSTRUMENTATION", "AFL_DONT_OPTIMIZE",
|
||||
"AFL_DRIVER_STDERR_DUPLICATE_FILENAME", "AFL_DUMB_FORKSRV",
|
||||
"AFL_EARLY_FORKSERVER", "AFL_ENTRYPOINT", "AFL_EXIT_WHEN_DONE",
|
||||
"AFL_EXIT_ON_TIME", "AFL_EXIT_ON_SEED_ISSUES", "AFL_FAST_CAL",
|
||||
"AFL_FINAL_SYNC", "AFL_FORCE_UI", "AFL_FRIDA_DEBUG_MAPS",
|
||||
"AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES",
|
||||
"AFL_FRIDA_INST_CACHE_SIZE", "AFL_FRIDA_INST_COVERAGE_ABSOLUTE",
|
||||
"AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE",
|
||||
"AFL_FRIDA_INST_INSN", "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_CACHE",
|
||||
"AFL_FRIDA_INST_NO_DYNAMIC_LOAD", "AFL_FRIDA_INST_NO_OPTIMIZE",
|
||||
"AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_NO_PREFETCH_BACKPATCH",
|
||||
"AFL_FRIDA_INST_NO_SUPPRESS"
|
||||
"AFL_FRIDA_INST_RANGES",
|
||||
"AFL_FRIDA_INST_NO_SUPPRESS", "AFL_FRIDA_INST_RANGES",
|
||||
"AFL_FRIDA_INST_REGS_FILE", "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE",
|
||||
"AFL_FRIDA_INST_TRACE_UNIQUE", "AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE",
|
||||
"AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR",
|
||||
@ -49,7 +49,7 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_FRIDA_PERSISTENT_RET", "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
|
||||
"AFL_FRIDA_STALKER_IC_ENTRIES", "AFL_FRIDA_STALKER_NO_BACKPATCH",
|
||||
"AFL_FRIDA_STATS_FILE", "AFL_FRIDA_STATS_INTERVAL", "AFL_FRIDA_TRACEABLE",
|
||||
"AFL_FRIDA_VERBOSE",
|
||||
"AFL_FRIDA_VERBOSE", "AFL_OLD_FORKSERVER",
|
||||
"AFL_FUZZER_ARGS", // oss-fuzz
|
||||
"AFL_FUZZER_STATS_UPDATE_INTERVAL", "AFL_GDB", "AFL_GCC_ALLOWLIST",
|
||||
"AFL_GCC_DENYLIST", "AFL_GCC_BLOCKLIST", "AFL_GCC_INSTRUMENT_FILE",
|
||||
@ -64,7 +64,8 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_LD_LIMIT_MB", "AFL_LD_NO_CALLOC_OVER", "AFL_LD_PASSTHROUGH",
|
||||
"AFL_REAL_LD", "AFL_LD_PRELOAD", "AFL_LD_VERBOSE", "AFL_LLVM_ALLOWLIST",
|
||||
"AFL_LLVM_DENYLIST", "AFL_LLVM_BLOCKLIST", "AFL_CMPLOG", "AFL_LLVM_CMPLOG",
|
||||
"AFL_GCC_CMPLOG", "AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
||||
"AFL_LLVM_VALUEPROFILE", "AFL_LLVM_VALUE_PROFILE", "AFL_GCC_CMPLOG",
|
||||
"AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
||||
"AFL_LLVM_LTO_CALLER", "AFL_LLVM_LTO_CTX", "AFL_LLVM_LTO_CALLER_DEPTH",
|
||||
"AFL_LLVM_LTO_CTX_DEPTH", "AFL_LLVM_CALLER_DEPTH", "AFL_LLVM_CTX_DEPTH",
|
||||
"AFL_LLVM_CTX_K", "AFL_LLVM_DICT2FILE", "AFL_LLVM_DICT2FILE_NO_MAIN",
|
||||
@ -115,7 +116,8 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_TRACE_PC", "AFL_USE_ASAN", "AFL_USE_MSAN", "AFL_USE_TRACE_PC",
|
||||
"AFL_USE_UBSAN", "AFL_USE_TSAN", "AFL_USE_CFISAN", "AFL_USE_LSAN",
|
||||
"AFL_WINE_PATH", "AFL_NO_SNAPSHOT", "AFL_EXPAND_HAVOC_NOW", "AFL_USE_FASAN",
|
||||
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
||||
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE",
|
||||
"AFL_NO_FASTRESUME", NULL
|
||||
|
||||
};
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "valueprofile.h"
|
||||
|
||||
#ifdef __linux__
|
||||
/**
|
||||
@ -89,11 +90,14 @@ typedef struct {
|
||||
bool (*nyx_config_set_aux_buffer_size)(void *config,
|
||||
uint32_t aux_buffer_size);
|
||||
|
||||
uint64_t (*nyx_get_target_hash64)(void *config);
|
||||
|
||||
void (*nyx_config_free)(void *config);
|
||||
|
||||
} nyx_plugin_handler_t;
|
||||
|
||||
/* Imports helper functions to enable Nyx mode (Linux only )*/
|
||||
nyx_plugin_handler_t *afl_load_libnyx_plugin(u8 *libnyx_binary);
|
||||
|
||||
#endif
|
||||
|
||||
typedef struct afl_forkserver {
|
||||
@ -179,7 +183,8 @@ typedef struct afl_forkserver {
|
||||
/* Function to kick off the forkserver child */
|
||||
void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
|
||||
|
||||
u8 *afl_ptr; /* for autodictionary: afl ptr */
|
||||
u8 *afl_ptr; /* for autodictionary: afl ptr */
|
||||
u32 *vp_map_control;
|
||||
|
||||
void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
|
||||
|
||||
@ -204,8 +209,18 @@ typedef struct afl_forkserver {
|
||||
bool nyx_use_tmp_workdir;
|
||||
char *nyx_tmp_workdir_path;
|
||||
s32 nyx_log_fd;
|
||||
u64 nyx_target_hash64;
|
||||
#endif
|
||||
|
||||
#ifdef __AFL_CODE_COVERAGE
|
||||
u8 *persistent_trace_bits; /* Persistent copy of bitmap */
|
||||
#endif
|
||||
|
||||
void *custom_data_ptr;
|
||||
u8 *custom_input;
|
||||
u32 custom_input_len;
|
||||
void (*late_send)(void *, const u8 *, size_t);
|
||||
|
||||
} afl_forkserver_t;
|
||||
|
||||
typedef enum fsrv_run_result {
|
||||
@ -232,6 +247,10 @@ void afl_fsrv_killall(void);
|
||||
void afl_fsrv_deinit(afl_forkserver_t *fsrv);
|
||||
void afl_fsrv_kill(afl_forkserver_t *fsrv);
|
||||
|
||||
#ifdef __linux__
|
||||
void nyx_load_target_hash(afl_forkserver_t *fsrv);
|
||||
#endif
|
||||
|
||||
#ifdef __APPLE__
|
||||
#define MSG_FORK_ON_APPLE \
|
||||
" - On MacOS X, the semantics of fork() syscalls are non-standard and " \
|
||||
|
@ -52,7 +52,9 @@ typedef struct sharedmem {
|
||||
|
||||
int cmplog_mode;
|
||||
int shmemfuzz_mode;
|
||||
int vp_mode;
|
||||
struct cmp_map *cmp_map;
|
||||
struct vp_map *vp_map;
|
||||
|
||||
} sharedmem_t;
|
||||
|
||||
|
@ -455,9 +455,10 @@ typedef struct {
|
||||
|
||||
} __attribute__((__packed__)) t1ha_unaligned_proxy;
|
||||
|
||||
#define read_unaligned(ptr, bits) \
|
||||
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \
|
||||
t1ha_unaligned_proxy, unaligned_##bits))) \
|
||||
#define read_unaligned(ptr, bits) \
|
||||
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr) - \
|
||||
offsetof(t1ha_unaligned_proxy, \
|
||||
unaligned_##bits))) \
|
||||
->unaligned_##bits)
|
||||
#elif defined(_MSC_VER)
|
||||
#pragma warning( \
|
||||
@ -477,9 +478,10 @@ typedef struct {
|
||||
} t1ha_unaligned_proxy;
|
||||
|
||||
#pragma pack(pop)
|
||||
#define read_unaligned(ptr, bits) \
|
||||
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr)-offsetof( \
|
||||
t1ha_unaligned_proxy, unaligned_##bits))) \
|
||||
#define read_unaligned(ptr, bits) \
|
||||
(((const t1ha_unaligned_proxy *)((const uint8_t *)(ptr) - \
|
||||
offsetof(t1ha_unaligned_proxy, \
|
||||
unaligned_##bits))) \
|
||||
->unaligned_##bits)
|
||||
#endif
|
||||
#endif /* read_unaligned */
|
||||
@ -496,21 +498,24 @@ typedef struct {
|
||||
#elif __has_attribute(__assume_aligned__)
|
||||
|
||||
static __always_inline const uint16_t *__attribute__((
|
||||
__assume_aligned__(ALIGNMENT_16))) cast_aligned_16(const void *ptr) {
|
||||
__assume_aligned__(ALIGNMENT_16)))
|
||||
cast_aligned_16(const void *ptr) {
|
||||
|
||||
return (const uint16_t *)ptr;
|
||||
|
||||
}
|
||||
|
||||
static __always_inline const uint32_t *__attribute__((
|
||||
__assume_aligned__(ALIGNMENT_32))) cast_aligned_32(const void *ptr) {
|
||||
__assume_aligned__(ALIGNMENT_32)))
|
||||
cast_aligned_32(const void *ptr) {
|
||||
|
||||
return (const uint32_t *)ptr;
|
||||
|
||||
}
|
||||
|
||||
static __always_inline const uint64_t *__attribute__((
|
||||
__assume_aligned__(ALIGNMENT_64))) cast_aligned_64(const void *ptr) {
|
||||
__assume_aligned__(ALIGNMENT_64)))
|
||||
cast_aligned_64(const void *ptr) {
|
||||
|
||||
return (const uint64_t *)ptr;
|
||||
|
||||
|
@ -155,7 +155,7 @@ typedef int128_t s128;
|
||||
({ \
|
||||
\
|
||||
char *d = (char *)(_x), *s = (char *)(_y); \
|
||||
u32 i, l = (_l)-1; \
|
||||
u32 i, l = (_l) - 1; \
|
||||
for (i = 0; i <= l; i++) \
|
||||
d[l - i] = s[i]; \
|
||||
\
|
||||
|
60
include/valueprofile.h
Normal file
60
include/valueprofile.h
Normal file
@ -0,0 +1,60 @@
|
||||
/*
|
||||
american fuzzy lop++ - value profile header
|
||||
------------------------------------
|
||||
|
||||
Originally written by Michal Zalewski
|
||||
|
||||
Forkserver design by Jann Horn <jannhorn@googlemail.com>
|
||||
|
||||
Now maintained by Marc Heuse <mh@mh-sec.de>,
|
||||
Dominik Maier <mail@dmnk.co>,
|
||||
Andrea Fioraldi <andreafioraldi@gmail.com>,
|
||||
Heiko Eissfeldt <heiko.eissfeldt@hexco.de>
|
||||
|
||||
Copyright 2016, 2017 Google Inc. All rights reserved.
|
||||
Copyright 2019-2024 AFLplusplus Project. All rights reserved.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at:
|
||||
|
||||
https://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Shared code to handle the shared memory. This is used by the fuzzer
|
||||
as well the other components like afl-tmin, afl-showmap, etc...
|
||||
|
||||
*/
|
||||
|
||||
#ifndef _AFL_VALUEPROFILE_H
|
||||
#define _AFL_VALUEPROFILE_H
|
||||
|
||||
#include "config.h"
|
||||
|
||||
#define VP_MAP_SIZE 65536
|
||||
|
||||
#define VP_TYPE_CMP 1
|
||||
#define VP_TYPE_FCMP 2
|
||||
#define VP_TYPE_RTN 3
|
||||
#define VP_TYPE_STR 4
|
||||
|
||||
struct vp_header { // 16 bit = 2 bytes
|
||||
|
||||
u64 value; // up to u64
|
||||
u64 value_ext; // u65 to u128
|
||||
u8 type; // 0-2
|
||||
u8 status; // 0-1
|
||||
u8 len; // 2-16
|
||||
u8 attribute; // 0-15
|
||||
u32 reserved2;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct vp_map {
|
||||
|
||||
struct vp_header header[VP_MAP_SIZE];
|
||||
u32 control[VP_MAP_SIZE + 1];
|
||||
|
||||
};
|
||||
|
||||
#endif
|
||||
|
@ -6616,12 +6616,14 @@ static XXH64_hash_t XXH3_mergeAccs(const xxh_u64 *XXH_RESTRICT acc,
|
||||
|
||||
}
|
||||
|
||||
#define XXH3_INIT_ACC \
|
||||
{ \
|
||||
\
|
||||
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, XXH_PRIME64_3, \
|
||||
XXH_PRIME64_4, XXH_PRIME32_2, XXH_PRIME64_5, XXH_PRIME32_1 \
|
||||
\
|
||||
#define XXH3_INIT_ACC \
|
||||
{ \
|
||||
\
|
||||
\
|
||||
XXH_PRIME32_3, XXH_PRIME64_1, XXH_PRIME64_2, \
|
||||
XXH_PRIME64_3, XXH_PRIME64_4, XXH_PRIME32_2, \
|
||||
XXH_PRIME64_5, XXH_PRIME32_1 \
|
||||
\
|
||||
}
|
||||
|
||||
XXH_FORCE_INLINE XXH64_hash_t XXH3_hashLong_64b_internal(
|
||||
|
@ -50,7 +50,11 @@
|
||||
#include "llvm/Support/SpecialCaseList.h"
|
||||
#include "llvm/Support/VirtualFileSystem.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#if LLVM_VERSION_MAJOR < 20
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#else
|
||||
#include "llvm/Transforms/Utils/Instrumentation.h"
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#endif
|
||||
@ -214,8 +218,12 @@ class ModuleSanitizerCoverageLTO
|
||||
|
||||
void SetNoSanitizeMetadata(Instruction *I) {
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
I->setNoSanitizeMetadata();
|
||||
#else
|
||||
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
|
||||
MDNode::get(*C, None));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@ -225,7 +233,7 @@ class ModuleSanitizerCoverageLTO
|
||||
FunctionCallee SanCovTracePCIndir;
|
||||
FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/;
|
||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
|
||||
Module *CurModule;
|
||||
std::string CurModuleUniqueId;
|
||||
Triple TargetTriple;
|
||||
@ -416,6 +424,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
Int16Ty = IRB.getInt16Ty();
|
||||
Int8Ty = IRB.getInt8Ty();
|
||||
Int1Ty = IRB.getInt1Ty();
|
||||
PtrTy = PointerType::getUnqual(*C);
|
||||
|
||||
/* AFL++ START */
|
||||
char *ptr;
|
||||
@ -1350,7 +1359,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
|
||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
||||
|
||||
if (F.empty()) return;
|
||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
if (F.getName().contains(".module_ctor"))
|
||||
return; // Should not instrument sanitizer init functions.
|
||||
#if LLVM_VERSION_MAJOR >= 18
|
||||
if (F.getName().starts_with("__sanitizer_"))
|
||||
@ -1372,6 +1381,10 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
|
||||
if (F.hasPersonalityFn() &&
|
||||
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
|
||||
return;
|
||||
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
|
||||
#endif
|
||||
// if (Allowlist && !Allowlist->inSection("coverage", "fun", F.getName()))
|
||||
// return;
|
||||
// if (Blocklist && Blocklist->inSection("coverage", "fun", F.getName()))
|
||||
@ -2023,16 +2036,20 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray(
|
||||
|
||||
if (&F.getEntryBlock() == AllBlocks[i]) {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
|
||||
PCs.push_back(
|
||||
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
|
||||
|
||||
} else {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(
|
||||
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
|
||||
BlockAddress::get(AllBlocks[i]), PtrTy));
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PCs.push_back(Constant::getNullValue(PtrTy));
|
||||
#else
|
||||
PCs.push_back(
|
||||
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 0), PtrTy));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
@ -63,11 +63,16 @@
|
||||
#if LLVM_VERSION_MAJOR < 15
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#if LLVM_VERSION_MAJOR < 20
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#else
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#endif
|
||||
#else
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#include "llvm/Transforms/Utils/Instrumentation.h"
|
||||
#endif
|
||||
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
|
||||
@ -161,7 +166,9 @@ class ModuleSanitizerCoverageAFL
|
||||
|
||||
void SetNoSanitizeMetadata(Instruction *I) {
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
I->setNoSanitizeMetadata();
|
||||
#elif LLVM_VERSION_MAJOR >= 16
|
||||
I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt));
|
||||
#else
|
||||
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
|
||||
@ -179,7 +186,7 @@ class ModuleSanitizerCoverageAFL
|
||||
FunctionCallee SanCovTraceSwitchFunction;
|
||||
GlobalVariable *SanCovLowestStack;
|
||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
|
||||
Module *CurModule;
|
||||
std::string CurModuleUniqueId;
|
||||
Triple TargetTriple;
|
||||
@ -272,13 +279,19 @@ std::pair<Value *, Value *> ModuleSanitizerCoverageAFL::CreateSecStartEnd(
|
||||
if (!TargetTriple.isOSBinFormatCOFF())
|
||||
return std::make_pair(SecStart, SecEnd);
|
||||
|
||||
// Account for the fact that on windows-msvc __start_* symbols actually
|
||||
// point to a uint64_t before the start of the array.
|
||||
// Account for the fact that on windows-msvc __start_* symbols actually
|
||||
// point to a uint64_t before the start of the array.
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
auto GEP =
|
||||
IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
|
||||
return std::make_pair(GEP, SecEnd);
|
||||
#else
|
||||
auto SecStartI8Ptr = IRB.CreatePointerCast(SecStart, Int8PtrTy);
|
||||
auto GEP = IRB.CreateGEP(Int8Ty, SecStartI8Ptr,
|
||||
ConstantInt::get(IntptrTy, sizeof(uint64_t)));
|
||||
return std::make_pair(IRB.CreatePointerCast(GEP, PointerType::getUnqual(Ty)),
|
||||
SecEnd);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
@ -370,6 +383,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||
Int16Ty = IRB.getInt16Ty();
|
||||
Int8Ty = IRB.getInt8Ty();
|
||||
Int1Ty = IRB.getInt1Ty();
|
||||
PtrTy = PointerType::getUnqual(*C);
|
||||
|
||||
LLVMContext &Ctx = M.getContext();
|
||||
AFLMapPtr =
|
||||
@ -572,7 +586,8 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||
|
||||
if (F.empty()) return;
|
||||
if (!isInInstrumentList(&F, FMNAME)) return;
|
||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
// if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
if (F.getName().contains(".module_ctor"))
|
||||
return; // Should not instrument sanitizer init functions.
|
||||
#if LLVM_VERSION_MAJOR >= 18
|
||||
if (F.getName().starts_with("__sanitizer_"))
|
||||
@ -595,6 +610,9 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||
isAsynchronousEHPersonality(classifyEHPersonality(F.getPersonalityFn())))
|
||||
return;
|
||||
if (F.hasFnAttribute(Attribute::NoSanitizeCoverage)) return;
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
if (F.hasFnAttribute(Attribute::DisableSanitizerInstrumentation)) return;
|
||||
#endif
|
||||
if (Options.CoverageType >= SanitizerCoverageOptions::SCK_Edge)
|
||||
SplitAllCriticalEdges(
|
||||
F, CriticalEdgeSplittingOptions().setIgnoreUnreachableDests());
|
||||
@ -692,16 +710,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
|
||||
|
||||
if (&F.getEntryBlock() == AllBlocks[i]) {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
|
||||
PCs.push_back(
|
||||
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
|
||||
|
||||
} else {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(
|
||||
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
|
||||
BlockAddress::get(AllBlocks[i]), PtrTy));
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PCs.push_back(Constant::getNullValue(IntptrPtrTy));
|
||||
PCs.push_back(Constant::getNullValue(PtrTy));
|
||||
#else
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
|
||||
@ -711,10 +729,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
|
||||
|
||||
}
|
||||
|
||||
auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy,
|
||||
SanCovPCsSectionName);
|
||||
auto *PCArray =
|
||||
CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName);
|
||||
PCArray->setInitializer(
|
||||
ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs));
|
||||
ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));
|
||||
PCArray->setConstant(true);
|
||||
|
||||
return PCArray;
|
||||
@ -822,7 +840,12 @@ bool ModuleSanitizerCoverageAFL::InjectCoverage(
|
||||
StringRef FuncName = Callee->getName();
|
||||
if (FuncName.compare(StringRef("__afl_coverage_interesting"))) continue;
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 20
|
||||
// test canary
|
||||
InstrumentationIRBuilder IRB(callInst);
|
||||
#else
|
||||
IRBuilder<> IRB(callInst);
|
||||
#endif
|
||||
|
||||
if (!FunctionGuardArray) {
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -661,6 +661,13 @@ bool AFLdict2filePass::runOnModule(Module &M) {
|
||||
Value *op2 = callInst->getArgOperand(2);
|
||||
ConstantInt *ilen = dyn_cast<ConstantInt>(op2);
|
||||
|
||||
if (!ilen) {
|
||||
|
||||
op2 = callInst->getArgOperand(1);
|
||||
ilen = dyn_cast<ConstantInt>(op2);
|
||||
|
||||
}
|
||||
|
||||
if (ilen) {
|
||||
|
||||
uint64_t literalLength = optLen;
|
||||
|
@ -61,6 +61,7 @@
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
using namespace llvm;
|
||||
static int vp_mode = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -164,6 +165,8 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
|
||||
IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
|
||||
IntegerType *Int128Ty = IntegerType::getInt128Ty(C);
|
||||
Type *floatTy = Type::getFloatTy(C);
|
||||
Type *doubleTy = Type::getDoubleTy(C);
|
||||
|
||||
/*
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
@ -275,6 +278,119 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
Function *cmplogHookInsN = cast<Function>(cN);
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
FunctionCallee vp_float;
|
||||
FunctionCallee vp_double;
|
||||
#else
|
||||
Function *vp_float;
|
||||
Function *vp_double;
|
||||
#endif
|
||||
|
||||
if (vp_mode) {
|
||||
|
||||
c2 = M.getOrInsertFunction("__valueprofile_hook2", VoidTy, Int16Ty, Int16Ty,
|
||||
Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookIns2 = c2;
|
||||
#else
|
||||
cmplogHookIns2 = cast<Function>(c2);
|
||||
#endif
|
||||
|
||||
c4 = M.getOrInsertFunction("__valueprofile_hook4", VoidTy, Int32Ty, Int32Ty,
|
||||
Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookIns4 = c4;
|
||||
#else
|
||||
cmplogHookIns4 = cast<Function>(c4);
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
FunctionCallee
|
||||
#else
|
||||
Constant *
|
||||
#endif
|
||||
cfloat = M.getOrInsertFunction("__valueprofile_hook_float", VoidTy,
|
||||
floatTy, floatTy, Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
vp_float = cfloat;
|
||||
#else
|
||||
vp_float = cast<Function>(cfloat);
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
FunctionCallee
|
||||
#else
|
||||
Constant *
|
||||
#endif
|
||||
cdouble = M.getOrInsertFunction("__valueprofile_hook_float", VoidTy,
|
||||
doubleTy, doubleTy, Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
vp_double = cdouble;
|
||||
#else
|
||||
vp_double = cast<Function>(cdouble);
|
||||
#endif
|
||||
|
||||
c8 = M.getOrInsertFunction("__valueprofile_hook8", VoidTy, Int64Ty, Int64Ty,
|
||||
Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookIns8 = c8;
|
||||
#else
|
||||
cmplogHookIns8 = cast<Function>(c8);
|
||||
#endif
|
||||
|
||||
c16 = M.getOrInsertFunction("__valueprofile_hook16", VoidTy, Int128Ty,
|
||||
Int128Ty, Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
cmplogHookIns16 = cast<Function>(c16);
|
||||
#else
|
||||
cmplogHookIns16 = c16;
|
||||
#endif
|
||||
|
||||
cN = M.getOrInsertFunction("__valueprofile_hookN", VoidTy, Int128Ty,
|
||||
Int128Ty, Int8Ty, Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookInsN = cN;
|
||||
#else
|
||||
cmplogHookInsN = cast<Function>(cN);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map");
|
||||
|
||||
if (!AFLCmplogPtr) {
|
||||
@ -285,7 +401,11 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0));
|
||||
Value *Null;
|
||||
// if (debug)
|
||||
// Null = AFLCmplogPtr;
|
||||
// else
|
||||
Null = Constant::getNullValue(PointerType::get(Int8Ty, 0));
|
||||
|
||||
/* iterate over all functions, bbs and instruction and add suitable calls */
|
||||
for (auto &F : M) {
|
||||
@ -582,68 +702,88 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
if (!skip) {
|
||||
|
||||
// errs() << "[CMPLOG] cmp " << *cmpInst << "(in function " <<
|
||||
// cmpInst->getFunction()->getName() << ")\n";
|
||||
|
||||
// first bitcast to integer type of the same bitsize as the original
|
||||
// type (this is a nop, if already integer)
|
||||
Value *op0_i = IRB.CreateBitCast(
|
||||
op0, IntegerType::get(C, ty0->getPrimitiveSizeInBits()));
|
||||
// then create a int cast, which does zext, trunc or bitcast. In our
|
||||
// case usually zext to the next larger supported type (this is a nop
|
||||
// if already the right type)
|
||||
Value *V0 =
|
||||
IRB.CreateIntCast(op0_i, IntegerType::get(C, cast_size), false);
|
||||
args.push_back(V0);
|
||||
Value *op1_i = IRB.CreateBitCast(
|
||||
op1, IntegerType::get(C, ty1->getPrimitiveSizeInBits()));
|
||||
Value *V1 =
|
||||
IRB.CreateIntCast(op1_i, IntegerType::get(C, cast_size), false);
|
||||
args.push_back(V1);
|
||||
|
||||
// errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " <<
|
||||
// *V1
|
||||
// << "\n";
|
||||
|
||||
ConstantInt *attribute = ConstantInt::get(Int8Ty, attr);
|
||||
args.push_back(attribute);
|
||||
ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1);
|
||||
|
||||
if (cast_size != max_size) {
|
||||
if (is_fp && vp_mode && (cast_size == 32 || cast_size == 64)) {
|
||||
|
||||
ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1);
|
||||
Value *opf0 = selectcmpInst->getOperand(0);
|
||||
Value *opf1 = selectcmpInst->getOperand(1);
|
||||
args.push_back(opf0);
|
||||
args.push_back(opf1);
|
||||
args.push_back(attribute);
|
||||
|
||||
switch (cast_size) {
|
||||
|
||||
case 32:
|
||||
IRB.CreateCall(vp_float, args);
|
||||
break;
|
||||
case 64:
|
||||
IRB.CreateCall(vp_double, args);
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// errs() << "[CMPLOG] cmp " << *cmpInst << "(in function " <<
|
||||
// cmpInst->getFunction()->getName() << ")\n";
|
||||
|
||||
// first bitcast to integer type of the same bitsize as the original
|
||||
// type (this is a nop, if already integer)
|
||||
Value *op0_i = IRB.CreateBitCast(
|
||||
op0, IntegerType::get(C, ty0->getPrimitiveSizeInBits()));
|
||||
// then create a int cast, which does zext, trunc or bitcast. In our
|
||||
// case usually zext to the next larger supported type (this is a
|
||||
// nop if already the right type)
|
||||
Value *V0 =
|
||||
IRB.CreateIntCast(op0_i, IntegerType::get(C, cast_size), false);
|
||||
args.push_back(V0);
|
||||
Value *op1_i = IRB.CreateBitCast(
|
||||
op1, IntegerType::get(C, ty1->getPrimitiveSizeInBits()));
|
||||
Value *V1 =
|
||||
IRB.CreateIntCast(op1_i, IntegerType::get(C, cast_size), false);
|
||||
args.push_back(V1);
|
||||
|
||||
// errs() << "[CMPLOG] casted parameters:\n0: " << *V0 << "\n1: " <<
|
||||
// *V1
|
||||
// << "\n";
|
||||
|
||||
args.push_back(attribute);
|
||||
args.push_back(bitsize);
|
||||
|
||||
}
|
||||
// fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast
|
||||
// %u\n",
|
||||
// max_size, cast_size, attr);
|
||||
|
||||
// fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast %u\n",
|
||||
// max_size, cast_size, attr);
|
||||
switch (cast_size) {
|
||||
|
||||
switch (cast_size) {
|
||||
case 8:
|
||||
// IRB.CreateCall(cmplogHookIns1, args);
|
||||
break;
|
||||
case 16:
|
||||
IRB.CreateCall(cmplogHookIns2, args);
|
||||
break;
|
||||
case 32:
|
||||
IRB.CreateCall(cmplogHookIns4, args);
|
||||
break;
|
||||
case 64:
|
||||
IRB.CreateCall(cmplogHookIns8, args);
|
||||
break;
|
||||
case 128:
|
||||
if (max_size == 128) {
|
||||
|
||||
case 8:
|
||||
// IRB.CreateCall(cmplogHookIns1, args);
|
||||
break;
|
||||
case 16:
|
||||
IRB.CreateCall(cmplogHookIns2, args);
|
||||
break;
|
||||
case 32:
|
||||
IRB.CreateCall(cmplogHookIns4, args);
|
||||
break;
|
||||
case 64:
|
||||
IRB.CreateCall(cmplogHookIns8, args);
|
||||
break;
|
||||
case 128:
|
||||
if (max_size == 128) {
|
||||
IRB.CreateCall(cmplogHookIns16, args);
|
||||
|
||||
IRB.CreateCall(cmplogHookIns16, args);
|
||||
} else {
|
||||
|
||||
} else {
|
||||
IRB.CreateCall(cmplogHookInsN, args);
|
||||
|
||||
IRB.CreateCall(cmplogHookInsN, args);
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -676,9 +816,26 @@ bool CmpLogInstructions::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL)
|
||||
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
if (getenv("AFL_LLVM_VALUEPROFILE") || getenv("AFL_LLVM_VALUE_PROFILE")) {
|
||||
|
||||
vp_mode = 1;
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL) {
|
||||
|
||||
if (vp_mode) {
|
||||
|
||||
printf("Running valueprofile-instruction-pass by AFL++ team\n");
|
||||
|
||||
} else {
|
||||
|
||||
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
||||
|
||||
}
|
||||
|
||||
} else
|
||||
|
||||
be_quiet = 1;
|
||||
bool ret = hookInstrs(M);
|
||||
verifyModule(M);
|
||||
|
@ -59,6 +59,8 @@
|
||||
#include <set>
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
static int vp_mode = 0;
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
@ -288,6 +290,114 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
Function *cmplogHookFnStr = cast<Function>(c7);
|
||||
#endif
|
||||
|
||||
if (vp_mode) {
|
||||
|
||||
c = M.getOrInsertFunction("__valueprofile_rtn_hook", VoidTy, i8PtrTy,
|
||||
i8PtrTy
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookFn = c;
|
||||
#else
|
||||
cmplogHookFn = cast<Function>(c);
|
||||
#endif
|
||||
|
||||
c1 = M.getOrInsertFunction("__valueprofile_rtn_llvm_stdstring_stdstring",
|
||||
VoidTy, i8PtrTy, i8PtrTy
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogLlvmStdStd = c1;
|
||||
#else
|
||||
cmplogLlvmStdStd = cast<Function>(c1);
|
||||
#endif
|
||||
|
||||
c2 = M.getOrInsertFunction("__valueprofile_rtn_llvm_stdstring_cstring",
|
||||
VoidTy, i8PtrTy, i8PtrTy
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogLlvmStdC = c2;
|
||||
#else
|
||||
cmplogLlvmStdC = cast<Function>(c2);
|
||||
#endif
|
||||
|
||||
c3 = M.getOrInsertFunction("__valueprofile_rtn_gcc_stdstring_stdstring",
|
||||
VoidTy, i8PtrTy, i8PtrTy
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogGccStdStd = c3;
|
||||
#else
|
||||
cmplogGccStdStd = cast<Function>(c3);
|
||||
#endif
|
||||
|
||||
c4 = M.getOrInsertFunction("__valueprofile_rtn_gcc_stdstring_cstring",
|
||||
VoidTy, i8PtrTy, i8PtrTy
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogGccStdC = c4;
|
||||
#else
|
||||
cmplogGccStdC = cast<Function>(c4);
|
||||
#endif
|
||||
|
||||
c5 = M.getOrInsertFunction("__valueprofile_rtn_hook_n", VoidTy, i8PtrTy,
|
||||
i8PtrTy, Int64Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookFnN = c5;
|
||||
#else
|
||||
cmplogHookFnN = cast<Function>(c5);
|
||||
#endif
|
||||
|
||||
c6 = M.getOrInsertFunction("__valueprofile_rtn_hook_strn", VoidTy, i8PtrTy,
|
||||
i8PtrTy, Int64Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookFnStrN = c6;
|
||||
#else
|
||||
cmplogHookFnStrN = cast<Function>(c6);
|
||||
#endif
|
||||
|
||||
c7 = M.getOrInsertFunction("__valueprofile_rtn_hook_str", VoidTy, i8PtrTy,
|
||||
i8PtrTy
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookFnStr = c7;
|
||||
#else
|
||||
cmplogHookFnStr = cast<Function>(c7);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map");
|
||||
|
||||
if (!AFLCmplogPtr) {
|
||||
@ -490,33 +600,39 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
<< " calls with pointers as arguments\n";
|
||||
*/
|
||||
|
||||
for (auto &callInst : calls) {
|
||||
// TODO VP
|
||||
if (!vp_mode) {
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
for (auto &callInst : calls) {
|
||||
|
||||
IRBuilder<> IRB2(callInst->getParent());
|
||||
IRB2.SetInsertPoint(callInst);
|
||||
Value *v1P = callInst->getArgOperand(0),
|
||||
*v2P = callInst->getArgOperand(1);
|
||||
|
||||
LoadInst *CmpPtr = IRB2.CreateLoad(
|
||||
IRBuilder<> IRB2(callInst->getParent());
|
||||
IRB2.SetInsertPoint(callInst);
|
||||
|
||||
LoadInst *CmpPtr = IRB2.CreateLoad(
|
||||
#if LLVM_VERSION_MAJOR >= 14
|
||||
PointerType::get(Int8Ty, 0),
|
||||
PointerType::get(Int8Ty, 0),
|
||||
#endif
|
||||
AFLCmplogPtr);
|
||||
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
|
||||
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);
|
||||
AFLCmplogPtr);
|
||||
CmpPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
|
||||
auto is_not_null = IRB2.CreateICmpNE(CmpPtr, Null);
|
||||
auto ThenTerm = SplitBlockAndInsertIfThen(is_not_null, callInst, false);
|
||||
|
||||
IRBuilder<> IRB(ThenTerm);
|
||||
IRBuilder<> IRB(ThenTerm);
|
||||
|
||||
std::vector<Value *> args;
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
std::vector<Value *> args;
|
||||
Value *v1Pcasted = IRB.CreatePointerCast(v1P, i8PtrTy);
|
||||
Value *v2Pcasted = IRB.CreatePointerCast(v2P, i8PtrTy);
|
||||
args.push_back(v1Pcasted);
|
||||
args.push_back(v2Pcasted);
|
||||
|
||||
IRB.CreateCall(cmplogHookFn, args);
|
||||
IRB.CreateCall(cmplogHookFn, args);
|
||||
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
// errs() << callInst->getCalledFunction()->getName() << "\n";
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -754,10 +870,30 @@ bool CmpLogRoutines::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL)
|
||||
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
if (getenv("AFL_LLVM_VALUEPROFILE") || getenv("AFL_LLVM_VALUE_PROFILE")) {
|
||||
|
||||
vp_mode = 1;
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL) {
|
||||
|
||||
if (vp_mode) {
|
||||
|
||||
printf("Running valueprofile-routines-pass by AFL++ team\n");
|
||||
|
||||
} else {
|
||||
|
||||
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
|
||||
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
be_quiet = 1;
|
||||
|
||||
}
|
||||
|
||||
bool ret = hookRtns(M);
|
||||
verifyModule(M);
|
||||
|
||||
|
@ -62,6 +62,8 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static int vp_mode = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
@ -231,6 +233,77 @@ bool CmplogSwitches::hookInstrs(Module &M) {
|
||||
Function *cmplogHookIns8 = cast<Function>(c8);
|
||||
#endif
|
||||
|
||||
if (vp_mode) {
|
||||
|
||||
c2 = M.getOrInsertFunction("__valueprofile_hook2", VoidTy, Int16Ty, Int16Ty,
|
||||
Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookIns2 = c2;
|
||||
#else
|
||||
cmplogHookIns2 = cast<Function>(c2);
|
||||
#endif
|
||||
|
||||
c4 = M.getOrInsertFunction("__valueprofile_hook4", VoidTy, Int32Ty, Int32Ty,
|
||||
Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookIns4 = c4;
|
||||
#else
|
||||
cmplogHookIns4 = cast<Function>(c4);
|
||||
#endif
|
||||
|
||||
c8 = M.getOrInsertFunction("__valueprofile_hook8", VoidTy, Int64Ty, Int64Ty,
|
||||
Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookIns8 = c8;
|
||||
#else
|
||||
cmplogHookIns8 = cast<Function>(c8);
|
||||
#endif
|
||||
|
||||
/*
|
||||
c16 = M.getOrInsertFunction("__valueprofile_hook16", VoidTy, Int128Ty,
|
||||
Int128Ty, Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR < 9
|
||||
cmplogHookIns16 = cast<Function>(c16);
|
||||
#else
|
||||
cmplogHookIns16 = c16;
|
||||
#endif
|
||||
|
||||
cN = M.getOrInsertFunction("__valueprofile_hookN", VoidTy, Int128Ty,
|
||||
Int128Ty, Int8Ty, Int8Ty
|
||||
#if LLVM_VERSION_MAJOR < 5
|
||||
,
|
||||
NULL
|
||||
#endif
|
||||
);
|
||||
#if LLVM_VERSION_MAJOR >= 9
|
||||
cmplogHookInsN = cN;
|
||||
#else
|
||||
cmplogHookInsN = cast<Function>(cN);
|
||||
#endif
|
||||
*/
|
||||
|
||||
}
|
||||
|
||||
GlobalVariable *AFLCmplogPtr = M.getNamedGlobal("__afl_cmp_map");
|
||||
|
||||
if (!AFLCmplogPtr) {
|
||||
@ -438,9 +511,21 @@ bool CmplogSwitches::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL)
|
||||
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
if (getenv("AFL_LLVM_VALUEPROFILE") || getenv("AFL_LLVM_VALUE_PROFILE")) {
|
||||
|
||||
vp_mode = 1;
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL) {
|
||||
|
||||
if (vp_mode)
|
||||
printf("Running valueprofile-switches-pass by AFL++ team\n");
|
||||
else
|
||||
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
|
||||
|
||||
} else
|
||||
|
||||
be_quiet = 1;
|
||||
bool ret = hookInstrs(M);
|
||||
verifyModule(M);
|
||||
|
@ -1 +1 @@
|
||||
6833d23
|
||||
ea6ceb9
|
||||
|
@ -1 +1 @@
|
||||
bcf3e24
|
||||
6067e5c
|
||||
|
Submodule nyx_mode/QEMU-Nyx updated: e5e1c4c21f...ff1c897321
@ -1 +1 @@
|
||||
e5e1c4c21ff9c4dc80e6409d4eab47146c6024cd
|
||||
ff1c897321
|
||||
|
@ -23,7 +23,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel
|
||||
2. Additionally, install the following packages:
|
||||
|
||||
```shell
|
||||
apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2
|
||||
apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2 libcapstone-dev
|
||||
```
|
||||
|
||||
3. As Nyx is written in Rust, install the newest rust compiler (rust packages in
|
||||
@ -33,7 +33,7 @@ requires an Intel processor (6th generation onwards) and a special 5.10 kernel
|
||||
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh
|
||||
```
|
||||
|
||||
4. Finally build Nyx mode:
|
||||
4. Finally build Nyx mode (or use `make distrib` at the repo root to build all AFL++ modes):
|
||||
|
||||
```shell
|
||||
./build_nyx_support.sh
|
||||
@ -92,7 +92,7 @@ sudo modprobe -r kvm-intel
|
||||
sudo modprobe -r kvm
|
||||
sudo modprobe kvm enable_vmware_backdoor=y
|
||||
sudo modprobe kvm-intel
|
||||
cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echi OK || echo KVM module problem
|
||||
cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echo OK || echo KVM module problem
|
||||
```
|
||||
|
||||
All the hard parts are done, fuzzing with Nyx mode is easy - just supply the
|
||||
@ -186,7 +186,7 @@ make CC=afl-clang-fast CXX=afl-clang-fast++ LD=afl-clang-fast
|
||||
|
||||
#### Nyx share directories
|
||||
|
||||
Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Both bootstrap scripts use several tools to communicate with the "outer world":
|
||||
Nyx expects that the target is provided in a certain format. More specifically, the target is passed as a so-called „share directory“ to a Nyx-frontend implementation. The share directory contains the target as well as a folder containing all dependencies and other files that are copied over to the guest. But more importantly, this share directory also contains a bootstrap script (`fuzz.sh`if you are using `KVM-Nyx`otherwise `fuzz_no_pt.sh`) that is also executed right after launching the fuzzer. Either of these scripts can be edited to more fully prepare an environment for the target, like transferring configuration files to the target's filesystem. Both bootstrap scripts use several tools to communicate with the "outer world":
|
||||
|
||||
- `hcat` - this tool copies a given string to the host
|
||||
- `hget` - this program requests a file from the host's share directory
|
||||
|
Submodule nyx_mode/libnyx updated: 6833d236df...ea6ceb994a
Submodule nyx_mode/packer updated: bcf3e248b6...6067e5c0ff
@ -1 +1 @@
|
||||
a6f0632a65
|
||||
d40bcd8965
|
||||
|
@ -99,10 +99,7 @@ be lost at the second execution of the loop.
|
||||
|
||||
### 2.5) Resetting the memory state
|
||||
|
||||
This option restores the memory state using the AFL++ Snapshot LKM if loaded.
|
||||
Otherwise, all the writeable pages are restored.
|
||||
|
||||
To enable this option, set `AFL_QEMU_PERSISTENT_MEM=1`.
|
||||
(obsolete chapter)
|
||||
|
||||
### 2.6) Reset on exit()
|
||||
|
||||
@ -113,15 +110,7 @@ The environment variable is `AFL_QEMU_PERSISTENT_EXITS`.
|
||||
|
||||
### 2.7) Snapshot
|
||||
|
||||
`AFL_QEMU_SNAPSHOT=address` is just a "syntactical sugar" environment variable
|
||||
that is equivalent to the following set of variables:
|
||||
|
||||
```
|
||||
AFL_QEMU_PERSISTENT_ADDR=address
|
||||
AFL_QEMU_PERSISTENT_GPR=1
|
||||
AFL_QEMU_PERSISTENT_MEM=1
|
||||
AFL_QEMU_PERSISTENT_EXITS=1
|
||||
```
|
||||
obsolete
|
||||
|
||||
## 3) Optional parameters
|
||||
|
||||
|
@ -386,6 +386,19 @@ else
|
||||
make -C libqasan CC="$CROSS $CROSS_FLAGS" && echo "[+] libqasan ready"
|
||||
fi
|
||||
|
||||
#### Hooking support
|
||||
if [ "$ENABLE_HOOKING" = "1" ];then
|
||||
echo "[+] ENABLING HOOKING"
|
||||
set -e
|
||||
cd ./hooking_bridge || exit 255
|
||||
mkdir -p ./build
|
||||
echo "[+] Hook compiler = $CROSS"
|
||||
make CC="$CROSS $CROSS_FLAGS" GLIB_H="$GLIB_H" GLIB_CONFIG_H="$GLIB_CONFIG_H"
|
||||
set +e
|
||||
cd ..
|
||||
fi
|
||||
#### End of hooking support
|
||||
|
||||
echo "[+] All done for qemu_mode, enjoy!"
|
||||
|
||||
exit 0
|
||||
|
18
qemu_mode/hooking_bridge/Makefile
Normal file
18
qemu_mode/hooking_bridge/Makefile
Normal file
@ -0,0 +1,18 @@
|
||||
.PHONY: clean
|
||||
|
||||
all: plugin
|
||||
SRC=./src
|
||||
BLD=./build
|
||||
INC=-I./inc -I../qemuafl/include -I$(GLIB_H) -I$(GLIB_CONFIG_H)
|
||||
# CC=gcc
|
||||
|
||||
$(BLD)/patching.o:$(SRC)/patching.c
|
||||
$(CC) -c -fPIC $(INC) -o $(BLD)/patching.o $(SRC)/patching.c
|
||||
|
||||
plugin:$(SRC)/main.c $(BLD)/patching.o
|
||||
$(CC) -c -fPIC $(INC) -o $(BLD)/plugin.o $(SRC)/main.c
|
||||
$(CC) -shared -o $(BLD)/plugin.so $(BLD)/plugin.o $(BLD)/patching.o
|
||||
|
||||
clean:
|
||||
rm -rf $(BLD)/*.o
|
||||
rm -rf $(BLD)/*.so
|
96
qemu_mode/hooking_bridge/README.md
Normal file
96
qemu_mode/hooking_bridge/README.md
Normal file
@ -0,0 +1,96 @@
|
||||
# Native hooking support into QEMUAFL
|
||||
* The essential idea is to have inbuilt hooking support into QEMU, instead of relying on the more expensive options UNICORN and its children.
|
||||
* This solution comprises a bridge (QEMU plugin) that connects your hooks (in a shared library (.so)) with the QEMU usermode ecosystem.
|
||||
* Currently, LINUX only
|
||||
|
||||
## Bridge compilation
|
||||
Run build_qemu_support.sh as you do to compile qemuafl, additionally with three args namely:
|
||||
* `ENABLE_HOOKING=1` to compile the bridge
|
||||
* `GLIB_H` and `GLIB_CONFIG_H` point to headers `glib.h` and `glibconfig.h` to wherever they are installed on your system
|
||||
|
||||
## Writting hooks
|
||||
1. Create one or more hooking functions in a shared library, say `hook.so`.
|
||||
2. Include `exports.h` in your hook build. You can find this header at `<your AFL++ path>/qemu_mode/hooking_bridge/inc`.
|
||||
3. Shown below is an example which will use to walkthrough hook creation
|
||||
```C
|
||||
struct ret* hook_000000400deadc08(){
|
||||
memset (buf, 0, 8);
|
||||
scanf("%s",buf);
|
||||
r_reg(RSI,(void *)&h_addr);
|
||||
w_mem(h_addr,8, buf);
|
||||
to_ret = (struct ret){0x400deadcab, 0};
|
||||
return &to_ret;
|
||||
}
|
||||
```
|
||||
i. Hook functions must be named as `hook_<left padded hook location>`. Here, `<left padded hook location>` means `<hook location>` left padded with 0's to until 16 hex characters. The unpaded part of `<hook location>` is the absolute address where you want to place the hook. It is basically the file base address (which does not change in QEMU as of now) plus the instruction offset where the hooks is to be placed. The hook function must return a `struct ret *`, which is touched upon later.
|
||||
|
||||
ii. Most likely you will need to access memory or registers in the hook. So we provide four functions
|
||||
```C
|
||||
// Read memory (from address, num. bytes, destination buffer) -> returns 0 on success
|
||||
int r_mem(unsigned long long addr, unsigned long long len, void *dest);
|
||||
// Write memory (to address, num. bytes, source buffer) -> returns 0 on success
|
||||
int w_mem(unsigned long long addr, unsigned long long len, void *src);
|
||||
// Read register (identifier, destination buffer) -> returns number of bytes read
|
||||
int r_reg(unsigned char reg, void *dest);
|
||||
// Read register (identifier, source buffer) -> returns number of bytes written
|
||||
int w_reg(unsigned char reg, char *src);
|
||||
```
|
||||
When operating on registers, the functions require a `reg` identifier. This is basically a number gdb uses to lookup a register and can be found under `<qemu(afl) path>/gdb-xml` in the architecture specific xml files. For the example case from above, `RSI` is 4 as obtained from `i386-64bit.xml`.
|
||||
|
||||
iii. Once done with the processing, the hooks needs to return a `struct ret` type pointer, the struct format being
|
||||
```C
|
||||
struct ret{
|
||||
unsigned long long addr;
|
||||
char remove_bp;
|
||||
};
|
||||
```
|
||||
As we can see, there are two fields: first that indicates the address to return to and second that indicates whether the installed hook should be removed after the return. The second field becomes critical if the hook is within an ongoing loop and should be kept intact for future references.
|
||||
|
||||
iv. Finally, mention the list of hooks in a `configure` function that we can call and install your hooks
|
||||
```C
|
||||
struct conf config;
|
||||
struct conf* configure(){
|
||||
config.IP_reg_num = 16;
|
||||
config.entry_addr = 0x4000001000;
|
||||
config.num_hooks = NUMHOOKS; //1,2,3...
|
||||
hooks[0] = 0x400deadc08;
|
||||
// hooks[1] = 0xcafecace
|
||||
// ....
|
||||
config.hooks = hooks;
|
||||
|
||||
//Any other processing stuff you need done before fuzztime
|
||||
|
||||
return &config;
|
||||
}
|
||||
```
|
||||
The `configure` function must have the signature `struct conf* configure()` i.e. it must return a pointer to the `config` object. The format of the `config` object is
|
||||
```C
|
||||
struct conf{
|
||||
unsigned char IP_reg_num; //found in <qemudir>/gdb-xml
|
||||
unsigned long long entry_addr; //Main, init, or any entry point that is executed by QEMU prior to hooking targets
|
||||
unsigned long long* hooks; //list of hooked addresses
|
||||
unsigned long long num_hooks; // Number of hooks
|
||||
};
|
||||
```
|
||||
`IP_reg_num` here is the register number assigned under the architecture specific xml file under `<qemu(afl) path>/gdb-xml` to the instruction pointer.
|
||||
|
||||
## Running with hooks
|
||||
Set `QEMU_PLUGIN="file=<AFL download path>qemu_mode/hooking_bridge/build/plugin.so,arg=<your hook .so>"` before running AFL++ in QEMU mode. Note `<your hook .so>` is the absolute path to your hooks library.
|
||||
|
||||
## Current limitations
|
||||
1. Cannot be used to debug (-g option) when using the bridge as it uses the gdbstub internally. This is not a problem if used with AFL++, so not such a big issue.
|
||||
2. Cannot put a hook on the first block after `<entry point>`. Not typically a hookable location.
|
||||
3. The current implementation can only function on Linux. We have tested on the following configuration
|
||||
```Bash
|
||||
lsb_release -a
|
||||
---------------
|
||||
Distributor ID: Ubuntu
|
||||
Description: Ubuntu 22.04.3 LTS
|
||||
Release: 22.04
|
||||
Codename: jammy
|
||||
```
|
||||
```Bash
|
||||
uname -a
|
||||
----------
|
||||
Linux someone 6.5.0-28-generic #29~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Thu Apr 4 14:39:20 UTC 2 x86_64 x86_64 x86_64 GNU/Linux
|
||||
```
|
11
qemu_mode/hooking_bridge/inc/common.h
Normal file
11
qemu_mode/hooking_bridge/inc/common.h
Normal file
@ -0,0 +1,11 @@
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <qemu/qemu-plugin.h>
|
||||
|
||||
void patch_finish_cb(void *userdata);
|
||||
void patch_block_trans_cb(struct qemu_plugin_tb *tb);
|
||||
void patch_vpu_init_cb(unsigned int vcpu_index);
|
||||
void patch_init(char *hook_library);
|
||||
|
||||
#endif
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user