mirror of
https://github.com/AFLplusplus/AFLplusplus.git
synced 2025-06-24 22:53:24 +00:00
Compare commits
16 Commits
Author | SHA1 | Date | |
---|---|---|---|
9287f45e3e | |||
b0839ffcaf | |||
3f065ea70a | |||
d869913efa | |||
6a246516df | |||
daab85f3f1 | |||
97ed8c2877 | |||
dca144fbff | |||
ab9bd37b86 | |||
d4071b0fe4 | |||
5a0a33e52a | |||
c510ba6863 | |||
bd4c9a5eab | |||
f9e85817ad | |||
8758be3630 | |||
31a7ff2ba2 |
@ -24,7 +24,7 @@ import importlib.metadata
|
||||
|
||||
# string_re = re.compile('(\\"(\\\\.|[^"\\\\])*\\")') # TODO: for future use
|
||||
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 18)
|
||||
CURRENT_LLVM = os.getenv('LLVM_VERSION', 17)
|
||||
CLANG_FORMAT_BIN = os.getenv("CLANG_FORMAT_BIN", "")
|
||||
|
||||
|
||||
|
42
.github/workflows/ci.yml
vendored
42
.github/workflows/ci.yml
vendored
@ -34,25 +34,23 @@ 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 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
|
||||
# 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
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@ -6,7 +6,6 @@
|
||||
*.pyc
|
||||
*.so
|
||||
*.swp
|
||||
.DS_Store
|
||||
.sync_tmp
|
||||
.test
|
||||
.test2
|
||||
@ -112,5 +111,3 @@ 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,7 +34,6 @@ 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/)
|
||||
|
||||
@ -48,7 +47,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](#how-to-submit-a-pull-request).
|
||||
[#how-to-submit-a-pull-request-to-afl](#how-to-submit-a-pull-request-to-afl).
|
||||
|
||||
And finally, here are some best practices for writing docs content:
|
||||
|
||||
@ -57,4 +56,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,14 +441,6 @@ 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:
|
||||
@ -479,8 +471,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 | 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-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-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,9 +32,6 @@ 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)
|
||||
@ -42,36 +39,24 @@ 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
|
||||
# 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)
|
||||
LLVM_CONFIG ?= llvm-config
|
||||
endif
|
||||
|
||||
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))))
|
||||
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
|
||||
|
||||
ifeq "$(LLVMVER)" ""
|
||||
$(warning [!] llvm_mode needs llvm-config, which was not found. Set LLVM_CONFIG to its path and retry.)
|
||||
@ -118,6 +103,10 @@ 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.
|
||||
@ -125,11 +114,6 @@ 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"
|
||||
@ -261,7 +245,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
|
||||
@ -316,8 +300,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
|
||||
@ -327,7 +311,7 @@ endif
|
||||
|
||||
# User teor2345 reports that this is required to make things work on MacOS X.
|
||||
ifeq "$(SYS)" "Darwin"
|
||||
CLANG_LFL += -Wl,-undefined,dynamic_lookup
|
||||
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
|
||||
override LLVM_HAVE_LTO := 0
|
||||
override LLVM_LTO := 0
|
||||
else
|
||||
@ -335,7 +319,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
|
||||
@ -433,7 +417,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" height="250">
|
||||
<img align="right" src="https://raw.githubusercontent.com/AFLplusplus/Website/main/static/aflpp_bg.svg" alt="AFL++ logo" width="250" heigh="250">
|
||||
|
||||
Release version: [4.21c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
Release version: [4.20c](https://github.com/AFLplusplus/AFLplusplus/releases)
|
||||
|
||||
GitHub version: 4.22a
|
||||
GitHub version: 4.21a
|
||||
|
||||
Repository:
|
||||
[https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
|
||||
|
4
TODO.md
4
TODO.md
@ -2,8 +2,6 @@
|
||||
|
||||
## Must
|
||||
|
||||
- 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
|
||||
- cmplog max items env?
|
||||
@ -13,12 +11,12 @@
|
||||
- afl-showmap -f support
|
||||
- afl-fuzz multicore wrapper script
|
||||
- when trimming then perform crash detection
|
||||
- cyclomatic complexity: 2 + calls + edges - blocks
|
||||
|
||||
|
||||
## Should
|
||||
|
||||
- afl-crash-analysis
|
||||
- cmplog: add loop count resolving (byte -> loop cnt change, calc special values)
|
||||
- support persistent and deferred fork server in afl-showmap?
|
||||
- better autodetection of shifting runtime timeout values
|
||||
- afl-plot to support multiple plot_data
|
||||
|
@ -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,4 +11,3 @@
|
||||
|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) -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
|
||||
$(CC) $(CFLAGS) -I../../../include -I. -o aflpp-standalone aflpp-standalone.c ../../../src/afl-performance.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 -h # to see all parameteres
|
||||
cat file | aflpp-standalone -m 4 -x foo.dict - outputfile splicefile # example
|
||||
aflpp-standalone inputfile outputfile [splicefile]
|
||||
```
|
||||
|
||||
|
@ -1,12 +1,6 @@
|
||||
#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;
|
||||
@ -27,14 +21,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;
|
||||
|
||||
}
|
||||
|
||||
@ -42,23 +36,9 @@ 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;
|
||||
|
||||
}
|
||||
@ -73,7 +53,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;
|
||||
|
||||
@ -86,20 +66,14 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
}
|
||||
|
||||
u32 havoc_steps = 1 + rand_below(data->afl, max_havoc);
|
||||
if (verbose) fprintf(stderr, "Havoc steps: %u\n", havoc_steps);
|
||||
u32 havoc_steps = 1 + rand_below(data->afl, 16);
|
||||
|
||||
/* set everything up, costly ... :( */
|
||||
memcpy(data->buf, buf, buf_size);
|
||||
|
||||
/* the mutation */
|
||||
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);
|
||||
u32 out_buf_len = afl_mutate(data->afl, data->buf, buf_size, havoc_steps,
|
||||
false, true, add_buf, add_buf_size, max_size);
|
||||
|
||||
/* return size of mutated data */
|
||||
*out_buf = data->buf;
|
||||
@ -110,143 +84,80 @@ 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] [-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("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("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("The -v verbose option prints debug output to stderr.\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);
|
||||
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);
|
||||
FILE *in = stdin, *out = stdout, *splice = NULL;
|
||||
unsigned char *inbuf = malloc(1024 * 1024), *outbuf, *splicebuf = NULL;
|
||||
int verbose = 0, splicelen = 0;
|
||||
|
||||
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 > optind && strcmp(argv[optind], "-") != 0) {
|
||||
|
||||
if ((in = fopen(argv[optind], "r")) == NULL) {
|
||||
|
||||
if (argc > 1 && strcmp(argv[1], "-") != 0) {
|
||||
if ((in = fopen(argv[1], "r")) == NULL) {
|
||||
perror(argv[1]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[optind]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Input: %s\n", argv[1]);
|
||||
}
|
||||
|
||||
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[optind] ? argv[optind] : "stdin");
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[1] ? argv[1] : "stdin");
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (argc > optind + 1 && strcmp(argv[optind + 1], "-") != 0) {
|
||||
|
||||
if ((out = fopen(argv[optind + 1], "w")) == NULL) {
|
||||
|
||||
perror(argv[optind + 1]);
|
||||
if (argc > 2 && strcmp(argv[2], "-") != 0) {
|
||||
if ((out = fopen(argv[2], "w")) == NULL) {
|
||||
perror(argv[2]);
|
||||
return -1;
|
||||
|
||||
}
|
||||
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[optind + 1]);
|
||||
|
||||
if (verbose) fprintf(stderr, "Output: %s\n", argv[2]);
|
||||
}
|
||||
|
||||
if (argc > optind + 2) {
|
||||
|
||||
if ((splice = fopen(argv[optind + 2], "r")) == NULL) {
|
||||
|
||||
perror(argv[optind + 2]);
|
||||
if (argc > 3) {
|
||||
if ((splice = fopen(argv[3], "r")) == NULL) {
|
||||
perror(argv[3]);
|
||||
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 (verbose) fprintf(stderr, "Splice: %s\n", argv[3]);
|
||||
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]);
|
||||
fprintf(stderr, "Error: empty file %s\n", argv[3]);
|
||||
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 random seed first
|
||||
# create the required a 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,8 +180,7 @@ size_t fail_fatal(int fd_socket, uint8_t **out_buf) {
|
||||
|
||||
if (fd_socket != -1) { close(fd_socket); }
|
||||
*out_buf = NULL;
|
||||
fprintf(stderr, "atnwalk.socket not found in current directory!\n");
|
||||
exit(-1);
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -39,7 +39,6 @@ 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
|
||||
@ -58,9 +57,8 @@ 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;
|
||||
@ -106,9 +104,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 < AUTOTOKENS_TXT_MIN_LEN)) {
|
||||
afl_ptr->queue_cur->len < AFL_TXT_MIN_LEN)) {
|
||||
|
||||
if (afl_ptr->extras_cnt) {
|
||||
if (afl_ptr->extras_cnt > 8) {
|
||||
|
||||
u32 valid = 0;
|
||||
|
||||
@ -239,7 +237,7 @@ extern "C" u32 afl_custom_fuzz_count(void *data, const u8 *buf,
|
||||
|
||||
}
|
||||
|
||||
extern "C" size_t afl_custom_fuzz(void *data, u8 *buf, size_t buf_size,
|
||||
extern "C" size_t afl_custom_fuzz(my_mutator_t *data, u8 *buf, size_t buf_size,
|
||||
u8 **out_buf, u8 *add_buf,
|
||||
size_t add_buf_size, size_t max_size) {
|
||||
|
||||
@ -657,7 +655,6 @@ 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;
|
||||
@ -687,6 +684,8 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
}
|
||||
|
||||
create_from_thin_air = 0;
|
||||
|
||||
}
|
||||
|
||||
if (entry == file_mapping.end()) {
|
||||
@ -694,7 +693,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 < AUTOTOKENS_TXT_MIN_LEN) {
|
||||
if (len < AFL_TXT_MIN_LEN) {
|
||||
|
||||
file_mapping[fn] = structure; // NULL ptr so we don't read the file again
|
||||
s = NULL;
|
||||
@ -896,7 +895,6 @@ 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");
|
||||
@ -957,7 +955,7 @@ extern "C" unsigned char afl_custom_queue_get(void *data,
|
||||
|
||||
}
|
||||
|
||||
extern "C" void *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
extern "C" my_mutator_t *afl_custom_init(afl_state *afl, unsigned int seed) {
|
||||
|
||||
(void)(seed);
|
||||
my_mutator_t *data = (my_mutator_t *)calloc(1, sizeof(my_mutator_t));
|
||||
@ -1072,7 +1070,7 @@ extern "C" void *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
id_to_token[current_id] = "'";
|
||||
++current_id;
|
||||
|
||||
return (void *)data;
|
||||
return data;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,19 +0,0 @@
|
||||
|
||||
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
|
@ -1,12 +0,0 @@
|
||||
# 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
|
||||
```
|
@ -1,192 +0,0 @@
|
||||
#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;
|
||||
|
||||
}
|
||||
|
@ -1,7 +0,0 @@
|
||||
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
|
@ -1,13 +0,0 @@
|
||||
# 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 ...
|
||||
```
|
@ -1,113 +0,0 @@
|
||||
#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: af8dd4a307...11546bfd07
@ -1 +1 @@
|
||||
05d8f53
|
||||
5ed4f8d
|
||||
|
Submodule custom_mutators/grammar_mutator/grammar_mutator updated: 05d8f537f8...5ed4f8d6e6
@ -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 \
|
||||
((1U << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
|
||||
((1 << FBITS) - 1) /* maximum fixnum (and most negative fixnum) \
|
||||
*/
|
||||
#define MAXOBJ 0xffff /* max words in tuple including header */
|
||||
#define MAXPAYL \
|
||||
|
@ -22,10 +22,10 @@ afl_state_t *afl_struct;
|
||||
typedef struct my_mutator {
|
||||
|
||||
afl_state_t *afl;
|
||||
u8 *mutator_buf;
|
||||
u8 *out_dir;
|
||||
u8 *tmp_dir;
|
||||
u8 *target;
|
||||
u8 * mutator_buf;
|
||||
u8 * out_dir;
|
||||
u8 * tmp_dir;
|
||||
u8 * target;
|
||||
uint32_t seed;
|
||||
|
||||
} my_mutator_t;
|
||||
@ -101,7 +101,7 @@ my_mutator_t *afl_custom_init(afl_state_t *afl, unsigned int seed) {
|
||||
|
||||
/* When a new queue entry is added we run this input with the symcc
|
||||
instrumented binary */
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
|
||||
uint8_t afl_custom_queue_new_entry(my_mutator_t * data,
|
||||
const uint8_t *filename_new_queue,
|
||||
const uint8_t *filename_orig_queue) {
|
||||
|
||||
@ -176,7 +176,7 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
|
||||
|
||||
struct dirent **nl;
|
||||
int32_t items = scandir(data->tmp_dir, &nl, NULL, NULL);
|
||||
u8 *origin_name = basename(filename_new_queue);
|
||||
u8 * origin_name = basename(filename_new_queue);
|
||||
int32_t i;
|
||||
if (items > 0) {
|
||||
|
||||
@ -187,8 +187,8 @@ uint8_t afl_custom_queue_new_entry(my_mutator_t *data,
|
||||
DBG("test=%s\n", fn);
|
||||
if (stat(source_name, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
u8 *destination_name = alloc_printf("%s/%s.%s", data->out_dir,
|
||||
origin_name, nl[i]->d_name);
|
||||
u8 *destination_name =
|
||||
alloc_printf("%s/%s.%s", data->out_dir, origin_name, nl[i]->d_name);
|
||||
rename(source_name, destination_name);
|
||||
ck_free(destination_name);
|
||||
DBG("found=%s\n", source_name);
|
||||
@ -248,7 +248,7 @@ uint32_t afl_custom_fuzz_count(my_mutator_t *data, const u8 *buf,
|
||||
for (i = 0; i < (u32)items; ++i) {
|
||||
|
||||
struct stat st;
|
||||
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
DBG("test=%s\n", fn);
|
||||
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
@ -282,12 +282,12 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
|
||||
if (items <= 0) return 0;
|
||||
|
||||
for (i = 0; i < (s32)items; ++i) {
|
||||
for (i = 0; i < (u32)items; ++i) {
|
||||
|
||||
if (!done) {
|
||||
struct stat st;
|
||||
u8 * fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
|
||||
struct stat st;
|
||||
u8 *fn = alloc_printf("%s/%s", data->out_dir, nl[i]->d_name);
|
||||
if (done == 0) {
|
||||
|
||||
if (stat(fn, &st) == 0 && S_ISREG(st.st_mode) && st.st_size) {
|
||||
|
||||
@ -306,10 +306,10 @@ size_t afl_custom_fuzz(my_mutator_t *data, uint8_t *buf, size_t buf_size,
|
||||
}
|
||||
|
||||
unlink(fn);
|
||||
ck_free(fn);
|
||||
|
||||
}
|
||||
|
||||
ck_free(fn);
|
||||
free(nl[i]);
|
||||
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3,81 +3,25 @@
|
||||
This is the list of all noteworthy changes made in every public
|
||||
release of the tool. See README.md for the general instruction manual.
|
||||
|
||||
### Version ++4.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)
|
||||
### Version ++4.21a (dev)
|
||||
* afl-fuzz
|
||||
- fixed a regression in afl-fuzz that resulted in a 5-10% performace loss
|
||||
do a switch from gettimeofday() to clock_gettime() which should be rather
|
||||
three times faster. The reason for this is unknown.
|
||||
- new queue selection algorithm based on 2 core years of queue data
|
||||
analysis. gives a noticable improvement on coverage although the results
|
||||
seem counterintuitive :-)
|
||||
- added AFL_DISABLE_REDUNDANT for huge queues
|
||||
- added `AFL_NO_SYNC` environment variable that does what you think it does
|
||||
- fix AFL_PERSISTENT_RECORD
|
||||
- run custom_post_process after standard trimming
|
||||
- prevent filenames in the queue that have spaces
|
||||
- minor fix for FAST schedules
|
||||
- more frequent stats update when syncing (todo: check performance impact)
|
||||
- now timing of calibration, trimming and syncing is measured seperately,
|
||||
thanks to @eqv!
|
||||
- -V timing is now accurately the fuzz time (without syncing), before
|
||||
long calibration times and syncing could result in now fuzzing being
|
||||
made when the time was already run out until then, thanks to @eqv!
|
||||
- fix -n uninstrumented mode when ending fuzzing
|
||||
- enhanced the ASAN configuration
|
||||
- make afl-fuzz use less memory with cmplog and fix a memleak
|
||||
* afl-cc:
|
||||
- re-enable i386 support that was accidently disabled
|
||||
- fixes for LTO and outdated afl-gcc mode for i386
|
||||
- fixes for LTO and outdated afl-gcc mode
|
||||
- fix COMPCOV split compare for old LLVMs
|
||||
- disable xml/curl/g_ string transform functions because we do not check
|
||||
for null pointers ... TODO
|
||||
- ensure shared memory variables are visible in weird build setups
|
||||
- compatability to new LLVM 19 changes
|
||||
* afl-cmin
|
||||
- work with input files that have a space
|
||||
* afl-showmap
|
||||
- fix memory leak on shmem testcase usage (thanks to @ndrewh)
|
||||
- minor fix to collect coverage -C (thanks to @bet4it)
|
||||
* Fixed a shmem mmap bug (that rarely came up on MacOS)
|
||||
* libtokencap: script generate_libtoken_dict.sh added by @a-shvedov
|
||||
* enhanced the ASAN configuration
|
||||
|
||||
|
||||
### Version ++4.20c (release)
|
||||
! A new forkserver communication model is now introduced. afl-fuzz is
|
||||
@ -112,13 +56,12 @@
|
||||
- afl-whatsup:
|
||||
- now also displays current average speed
|
||||
- small bugfixes
|
||||
- custom mutators:
|
||||
- fixes for aflpp custom mutator and standalone tool
|
||||
- important fix to the symcc custom mutator
|
||||
- Fixes for aflpp custom mutator and standalone tool
|
||||
- Minor edits to afl-persistent-config
|
||||
- Prevent temporary files being left behind on aborted afl-whatsup
|
||||
- More CPU benchmarks added to benchmark/
|
||||
|
||||
|
||||
### Version ++4.10c (release)
|
||||
- afl-fuzz:
|
||||
- default power schedule is now EXPLORE, due a fix in fast schedules
|
||||
|
@ -30,9 +30,6 @@ 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,11 +198,6 @@ 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,26 +331,7 @@ mode.
|
||||
the target performs only a few loops, then this will give a small
|
||||
performance boost.
|
||||
|
||||
## 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
|
||||
## 4) 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:
|
||||
@ -387,10 +368,6 @@ 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.
|
||||
|
||||
@ -537,8 +514,6 @@ 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.
|
||||
@ -610,12 +585,9 @@ 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 20 minutes,
|
||||
between fuzzing instances synchronization. Default sync time is 30 minutes,
|
||||
note that time is halved for -M main nodes.
|
||||
|
||||
- `AFL_NO_SYNC` disables any syncing whatsoever and takes priority on all
|
||||
other syncing parameters.
|
||||
|
||||
- Setting `AFL_TARGET_ENV` causes AFL++ to set extra environment variables for
|
||||
the target binary. Example: `AFL_TARGET_ENV="VAR1=1 VAR2='a b c'" afl-fuzz
|
||||
... `. This exists mostly for things like `LD_LIBRARY_PATH` but it would
|
||||
@ -661,7 +633,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.
|
||||
|
||||
## 6) Settings for afl-qemu-trace
|
||||
## 5) Settings for afl-qemu-trace
|
||||
|
||||
The QEMU wrapper used to instrument binary-only code supports several settings:
|
||||
|
||||
@ -733,7 +705,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.
|
||||
|
||||
## 8) Settings for afl-frida-trace
|
||||
## 7) 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
|
||||
@ -823,7 +795,7 @@ support.
|
||||
dump you must set a sufficient timeout (using `-t`) to avoid `afl-fuzz`
|
||||
killing the process whilst it is being dumped.
|
||||
|
||||
## 9) Settings for afl-cmin
|
||||
## 8) Settings for afl-cmin
|
||||
|
||||
The corpus minimization script offers very little customization:
|
||||
|
||||
@ -841,7 +813,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.
|
||||
|
||||
## 10) Settings for afl-tmin
|
||||
## 9) 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
|
||||
@ -852,12 +824,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.
|
||||
|
||||
## 11) Settings for afl-analyze
|
||||
## 10) Settings for afl-analyze
|
||||
|
||||
You can set `AFL_ANALYZE_HEX` to get file offsets printed as hexadecimal instead
|
||||
of decimal.
|
||||
|
||||
## 12) Settings for libdislocator
|
||||
## 11) Settings for libdislocator
|
||||
|
||||
The library honors these environment variables:
|
||||
|
||||
@ -879,12 +851,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.
|
||||
|
||||
## 13) Settings for libtokencap
|
||||
## 11) Settings for libtokencap
|
||||
|
||||
This library accepts `AFL_TOKEN_FILE` to indicate the location to which the
|
||||
discovered tokens should be written.
|
||||
|
||||
## 14) Third-party variables set by afl-fuzz & other tools
|
||||
## 12) 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 if you have many fuzzers and/or many seeds.
|
||||
of the first fuzz by quite a lot of 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,9 +214,6 @@ 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,39 +6,34 @@
|
||||
|
||||
#define UNUSED_PARAMETER(x) (void)(x)
|
||||
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data) {
|
||||
int phdr_callback(struct dl_phdr_info *info, size_t size, void *data)
|
||||
{
|
||||
UNUSED_PARAMETER (size);
|
||||
|
||||
UNUSED_PARAMETER(size);
|
||||
|
||||
ElfW(Addr) *base = data;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
ElfW(Addr) * base = data;
|
||||
|
||||
if (info->dlpi_name[0] == 0) { *base = info->dlpi_addr; }
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char **argv, char **envp) {
|
||||
int main (int argc, char** argv, char** envp) {
|
||||
UNUSED_PARAMETER (argc);
|
||||
|
||||
UNUSED_PARAMETER(argc);
|
||||
ElfW(Addr) base = 0;
|
||||
|
||||
ElfW(Addr) base = 0;
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
|
||||
int persona = personality(ADDR_NO_RANDOMIZE);
|
||||
if (persona == -1) {
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("Failed to set ADDR_NO_RANDOMIZE: %d", errno);
|
||||
return 1;
|
||||
if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
|
||||
|
||||
}
|
||||
dl_iterate_phdr(phdr_callback, &base);
|
||||
|
||||
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;
|
||||
printf("%p\n", (void *)base);
|
||||
if (base == 0) { return 1; }
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -45,7 +45,6 @@
|
||||
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[1];
|
||||
void **arg2 = &esp[2];
|
||||
void *arg1 = esp[0];
|
||||
void **arg2 = &esp[1];
|
||||
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,15 +76,14 @@ 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 {
|
||||
@ -178,10 +177,9 @@ 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
|
||||
@ -195,4 +193,3 @@ int afl_persistent_hook_init(void) {
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
|
@ -22,7 +22,6 @@ 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;
|
||||
|
||||
@ -73,7 +72,5 @@ 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_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);
|
||||
|
||||
}
|
||||
|
||||
if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) {
|
||||
|
||||
asan_storeN(address, asan_ctx->size);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
|
||||
|
@ -449,9 +449,3 @@ void instrument_regs_format(int fd, char *format, ...) {
|
||||
|
||||
}
|
||||
|
||||
void ijon_set(uint32_t edge) {
|
||||
|
||||
__afl_coverage_interesting(1, edge);
|
||||
|
||||
}
|
||||
|
||||
|
@ -818,9 +818,6 @@ 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;
|
||||
@ -832,7 +829,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, instance_name) != 0) {
|
||||
if (g_strcmp0(basename, "default") != 0) {
|
||||
|
||||
g_free(basename);
|
||||
g_free(link);
|
||||
@ -877,7 +874,6 @@ 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) {
|
||||
|
@ -49,23 +49,14 @@ void instrument_cache_init(void) {
|
||||
|
||||
if (setrlimit(RLIMIT_AS, &data_limit) != 0) {
|
||||
|
||||
FWARNF("Failed to setrlimit: %d, you may need root or CAP_SYS_RESOURCE",
|
||||
errno);
|
||||
FFATAL("Failed to setrlimit: %d", errno);
|
||||
|
||||
}
|
||||
|
||||
map_base =
|
||||
gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size,
|
||||
GUM_PAGE_READ | GUM_PAGE_WRITE);
|
||||
if (map_base == MAP_FAILED) {
|
||||
|
||||
FFATAL(
|
||||
"Failed to map segment: %d. This can be caused by failure to setrlimit."
|
||||
"Disabling or reducing the size of the allocation using "
|
||||
"AFL_FRIDA_INST_NO_CACHE or AFL_FRIDA_INST_CACHE_SIZE may help",
|
||||
errno);
|
||||
|
||||
}
|
||||
if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); }
|
||||
|
||||
FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]",
|
||||
GUM_ADDRESS(map_base));
|
||||
|
@ -326,12 +326,6 @@ 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
|
||||
@ -383,4 +377,3 @@ 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,9 +316,3 @@ __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 persistent_loop = NULL;
|
||||
static gpointer saved_lr = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -141,10 +141,17 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
static void instrument_exit(GumArmWriter *cw) {
|
||||
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
@ -152,6 +159,7 @@ static void instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -195,8 +203,7 @@ 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(&persistent_ret));
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
|
||||
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,
|
||||
@ -207,35 +214,65 @@ 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
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* CALL hook (optionally)
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* 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);
|
||||
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_arm_writer_cur(cw);
|
||||
/* loop: */
|
||||
gum_arm_writer_put_label(cw, loop);
|
||||
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
/* call instrument_prologue_func */
|
||||
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); }
|
||||
|
||||
@ -247,8 +284,7 @@ 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(&persistent_loop));
|
||||
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr));
|
||||
|
||||
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 persistent_loop = NULL;
|
||||
static gpointer saved_lr = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -216,10 +216,17 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
static void instrument_exit(GumArm64Writer *cw) {
|
||||
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
@ -227,6 +234,7 @@ static void instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -276,7 +284,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(&persistent_ret));
|
||||
GUM_ADDRESS(&saved_lr));
|
||||
|
||||
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0);
|
||||
|
||||
@ -289,35 +297,65 @@ 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
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* CALL hook (optionally)
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* 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);
|
||||
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_arm64_writer_cur(cw);
|
||||
/* loop: */
|
||||
gum_arm64_writer_put_label(cw, loop);
|
||||
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
/* call instrument_prologue_func */
|
||||
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); }
|
||||
|
||||
@ -330,7 +368,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(&persistent_loop));
|
||||
GUM_ADDRESS(&saved_lr));
|
||||
|
||||
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 persistent_loop = NULL;
|
||||
static gpointer saved_ret = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -162,10 +162,17 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
static void instrument_exit(GumX86Writer *cw) {
|
||||
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
@ -173,6 +180,7 @@ static void instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -182,6 +190,7 @@ 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));
|
||||
@ -226,8 +235,7 @@ 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(&persistent_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_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);
|
||||
@ -244,44 +252,70 @@ 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
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* CALL hook (optionally)
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* 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");
|
||||
|
||||
/*
|
||||
* 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); }
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8);
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_x86_writer_cur(cw);
|
||||
/* loop: */
|
||||
gum_x86_writer_put_label(cw, loop);
|
||||
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
/* call instrument_prologue_func */
|
||||
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) {
|
||||
@ -297,8 +331,7 @@ 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(&persistent_loop));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
|
||||
|
||||
}
|
||||
|
@ -16,7 +16,8 @@ typedef struct {
|
||||
} persistent_ctx_t;
|
||||
|
||||
static persistent_ctx_t saved_regs = {0};
|
||||
static gpointer persistent_loop = NULL;
|
||||
|
||||
static gpointer saved_ret = NULL;
|
||||
|
||||
gboolean persistent_is_supported(void) {
|
||||
|
||||
@ -117,10 +118,18 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
|
||||
|
||||
}
|
||||
|
||||
static void instrument_afl_persistent_loop_func(void) {
|
||||
static void instrument_exit(GumX86Writer *cw) {
|
||||
|
||||
if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
|
||||
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);
|
||||
|
||||
}
|
||||
|
||||
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");
|
||||
@ -128,6 +137,7 @@ static void instrument_afl_persistent_loop_func(void) {
|
||||
}
|
||||
|
||||
*instrument_previous_pc_addr = instrument_hash_zero;
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
@ -135,6 +145,7 @@ 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);
|
||||
|
||||
}
|
||||
|
||||
@ -168,8 +179,7 @@ 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(&persistent_ret));
|
||||
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_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);
|
||||
@ -183,44 +193,68 @@ 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
|
||||
* loop: (Save address of where the eiplogue should jump back to)
|
||||
* SAVE RET
|
||||
* POP RET
|
||||
* loop:
|
||||
* CALL instrument_afl_persistent_loop
|
||||
* CALL hook (optionally)
|
||||
* TEST EAX, EAX
|
||||
* JZ end:
|
||||
* 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");
|
||||
|
||||
/*
|
||||
* 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); }
|
||||
/* Pop the return value */
|
||||
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4);
|
||||
|
||||
/* Save the current context */
|
||||
instrument_persitent_save_regs(cw, &saved_regs);
|
||||
|
||||
/* Store a pointer to where we should return for our next iteration */
|
||||
persistent_loop = gum_x86_writer_cur(cw);
|
||||
/* loop: */
|
||||
gum_x86_writer_put_label(cw, loop);
|
||||
|
||||
/* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
|
||||
/* call instrument_prologue_func */
|
||||
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) {
|
||||
@ -229,12 +263,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
|
||||
|
||||
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
|
||||
|
||||
/* 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_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret));
|
||||
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
|
||||
|
||||
}
|
||||
|
@ -194,23 +194,24 @@ static gboolean print_ranges_callback(const GumRangeDetails *details,
|
||||
|
||||
if (details->file == NULL) {
|
||||
|
||||
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
|
||||
|
||||
} else {
|
||||
|
||||
OKF("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
|
||||
details->file->offset);
|
||||
FVERBOSE("\t0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER
|
||||
"X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
|
||||
details->range->base_address,
|
||||
details->range->base_address + details->range->size,
|
||||
details->protection & GUM_PAGE_READ ? 'R' : '-',
|
||||
details->protection & GUM_PAGE_WRITE ? 'W' : '-',
|
||||
details->protection & GUM_PAGE_EXECUTE ? 'X' : '-',
|
||||
details->file->path, details->file->offset);
|
||||
|
||||
}
|
||||
|
||||
@ -580,7 +581,7 @@ static GArray *merge_ranges(GArray *a) {
|
||||
|
||||
void ranges_print_debug_maps(void) {
|
||||
|
||||
OKF("Maps");
|
||||
FVERBOSE("Maps");
|
||||
gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL);
|
||||
|
||||
}
|
||||
|
@ -110,11 +110,7 @@ gboolean util_verbose_enabled(void) {
|
||||
if (!initialized) {
|
||||
|
||||
initialized = TRUE;
|
||||
if (getenv("AFL_FRIDA_VERBOSE") || getenv("AFL_DEBUG")) {
|
||||
|
||||
util_verbose = TRUE;
|
||||
|
||||
}
|
||||
if (getenv("AFL_FRIDA_VERBOSE") != NULL) { util_verbose = TRUE; }
|
||||
|
||||
}
|
||||
|
||||
|
69
frida_mode/test/cache/cache.c
vendored
69
frida_mode/test/cache/cache.c
vendored
@ -6,45 +6,46 @@
|
||||
|
||||
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,7 +51,6 @@ int run(char *file) {
|
||||
|
||||
fd = open(file, O_RDONLY);
|
||||
if (fd < 0) {
|
||||
|
||||
perror("open");
|
||||
break;
|
||||
|
||||
@ -111,10 +110,8 @@ 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,40 +19,32 @@
|
||||
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);
|
||||
|
||||
@ -60,43 +52,33 @@ 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);
|
||||
@ -113,6 +95,4 @@ int main(int argc, char **argv) {
|
||||
if (fd != -1) { close(fd); }
|
||||
|
||||
return result;
|
||||
|
||||
}
|
||||
|
||||
|
@ -1,7 +1,6 @@
|
||||
#include <stdio.h>
|
||||
|
||||
void testinstrlib(char *buf, int len) {
|
||||
|
||||
if (len < 1) return;
|
||||
buf[len] = 0;
|
||||
|
||||
@ -12,6 +11,4 @@ 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
|
||||
};
|
||||
|
||||
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;
|
||||
|
||||
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,13 +83,11 @@ uint32_t 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;
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
@ -99,31 +97,27 @@ 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) {
|
||||
|
||||
@ -133,20 +127,16 @@ 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");
|
||||
|
||||
}
|
||||
@ -155,7 +145,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;
|
||||
|
||||
@ -183,6 +173,5 @@ int main(int argc, char **argv) {
|
||||
printf("Done: %s: (%zd bytes)\n", argv[1], n_read);
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
|
||||
|
@ -4,68 +4,66 @@
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
||||
__attribute__((constructor())) void constructor(void) {
|
||||
__attribute__((constructor()))
|
||||
void constructor(void) {
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
|
||||
if (dylib == NULL)
|
||||
{
|
||||
|
||||
dylib = dlopen("./libcrashme.dylib", RTLD_NOW);
|
||||
if (dylib == NULL) {
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
printf("[+] Resolve function\n");
|
||||
|
||||
printf("[+] Resolve function\n");
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme)
|
||||
{
|
||||
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme) {
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
|
@ -4,68 +4,66 @@
|
||||
#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);
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
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;
|
||||
}
|
||||
|
||||
__attribute__((constructor())) void constructor(void) {
|
||||
__attribute__((constructor()))
|
||||
void constructor(void) {
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
|
||||
// handles to required libs
|
||||
void *dylib = NULL;
|
||||
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
|
||||
if (dylib == NULL)
|
||||
{
|
||||
|
||||
dylib = dlopen("./libcrashme2.dylib", RTLD_NOW);
|
||||
if (dylib == NULL) {
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
|
||||
printf("[-] Failed to load lib\n");
|
||||
printf("[-] Dlerror: %s\n", dlerror());
|
||||
exit(1);
|
||||
}
|
||||
|
||||
}
|
||||
printf("[+] Resolve function\n");
|
||||
|
||||
printf("[+] Resolve function\n");
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme)
|
||||
{
|
||||
|
||||
fpn_crashme = (CRASHME)dlsym(dylib, "crashme");
|
||||
if (!fpn_crashme) {
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
printf("[-] Failed to find function\n");
|
||||
exit(1);
|
||||
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
printf("[+] Found function.\n");
|
||||
}
|
||||
|
||||
|
@ -4,42 +4,37 @@
|
||||
#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);
|
||||
|
||||
return 0;
|
||||
run(argc, argv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (Size < 5) return;
|
||||
@ -12,5 +13,5 @@ void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
if (Data[3] == '$')
|
||||
if (Data[4] == '$') abort();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -3,6 +3,7 @@
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
|
||||
void __attribute__((noinline)) crashme(const uint8_t *Data, size_t Size) {
|
||||
|
||||
if (Size < 1) return;
|
||||
@ -55,5 +56,6 @@ 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,32 +20,22 @@ 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++" PNG_ARCH="arm" make $(TEST_BIN)
|
||||
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN)
|
||||
|
||||
$(BUILD_DIR):
|
||||
mkdir -p $@
|
||||
@ -93,7 +93,8 @@ $(LIBZ_PC): | $(LIBZ_DIR)
|
||||
cd $(LIBZ_DIR) && \
|
||||
CFLAGS="$(CFLAGS) -fPIC" \
|
||||
./configure \
|
||||
--static
|
||||
--static \
|
||||
--archs="$(ARCH)"
|
||||
|
||||
$(LIBZ_LIB): | $(LIBZ_PC)
|
||||
CFLAGS="$(CFLAGS) -fPIC" \
|
||||
@ -119,7 +120,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
|
||||
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
|
||||
LDFLAGS="-L$(LIBZ_DIR)" \
|
||||
./configure \
|
||||
--host="$(PNG_ARCH)"
|
||||
--host="$(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,13 +30,9 @@ 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
|
||||
@ -49,33 +45,26 @@ 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,7 +42,6 @@
|
||||
#include "debug.h"
|
||||
#include "alloc-inl.h"
|
||||
#include "hash.h"
|
||||
#include "valueprofile.h"
|
||||
#include "sharedmem.h"
|
||||
#include "forkserver.h"
|
||||
#include "common.h"
|
||||
@ -117,10 +116,6 @@
|
||||
#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
|
||||
@ -144,10 +139,6 @@
|
||||
#define AFL_RAND_RETURN u32
|
||||
#endif
|
||||
|
||||
#ifndef INTERESTING_32_LEN
|
||||
#error INTERESTING_32_LEN not defined - BUG!
|
||||
#endif
|
||||
|
||||
extern s8 interesting_8[INTERESTING_8_LEN];
|
||||
extern s16 interesting_16[INTERESTING_8_LEN + INTERESTING_16_LEN];
|
||||
extern s32
|
||||
@ -209,10 +200,10 @@ struct queue_entry {
|
||||
u8 *fname; /* File name for the test case */
|
||||
u32 len; /* Input length */
|
||||
u32 id; /* entry number in queue_buf */
|
||||
u32 found;
|
||||
|
||||
u8 colorized, /* Do not run redqueen stage again */
|
||||
cal_failed, /* Calibration failed? */
|
||||
really_interesting; /* really has coverage (VP) */
|
||||
cal_failed; /* Calibration failed? */
|
||||
|
||||
bool trim_done, /* Trimmed? */
|
||||
was_fuzzed, /* historical, but needed for MOpt */
|
||||
@ -242,6 +233,7 @@ 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
|
||||
@ -251,13 +243,18 @@ struct queue_entry {
|
||||
double perf_score, /* performance score */
|
||||
weight;
|
||||
|
||||
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 */
|
||||
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 skipdet_entry *skipdet_e;
|
||||
|
||||
u32 score; /* complexity/vulnerability score */
|
||||
u64 total_execs; /* total executes of this item */
|
||||
|
||||
};
|
||||
|
||||
struct extra_data {
|
||||
@ -451,9 +448,8 @@ 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_custom_mutator_late_send, 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_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,
|
||||
@ -461,7 +457,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_no_fastresume;
|
||||
afl_sha1_filenames;
|
||||
|
||||
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
|
||||
*afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
|
||||
@ -660,7 +656,6 @@ typedef struct afl_state {
|
||||
switch_fuzz_mode, /* auto or fixed fuzz mode */
|
||||
calibration_time_us, /* Time spend on calibration */
|
||||
sync_time_us, /* Time spend on sync */
|
||||
cmplog_time_us, /* Time spend on cmplog */
|
||||
trim_time_us; /* Time spend on trimming */
|
||||
|
||||
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
|
||||
@ -841,6 +836,9 @@ typedef struct afl_state {
|
||||
/* How often did we evict from the cache (for statistics only) */
|
||||
u32 q_testcase_evictions;
|
||||
|
||||
/* current complexity/vulnerability score received */
|
||||
u32 current_score;
|
||||
|
||||
/* Refs to each queue entry with cached testcase (for eviction, if cache_count
|
||||
* is too large) */
|
||||
struct queue_entry **q_testcase_cache;
|
||||
@ -857,8 +855,6 @@ typedef struct afl_state {
|
||||
u32 bitsmap_size;
|
||||
#endif
|
||||
|
||||
u32 vp_ptr[VP_MAP_SIZE];
|
||||
|
||||
} afl_state_t;
|
||||
|
||||
struct custom_mutator {
|
||||
@ -1197,7 +1193,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);
|
||||
u8 *describe_op(afl_state_t *, u8, size_t);
|
||||
#endif
|
||||
u8 save_if_interesting(afl_state_t *, void *, u32, u8);
|
||||
u8 has_new_bits(afl_state_t *, u8 *);
|
||||
@ -1233,7 +1229,6 @@ void show_init_stats(afl_state_t *);
|
||||
void update_calibration_time(afl_state_t *afl, u64 *time);
|
||||
void update_trim_time(afl_state_t *afl, u64 *time);
|
||||
void update_sync_time(afl_state_t *afl, u64 *time);
|
||||
void update_cmplog_time(afl_state_t *afl, u64 *time);
|
||||
|
||||
/* StatsD */
|
||||
|
||||
@ -1284,7 +1279,6 @@ void get_core_count(afl_state_t *);
|
||||
void fix_up_sync(afl_state_t *);
|
||||
void check_asan_opts(afl_state_t *);
|
||||
void check_binary(afl_state_t *, u8 *);
|
||||
u64 get_binary_hash(u8 *fn);
|
||||
void check_if_tty(afl_state_t *);
|
||||
void save_cmdline(afl_state_t *, u32, char **);
|
||||
void read_foreign_testcases(afl_state_t *, int);
|
||||
|
@ -33,10 +33,6 @@
|
||||
|
||||
#define MUT_STRATEGY_ARRAY_SIZE 256
|
||||
|
||||
#ifndef INTERESTING_32
|
||||
#error INTERESTING_32 is not defined - BUG!
|
||||
#endif
|
||||
|
||||
s8 interesting_8[] = {INTERESTING_8};
|
||||
s16 interesting_16[] = {INTERESTING_8, INTERESTING_16};
|
||||
s32 interesting_32[] = {INTERESTING_8, INTERESTING_16, INTERESTING_32};
|
||||
|
@ -53,24 +53,21 @@ struct cmp_header { // 16 bit = 2 bytes
|
||||
struct cmp_operands {
|
||||
|
||||
u64 v0;
|
||||
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 v0_128;
|
||||
u64 v1_128;
|
||||
u64 v1_256_0;
|
||||
u64 v1_256_1;
|
||||
u8 unused[8];
|
||||
u64 unused;
|
||||
u8 unused1;
|
||||
u8 unused2;
|
||||
|
||||
} __attribute__((packed));
|
||||
|
||||
struct cmpfn_operands {
|
||||
|
||||
u8 v0[32];
|
||||
u8 v1[32];
|
||||
u8 v0_len;
|
||||
u8 v1[32];
|
||||
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.22a"
|
||||
#define VERSION "++4.21a"
|
||||
|
||||
/******************************************************
|
||||
* *
|
||||
@ -324,9 +324,9 @@
|
||||
#define SYNC_INTERVAL 8
|
||||
|
||||
/* Sync time (minimum time between syncing in ms, time is halfed for -M main
|
||||
nodes) - default is 20 minutes: */
|
||||
nodes) - default is 30 minutes: */
|
||||
|
||||
#define SYNC_TIME (20 * 60 * 1000)
|
||||
#define SYNC_TIME (30 * 60 * 1000)
|
||||
|
||||
/* Output directory reuse grace period (minutes): */
|
||||
|
||||
|
@ -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)); \
|
||||
|
@ -21,10 +21,11 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_BENCH_UNTIL_CRASH", "AFL_CAL_FAST", "AFL_CC", "AFL_CC_COMPILER",
|
||||
"AFL_CMIN_ALLOW_ANY", "AFL_CMIN_CRASHES_ONLY", "AFL_CMPLOG_ONLY_NEW",
|
||||
"AFL_CODE_END", "AFL_CODE_START", "AFL_COMPCOV_BINNAME",
|
||||
"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_MUTATOR_LATE_SEND", "AFL_CUSTOM_INFO_PROGRAM",
|
||||
"AFL_DUMP_QUEUE_ON_EXIT", "AFL_DUMP_CYCLOMATIC_COMPLEXITY",
|
||||
"AFL_DUMP_VULNERABILITY_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",
|
||||
@ -40,7 +41,8 @@ static char *afl_environment_variables[] = {
|
||||
"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 +51,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_OLD_FORKSERVER",
|
||||
"AFL_FRIDA_VERBOSE",
|
||||
"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,8 +66,7 @@ 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_LLVM_VALUEPROFILE", "AFL_LLVM_VALUE_PROFILE", "AFL_GCC_CMPLOG",
|
||||
"AFL_LLVM_INSTRIM", "AFL_LLVM_CALLER", "AFL_LLVM_CTX",
|
||||
"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",
|
||||
@ -82,13 +83,14 @@ static char *afl_environment_variables[] = {
|
||||
"AFL_LLVM_MAP_DYNAMIC", "AFL_LLVM_NGRAM_SIZE", "AFL_NGRAM_SIZE",
|
||||
"AFL_LLVM_NO_RPATH", "AFL_LLVM_NOT_ZERO", "AFL_LLVM_INSTRUMENT_FILE",
|
||||
"AFL_LLVM_THREADSAFE_INST", "AFL_LLVM_SKIP_NEVERZERO", "AFL_NO_AFFINITY",
|
||||
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID", "AFL_LLVM_LTO_SKIPINIT",
|
||||
"AFL_LLVM_LTO_STARTID", "AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH",
|
||||
"AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
|
||||
"AFL_TRY_AFFINITY", "AFL_LLVM_LTO_DONTWRITEID",
|
||||
"AFL_LLVM_LTO_SKIPINIT"
|
||||
"AFL_LLVM_LTO_STARTID",
|
||||
"AFL_FUZZER_LOOPCOUNT", "AFL_NO_ARITH", "AFL_NO_AUTODICT", "AFL_NO_BUILTIN",
|
||||
#if defined USE_COLOR && !defined ALWAYS_COLORED
|
||||
"AFL_NO_COLOR", "AFL_NO_COLOUR",
|
||||
#endif
|
||||
"AFL_NO_CPU_RED", "AFL_NO_SYNC",
|
||||
"AFL_NO_CPU_RED",
|
||||
"AFL_NO_CFG_FUZZING", // afl.rs rust crate option
|
||||
"AFL_NO_CRASH_README", "AFL_NO_FORKSRV", "AFL_NO_UI", "AFL_NO_PYTHON",
|
||||
"AFL_NO_STARTUP_CALIBRATION", "AFL_NO_WARN_INSTABILITY",
|
||||
@ -116,8 +118,7 @@ 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",
|
||||
"AFL_NO_FASTRESUME", NULL
|
||||
"AFL_USE_QASAN", "AFL_PRINT_FILENAMES", "AFL_PIZZA_MODE", NULL
|
||||
|
||||
};
|
||||
|
||||
|
@ -32,7 +32,6 @@
|
||||
#include <stdbool.h>
|
||||
|
||||
#include "types.h"
|
||||
#include "valueprofile.h"
|
||||
|
||||
#ifdef __linux__
|
||||
/**
|
||||
@ -90,14 +89,11 @@ 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 {
|
||||
@ -183,8 +179,7 @@ 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 */
|
||||
u32 *vp_map_control;
|
||||
u8 *afl_ptr; /* for autodictionary: afl ptr */
|
||||
|
||||
void (*add_extra_func)(void *afl_ptr, u8 *mem, u32 len);
|
||||
|
||||
@ -209,18 +204,8 @@ 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 {
|
||||
@ -247,10 +232,6 @@ 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,9 +52,7 @@ 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,10 +455,9 @@ 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( \
|
||||
@ -478,10 +477,9 @@ 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 */
|
||||
@ -498,24 +496,21 @@ 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]; \
|
||||
\
|
||||
|
@ -1,60 +0,0 @@
|
||||
/*
|
||||
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,14 +6616,12 @@ 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,11 +50,7 @@
|
||||
#include "llvm/Support/SpecialCaseList.h"
|
||||
#include "llvm/Support/VirtualFileSystem.h"
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#if LLVM_VERSION_MAJOR < 20
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#else
|
||||
#include "llvm/Transforms/Utils/Instrumentation.h"
|
||||
#endif
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#endif
|
||||
@ -64,6 +60,8 @@
|
||||
#include "llvm/Passes/PassPlugin.h"
|
||||
#include "llvm/Passes/PassBuilder.h"
|
||||
#include "llvm/IR/PassManager.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
@ -176,6 +174,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
|
||||
|
||||
}
|
||||
|
||||
using LoopInfoCallback = function_ref<const LoopInfo *(Function &F)>;
|
||||
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
|
||||
using PostDomTreeCallback =
|
||||
function_ref<const PostDominatorTree *(Function &F)>;
|
||||
@ -191,13 +190,15 @@ class ModuleSanitizerCoverageLTO
|
||||
}
|
||||
|
||||
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
|
||||
PostDomTreeCallback PDTCallback);
|
||||
PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback);
|
||||
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
|
||||
|
||||
private:
|
||||
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
|
||||
PostDomTreeCallback PDTCallback);
|
||||
PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback);
|
||||
/* void InjectCoverageForIndirectCalls(Function &F,
|
||||
ArrayRef<Instruction *>
|
||||
IndirCalls);*/
|
||||
@ -218,12 +219,8 @@ 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
|
||||
|
||||
}
|
||||
|
||||
@ -233,7 +230,7 @@ class ModuleSanitizerCoverageLTO
|
||||
FunctionCallee SanCovTracePCIndir;
|
||||
FunctionCallee SanCovTracePC /*, SanCovTracePCGuard*/;
|
||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
|
||||
Module *CurModule;
|
||||
std::string CurModuleUniqueId;
|
||||
Triple TargetTriple;
|
||||
@ -258,6 +255,7 @@ class ModuleSanitizerCoverageLTO
|
||||
uint32_t afl_global_id = 0;
|
||||
uint32_t unhandled = 0;
|
||||
uint32_t select_cnt = 0;
|
||||
uint32_t dump_cc = 0, dump_vc = 0;
|
||||
uint32_t instrument_ctx = 0;
|
||||
uint32_t instrument_ctx_max_depth = 0;
|
||||
uint32_t extra_ctx_inst = 0;
|
||||
@ -299,6 +297,7 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
|
||||
|
||||
AU.addRequired<DominatorTreeWrapperPass>();
|
||||
AU.addRequired<PostDominatorTreeWrapperPass>();
|
||||
AU.addRequired<LoopInfoWrapperPass>();
|
||||
|
||||
}
|
||||
|
||||
@ -327,7 +326,15 @@ class ModuleSanitizerCoverageLTOLegacyPass : public ModulePass {
|
||||
|
||||
};
|
||||
|
||||
return ModuleSancov.instrumentModule(M, DTCallback, PDTCallback);
|
||||
auto LoopCallback = [this](Function &F) -> const LoopInfo * {
|
||||
|
||||
return &this->getAnalysis<LoopInfoWrapperPass>(F).getLoopInfo();
|
||||
|
||||
};
|
||||
|
||||
ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback);
|
||||
|
||||
return 1;
|
||||
|
||||
}
|
||||
|
||||
@ -380,15 +387,21 @@ PreservedAnalyses ModuleSanitizerCoverageLTO::run(Module &M,
|
||||
|
||||
};
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
||||
return PreservedAnalyses::none();
|
||||
auto LoopCallback = [&FAM](Function &F) -> const LoopInfo * {
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
return &FAM.getResult<LoopAnalysis>(F);
|
||||
|
||||
};
|
||||
|
||||
ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback);
|
||||
|
||||
return PreservedAnalyses::none();
|
||||
|
||||
}
|
||||
|
||||
bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
||||
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback) {
|
||||
|
||||
if (Options.CoverageType == SanitizerCoverageOptions::SCK_None) return false;
|
||||
/*
|
||||
@ -424,7 +437,6 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
Int16Ty = IRB.getInt16Ty();
|
||||
Int8Ty = IRB.getInt8Ty();
|
||||
Int1Ty = IRB.getInt1Ty();
|
||||
PtrTy = PointerType::getUnqual(*C);
|
||||
|
||||
/* AFL++ START */
|
||||
char *ptr;
|
||||
@ -483,6 +495,10 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
|
||||
}
|
||||
|
||||
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
|
||||
|
||||
if (getenv("AFL_DUMP_VULNERABILITY_COMPLEXITY")) { dump_vc = 1; }
|
||||
|
||||
skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
|
||||
use_threadsafe_counters = getenv("AFL_LLVM_THREADSAFE_INST");
|
||||
|
||||
@ -1066,7 +1082,7 @@ bool ModuleSanitizerCoverageLTO::instrumentModule(
|
||||
// M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
|
||||
|
||||
for (auto &F : M)
|
||||
instrumentFunction(F, DTCallback, PDTCallback);
|
||||
instrumentFunction(F, DTCallback, PDTCallback, LCallback);
|
||||
|
||||
// AFL++ START
|
||||
if (dFile.is_open()) dFile.close();
|
||||
@ -1356,10 +1372,11 @@ Function *returnOnlyCaller(Function *F) {
|
||||
}
|
||||
|
||||
void ModuleSanitizerCoverageLTO::instrumentFunction(
|
||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback) {
|
||||
|
||||
if (F.empty()) return;
|
||||
if (F.getName().contains(".module_ctor"))
|
||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
return; // Should not instrument sanitizer init functions.
|
||||
#if LLVM_VERSION_MAJOR >= 18
|
||||
if (F.getName().starts_with("__sanitizer_"))
|
||||
@ -1381,10 +1398,6 @@ 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()))
|
||||
@ -1434,6 +1447,7 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
|
||||
|
||||
const DominatorTree *DT = DTCallback(F);
|
||||
const PostDominatorTree *PDT = PDTCallback(F);
|
||||
const LoopInfo *LI = LCallback(F);
|
||||
bool IsLeafFunc = true;
|
||||
uint32_t skip_next = 0;
|
||||
uint32_t call_counter = 0, call_depth = 0;
|
||||
@ -1968,6 +1982,51 @@ void ModuleSanitizerCoverageLTO::instrumentFunction(
|
||||
|
||||
}
|
||||
|
||||
unsigned int score = 0;
|
||||
|
||||
if (dump_cc) { score += calcCyclomaticComplexity(&F, LI); }
|
||||
if (dump_vc) { score += calcVulnerabilityScore(&F, LI, DT, PDT); }
|
||||
|
||||
if (score) {
|
||||
|
||||
BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
|
||||
IRBuilder<> builder(&*IP);
|
||||
|
||||
// Access the int32 value at u8 offset 1 (unaligned access)
|
||||
LoadInst *MapPtr =
|
||||
builder.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
|
||||
llvm::Value *CastToInt8Ptr =
|
||||
builder.CreateBitCast(MapPtr, llvm::PointerType::get(Int8Ty, 0));
|
||||
llvm::Value *Int32Ptr = builder.CreateGEP(
|
||||
Int8Ty, CastToInt8Ptr, llvm::ConstantInt::get(Int32Ty, 1));
|
||||
llvm::Value *CastToInt32Ptr =
|
||||
builder.CreateBitCast(Int32Ptr, llvm::PointerType::get(Int32Ty, 0));
|
||||
|
||||
// Load the unaligned int32 value
|
||||
llvm::LoadInst *Load = builder.CreateLoad(Int32Ty, CastToInt32Ptr);
|
||||
Load->setAlignment(llvm::Align(1));
|
||||
|
||||
// Value to add
|
||||
llvm::Value *ValueToAdd = llvm::ConstantInt::get(Int32Ty, score);
|
||||
|
||||
// Perform addition and check for wrap around
|
||||
llvm::Value *Add =
|
||||
builder.CreateAdd(Load, ValueToAdd, "addValue", true, true);
|
||||
|
||||
// Check if addition wrapped (unsigned)
|
||||
llvm::Value *DidWrap = builder.CreateICmpULT(Add, Load, "didWrap");
|
||||
|
||||
// Select the maximum value if there was a wrap, otherwise use the result
|
||||
llvm::Value *MaxInt32 = llvm::ConstantInt::get(Int32Ty, UINT32_MAX);
|
||||
llvm::Value *Result =
|
||||
builder.CreateSelect(DidWrap, MaxInt32, Add, "selectMaxOrResult");
|
||||
|
||||
// Store the result back at the same unaligned offset
|
||||
llvm::StoreInst *Store = builder.CreateStore(Result, CastToInt32Ptr);
|
||||
Store->setAlignment(llvm::Align(1));
|
||||
|
||||
}
|
||||
|
||||
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
|
||||
// InjectCoverageForIndirectCalls(F, IndirCalls);
|
||||
|
||||
@ -2036,20 +2095,16 @@ GlobalVariable *ModuleSanitizerCoverageLTO::CreatePCArray(
|
||||
|
||||
if (&F.getEntryBlock() == AllBlocks[i]) {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
|
||||
PCs.push_back(
|
||||
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
|
||||
|
||||
} else {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(
|
||||
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
|
||||
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
|
||||
|
||||
}
|
||||
|
||||
|
@ -63,18 +63,15 @@
|
||||
#if LLVM_VERSION_MAJOR < 15
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR < 20
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#else
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#endif
|
||||
#if LLVM_VERSION_MAJOR < 17
|
||||
#include "llvm/Transforms/Instrumentation.h"
|
||||
#else
|
||||
#include "llvm/Transforms/Utils/Instrumentation.h"
|
||||
#include "llvm/TargetParser/Triple.h"
|
||||
#endif
|
||||
|
||||
#include "llvm/Transforms/Utils/BasicBlockUtils.h"
|
||||
#include "llvm/Transforms/Utils/ModuleUtils.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
|
||||
#include "config.h"
|
||||
#include "debug.h"
|
||||
@ -124,6 +121,7 @@ SanitizerCoverageOptions OverrideFromCL(SanitizerCoverageOptions Options) {
|
||||
|
||||
}
|
||||
|
||||
using LoopInfoCallback = function_ref<const LoopInfo *(Function &F)>;
|
||||
using DomTreeCallback = function_ref<const DominatorTree *(Function &F)>;
|
||||
using PostDomTreeCallback =
|
||||
function_ref<const PostDominatorTree *(Function &F)>;
|
||||
@ -140,11 +138,13 @@ class ModuleSanitizerCoverageAFL
|
||||
|
||||
PreservedAnalyses run(Module &M, ModuleAnalysisManager &MAM);
|
||||
bool instrumentModule(Module &M, DomTreeCallback DTCallback,
|
||||
PostDomTreeCallback PDTCallback);
|
||||
PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback);
|
||||
|
||||
private:
|
||||
void instrumentFunction(Function &F, DomTreeCallback DTCallback,
|
||||
PostDomTreeCallback PDTCallback);
|
||||
PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback);
|
||||
void InjectTraceForCmp(Function &F, ArrayRef<Instruction *> CmpTraceTargets);
|
||||
void InjectTraceForSwitch(Function &F,
|
||||
ArrayRef<Instruction *> SwitchTraceTargets);
|
||||
@ -166,9 +166,7 @@ class ModuleSanitizerCoverageAFL
|
||||
|
||||
void SetNoSanitizeMetadata(Instruction *I) {
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
I->setNoSanitizeMetadata();
|
||||
#elif LLVM_VERSION_MAJOR >= 16
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
I->setMetadata(LLVMContext::MD_nosanitize, MDNode::get(*C, std::nullopt));
|
||||
#else
|
||||
I->setMetadata(I->getModule()->getMDKindID("nosanitize"),
|
||||
@ -186,7 +184,7 @@ class ModuleSanitizerCoverageAFL
|
||||
FunctionCallee SanCovTraceSwitchFunction;
|
||||
GlobalVariable *SanCovLowestStack;
|
||||
Type *IntptrTy, *IntptrPtrTy, *Int64Ty, *Int64PtrTy, *Int32Ty, *Int32PtrTy,
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy, *PtrTy;
|
||||
*Int16Ty, *Int8Ty, *Int8PtrTy, *Int1Ty, *Int1PtrTy;
|
||||
Module *CurModule;
|
||||
std::string CurModuleUniqueId;
|
||||
Triple TargetTriple;
|
||||
@ -202,7 +200,7 @@ class ModuleSanitizerCoverageAFL
|
||||
|
||||
SanitizerCoverageOptions Options;
|
||||
|
||||
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0;
|
||||
uint32_t instr = 0, selects = 0, unhandled = 0, dump_cc = 0, dump_vc = 0;
|
||||
GlobalVariable *AFLMapPtr = NULL;
|
||||
ConstantInt *One = NULL;
|
||||
ConstantInt *Zero = NULL;
|
||||
@ -240,8 +238,10 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
|
||||
ModuleAnalysisManager &MAM) {
|
||||
|
||||
ModuleSanitizerCoverageAFL ModuleSancov(Options);
|
||||
|
||||
auto &FAM = MAM.getResult<FunctionAnalysisManagerModuleProxy>(M).getManager();
|
||||
auto DTCallback = [&FAM](Function &F) -> const DominatorTree *{
|
||||
|
||||
auto DTCallback = [&FAM](Function &F) -> const DominatorTree * {
|
||||
|
||||
return &FAM.getResult<DominatorTreeAnalysis>(F);
|
||||
|
||||
@ -253,9 +253,21 @@ PreservedAnalyses ModuleSanitizerCoverageAFL::run(Module &M,
|
||||
|
||||
};
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback))
|
||||
auto LoopCallback = [&FAM](Function &F) -> const LoopInfo * {
|
||||
|
||||
return &FAM.getResult<LoopAnalysis>(F);
|
||||
|
||||
};
|
||||
|
||||
if (ModuleSancov.instrumentModule(M, DTCallback, PDTCallback, LoopCallback)) {
|
||||
|
||||
return PreservedAnalyses::none();
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
} else {
|
||||
|
||||
return PreservedAnalyses::all();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@ -279,19 +291,13 @@ 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.
|
||||
#if LLVM_VERSION_MAJOR >= 19
|
||||
auto GEP =
|
||||
IRB.CreatePtrAdd(SecStart, ConstantInt::get(IntptrTy, sizeof(uint64_t)));
|
||||
return std::make_pair(GEP, SecEnd);
|
||||
#else
|
||||
// Account for the fact that on windows-msvc __start_* symbols actually
|
||||
// point to a uint64_t before the start of the array.
|
||||
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
|
||||
|
||||
}
|
||||
|
||||
@ -337,7 +343,8 @@ Function *ModuleSanitizerCoverageAFL::CreateInitCallsForSections(
|
||||
}
|
||||
|
||||
bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
||||
Module &M, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback) {
|
||||
|
||||
setvbuf(stdout, NULL, _IONBF, 0);
|
||||
|
||||
@ -345,6 +352,8 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||
|
||||
if (getenv("AFL_DUMP_CYCLOMATIC_COMPLEXITY")) { dump_cc = 1; }
|
||||
|
||||
if (getenv("AFL_DUMP_VULNERABILITY_COMPLEXITY")) { dump_vc = 1; }
|
||||
|
||||
if ((isatty(2) && !getenv("AFL_QUIET")) || debug) {
|
||||
|
||||
SAYF(cCYA "SanitizerCoveragePCGUARD" VERSION cRST "\n");
|
||||
@ -383,7 +392,6 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||
Int16Ty = IRB.getInt16Ty();
|
||||
Int8Ty = IRB.getInt8Ty();
|
||||
Int1Ty = IRB.getInt1Ty();
|
||||
PtrTy = PointerType::getUnqual(*C);
|
||||
|
||||
LLVMContext &Ctx = M.getContext();
|
||||
AFLMapPtr =
|
||||
@ -443,7 +451,7 @@ bool ModuleSanitizerCoverageAFL::instrumentModule(
|
||||
M.getOrInsertFunction(SanCovTracePCGuardName, VoidTy, Int32PtrTy);
|
||||
|
||||
for (auto &F : M)
|
||||
instrumentFunction(F, DTCallback, PDTCallback);
|
||||
instrumentFunction(F, DTCallback, PDTCallback, LCallback);
|
||||
|
||||
Function *Ctor = nullptr;
|
||||
|
||||
@ -582,12 +590,12 @@ static bool IsInterestingCmp(ICmpInst *CMP, const DominatorTree *DT,
|
||||
#endif
|
||||
|
||||
void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback) {
|
||||
Function &F, DomTreeCallback DTCallback, PostDomTreeCallback PDTCallback,
|
||||
LoopInfoCallback LCallback) {
|
||||
|
||||
if (F.empty()) return;
|
||||
if (!isInInstrumentList(&F, FMNAME)) return;
|
||||
// if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
if (F.getName().contains(".module_ctor"))
|
||||
if (F.getName().find(".module_ctor") != std::string::npos)
|
||||
return; // Should not instrument sanitizer init functions.
|
||||
#if LLVM_VERSION_MAJOR >= 18
|
||||
if (F.getName().starts_with("__sanitizer_"))
|
||||
@ -610,9 +618,6 @@ 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());
|
||||
@ -622,6 +627,7 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||
|
||||
const DominatorTree *DT = DTCallback(F);
|
||||
const PostDominatorTree *PDT = PDTCallback(F);
|
||||
const LoopInfo *LI = LCallback(F);
|
||||
bool IsLeafFunc = true;
|
||||
|
||||
for (auto &BB : F) {
|
||||
@ -654,12 +660,55 @@ void ModuleSanitizerCoverageAFL::instrumentFunction(
|
||||
|
||||
}
|
||||
|
||||
unsigned int score = 0;
|
||||
|
||||
if (dump_cc) { score += calcCyclomaticComplexity(&F, LI); }
|
||||
if (dump_vc) { score += calcVulnerabilityScore(&F, LI, DT, PDT); }
|
||||
|
||||
if (score) {
|
||||
|
||||
BasicBlock::iterator IP = F.getEntryBlock().getFirstInsertionPt();
|
||||
IRBuilder<> builder(&*IP);
|
||||
|
||||
// Access the int32 value at u8 offset 1 (unaligned access)
|
||||
LoadInst *MapPtr =
|
||||
builder.CreateLoad(PointerType::get(Int8Ty, 0), AFLMapPtr);
|
||||
llvm::Value *CastToInt8Ptr =
|
||||
builder.CreateBitCast(MapPtr, llvm::PointerType::get(Int8Ty, 0));
|
||||
llvm::Value *Int32Ptr = builder.CreateGEP(
|
||||
Int8Ty, CastToInt8Ptr, llvm::ConstantInt::get(Int32Ty, 1));
|
||||
llvm::Value *CastToInt32Ptr =
|
||||
builder.CreateBitCast(Int32Ptr, llvm::PointerType::get(Int32Ty, 0));
|
||||
|
||||
// Load the unaligned int32 value
|
||||
llvm::LoadInst *Load = builder.CreateLoad(Int32Ty, CastToInt32Ptr);
|
||||
Load->setAlignment(llvm::Align(1));
|
||||
|
||||
// Value to add
|
||||
llvm::Value *ValueToAdd = llvm::ConstantInt::get(Int32Ty, score);
|
||||
|
||||
// Perform addition and check for wrap around
|
||||
llvm::Value *Add =
|
||||
builder.CreateAdd(Load, ValueToAdd, "addValue", true, true);
|
||||
|
||||
// Check if addition wrapped (unsigned)
|
||||
llvm::Value *DidWrap = builder.CreateICmpULT(Add, Load, "didWrap");
|
||||
|
||||
// Select the maximum value if there was a wrap, otherwise use the result
|
||||
llvm::Value *MaxInt32 = llvm::ConstantInt::get(Int32Ty, UINT32_MAX);
|
||||
llvm::Value *Result =
|
||||
builder.CreateSelect(DidWrap, MaxInt32, Add, "selectMaxOrResult");
|
||||
|
||||
// Store the result back at the same unaligned offset
|
||||
llvm::StoreInst *Store = builder.CreateStore(Result, CastToInt32Ptr);
|
||||
Store->setAlignment(llvm::Align(1));
|
||||
|
||||
}
|
||||
|
||||
InjectCoverage(F, BlocksToInstrument, IsLeafFunc);
|
||||
// InjectTraceForCmp(F, CmpTraceTargets);
|
||||
// InjectTraceForSwitch(F, SwitchTraceTargets);
|
||||
|
||||
if (dump_cc) { calcCyclomaticComplexity(&F); }
|
||||
|
||||
}
|
||||
|
||||
GlobalVariable *ModuleSanitizerCoverageAFL::CreateFunctionLocalArrayInSection(
|
||||
@ -710,16 +759,16 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
|
||||
|
||||
if (&F.getEntryBlock() == AllBlocks[i]) {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, PtrTy));
|
||||
PCs.push_back(
|
||||
(Constant *)IRB.CreateIntToPtr(ConstantInt::get(IntptrTy, 1), PtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(&F, IntptrPtrTy));
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 1), IntptrPtrTy));
|
||||
|
||||
} else {
|
||||
|
||||
PCs.push_back((Constant *)IRB.CreatePointerCast(
|
||||
BlockAddress::get(AllBlocks[i]), PtrTy));
|
||||
BlockAddress::get(AllBlocks[i]), IntptrPtrTy));
|
||||
#if LLVM_VERSION_MAJOR >= 16
|
||||
PCs.push_back(Constant::getNullValue(PtrTy));
|
||||
PCs.push_back(Constant::getNullValue(IntptrPtrTy));
|
||||
#else
|
||||
PCs.push_back((Constant *)IRB.CreateIntToPtr(
|
||||
ConstantInt::get(IntptrTy, 0), IntptrPtrTy));
|
||||
@ -729,10 +778,10 @@ GlobalVariable *ModuleSanitizerCoverageAFL::CreatePCArray(
|
||||
|
||||
}
|
||||
|
||||
auto *PCArray =
|
||||
CreateFunctionLocalArrayInSection(N * 2, F, PtrTy, SanCovPCsSectionName);
|
||||
auto *PCArray = CreateFunctionLocalArrayInSection(N * 2, F, IntptrPtrTy,
|
||||
SanCovPCsSectionName);
|
||||
PCArray->setInitializer(
|
||||
ConstantArray::get(ArrayType::get(PtrTy, N * 2), PCs));
|
||||
ConstantArray::get(ArrayType::get(IntptrPtrTy, N * 2), PCs));
|
||||
PCArray->setConstant(true);
|
||||
|
||||
return PCArray;
|
||||
@ -840,12 +889,7 @@ 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
@ -14,7 +14,21 @@
|
||||
#include <fstream>
|
||||
#include <cmath>
|
||||
|
||||
#include <llvm/Support/raw_ostream.h>
|
||||
#if LLVM_VERSION_MAJOR >= 13
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/IR/Module.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#endif
|
||||
|
||||
// #define LEOPARD_USE_WEIGHTS 1
|
||||
|
||||
#define IS_EXTERN extern
|
||||
#include "afl-llvm-common.h"
|
||||
@ -26,11 +40,79 @@ static std::list<std::string> allowListFunctions;
|
||||
static std::list<std::string> denyListFiles;
|
||||
static std::list<std::string> denyListFunctions;
|
||||
|
||||
unsigned int calcCyclomaticComplexity(llvm::Function *F) {
|
||||
#if LLVM_VERSION_MAJOR >= 13
|
||||
// Leopard complexity calculations
|
||||
|
||||
#ifndef LEOPARD_USE_WEIGHTS
|
||||
#define C1_WEIGHT 1.0
|
||||
#define C2_WEIGHT 1.0
|
||||
#define C3_WEIGHT 1.0
|
||||
#define C4_WEIGHT 1.0
|
||||
#define V1_WEIGHT 1.0
|
||||
#define V2_WEIGHT 1.0
|
||||
#define V3_WEIGHT 1.0
|
||||
#define V4_WEIGHT 1.0
|
||||
#define V5_WEIGHT 1.0
|
||||
#define V6_WEIGHT 1.0
|
||||
#define V7_WEIGHT 1.0
|
||||
#define V8_WEIGHT 1.0
|
||||
#define V9_WEIGHT 1.0
|
||||
#define V10_WEIGHT 1.0
|
||||
#define V11_WEIGHT 1.0
|
||||
#else
|
||||
// Cyclomatic weights
|
||||
#define C1_WEIGHT 1.0
|
||||
#define C2_WEIGHT 1.0
|
||||
#define C3_WEIGHT 1.0
|
||||
#define C4_WEIGHT 1.0
|
||||
|
||||
// Vulnerability weights
|
||||
#define V1_WEIGHT 1.5
|
||||
#define V2_WEIGHT 3.25
|
||||
#define V3_WEIGHT 4.25
|
||||
#define V4_WEIGHT 3.0
|
||||
#define V5_WEIGHT 4.25
|
||||
#define V6_WEIGHT 7.75
|
||||
#define V7_WEIGHT 2.5
|
||||
#define V8_WEIGHT 2.5
|
||||
#define V9_WEIGHT 4.0
|
||||
#define V10_WEIGHT 5.25
|
||||
#define V11_WEIGHT 3.5
|
||||
#endif
|
||||
|
||||
static void countNestedLoops(Loop *L, int depth, unsigned int &loopCount,
|
||||
unsigned int &nestedLoopCount,
|
||||
unsigned int &maxNestingLevel) {
|
||||
|
||||
loopCount++;
|
||||
if (!L->getSubLoops().empty()) {
|
||||
|
||||
// Increment nested loop count by the number of sub-loops
|
||||
nestedLoopCount += L->getSubLoops().size();
|
||||
// Update maximum nesting level
|
||||
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
|
||||
|
||||
// Recursively count sub-loops
|
||||
for (Loop *SubLoop : L->getSubLoops()) {
|
||||
|
||||
countNestedLoops(SubLoop, depth + 1, loopCount, nestedLoopCount,
|
||||
maxNestingLevel);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
unsigned int calcCyclomaticComplexity(llvm::Function *F,
|
||||
const llvm::LoopInfo *LI) {
|
||||
|
||||
unsigned int numBlocks = 0;
|
||||
unsigned int numEdges = 0;
|
||||
unsigned int numCalls = 0;
|
||||
unsigned int numLoops = 0;
|
||||
unsigned int numNestedLoops = 0;
|
||||
unsigned int maxLoopNesting = 0;
|
||||
|
||||
// Iterate through each basic block in the function
|
||||
for (BasicBlock &BB : *F) {
|
||||
@ -55,22 +137,197 @@ unsigned int calcCyclomaticComplexity(llvm::Function *F) {
|
||||
|
||||
}
|
||||
|
||||
for (Loop *L : *LI) {
|
||||
|
||||
countNestedLoops(L, 1, numLoops, numNestedLoops, maxLoopNesting);
|
||||
|
||||
}
|
||||
|
||||
// Cyclomatic Complexity V(G) = E - N + 2P
|
||||
// For a single function, P (number of connected components) is 1
|
||||
// Calls are considered to be an edge
|
||||
unsigned int CC = 2 + numCalls + numEdges - numBlocks;
|
||||
unsigned int cc =
|
||||
(unsigned int)(C1_WEIGHT * (double)(2 + numCalls + numEdges - numBlocks) +
|
||||
C2_WEIGHT * (double)numLoops +
|
||||
C3_WEIGHT * (double)numNestedLoops +
|
||||
C4_WEIGHT * (double)maxLoopNesting);
|
||||
|
||||
// if (debug) {
|
||||
|
||||
fprintf(stderr, "CyclomaticComplexity for %s: %u\n",
|
||||
F->getName().str().c_str(), CC);
|
||||
fprintf(stderr,
|
||||
"CyclomaticComplexity for %s: %u (calls=%u edges=%u blocks=%u "
|
||||
"loops=%u nested_loops=%u max_loop_nesting_level=%u)\n",
|
||||
F->getName().str().c_str(), cc, numCalls, numEdges, numBlocks,
|
||||
numLoops, numNestedLoops, maxLoopNesting);
|
||||
|
||||
//}
|
||||
|
||||
return CC;
|
||||
return cc;
|
||||
|
||||
}
|
||||
|
||||
unsigned int calcVulnerabilityScore(llvm::Function *F, const llvm::LoopInfo *LI,
|
||||
const llvm::DominatorTree *DT,
|
||||
const llvm::PostDominatorTree *PDT) {
|
||||
|
||||
unsigned int score = 0;
|
||||
// V1 and V2
|
||||
unsigned paramCount = F->arg_size();
|
||||
unsigned calledParamCount = 0;
|
||||
// V3, V4 and V5
|
||||
unsigned pointerArithCount = 0;
|
||||
unsigned totalPointerArithParams = 0;
|
||||
unsigned maxPointerArithVars = 0;
|
||||
// V6 to V11
|
||||
unsigned nestedControlStructCount = 0;
|
||||
unsigned maxNestingLevel = 0;
|
||||
unsigned maxControlDependentControls = 0;
|
||||
unsigned maxDataDependentControls = 0;
|
||||
unsigned ifWithoutElseCount = 0;
|
||||
unsigned controlPredicateVarCount = 0;
|
||||
|
||||
std::function<void(Loop *, unsigned)> countNestedLoops = [&](Loop *L,
|
||||
unsigned depth) {
|
||||
|
||||
nestedControlStructCount++;
|
||||
if (depth > maxNestingLevel) { maxNestingLevel = depth; }
|
||||
for (Loop *SubLoop : L->getSubLoops()) {
|
||||
|
||||
countNestedLoops(SubLoop, depth + 1);
|
||||
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
for (Loop *TopLoop : *LI) {
|
||||
|
||||
countNestedLoops(TopLoop, 1);
|
||||
|
||||
}
|
||||
|
||||
for (inst_iterator I = inst_begin(*F), E = inst_end(*F); I != E; ++I) {
|
||||
|
||||
if (CallInst *CI = dyn_cast<CallInst>(&*I)) {
|
||||
|
||||
if (Function *CalledF = CI->getCalledFunction()) {
|
||||
|
||||
calledParamCount += CalledF->arg_size();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (auto *GEP = dyn_cast<GetElementPtrInst>(&*I)) {
|
||||
|
||||
pointerArithCount++;
|
||||
unsigned numPointerArithVars = GEP->getNumOperands();
|
||||
totalPointerArithParams += numPointerArithVars;
|
||||
if (numPointerArithVars > maxPointerArithVars) {
|
||||
|
||||
maxPointerArithVars = numPointerArithVars;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (BranchInst *BI = dyn_cast<BranchInst>(&*I)) {
|
||||
|
||||
if (BI->isConditional()) {
|
||||
|
||||
unsigned controlDependentCount = 0;
|
||||
unsigned dataDependentCount = 0;
|
||||
for (Use &U : BI->operands()) {
|
||||
|
||||
if (Instruction *Op = dyn_cast<Instruction>(U.get())) {
|
||||
|
||||
if (DT->dominates(Op, &*I)) { controlDependentCount++; }
|
||||
if (PDT->dominates(Op, &*I)) { dataDependentCount++; }
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (controlDependentCount > maxControlDependentControls) {
|
||||
|
||||
maxControlDependentControls = controlDependentCount;
|
||||
|
||||
}
|
||||
|
||||
if (dataDependentCount > maxDataDependentControls) {
|
||||
|
||||
maxDataDependentControls = dataDependentCount;
|
||||
|
||||
}
|
||||
|
||||
// Check for if() without else
|
||||
BasicBlock *TrueBB = BI->getSuccessor(0);
|
||||
BasicBlock *FalseBB = BI->getSuccessor(1);
|
||||
if (TrueBB && FalseBB) {
|
||||
|
||||
if (TrueBB->getSinglePredecessor() == &*I->getParent() &&
|
||||
FalseBB->empty()) {
|
||||
|
||||
ifWithoutElseCount++;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Count variables involved in control predicates
|
||||
if (ICmpInst *ICmp = dyn_cast<ICmpInst>(BI->getCondition())) {
|
||||
|
||||
controlPredicateVarCount += ICmp->getNumOperands();
|
||||
|
||||
} else if (BinaryOperator *BinOp =
|
||||
|
||||
dyn_cast<BinaryOperator>(BI->getCondition())) {
|
||||
|
||||
controlPredicateVarCount += BinOp->getNumOperands();
|
||||
|
||||
} else if (SelectInst *Select =
|
||||
|
||||
dyn_cast<SelectInst>(BI->getCondition())) {
|
||||
|
||||
controlPredicateVarCount += Select->getNumOperands();
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
score = (unsigned int)(V1_WEIGHT * (double)paramCount +
|
||||
V2_WEIGHT * (double)calledParamCount +
|
||||
V3_WEIGHT * (double)pointerArithCount +
|
||||
V4_WEIGHT * (double)totalPointerArithParams +
|
||||
V5_WEIGHT * (double)maxPointerArithVars +
|
||||
V6_WEIGHT * (double)nestedControlStructCount +
|
||||
V7_WEIGHT * (double)maxNestingLevel +
|
||||
V8_WEIGHT * (double)maxControlDependentControls +
|
||||
V9_WEIGHT * (double)maxDataDependentControls +
|
||||
V10_WEIGHT * (double)ifWithoutElseCount +
|
||||
V11_WEIGHT * (double)controlPredicateVarCount);
|
||||
|
||||
fprintf(stderr,
|
||||
"VulnerabilityScore for %s: %u (paramCount=%u "
|
||||
"calledParamCount=%u|pointerArithCount=%u totalPointerArithParams=%u "
|
||||
"maxPointerArithVars=%u|maxNestingLevel=%u "
|
||||
"maxControlDependentControls=%u maxDataDependentControls=%u "
|
||||
"ifWithoutElseCount=%u controlPredicateVarCount=%u)\n",
|
||||
F->getName().str().c_str(), score, paramCount, calledParamCount,
|
||||
pointerArithCount, totalPointerArithParams, maxPointerArithVars,
|
||||
maxNestingLevel, maxControlDependentControls,
|
||||
maxDataDependentControls, ifWithoutElseCount,
|
||||
controlPredicateVarCount);
|
||||
|
||||
return score;
|
||||
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *getBBName(const llvm::BasicBlock *BB) {
|
||||
|
||||
static char *name;
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include <sys/time.h>
|
||||
|
||||
#include "llvm/Config/llvm-config.h"
|
||||
|
||||
#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
|
||||
typedef long double max_align_t;
|
||||
#endif
|
||||
@ -26,6 +27,19 @@ typedef long double max_align_t;
|
||||
#include "llvm/Transforms/IPO/PassManagerBuilder.h"
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 12
|
||||
#include "llvm/Support/raw_ostream.h"
|
||||
#include "llvm/Analysis/LoopInfo.h"
|
||||
#include "llvm/Analysis/LoopPass.h"
|
||||
#include "llvm/IR/Function.h"
|
||||
#include "llvm/Pass.h"
|
||||
#include "llvm/IR/InstIterator.h"
|
||||
#include "llvm/IR/Instructions.h"
|
||||
#include "llvm/IR/Operator.h"
|
||||
#include "llvm/IR/Dominators.h"
|
||||
#include "llvm/Analysis/PostDominators.h"
|
||||
#endif
|
||||
|
||||
#if LLVM_VERSION_MAJOR > 3 || \
|
||||
(LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
|
||||
#include "llvm/IR/DebugInfo.h"
|
||||
@ -55,7 +69,11 @@ void initInstrumentList();
|
||||
bool isInInstrumentList(llvm::Function *F, std::string Filename);
|
||||
unsigned long long int calculateCollisions(uint32_t edges);
|
||||
void scanForDangerousFunctions(llvm::Module *M);
|
||||
unsigned int calcCyclomaticComplexity(llvm::Function *F);
|
||||
unsigned int calcCyclomaticComplexity(llvm::Function *F,
|
||||
const llvm::LoopInfo *LI);
|
||||
unsigned int calcVulnerabilityScore(llvm::Function *F, const llvm::LoopInfo *LI,
|
||||
const llvm::DominatorTree *DT,
|
||||
const llvm::PostDominatorTree *PDT);
|
||||
|
||||
#ifndef IS_EXTERN
|
||||
#define IS_EXTERN
|
||||
|
@ -661,13 +661,6 @@ 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,7 +61,6 @@
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
using namespace llvm;
|
||||
static int vp_mode = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
@ -165,8 +164,6 @@ 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
|
||||
@ -278,119 +275,6 @@ 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) {
|
||||
@ -401,11 +285,7 @@ bool CmpLogInstructions::hookInstrs(Module &M) {
|
||||
|
||||
}
|
||||
|
||||
Value *Null;
|
||||
// if (debug)
|
||||
// Null = AFLCmplogPtr;
|
||||
// else
|
||||
Null = Constant::getNullValue(PointerType::get(Int8Ty, 0));
|
||||
Constant *Null = Constant::getNullValue(PointerType::get(Int8Ty, 0));
|
||||
|
||||
/* iterate over all functions, bbs and instruction and add suitable calls */
|
||||
for (auto &F : M) {
|
||||
@ -702,88 +582,68 @@ 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);
|
||||
ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1);
|
||||
args.push_back(attribute);
|
||||
|
||||
if (is_fp && vp_mode && (cast_size == 32 || cast_size == 64)) {
|
||||
if (cast_size != max_size) {
|
||||
|
||||
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);
|
||||
ConstantInt *bitsize = ConstantInt::get(Int8Ty, (max_size / 8) - 1);
|
||||
args.push_back(bitsize);
|
||||
|
||||
// fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast
|
||||
// %u\n",
|
||||
// max_size, cast_size, attr);
|
||||
}
|
||||
|
||||
switch (cast_size) {
|
||||
// fprintf(stderr, "_ExtInt(%u) castTo %u with attr %u didcast %u\n",
|
||||
// max_size, cast_size, attr);
|
||||
|
||||
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) {
|
||||
switch (cast_size) {
|
||||
|
||||
IRB.CreateCall(cmplogHookIns16, args);
|
||||
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) {
|
||||
|
||||
} else {
|
||||
IRB.CreateCall(cmplogHookIns16, args);
|
||||
|
||||
IRB.CreateCall(cmplogHookInsN, args);
|
||||
} else {
|
||||
|
||||
}
|
||||
IRB.CreateCall(cmplogHookInsN, args);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@ -816,26 +676,9 @@ bool CmpLogInstructions::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL)
|
||||
printf("Running cmplog-instructions-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
be_quiet = 1;
|
||||
bool ret = hookInstrs(M);
|
||||
verifyModule(M);
|
||||
|
@ -59,8 +59,6 @@
|
||||
#include <set>
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
static int vp_mode = 0;
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
@ -290,114 +288,6 @@ 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) {
|
||||
@ -600,39 +490,33 @@ bool CmpLogRoutines::hookRtns(Module &M) {
|
||||
<< " calls with pointers as arguments\n";
|
||||
*/
|
||||
|
||||
// TODO VP
|
||||
if (!vp_mode) {
|
||||
for (auto &callInst : calls) {
|
||||
|
||||
for (auto &callInst : calls) {
|
||||
Value *v1P = callInst->getArgOperand(0), *v2P = callInst->getArgOperand(1);
|
||||
|
||||
Value *v1P = callInst->getArgOperand(0),
|
||||
*v2P = callInst->getArgOperand(1);
|
||||
IRBuilder<> IRB2(callInst->getParent());
|
||||
IRB2.SetInsertPoint(callInst);
|
||||
|
||||
IRBuilder<> IRB2(callInst->getParent());
|
||||
IRB2.SetInsertPoint(callInst);
|
||||
|
||||
LoadInst *CmpPtr = IRB2.CreateLoad(
|
||||
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";
|
||||
|
||||
}
|
||||
|
||||
@ -870,30 +754,10 @@ bool CmpLogRoutines::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
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 {
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL)
|
||||
printf("Running cmplog-routines-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
be_quiet = 1;
|
||||
|
||||
}
|
||||
|
||||
bool ret = hookRtns(M);
|
||||
verifyModule(M);
|
||||
|
||||
|
@ -62,8 +62,6 @@
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
static int vp_mode = 0;
|
||||
|
||||
namespace {
|
||||
|
||||
#if LLVM_VERSION_MAJOR >= 11 /* use new pass manager */
|
||||
@ -233,77 +231,6 @@ 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) {
|
||||
@ -511,21 +438,9 @@ bool CmplogSwitches::runOnModule(Module &M) {
|
||||
|
||||
#endif
|
||||
|
||||
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
|
||||
|
||||
if (getenv("AFL_QUIET") == NULL)
|
||||
printf("Running cmplog-switches-pass by andreafioraldi@gmail.com\n");
|
||||
else
|
||||
be_quiet = 1;
|
||||
bool ret = hookInstrs(M);
|
||||
verifyModule(M);
|
||||
|
@ -54,15 +54,15 @@
|
||||
#define nullptr 0
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
#if LLVM_MAJOR >= 19
|
||||
#define STARTSWITH starts_with
|
||||
#else
|
||||
#define STARTSWITH startswith
|
||||
#endif
|
||||
|
||||
#include <set>
|
||||
#include "afl-llvm-common.h"
|
||||
|
||||
using namespace llvm;
|
||||
|
||||
namespace {
|
||||
|
@ -1 +1 @@
|
||||
ea6ceb9
|
||||
6833d23
|
||||
|
@ -1 +1 @@
|
||||
6067e5c
|
||||
bcf3e24
|
||||
|
Submodule nyx_mode/QEMU-Nyx updated: ff1c897321...e5e1c4c21f
@ -1 +1 @@
|
||||
ff1c897321
|
||||
e5e1c4c21ff9c4dc80e6409d4eab47146c6024cd
|
||||
|
@ -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 libcapstone-dev
|
||||
apt-get install -y libgtk-3-dev pax-utils python3-msgpack python3-jinja2
|
||||
```
|
||||
|
||||
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 (or use `make distrib` at the repo root to build all AFL++ modes):
|
||||
4. Finally build Nyx mode:
|
||||
|
||||
```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 && echo OK || echo KVM module problem
|
||||
cat /sys/module/kvm/parameters/enable_vmware_backdoor | grep -q Y && echi 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. 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":
|
||||
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":
|
||||
|
||||
- `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: ea6ceb994a...6833d236df
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user