diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 00000000..102722a4
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,12 @@
+# These are supported funding model platforms
+
+github: # Replace with up to 4 GitHub Sponsors-enabled usernames e.g., [user1, user2]
+patreon: # Replace with a single Patreon username
+open_collective: AFLplusplusEU
+ko_fi: # Replace with a single Ko-fi username
+tidelift: # Replace with a single Tidelift platform-name/package-name e.g., npm/babel
+community_bridge: # Replace with a single Community Bridge project-name e.g., cloud-foundry
+liberapay: # Replace with a single Liberapay username
+issuehunt: # Replace with a single IssueHunt username
+otechie: # Replace with a single Otechie username
+custom: # Replace with up to 4 custom sponsorship URLs e.g., ['link1', 'link2']
diff --git a/.github/workflows/build_aflplusplus_docker.yaml b/.github/workflows/build_aflplusplus_docker.yaml
index be8d795d..8aa5b8f7 100644
--- a/.github/workflows/build_aflplusplus_docker.yaml
+++ b/.github/workflows/build_aflplusplus_docker.yaml
@@ -1,13 +1,11 @@
name: Publish Docker Images
+
on:
push:
branches: [ stable ]
- paths:
- - Dockerfile
- pull_request:
- branches: [ stable ]
- paths:
- - Dockerfile
+# paths:
+# - Dockerfile
+
jobs:
push_to_registry:
name: Push Docker images to Dockerhub
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 31cfceaf..35051a20 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -16,8 +16,10 @@ jobs:
- uses: actions/checkout@v2
- name: debug
run: apt-cache search plugin-dev | grep gcc- ; echo ; apt-cache search clang-format- | grep clang-format-
+ - name: update
+ run: sudo apt-get update && sudo apt-get upgrade -y
- name: install packages
- run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools
+ run: sudo apt-get install -y -m -f --install-suggests build-essential git libtool libtool-bin automake bison libglib2.0-0 clang llvm-dev libc++-dev findutils libcmocka-dev python3-dev python3-setuptools ninja-build
- name: compiler installed
run: gcc -v ; echo ; clang -v
- name: install gcc plugin
diff --git a/.gitignore b/.gitignore
index 3f440730..8c420b5e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -82,3 +82,7 @@ libAFLDriver.a
libAFLQemuDriver.a
test/.afl_performance
gmon.out
+afl-frida-trace.so
+utils/afl_network_proxy/afl-network-client
+utils/afl_network_proxy/afl-network-server
+*.o.tmp
diff --git a/Android.bp b/Android.bp
index ee076d1e..bf37757d 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,8 +1,5 @@
cc_defaults {
name: "afl-defaults",
- sanitize: {
- never: true,
- },
local_include_dirs: [
"include",
@@ -23,18 +20,44 @@ cc_defaults {
"-DBIN_PATH=\"out/host/linux-x86/bin\"",
"-DDOC_PATH=\"out/host/linux-x86/shared/doc/afl\"",
"-D__USE_GNU",
- "-D__aarch64__",
"-DDEBUG_BUILD",
"-U_FORTIFY_SOURCE",
"-ggdb3",
"-g",
"-O0",
"-fno-omit-frame-pointer",
+ "-fPIC",
],
+
+ target: {
+ android_arm64: {
+ cflags: [
+ "-D__ANDROID__",
+ ],
+ },
+ android_arm: {
+ cflags: [
+ "-D__ANDROID__",
+ ],
+ },
+ android_x86_64: {
+ cflags: [
+ "-D__ANDROID__",
+ ],
+ },
+ android_x86: {
+ cflags: [
+ "-D__ANDROID__",
+ ],
+ },
+ },
}
cc_binary {
name: "afl-fuzz",
+ sanitize: {
+ never: true,
+ },
host_supported: true,
compile_multilib: "64",
@@ -128,7 +151,6 @@ cc_binary_host {
],
cflags: [
- "-D__ANDROID__",
"-DAFL_PATH=\"out/host/linux-x86/lib64\"",
"-DAFL_CLANG_FLTO=\"-flto=full\"",
"-DUSE_BINDIR=1",
@@ -199,6 +221,7 @@ cc_library_headers {
export_include_dirs: [
"include",
+ "instrumentation",
],
}
@@ -268,6 +291,116 @@ cc_binary {
],
}
+cc_binary {
+ name: "afl-fuzz-32",
+ sanitize: {
+ never: true,
+ },
+ host_supported: true,
+ compile_multilib: "32",
+
+ defaults: [
+ "afl-defaults",
+ ],
+
+ srcs: [
+ "src/afl-fuzz*.c",
+ "src/afl-common.c",
+ "src/afl-sharedmem.c",
+ "src/afl-forkserver.c",
+ "src/afl-performance.c",
+ ],
+}
+
+cc_binary_host {
+ name: "afl-cc-32",
+ compile_multilib: "32",
+ static_executable: true,
+
+ defaults: [
+ "afl-defaults",
+ ],
+
+ cflags: [
+ "-DAFL_PATH=\"out/host/linux-x86/lib64\"",
+ "-DAFL_CLANG_FLTO=\"-flto=full\"",
+ "-DUSE_BINDIR=1",
+ "-DLLVM_BINDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin\"",
+ "-DLLVM_LIBDIR=\"prebuilts/clang/host/linux-x86/clang-r383902b/lib64\"",
+ "-DCLANGPP_BIN=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/clang++\"",
+ "-DAFL_REAL_LD=\"prebuilts/clang/host/linux-x86/clang-r383902b/bin/ld.lld\"",
+ "-DLLVM_LTO=1",
+ "-DLLVM_MAJOR=11",
+ "-DLLVM_MINOR=2",
+ ],
+
+ srcs: [
+ "src/afl-cc.c",
+ "src/afl-common.c",
+ ],
+
+ symlinks: [
+ "afl-clang-fast-32",
+ "afl-clang-fast++-32",
+ ],
+}
+
+cc_library_static {
+ name: "afl-llvm-rt-32",
+ compile_multilib: "32",
+ vendor_available: true,
+ host_supported: true,
+ recovery_available: true,
+ sdk_version: "9",
+
+ apex_available: [
+ "com.android.adbd",
+ "com.android.appsearch",
+ "com.android.art",
+ "com.android.bluetooth.updatable",
+ "com.android.cellbroadcast",
+ "com.android.conscrypt",
+ "com.android.extservices",
+ "com.android.cronet",
+ "com.android.neuralnetworks",
+ "com.android.media",
+ "com.android.media.swcodec",
+ "com.android.mediaprovider",
+ "com.android.permission",
+ "com.android.runtime",
+ "com.android.resolv",
+ "com.android.tethering",
+ "com.android.wifi",
+ "com.android.sdkext",
+ "com.android.os.statsd",
+ "//any",
+ ],
+
+ defaults: [
+ "afl-defaults",
+ ],
+
+ srcs: [
+ "instrumentation/afl-compiler-rt.o.c",
+ ],
+}
+
+cc_prebuilt_library_static {
+ name: "libfrida-gum-32",
+ compile_multilib: "32",
+ strip: {
+ none: true,
+ },
+
+ srcs: [
+ "utils/afl_frida/android/arm/libfrida-gum.a",
+ ],
+
+ export_include_dirs: [
+ "utils/afl_frida/android/arm",
+ ],
+}
+
subdirs = [
"custom_mutators",
]
diff --git a/Dockerfile b/Dockerfile
index 1cb00d5d..18fb6367 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -37,7 +37,7 @@ RUN echo "deb http://ppa.launchpad.net/ubuntu-toolchain-r/test/ubuntu focal main
RUN apt-get update && apt-get full-upgrade -y && \
apt-get -y install --no-install-suggests --no-install-recommends \
- gcc-10 g++-10 gcc-10-plugin-dev gcc-10-multilib gdb lcov \
+ gcc-10 g++-10 gcc-10-plugin-dev gcc-10-multilib gcc-multilib gdb lcov \
clang-12 clang-tools-12 libc++1-12 libc++-12-dev \
libc++abi1-12 libc++abi-12-dev libclang1-12 libclang-12-dev \
libclang-common-12-dev libclang-cpp12 libclang-cpp12-dev liblld-12 \
@@ -50,6 +50,7 @@ RUN update-alternatives --install /usr/bin/g++ g++ /usr/bin/g++-10 0
ENV LLVM_CONFIG=llvm-config-12
ENV AFL_SKIP_CPUFREQ=1
+ENV AFL_TRY_AFFINITY=1
ENV AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1
RUN git clone --depth=1 https://github.com/vanhauser-thc/afl-cov /afl-cov
@@ -61,8 +62,10 @@ WORKDIR /AFLplusplus
RUN export CC=gcc-10 && export CXX=g++-10 && make clean && \
make distrib && make install && make clean
-RUN echo 'alias joe="jupp --wordwrap"' >> ~/.bashrc
-RUN echo 'export PS1="[afl++]$PS1"' >> ~/.bashrc
+RUN sh -c 'echo set encoding=utf-8 > /root/.vimrc'
+RUN echo '. /etc/bash_completion' >> ~/.bashrc
+RUN echo 'alias joe="joe --wordwrap --joe_state -nobackup"' >> ~/.bashrc
+RUN echo "export PS1='"'[afl++ \h] \w$(__git_ps1) \$ '"'" >> ~/.bashrc
ENV IS_DOCKER="1"
# Disabled until we have the container ready
diff --git a/GNUmakefile b/GNUmakefile
index ac8fe796..270746b4 100644
--- a/GNUmakefile
+++ b/GNUmakefile
@@ -36,6 +36,11 @@ SH_PROGS = afl-plot afl-cmin afl-cmin.bash afl-whatsup afl-system-config
MANPAGES=$(foreach p, $(PROGS) $(SH_PROGS), $(p).8) afl-as.8
ASAN_OPTIONS=detect_leaks=0
+SYS = $(shell uname -s)
+ARCH = $(shell uname -m)
+
+$(info [*] Compiling afl++ for OS $(SYS) on ARCH $(ARCH))
+
ifdef NO_SPLICING
override CFLAGS += -DNO_SPLICING
endif
@@ -82,7 +87,7 @@ endif
# endif
#endif
-ifneq "$(shell uname)" "Darwin"
+ifneq "$(SYS)" "Darwin"
#ifeq "$(HAVE_MARCHNATIVE)" "1"
# SPECIAL_PERFORMANCE += -march=native
#endif
@@ -92,7 +97,7 @@ ifneq "$(shell uname)" "Darwin"
endif
endif
-ifeq "$(shell uname)" "SunOS"
+ifeq "$(SYS)" "SunOS"
CFLAGS_OPT += -Wno-format-truncation
LDFLAGS = -lkstat -lrt
endif
@@ -119,11 +124,10 @@ ifdef INTROSPECTION
CFLAGS_OPT += -DINTROSPECTION=1
endif
-
-ifneq "$(shell uname -m)" "x86_64"
- ifneq "$(patsubst i%86,i386,$(shell uname -m))" "i386"
- ifneq "$(shell uname -m)" "amd64"
- ifneq "$(shell uname -m)" "i86pc"
+ifneq "$(ARCH)" "x86_64"
+ ifneq "$(patsubst i%86,i386,$(ARCH))" "i386"
+ ifneq "$(ARCH)" "amd64"
+ ifneq "$(ARCH)" "i86pc"
AFL_NO_X86=1
endif
endif
@@ -141,30 +145,30 @@ override CFLAGS += -g -Wno-pointer-sign -Wno-variadic-macros -Wall -Wextra -Wpoi
-I include/ -DAFL_PATH=\"$(HELPER_PATH)\" \
-DBIN_PATH=\"$(BIN_PATH)\" -DDOC_PATH=\"$(DOC_PATH)\"
-ifeq "$(shell uname -s)" "FreeBSD"
+ifeq "$(SYS)" "FreeBSD"
override CFLAGS += -I /usr/local/include/
LDFLAGS += -L /usr/local/lib/
endif
-ifeq "$(shell uname -s)" "DragonFly"
+ifeq "$(SYS)" "DragonFly"
override CFLAGS += -I /usr/local/include/
LDFLAGS += -L /usr/local/lib/
endif
-ifeq "$(shell uname -s)" "OpenBSD"
+ifeq "$(SYS)" "OpenBSD"
override CFLAGS += -I /usr/local/include/ -mno-retpoline
LDFLAGS += -Wl,-z,notext -L /usr/local/lib/
endif
-ifeq "$(shell uname -s)" "NetBSD"
+ifeq "$(SYS)" "NetBSD"
override CFLAGS += -I /usr/pkg/include/
LDFLAGS += -L /usr/pkg/lib/
endif
-ifeq "$(shell uname -s)" "Haiku"
+ifeq "$(SYS)" "Haiku"
SHMAT_OK=0
override CFLAGS += -DUSEMMAP=1 -Wno-error=format -fPIC
- LDFLAGS += -Wno-deprecated-declarations -lgnu
+ LDFLAGS += -Wno-deprecated-declarations -lgnu -lnetwork
SPECIAL_PERFORMANCE += -DUSEMMAP=1
endif
@@ -236,24 +240,24 @@ else
BUILD_DATE ?= $(shell date "+%Y-%m-%d")
endif
-ifneq "$(filter Linux GNU%,$(shell uname))" ""
+ifneq "$(filter Linux GNU%,$(SYS))" ""
ifndef DEBUG
override CFLAGS += -D_FORTIFY_SOURCE=2
endif
LDFLAGS += -ldl -lrt -lm
endif
-ifneq "$(findstring FreeBSD, $(shell uname))" ""
+ifneq "$(findstring FreeBSD, $(SYS))" ""
override CFLAGS += -pthread
LDFLAGS += -lpthread
endif
-ifneq "$(findstring NetBSD, $(shell uname))" ""
+ifneq "$(findstring NetBSD, $(SYS))" ""
override CFLAGS += -pthread
LDFLAGS += -lpthread
endif
-ifneq "$(findstring OpenBSD, $(shell uname))" ""
+ifneq "$(findstring OpenBSD, $(SYS))" ""
override CFLAGS += -pthread
LDFLAGS += -lpthread
endif
@@ -485,7 +489,7 @@ unit_clean:
@rm -f ./test/unittests/unit_preallocable ./test/unittests/unit_list ./test/unittests/unit_maybe_alloc test/unittests/*.o
.PHONY: unit
-ifneq "$(shell uname)" "Darwin"
+ifneq "$(SYS)" "Darwin"
unit: unit_maybe_alloc unit_preallocable unit_list unit_clean unit_rand unit_hash
else
unit:
@@ -499,25 +503,28 @@ code-format:
./.custom-format.py -i instrumentation/*.h
./.custom-format.py -i instrumentation/*.cc
./.custom-format.py -i instrumentation/*.c
+ ./.custom-format.py -i *.h
+ ./.custom-format.py -i *.c
@#./.custom-format.py -i custom_mutators/*/*.c* # destroys libfuzzer :-(
@#./.custom-format.py -i custom_mutators/*/*.h # destroys honggfuzz :-(
./.custom-format.py -i utils/*/*.c*
./.custom-format.py -i utils/*/*.h
./.custom-format.py -i test/*.c
+ ./.custom-format.py -i frida_mode/src/*.c
+ ./.custom-format.py -i frida_mode/include/*.h
+ -./.custom-format.py -i frida_mode/src/*/*.c
./.custom-format.py -i qemu_mode/libcompcov/*.c
./.custom-format.py -i qemu_mode/libcompcov/*.cc
./.custom-format.py -i qemu_mode/libcompcov/*.h
./.custom-format.py -i qemu_mode/libqasan/*.c
./.custom-format.py -i qemu_mode/libqasan/*.h
- ./.custom-format.py -i *.h
- ./.custom-format.py -i *.c
.PHONY: test_build
ifndef AFL_NO_X86
test_build: afl-cc afl-gcc afl-as afl-showmap
@echo "[*] Testing the CC wrapper afl-cc and its instrumentation output..."
- @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
+ @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-cc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-cc failed"; exit 1 )
ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
@rm -f test-instr
@@ -525,7 +532,7 @@ test_build: afl-cc afl-gcc afl-as afl-showmap
@echo
@echo "[+] All right, the instrumentation of afl-cc seems to be working!"
# @echo "[*] Testing the CC wrapper afl-gcc and its instrumentation output..."
-# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
+# @unset AFL_MAP_SIZE AFL_USE_UBSAN AFL_USE_CFISAN AFL_USE_LSAN AFL_USE_ASAN AFL_USE_MSAN; AFL_CC=$(CC) ASAN_OPTIONS=detect_leaks=0 AFL_INST_RATIO=100 AFL_PATH=. ./afl-gcc test-instr.c -o test-instr 2>&1 || (echo "Oops, afl-gcc failed"; exit 1 )
# ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr0 ./test-instr < /dev/null
# echo 1 | ASAN_OPTIONS=detect_leaks=0 ./afl-showmap -m none -q -o .test-instr1 ./test-instr
# @rm -f test-instr
@@ -546,7 +553,7 @@ all_done: test_build
@test -e SanitizerCoverageLTO.so && echo "[+] LLVM LTO mode for 'afl-cc' successfully built!" || echo "[-] LLVM LTO mode for 'afl-cc' failed to build, this would need LLVM 11+, see instrumentation/README.lto.md how to build it"
@test -e afl-gcc-pass.so && echo "[+] gcc_plugin for 'afl-cc' successfully built!" || echo "[-] gcc_plugin for 'afl-cc' failed to build, unless you really need it that is fine - or read instrumentation/README.gcc_plugin.md how to build it"
@echo "[+] All done! Be sure to review the README.md - it's pretty short and useful."
- @if [ "`uname`" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD. You can also use VirtualBox\n(virtualbox.org) to put AFL inside a Linux or *BSD VM.\n\n"; fi
+ @if [ "$(SYS)" = "Darwin" ]; then printf "\nWARNING: Fuzzing on MacOS X is slow because of the unusually high overhead of\nfork() on this OS. Consider using Linux or *BSD for fuzzing software not\nspecifically for MacOS.\n\n"; fi
@! tty <&1 >/dev/null || printf "\033[0;30mNOTE: If you can read this, your terminal probably uses white background.\nThis will make the UI hard to read. See docs/status_screen.md for advice.\033[0m\n" 2>/dev/null
.NOTPARALLEL: clean all
@@ -593,6 +600,7 @@ distrib: all
$(MAKE) -C utils/afl_network_proxy
$(MAKE) -C utils/socket_fuzzing
$(MAKE) -C utils/argv_fuzzing
+ -$(MAKE) -C frida_mode
-cd qemu_mode && sh ./build_qemu_support.sh
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
@@ -603,6 +611,7 @@ binary-only: test_shm test_python ready $(PROGS)
$(MAKE) -C utils/afl_network_proxy
$(MAKE) -C utils/socket_fuzzing
$(MAKE) -C utils/argv_fuzzing
+ -$(MAKE) -C frida_mode
-cd qemu_mode && sh ./build_qemu_support.sh
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
@@ -648,6 +657,7 @@ install: all $(MANPAGES)
@if [ -f afl-fuzz-document ]; then set -e; install -m 755 afl-fuzz-document $${DESTDIR}$(BIN_PATH); fi
@if [ -f socketfuzz32.so -o -f socketfuzz64.so ]; then $(MAKE) -C utils/socket_fuzzing install; fi
@if [ -f argvfuzz32.so -o -f argvfuzz64.so ]; then $(MAKE) -C utils/argv_fuzzing install; fi
+ @if [ -f afl-frida-trace.so ]; then install -m 755 afl-frida-trace.so $${DESTDIR}$(HELPER_PATH); fi
@if [ -f utils/afl_network_proxy/afl-network-server ]; then $(MAKE) -C utils/afl_network_proxy install; fi
@if [ -f utils/aflpp_driver/libAFLDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLDriver.a $${DESTDIR}$(HELPER_PATH); fi
@if [ -f utils/aflpp_driver/libAFLQemuDriver.a ]; then set -e; install -m 644 utils/aflpp_driver/libAFLQemuDriver.a $${DESTDIR}$(HELPER_PATH); fi
diff --git a/GNUmakefile.gcc_plugin b/GNUmakefile.gcc_plugin
index aa93c688..b0f90f1b 100644
--- a/GNUmakefile.gcc_plugin
+++ b/GNUmakefile.gcc_plugin
@@ -41,6 +41,8 @@ CXXEFLAGS := $(CXXFLAGS) -Wall -std=c++11
CC ?= gcc
CXX ?= g++
+SYS = $(shell uname -s)
+
ifeq "clang" "$(CC)"
CC = gcc
CXX = g++
@@ -75,25 +77,25 @@ ifeq "$(TEST_MMAP)" "1"
override CFLAGS_SAFE += -DUSEMMAP=1
endif
-ifneq "$(shell uname -s)" "Haiku"
-ifneq "$(shell uname -s)" "OpenBSD"
+ifneq "$(SYS)" "Haiku"
+ifneq "$(SYS)" "OpenBSD"
LDFLAGS += -lrt
endif
else
CFLAGS_SAFE += -DUSEMMAP=1
endif
-ifeq "$(shell uname -s)" "OpenBSD"
+ifeq "$(SYS)" "OpenBSD"
CC = egcc
CXX = eg++
PLUGIN_FLAGS += -I/usr/local/include
endif
-ifeq "$(shell uname -s)" "DragonFly"
+ifeq "$(SYS)" "DragonFly"
PLUGIN_FLAGS += -I/usr/local/include
endif
-ifeq "$(shell uname -s)" "SunOS"
+ifeq "$(SYS)" "SunOS"
PLUGIN_FLAGS += -I/usr/include/gmp
endif
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm
index 111a847d..2d50badc 100644
--- a/GNUmakefile.llvm
+++ b/GNUmakefile.llvm
@@ -30,11 +30,13 @@ BUILD_DATE ?= $(shell date -u -d "@$(SOURCE_DATE_EPOCH)" "+%Y-%m-%d" 2>/dev/nul
VERSION = $(shell grep '^$(HASH)define VERSION ' ./config.h | cut -d '"' -f2)
-ifeq "$(shell uname)" "OpenBSD"
+SYS = $(shell uname -s)
+
+ifeq "$(SYS)" "OpenBSD"
LLVM_CONFIG ?= $(BIN_PATH)/llvm-config
HAS_OPT = $(shell test -x $(BIN_PATH)/opt && echo 0 || echo 1)
ifeq "$(HAS_OPT)" "1"
- $(warning llvm_mode needs a complete llvm installation (versions 3.4 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
+ $(warning llvm_mode needs a complete llvm installation (versions 6.0 up to 12) -> e.g. "pkg_add llvm-7.0.1p9")
endif
else
LLVM_CONFIG ?= llvm-config
@@ -43,7 +45,7 @@ endif
LLVMVER = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/git//' | sed 's/svn//' )
LLVM_MAJOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/\..*//' )
LLVM_MINOR = $(shell $(LLVM_CONFIG) --version 2>/dev/null | sed 's/.*\.//' | sed 's/git//' | sed 's/svn//' | sed 's/ .*//' )
-LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^3\.[0-3]|^[0-2]\.' && echo 1 || echo 0 )
+LLVM_UNSUPPORTED = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^[0-5]\.' && echo 1 || echo 0 )
LLVM_TOO_NEW = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[3-9]' && echo 1 || echo 0 )
LLVM_NEW_API = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[0-9]' && echo 1 || echo 0 )
LLVM_10_OK = $(shell $(LLVM_CONFIG) --version 2>/dev/null | egrep -q '^1[1-9]|^10\.[1-9]|^10\.0.[1-9]' && echo 1 || echo 0 )
@@ -59,7 +61,7 @@ ifeq "$(LLVMVER)" ""
endif
ifeq "$(LLVM_UNSUPPORTED)" "1"
- $(error llvm_mode only supports llvm from version 3.4 onwards)
+ $(error llvm_mode only supports llvm from version 6.0 onwards)
endif
ifeq "$(LLVM_TOO_NEW)" "1"
@@ -275,13 +277,13 @@ CLANG_LFL = `$(LLVM_CONFIG) --ldflags` $(LDFLAGS)
# User teor2345 reports that this is required to make things work on MacOS X.
-ifeq "$(shell uname)" "Darwin"
+ifeq "$(SYS)" "Darwin"
CLANG_LFL += -Wl,-flat_namespace -Wl,-undefined,suppress
else
CLANG_CPPFL += -Wl,-znodelete
endif
-ifeq "$(shell uname)" "OpenBSD"
+ifeq "$(SYS)" "OpenBSD"
CLANG_LFL += `$(LLVM_CONFIG) --libdir`/libLLVM.so
CLANG_CPPFL += -mno-retpoline
CFLAGS += -mno-retpoline
@@ -304,7 +306,7 @@ ifeq "$(TEST_MMAP)" "1"
endif
PROGS_ALWAYS = ./afl-cc ./afl-compiler-rt.o ./afl-compiler-rt-32.o ./afl-compiler-rt-64.o
-PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./libLLVMInsTrim.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so
+PROGS = $(PROGS_ALWAYS) ./afl-llvm-pass.so ./SanitizerCoveragePCGUARD.so ./split-compares-pass.so ./split-switches-pass.so ./cmplog-routines-pass.so ./cmplog-instructions-pass.so ./afl-llvm-dict2file.so ./compare-transform-pass.so ./afl-ld-lto ./afl-llvm-lto-instrumentlist.so ./afl-llvm-lto-instrumentation.so ./SanitizerCoverageLTO.so
# If prerequisites are not given, warn, do not build anything, and exit with code 0
ifeq "$(LLVMVER)" ""
@@ -344,7 +346,7 @@ no_build:
test_deps:
@echo "[*] Checking for working 'llvm-config'..."
ifneq "$(LLVM_APPLE_XCODE)" "1"
- @type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-3.5 or something like that.)"; exit 1 )
+ @type $(LLVM_CONFIG) >/dev/null 2>&1 || ( echo "[-] Oops, can't find 'llvm-config'. Install clang or set \$$LLVM_CONFIG or \$$PATH beforehand."; echo " (Sometimes, the binary will be named llvm-config-11 or something like that.)"; exit 1 )
endif
@echo "[*] Checking for working '$(CC)'..."
@type $(CC) >/dev/null 2>&1 || ( echo "[-] Oops, can't find '$(CC)'. Make sure that it's in your \$$PATH (or set \$$CC and \$$CXX)."; exit 1 )
@@ -382,9 +384,6 @@ 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 $@
-./libLLVMInsTrim.so: instrumentation/LLVMInsTrim.so.cc instrumentation/MarkNodes.cc instrumentation/afl-llvm-common.o | test_deps
- -$(CXX) $(CLANG_CPPFL) -DLLVMInsTrim_EXPORTS -fno-rtti -fPIC -std=$(LLVM_STDCXX) -shared $< instrumentation/MarkNodes.cc -o $@ $(CLANG_LFL) instrumentation/afl-llvm-common.o
-
./afl-llvm-pass.so: instrumentation/afl-llvm-pass.so.cc instrumentation/afl-llvm-common.o | test_deps
ifeq "$(LLVM_MIN_4_0_1)" "0"
$(info [!] N-gram branch coverage instrumentation is not available for llvm version $(LLVMVER))
diff --git a/README.md b/README.md
index 084971f3..ba612edb 100644
--- a/README.md
+++ b/README.md
@@ -2,9 +2,9 @@
- Release Version: [3.12c](https://github.com/AFLplusplus/AFLplusplus/releases)
+ Release Version: [3.13c](https://github.com/AFLplusplus/AFLplusplus/releases)
- Github Version: 3.13a
+ Github Version: 3.14a
Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus)
@@ -25,7 +25,11 @@
For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast`
with `AFL_LLVM_CMPLOG=1`.
-## Major changes in afl++ 3.00 + 3.10
+## Major changes in afl++ 3.00 onwards:
+
+With afl++ 3.13-3.20 we introduce frida_mode (-O) to have an alternative for
+binary-only fuzzing. It is slower than Qemu mode but works on MacOS, Android,
+iOS etc.
With afl++ 3.10 we introduced the following changes from previous behaviours:
* The '+' feature of the '-t' option now means to auto-calculate the timeout
@@ -80,30 +84,32 @@ behaviours and defaults:
## Important features of afl++
- afl++ supports llvm up to version 12, very fast binary fuzzing with QEMU 5.1
- with laf-intel and redqueen, unicorn mode, gcc plugin, full *BSD, Solaris and
- Android support and much, much, much more.
+ afl++ supports llvm from 6.0 up to version 12, very fast binary fuzzing with QEMU 5.1
+ with laf-intel and redqueen, frida mode, unicorn mode, gcc plugin, full *BSD,
+ Mac OS, Solaris and Android support and much, much, much more.
- | Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | qemu_mode | unicorn_mode |
- | -------------------------|:-------:|:---------:|:----------:|:----------------:|:------------:|
- | NeverZero | x86[_64]| x(1) | x | x | x |
- | Persistent Mode | | x | x | x86[_64]/arm[64] | x |
- | LAF-Intel / CompCov | | x | | x86[_64]/arm[64] | x86[_64]/arm |
- | CmpLog | | x | | x86[_64]/arm[64] | |
- | Selective Instrumentation| | x | x | x | |
- | Non-Colliding Coverage | | x(4) | | (x)(5) | |
- | Ngram prev_loc Coverage | | x(6) | | | |
- | Context Coverage | | x(6) | | | |
- | Auto Dictionary | | x(7) | | | |
- | Snapshot LKM Support | | x(8) | x(8) | (x)(5) | |
+ | Feature/Instrumentation | afl-gcc | llvm | gcc_plugin | frida_mode | qemu_mode |unicorn_mode |
+ | -------------------------|:-------:|:---------:|:----------:|:----------:|:----------------:|:------------:|
+ | Threadsafe counters | | x(3) | | | | |
+ | NeverZero | x86[_64]| x(1) | x | x | x | x |
+ | Persistent Mode | | x | x | x86[_64] | x86[_64]/arm[64] | x |
+ | LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm |
+ | CmpLog | | x | | x86[_64] | x86[_64]/arm[64] | |
+ | Selective Instrumentation| | x | x | x | x | |
+ | Non-Colliding Coverage | | x(4) | | | (x)(5) | |
+ | Ngram prev_loc Coverage | | x(6) | | | | |
+ | Context Coverage | | x(6) | | | | |
+ | Auto Dictionary | | x(7) | | | | |
+ | Snapshot LKM Support | | (x)(8) | (x)(8) | | (x)(5) | |
+ | Shared Memory Testcases | | x | x | x | x | x |
- 1. default for LLVM >= 9.0, env var for older version due an efficiency bug in llvm <= 8
+ 1. default for LLVM >= 9.0, env var for older version due an efficiency bug in previous llvm versions
2. GCC creates non-performant code, hence it is disabled in gcc_plugin
- 3. (currently unassigned)
- 4. with pcguard mode and LTO mode for LLVM >= 11
+ 3. with `AFL_LLVM_THREADSAFE_INST`, disables NeverZero
+ 4. with pcguard mode and LTO mode for LLVM 11 and newer
5. upcoming, development in the branch
- 6. not compatible with LTO instrumentation and needs at least LLVM >= 4.1
- 7. automatic in LTO mode with LLVM >= 11, an extra pass for all LLVM version that writes to a file to use with afl-fuzz' `-x`
+ 6. not compatible with LTO instrumentation and needs at least LLVM v4.1
+ 7. automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM version that writes to a file to use with afl-fuzz' `-x`
8. the snapshot LKM is currently unmaintained due to too many kernel changes coming too fast :-(
Among others, the following features and patches have been integrated:
@@ -140,6 +146,7 @@ behaviours and defaults:
time when we are satisfied with its stability
* [dev](https://github.com/AFLplusplus/AFLplusplus/tree/dev) : development state of afl++ - bleeding edge and you might catch a
checkout which does not compile or has a bug. *We only accept PRs in dev!!*
+ * [release](https://github.com/AFLplusplus/AFLplusplus/tree/release) : the latest release
* (any other) : experimental branches to work on specific features or testing
new functionality or changes.
@@ -180,7 +187,7 @@ sudo apt-get install -y build-essential python3-dev automake git flex bison libg
# try to install llvm 11 and install the distro default if that fails
sudo apt-get install -y lld-11 llvm-11 llvm-11-dev clang-11 || 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
-git clone https://github.com/AFLplusplus/AFLplusplus && cd AFLplusplus
+git clone https://github.com/AFLplusplus/AFLplusplus
cd AFLplusplus
make distrib
sudo make install
@@ -249,6 +256,7 @@ Here are some good writeups to show how to effectively use AFL++:
If you are interested in fuzzing structured data (where you define what the
structure is), these links have you covered:
* Superion for afl++: [https://github.com/adrian-rt/superion-mutator](https://github.com/adrian-rt/superion-mutator)
+ * libprotobuf for afl++: [https://github.com/P1umer/AFLplusplus-protobuf-mutator](https://github.com/P1umer/AFLplusplus-protobuf-mutator)
* libprotobuf raw: [https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator](https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4_libprotobuf_aflpp_custom_mutator)
* libprotobuf for old afl++ API: [https://github.com/thebabush/afl-libprotobuf-mutator](https://github.com/thebabush/afl-libprotobuf-mutator)
@@ -288,7 +296,7 @@ anything below 9 is not recommended.
|
v
+---------------------------------+
-| clang/clang++ 3.3+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
+| clang/clang++ 6.0+ is available | --> use LLVM mode (afl-clang-fast/afl-clang-fast++)
+---------------------------------+ see [instrumentation/README.llvm.md](instrumentation/README.llvm.md)
|
| if not, or if the target fails with LLVM afl-clang-fast/++
@@ -370,7 +378,6 @@ There are many more options and modes available however these are most of the
time less effective. See:
* [instrumentation/README.ctx.md](instrumentation/README.ctx.md)
* [instrumentation/README.ngram.md](instrumentation/README.ngram.md)
- * [instrumentation/README.instrim.md](instrumentation/README.instrim.md)
afl++ performs "never zero" counting in its bitmap. You can read more about this
here:
@@ -431,7 +438,7 @@ described in [instrumentation/README.lto.md](instrumentation/README.lto.md).
##### cmake
For `cmake` build systems this is usually done by:
-`mkdir build; cmake -DCMAKE_C_COMPILERC=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..`
+`mkdir build; cd build; cmake -DCMAKE_C_COMPILER=afl-cc -DCMAKE_CXX_COMPILER=afl-c++ ..`
Note that if you are using the (better) afl-clang-lto compiler you also have to
set AR to llvm-ar[-VERSION] and RANLIB to llvm-ranlib[-VERSION] - as is
@@ -601,8 +608,9 @@ Every -M/-S entry needs a unique name (that can be whatever), however the same
For every secondary fuzzer there should be a variation, e.g.:
* one should fuzz the target that was compiled differently: with sanitizers
activated (`export AFL_USE_ASAN=1 ; export AFL_USE_UBSAN=1 ;
- export AFL_USE_CFISAN=1 ; `
- * one should fuzz the target with CMPLOG/redqueen (see above)
+ export AFL_USE_CFISAN=1 ; export AFL_USE_LSAN=1`)
+ * one or two should fuzz the target with CMPLOG/redqueen (see above), at
+ least one cmplog instance should follow transformations (`-l AT`)
* one to three fuzzers should fuzz a target compiled with laf-intel/COMPCOV
(see above). Important note: If you run more than one laf-intel/COMPCOV
fuzzer and you want them to share their intermediate results, the main
@@ -672,8 +680,8 @@ If you see that an important area or a feature has not been covered so far then
try to find an input that is able to reach that and start a new secondary in
that fuzzing campaign with that seed as input, let it run for a few minutes,
then terminate it. The main node will pick it up and make it available to the
-other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` if you have no
-free core.
+other secondary nodes over time. Set `export AFL_NO_AFFINITY=1` or
+`export AFL_TRY_AFFINITY=1` if you have no free core.
Note that you in nearly all cases can never reach full coverage. A lot of
functionality is usually behind options that were not activated or fuzz e.g.
@@ -784,16 +792,19 @@ How this can look like can e.g. be seen at afl++'s setup in Google's [oss-fuzz](
When source code is *NOT* available, afl++ offers various support for fast,
on-the-fly instrumentation of black-box binaries.
-If you do not have to use Unicorn the following setup is recommended:
+If you do not have to use Unicorn the following setup is recommended to use
+qemu_mode:
* run 1 afl-fuzz -Q instance with CMPLOG (`-c 0` + `AFL_COMPCOV_LEVEL=2`)
* run 1 afl-fuzz -Q instance with QASAN (`AFL_USE_QASAN=1`)
* run 1 afl-fuzz -Q instance with LAF (``AFL_PRELOAD=libcmpcov.so` + `AFL_COMPCOV_LEVEL=2`)
+Alternatively you can use frida_mode, just switch `-Q` with `-O` and remove the
+LAF instance.
Then run as many instances as you have cores left with either -Q mode or - better -
-use a binary rewriter like afl-dyninst, retrowrite, zipr, fibre, etc.
+use a binary rewriter like afl-dyninst, retrowrite, zaflr, etc.
-For Qemu mode, check out the persistent mode and snapshot features, they give
-a huge speed improvement!
+For Qemu and Frida mode, check out the persistent mode, it gives a huge speed
+improvement if it is possible to use.
### QEMU
@@ -805,18 +816,31 @@ feature by doing:
cd qemu_mode
./build_qemu_support.sh
```
-For additional instructions and caveats, see [qemu_mode/README.md](qemu_mode/README.md) -
-check out the snapshot feature! :-)
+For additional instructions and caveats, see [qemu_mode/README.md](qemu_mode/README.md).
If possible you should use the persistent mode, see [qemu_mode/README.persistent.md](qemu_mode/README.persistent.md).
The mode is approximately 2-5x slower than compile-time instrumentation, and is
less conducive to parallelization.
If [afl-dyninst](https://github.com/vanhauser-thc/afl-dyninst) works for
your binary, then you can use afl-fuzz normally and it will have twice
-the speed compared to qemu_mode (but slower than persistent mode).
+the speed compared to qemu_mode (but slower than qemu persistent mode).
Note that several other binary rewriters exist, all with their advantages and
caveats.
+### Frida
+
+Frida mode is sometimes faster and sometimes slower than Qemu mode.
+It is also newer, lacks COMPCOV, but supports MacOS.
+
+```shell
+cd frida_mode
+make
+```
+For additional instructions and caveats, see [frida_mode/README.md](frida_mode/README.md).
+If possible you should use the persistent mode, see [qemu_frida/README.persistent.md](qemu_frida/README.persistent.md).
+The mode is approximately 2-5x slower than compile-time instrumentation, and is
+less conducive to parallelization.
+
### Unicorn
For non-Linux binaries you can use afl++'s unicorn mode which can emulate
diff --git a/TODO.md b/TODO.md
index b8a091ff..398f3d11 100644
--- a/TODO.md
+++ b/TODO.md
@@ -2,15 +2,16 @@
## Roadmap 3.00+
+ - align map to 64 bytes but keep real IDs
- Update afl->pending_not_fuzzed for MOpt
- - CPU affinity for many cores? There seems to be an issue > 96 cores
+ - put fuzz target in top line of UI
- afl-plot to support multiple plot_data
- afl_custom_fuzz_splice_optin()
- afl_custom_splice()
- intel-pt tracer
- better autodetection of shifting runtime timeout values
- cmplog: use colorization input for havoc?
- - cmplog: too much tainted bytes, directly add to dict and skip?
+ - parallel builds for source-only targets
## Further down the road
@@ -35,4 +36,5 @@ qemu_mode:
up edge numbers that both following cmp paths have been found and then
disable working on this edge id -> cmplog_intelligence branch
- use cmplog colorization taint result for havoc locations?
-
+ - new instrumentation option for a thread-safe variant of feedback to shared mem.
+ The user decides, if this is needed (eg the target is multithreaded).
diff --git a/afl-cmin b/afl-cmin
index 778d7487..9fa63ec6 100755
--- a/afl-cmin
+++ b/afl-cmin
@@ -106,6 +106,7 @@ function usage() {
" -f file - location read by the fuzzed program (stdin)\n" \
" -m megs - memory limit for child process ("mem_limit" MB)\n" \
" -t msec - run time limit for child process (none)\n" \
+" -O - use binary-only instrumentation (FRIDA mode)\n" \
" -Q - use binary-only instrumentation (QEMU mode)\n" \
" -U - use unicorn-based instrumentation (unicorn mode)\n" \
"\n" \
@@ -118,11 +119,13 @@ function usage() {
"Environment variables used:\n" \
"AFL_ALLOW_TMP: allow unsafe use of input/output directories under {/var}/tmp\n" \
"AFL_CRASH_EXITCODE: optional child exit code to be interpreted as crash\n" \
-"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the target to come up, initially\n" \
+"AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \
"AFL_KEEP_TRACES: leave the temporary /.traces directory\n" \
-"AFL_KILL_SIGNAL: Signal ID delivered to child processes on timeout, etc. (default: SIGKILL)\n"
-"AFL_PATH: path for the afl-showmap binary if not found anywhere else\n" \
-"AFL_SKIP_BIN_CHECK: skip check for target binary\n"
+"AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \
+"AFL_PATH: path for the afl-showmap binary if not found anywhere in PATH\n" \
+"AFL_PRINT_FILENAMES: If set, the filename currently processed will be " \
+ "printed to stdout\n" \
+"AFL_SKIP_BIN_CHECK: skip afl instrumentation checks for target binary\n"
exit 1
}
@@ -140,7 +143,7 @@ BEGIN {
# process options
Opterr = 1 # default is to diagnose
Optind = 1 # skip ARGV[0]
- while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCQU?")) != -1) {
+ while ((_go_c = getopt(ARGC, ARGV, "hi:o:f:m:t:eCOQU?")) != -1) {
if (_go_c == "i") {
if (!Optarg) usage()
if (in_dir) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
@@ -180,6 +183,12 @@ BEGIN {
extra_par = extra_par " -e"
continue
} else
+ if (_go_c == "O") {
+ if (frida_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
+ extra_par = extra_par " -O"
+ frida_mode = 1
+ continue
+ } else
if (_go_c == "Q") {
if (qemu_mode) { print "Option "_go_c" is only allowed once" > "/dev/stderr"}
extra_par = extra_par " -Q"
@@ -243,7 +252,7 @@ BEGIN {
if (!stdin_file) {
found_atat = 0
for (prog_args_ind in prog_args) {
- if ("@@" == prog_args[prog_args_ind]) {
+ if (match(prog_args[prog_args_ind], "@@") != 0) {
found_atat = 1
break
}
@@ -275,7 +284,7 @@ BEGIN {
target_bin = tnew
}
- if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !unicorn_mode) {
+ if (!ENVIRON["AFL_SKIP_BIN_CHECK"] && !qemu_mode && !frida_mode && !unicorn_mode) {
if (0 != system( "grep -q __AFL_SHM_ID "target_bin )) {
print "[-] Error: binary '"target_bin"' doesn't appear to be instrumented." > "/dev/stderr"
exit 1
diff --git a/afl-cmin.bash b/afl-cmin.bash
index 5b2c3894..f4bd269d 100755
--- a/afl-cmin.bash
+++ b/afl-cmin.bash
@@ -53,7 +53,7 @@ unset IN_DIR OUT_DIR STDIN_FILE EXTRA_PAR MEM_LIMIT_GIVEN \
export AFL_QUIET=1
-while getopts "+i:o:f:m:t:eQUCh" opt; do
+while getopts "+i:o:f:m:t:eOQUCh" opt; do
case "$opt" in
@@ -83,6 +83,10 @@ while getopts "+i:o:f:m:t:eQUCh" opt; do
"C")
export AFL_CMIN_CRASHES_ONLY=1
;;
+ "O")
+ EXTRA_PAR="$EXTRA_PAR -O"
+ FRIDA_MODE=1
+ ;;
"Q")
EXTRA_PAR="$EXTRA_PAR -Q"
QEMU_MODE=1
@@ -118,6 +122,7 @@ Execution control settings:
-f file - location read by the fuzzed program (stdin)
-m megs - memory limit for child process ($MEM_LIMIT MB)
-t msec - run time limit for child process (none)
+ -O - use binary-only instrumentation (FRIDA mode)
-Q - use binary-only instrumentation (QEMU mode)
-U - use unicorn-based instrumentation (Unicorn mode)
@@ -209,7 +214,7 @@ if [ ! -f "$TARGET_BIN" -o ! -x "$TARGET_BIN" ]; then
fi
-if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
+if [ "$AFL_SKIP_BIN_CHECK" = "" -a "$QEMU_MODE" = "" -a "$FRIDA_MODE" = "" -a "$UNICORN_MODE" = "" ]; then
if ! grep -qF "__AFL_SHM_ID" "$TARGET_BIN"; then
echo "[-] Error: binary '$TARGET_BIN' doesn't appear to be instrumented." 1>&2
diff --git a/afl-plot b/afl-plot
index ba100d3e..60a351ab 100755
--- a/afl-plot
+++ b/afl-plot
@@ -111,9 +111,9 @@ set terminal png truecolor enhanced size 1000,300 butt
set output '$outputdir/high_freq.png'
-set xdata time
-set timefmt '%s'
-set format x "%b %d\n%H:%M"
+#set xdata time
+#set timefmt '%s'
+#set format x "%b %d\n%H:%M"
set tics font 'small'
unset mxtics
unset mytics
@@ -127,9 +127,8 @@ set key outside
set autoscale xfixmin
set autoscale xfixmax
-set xlabel "all times in UTC" font "small"
+#set xlabel "all times in UTC" font "small"
-set ytics auto
plot '$inputdir/plot_data' using 1:4 with filledcurve x1 title 'total paths' linecolor rgb '#000000' fillstyle transparent solid 0.2 noborder, \\
'' using 1:3 with filledcurve x1 title 'current path' linecolor rgb '#f0f0f0' fillstyle transparent solid 0.5 noborder, \\
'' using 1:5 with lines title 'pending paths' linecolor rgb '#0090ff' linewidth 3, \\
@@ -139,7 +138,6 @@ plot '$inputdir/plot_data' using 1:4 with filledcurve x1 title 'total paths' lin
set terminal png truecolor enhanced size 1000,200 butt
set output '$outputdir/low_freq.png'
-set ytics 1
plot '$inputdir/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb '#c00080' fillstyle transparent solid 0.2 noborder, \\
'' using 1:8 with lines title ' uniq crashes' linecolor rgb '#c00080' linewidth 3, \\
'' using 1:9 with lines title 'uniq hangs' linecolor rgb '#c000f0' linewidth 3, \\
@@ -148,14 +146,12 @@ plot '$inputdir/plot_data' using 1:8 with filledcurve x1 title '' linecolor rgb
set terminal png truecolor enhanced size 1000,200 butt
set output '$outputdir/exec_speed.png'
-set ytics auto
plot '$inputdir/plot_data' using 1:11 with filledcurve x1 title '' linecolor rgb '#0090ff' fillstyle transparent solid 0.2 noborder, \\
'$inputdir/plot_data' using 1:11 with lines title ' execs/sec' linecolor rgb '#0090ff' linewidth 3 smooth bezier;
set terminal png truecolor enhanced size 1000,300 butt
set output '$outputdir/edges.png'
-set ytics auto
plot '$inputdir/plot_data' using 1:13 with lines title ' edges' linecolor rgb '#0090ff' linewidth 3
_EOF_
diff --git a/afl-system-config b/afl-system-config
index ae37a062..e149e4cd 100755
--- a/afl-system-config
+++ b/afl-system-config
@@ -7,7 +7,7 @@ test "$1" = "-h" -o "$1" = "-hh" && {
echo afl-system-config has no command line options
echo
echo afl-system reconfigures the system to a high performance fuzzing state
- echo WARNING: this reduces the security of the system
+ echo "WARNING: this reduces the security of the system!"
echo
exit 1
}
@@ -15,14 +15,20 @@ test "$1" = "-h" -o "$1" = "-hh" && {
DONE=
PLATFORM=`uname -s`
echo This reconfigures the system to have a better fuzzing performance.
+echo "WARNING: this reduces the security of the system!"
+echo
if [ '!' "$EUID" = 0 ] && [ '!' `id -u` = 0 ] ; then
echo "Warning: you need to be root to run this!"
# we do not exit as other mechanisms exist that allows to do this than
# being root. let the errors speak for themselves.
fi
+sleep 1
if [ "$PLATFORM" = "Linux" ] ; then
{
- sysctl -w kernel.core_pattern=core
+ sysctl -w kernel.core_uses_pid=0
+ # Arch Linux requires core_pattern to be empty :(
+ test -e /etc/arch-release && sysctl -w kernel.core_pattern=
+ test -e /etc/arch-release || sysctl -w kernel.core_pattern=core
sysctl -w kernel.randomize_va_space=0
sysctl -w kernel.sched_child_runs_first=1
sysctl -w kernel.sched_autogroup_enabled=1
@@ -35,12 +41,17 @@ if [ "$PLATFORM" = "Linux" ] ; then
test -e /sys/devices/system/cpu/intel_pstate/no_turbo && echo 0 > /sys/devices/system/cpu/intel_pstate/no_turbo
test -e /sys/devices/system/cpu/cpufreq/boost && echo 1 > /sys/devices/system/cpu/cpufreq/boost
test -e /sys/devices/system/cpu/intel_pstate/max_perf_pct && echo 100 > /sys/devices/system/cpu/intel_pstate/max_perf_pct
+ test -n "$(which auditctl)" && auditctl -a never,task >/dev/null 2>&1
} > /dev/null
echo Settings applied.
+ echo
dmesg | egrep -q 'nospectre_v2|spectre_v2=off' || {
echo It is recommended to boot the kernel with lots of security off - if you are running a machine that is in a secured network - so set this:
echo ' /etc/default/grub:GRUB_CMDLINE_LINUX_DEFAULT="ibpb=off ibrs=off kpti=0 l1tf=off mds=off mitigations=off no_stf_barrier noibpb noibrs nopcid nopti nospec_store_bypass_disable nospectre_v1 nospectre_v2 pcid=off pti=off spec_store_bypass_disable=off spectre_v2=off stf_barrier=off srbds=off noexec=off noexec32=off tsx=on tsx_async_abort=off arm64.nopauth audit=0 hardened_usercopy=off ssbd=force-off"'
+ echo
}
+ echo If you run fuzzing instances in docker, run them with \"--security-opt seccomp=unconfined\" for more speed
+ echo
DONE=1
fi
if [ "$PLATFORM" = "FreeBSD" ] ; then
@@ -49,6 +60,7 @@ if [ "$PLATFORM" = "FreeBSD" ] ; then
sysctl kern.elf64.aslr.enable=0
} > /dev/null
echo Settings applied.
+ echo
cat < /dev/null
echo Settings applied.
+ echo
DONE=1
fi
if [ "$PLATFORM" = "Darwin" ] ; then
+ sysctl kern.sysv.shmmax=8388608
+ sysctl kern.sysv.shmseg=48
+ sysctl kern.sysv.shmall=98304
+ echo Settings applied.
+ echo
if [ $(launchctl list 2>/dev/null | grep -q '\.ReportCrash$') ] ; then
- echo We unload the default crash reporter here
+ echo
+ echo Unloading the default crash reporter
SL=/System/Library; PL=com.apple.ReportCrash
- launchctl unload -w ${SL}/LaunchAgents/${PL}.plist
- sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist
- echo Settings applied.
- else
- echo Nothing to do.
+ launchctl unload -w ${SL}/LaunchAgents/${PL}.plist >/dev/null 2>&1
+ sudo launchctl unload -w ${SL}/LaunchDaemons/${PL}.Root.plist >/dev/null 2>&1
+ echo
fi
+ echo It is recommended to disable System Integration Protection for increased performance.
+ echo
DONE=1
fi
if [ "$PLATFORM" = "Haiku" ] ; then
- SETTINGS=~/config/settings/system/debug_server/settings
+ DEBUG_SERVER_DIR=~/config/settings/system/debug_server
+ [ ! -d ${DEBUG_SERVER_DIR} ] && mkdir -p ${DEBUG_SERVER_DIR}
+ SETTINGS=${DEBUG_SERVER_DIR}/settings
[ -r ${SETTINGS} ] && grep -qE "default_action\s+kill" ${SETTINGS} && { echo "Nothing to do"; } || { \
echo We change the debug_server default_action from user to silently kill; \
[ ! -r ${SETTINGS} ] && echo "default_action kill" >${SETTINGS} || { mv ${SETTINGS} s.tmp; sed -e "s/default_action\s\s*user/default_action kill/" s.tmp > ${SETTINGS}; rm s.tmp; }; \
- echo Settings applied.; \
+ echo Settings applied.; echo; \
}
DONE=1
fi
diff --git a/afl-whatsup b/afl-whatsup
index e92b24bd..9c2564c6 100755
--- a/afl-whatsup
+++ b/afl-whatsup
@@ -21,32 +21,41 @@
echo "$0 status check tool for afl-fuzz by Michal Zalewski"
echo
test "$1" = "-h" -o "$1" = "-hh" && {
- echo $0 [-s] output_directory
+ echo "Usage: $0 [-s] [-d] afl_output_directory"
echo
echo Options:
- echo -s - skip details and output summary results only
+ echo " -s - skip details and output summary results only"
+ echo " -d - include dead fuzzer stats"
echo
exit 1
}
-if [ "$1" = "-s" ]; then
+unset SUMMARY_ONLY
+unset PROCESS_DEAD
- SUMMARY_ONLY=1
- DIR="$2"
+while [ "$1" = "-s" -o "$1" = "-d" ]; do
-else
+ if [ "$1" = "-s" ]; then
+ SUMMARY_ONLY=1
+ fi
- unset SUMMARY_ONLY
- DIR="$1"
+ if [ "$1" = "-d" ]; then
+ PROCESS_DEAD=1
+ fi
+
+ shift
-fi
+done
+
+DIR="$1"
if [ "$DIR" = "" ]; then
- echo "Usage: $0 [ -s ] afl_sync_dir" 1>&2
+ echo "Usage: $0 [-s] [-d] afl_output_directory" 1>&2
echo 1>&2
- echo "The -s option causes the tool to skip all the per-fuzzer trivia and show" 1>&2
- echo "just the summary results. See docs/parallel_fuzzing.md for additional tips." 1>&2
+ echo Options: 1>&2
+ echo " -s - skip details and output summary results only" 1>&2
+ echo " -d - include dead fuzzer stats" 1>&2
echo 1>&2
exit 1
@@ -133,7 +142,7 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
sed 's/^command_line.*$/_skip:1/;s/[ ]*:[ ]*/="/;s/$/"/' "$i" >"$TMP"
. "$TMP"
- RUN_UNIX=$((CUR_TIME - start_time))
+ RUN_UNIX=$run_time
RUN_DAYS=$((RUN_UNIX / 60 / 60 / 24))
RUN_HRS=$(((RUN_UNIX / 60 / 60) % 24))
@@ -160,7 +169,13 @@ for i in `find . -maxdepth 2 -iname fuzzer_stats | sort`; do
fi
DEAD_CNT=$((DEAD_CNT + 1))
- continue
+ last_path=0
+
+ if [ "$PROCESS_DEAD" = "" ]; then
+
+ continue
+
+ fi
fi
@@ -252,13 +267,24 @@ fmt_duration $TOTAL_LAST_PATH && TOTAL_LAST_PATH=$DUR_STRING
test "$TOTAL_TIME" = "0" && TOTAL_TIME=1
+if [ "$PROCESS_DEAD" = "" ]; then
+
+ TXT="excluded from stats"
+
+else
+
+ TXT="included in stats"
+ ALIVE_CNT=$(($ALIVE_CNT - $DEAD_CNT))
+
+fi
+
echo "Summary stats"
echo "============="
echo
echo " Fuzzers alive : $ALIVE_CNT"
if [ ! "$DEAD_CNT" = "0" ]; then
- echo " Dead or remote : $DEAD_CNT (excluded from stats)"
+ echo " Dead or remote : $DEAD_CNT ($TXT)"
fi
echo " Total run time : $FMT_TIME"
diff --git a/custom_mutators/Android.bp b/custom_mutators/Android.bp
index 89abc3e9..5c7e06e3 100644
--- a/custom_mutators/Android.bp
+++ b/custom_mutators/Android.bp
@@ -10,6 +10,8 @@ cc_library_shared {
"-fPIC",
"-fpermissive",
"-std=c++11",
+ "-Wno-unused-parameter",
+ "-Wno-unused-variable",
],
srcs: [
@@ -77,6 +79,8 @@ cc_library_shared {
"-O0",
"-funroll-loops",
"-fPIC",
+ "-Wno-unused-parameter",
+ "-Wno-unused-function",
],
srcs: [
@@ -99,6 +103,8 @@ cc_library_shared {
"-O0",
"-funroll-loops",
"-fPIC",
+ "-Wno-unused-parameter",
+ "-Wno-pointer-sign",
],
srcs: [
diff --git a/custom_mutators/README.md b/custom_mutators/README.md
index b0444c85..13172cdc 100644
--- a/custom_mutators/README.md
+++ b/custom_mutators/README.md
@@ -3,6 +3,14 @@
Custom mutators enhance and alter the mutation strategies of afl++.
For further information and documentation on how to write your own, read [the docs](../docs/custom_mutators.md).
+## Examples
+
+The `./examples` folder contains examples for custom mutators in python and C.
+
+## Rust
+
+In `./rust`, you will find rust bindings, including a simple example in `./rust/example` and an example for structured fuzzing, based on lain, in`./rust/example_lain`.
+
## The afl++ Grammar Mutator
If you use git to clone afl++, then the following will incorporate our
@@ -46,3 +54,6 @@ https://github.com/bruce30262/libprotobuf-mutator_fuzzing_learning/tree/master/4
has a transform function you need to fill for your protobuf format, however
needs to be ported to the updated afl++ custom mutator API (not much work):
https://github.com/thebabush/afl-libprotobuf-mutator
+
+same as above but is for current afl++:
+https://github.com/P1umer/AFLplusplus-protobuf-mutator
diff --git a/utils/custom_mutators/Makefile b/custom_mutators/examples/Makefile
similarity index 100%
rename from utils/custom_mutators/Makefile
rename to custom_mutators/examples/Makefile
diff --git a/utils/custom_mutators/README.md b/custom_mutators/examples/README.md
similarity index 100%
rename from utils/custom_mutators/README.md
rename to custom_mutators/examples/README.md
diff --git a/utils/custom_mutators/XmlMutatorMin.py b/custom_mutators/examples/XmlMutatorMin.py
similarity index 100%
rename from utils/custom_mutators/XmlMutatorMin.py
rename to custom_mutators/examples/XmlMutatorMin.py
diff --git a/utils/custom_mutators/common.py b/custom_mutators/examples/common.py
similarity index 100%
rename from utils/custom_mutators/common.py
rename to custom_mutators/examples/common.py
diff --git a/utils/custom_mutators/custom_mutator_helpers.h b/custom_mutators/examples/custom_mutator_helpers.h
similarity index 100%
rename from utils/custom_mutators/custom_mutator_helpers.h
rename to custom_mutators/examples/custom_mutator_helpers.h
diff --git a/utils/custom_mutators/example.c b/custom_mutators/examples/example.c
similarity index 100%
rename from utils/custom_mutators/example.c
rename to custom_mutators/examples/example.c
diff --git a/utils/custom_mutators/example.py b/custom_mutators/examples/example.py
similarity index 100%
rename from utils/custom_mutators/example.py
rename to custom_mutators/examples/example.py
diff --git a/utils/custom_mutators/post_library_gif.so.c b/custom_mutators/examples/post_library_gif.so.c
similarity index 96%
rename from utils/custom_mutators/post_library_gif.so.c
rename to custom_mutators/examples/post_library_gif.so.c
index ac10f409..aec05720 100644
--- a/utils/custom_mutators/post_library_gif.so.c
+++ b/custom_mutators/examples/post_library_gif.so.c
@@ -45,6 +45,7 @@
1) If you don't want to modify the test case, simply set `*out_buf = in_buf`
and return the original `len`.
+ NOTE: the following is currently NOT true, we abort in this case!
2) If you want to skip this test case altogether and have AFL generate a
new one, return 0 or set `*out_buf = NULL`.
Use this sparingly - it's faster than running the target program
@@ -53,14 +54,14 @@
3) If you want to modify the test case, allocate an appropriately-sized
buffer, move the data into that buffer, make the necessary changes, and
then return the new pointer as out_buf. Return an appropriate len
- afterwards.
+ afterwards.
Note that the buffer will *not* be freed for you. To avoid memory leaks,
you need to free it or reuse it on subsequent calls (as shown below).
*** Feel free to reuse the original 'in_buf' BUFFER and return it. ***
- Aight. The example below shows a simple postprocessor that tries to make
+ Alright. The example below shows a simple postprocessor that tries to make
sure that all input files start with "GIF89a".
PS. If you don't like C, you can try out the unix-based wrapper from
diff --git a/utils/custom_mutators/post_library_png.so.c b/custom_mutators/examples/post_library_png.so.c
similarity index 100%
rename from utils/custom_mutators/post_library_png.so.c
rename to custom_mutators/examples/post_library_png.so.c
diff --git a/utils/custom_mutators/simple-chunk-replace.py b/custom_mutators/examples/simple-chunk-replace.py
similarity index 100%
rename from utils/custom_mutators/simple-chunk-replace.py
rename to custom_mutators/examples/simple-chunk-replace.py
diff --git a/utils/custom_mutators/simple_example.c b/custom_mutators/examples/simple_example.c
similarity index 100%
rename from utils/custom_mutators/simple_example.c
rename to custom_mutators/examples/simple_example.c
diff --git a/utils/custom_mutators/wrapper_afl_min.py b/custom_mutators/examples/wrapper_afl_min.py
similarity index 100%
rename from utils/custom_mutators/wrapper_afl_min.py
rename to custom_mutators/examples/wrapper_afl_min.py
diff --git a/custom_mutators/grammar_mutator/GRAMMAR_VERSION b/custom_mutators/grammar_mutator/GRAMMAR_VERSION
index a3fe6bb1..3df8150e 100644
--- a/custom_mutators/grammar_mutator/GRAMMAR_VERSION
+++ b/custom_mutators/grammar_mutator/GRAMMAR_VERSION
@@ -1 +1 @@
-b3c4fcf
+b79d51a
diff --git a/custom_mutators/grammar_mutator/build_grammar_mutator.sh b/custom_mutators/grammar_mutator/build_grammar_mutator.sh
index ef145dfe..b6cef66f 100755
--- a/custom_mutators/grammar_mutator/build_grammar_mutator.sh
+++ b/custom_mutators/grammar_mutator/build_grammar_mutator.sh
@@ -106,23 +106,23 @@ git status 1>/dev/null 2>/dev/null
if [ $? -eq 0 ]; then
echo "[*] initializing grammar mutator submodule"
git submodule init || exit 1
- git submodule update ./grammar-mutator 2>/dev/null # ignore errors
+ git submodule update ./grammar_mutator 2>/dev/null # ignore errors
else
echo "[*] cloning grammar mutator"
- test -d grammar-mutator || {
+ test -d grammar_mutator || {
CNT=1
- while [ '!' -d grammar-mutator -a "$CNT" -lt 4 ]; do
- echo "Trying to clone grammar-mutator (attempt $CNT/3)"
+ while [ '!' -d grammar_mutator -a "$CNT" -lt 4 ]; do
+ echo "Trying to clone grammar_mutator (attempt $CNT/3)"
git clone "$GRAMMAR_REPO"
CNT=`expr "$CNT" + 1`
done
}
fi
-test -d grammar-mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
+test -d grammar_mutator || { echo "[-] not checked out, please install git or check your internet connection." ; exit 1 ; }
echo "[+] Got grammar mutator."
-cd "grammar-mutator" || exit 1
+cd "grammar_mutator" || exit 1
echo "[*] Checking out $GRAMMAR_VERSION"
sh -c 'git stash && git stash drop' 1>/dev/null 2>/dev/null
git checkout "$GRAMMAR_VERSION" || exit 1
@@ -134,7 +134,7 @@ echo
echo
echo "[+] All successfully prepared!"
echo "[!] To build for your grammar just do:"
-echo " cd grammar-mutator"
+echo " cd grammar_mutator"
echo " make GRAMMAR_FILE=/path/to/your/grammar"
-echo "[+] You will find a JSON and RUBY grammar in grammar-mutator/grammars to play with."
+echo "[+] You will find a JSON and RUBY grammar in grammar_mutator/grammars to play with."
echo
diff --git a/custom_mutators/grammar_mutator/grammar_mutator b/custom_mutators/grammar_mutator/grammar_mutator
index b3c4fcfa..b79d51a8 160000
--- a/custom_mutators/grammar_mutator/grammar_mutator
+++ b/custom_mutators/grammar_mutator/grammar_mutator
@@ -1 +1 @@
-Subproject commit b3c4fcfa6ae28918bc410f7747135eafd4fb7263
+Subproject commit b79d51a8daccbd7a693f9b6765c81ead14f28e26
diff --git a/custom_mutators/libprotobuf-mutator-example/Android.bp b/custom_mutators/libprotobuf-mutator-example/Android.bp
index 01f1c23e..4f579735 100644
--- a/custom_mutators/libprotobuf-mutator-example/Android.bp
+++ b/custom_mutators/libprotobuf-mutator-example/Android.bp
@@ -8,6 +8,7 @@ cc_library_shared {
"-O0",
"-fPIC",
"-Wall",
+ "-Wno-unused-parameter",
],
srcs: [
@@ -29,4 +30,9 @@ cc_binary {
srcs: [
"vuln.c",
],
+
+ cflags: [
+ "-Wno-unused-result",
+ "-Wno-unused-parameter",
+ ],
}
diff --git a/docs/Changelog.md b/docs/Changelog.md
index 5b7d6ab6..1887c099 100644
--- a/docs/Changelog.md
+++ b/docs/Changelog.md
@@ -8,6 +8,63 @@
Want to stay in the loop on major new features? Join our mailing list by
sending a mail to .
+### Version ++3.13c (release)
+ - Note: plot_data switched to relative time from unix time in 3.10
+ - frida_mode - new mode that uses frida to fuzz binary-only targets,
+ it currently supports persistent mode and cmplog.
+ thanks to @WorksButNotTested!
+ - create a fuzzing dictionary with the help of CodeQL thanks to
+ @microsvuln! see utils/autodict_ql
+ - afl-fuzz:
+ - added patch by @realmadsci to support @@ as part of command line
+ options, e.g. `afl-fuzz ... -- ./target --infile=@@`
+ - add recording of previous fuzz attempts for persistent mode
+ to allow replay of non-reproducable crashes, see
+ AFL_PERSISTENT_RECORD in config.h and docs/envs.h
+ - fixed a bug when trimming for stdin targets
+ - cmplog -l: default cmplog level is now 2, better efficiency.
+ level 3 now performs redqueen on everything. use with care.
+ - better fuzzing strategy yield display for enabled options
+ - ensure one fuzzer sync per cycle
+ - fix afl_custom_queue_new_entry original file name when syncing
+ from fuzzers
+ - fixed a crash when more than one custom mutator was used together
+ with afl_custom_post_process
+ - on a crashing seed potentially the wrong input was disabled
+ - added AFL_EXIT_ON_SEED_ISSUES env that will exit if a seed in
+ -i dir crashes the target or results in a timeout. By default
+ afl++ ignores these and uses them for splicing instead.
+ - added AFL_EXIT_ON_TIME env that will make afl-fuzz exit fuzzing
+ after no new paths have been found for n seconds
+ - when AFL_FAST_CAL is set a variable path will now be calibrated
+ 8 times instead of originally 40. Long calibration is now 20.
+ - added AFL_TRY_AFFINITY to try to bind to CPUs but don't error if
+ it fails
+ - afl-cc:
+ - We do not support llvm versions prior 6.0 anymore
+ - added thread safe counters to all modes (`AFL_LLVM_THREADSAFE_INST`),
+ note that this disables NeverZero counters.
+ - Fix for -pie compiled binaries with default afl-clang-fast PCGUARD
+ - Leak Sanitizer (AFL_USE_LSAN) added by Joshua Rogers, thanks!
+ - Removed InsTrim instrumentation as it is not as good as PCGUARD
+ - Removed automatic linking with -lc++ for LTO mode
+ - Fixed a crash in llvm dict2file when a strncmp length was -1
+ - added --afl-noopt support
+ - utils/aflpp_driver:
+ - aflpp_qemu_driver_hook fixed to work with qemu_mode
+ - aflpp_driver now compiled with -fPIC
+ - unicornafl:
+ - fix MIPS delay slot caching, thanks @JackGrence
+ - fixed aarch64 exit address
+ - execution no longer stops at address 0x0
+ - updated afl-system-config to support Arch Linux weirdness and increase
+ MacOS shared memory
+ - updated the grammar custom mutator to the newest version
+ - add -d (add dead fuzzer stats) to afl-whatsup
+ - added AFL_PRINT_FILENAMES to afl-showmap/cmin to print the
+ current filename
+ - afl-showmap/cmin will now process queue items in alphabetical order
+
### Version ++3.12c (release)
- afl-fuzz:
- added AFL_TARGET_ENV variable to pass extra env vars to the target
diff --git a/docs/INSTALL.md b/docs/INSTALL.md
index e3c06c9d..80d452f7 100644
--- a/docs/INSTALL.md
+++ b/docs/INSTALL.md
@@ -103,6 +103,41 @@ The llvm instrumentation requires a fully-operational installation of clang. The
comes with Xcode is missing some of the essential headers and helper tools.
See README.llvm.md for advice on how to build the compiler from scratch.
+MacOS X supports SYSV shared memory used by AFL's instrumentation, but the
+default settings aren't usable with AFL++. The default settings on 10.14 seem
+to be:
+
+```bash
+$ ipcs -M
+IPC status from as of XXX
+shminfo:
+ shmmax: 4194304 (max shared memory segment size)
+ shmmin: 1 (min shared memory segment size)
+ shmmni: 32 (max number of shared memory identifiers)
+ shmseg: 8 (max shared memory segments per process)
+ shmall: 1024 (max amount of shared memory in pages)
+```
+
+To temporarily change your settings to something minimally usable with AFL++,
+run these commands as root:
+
+```bash
+sysctl kern.sysv.shmmax=8388608
+sysctl kern.sysv.shmall=4096
+```
+
+If you're running more than one instance of AFL you likely want to make `shmall`
+bigger and increase `shmseg` as well:
+
+```bash
+sysctl kern.sysv.shmmax=8388608
+sysctl kern.sysv.shmseg=48
+sysctl kern.sysv.shmall=98304
+```
+
+See http://www.spy-hill.com/help/apple/SharedMemory.html for documentation for
+these settings and how to make them permanent.
+
## 4. Linux or *BSD on non-x86 systems
Standard build will fail on non-x86 systems, but you should be able to
diff --git a/docs/PATCHES.md b/docs/PATCHES.md
deleted file mode 100644
index b2cff43a..00000000
--- a/docs/PATCHES.md
+++ /dev/null
@@ -1,43 +0,0 @@
-# Applied Patches
-
-The following patches from https://github.com/vanhauser-thc/afl-patches
-have been installed or not installed:
-
-
-## INSTALLED
-```
-afl-llvm-fix.diff by kcwu(at)csie(dot)org
-afl-sort-all_uniq-fix.diff by legarrec(dot)vincent(at)gmail(dot)com
-laf-intel.diff by heiko(dot)eissfeldt(at)hexco(dot)de
-afl-llvm-optimize.diff by mh(at)mh-sec(dot)de
-afl-fuzz-tmpdir.diff by mh(at)mh-sec(dot)de
-afl-fuzz-79x24.diff by heiko(dot)eissfeldt(at)hexco(dot)de
-afl-fuzz-fileextensionopt.diff tbd
-afl-as-AFL_INST_RATIO.diff by legarrec(dot)vincent(at)gmail(dot)com
-afl-qemu-ppc64.diff by william(dot)barsse(at)airbus(dot)com
-afl-qemu-optimize-entrypoint.diff by mh(at)mh-sec(dot)de
-afl-qemu-speed.diff by abiondo on github
-afl-qemu-optimize-map.diff by mh(at)mh-sec(dot)de
-```
-
-+ llvm_mode ngram prev_loc coverage (github.com/adrianherrera/afl-ngram-pass)
-+ Custom mutator (native library) (by kyakdan)
-+ unicorn_mode (modernized and updated by domenukk)
-+ instrim (https://github.com/csienslab/instrim) was integrated
-+ MOpt (github.com/puppet-meteor/MOpt-AFL) was imported
-+ AFLfast additions (github.com/mboehme/aflfast) were incorporated.
-+ Qemu 3.1 upgrade with enhancement patches (github.com/andreafioraldi/afl)
-+ Python mutator modules support (github.com/choller/afl)
-+ Instrument file list in LLVM mode (github.com/choller/afl)
-+ forkserver patch for afl-tmin (github.com/nccgroup/TriforceAFL)
-
-
-## NOT INSTALLED
-
-```
-afl-fuzz-context_sensitive.diff - changes too much of the behaviour
-afl-tmpfs.diff - same as afl-fuzz-tmpdir.diff but more complex
-afl-cmin-reduce-dataset.diff - unsure of the impact
-afl-llvm-fix2.diff - not needed with the other patches
-```
-
diff --git a/docs/QuickStartGuide.md b/docs/QuickStartGuide.md
index 10be409a..d1966170 100644
--- a/docs/QuickStartGuide.md
+++ b/docs/QuickStartGuide.md
@@ -1,6 +1,6 @@
# AFL quick start guide
-You should read [README.md](README.md) - it's pretty short. If you really can't, here's
+You should read [README.md](../README.md) - it's pretty short. If you really can't, here's
how to hit the ground running:
1) Compile AFL with 'make'. If build fails, see [INSTALL.md](INSTALL.md) for tips.
diff --git a/docs/binaryonly_fuzzing.md b/docs/binaryonly_fuzzing.md
index 787d970d..11e1dbeb 100644
--- a/docs/binaryonly_fuzzing.md
+++ b/docs/binaryonly_fuzzing.md
@@ -41,6 +41,33 @@
As it is included in afl++ this needs no URL.
+ If you like to code a customized fuzzer without much work, we highly
+ recommend to check out our sister project libafl which will support QEMU
+ too:
+ [https://github.com/AFLplusplus/LibAFL](https://github.com/AFLplusplus/LibAFL)
+
+
+## AFL FRIDA
+
+ In frida_mode you can fuzz binary-only targets easily like with QEMU,
+ with the advantage that frida_mode also works on MacOS (both intel and M1).
+
+ If you want to fuzz a binary-only library then you can fuzz it with
+ frida-gum via utils/afl_frida/, you will have to write a harness to
+ call the target function in the library, use afl-frida.c as a template.
+
+ Both come with afl++ so this needs no URL.
+
+ You can also perform remote fuzzing with frida, e.g. if you want to fuzz
+ on iPhone or Android devices, for this you can use
+ [https://github.com/ttdennis/fpicker/](https://github.com/ttdennis/fpicker/)
+ as an intermediate that uses afl++ for fuzzing.
+
+ If you like to code a customized fuzzer without much work, we highly
+ recommend to check out our sister project libafl which supports Frida too:
+ [https://github.com/AFLplusplus/LibAFL](https://github.com/AFLplusplus/LibAFL)
+ Working examples already exist :-)
+
## WINE+QEMU
@@ -62,13 +89,6 @@
As it is included in afl++ this needs no URL.
-## AFL FRIDA
-
- If you want to fuzz a binary-only shared library then you can fuzz it with
- frida-gum via utils/afl_frida/, you will have to write a harness to
- call the target function in the library, use afl-frida.c as a template.
-
-
## AFL UNTRACER
If you want to fuzz a binary-only shared library then you can fuzz it with
@@ -157,19 +177,6 @@
If anyone finds any coresight implementation for afl please ping me: vh@thc.org
-## FRIDA
-
- Frida is a dynamic instrumentation engine like Pintool, Dyninst and Dynamorio.
- What is special is that it is written Python, and scripted with Javascript.
- It is mostly used to reverse binaries on mobile phones however can be used
- everywhere.
-
- There is a WIP fuzzer available at [https://github.com/andreafioraldi/frida-fuzzer](https://github.com/andreafioraldi/frida-fuzzer)
-
- There is also an early implementation in an AFL++ test branch:
- [https://github.com/AFLplusplus/AFLplusplus/tree/frida](https://github.com/AFLplusplus/AFLplusplus/tree/frida)
-
-
## PIN & DYNAMORIO
Pintool and Dynamorio are dynamic instrumentation engines, and they can be
@@ -205,7 +212,8 @@
* QSYM: [https://github.com/sslab-gatech/qsym](https://github.com/sslab-gatech/qsym)
* Manticore: [https://github.com/trailofbits/manticore](https://github.com/trailofbits/manticore)
* S2E: [https://github.com/S2E](https://github.com/S2E)
- * Tinyinst [https://github.com/googleprojectzero/TinyInst](https://github.com/googleprojectzero/TinyInst) (Mac/Windows only)
+ * Tinyinst: [https://github.com/googleprojectzero/TinyInst](https://github.com/googleprojectzero/TinyInst) (Mac/Windows only)
+ * Jackalope: [https://github.com/googleprojectzero/Jackalope](https://github.com/googleprojectzero/Jackalope)
* ... please send me any missing that are good
diff --git a/docs/custom_mutators.md b/docs/custom_mutators.md
index 61d711e4..129d6676 100644
--- a/docs/custom_mutators.md
+++ b/docs/custom_mutators.md
@@ -89,11 +89,14 @@ def queue_get(filename):
def queue_new_entry(filename_new_queue, filename_orig_queue):
pass
-```
def introspection():
return string
+def deinit(): # optional for Python
+ pass
+```
+
### Custom Mutation
- `init`:
@@ -120,6 +123,7 @@ def introspection():
Note that this function is optional - but it makes sense to use it.
You would only skip this if `post_process` is used to fix checksums etc.
so if you are using it e.g. as a post processing library.
+ Note that a length > 0 *must* be returned!
- `describe` (optional):
@@ -285,8 +289,8 @@ afl-fuzz /path/to/program
## 4) Example
-Please see [example.c](../utils/custom_mutators/example.c) and
-[example.py](../utils/custom_mutators/example.py)
+Please see [example.c](../custom_mutators/examples/example.c) and
+[example.py](../custom_mutators/examples/example.py)
## 5) Other Resources
diff --git a/docs/env_variables.md b/docs/env_variables.md
index 409425f1..38a67bc7 100644
--- a/docs/env_variables.md
+++ b/docs/env_variables.md
@@ -55,7 +55,7 @@ make fairly broad use of environmental variables instead:
overridden.
- Setting `AFL_USE_ASAN` automatically enables ASAN, provided that your
- compiler supports that. Note that fuzzing with ASAN is mildly challenging
+ compiler supports it. Note that fuzzing with ASAN is mildly challenging
- see [notes_for_asan.md](notes_for_asan.md).
(You can also enable MSAN via `AFL_USE_MSAN`; ASAN and MSAN come with the
@@ -64,6 +64,13 @@ make fairly broad use of environmental variables instead:
there is the Control Flow Integrity sanitizer that can be activated by
`AFL_USE_CFISAN=1`)
+ - Setting `AFL_USE_LSAN` automatically enables Leak-Sanitizer, provided
+ that your compiler supports it. To perform a leak check within your
+ program at a certain point (such as at the end of an __AFL_LOOP),
+ you can run the macro __AFL_LEAK_CHECK(); which will cause
+ an abort if any memory is leaked (you can combine this with the
+ LSAN_OPTIONS=suppressions option to supress some known leaks).
+
- Setting `AFL_CC`, `AFL_CXX`, and `AFL_AS` lets you use alternate downstream
compilation tools, rather than the default 'clang', 'gcc', or 'as' binaries
in your `$PATH`.
@@ -130,16 +137,15 @@ Then there are a few specific features that are only available in instrumentatio
PCGUARD - our own pcgard based instrumentation (default)
NATIVE - clang's original pcguard based instrumentation
CLASSIC - classic AFL (map[cur_loc ^ prev_loc >> 1]++) (default)
- CFG - InsTrim instrumentation (see below)
LTO - LTO instrumentation (see below)
CTX - context sensitive instrumentation (see below)
NGRAM-x - deeper previous location coverage (from NGRAM-2 up to NGRAM-16)
GCC - outdated gcc instrumentation
CLANG - outdated clang instrumentation
- In CLASSIC (default) and CFG/INSTRIM you can also specify CTX and/or
- NGRAM, seperate the options with a comma "," then, e.g.:
- `AFL_LLVM_INSTRUMENT=CFG,CTX,NGRAM-4`
- Not that this is a good idea to use both CTX and NGRAM :)
+ In CLASSIC you can also specify CTX and/or NGRAM, seperate the options
+ with a comma "," then, e.g.:
+ `AFL_LLVM_INSTRUMENT=CLASSIC,CTX,NGRAM-4`
+ Note that this is actually not a good idea to use both CTX and NGRAM :)
### LTO
@@ -173,24 +179,6 @@ Then there are a few specific features that are only available in instrumentatio
See [instrumentation/README.lto.md](../instrumentation/README.lto.md) for more information.
-### INSTRIM
-
- This feature increases the speed by ~15% without any disadvantages to the
- classic instrumentation.
-
- Note that there is also an LTO version (if you have llvm 11 or higher) -
- that is the best instrumentation we have. Use `afl-clang-lto` to activate.
- The InsTrim LTO version additionally has all the options and features of
- LTO (see above).
-
- - Setting `AFL_LLVM_INSTRIM` or `AFL_LLVM_INSTRUMENT=CFG` activates this mode
-
- - Setting `AFL_LLVM_INSTRIM_LOOPHEAD=1` expands on INSTRIM to optimize loops.
- afl-fuzz will only be able to see the path the loop took, but not how
- many times it was called (unless it is a complex loop).
-
- See [instrumentation/README.instrim.md](../instrumentation/README.instrim.md)
-
### NGRAM
- Setting `AFL_LLVM_NGRAM_SIZE` or `AFL_LLVM_INSTRUMENT=NGRAM-{value}`
@@ -243,6 +231,12 @@ Then there are a few specific features that are only available in instrumentatio
See [instrumentation/README.instrument_list.md](../instrumentation/README.instrument_list.md) for more information.
+### Thread safe instrumentation counters (in all modes)
+
+ - Setting `AFL_LLVM_THREADSAFE_INST` will inject code that implements thread
+ safe counters. The overhead is a little bit higher compared to the older
+ non-thread safe case. Note that this disables neverzero (see below).
+
### NOT_ZERO
- Setting `AFL_LLVM_NOT_ZERO=1` during compilation will use counters
@@ -296,6 +290,13 @@ checks or alter some of the more exotic semantics of the tool:
normally indicated by the cycle counter in the UI turning green. May be
convenient for some types of automated jobs.
+ - `AFL_EXIT_ON_TIME` Causes afl-fuzz to terminate if no new paths were
+ found within a specified period of time (in seconds). May be convenient
+ for some types of automated jobs.
+
+ - `AFL_EXIT_ON_SEED_ISSUES` will restore the vanilla afl-fuzz behaviour
+ which does not allow crashes or timeout seeds in the initial -i corpus.
+
- `AFL_MAP_SIZE` sets the size of the shared map that afl-fuzz, afl-showmap,
afl-tmin and afl-analyze create to gather instrumentation data from
the target. This must be equal or larger than the size the target was
@@ -317,14 +318,12 @@ checks or alter some of the more exotic semantics of the tool:
on Linux systems. This slows things down, but lets you run more instances
of afl-fuzz than would be prudent (if you really want to).
+ - Setting `AFL_TRY_AFFINITY` tries to attempt binding to a specific CPU core
+ on Linux systems, but will not terminate if that fails.
+
- Setting `AFL_NO_AUTODICT` will not load an LTO generated auto dictionary
that is compiled into the target.
- - `AFL_SKIP_CRASHES` causes AFL++ to tolerate crashing files in the input
- queue. This can help with rare situations where a program crashes only
- intermittently, but it's not really recommended under normal operating
- conditions.
-
- Setting `AFL_HANG_TMOUT` allows you to specify a different timeout for
deciding if a particular test case is a "hang". The default is 1 second
or the value of the `-t` parameter, whichever is larger. Dialing the value
@@ -360,6 +359,7 @@ checks or alter some of the more exotic semantics of the tool:
and shell scripts; and `AFL_DUMB_FORKSRV` in conjunction with the `-n`
setting to instruct afl-fuzz to still follow the fork server protocol
without expecting any instrumentation data in return.
+ Note that this also turns off auto map size detection.
- When running in the `-M` or `-S` mode, setting `AFL_IMPORT_FIRST` causes the
fuzzer to import test cases from other instances before doing anything
@@ -391,7 +391,8 @@ checks or alter some of the more exotic semantics of the tool:
may complain of high load prematurely, especially on systems with low core
counts. To avoid the alarming red color, you can set `AFL_NO_CPU_RED`.
- - In QEMU mode (-Q), `AFL_PATH` will be searched for afl-qemu-trace.
+ - In QEMU mode (-Q) and Frida mode (-O), `AFL_PATH` will
+ be searched for afl-qemu-trace and afl-frida-trace.so.
- In QEMU mode (-Q), setting `AFL_QEMU_CUSTOM_BIN` cause afl-fuzz to skip
prepending `afl-qemu-trace` to your command line. Use this if you wish to use a
@@ -424,6 +425,16 @@ checks or alter some of the more exotic semantics of the tool:
- Setting `AFL_FORCE_UI` will force painting the UI on the screen even if
no valid terminal was detected (for virtual consoles)
+ - If you are using persistent mode (you should, see [instrumentation/README.persistent_mode.md](instrumentation/README.persistent_mode.md))
+ some targets keep inherent state due which a detected crash testcase does
+ not crash the target again when the testcase is given. To be able to still
+ re-trigger these crashes you can use the `AFL_PERSISTENT_RECORD` variable
+ with a value of how many previous fuzz cases to keep prio a crash.
+ if set to e.g. 10, then the 9 previous inputs are written to
+ out/default/crashes as RECORD:000000,cnt:000000 to RECORD:000000,cnt:000008
+ and RECORD:000000,cnt:000009 being the crash case.
+ NOTE: This option needs to be enabled in config.h first!
+
- If you are Jakub, you may need `AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES`.
Others need not apply, unless they also want to disable the
`/proc/sys/kernel/core_pattern` check.
@@ -561,6 +572,9 @@ The corpus minimization script offers very little customization:
a modest security risk on multi-user systems with rogue users, but should
be safe on dedicated fuzzing boxes.
+ - `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 scripting.
+
## 7) Settings for afl-tmin
Virtually nothing to play with. Well, in QEMU mode (`-Q`), `AFL_PATH` will be
@@ -614,7 +628,7 @@ optimal values if not already present in the environment:
override this by setting `LD_BIND_LAZY` beforehand, but it is almost
certainly pointless.
- - By default, `ASAN_OPTIONS` are set to:
+ - By default, `ASAN_OPTIONS` are set to (among others):
```
abort_on_error=1
detect_leaks=0
@@ -635,7 +649,14 @@ optimal values if not already present in the environment:
msan_track_origins=0
allocator_may_return_null=1
```
- Be sure to include the first one when customizing anything, since some
- MSAN versions don't call `abort()` on error, and we need a way to detect
- faults.
+ - Similarly, the default `LSAN_OPTIONS` are set to:
+```
+ exit_code=23
+ fast_unwind_on_malloc=0
+ symbolize=0
+ print_suppressions=0
+```
+ Be sure to include the first ones for LSAN and MSAN when customizing
+ anything, since some MSAN and LSAN versions don't call `abort()` on
+ error, and we need a way to detect faults.
diff --git a/docs/ideas.md b/docs/ideas.md
index 0130cf61..e25d3ba6 100644
--- a/docs/ideas.md
+++ b/docs/ideas.md
@@ -3,42 +3,6 @@
In the following, we describe a variety of ideas that could be implemented
for future AFL++ versions.
-# GSoC 2021
-
-All GSoC 2021 projects will be in the Rust development language!
-
-## UI for libaflrs
-
-Write a user interface to libaflrs, the upcoming backend of afl++.
-This might look like the afl-fuzz UI, but you can improve on it - and should!
-
-## Schedulers for libaflrs
-
-Schedulers is a mechanism that selects items from the fuzzing corpus based
-on strategy and randomness. One scheduler might focus on long paths,
-another on rarity of edges disocvered, still another on a combination on
-things. Some of the schedulers in afl++ have to be ported, but you are free
-to come up with your own if you want to - and see how it performs.
-
-## Forkserver support for libaflrs
-
-The current libaflrs implementation fuzzes in-memory, however obviously we
-want to support afl instrumented binaries as well.
-Hence a forkserver support needs to be implemented - forking off the target
-and talking to the target via a socketpair and the communication protocol
-within.
-
-## More Observers for libaflrs
-
-An observer is measuring functionality that looks at the target being fuzzed
-and documents something about it. In traditional fuzzing this is the coverage
-in the target, however we want to add various more observers, e.g. stack depth,
-heap usage, etc. - this is a topic for an experienced Rust developer.
-
-# Generic ideas and wishlist - NOT PART OF GSoC 2021 !
-
-The below list is not part of GSoC 2021.
-
## Analysis software
Currently analysis is done by using afl-plot, which is rather outdated.
@@ -65,6 +29,13 @@ the current Unicorn instrumentation.
Mentor: any
+## Support other programming languages
+
+Other programming languages also use llvm hence they could (easily?) supported
+for fuzzing, e.g. mono, swift, go, kotlin native, fortran, ...
+
+Mentor: vanhauser-thc
+
## Machine Learning
Something with machine learning, better than [NEUZZ](https://github.com/dongdongshe/neuzz) :-)
diff --git a/docs/life_pro_tips.md b/docs/life_pro_tips.md
index 50ad75d4..13ffcea0 100644
--- a/docs/life_pro_tips.md
+++ b/docs/life_pro_tips.md
@@ -83,5 +83,5 @@ You can find a simple solution in utils/argv_fuzzing.
## Attacking a format that uses checksums?
Remove the checksum-checking code or use a postprocessor!
-See utils/custom_mutators/ for more.
+See `afl_custom_post_process` in custom_mutators/examples/example.c for more.
diff --git a/docs/notes_for_asan.md b/docs/notes_for_asan.md
index 2b3bc028..f55aeaf2 100644
--- a/docs/notes_for_asan.md
+++ b/docs/notes_for_asan.md
@@ -28,6 +28,13 @@ Note that ASAN is incompatible with -static, so be mindful of that.
(You can also use AFL_USE_MSAN=1 to enable MSAN instead.)
+When compiling with AFL_USE_LSAN, the leak sanitizer will normally run
+when the program exits. In order to utilize this check at different times,
+such as at the end of a loop, you may use the macro __AFL_LEAK_CHECK();.
+This macro will report a crash in afl-fuzz if any memory is left leaking
+at this stage. You can also use LSAN_OPTIONS and a supressions file
+for more fine-tuned checking, however make sure you keep exitcode=23.
+
NOTE: if you run several secondary instances, only one should run the target
compiled with ASAN (and UBSAN, CFISAN), the others should run the target with
no sanitizers compiled in.
diff --git a/docs/perf_tips.md b/docs/perf_tips.md
index fbcb4d8d..c5968206 100644
--- a/docs/perf_tips.md
+++ b/docs/perf_tips.md
@@ -69,9 +69,6 @@ If you are only interested in specific parts of the code being fuzzed, you can
instrument_files the files that are actually relevant. This improves the speed and
accuracy of afl. See instrumentation/README.instrument_list.md
-Also use the InsTrim mode on larger binaries, this improves performance and
-coverage a lot.
-
## 4. Profile and optimize the binary
Check for any parameters or settings that obviously improve performance. For
diff --git a/docs/status_screen.md b/docs/status_screen.md
index 0329d960..e3abcc5f 100644
--- a/docs/status_screen.md
+++ b/docs/status_screen.md
@@ -251,8 +251,9 @@ exceed it by a margin sufficient to be classified as hangs.
| arithmetics : 53/2.54M, 0/537k, 0/55.2k |
| known ints : 8/322k, 12/1.32M, 10/1.70M |
| dictionary : 9/52k, 1/53k, 1/24k |
- | havoc : 1903/20.0M, 0/0 |
- | trim : 20.31%/9201, 17.05% |
+ |havoc/splice : 1903/20.0M, 0/0 |
+ |py/custom/rq : unused, 53/2.54M, unused |
+ | trim/eff : 20.31%/9201, 17.05% |
+-----------------------------------------------------+
```
@@ -268,6 +269,12 @@ goal. Finally, the third number shows the proportion of bytes that, although
not possible to remove, were deemed to have no effect and were excluded from
some of the more expensive deterministic fuzzing steps.
+Note that when deterministic mutation mode is off (which is the default
+because it is not very efficient) the first five lines display
+"disabled (default, enable with -D)".
+
+Only what is activated will have counter shown.
+
### Path geometry
```
diff --git a/dynamic_list.txt b/dynamic_list.txt
index f0e54d92..d1905d43 100644
--- a/dynamic_list.txt
+++ b/dynamic_list.txt
@@ -21,6 +21,7 @@
"__afl_coverage_interesting";
"__afl_fuzz_len";
"__afl_fuzz_ptr";
+ "__afl_sharedmem_fuzzing";
"__sanitizer_cov_trace_pc_guard";
"__sanitizer_cov_trace_pc_guard_init";
"__cmplog_ins_hook1";
diff --git a/frida_mode/.gitignore b/frida_mode/.gitignore
new file mode 100644
index 00000000..956b9911
--- /dev/null
+++ b/frida_mode/.gitignore
@@ -0,0 +1,5 @@
+build/
+frida_test.dat
+qemu_test.dat
+frida_out/**
+qemu_out/**
diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile
new file mode 100644
index 00000000..a0387cac
--- /dev/null
+++ b/frida_mode/GNUmakefile
@@ -0,0 +1,188 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)..)/
+INC_DIR:=$(PWD)include/
+SRC_DIR:=$(PWD)src/
+INCLUDES:=$(wildcard $(INC_DIR)*.h)
+BUILD_DIR:=$(PWD)build/
+OBJ_DIR:=$(BUILD_DIR)obj/
+
+SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c)
+OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src))))
+CFLAGS+=-fPIC \
+ -D_GNU_SOURCE \
+ -D_FORTIFY_SOURCE=2 \
+ -g \
+ -O3 \
+ -funroll-loops \
+
+RT_CFLAGS:=-Wno-unused-parameter \
+ -Wno-sign-compare \
+ -Wno-unused-function \
+ -Wno-unused-result \
+ -Wno-int-to-pointer-cast \
+
+LDFLAGS+=-shared \
+ -lpthread \
+ -lresolv \
+ -ldl \
+ -z noexecstack \
+
+ifdef DEBUG
+CFLAGS+=-Werror \
+ -Wall \
+ -Wextra \
+ -Wpointer-arith
+else
+CFLAGS+=-Wno-pointer-arith
+endif
+
+FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/
+FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so
+FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+ifeq "$(shell uname)" "Darwin"
+ OS:=macos
+ RT_CFLAGS:=$(RT_CFLAGS) -Wno-deprecated-declarations
+else
+ifdef DEBUG
+ RT_CFLAGS:=$(RT_CFLAGS) -Wno-prio-ctor-dtor
+endif
+endif
+
+ifeq "$(shell uname)" "Linux"
+ OS:=linux
+endif
+
+ifndef OS
+ $(error "Operating system unsupported")
+endif
+
+GUM_DEVKIT_VERSION=14.2.18
+GUM_DEVKIT_FILENAME=frida-gum-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz
+GUM_DEVKIT_URL="https://github.com/frida/frida/releases/download/$(GUM_DEVKIT_VERSION)/$(GUM_DEVKIT_FILENAME)"
+
+GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME)
+GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gum.a
+GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gum.h
+
+FRIDA_DIR:=$(PWD)build/frida-source/
+FRIDA_MAKEFILE:=$(FRIDA_DIR)Makefile
+FRIDA_GUM:=$(FRIDA_DIR)build/frida-linux-x86_64/lib/libfrida-gum-1.0.a
+FRIDA_GUM_DEVKIT_DIR:=$(FRIDA_DIR)build/gum-devkit/
+FRIDA_GUM_DEVKIT_HEADER:=$(FRIDA_GUM_DEVKIT_DIR)frida-gum.h
+FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gum-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar
+FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL:=$(FRIDA_DIR)build/$(GUM_DEVKIT_FILENAME)
+
+AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c
+AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o
+
+.PHONY: all 32 clean format $(FRIDA_GUM)
+
+############################## ALL #############################################
+
+all: $(FRIDA_TRACE)
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $(BUILD_DIR)
+
+$(OBJ_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+############################# FRIDA ############################################
+
+$(FRIDA_MAKEFILE): | $(BUILD_DIR)
+ git clone --recursive https://github.com/frida/frida.git $(FRIDA_DIR)
+
+$(FRIDA_GUM): $(FRIDA_MAKEFILE)
+ cd $(FRIDA_DIR) && make gum-linux-$(ARCH)
+
+$(FRIDA_GUM_DEVKIT_HEADER): $(FRIDA_GUM)
+ $(FRIDA_DIR)releng/devkit.py frida-gum linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/
+
+$(FRIDA_GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_HEADER)
+ cd $(FRIDA_GUM_DEVKIT_DIR) && tar cvf $(FRIDA_GUM_DEVKIT_TARBALL) .
+
+$(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL): $(FRIDA_GUM_DEVKIT_TARBALL)
+ xz -k -f -0 $(FRIDA_GUM_DEVKIT_TARBALL)
+
+############################# DEVKIT ###########################################
+
+$(FRIDA_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+ifdef FRIDA_SOURCE
+$(GUM_DEVKIT_TARBALL): $(FRIDA_GUM_DEVKIT_COMPRESSED_TARBALL)| $(FRIDA_BUILD_DIR)
+ cp -v $< $@
+else
+$(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR)
+ wget -O $@ $(GUM_DEVKIT_URL)
+endif
+
+$(GUM_DEVIT_LIBRARY): | $(GUM_DEVKIT_TARBALL)
+ tar Jxvf $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
+
+$(GUM_DEVIT_HEADER): | $(GUM_DEVKIT_TARBALL)
+ tar Jxvf $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR)
+
+############################## AFL #############################################
+$(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC)
+ $(CC) \
+ $(CFLAGS) \
+ $(RT_CFLAGS) \
+ -I $(ROOT) \
+ -I $(ROOT)include \
+ -o $@ \
+ -c $<
+
+############################# SOURCE ###########################################
+
+define BUILD_SOURCE
+$(2): $(1) $(INCLUDES) GNUmakefile | $(OBJ_DIR)
+ $(CC) \
+ $(CFLAGS) \
+ -I $(ROOT)include \
+ -I $(FRIDA_BUILD_DIR) \
+ -I $(INC_DIR) \
+ -c $1 \
+ -o $2
+endef
+
+$(foreach src,$(SOURCES),$(eval $(call BUILD_SOURCE,$(src),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src))))))
+
+######################## AFL-FRIDA-TRACE #######################################
+
+$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR)
+ $(CC) \
+ $(OBJS) \
+ $(GUM_DEVIT_LIBRARY) \
+ $(AFL_COMPILER_RT_OBJ) \
+ $(LDFLAGS) \
+ -o $@ \
+
+ cp -v $(FRIDA_TRACE) $(ROOT)
+
+############################# CLEAN ############################################
+clean:
+ rm -rf $(BUILD_DIR)
+
+############################# FORMAT ###########################################
+format:
+ cd $(ROOT) && echo $(SOURCES) | xargs -L1 ./.custom-format.py -i
+ cd $(ROOT) && echo $(INCLUDES) | xargs -L1 ./.custom-format.py -i
+
+############################# RUN #############################################
diff --git a/frida_mode/Makefile b/frida_mode/Makefile
new file mode 100644
index 00000000..6cd1a64e
--- /dev/null
+++ b/frida_mode/Makefile
@@ -0,0 +1,13 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+format:
+ @gmake format
diff --git a/frida_mode/README.md b/frida_mode/README.md
new file mode 100644
index 00000000..0103a395
--- /dev/null
+++ b/frida_mode/README.md
@@ -0,0 +1,294 @@
+# FRIDA MODE
+
+The purpose of FRIDA mode is to provide an alternative binary only fuzzer for
+AFL just like that provided by QEMU mode. The intention is to provide a very
+similar user experience, right down to the options provided through environment
+variables.
+
+Whilst AFLplusplus already has some support for running on FRIDA [here](https://github.com/AFLplusplus/AFLplusplus/tree/stable/utils/afl_frida)
+this requires the code to be fuzzed to be provided as a shared library, it
+cannot be used to fuzz executables. Additionally, it requires the user to write
+a small harness around their target code of interest.
+FRIDA mode instead takes a different approach to avoid these limitations.
+In Frida mode binary programs are instrumented, similarly to QEMU mode.
+
+## Current Progress
+
+As FRIDA mode is new, it is missing a lot of features. The design is such that it
+should be possible to add these features in a similar manner to QEMU mode and
+perhaps leverage some of its design and implementation.
+
+ | Feature/Instrumentation | frida-mode | Notes |
+ | -------------------------|:----------:|:--------------------------------------------:|
+ | NeverZero | x | |
+ | Persistent Mode | x | (x86/x64 only)(Only on function boundaries) |
+ | LAF-Intel / CompCov | - | (CMPLOG is better 90% of the time) |
+ | CMPLOG | x | (x86/x64 only) |
+ | Selective Instrumentation| x | |
+ | Non-Colliding Coverage | - | (Not possible in binary-only instrumentation |
+ | Ngram prev_loc Coverage | - | |
+ | Context Coverage | - | |
+ | Auto Dictionary | - | |
+ | Snapshot LKM Support | - | |
+ | In-Memory Test Cases | x | (x86/x64 only) |
+
+## Compatibility
+Currently FRIDA mode supports Linux and macOS targets on both x86/x64
+architecture and aarch64. Later releases may add support for aarch32 and Windows
+targets as well as embedded linux environments.
+
+FRIDA has been used on various embedded targets using both uClibc and musl C
+runtime libraries, so porting should be possible. However, the current build
+system does not support cross compilation.
+
+## Getting Started
+
+To build everything run `make`. To build for x86 run `make 32`. Note that in
+x86 bit mode, it is not necessary for afl-fuzz to be built for 32-bit. However,
+the shared library for frida_mode must be since it is injected into the target
+process.
+
+Various tests can be found in subfolders within the `test/` directory. To use
+these, first run `make` to build any dependencies. Then run `make qemu` or
+`make frida` to run on either QEMU of FRIDA mode respectively. To run frida
+tests in 32-bit mode, run `make ARCH=x86 frida`. When switching between
+architectures it may be necessary to run `make clean` first for a given build
+target to remove previously generated binaries for a different architecture.
+
+## Usage
+
+FRIDA mode added some small modifications to `afl-fuzz` and similar tools
+in AFLplusplus. The intention was that it behaves identically to QEMU, but it uses
+the 'O' switch rather than 'Q'. Whilst the options 'f', 'F', 's' or 'S' may have
+made more sense for a mode powered by FRIDA Stalker, they were all taken, so
+instead we use 'O' in hommage to the [author](https://github.com/oleavr) of
+FRIDA.
+
+Similarly, the intention is to mimic the use of environment variables used by
+QEMU where possible (by replacing `s/QEMU/FRIDA/g`). Accordingly, the
+following options are currently supported:
+
+* `AFL_FRIDA_DEBUG_MAPS` - See `AFL_QEMU_DEBUG_MAPS`
+* `AFL_FRIDA_EXCLUDE_RANGES` - See `AFL_QEMU_EXCLUDE_RANGES`
+* `AFL_FRIDA_INST_RANGES` - See `AFL_QEMU_INST_RANGES`
+* `AFL_FRIDA_PERSISTENT_ADDR` - See `AFL_QEMU_PERSISTENT_ADDR`
+* `AFL_FRIDA_PERSISTENT_CNT` - See `AFL_QEMU_PERSISTENT_CNT`
+* `AFL_FRIDA_PERSISTENT_HOOK` - See `AFL_QEMU_PERSISTENT_HOOK`
+* `AFL_FRIDA_PERSISTENT_RET` - See `AFL_QEMU_PERSISTENT_RET`
+* `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` - See `AFL_QEMU_PERSISTENT_RETADDR_OFFSET`
+
+To enable the powerful CMPLOG mechanism, set `-c 0` for `afl-fuzz`.
+
+## Performance
+
+Additionally, the intention is to be able to make a direct performance
+comparison between the two approaches. Accordingly, FRIDA mode includes various
+test targets based on the [libpng](https://libpng.sourceforge.io/) benchmark
+used by [fuzzbench](https://google.github.io/fuzzbench/) and integrated with the
+[StandaloneFuzzTargetMain](https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c)
+from the llvm project. These tests include basic fork-server support, persistent
+mode and persistent mode with in-memory test-cases. These are built and linked
+without any special modifications to suit FRIDA or QEMU. The test data provided
+with libpng is used as the corpus.
+
+The intention is to add support for FRIDA mode to the FuzzBench project and
+perform a like-for-like comparison with QEMU mode to get an accurate
+appreciation of its performance.
+
+## Design
+
+FRIDA mode is supported by using `LD_PRELOAD` (`DYLD_INSERT_LIBRARIES` on macOS)
+to inject a shared library (`afl-frida-trace.so`) into the target. This shared
+library is built using the [frida-gum](https://github.com/frida/frida-gum)
+devkit from the [FRIDA](https://github.com/frida/frida) project. One of the
+components of frida-gum is [Stalker](https://medium.com/@oleavr/anatomy-of-a-code-tracer-b081aadb0df8),
+this allows the dynamic instrumentation of running code for AARCH32, AARCH64,
+x86 and x64 architectures. Implementation details can be found
+[here](https://frida.re/docs/stalker/).
+
+Dynamic instrumentation is used to augment the target application with similar
+coverage information to that inserted by `afl-gcc` or `afl-clang`. The shared
+library is also linked to the `compiler-rt` component of AFLplusplus to feedback
+this coverage information to AFL++ and also provide a fork server. It also makes
+use of the FRIDA [prefetch](https://github.com/frida/frida-gum/blob/56dd9ba3ee9a5511b4b0c629394bf122775f1ab7/gum/gumstalker.h#L115)
+support to feedback instrumented blocks from the child to the parent using a
+shared memory region to avoid the need to regenerate instrumented blocks on each
+fork.
+
+Whilst FRIDA allows for a normal C function to be used to augment instrumented
+code, FRIDA mode instead makes use of optimized assembly instead on AARCH64 and
+x86/64 targets. By injecting these small snippets of assembly, we avoid having
+to push and pop the full register context. Note that since this instrumentation
+is used on every basic block to generate coverage, it has a large impact on
+performance.
+
+CMPLOG support also adds code to the assembly, however, at present this code
+makes use of a basic C function and is yet to be optimized. Since not all
+instances run CMPLOG mode and instrumentation of the binary is less frequent
+(only on CMP, SUB and CALL instructions) performance is not quite so critical.
+
+## Advanced configuration options
+
+* `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks
+and their instrumented counterparts during block compilation.
+```
+***
+
+Creating block for 0x7ffff7953313:
+ 0x7ffff7953313 mov qword ptr [rax], 0
+ 0x7ffff795331a add rsp, 8
+ 0x7ffff795331e ret
+
+Generated block 0x7ffff75e98e2
+ 0x7ffff75e98e2 mov qword ptr [rax], 0
+ 0x7ffff75e98e9 add rsp, 8
+ 0x7ffff75e98ed lea rsp, [rsp - 0x80]
+ 0x7ffff75e98f5 push rcx
+ 0x7ffff75e98f6 movabs rcx, 0x7ffff795331e
+ 0x7ffff75e9900 jmp 0x7ffff75e9384
+
+
+***
+```
+* `AFL_FRIDA_INST_NO_OPTIMIZE` - Don't use optimized inline assembly coverage
+instrumentation (the default where available). Required to use
+`AFL_FRIDA_INST_TRACE`.
+* `AFL_FRIDA_INST_NO_PREFETCH` - Disable prefetching. By default the child will
+report instrumented blocks back to the parent so that it can also instrument
+them and they be inherited by the next child on fork.
+* `AFL_FRIDA_INST_TRACE` - Log to stdout the address of executed blocks
+`AFL_FRIDA_INST_NO_OPTIMIZE`.
+* `AFL_FRIDA_OUTPUT_STDOUT` - Redirect the standard output of the target
+application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`)
+* `AFL_FRIDA_OUTPUT_STDERR` - Redirect the standard error of the target
+application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`)
+* `AFL_FRIDA_PERSISTENT_DEBUG` - Insert a Breakpoint into the instrumented code
+at `AFL_FRIDA_PERSISTENT_HOOK` and `AFL_FRIDA_PERSISTENT_RET` to allow the user
+to determine the value of `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` using a
+debugger.
+
+```
+
+gdb \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=XXXXXXXXXX' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_RET=XXXXXXXXXX' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_DEBUG=1' \
+ --ex 'set environment AFL_DEBUG_CHILD=1' \
+ --ex 'set environment LD_PRELOAD=afl-frida-trace.so' \
+ --args [my arguments]
+
+```
+* `AFL_FRIDA_STATS_FILE` - Write statistics information about the code being
+instrumented to the given file name. The statistics are written only for the
+child process when new block is instrumented (when the
+`AFL_FRIDA_STATS_INTERVAL` has expired). Note that simply because a new path is
+found does not mean a new block needs to be compiled. It could simply be that
+the existing blocks instrumented have been executed in a different order.
+```
+stats
+-----
+Index: 2
+Pid: 1815944
+Time: 2021-05-28 15:26:41
+Blocks: 1985
+Instructions: 9192
+Avg Instructions / Block: 4
+
+Call Immediates: 391 (4.25%)
+Call Immediates Excluded: 65 (0.71%)
+Call Register: 0 (0.00%)
+Call Memory: 0 (0.00%)
+
+Jump Immediates: 202 (2.20%)
+Jump Register: 10 (0.11%)
+Jump Memory: 12 (0.13%)
+
+Conditional Jump Immediates: 1210 (13.16%)
+Conditional Jump CX Immediate: 0 (0.00%)
+Conditional Jump Register: 0 (0.00%)
+Conditional Jump Memory: 0 (0.00%)
+
+Returns: 159 (0.00%)
+
+Rip Relative: 247 (0.00%)
+
+```
+* `AFL_FRIDA_STATS_INTERVAL` - The maximum frequency to output statistics
+information. Stats will be written whenever they are updated if the given
+interval has elapsed since last time they were written.
+* `AFL_FRIDA_STATS_TRANSITIONS` - Also dump the internal stalker counters to
+stderr when the regular stats are written. Note that these stats are reset in
+the child each time a new fork occurs since they are not stored in shared
+memory. Unfortunately, these stats are internal to stalker, so this is the best
+we can do for now.
+```
+stats
+-----
+Index: 2
+Pid: 1816794
+Time: 2021-05-28 15:26:41
+
+
+total_transitions: 786
+ call_imms: 97
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 86
+ excluded_call_imms: 29
+ ret_slow_paths: 23
+
+ jmp_imms: 58
+ jmp_mems: 7
+ jmp_regs: 26
+
+ jmp_cond_imms: 460
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+```
+## FASAN - Frida Address Sanitizer Mode
+Frida mode also supports FASAN. The design of this is actually quite simple and
+very similar to that used when instrumenting applications compiled from source.
+
+### Address Sanitizer Basics
+
+When Address Sanitizer is used to instrument programs built from source, the
+compiler first adds a dependency (`DT_NEEDED` entry) for the Address Sanitizer
+dynamic shared object (DSO). This shared object contains the main logic for Address
+Sanitizer, including setting and managing up the shadow memory. It also provides
+replacement implementations for a number of functions in standard libraries.
+
+These replacements include things like `malloc` and `free` which allows for those
+allocations to be marked in the shadow memory, but also a number of other fuctions.
+Consider `memcpy` for example, this is instrumented to validate the paramters
+(test the source and destination buffers against the shadow memory. This is much
+easier than instrumenting those standard libraries since, first it would require
+you to re-compile them and secondly it would mean that the instrumentation would
+be applied at a more expensive granular level. Lastly, load-widening (typically
+found in highy optimized code) can also make this instrumentation more difficult.
+
+Since the DSO is loaded before all of the standard libraries (in fact it insists
+on being first), the dynamic loader will use it to resolve imports from other
+modules which depend on it.
+
+### FASAN Implementation
+
+FASAN takes a similar approach. It requires the user to add the Address Sanitizer
+DSO to the `AFL_PRELOAD` environment variable such that it is loaded into the target.
+Again, it must be first in the list. This means that it is not necessary to
+instrument the standard libraries to detect when an application has provided an
+incorrect argument to `memcpy` for example. This avoids issues with load-widening
+and should also mean a huge improvement in performance.
+
+FASAN then adds instrumentation for any instrucutions which use memory operands and
+then calls into the `__asan_loadN` and `__asan_storeN` functions provided by the DSO
+to validate memory accesses against the shadow memory.
+
+## TODO
+
+The next features to be added are Aarch64 and Aarch32 support as well as looking at
+potential performance improvements. The intention is to achieve feature parity with
+QEMU mode in due course. Contributions are welcome, but please get in touch to
+ensure that efforts are deconflicted.
diff --git a/frida_mode/include/asan.h b/frida_mode/include/asan.h
new file mode 100644
index 00000000..7a8726e0
--- /dev/null
+++ b/frida_mode/include/asan.h
@@ -0,0 +1,13 @@
+#ifndef _ASAN_H
+#define _ASAN_H
+
+#include "frida-gum.h"
+
+extern gboolean asan_initialized;
+
+void asan_init(void);
+void asan_arch_init(void);
+void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator);
+
+#endif
+
diff --git a/frida_mode/include/ctx.h b/frida_mode/include/ctx.h
new file mode 100644
index 00000000..cbcc892a
--- /dev/null
+++ b/frida_mode/include/ctx.h
@@ -0,0 +1,11 @@
+#ifndef _CTX_H
+#define _CTX_H
+
+#include "frida-gum.h"
+
+#if defined(__x86_64__) || defined(__i386__)
+gsize ctx_read_reg(GumCpuContext *ctx, x86_reg reg);
+#endif
+
+#endif
+
diff --git a/frida_mode/include/entry.h b/frida_mode/include/entry.h
new file mode 100644
index 00000000..967831af
--- /dev/null
+++ b/frida_mode/include/entry.h
@@ -0,0 +1,15 @@
+#ifndef _ENTRY_H
+#define _ENTRY_H
+
+#include "frida-gum.h"
+
+extern guint64 entry_start;
+
+void entry_init(void);
+
+void entry_run(void);
+
+void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output);
+
+#endif
+
diff --git a/frida_mode/include/frida_cmplog.h b/frida_mode/include/frida_cmplog.h
new file mode 100644
index 00000000..b620a472
--- /dev/null
+++ b/frida_mode/include/frida_cmplog.h
@@ -0,0 +1,14 @@
+#ifndef _CMPLOG_H
+#define _CMPLOG_H
+
+extern struct cmp_map *__afl_cmp_map;
+
+void cmplog_init(void);
+
+/* Functions to be implemented by the different architectures */
+void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator);
+
+gboolean cmplog_is_readable(guint64 addr, size_t size);
+
+#endif
+
diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h
new file mode 100644
index 00000000..ed92c25a
--- /dev/null
+++ b/frida_mode/include/instrument.h
@@ -0,0 +1,27 @@
+#ifndef _INSTRUMENT_H
+#define _INSTRUMENT_H
+
+#include "frida-gum.h"
+
+#include "config.h"
+
+extern __thread uint64_t previous_pc;
+extern uint8_t * __afl_area_ptr;
+extern uint32_t __afl_map_size;
+
+void instrument_init(void);
+
+GumStalkerTransformer *instrument_get_transformer(void);
+
+/* Functions to be implemented by the different architectures */
+gboolean instrument_is_coverage_optimize_supported(void);
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output);
+
+void instrument_debug_init(void);
+void instrument_debug_start(uint64_t address, GumStalkerOutput *output);
+void instrument_debug_instruction(uint64_t address, uint16_t size);
+void instrument_debug_end(GumStalkerOutput *output);
+#endif
+
diff --git a/frida_mode/include/interceptor.h b/frida_mode/include/interceptor.h
new file mode 100644
index 00000000..0ff754a4
--- /dev/null
+++ b/frida_mode/include/interceptor.h
@@ -0,0 +1,11 @@
+#ifndef _INTERCEPTOR_H
+#define _INTERCEPTOR_H
+
+#include "frida-gum.h"
+
+void intercept(void *address, gpointer replacement, gpointer user_data);
+void unintercept(void *address);
+void unintercept_self(void);
+
+#endif
+
diff --git a/frida_mode/include/lib.h b/frida_mode/include/lib.h
new file mode 100644
index 00000000..237aecb0
--- /dev/null
+++ b/frida_mode/include/lib.h
@@ -0,0 +1,13 @@
+#ifndef _LIB_H
+#define _LIB_H
+
+#include "frida-gum.h"
+
+void lib_init(void);
+
+guint64 lib_get_text_base(void);
+
+guint64 lib_get_text_limit(void);
+
+#endif
+
diff --git a/frida_mode/include/output.h b/frida_mode/include/output.h
new file mode 100644
index 00000000..53a9fdd3
--- /dev/null
+++ b/frida_mode/include/output.h
@@ -0,0 +1,9 @@
+#ifndef _OUTPUT_H
+#define _OUTPUT_H
+
+#include "frida-gum.h"
+
+void output_init(void);
+
+#endif
+
diff --git a/frida_mode/include/persistent.h b/frida_mode/include/persistent.h
new file mode 100644
index 00000000..25b44ab0
--- /dev/null
+++ b/frida_mode/include/persistent.h
@@ -0,0 +1,35 @@
+
+#ifndef _PERSISTENT_H
+#define _PERSISTENT_H
+
+#include "frida-gum.h"
+#include "config.h"
+
+typedef struct arch_api_regs api_regs;
+
+typedef void (*afl_persistent_hook_fn)(api_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf,
+ uint32_t input_buf_len);
+
+extern int __afl_persistent_loop(unsigned int max_cnt);
+
+extern unsigned int * __afl_fuzz_len;
+extern unsigned char *__afl_fuzz_ptr;
+
+extern guint64 persistent_start;
+extern guint64 persistent_count;
+extern guint64 persistent_ret;
+extern guint64 persistent_ret_offset;
+extern gboolean persistent_debug;
+extern afl_persistent_hook_fn hook;
+
+void persistent_init(void);
+
+/* Functions to be implemented by the different architectures */
+gboolean persistent_is_supported(void);
+
+void persistent_prologue(GumStalkerOutput *output);
+void persistent_epilogue(GumStalkerOutput *output);
+
+#endif
+
diff --git a/frida_mode/include/prefetch.h b/frida_mode/include/prefetch.h
new file mode 100644
index 00000000..8f0cee68
--- /dev/null
+++ b/frida_mode/include/prefetch.h
@@ -0,0 +1,11 @@
+#ifndef _PREFETCH_H
+#define _PREFETCH_H
+
+#include "frida-gum.h"
+
+void prefetch_init(void);
+void prefetch_write(void *addr);
+void prefetch_read(void);
+
+#endif
+
diff --git a/frida_mode/include/ranges.h b/frida_mode/include/ranges.h
new file mode 100644
index 00000000..c623f473
--- /dev/null
+++ b/frida_mode/include/ranges.h
@@ -0,0 +1,13 @@
+#ifndef _RANGES_H
+#define _RANGES_H
+
+#include "frida-gum.h"
+
+void ranges_init(void);
+
+gboolean range_is_excluded(gpointer address);
+
+void ranges_exclude();
+
+#endif
+
diff --git a/frida_mode/include/stalker.h b/frida_mode/include/stalker.h
new file mode 100644
index 00000000..186ead11
--- /dev/null
+++ b/frida_mode/include/stalker.h
@@ -0,0 +1,11 @@
+#ifndef _STALKER_H
+#define _STALKER_H
+
+#include "frida-gum.h"
+
+void stalker_init(void);
+GumStalker *stalker_get(void);
+void stalker_start(void);
+
+#endif
+
diff --git a/frida_mode/include/stats.h b/frida_mode/include/stats.h
new file mode 100644
index 00000000..4271132a
--- /dev/null
+++ b/frida_mode/include/stats.h
@@ -0,0 +1,28 @@
+#ifndef _STATS_H
+#define _STATS_H
+
+#include "frida-gum.h"
+
+typedef struct {
+
+ guint64 num_blocks;
+ guint64 num_instructions;
+ guint64 stats_last_time;
+ guint64 stats_idx;
+ guint64 transitions_idx;
+
+} stats_data_header_t;
+
+extern stats_data_header_t *stats_data;
+
+void stats_init(void);
+void stats_collect(const cs_insn *instr, gboolean begin);
+void stats_print(char *format, ...);
+
+gboolean stats_is_supported_arch(void);
+size_t stats_data_size_arch(void);
+void stats_collect_arch(const cs_insn *instr);
+void stats_write_arch(void);
+
+#endif
+
diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h
new file mode 100644
index 00000000..7b443b5e
--- /dev/null
+++ b/frida_mode/include/util.h
@@ -0,0 +1,14 @@
+#ifndef _UTIL_H
+#define _UTIL_H
+
+#include "frida-gum.h"
+
+#define UNUSED_PARAMETER(x) (void)(x)
+#define IGNORED_RETURN(x) (void)!(x)
+
+guint64 util_read_address(char *key);
+
+guint64 util_read_num(char *key);
+
+#endif
+
diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c
new file mode 100644
index 00000000..f78f690c
--- /dev/null
+++ b/frida_mode/src/asan/asan.c
@@ -0,0 +1,24 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "asan.h"
+
+gboolean asan_initialized = FALSE;
+
+void asan_init(void) {
+
+ if (getenv("AFL_USE_FASAN") != NULL) {
+
+ OKF("Frida ASAN mode enabled");
+ asan_arch_init();
+ asan_initialized = TRUE;
+
+ } else {
+
+ OKF("Frida ASAN mode disabled");
+
+ }
+
+}
+
diff --git a/frida_mode/src/asan/asan_arm.c b/frida_mode/src/asan/asan_arm.c
new file mode 100644
index 00000000..79475ced
--- /dev/null
+++ b/frida_mode/src/asan/asan_arm.c
@@ -0,0 +1,28 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "asan.h"
+#include "util.h"
+
+#if defined(__arm__)
+void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(iterator);
+ if (asan_initialized) {
+
+ FATAL("ASAN mode not supported on this architecture");
+
+ }
+
+}
+
+void asan_arch_init(void) {
+
+ FATAL("ASAN mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/asan/asan_arm64.c b/frida_mode/src/asan/asan_arm64.c
new file mode 100644
index 00000000..6262ee18
--- /dev/null
+++ b/frida_mode/src/asan/asan_arm64.c
@@ -0,0 +1,28 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "asan.h"
+#include "util.h"
+
+#if defined(__aarch64__)
+void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(iterator);
+ if (asan_initialized) {
+
+ FATAL("ASAN mode not supported on this architecture");
+
+ }
+
+}
+
+void asan_arch_init(void) {
+
+ FATAL("ASAN mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/asan/asan_x64.c b/frida_mode/src/asan/asan_x64.c
new file mode 100644
index 00000000..a2eabe3c
--- /dev/null
+++ b/frida_mode/src/asan/asan_x64.c
@@ -0,0 +1,93 @@
+#include
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "asan.h"
+#include "ctx.h"
+#include "util.h"
+
+#if defined(__x86_64__)
+
+typedef void (*asan_loadN_t)(uint64_t address, uint8_t size);
+typedef void (*asan_storeN_t)(uint64_t address, uint8_t size);
+
+asan_loadN_t asan_loadN = NULL;
+asan_storeN_t asan_storeN = NULL;
+
+static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+
+ cs_x86_op * operand = (cs_x86_op *)user_data;
+ x86_op_mem *mem = &operand->mem;
+ gsize base = 0;
+ gsize index = 0;
+ gsize address;
+ uint8_t size;
+
+ if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); }
+
+ if (mem->index != X86_REG_INVALID) { index = ctx_read_reg(ctx, mem->index); }
+
+ address = base + (mem->scale * index) + mem->disp;
+ size = operand->size;
+
+ if (operand->access == CS_AC_READ) {
+
+ asan_loadN(address, size);
+
+ } else if (operand->access == CS_AC_WRITE) {
+
+ asan_storeN(address, size);
+
+ }
+
+}
+
+void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ UNUSED_PARAMETER(iterator);
+
+ cs_x86 x86 = instr->detail->x86;
+ cs_x86_op * operand;
+ x86_op_mem *mem;
+ cs_x86_op * ctx;
+
+ if (!asan_initialized) return;
+
+ if (instr->id == X86_INS_LEA) return;
+
+ if (instr->id == X86_INS_NOP) return;
+
+ for (uint8_t i = 0; i < x86.op_count; i++) {
+
+ operand = &x86.operands[i];
+
+ if (operand->type != X86_OP_MEM) { continue; }
+
+ mem = &operand->mem;
+ if (mem->segment != X86_REG_INVALID) { continue; }
+
+ ctx = g_malloc0(sizeof(cs_x86_op));
+ memcpy(ctx, operand, sizeof(cs_x86_op));
+ gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free);
+
+ }
+
+}
+
+void asan_arch_init(void) {
+
+ asan_loadN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_loadN");
+ asan_storeN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_storeN");
+ if (asan_loadN == NULL || asan_storeN == NULL) {
+
+ FATAL("Frida ASAN failed to find '__asan_loadN' or '__asan_storeN'");
+
+ }
+
+}
+
+#endif
+
diff --git a/frida_mode/src/asan/asan_x86.c b/frida_mode/src/asan/asan_x86.c
new file mode 100644
index 00000000..8490b490
--- /dev/null
+++ b/frida_mode/src/asan/asan_x86.c
@@ -0,0 +1,93 @@
+#include
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "asan.h"
+#include "ctx.h"
+#include "util.h"
+
+#if defined(__i386__)
+
+typedef void (*asan_loadN_t)(gsize address, uint8_t size);
+typedef void (*asan_storeN_t)(gsize address, uint8_t size);
+
+asan_loadN_t asan_loadN = NULL;
+asan_storeN_t asan_storeN = NULL;
+
+static void asan_callout(GumCpuContext *ctx, gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+
+ cs_x86_op * operand = (cs_x86_op *)user_data;
+ x86_op_mem *mem = &operand->mem;
+ gsize base = 0;
+ gsize index = 0;
+ gsize address;
+ uint8_t size;
+
+ if (mem->base != X86_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); }
+
+ if (mem->index != X86_REG_INVALID) { index = ctx_read_reg(ctx, mem->index); }
+
+ address = base + (mem->scale * index) + mem->disp;
+ size = operand->size;
+
+ if (operand->access == CS_AC_READ) {
+
+ asan_loadN(address, size);
+
+ } else if (operand->access == CS_AC_WRITE) {
+
+ asan_storeN(address, size);
+
+ }
+
+}
+
+void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ UNUSED_PARAMETER(iterator);
+
+ cs_x86 x86 = instr->detail->x86;
+ cs_x86_op * operand;
+ x86_op_mem *mem;
+ cs_x86_op * ctx;
+
+ if (!asan_initialized) return;
+
+ if (instr->id == X86_INS_LEA) return;
+
+ if (instr->id == X86_INS_NOP) return;
+
+ for (uint8_t i = 0; i < x86.op_count; i++) {
+
+ operand = &x86.operands[i];
+
+ if (operand->type != X86_OP_MEM) { continue; }
+
+ mem = &operand->mem;
+ if (mem->segment != X86_REG_INVALID) { continue; }
+
+ ctx = g_malloc0(sizeof(cs_x86_op));
+ memcpy(ctx, operand, sizeof(cs_x86_op));
+ gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free);
+
+ }
+
+}
+
+void asan_arch_init(void) {
+
+ asan_loadN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_loadN");
+ asan_storeN = (asan_loadN_t)dlsym(RTLD_DEFAULT, "__asan_storeN");
+ if (asan_loadN == NULL || asan_storeN == NULL) {
+
+ FATAL("Frida ASAN failed to find '__asan_loadN' or '__asan_storeN'");
+
+ }
+
+}
+
+#endif
+
diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c
new file mode 100644
index 00000000..7b11c350
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog.c
@@ -0,0 +1,87 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "util.h"
+
+#define DEFAULT_MMAP_MIN_ADDR (32UL << 10)
+
+extern struct cmp_map *__afl_cmp_map;
+
+static GArray *cmplog_ranges = NULL;
+
+static gboolean cmplog_range(const GumRangeDetails *details,
+ gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+ GumMemoryRange range = *details->range;
+ g_array_append_val(cmplog_ranges, range);
+ return TRUE;
+
+}
+
+static gint cmplog_sort(gconstpointer a, gconstpointer b) {
+
+ return ((GumMemoryRange *)b)->base_address -
+ ((GumMemoryRange *)a)->base_address;
+
+}
+
+void cmplog_init(void) {
+
+ if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
+
+ cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100);
+ gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, NULL);
+ g_array_sort(cmplog_ranges, cmplog_sort);
+
+ for (guint i = 0; i < cmplog_ranges->len; i++) {
+
+ GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
+ OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
+ "X",
+ range->base_address, range->base_address + range->size);
+
+ }
+
+}
+
+static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
+ GumAddress outer_base, GumAddress outer_limit) {
+
+ return (inner_base >= outer_base && inner_limit <= outer_limit);
+
+}
+
+gboolean cmplog_is_readable(guint64 addr, size_t size) {
+
+ if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
+
+ /*
+ * The Linux kernel prevents mmap from allocating from the very bottom of the
+ * address space to mitigate NULL pointer dereference attacks. The exact size
+ * is set by sysctl by setting mmap_min_addr and 64k is suggested on most
+ * platforms with 32k on ARM systems. We therefore fail fast if the address
+ * is lower than this. This should avoid some overhead when functions are
+ * called where one of the parameters is a size, or a some other small value.
+ */
+ if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; }
+
+ GumAddress inner_base = addr;
+ GumAddress inner_limit = inner_base + size;
+
+ for (guint i = 0; i < cmplog_ranges->len; i++) {
+
+ GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
+ GumAddress outer_base = range->base_address;
+ GumAddress outer_limit = outer_base + range->size;
+
+ if (cmplog_contains(inner_base, inner_limit, outer_base, outer_limit))
+ return true;
+
+ }
+
+ return false;
+
+}
+
diff --git a/frida_mode/src/cmplog/cmplog_arm.c b/frida_mode/src/cmplog/cmplog_arm.c
new file mode 100644
index 00000000..5af28f3f
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog_arm.c
@@ -0,0 +1,19 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "frida_cmplog.h"
+#include "util.h"
+
+#if defined(__arm__)
+void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(iterator);
+ if (__afl_cmp_map == NULL) { return; }
+ FATAL("CMPLOG mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/cmplog/cmplog_arm64.c b/frida_mode/src/cmplog/cmplog_arm64.c
new file mode 100644
index 00000000..187d0162
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog_arm64.c
@@ -0,0 +1,19 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "frida_cmplog.h"
+#include "util.h"
+
+#if defined(__aarch64__)
+void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(iterator);
+ if (__afl_cmp_map == NULL) { return; }
+ FATAL("CMPLOG mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c
new file mode 100644
index 00000000..9f56c32a
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog_x64.c
@@ -0,0 +1,272 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+#include "cmplog.h"
+
+#include "ctx.h"
+#include "frida_cmplog.h"
+#include "util.h"
+
+#if defined(__x86_64__)
+
+typedef struct {
+
+ x86_op_type type;
+ uint8_t size;
+
+ union {
+
+ x86_op_mem mem;
+ x86_reg reg;
+ int64_t imm;
+
+ };
+
+} cmplog_ctx_t;
+
+typedef struct {
+
+ cmplog_ctx_t operand1;
+ cmplog_ctx_t operand2;
+
+} cmplog_pair_ctx_t;
+
+static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size,
+ x86_op_mem *mem, gsize *val) {
+
+ gsize base = 0;
+ gsize index = 0;
+ gsize address;
+
+ if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base);
+
+ if (mem->index != X86_REG_INVALID) index = ctx_read_reg(ctx, mem->index);
+
+ address = base + (index * mem->scale) + mem->disp;
+
+ if (!cmplog_is_readable(address, size)) { return FALSE; }
+
+ switch (size) {
+
+ case 1:
+ *val = *((guint8 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ case 2:
+ *val = *((guint16 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ case 4:
+ *val = *((guint32 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ case 8:
+ *val = *((guint64 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ default:
+ FATAL("Invalid operand size: %d\n", size);
+
+ }
+
+ return FALSE;
+
+}
+
+static gboolean cmplog_get_operand_value(GumCpuContext *context,
+ cmplog_ctx_t *ctx, gsize *val) {
+
+ switch (ctx->type) {
+
+ case X86_OP_REG:
+ *val = ctx_read_reg(context, ctx->reg);
+ return TRUE;
+ case X86_OP_IMM:
+ *val = ctx->imm;
+ return TRUE;
+ case X86_OP_MEM:
+ return cmplog_read_mem(context, ctx->size, &ctx->mem, val);
+ default:
+ FATAL("Invalid operand type: %d\n", ctx->type);
+
+ }
+
+ return FALSE;
+
+}
+
+static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+
+ gsize address = ctx_read_reg(context, X86_REG_RIP);
+ gsize rdi = ctx_read_reg(context, X86_REG_RDI);
+ gsize rsi = ctx_read_reg(context, X86_REG_RSI);
+
+ if (((G_MAXULONG - rdi) < 32) || ((G_MAXULONG - rsi) < 32)) return;
+
+ if (!cmplog_is_readable(rdi, 32) || !cmplog_is_readable(rsi, 32)) return;
+
+ void *ptr1 = GSIZE_TO_POINTER(rdi);
+ void *ptr2 = GSIZE_TO_POINTER(rsi);
+
+ uintptr_t k = address;
+
+ k = (k >> 4) ^ (k << 8);
+ k &= CMP_MAP_W - 1;
+
+ __afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
+
+ u32 hits = __afl_cmp_map->headers[k].hits;
+ __afl_cmp_map->headers[k].hits = hits + 1;
+
+ __afl_cmp_map->headers[k].shape = 31;
+
+ hits &= CMP_MAP_RTN_H - 1;
+ gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
+ 32);
+ gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
+ 32);
+
+}
+
+static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
+ cs_x86_op * operand) {
+
+ ctx->type = operand->type;
+ ctx->size = operand->size;
+ switch (operand->type) {
+
+ case X86_OP_REG:
+ gum_memcpy(&ctx->reg, &operand->reg, sizeof(x86_reg));
+ break;
+ case X86_OP_IMM:
+ gum_memcpy(&ctx->imm, &operand->imm, sizeof(int64_t));
+ break;
+ case X86_OP_MEM:
+ gum_memcpy(&ctx->mem, &operand->mem, sizeof(x86_op_mem));
+ break;
+ default:
+ FATAL("Invalid operand type: %d\n", operand->type);
+
+ }
+
+}
+
+static void cmplog_instrument_call(const cs_insn * instr,
+ GumStalkerIterator *iterator) {
+
+ cs_x86 x86 = instr->detail->x86;
+ cs_x86_op *operand;
+
+ if (instr->id != X86_INS_CALL) return;
+
+ if (x86.op_count != 1) return;
+
+ operand = &x86.operands[0];
+
+ if (operand->type == X86_OP_INVALID) return;
+ if (operand->type == X86_OP_MEM && operand->mem.segment != X86_REG_INVALID)
+ return;
+
+ gum_stalker_iterator_put_callout(iterator, cmplog_call_callout, NULL, NULL);
+
+}
+
+static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
+ gsize operand2, uint8_t size) {
+
+ gsize address = ctx_read_reg(context, X86_REG_RIP);
+
+ register uintptr_t k = (uintptr_t)address;
+
+ k = (k >> 4) ^ (k << 8);
+ k &= CMP_MAP_W - 1;
+
+ __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+
+ u32 hits = __afl_cmp_map->headers[k].hits;
+ __afl_cmp_map->headers[k].hits = hits + 1;
+
+ __afl_cmp_map->headers[k].shape = (size - 1);
+
+ hits &= CMP_MAP_H - 1;
+ __afl_cmp_map->log[k][hits].v0 = operand1;
+ __afl_cmp_map->log[k][hits].v1 = operand2;
+
+}
+
+static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
+
+ cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data;
+ gsize operand1;
+ gsize operand2;
+
+ if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch");
+
+ if (!cmplog_get_operand_value(context, &ctx->operand1, &operand1)) { return; }
+ if (!cmplog_get_operand_value(context, &ctx->operand2, &operand2)) { return; }
+
+ cmplog_handle_cmp_sub(context, operand1, operand2, ctx->operand1.size);
+
+}
+
+static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
+ cs_x86_op * operand1,
+ cs_x86_op *operand2) {
+
+ cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
+ if (ctx == NULL) return;
+
+ cmplog_instrument_put_operand(&ctx->operand1, operand1);
+ cmplog_instrument_put_operand(&ctx->operand2, operand2);
+
+ gum_stalker_iterator_put_callout(iterator, cmplog_cmp_sub_callout, ctx,
+ g_free);
+
+}
+
+static void cmplog_instrument_cmp_sub(const cs_insn * instr,
+ GumStalkerIterator *iterator) {
+
+ cs_x86 x86 = instr->detail->x86;
+ cs_x86_op *operand1;
+ cs_x86_op *operand2;
+
+ switch (instr->id) {
+
+ case X86_INS_CMP:
+ case X86_INS_SUB:
+ break;
+ default:
+ return;
+
+ }
+
+ if (x86.op_count != 2) return;
+
+ operand1 = &x86.operands[0];
+ operand2 = &x86.operands[1];
+
+ if (operand1->type == X86_OP_INVALID) return;
+ if (operand2->type == X86_OP_INVALID) return;
+
+ if ((operand1->type == X86_OP_MEM) &&
+ (operand1->mem.segment != X86_REG_INVALID))
+ return;
+
+ if ((operand2->type == X86_OP_MEM) &&
+ (operand2->mem.segment != X86_REG_INVALID))
+ return;
+
+ cmplog_instrument_cmp_sub_put_callout(iterator, operand1, operand2);
+
+}
+
+void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ if (__afl_cmp_map == NULL) return;
+
+ cmplog_instrument_call(instr, iterator);
+ cmplog_instrument_cmp_sub(instr, iterator);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/cmplog/cmplog_x86.c b/frida_mode/src/cmplog/cmplog_x86.c
new file mode 100644
index 00000000..a27df0af
--- /dev/null
+++ b/frida_mode/src/cmplog/cmplog_x86.c
@@ -0,0 +1,277 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+#include "cmplog.h"
+
+#include "ctx.h"
+#include "frida_cmplog.h"
+#include "util.h"
+
+#if defined(__i386__)
+
+typedef struct {
+
+ x86_op_type type;
+ uint8_t size;
+
+ union {
+
+ x86_op_mem mem;
+ x86_reg reg;
+ int64_t imm;
+
+ };
+
+} cmplog_ctx_t;
+
+typedef struct {
+
+ cmplog_ctx_t operand1;
+ cmplog_ctx_t operand2;
+
+} cmplog_pair_ctx_t;
+
+static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size,
+ x86_op_mem *mem, gsize *val) {
+
+ gsize base = 0;
+ gsize index = 0;
+ gsize address;
+
+ if (mem->base != X86_REG_INVALID) base = ctx_read_reg(ctx, mem->base);
+
+ if (mem->index != X86_REG_INVALID) index = ctx_read_reg(ctx, mem->index);
+
+ address = base + (index * mem->scale) + mem->disp;
+
+ if (!cmplog_is_readable(address, size)) { return FALSE; }
+
+ switch (size) {
+
+ case 1:
+ *val = *((guint8 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ case 2:
+ *val = *((guint16 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ case 4:
+ *val = *((guint32 *)GSIZE_TO_POINTER(address));
+ return TRUE;
+ default:
+ FATAL("Invalid operand size: %d\n", size);
+
+ }
+
+ return FALSE;
+
+}
+
+static gboolean cmplog_get_operand_value(GumCpuContext *context,
+ cmplog_ctx_t *ctx, gsize *val) {
+
+ switch (ctx->type) {
+
+ case X86_OP_REG:
+ *val = ctx_read_reg(context, ctx->reg);
+ return TRUE;
+ case X86_OP_IMM:
+ *val = ctx->imm;
+ return TRUE;
+ case X86_OP_MEM:
+ return cmplog_read_mem(context, ctx->size, &ctx->mem, val);
+ default:
+ FATAL("Invalid operand type: %d\n", ctx->type);
+
+ }
+
+ return FALSE;
+
+}
+
+static void cmplog_call_callout(GumCpuContext *context, gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+
+ gsize address = ctx_read_reg(context, X86_REG_EIP);
+ gsize *esp = (gsize *)ctx_read_reg(context, X86_REG_ESP);
+
+ if (!cmplog_is_readable(GPOINTER_TO_SIZE(esp), 12)) return;
+
+ /*
+ * This callout is place immediately before the call instruction, and hence
+ * the return address is not yet pushed on the top of the stack.
+ */
+ gsize arg1 = esp[0];
+ gsize arg2 = esp[1];
+
+ if (((G_MAXULONG - arg1) < 32) || ((G_MAXULONG - arg2) < 32)) return;
+
+ if (!cmplog_is_readable(arg1, 32) || !cmplog_is_readable(arg2, 32)) return;
+
+ void *ptr1 = GSIZE_TO_POINTER(arg1);
+ void *ptr2 = GSIZE_TO_POINTER(arg2);
+
+ uintptr_t k = address;
+
+ k = (k >> 4) ^ (k << 8);
+ k &= CMP_MAP_W - 1;
+
+ __afl_cmp_map->headers[k].type = CMP_TYPE_RTN;
+
+ u32 hits = __afl_cmp_map->headers[k].hits;
+ __afl_cmp_map->headers[k].hits = hits + 1;
+
+ __afl_cmp_map->headers[k].shape = 31;
+
+ hits &= CMP_MAP_RTN_H - 1;
+ gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v0, ptr1,
+ 32);
+ gum_memcpy(((struct cmpfn_operands *)__afl_cmp_map->log[k])[hits].v1, ptr2,
+ 32);
+
+}
+
+static void cmplog_instrument_put_operand(cmplog_ctx_t *ctx,
+ cs_x86_op * operand) {
+
+ ctx->type = operand->type;
+ ctx->size = operand->size;
+ switch (operand->type) {
+
+ case X86_OP_REG:
+ gum_memcpy(&ctx->reg, &operand->reg, sizeof(x86_reg));
+ break;
+ case X86_OP_IMM:
+ gum_memcpy(&ctx->imm, &operand->imm, sizeof(int64_t));
+ break;
+ case X86_OP_MEM:
+ gum_memcpy(&ctx->mem, &operand->mem, sizeof(x86_op_mem));
+ break;
+ default:
+ FATAL("Invalid operand type: %d\n", operand->type);
+
+ }
+
+}
+
+static void cmplog_instrument_call(const cs_insn * instr,
+ GumStalkerIterator *iterator) {
+
+ cs_x86 x86 = instr->detail->x86;
+ cs_x86_op *operand;
+
+ if (instr->id != X86_INS_CALL) return;
+
+ if (x86.op_count != 1) return;
+
+ operand = &x86.operands[0];
+
+ if (operand->type == X86_OP_INVALID) return;
+ if (operand->type == X86_OP_MEM && operand->mem.segment != X86_REG_INVALID)
+ return;
+
+ gum_stalker_iterator_put_callout(iterator, cmplog_call_callout, NULL, NULL);
+
+}
+
+static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1,
+ gsize operand2, uint8_t size) {
+
+ gsize address = ctx_read_reg(context, X86_REG_EIP);
+
+ register uintptr_t k = (uintptr_t)address;
+
+ k = (k >> 4) ^ (k << 8);
+ k &= CMP_MAP_W - 1;
+
+ __afl_cmp_map->headers[k].type = CMP_TYPE_INS;
+
+ u32 hits = __afl_cmp_map->headers[k].hits;
+ __afl_cmp_map->headers[k].hits = hits + 1;
+
+ __afl_cmp_map->headers[k].shape = (size - 1);
+
+ hits &= CMP_MAP_H - 1;
+ __afl_cmp_map->log[k][hits].v0 = operand1;
+ __afl_cmp_map->log[k][hits].v1 = operand2;
+
+}
+
+static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer user_data) {
+
+ cmplog_pair_ctx_t *ctx = (cmplog_pair_ctx_t *)user_data;
+ gsize operand1;
+ gsize operand2;
+
+ if (ctx->operand1.size != ctx->operand2.size) FATAL("Operand size mismatch");
+
+ if (!cmplog_get_operand_value(context, &ctx->operand1, &operand1)) { return; }
+ if (!cmplog_get_operand_value(context, &ctx->operand2, &operand2)) { return; }
+
+ cmplog_handle_cmp_sub(context, operand1, operand2, ctx->operand1.size);
+
+}
+
+static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator,
+ cs_x86_op * operand1,
+ cs_x86_op *operand2) {
+
+ cmplog_pair_ctx_t *ctx = g_malloc(sizeof(cmplog_pair_ctx_t));
+ if (ctx == NULL) return;
+
+ cmplog_instrument_put_operand(&ctx->operand1, operand1);
+ cmplog_instrument_put_operand(&ctx->operand2, operand2);
+
+ gum_stalker_iterator_put_callout(iterator, cmplog_cmp_sub_callout, ctx,
+ g_free);
+
+}
+
+static void cmplog_instrument_cmp_sub(const cs_insn * instr,
+ GumStalkerIterator *iterator) {
+
+ cs_x86 x86 = instr->detail->x86;
+ cs_x86_op *operand1;
+ cs_x86_op *operand2;
+
+ switch (instr->id) {
+
+ case X86_INS_CMP:
+ case X86_INS_SUB:
+ break;
+ default:
+ return;
+
+ }
+
+ if (x86.op_count != 2) return;
+
+ operand1 = &x86.operands[0];
+ operand2 = &x86.operands[1];
+
+ if (operand1->type == X86_OP_INVALID) return;
+ if (operand2->type == X86_OP_INVALID) return;
+
+ if ((operand1->type == X86_OP_MEM) &&
+ (operand1->mem.segment != X86_REG_INVALID))
+ return;
+
+ if ((operand2->type == X86_OP_MEM) &&
+ (operand2->mem.segment != X86_REG_INVALID))
+ return;
+
+ cmplog_instrument_cmp_sub_put_callout(iterator, operand1, operand2);
+
+}
+
+void cmplog_instrument(const cs_insn *instr, GumStalkerIterator *iterator) {
+
+ if (__afl_cmp_map == NULL) return;
+
+ cmplog_instrument_call(instr, iterator);
+ cmplog_instrument_cmp_sub(instr, iterator);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/ctx/ctx_x64.c b/frida_mode/src/ctx/ctx_x64.c
new file mode 100644
index 00000000..c5900533
--- /dev/null
+++ b/frida_mode/src/ctx/ctx_x64.c
@@ -0,0 +1,114 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "ctx.h"
+
+#if defined(__x86_64__)
+
+ #define X86_REG_8L(LABEL, REG) \
+ case LABEL: { \
+ \
+ return REG & GUM_INT8_MASK; \
+ \
+ }
+
+ #define X86_REG_8H(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG & GUM_INT16_MASK) >> 8; \
+ \
+ }
+
+ #define X86_REG_16(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG & GUM_INT16_MASK); \
+ \
+ }
+
+ #define X86_REG_32(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG & GUM_INT32_MASK); \
+ \
+ }
+
+ #define X86_REG_64(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG); \
+ \
+ }
+
+gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) {
+
+ switch (reg) {
+
+ X86_REG_8L(X86_REG_AL, ctx->rax)
+ X86_REG_8L(X86_REG_BL, ctx->rbx)
+ X86_REG_8L(X86_REG_CL, ctx->rcx)
+ X86_REG_8L(X86_REG_DL, ctx->rdx)
+ X86_REG_8L(X86_REG_BPL, ctx->rbp)
+ X86_REG_8L(X86_REG_SIL, ctx->rsi)
+ X86_REG_8L(X86_REG_DIL, ctx->rdi)
+
+ X86_REG_8H(X86_REG_AH, ctx->rax)
+ X86_REG_8H(X86_REG_BH, ctx->rbx)
+ X86_REG_8H(X86_REG_CH, ctx->rcx)
+ X86_REG_8H(X86_REG_DH, ctx->rdx)
+
+ X86_REG_16(X86_REG_AX, ctx->rax)
+ X86_REG_16(X86_REG_BX, ctx->rbx)
+ X86_REG_16(X86_REG_CX, ctx->rcx)
+ X86_REG_16(X86_REG_DX, ctx->rdx)
+ X86_REG_16(X86_REG_DI, ctx->rdi)
+ X86_REG_16(X86_REG_SI, ctx->rsi)
+ X86_REG_16(X86_REG_BP, ctx->rbp)
+
+ X86_REG_32(X86_REG_EAX, ctx->rax)
+ X86_REG_32(X86_REG_ECX, ctx->rcx)
+ X86_REG_32(X86_REG_EDX, ctx->rdx)
+ X86_REG_32(X86_REG_EBX, ctx->rbx)
+ X86_REG_32(X86_REG_ESP, ctx->rsp)
+ X86_REG_32(X86_REG_EBP, ctx->rbp)
+ X86_REG_32(X86_REG_ESI, ctx->rsi)
+ X86_REG_32(X86_REG_EDI, ctx->rdi)
+ X86_REG_32(X86_REG_R8D, ctx->r8)
+ X86_REG_32(X86_REG_R9D, ctx->r9)
+ X86_REG_32(X86_REG_R10D, ctx->r10)
+ X86_REG_32(X86_REG_R11D, ctx->r11)
+ X86_REG_32(X86_REG_R12D, ctx->r12)
+ X86_REG_32(X86_REG_R13D, ctx->r13)
+ X86_REG_32(X86_REG_R14D, ctx->r14)
+ X86_REG_32(X86_REG_R15D, ctx->r15)
+ X86_REG_32(X86_REG_EIP, ctx->rip)
+
+ X86_REG_64(X86_REG_RAX, ctx->rax)
+ X86_REG_64(X86_REG_RCX, ctx->rcx)
+ X86_REG_64(X86_REG_RDX, ctx->rdx)
+ X86_REG_64(X86_REG_RBX, ctx->rbx)
+ X86_REG_64(X86_REG_RSP, ctx->rsp)
+ X86_REG_64(X86_REG_RBP, ctx->rbp)
+ X86_REG_64(X86_REG_RSI, ctx->rsi)
+ X86_REG_64(X86_REG_RDI, ctx->rdi)
+ X86_REG_64(X86_REG_R8, ctx->r8)
+ X86_REG_64(X86_REG_R9, ctx->r9)
+ X86_REG_64(X86_REG_R10, ctx->r10)
+ X86_REG_64(X86_REG_R11, ctx->r11)
+ X86_REG_64(X86_REG_R12, ctx->r12)
+ X86_REG_64(X86_REG_R13, ctx->r13)
+ X86_REG_64(X86_REG_R14, ctx->r14)
+ X86_REG_64(X86_REG_R15, ctx->r15)
+ X86_REG_64(X86_REG_RIP, ctx->rip)
+
+ default:
+ FATAL("Failed to read register: %d", reg);
+ return 0;
+
+ }
+
+}
+
+#endif
+
diff --git a/frida_mode/src/ctx/ctx_x86.c b/frida_mode/src/ctx/ctx_x86.c
new file mode 100644
index 00000000..45308272
--- /dev/null
+++ b/frida_mode/src/ctx/ctx_x86.c
@@ -0,0 +1,81 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "ctx.h"
+
+#if defined(__i386__)
+
+ #define X86_REG_8L(LABEL, REG) \
+ case LABEL: { \
+ \
+ return REG & GUM_INT8_MASK; \
+ \
+ }
+
+ #define X86_REG_8H(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG & GUM_INT16_MASK) >> 8; \
+ \
+ }
+
+ #define X86_REG_16(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG & GUM_INT16_MASK); \
+ \
+ }
+
+ #define X86_REG_32(LABEL, REG) \
+ case LABEL: { \
+ \
+ return (REG & GUM_INT32_MASK); \
+ \
+ }
+
+gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg) {
+
+ switch (reg) {
+
+ X86_REG_8L(X86_REG_AL, ctx->eax)
+ X86_REG_8L(X86_REG_BL, ctx->ebx)
+ X86_REG_8L(X86_REG_CL, ctx->ecx)
+ X86_REG_8L(X86_REG_DL, ctx->edx)
+ X86_REG_8L(X86_REG_BPL, ctx->ebp)
+ X86_REG_8L(X86_REG_SIL, ctx->esi)
+ X86_REG_8L(X86_REG_DIL, ctx->edi)
+
+ X86_REG_8H(X86_REG_AH, ctx->eax)
+ X86_REG_8H(X86_REG_BH, ctx->ebx)
+ X86_REG_8H(X86_REG_CH, ctx->ecx)
+ X86_REG_8H(X86_REG_DH, ctx->edx)
+
+ X86_REG_16(X86_REG_AX, ctx->eax)
+ X86_REG_16(X86_REG_BX, ctx->ebx)
+ X86_REG_16(X86_REG_CX, ctx->ecx)
+ X86_REG_16(X86_REG_DX, ctx->edx)
+ X86_REG_16(X86_REG_DI, ctx->edi)
+ X86_REG_16(X86_REG_SI, ctx->esi)
+ X86_REG_16(X86_REG_BP, ctx->ebp)
+
+ X86_REG_32(X86_REG_EAX, ctx->eax)
+ X86_REG_32(X86_REG_ECX, ctx->ecx)
+ X86_REG_32(X86_REG_EDX, ctx->edx)
+ X86_REG_32(X86_REG_EBX, ctx->ebx)
+ X86_REG_32(X86_REG_ESP, ctx->esp)
+ X86_REG_32(X86_REG_EBP, ctx->ebp)
+ X86_REG_32(X86_REG_ESI, ctx->esi)
+ X86_REG_32(X86_REG_EDI, ctx->edi)
+ X86_REG_32(X86_REG_EIP, ctx->eip)
+
+ default:
+ FATAL("Failed to read register: %d", reg);
+ return 0;
+
+ }
+
+}
+
+#endif
+
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c
new file mode 100644
index 00000000..e71386a0
--- /dev/null
+++ b/frida_mode/src/entry.c
@@ -0,0 +1,50 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "entry.h"
+#include "instrument.h"
+#include "stalker.h"
+#include "util.h"
+
+extern void __afl_manual_init();
+
+guint64 entry_start = 0;
+
+static void entry_launch(void) {
+
+ __afl_manual_init();
+
+ /* Child here */
+ previous_pc = 0;
+
+}
+
+void entry_init(void) {
+
+ entry_start = util_read_address("AFL_ENTRYPOINT");
+ OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_start);
+
+}
+
+void entry_run(void) {
+
+ if (entry_start == 0) { entry_launch(); }
+
+}
+
+static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) {
+
+ UNUSED_PARAMETER(cpu_context);
+ UNUSED_PARAMETER(user_data);
+ entry_launch();
+
+}
+
+void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(output);
+ gum_stalker_iterator_put_callout(iterator, entry_callout, NULL, NULL);
+
+}
+
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
new file mode 100644
index 00000000..cd1ac0be
--- /dev/null
+++ b/frida_mode/src/instrument/instrument.c
@@ -0,0 +1,199 @@
+#include
+
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+
+#include "asan.h"
+#include "entry.h"
+#include "frida_cmplog.h"
+#include "instrument.h"
+#include "persistent.h"
+#include "prefetch.h"
+#include "ranges.h"
+#include "stalker.h"
+#include "stats.h"
+#include "util.h"
+
+static gboolean tracing = false;
+static gboolean optimize = false;
+static GumStalkerTransformer *transformer = NULL;
+
+__thread uint64_t previous_pc = 0;
+
+__attribute__((hot)) static void on_basic_block(GumCpuContext *context,
+ gpointer user_data) {
+
+ UNUSED_PARAMETER(context);
+ /*
+ * This function is performance critical as it is called to instrument every
+ * basic block. By moving our print buffer to a global, we avoid it affecting
+ * the critical path with additional stack adjustments if tracing is not
+ * enabled. If tracing is enabled, then we're printing a load of diagnostic
+ * information so this overhead is unlikely to be noticeable.
+ */
+ static char buffer[200];
+ int len;
+ GumAddress current_pc = GUM_ADDRESS(user_data);
+ uint8_t * cursor;
+ uint64_t value;
+ if (unlikely(tracing)) {
+
+ /* Avoid any functions which may cause an allocation since the target app
+ * may already be running inside malloc and it isn't designed to be
+ * re-entrant on a single thread */
+ len = snprintf(buffer, sizeof(buffer),
+ "current_pc: 0x%016" G_GINT64_MODIFIER
+ "x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n",
+ current_pc, previous_pc);
+
+ IGNORED_RETURN(write(STDOUT_FILENO, buffer, len + 1));
+
+ }
+
+ current_pc = (current_pc >> 4) ^ (current_pc << 8);
+ current_pc &= MAP_SIZE - 1;
+
+ cursor = &__afl_area_ptr[current_pc ^ previous_pc];
+ value = *cursor;
+
+ if (value == 0xff) {
+
+ value = 1;
+
+ } else {
+
+ value++;
+
+ }
+
+ *cursor = value;
+ previous_pc = current_pc >> 1;
+
+}
+
+static void instr_basic_block(GumStalkerIterator *iterator,
+ GumStalkerOutput *output, gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+
+ const cs_insn *instr;
+ gboolean begin = TRUE;
+ gboolean excluded;
+
+ while (gum_stalker_iterator_next(iterator, &instr)) {
+
+ if (instr->address == entry_start) { entry_prologue(iterator, output); }
+ if (instr->address == persistent_start) { persistent_prologue(output); }
+ if (instr->address == persistent_ret) { persistent_epilogue(output); }
+
+ /*
+ * Until we reach AFL_ENTRYPOINT (assumed to be main if not specified) or
+ * AFL_FRIDA_PERSISTENT_ADDR (if specified), we don't mark our ranges
+ * excluded as we wish to remain inside stalker at all times so that we can
+ * instrument our entry point and persistent loop (if present). This allows
+ * the user to exclude ranges which would be traversed between main and the
+ * AFL_ENTRYPOINT, but which they don't want included in their coverage
+ * information when fuzzing.
+ *
+ * Since we have no means to discard the instrumented copies of blocks
+ * (setting the trust threshold simply causes a new copy to be made on each
+ * execution), we instead ensure that we honour the additional
+ * instrumentation requested (e.g. coverage, asan and complog) when a block
+ * is compiled no matter where we are during initialization. We will end up
+ * re-using these blocks if the code under test calls a block which is also
+ * used during initialization.
+ *
+ * Coverage data generated during initialization isn't a problem since the
+ * map is zeroed each time the target is forked or each time the persistent
+ * loop is run.
+ *
+ * Lastly, we don't enable pre-fetching back to the parent until we reach
+ * our AFL_ENTRYPOINT, since it is not until then that we start the
+ * fork-server and thus start executing in the child.
+ */
+ excluded = range_is_excluded(GSIZE_TO_POINTER(instr->address));
+
+ stats_collect(instr, begin);
+
+ if (unlikely(begin)) {
+
+ instrument_debug_start(instr->address, output);
+
+ prefetch_write(GSIZE_TO_POINTER(instr->address));
+
+ if (likely(!excluded)) {
+
+ if (likely(optimize)) {
+
+ instrument_coverage_optimize(instr, output);
+
+ } else {
+
+ gum_stalker_iterator_put_callout(
+ iterator, on_basic_block, GSIZE_TO_POINTER(instr->address), NULL);
+
+ }
+
+ }
+
+ begin = FALSE;
+
+ }
+
+ instrument_debug_instruction(instr->address, instr->size);
+
+ if (likely(!excluded)) {
+
+ asan_instrument(instr, iterator);
+ cmplog_instrument(instr, iterator);
+
+ }
+
+ gum_stalker_iterator_keep(iterator);
+
+ }
+
+ instrument_debug_end(output);
+
+}
+
+void instrument_init(void) {
+
+ optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
+ tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
+
+ if (!instrument_is_coverage_optimize_supported()) optimize = false;
+
+ OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' ');
+ OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' ');
+
+ if (tracing && optimize) {
+
+ FATAL("AFL_FRIDA_INST_OPTIMIZE and AFL_FRIDA_INST_TRACE are incompatible");
+
+ }
+
+ if (__afl_map_size != 0x10000) {
+
+ FATAL("Bad map size: 0x%08x", __afl_map_size);
+
+ }
+
+ transformer =
+ gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL);
+
+ instrument_debug_init();
+ asan_init();
+ cmplog_init();
+
+}
+
+GumStalkerTransformer *instrument_get_transformer(void) {
+
+ if (transformer == NULL) { FATAL("Instrumentation not initialized"); }
+ return transformer;
+
+}
+
diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c
new file mode 100644
index 00000000..1a3c40bb
--- /dev/null
+++ b/frida_mode/src/instrument/instrument_arm32.c
@@ -0,0 +1,26 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "instrument.h"
+#include "util.h"
+
+#if defined(__arm__)
+
+gboolean instrument_is_coverage_optimize_supported(void) {
+
+ return false;
+
+}
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(output);
+ FATAL("Optimized coverage not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
new file mode 100644
index 00000000..fa3afb48
--- /dev/null
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -0,0 +1,97 @@
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+
+#include "instrument.h"
+
+#if defined(__aarch64__)
+
+static GumAddress current_log_impl = GUM_ADDRESS(0);
+
+static const guint8 afl_log_code[] = {
+
+ // __afl_area_ptr[current_pc ^ previous_pc]++;
+ // previous_pc = current_pc >> 1;
+ 0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]!
+ 0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]!
+
+ // x0 = current_pc
+ 0xe1, 0x01, 0x00, 0x58, // ldr x1, #0x3c, =&__afl_area_ptr
+ 0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr)
+
+ 0xe2, 0x01, 0x00, 0x58, // ldr x2, #0x3c, =&previous_pc
+ 0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc)
+
+ // __afl_area_ptr[current_pc ^ previous_pc]++;
+ 0x42, 0x00, 0x00, 0xca, // eor x2, x2, x0
+ 0x23, 0x68, 0x62, 0xf8, // ldr x3, [x1, x2]
+ 0x63, 0x04, 0x00, 0x91, // add x3, x3, #1
+ 0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr
+ 0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2]
+
+ // previous_pc = current_pc >> 1;
+ 0xe0, 0x07, 0x40, 0x8b, // add x0, xzr, x0, LSR #1
+ 0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc
+ 0x40, 0x00, 0x00, 0xf9, // str x0, [x2]
+
+ 0xE3, 0x13, 0xc1, 0xA8, // ldp x3, x4, [sp], #0x10
+ 0xE1, 0x0B, 0xc1, 0xA8, // ldp x1, x2, [sp], #0x10
+ 0xC0, 0x03, 0x5F, 0xD6, // ret
+
+ // &afl_area_ptr_ptr
+ // &afl_prev_loc_ptr
+
+};
+
+gboolean instrument_is_coverage_optimize_supported(void) {
+
+ return true;
+
+}
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output) {
+
+ guint64 current_pc = instr->address;
+ guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
+ area_offset &= MAP_SIZE - 1;
+ GumArm64Writer *cw = output->writer.arm64;
+
+ if (current_log_impl == 0 ||
+ !gum_arm64_writer_can_branch_directly_between(cw, cw->pc,
+ current_log_impl) ||
+ !gum_arm64_writer_can_branch_directly_between(cw, cw->pc + 128,
+ current_log_impl)) {
+
+ gconstpointer after_log_impl = cw->code + 1;
+
+ gum_arm64_writer_put_b_label(cw, after_log_impl);
+
+ current_log_impl = cw->pc;
+ gum_arm64_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+
+ uint8_t **afl_area_ptr_ptr = &__afl_area_ptr;
+ uint64_t *afl_prev_loc_ptr = &previous_pc;
+ gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_area_ptr_ptr,
+ sizeof(afl_area_ptr_ptr));
+ gum_arm64_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
+ sizeof(afl_prev_loc_ptr));
+
+ gum_arm64_writer_put_label(cw, after_log_impl);
+
+ }
+
+ gum_arm64_writer_put_stp_reg_reg_reg_offset(
+ cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE),
+ GUM_INDEX_PRE_ADJUST);
+ gum_arm64_writer_put_ldr_reg_u64(cw, ARM64_REG_X0, area_offset);
+ gum_arm64_writer_put_bl_imm(cw, current_log_impl);
+ gum_arm64_writer_put_ldp_reg_reg_reg_offset(
+ cw, ARM64_REG_LR, ARM64_REG_X0, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE,
+ GUM_INDEX_POST_ADJUST);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/instrument/instrument_debug.c b/frida_mode/src/instrument/instrument_debug.c
new file mode 100644
index 00000000..f8c1df77
--- /dev/null
+++ b/frida_mode/src/instrument/instrument_debug.c
@@ -0,0 +1,129 @@
+#include
+#include
+#include
+#include
+
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "util.h"
+
+static int debugging_fd = -1;
+static gpointer instrument_gen_start = NULL;
+
+static void instrument_debug(char *format, ...) {
+
+ va_list ap;
+ char buffer[4096] = {0};
+ int ret;
+ int len;
+
+ va_start(ap, format);
+ ret = vsnprintf(buffer, sizeof(buffer) - 1, format, ap);
+ va_end(ap);
+
+ if (ret < 0) { return; }
+
+ len = strnlen(buffer, sizeof(buffer));
+
+ IGNORED_RETURN(write(debugging_fd, buffer, len));
+
+}
+
+static void instrument_disasm(guint8 *code, guint size) {
+
+ csh capstone;
+ cs_err err;
+ cs_insn *insn;
+ size_t count, i;
+
+ err = cs_open(GUM_DEFAULT_CS_ARCH,
+ GUM_DEFAULT_CS_MODE | GUM_DEFAULT_CS_ENDIAN, &capstone);
+ g_assert(err == CS_ERR_OK);
+
+ count = cs_disasm(capstone, code, size, GPOINTER_TO_SIZE(code), 0, &insn);
+ g_assert(insn != NULL);
+
+ for (i = 0; i != count; i++) {
+
+ instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t%s %s\n", insn[i].address,
+ insn[i].mnemonic, insn[i].op_str);
+
+ }
+
+ cs_free(insn, count);
+
+ cs_close(&capstone);
+
+}
+
+static gpointer instrument_cur(GumStalkerOutput *output) {
+
+#if defined(__i386__) || defined(__x86_64__)
+ return gum_x86_writer_cur(output->writer.x86);
+#elif defined(__aarch64__)
+ return gum_arm64_writer_cur(output->writer.arm64);
+#elif defined(__arm__)
+ return gum_arm_writer_cur(output->writer.arm);
+#else
+ #error "Unsupported architecture"
+#endif
+
+}
+
+void instrument_debug_init(void) {
+
+ char *filename = getenv("AFL_FRIDA_INST_DEBUG_FILE");
+ OKF("Instrumentation debugging - enabled [%c]", filename == NULL ? ' ' : 'X');
+
+ if (filename == NULL) { return; }
+
+ OKF("Instrumentation debugging - file [%s]", filename);
+
+ if (filename == NULL) { return; }
+
+ char *path = g_canonicalize_filename(filename, g_get_current_dir());
+
+ OKF("Instrumentation debugging - path [%s]", path);
+
+ debugging_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+ if (debugging_fd < 0) { FATAL("Failed to open stats file '%s'", path); }
+
+ g_free(path);
+
+}
+
+void instrument_debug_start(uint64_t address, GumStalkerOutput *output) {
+
+ if (likely(debugging_fd < 0)) { return; }
+
+ instrument_gen_start = instrument_cur(output);
+
+ instrument_debug("\n\n***\n\nCreating block for 0x%" G_GINT64_MODIFIER "x:\n",
+ address);
+
+}
+
+void instrument_debug_instruction(uint64_t address, uint16_t size) {
+
+ if (likely(debugging_fd < 0)) { return; }
+ uint8_t *start = (uint8_t *)GSIZE_TO_POINTER(address);
+ instrument_disasm(start, size);
+
+}
+
+void instrument_debug_end(GumStalkerOutput *output) {
+
+ if (likely(debugging_fd < 0)) { return; }
+ gpointer instrument_gen_end = instrument_cur(output);
+ uint16_t size = GPOINTER_TO_SIZE(instrument_gen_end) -
+ GPOINTER_TO_SIZE(instrument_gen_start);
+
+ instrument_debug("\nGenerated block %p\n", instrument_gen_start);
+ instrument_disasm(instrument_gen_start, size);
+
+}
+
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
new file mode 100644
index 00000000..901f3bd0
--- /dev/null
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -0,0 +1,93 @@
+#include "frida-gum.h"
+
+#include "config.h"
+
+#include "instrument.h"
+
+#if defined(__x86_64__)
+
+static GumAddress current_log_impl = GUM_ADDRESS(0);
+
+static const guint8 afl_log_code[] = {
+
+ // 0xcc,
+
+ 0x9c, /* pushfq */
+ 0x51, /* push rcx */
+ 0x52, /* push rdx */
+
+ 0x48, 0x8b, 0x0d, 0x28,
+ 0x00, 0x00, 0x00, /* mov rcx, sym.&previous_pc */
+ 0x48, 0x8b, 0x11, /* mov rdx, qword [rcx] */
+ 0x48, 0x31, 0xfa, /* xor rdx, rdi */
+
+ 0x48, 0x03, 0x15, 0x13,
+ 0x00, 0x00, 0x00, /* add rdx, sym._afl_area_ptr_ptr */
+
+ 0x80, 0x02, 0x01, /* add byte ptr [rdx], 1 */
+ 0x80, 0x12, 0x00, /* adc byte ptr [rdx], 0 */
+ 0x48, 0xd1, 0xef, /* shr rdi, 1 */
+ 0x48, 0x89, 0x39, /* mov qword [rcx], rdi */
+
+ 0x5a, /* pop rdx */
+ 0x59, /* pop rcx */
+ 0x9d, /* popfq */
+
+ 0xc3, /* ret */
+ 0x90, 0x90, 0x90 /* nop pad */
+
+ /* Read-only data goes here: */
+ /* uint8_t* __afl_area_ptr */
+ /* uint64_t* &previous_pc */
+
+};
+
+gboolean instrument_is_coverage_optimize_supported(void) {
+
+ return true;
+
+}
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output) {
+
+ guint64 current_pc = instr->address;
+ guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
+ area_offset &= MAP_SIZE - 1;
+ GumX86Writer *cw = output->writer.x86;
+
+ if (current_log_impl == 0 ||
+ !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
+ !gum_x86_writer_can_branch_directly_between(cw->pc + 128,
+ current_log_impl)) {
+
+ gconstpointer after_log_impl = cw->code + 1;
+
+ gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
+
+ current_log_impl = cw->pc;
+ gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
+
+ uint64_t *afl_prev_loc_ptr = &previous_pc;
+ gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr,
+ sizeof(__afl_area_ptr));
+ gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr,
+ sizeof(afl_prev_loc_ptr));
+
+ gum_x86_writer_put_label(cw, after_log_impl);
+
+ }
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ -GUM_RED_ZONE_SIZE);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_RDI);
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, area_offset);
+ gum_x86_writer_put_call_address(cw, current_log_impl);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI);
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ GUM_RED_ZONE_SIZE);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c
new file mode 100644
index 00000000..585bb5b8
--- /dev/null
+++ b/frida_mode/src/instrument/instrument_x86.c
@@ -0,0 +1,85 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "instrument.h"
+#include "util.h"
+
+#if defined(__i386__)
+
+static GumAddress current_log_impl = GUM_ADDRESS(0);
+
+static void instrument_coverage_function(GumX86Writer *cw) {
+
+ gum_x86_writer_put_pushfx(cw);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_ECX);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EDX);
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX,
+ GUM_ADDRESS(&previous_pc));
+ gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_EDX, GUM_REG_ECX);
+ gum_x86_writer_put_xor_reg_reg(cw, GUM_REG_EDX, GUM_REG_EDI);
+
+ gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EDX, GUM_ADDRESS(__afl_area_ptr));
+
+ /* add byte ptr [edx], 1 */
+ uint8_t add_byte_ptr_edx_1[] = {0x80, 0x02, 0x01};
+ gum_x86_writer_put_bytes(cw, add_byte_ptr_edx_1, sizeof(add_byte_ptr_edx_1));
+
+ /* adc byte ptr [edx], 0 */
+ uint8_t adc_byte_ptr_edx_0[] = {0x80, 0x12, 0x00};
+ gum_x86_writer_put_bytes(cw, adc_byte_ptr_edx_0, sizeof(adc_byte_ptr_edx_0));
+
+ gum_x86_writer_put_shr_reg_u8(cw, GUM_REG_EDI, 1);
+ gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_ECX, GUM_REG_EDI);
+
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_EDX);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_ECX);
+ gum_x86_writer_put_popfx(cw);
+ gum_x86_writer_put_ret(cw);
+
+}
+
+gboolean instrument_is_coverage_optimize_supported(void) {
+
+ return true;
+
+}
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(output);
+
+ guint64 current_pc = instr->address;
+ guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
+ area_offset &= MAP_SIZE - 1;
+ GumX86Writer *cw = output->writer.x86;
+
+ if (current_log_impl == 0 ||
+ !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) ||
+ !gum_x86_writer_can_branch_directly_between(cw->pc + 128,
+ current_log_impl)) {
+
+ gconstpointer after_log_impl = cw->code + 1;
+
+ gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
+
+ current_log_impl = cw->pc;
+ instrument_coverage_function(cw);
+
+ gum_x86_writer_put_label(cw, after_log_impl);
+
+ }
+
+ // gum_x86_writer_put_breakpoint(cw);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EDI);
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDI, area_offset);
+ gum_x86_writer_put_call_address(cw, current_log_impl);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_EDI);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/interceptor.c b/frida_mode/src/interceptor.c
new file mode 100644
index 00000000..d2802752
--- /dev/null
+++ b/frida_mode/src/interceptor.c
@@ -0,0 +1,35 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "interceptor.h"
+
+void intercept(void *address, gpointer replacement, gpointer user_data) {
+
+ GumInterceptor *interceptor = gum_interceptor_obtain();
+ gum_interceptor_begin_transaction(interceptor);
+ GumReplaceReturn ret =
+ gum_interceptor_replace(interceptor, address, replacement, user_data);
+ if (ret != GUM_REPLACE_OK) { FATAL("gum_interceptor_attach: %d", ret); }
+ gum_interceptor_end_transaction(interceptor);
+
+}
+
+void unintercept(void *address) {
+
+ GumInterceptor *interceptor = gum_interceptor_obtain();
+
+ gum_interceptor_begin_transaction(interceptor);
+ gum_interceptor_revert(interceptor, address);
+ gum_interceptor_end_transaction(interceptor);
+ gum_interceptor_flush(interceptor);
+
+}
+
+void unintercept_self(void) {
+
+ GumInvocationContext *ctx = gum_interceptor_get_current_invocation();
+ unintercept(ctx->function);
+
+}
+
diff --git a/frida_mode/src/lib/lib.c b/frida_mode/src/lib/lib.c
new file mode 100644
index 00000000..13a7d1e7
--- /dev/null
+++ b/frida_mode/src/lib/lib.c
@@ -0,0 +1,179 @@
+#ifndef __APPLE__
+ #include
+ #include
+ #include
+ #include
+ #include
+ #include
+
+ #include "frida-gum.h"
+
+ #include "debug.h"
+
+ #include "lib.h"
+
+ #if defined(__arm__) || defined(__i386__)
+ #define ELFCLASS ELFCLASS32
+typedef Elf32_Ehdr Elf_Ehdr;
+typedef Elf32_Phdr Elf_Phdr;
+typedef Elf32_Shdr Elf_Shdr;
+typedef Elf32_Addr Elf_Addr;
+ #elif defined(__aarch64__) || defined(__x86_64__)
+ #define ELFCLASS ELFCLASS64
+typedef Elf64_Ehdr Elf_Ehdr;
+typedef Elf64_Phdr Elf_Phdr;
+typedef Elf64_Shdr Elf_Shdr;
+typedef Elf64_Addr Elf_Addr;
+ #else
+ #error "Unsupported platform"
+ #endif
+
+typedef struct {
+
+ gchar name[PATH_MAX + 1];
+ gchar path[PATH_MAX + 1];
+ GumAddress base_address;
+ gsize size;
+
+} lib_details_t;
+
+static guint64 text_base = 0;
+static guint64 text_limit = 0;
+
+static gboolean lib_find_exe(const GumModuleDetails *details,
+ gpointer user_data) {
+
+ lib_details_t *lib_details = (lib_details_t *)user_data;
+
+ memcpy(lib_details->name, details->name, PATH_MAX);
+ memcpy(lib_details->path, details->path, PATH_MAX);
+ lib_details->base_address = details->range->base_address;
+ lib_details->size = details->range->size;
+ return FALSE;
+
+}
+
+static void lib_validate_hdr(Elf_Ehdr *hdr) {
+
+ if (hdr->e_ident[0] != ELFMAG0) FATAL("Invalid e_ident[0]");
+ if (hdr->e_ident[1] != ELFMAG1) FATAL("Invalid e_ident[1]");
+ if (hdr->e_ident[2] != ELFMAG2) FATAL("Invalid e_ident[2]");
+ if (hdr->e_ident[3] != ELFMAG3) FATAL("Invalid e_ident[3]");
+ if (hdr->e_ident[4] != ELFCLASS) FATAL("Invalid class");
+
+}
+
+static void lib_read_text_section(lib_details_t *lib_details, Elf_Ehdr *hdr) {
+
+ Elf_Phdr *phdr;
+ gboolean found_preferred_base = FALSE;
+ Elf_Addr preferred_base;
+ Elf_Shdr *shdr;
+ Elf_Shdr *shstrtab;
+ char * shstr;
+ char * section_name;
+ Elf_Shdr *curr;
+ char text_name[] = ".text";
+
+ phdr = (Elf_Phdr *)((char *)hdr + hdr->e_phoff);
+ for (size_t i = 0; i < hdr->e_phnum; i++) {
+
+ if (phdr[i].p_type == PT_LOAD) {
+
+ preferred_base = phdr[i].p_vaddr;
+ found_preferred_base = TRUE;
+ break;
+
+ }
+
+ }
+
+ if (!found_preferred_base) { FATAL("Failed to find preferred load address"); }
+
+ OKF("Image preferred load address 0x%016" G_GSIZE_MODIFIER "x",
+ preferred_base);
+
+ shdr = (Elf_Shdr *)((char *)hdr + hdr->e_shoff);
+ shstrtab = &shdr[hdr->e_shstrndx];
+ shstr = (char *)hdr + shstrtab->sh_offset;
+
+ OKF("shdr: %p", shdr);
+ OKF("shstrtab: %p", shstrtab);
+ OKF("shstr: %p", shstr);
+
+ for (size_t i = 0; i < hdr->e_shnum; i++) {
+
+ curr = &shdr[i];
+
+ if (curr->sh_name == 0) continue;
+
+ section_name = &shstr[curr->sh_name];
+ OKF("Section: %2" G_GSIZE_MODIFIER "u - base: 0x%016" G_GSIZE_MODIFIER
+ "X size: 0x%016" G_GSIZE_MODIFIER "X %s",
+ i, curr->sh_addr, curr->sh_size, section_name);
+ if (memcmp(section_name, text_name, sizeof(text_name)) == 0 &&
+ text_base == 0) {
+
+ text_base = lib_details->base_address + curr->sh_addr - preferred_base;
+ text_limit = text_base + curr->sh_size;
+ OKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
+ OKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
+
+ }
+
+ }
+
+}
+
+static void lib_get_text_section(lib_details_t *details) {
+
+ int fd = -1;
+ off_t len;
+ Elf_Ehdr *hdr;
+
+ fd = open(details->path, O_RDONLY);
+ if (fd < 0) { FATAL("Failed to open %s", details->path); }
+
+ len = lseek(fd, 0, SEEK_END);
+
+ if (len == (off_t)-1) { FATAL("Failed to lseek %s", details->path); }
+
+ OKF("len: %ld", len);
+
+ hdr = (Elf_Ehdr *)mmap(NULL, len, PROT_READ, MAP_PRIVATE, fd, 0);
+ if (hdr == MAP_FAILED) { FATAL("Failed to map %s", details->path); }
+
+ lib_validate_hdr(hdr);
+ lib_read_text_section(details, hdr);
+
+ munmap(hdr, len);
+ close(fd);
+
+}
+
+void lib_init(void) {
+
+ lib_details_t lib_details;
+ gum_process_enumerate_modules(lib_find_exe, &lib_details);
+ OKF("Executable: 0x%016" G_GINT64_MODIFIER "x - %s", lib_details.base_address,
+ lib_details.path);
+ lib_get_text_section(&lib_details);
+
+}
+
+guint64 lib_get_text_base(void) {
+
+ if (text_base == 0) FATAL("Lib not initialized");
+ return text_base;
+
+}
+
+guint64 lib_get_text_limit(void) {
+
+ if (text_limit == 0) FATAL("Lib not initialized");
+ return text_limit;
+
+}
+
+#endif
+
diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c
new file mode 100644
index 00000000..8f863861
--- /dev/null
+++ b/frida_mode/src/lib/lib_apple.c
@@ -0,0 +1,82 @@
+#ifdef __APPLE__
+ #include "frida-gum.h"
+
+ #include "debug.h"
+
+ #include "lib.h"
+ #include "util.h"
+
+extern mach_port_t mach_task_self();
+extern void gum_darwin_enumerate_modules(mach_port_t task,
+ GumFoundModuleFunc func,
+ gpointer user_data);
+
+static guint64 text_base = 0;
+static guint64 text_limit = 0;
+
+static gboolean lib_get_main_module(const GumModuleDetails *details,
+ gpointer user_data) {
+
+ GumDarwinModule **ret = (GumDarwinModule **)user_data;
+ GumDarwinModule * module = gum_darwin_module_new_from_memory(
+ details->path, mach_task_self(), details->range->base_address,
+ GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
+
+ OKF("Found main module: %s", module->name);
+
+ *ret = module;
+
+ return FALSE;
+
+}
+
+gboolean lib_get_text_section(const GumDarwinSectionDetails *details,
+ gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+ static size_t idx = 0;
+ char text_name[] = "__text";
+
+ OKF("Section: %2lu - base: 0x%016" G_GINT64_MODIFIER
+ "X size: 0x%016" G_GINT64_MODIFIER "X %s",
+ idx++, details->vm_address, details->vm_address + details->size,
+ details->section_name);
+
+ if (memcmp(details->section_name, text_name, sizeof(text_name)) == 0 &&
+ text_base == 0) {
+
+ text_base = details->vm_address;
+ text_limit = details->vm_address + details->size;
+ OKF("> text_addr: 0x%016" G_GINT64_MODIFIER "X", text_base);
+ OKF("> text_limit: 0x%016" G_GINT64_MODIFIER "X", text_limit);
+
+ }
+
+ return TRUE;
+
+}
+
+void lib_init(void) {
+
+ GumDarwinModule *module = NULL;
+ gum_darwin_enumerate_modules(mach_task_self(), lib_get_main_module, &module);
+ gum_darwin_module_enumerate_sections(module, lib_get_text_section, NULL);
+
+}
+
+guint64 lib_get_text_base(void) {
+
+ if (text_base == 0) FATAL("Lib not initialized");
+ return text_base;
+
+}
+
+guint64 lib_get_text_limit(void) {
+
+ if (text_limit == 0) FATAL("Lib not initialized");
+ return text_limit;
+
+}
+
+#endif
+
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
new file mode 100644
index 00000000..1ab9993f
--- /dev/null
+++ b/frida_mode/src/main.c
@@ -0,0 +1,179 @@
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #include
+ #include
+#else
+ #include
+ #include
+#endif
+
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+
+#include "entry.h"
+#include "instrument.h"
+#include "interceptor.h"
+#include "lib.h"
+#include "output.h"
+#include "persistent.h"
+#include "prefetch.h"
+#include "ranges.h"
+#include "stalker.h"
+#include "stats.h"
+#include "util.h"
+
+#ifdef __APPLE__
+extern mach_port_t mach_task_self();
+extern GumAddress gum_darwin_find_entrypoint(mach_port_t task);
+#else
+extern int __libc_start_main(int *(main)(int, char **, char **), int argc,
+ char **ubp_av, void (*init)(void),
+ void (*fini)(void), void (*rtld_fini)(void),
+ void(*stack_end));
+#endif
+
+typedef int *(*main_fn_t)(int argc, char **argv, char **envp);
+
+static main_fn_t main_fn = NULL;
+
+static int on_fork(void) {
+
+ prefetch_read();
+ return fork();
+
+}
+
+#ifdef __APPLE__
+static void on_main_os(int argc, char **argv, char **envp) {
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+ UNUSED_PARAMETER(envp);
+
+}
+
+#else
+static void on_main_os(int argc, char **argv, char **envp) {
+
+ UNUSED_PARAMETER(argc);
+ /* Personality doesn't affect the current process, it only takes effect on
+ * evec */
+ int persona = personality(ADDR_NO_RANDOMIZE);
+ if (persona == -1) { WARNF("Failed to set ADDR_NO_RANDOMIZE: %d", errno); }
+ if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); }
+
+ GumInterceptor *interceptor = gum_interceptor_obtain();
+
+ gum_interceptor_begin_transaction(interceptor);
+ gum_interceptor_revert(interceptor, __libc_start_main);
+ gum_interceptor_end_transaction(interceptor);
+ gum_interceptor_flush(interceptor);
+
+}
+
+#endif
+
+static void embedded_init() {
+
+ static gboolean initialized = false;
+ if (!initialized) {
+
+ gum_init_embedded();
+ initialized = true;
+
+ }
+
+}
+
+void afl_frida_start() {
+
+ embedded_init();
+ stalker_init();
+ lib_init();
+ entry_init();
+ instrument_init();
+ output_init();
+ persistent_init();
+ prefetch_init();
+ ranges_init();
+ stats_init();
+
+ void *fork_addr =
+ GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork"));
+ intercept(fork_addr, on_fork, NULL);
+
+ stalker_start();
+ entry_run();
+
+}
+
+static int *on_main(int argc, char **argv, char **envp) {
+
+ on_main_os(argc, argv, envp);
+
+ unintercept_self();
+
+ afl_frida_start();
+
+ return main_fn(argc, argv, envp);
+
+}
+
+#if defined(EMBEDDED)
+extern int *main(int argc, char **argv, char **envp);
+
+static void intercept_main(void) {
+
+ main_fn = main;
+ intercept(main, on_main, NULL);
+
+}
+
+#elif defined(__APPLE__)
+static void intercept_main(void) {
+
+ mach_port_t task = mach_task_self();
+ OKF("Task Id: %u", task);
+ GumAddress entry = gum_darwin_find_entrypoint(task);
+ OKF("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry);
+ void *main = GSIZE_TO_POINTER(entry);
+ main_fn = main;
+ intercept(main, on_main, NULL);
+
+}
+
+#else
+static int on_libc_start_main(int *(main)(int, char **, char **), int argc,
+ char **ubp_av, void (*init)(void),
+ void (*fini)(void), void (*rtld_fini)(void),
+ void(*stack_end)) {
+
+ main_fn = main;
+ unintercept_self();
+ intercept(main, on_main, NULL);
+ return __libc_start_main(main, argc, ubp_av, init, fini, rtld_fini,
+ stack_end);
+
+}
+
+static void intercept_main(void) {
+
+ intercept(__libc_start_main, on_libc_start_main, NULL);
+
+}
+
+#endif
+
+__attribute__((constructor)) static void init(void) {
+
+ embedded_init();
+
+ intercept_main();
+
+}
+
diff --git a/frida_mode/src/output.c b/frida_mode/src/output.c
new file mode 100644
index 00000000..8a222b25
--- /dev/null
+++ b/frida_mode/src/output.c
@@ -0,0 +1,45 @@
+#include
+#include
+#include
+
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "output.h"
+
+static int output_fd = -1;
+
+static void output_redirect(int fd, char *variable) {
+
+ char *filename = getenv(variable);
+ char *path = NULL;
+
+ if (filename == NULL) { return; }
+
+ path = g_canonicalize_filename(filename, g_get_current_dir());
+
+ OKF("Redirect %d -> '%s'", fd, path);
+
+ output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+ g_free(path);
+
+ if (output_fd < 0) { FATAL("Failed to open fd(%d) error %d", fd, errno); }
+
+ if (dup2(output_fd, fd) < 0) {
+
+ FATAL("Failed to set fd(%d) error %d", fd, errno);
+
+ }
+
+}
+
+void output_init(void) {
+
+ output_redirect(STDOUT_FILENO, "AFL_FRIDA_OUTPUT_STDOUT");
+ output_redirect(STDERR_FILENO, "AFL_FRIDA_OUTPUT_STDERR");
+
+}
+
diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c
new file mode 100644
index 00000000..2ec5b9cc
--- /dev/null
+++ b/frida_mode/src/persistent/persistent.c
@@ -0,0 +1,97 @@
+#include
+
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+
+#include "persistent.h"
+#include "util.h"
+
+int __afl_sharedmem_fuzzing = 0;
+afl_persistent_hook_fn hook = NULL;
+guint64 persistent_start = 0;
+guint64 persistent_count = 0;
+guint64 persistent_ret = 0;
+guint64 persistent_ret_offset = 0;
+gboolean persistent_debug = FALSE;
+
+void persistent_init(void) {
+
+ char *hook_name = getenv("AFL_FRIDA_PERSISTENT_HOOK");
+
+ persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR");
+ persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT");
+ persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET");
+ persistent_ret_offset =
+ util_read_address("AFL_FRIDA_PERSISTENT_RETADDR_OFFSET");
+
+ if (getenv("AFL_FRIDA_PERSISTENT_DEBUG") != NULL) { persistent_debug = TRUE; }
+
+ if (persistent_count != 0 && persistent_start == 0) {
+
+ FATAL(
+ "AFL_FRIDA_PERSISTENT_ADDR must be specified if "
+ "AFL_FRIDA_PERSISTENT_CNT is");
+
+ }
+
+ if (persistent_ret != 0 && persistent_start == 0) {
+
+ FATAL(
+ "AFL_FRIDA_PERSISTENT_ADDR must be specified if "
+ "AFL_FRIDA_PERSISTENT_RET is");
+
+ }
+
+ if (persistent_ret_offset != 0 && persistent_ret == 0) {
+
+ FATAL(
+ "AFL_FRIDA_PERSISTENT_RET must be specified if "
+ "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET is");
+
+ }
+
+ if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000;
+
+ if (persistent_count != 0 && persistent_count < 100)
+ WARNF("Persistent count out of recommended range (<100)");
+
+ if (persistent_start != 0 && !persistent_is_supported())
+ FATAL("Persistent mode not supported on this architecture");
+
+ OKF("Instrumentation - persistent mode [%c] (0x%016" G_GINT64_MODIFIER "X)",
+ persistent_start == 0 ? ' ' : 'X', persistent_start);
+ OKF("Instrumentation - persistent count [%c] (%" G_GINT64_MODIFIER "d)",
+ persistent_start == 0 ? ' ' : 'X', persistent_count);
+ OKF("Instrumentation - hook [%s]", hook_name);
+
+ OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)",
+ persistent_ret == 0 ? ' ' : 'X', persistent_ret);
+ OKF("Instrumentation - persistent ret offset [%c] (%" G_GINT64_MODIFIER "d)",
+ persistent_ret_offset == 0 ? ' ' : 'X', persistent_ret_offset);
+
+ if (hook_name != NULL) {
+
+ void *hook_obj = dlopen(hook_name, RTLD_NOW);
+ if (hook_obj == NULL)
+ FATAL("Failed to load AFL_FRIDA_PERSISTENT_HOOK (%s)", hook_name);
+
+ int (*afl_persistent_hook_init_ptr)(void) =
+ dlsym(hook_obj, "afl_persistent_hook_init");
+ if (afl_persistent_hook_init_ptr == NULL)
+ FATAL("Failed to find afl_persistent_hook_init in %s", hook_name);
+
+ if (afl_persistent_hook_init_ptr() == 0)
+ FATAL("afl_persistent_hook_init returned a failure");
+
+ hook = (afl_persistent_hook_fn)dlsym(hook_obj, "afl_persistent_hook");
+ if (hook == NULL)
+ FATAL("Failed to find afl_persistent_hook in %s", hook_name);
+
+ __afl_sharedmem_fuzzing = 1;
+
+ }
+
+}
+
diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c
new file mode 100644
index 00000000..6a3c06fa
--- /dev/null
+++ b/frida_mode/src/persistent/persistent_arm32.c
@@ -0,0 +1,79 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "persistent.h"
+#include "util.h"
+
+#if defined(__arm__)
+
+struct arm_regs {
+
+ uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10;
+
+ union {
+
+ uint32_t r11;
+ uint32_t fp;
+
+ };
+
+ union {
+
+ uint32_t r12;
+ uint32_t ip;
+
+ };
+
+ union {
+
+ uint32_t r13;
+ uint32_t sp;
+
+ };
+
+ union {
+
+ uint32_t r14;
+ uint32_t lr;
+
+ };
+
+ union {
+
+ uint32_t r15;
+ uint32_t pc;
+
+ };
+
+ uint32_t cpsr;
+
+ uint8_t vfp_zregs[32][16];
+ uint32_t vfp_xregs[16];
+
+};
+
+typedef struct arm_regs arch_api_regs;
+
+gboolean persistent_is_supported(void) {
+
+ return false;
+
+}
+
+void persistent_prologue(GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(output);
+ FATAL("Persistent mode not supported on this architecture");
+
+}
+
+void persistent_epilogue(GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(output);
+ FATAL("Persistent mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c
new file mode 100644
index 00000000..1215d8da
--- /dev/null
+++ b/frida_mode/src/persistent/persistent_arm64.c
@@ -0,0 +1,122 @@
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+
+#include "instrument.h"
+#include "util.h"
+
+#if defined(__aarch64__)
+
+struct arm64_regs {
+
+ uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10;
+
+ union {
+
+ uint64_t x11;
+ uint32_t fp_32;
+
+ };
+
+ union {
+
+ uint64_t x12;
+ uint32_t ip_32;
+
+ };
+
+ union {
+
+ uint64_t x13;
+ uint32_t sp_32;
+
+ };
+
+ union {
+
+ uint64_t x14;
+ uint32_t lr_32;
+
+ };
+
+ union {
+
+ uint64_t x15;
+ uint32_t pc_32;
+
+ };
+
+ union {
+
+ uint64_t x16;
+ uint64_t ip0;
+
+ };
+
+ union {
+
+ uint64_t x17;
+ uint64_t ip1;
+
+ };
+
+ uint64_t x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28;
+
+ union {
+
+ uint64_t x29;
+ uint64_t fp;
+
+ };
+
+ union {
+
+ uint64_t x30;
+ uint64_t lr;
+
+ };
+
+ union {
+
+ uint64_t x31;
+ uint64_t sp;
+
+ };
+
+ // the zero register is not saved here ofc
+
+ uint64_t pc;
+
+ uint32_t cpsr;
+
+ uint8_t vfp_zregs[32][16 * 16];
+ uint8_t vfp_pregs[17][32];
+ uint32_t vfp_xregs[16];
+
+};
+
+typedef struct arm64_regs arch_api_regs;
+
+gboolean persistent_is_supported(void) {
+
+ return false;
+
+}
+
+void persistent_prologue(GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(output);
+ FATAL("Persistent mode not supported on this architecture");
+
+}
+
+void persistent_epilogue(GumStalkerOutput *output) {
+
+ UNUSED_PARAMETER(output);
+ FATAL("Persistent mode not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c
new file mode 100644
index 00000000..4cb960fc
--- /dev/null
+++ b/frida_mode/src/persistent/persistent_x64.c
@@ -0,0 +1,326 @@
+#include
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+
+#include "instrument.h"
+#include "persistent.h"
+#include "util.h"
+
+#if defined(__x86_64__)
+
+struct x86_64_regs {
+
+ uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14,
+ r15;
+
+ union {
+
+ uint64_t rip;
+ uint64_t pc;
+
+ };
+
+ union {
+
+ uint64_t rsp;
+ uint64_t sp;
+
+ };
+
+ union {
+
+ uint64_t rflags;
+ uint64_t flags;
+
+ };
+
+ uint8_t zmm_regs[32][64];
+
+};
+
+typedef struct x86_64_regs arch_api_regs;
+
+static arch_api_regs saved_regs = {0};
+
+gboolean persistent_is_supported(void) {
+
+ return true;
+
+}
+
+static void instrument_persitent_save_regs(GumX86Writer * cw,
+ struct x86_64_regs *regs) {
+
+ GumAddress regs_address = GUM_ADDRESS(regs);
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ -(GUM_RED_ZONE_SIZE));
+
+ /* Should be pushing FPU here, but meh */
+ gum_x86_writer_put_pushfx(cw);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_RAX);
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address);
+
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 1),
+ GUM_REG_RBX);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 2),
+ GUM_REG_RCX);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 3),
+ GUM_REG_RDX);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 4),
+ GUM_REG_RDI);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 5),
+ GUM_REG_RSI);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 6),
+ GUM_REG_RBP);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 7),
+ GUM_REG_R8);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 8),
+ GUM_REG_R9);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 9),
+ GUM_REG_R10);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 10),
+ GUM_REG_R11);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 11),
+ GUM_REG_R12);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 12),
+ GUM_REG_R13);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 13),
+ GUM_REG_R14);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 14),
+ GUM_REG_R15);
+
+ /* Store RIP */
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RBX,
+ GUM_ADDRESS(persistent_start));
+
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 15),
+ GUM_REG_RBX);
+
+ /* Store adjusted RSP */
+ gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_RBX, GUM_REG_RSP);
+
+ /* RED_ZONE + Saved flags, RAX, alignment */
+ gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX,
+ GUM_RED_ZONE_SIZE + (0x8 * 3));
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 16),
+ GUM_REG_RBX);
+
+ /* Save the flags */
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x8);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 17),
+ GUM_REG_RBX);
+
+ /* Save the RAX */
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x0);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 0),
+ GUM_REG_RBX);
+
+ /* Pop the saved values */
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 0x10);
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ (GUM_RED_ZONE_SIZE));
+
+}
+
+static void instrument_persitent_restore_regs(GumX86Writer * cw,
+ struct x86_64_regs *regs) {
+
+ GumAddress regs_address = GUM_ADDRESS(regs);
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address);
+
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RAX,
+ (0x8 * 2));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RAX,
+ (0x8 * 3));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDI, GUM_REG_RAX,
+ (0x8 * 4));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RAX,
+ (0x8 * 5));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBP, GUM_REG_RAX,
+ (0x8 * 6));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R8, GUM_REG_RAX,
+ (0x8 * 7));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R9, GUM_REG_RAX,
+ (0x8 * 8));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R10, GUM_REG_RAX,
+ (0x8 * 9));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R11, GUM_REG_RAX,
+ (0x8 * 10));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R12, GUM_REG_RAX,
+ (0x8 * 11));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R13, GUM_REG_RAX,
+ (0x8 * 12));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R14, GUM_REG_RAX,
+ (0x8 * 13));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX,
+ (0x8 * 14));
+
+ /* Don't restore RIP or RSP */
+
+ /* Restore RBX, RAX & Flags */
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ -(GUM_RED_ZONE_SIZE));
+
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX,
+ (0x8 * 1));
+ gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
+
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX,
+ (0x8 * 0));
+ gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX,
+ (0x8 * 17));
+ gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
+
+ gum_x86_writer_put_popfx(cw);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX);
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ (GUM_RED_ZONE_SIZE));
+
+}
+
+static void instrument_exit(GumX86Writer *cw) {
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(_exit));
+ gum_x86_writer_put_mov_reg_u32(cw, GUM_REG_RDI, 0);
+ gum_x86_writer_put_call_reg(cw, GUM_REG_RAX);
+
+}
+
+static int instrument_afl_persistent_loop_func(void) {
+
+ int ret = __afl_persistent_loop(persistent_count);
+ previous_pc = 0;
+ return ret;
+
+}
+
+static void instrument_afl_persistent_loop(GumX86Writer *cw) {
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ -(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_REG_RAX, GUM_REG_RAX);
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ (GUM_RED_ZONE_SIZE));
+
+}
+
+static void persistent_prologue_hook(GumX86Writer * cw,
+ struct x86_64_regs *regs) {
+
+ if (hook == NULL) return;
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ -(GUM_RED_ZONE_SIZE));
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RCX,
+ GUM_ADDRESS(&__afl_fuzz_len));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0);
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0);
+ gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_RDI, 0xffffffff);
+ gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RCX, GUM_REG_RDI);
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX,
+ GUM_ADDRESS(&__afl_fuzz_ptr));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0);
+
+ gum_x86_writer_put_call_address_with_arguments(
+ cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 4, GUM_ARG_ADDRESS,
+ GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER,
+ GUM_REG_RDX, GUM_ARG_REGISTER, GUM_REG_RCX);
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ (GUM_RED_ZONE_SIZE));
+
+}
+
+void persistent_prologue(GumStalkerOutput *output) {
+
+ /*
+ * SAVE REGS
+ * SAVE RET
+ * POP RET
+ * loop:
+ * CALL instrument_afl_persistent_loop
+ * 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;
+
+ /* Stack must be 16-byte aligned per ABI */
+ instrument_persitent_save_regs(cw, &saved_regs);
+
+ /* pop the return value */
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (8));
+
+ /* loop: */
+ gum_x86_writer_put_label(cw, loop);
+
+ /* 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);
+
+ 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);
+
+ if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
+
+ gum_x86_writer_flush(cw);
+
+}
+
+void persistent_epilogue(GumStalkerOutput *output) {
+
+ GumX86Writer *cw = output->writer.x86;
+
+ if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+ persistent_ret_offset);
+ gum_x86_writer_put_ret(cw);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c
new file mode 100644
index 00000000..b30dfadf
--- /dev/null
+++ b/frida_mode/src/persistent/persistent_x86.c
@@ -0,0 +1,267 @@
+#include "frida-gum.h"
+
+#include "config.h"
+
+#include "instrument.h"
+#include "persistent.h"
+
+#if defined(__i386__)
+
+struct x86_regs {
+
+ uint32_t eax, ebx, ecx, edx, edi, esi, ebp;
+
+ union {
+
+ uint32_t eip;
+ uint32_t pc;
+
+ };
+
+ union {
+
+ uint32_t esp;
+ uint32_t sp;
+
+ };
+
+ union {
+
+ uint32_t eflags;
+ uint32_t flags;
+
+ };
+
+ uint8_t xmm_regs[8][16];
+
+};
+
+typedef struct x86_regs arch_api_regs;
+
+static arch_api_regs saved_regs = {0};
+
+gboolean persistent_is_supported(void) {
+
+ return true;
+
+}
+
+static void instrument_persitent_save_regs(GumX86Writer * cw,
+ struct x86_regs *regs) {
+
+ GumAddress regs_address = GUM_ADDRESS(regs);
+
+ /* Should be pushing FPU here, but meh */
+ gum_x86_writer_put_pushfx(cw);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address);
+
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 1),
+ GUM_REG_EBX);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 2),
+ GUM_REG_ECX);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 3),
+ GUM_REG_EDX);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 4),
+ GUM_REG_EDI);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 5),
+ GUM_REG_ESI);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 6),
+ GUM_REG_EBP);
+
+ /* Store RIP */
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EBX,
+ GUM_ADDRESS(persistent_start));
+
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 7),
+ GUM_REG_EBX);
+
+ /* Store adjusted RSP */
+ gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_EBX, GUM_REG_ESP);
+
+ /* RED_ZONE + Saved flags, RAX */
+ gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EBX, (0x4 * 2));
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 8),
+ GUM_REG_EBX);
+
+ /* Save the flags */
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x4);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 9),
+ GUM_REG_EBX);
+
+ /* Save the RAX */
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x0);
+ gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, (0x4 * 0),
+ GUM_REG_EBX);
+
+ /* Pop the saved values */
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 0x8);
+
+}
+
+static void instrument_persitent_restore_regs(GumX86Writer * cw,
+ struct x86_regs *regs) {
+
+ GumAddress regs_address = GUM_ADDRESS(regs);
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, regs_address);
+
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_EAX,
+ (0x4 * 2));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX,
+ (0x4 * 3));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX,
+ (0x4 * 4));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX,
+ (0x4 * 5));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX,
+ (0x4 * 6));
+
+ /* Don't restore RIP or RSP */
+
+ /* Restore RBX, RAX & Flags */
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
+ (0x4 * 1));
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
+
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
+ (0x4 * 0));
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
+ (0x4 * 9));
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
+
+ gum_x86_writer_put_popfx(cw);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
+ gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
+
+}
+
+static void instrument_exit(GumX86Writer *cw) {
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(_exit));
+ gum_x86_writer_put_mov_reg_u32(cw, GUM_REG_EDI, 0);
+ gum_x86_writer_put_push_reg(cw, GUM_REG_EDI);
+ gum_x86_writer_put_call_reg(cw, GUM_REG_EAX);
+
+}
+
+static int instrument_afl_persistent_loop_func(void) {
+
+ int ret = __afl_persistent_loop(persistent_count);
+ previous_pc = 0;
+ return ret;
+
+}
+
+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_REG_EAX, GUM_REG_EAX);
+
+}
+
+static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) {
+
+ if (hook == NULL) return;
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX,
+ GUM_ADDRESS(&__afl_fuzz_len));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0);
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ECX, GUM_REG_ECX, 0);
+
+ gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDX,
+ GUM_ADDRESS(&__afl_fuzz_ptr));
+ gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EDX, 0);
+
+ /* Base address is 64-bits (hence two zero arguments) */
+ gum_x86_writer_put_call_address_with_arguments(
+ cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 5, GUM_ARG_ADDRESS,
+ GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_ADDRESS,
+ GUM_ADDRESS(0), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER,
+ GUM_REG_ECX);
+
+}
+
+void persistent_prologue(GumStalkerOutput *output) {
+
+ /*
+ * SAVE REGS
+ * SAVE RET
+ * POP RET
+ * loop:
+ * CALL instrument_afl_persistent_loop
+ * 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;
+
+ /* Stack must be 16-byte aligned per ABI */
+ instrument_persitent_save_regs(cw, &saved_regs);
+
+ /* Pop the return value */
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4));
+
+ /* loop: */
+ gum_x86_writer_put_label(cw, loop);
+
+ /* 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);
+
+ 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);
+
+ if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
+
+ gum_x86_writer_flush(cw);
+
+}
+
+void persistent_epilogue(GumStalkerOutput *output) {
+
+ GumX86Writer *cw = output->writer.x86;
+
+ if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
+
+ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP,
+ persistent_ret_offset);
+
+ gum_x86_writer_put_ret(cw);
+
+}
+
+#endif
+
diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c
new file mode 100644
index 00000000..65c09fba
--- /dev/null
+++ b/frida_mode/src/prefetch.c
@@ -0,0 +1,112 @@
+#include
+#include
+#include
+
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "prefetch.h"
+#include "stalker.h"
+
+#define TRUST 0
+#define PREFETCH_SIZE 65536
+#define PREFETCH_ENTRIES ((PREFETCH_SIZE - sizeof(size_t)) / sizeof(void *))
+
+typedef struct {
+
+ size_t count;
+ void * entry[PREFETCH_ENTRIES];
+
+} prefetch_data_t;
+
+static prefetch_data_t *prefetch_data = NULL;
+
+static int prefetch_shm_id = -1;
+
+/*
+ * We do this from the transformer since we need one anyway for coverage, this
+ * saves the need to use an event sink.
+ */
+void prefetch_write(void *addr) {
+
+ /* Bail if we aren't initialized */
+ if (prefetch_data == NULL) return;
+
+ /*
+ * Our shared memory IPC is large enough for about 1000 entries, we can fine
+ * tune this if we need to. But if we have more new blocks that this in a
+ * single run then we ignore them and we'll pick them up next time.
+ */
+ if (prefetch_data->count >= PREFETCH_ENTRIES) return;
+
+ /*
+ * Write the block address to the SHM IPC and increment the number of entries.
+ */
+
+ prefetch_data->entry[prefetch_data->count] = addr;
+ prefetch_data->count++;
+
+}
+
+/*
+ * Read the IPC region one block at the time and prefetch it
+ */
+void prefetch_read(void) {
+
+ GumStalker *stalker = stalker_get();
+ if (prefetch_data == NULL) return;
+
+ for (size_t i = 0; i < prefetch_data->count; i++) {
+
+ void *addr = prefetch_data->entry[i];
+ gum_stalker_prefetch(stalker, addr, 1);
+
+ }
+
+ /*
+ * Reset the entry count to indicate we have finished with it and it can be
+ * refilled by the child.
+ */
+ prefetch_data->count = 0;
+
+}
+
+void prefetch_init(void) {
+
+ g_assert_cmpint(sizeof(prefetch_data_t), ==, PREFETCH_SIZE);
+ gboolean prefetch = (getenv("AFL_FRIDA_INST_NO_PREFETCH") == NULL);
+
+ OKF("Instrumentation - prefetch [%c]", prefetch ? 'X' : ' ');
+
+ if (!prefetch) { return; }
+ /*
+ * Make our shared memory, we can attach before we fork, just like AFL does
+ * with the coverage bitmap region and fork will take care of ensuring both
+ * the parent and child see the same consistent memory region.
+ */
+ prefetch_shm_id =
+ shmget(IPC_PRIVATE, sizeof(prefetch_data_t), IPC_CREAT | IPC_EXCL | 0600);
+ if (prefetch_shm_id < 0) {
+
+ FATAL("prefetch_shm_id < 0 - errno: %d\n", errno);
+
+ }
+
+ prefetch_data = shmat(prefetch_shm_id, NULL, 0);
+ g_assert(prefetch_data != MAP_FAILED);
+
+ /*
+ * Configure the shared memory region to be removed once the process dies.
+ */
+ if (shmctl(prefetch_shm_id, IPC_RMID, NULL) < 0) {
+
+ FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
+
+ }
+
+ /* Clear it, not sure it's necessary, just seems like good practice */
+ memset(prefetch_data, '\0', sizeof(prefetch_data_t));
+
+}
+
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
new file mode 100644
index 00000000..ef25b371
--- /dev/null
+++ b/frida_mode/src/ranges.c
@@ -0,0 +1,611 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "lib.h"
+#include "ranges.h"
+#include "stalker.h"
+#include "util.h"
+
+#define MAX_RANGES 20
+
+typedef struct {
+
+ gchar * suffix;
+ GumMemoryRange *range;
+ gboolean done;
+
+} convert_name_ctx_t;
+
+GArray *module_ranges = NULL;
+GArray *libs_ranges = NULL;
+GArray *include_ranges = NULL;
+GArray *exclude_ranges = NULL;
+GArray *ranges = NULL;
+
+static void convert_address_token(gchar *token, GumMemoryRange *range) {
+
+ gchar **tokens;
+ int token_count;
+ tokens = g_strsplit(token, "-", 2);
+ for (token_count = 0; tokens[token_count] != NULL; token_count++) {}
+
+ if (token_count != 2) {
+
+ FATAL("Invalid range (should have two addresses seperated by a '-'): %s\n",
+ token);
+
+ }
+
+ gchar *from_str = tokens[0];
+ gchar *to_str = tokens[1];
+
+ if (!g_str_has_prefix(from_str, "0x")) {
+
+ FATAL("Invalid range: %s - Start address should have 0x prefix: %s\n",
+ token, from_str);
+
+ }
+
+ if (!g_str_has_prefix(to_str, "0x")) {
+
+ FATAL("Invalid range: %s - End address should have 0x prefix: %s\n", token,
+ to_str);
+
+ }
+
+ from_str = &from_str[2];
+ to_str = &to_str[2];
+
+ for (char *c = from_str; *c != '\0'; c++) {
+
+ if (!g_ascii_isxdigit(*c)) {
+
+ FATAL("Invalid range: %s - Start address not formed of hex digits: %s\n",
+ token, from_str);
+
+ }
+
+ }
+
+ for (char *c = to_str; *c != '\0'; c++) {
+
+ if (!g_ascii_isxdigit(*c)) {
+
+ FATAL("Invalid range: %s - End address not formed of hex digits: %s\n",
+ token, to_str);
+
+ }
+
+ }
+
+ guint64 from = g_ascii_strtoull(from_str, NULL, 16);
+ if (from == 0) {
+
+ FATAL("Invalid range: %s - Start failed hex conversion: %s\n", token,
+ from_str);
+
+ }
+
+ guint64 to = g_ascii_strtoull(to_str, NULL, 16);
+ if (to == 0) {
+
+ FATAL("Invalid range: %s - End failed hex conversion: %s\n", token, to_str);
+
+ }
+
+ if (from >= to) {
+
+ FATAL("Invalid range: %s - Start (0x%016" G_GINT64_MODIFIER
+ "x) must be less than end "
+ "(0x%016" G_GINT64_MODIFIER "x)\n",
+ token, from, to);
+
+ }
+
+ range->base_address = from;
+ range->size = to - from;
+
+ g_strfreev(tokens);
+
+}
+
+static gboolean convert_name_token_for_module(const GumModuleDetails *details,
+ gpointer user_data) {
+
+ convert_name_ctx_t *ctx = (convert_name_ctx_t *)user_data;
+ if (details->path == NULL) { return true; };
+
+ if (!g_str_has_suffix(details->path, ctx->suffix)) { return true; };
+
+ OKF("Found module - prefix: %s, 0x%016" G_GINT64_MODIFIER
+ "x-0x%016" G_GINT64_MODIFIER "x %s",
+ ctx->suffix, details->range->base_address,
+ details->range->base_address + details->range->size, details->path);
+
+ *ctx->range = *details->range;
+ ctx->done = true;
+ return false;
+
+}
+
+static void convert_name_token(gchar *token, GumMemoryRange *range) {
+
+ gchar * suffix = g_strconcat("/", token, NULL);
+ convert_name_ctx_t ctx = {.suffix = suffix, .range = range, .done = false};
+
+ gum_process_enumerate_modules(convert_name_token_for_module, &ctx);
+ if (!ctx.done) { FATAL("Failed to resolve module: %s\n", token); }
+ g_free(suffix);
+
+}
+
+static void convert_token(gchar *token, GumMemoryRange *range) {
+
+ if (g_strrstr(token, "-")) {
+
+ convert_address_token(token, range);
+
+ } else {
+
+ convert_name_token(token, range);
+
+ }
+
+ OKF("Converted token: %s -> 0x%016" G_GINT64_MODIFIER
+ "x-0x%016" G_GINT64_MODIFIER "x\n",
+ token, range->base_address, range->base_address + range->size);
+
+}
+
+gint range_sort(gconstpointer a, gconstpointer b) {
+
+ return ((GumMemoryRange *)a)->base_address -
+ ((GumMemoryRange *)b)->base_address;
+
+}
+
+static gboolean print_ranges_callback(const GumRangeDetails *details,
+ gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+ if (details->file == NULL) {
+
+ OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER "X",
+ details->range->base_address,
+ details->range->base_address + details->range->size);
+
+ } else {
+
+ OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER
+ "X %s(0x%016" G_GINT64_MODIFIER "x)",
+ details->range->base_address,
+ details->range->base_address + details->range->size,
+ details->file->path, details->file->offset);
+
+ }
+
+ return true;
+
+}
+
+static void print_ranges(char *key, GArray *ranges) {
+
+ OKF("Range: %s Length: %d", key, ranges->len);
+ for (guint i = 0; i < ranges->len; i++) {
+
+ GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i);
+ GumAddress curr_limit = curr->base_address + curr->size;
+ OKF("Range: %s Idx: %3d - 0x%016" G_GINT64_MODIFIER
+ "x-0x%016" G_GINT64_MODIFIER "x",
+ key, i, curr->base_address, curr_limit);
+
+ }
+
+}
+
+static gboolean collect_module_ranges_callback(const GumRangeDetails *details,
+ gpointer user_data) {
+
+ GArray * ranges = (GArray *)user_data;
+ GumMemoryRange range = *details->range;
+ g_array_append_val(ranges, range);
+ return TRUE;
+
+}
+
+static GArray *collect_module_ranges(void) {
+
+ GArray *result;
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+ gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS,
+ collect_module_ranges_callback, result);
+ print_ranges("Modules", result);
+ return result;
+
+}
+
+static GArray *collect_ranges(char *env_key) {
+
+ char * env_val;
+ gchar ** tokens;
+ int token_count;
+ GumMemoryRange range;
+ int i;
+ GArray * result;
+
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+
+ env_val = getenv(env_key);
+ if (env_val == NULL) return result;
+
+ tokens = g_strsplit(env_val, ",", MAX_RANGES);
+
+ for (token_count = 0; tokens[token_count] != NULL; token_count++)
+ ;
+
+ for (i = 0; i < token_count; i++) {
+
+ convert_token(tokens[i], &range);
+ g_array_append_val(result, range);
+
+ }
+
+ g_array_sort(result, range_sort);
+
+ /* Check for overlaps */
+ for (i = 1; i < token_count; i++) {
+
+ GumMemoryRange *prev = &g_array_index(result, GumMemoryRange, i - 1);
+ GumMemoryRange *curr = &g_array_index(result, GumMemoryRange, i);
+ GumAddress prev_limit = prev->base_address + prev->size;
+ GumAddress curr_limit = curr->base_address + curr->size;
+ if (prev_limit > curr->base_address) {
+
+ FATAL("OVerlapping ranges 0x%016" G_GINT64_MODIFIER
+ "x-0x%016" G_GINT64_MODIFIER "x 0x%016" G_GINT64_MODIFIER
+ "x-0x%016" G_GINT64_MODIFIER "x",
+ prev->base_address, prev_limit, curr->base_address, curr_limit);
+
+ }
+
+ }
+
+ print_ranges(env_key, result);
+
+ g_strfreev(tokens);
+
+ return result;
+
+}
+
+static GArray *collect_libs_ranges(void) {
+
+ GArray * result;
+ GumMemoryRange range;
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+
+ if (getenv("AFL_INST_LIBS") == NULL) {
+
+ range.base_address = lib_get_text_base();
+ range.size = lib_get_text_limit() - lib_get_text_base();
+
+ } else {
+
+ range.base_address = 0;
+ range.size = G_MAXULONG;
+
+ }
+
+ g_array_append_val(result, range);
+
+ print_ranges("AFL_INST_LIBS", result);
+
+ return result;
+
+}
+
+static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra,
+ GumMemoryRange *rb) {
+
+ GumAddress rab = ra->base_address;
+ GumAddress ral = rab + ra->size;
+
+ GumAddress rbb = rb->base_address;
+ GumAddress rbl = rbb + rb->size;
+
+ GumAddress rrb = 0;
+ GumAddress rrl = 0;
+
+ rr->base_address = 0;
+ rr->size = 0;
+
+ /* ra is before rb */
+ if (ral < rbb) { return false; }
+
+ /* ra is after rb */
+ if (rab > rbl) { return true; }
+
+ /* The largest of the two base addresses */
+ rrb = rab > rbb ? rab : rbb;
+
+ /* The smallest of the two limits */
+ rrl = ral < rbl ? ral : rbl;
+
+ rr->base_address = rrb;
+ rr->size = rrl - rrb;
+ return true;
+
+}
+
+static GArray *intersect_ranges(GArray *a, GArray *b) {
+
+ GArray * result;
+ GumMemoryRange *ra;
+ GumMemoryRange *rb;
+ GumMemoryRange ri;
+
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+
+ for (guint i = 0; i < a->len; i++) {
+
+ ra = &g_array_index(a, GumMemoryRange, i);
+ for (guint j = 0; j < b->len; j++) {
+
+ rb = &g_array_index(b, GumMemoryRange, j);
+
+ if (!intersect_range(&ri, ra, rb)) { break; }
+
+ if (ri.size == 0) { continue; }
+
+ g_array_append_val(result, ri);
+
+ }
+
+ }
+
+ return result;
+
+}
+
+static GArray *subtract_ranges(GArray *a, GArray *b) {
+
+ GArray * result;
+ GumMemoryRange *ra;
+ GumAddress ral;
+ GumMemoryRange *rb;
+ GumMemoryRange ri;
+ GumMemoryRange rs;
+
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+
+ for (guint i = 0; i < a->len; i++) {
+
+ ra = &g_array_index(a, GumMemoryRange, i);
+ ral = ra->base_address + ra->size;
+ for (guint j = 0; j < b->len; j++) {
+
+ rb = &g_array_index(b, GumMemoryRange, j);
+
+ /*
+ * If rb is after ra, we have no more possible intersections and we can
+ * simply keep the remaining range
+ */
+ if (!intersect_range(&ri, ra, rb)) { break; }
+
+ /*
+ * If there is no intersection, then rb must be before ra, so we must
+ * continue
+ */
+ if (ri.size == 0) { continue; }
+
+ /*
+ * If the intersection is part way through the range, then we keep the
+ * start of the range
+ */
+ if (ra->base_address < ri.base_address) {
+
+ rs.base_address = ra->base_address;
+ rs.size = ri.base_address - ra->base_address;
+ g_array_append_val(result, rs);
+
+ }
+
+ /*
+ * If the intersection extends past the limit of the range, then we should
+ * continue with the next range
+ */
+ if ((ri.base_address + ri.size) > ral) {
+
+ ra->base_address = ral;
+ ra->size = 0;
+ break;
+
+ }
+
+ /*
+ * Otherwise we advance the base of the range to the end of the
+ * intersection and continue with the remainder of the range
+ */
+ ra->base_address = ri.base_address + ri.size;
+ ra->size = ral - ra->base_address;
+
+ }
+
+ /*
+ * When we have processed all the possible intersections, we add what is
+ * left
+ */
+ if (ra->size != 0) g_array_append_val(result, *ra);
+
+ }
+
+ return result;
+
+}
+
+static GArray *merge_ranges(GArray *a) {
+
+ GArray * result;
+ GumMemoryRange rp;
+ GumMemoryRange *r;
+
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+ if (a->len == 0) return result;
+
+ rp = g_array_index(a, GumMemoryRange, 0);
+
+ for (guint i = 1; i < a->len; i++) {
+
+ r = &g_array_index(a, GumMemoryRange, i);
+
+ if (rp.base_address + rp.size == r->base_address) {
+
+ rp.size += r->size;
+
+ } else {
+
+ g_array_append_val(result, rp);
+ rp.base_address = r->base_address;
+ rp.size = r->size;
+ continue;
+
+ }
+
+ }
+
+ g_array_append_val(result, rp);
+
+ return result;
+
+}
+
+static gboolean exclude_ranges_callback(const GumRangeDetails *details,
+ gpointer user_data) {
+
+ UNUSED_PARAMETER(user_data);
+ gchar * name;
+ gboolean found;
+ GumStalker *stalker;
+ if (details->file == NULL) { return TRUE; }
+ name = g_path_get_basename(details->file->path);
+
+ found = (g_strcmp0(name, "afl-frida-trace.so") == 0);
+ g_free(name);
+ if (!found) { return TRUE; }
+
+ stalker = stalker_get();
+ gum_stalker_exclude(stalker, details->range);
+
+ return FALSE;
+
+}
+
+static void ranges_exclude_self(void) {
+
+ gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, exclude_ranges_callback, NULL);
+
+}
+
+void ranges_init(void) {
+
+ GumMemoryRange ri;
+ GArray * step1;
+ GArray * step2;
+ GArray * step3;
+ GArray * step4;
+
+ if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) {
+
+ gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
+ NULL);
+
+ }
+
+ module_ranges = collect_module_ranges();
+ libs_ranges = collect_libs_ranges();
+ include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
+
+ /* If include ranges is empty, then assume everything is included */
+ if (include_ranges->len == 0) {
+
+ ri.base_address = 0;
+ ri.size = G_MAXULONG;
+ g_array_append_val(include_ranges, ri);
+
+ }
+
+ exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");
+
+ /* Intersect with .text section of main executable unless AFL_INST_LIBS */
+ step1 = intersect_ranges(module_ranges, libs_ranges);
+ print_ranges("step1", step1);
+
+ /* Intersect with AFL_FRIDA_INST_RANGES */
+ step2 = intersect_ranges(step1, include_ranges);
+ print_ranges("step2", step2);
+
+ /* Subtract AFL_FRIDA_EXCLUDE_RANGES */
+ step3 = subtract_ranges(step2, exclude_ranges);
+ print_ranges("step3", step3);
+
+ /*
+ * After step3, we have the total ranges to be instrumented, we now subtract
+ * that from the original ranges of the modules to configure stalker.
+ */
+
+ step4 = subtract_ranges(module_ranges, step3);
+ print_ranges("step4", step4);
+
+ ranges = merge_ranges(step4);
+ print_ranges("final", ranges);
+
+ g_array_free(step4, TRUE);
+ g_array_free(step3, TRUE);
+ g_array_free(step2, TRUE);
+ g_array_free(step1, TRUE);
+
+ /* *NEVER* stalk the stalker, only bad things will ever come of this! */
+ ranges_exclude_self();
+
+ ranges_exclude();
+
+}
+
+gboolean range_is_excluded(gpointer address) {
+
+ GumAddress test = GUM_ADDRESS(address);
+
+ if (ranges == NULL) { return false; }
+
+ for (guint i = 0; i < ranges->len; i++) {
+
+ GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i);
+ GumAddress curr_limit = curr->base_address + curr->size;
+
+ if (test < curr->base_address) { return false; }
+
+ if (test < curr_limit) { return true; }
+
+ }
+
+ return false;
+
+}
+
+void ranges_exclude() {
+
+ GumMemoryRange *r;
+ GumStalker * stalker = stalker_get();
+
+ OKF("Excluding ranges");
+
+ for (guint i = 0; i < ranges->len; i++) {
+
+ r = &g_array_index(ranges, GumMemoryRange, i);
+ gum_stalker_exclude(stalker, r);
+
+ }
+
+}
+
diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c
new file mode 100644
index 00000000..63f3c529
--- /dev/null
+++ b/frida_mode/src/stalker.c
@@ -0,0 +1,32 @@
+#include "debug.h"
+
+#include "instrument.h"
+#include "stalker.h"
+
+static GumStalker *stalker = NULL;
+
+void stalker_init(void) {
+
+ if (!gum_stalker_is_supported()) { FATAL("Failed to initialize embedded"); }
+
+ stalker = gum_stalker_new();
+ if (stalker == NULL) { FATAL("Failed to initialize stalker"); }
+
+ gum_stalker_set_trust_threshold(stalker, 0);
+
+}
+
+GumStalker *stalker_get(void) {
+
+ if (stalker == NULL) { FATAL("Stalker uninitialized"); }
+ return stalker;
+
+}
+
+void stalker_start(void) {
+
+ GumStalkerTransformer *transformer = instrument_get_transformer();
+ gum_stalker_follow_me(stalker, transformer, NULL);
+
+}
+
diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c
new file mode 100644
index 00000000..662fb6d5
--- /dev/null
+++ b/frida_mode/src/stats/stats.c
@@ -0,0 +1,208 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "frida-gum.h"
+
+#include "config.h"
+#include "debug.h"
+#include "util.h"
+
+#include "stats.h"
+
+#define MICRO_TO_SEC 1000000
+
+stats_data_header_t *stats_data = NULL;
+
+static int stats_parent_pid = -1;
+static int stats_fd = -1;
+static gboolean stats_transitions = FALSE;
+static guint64 stats_interval = 0;
+
+void stats_init(void) {
+
+ stats_parent_pid = getpid();
+ char *filename = getenv("AFL_FRIDA_STATS_FILE");
+ stats_interval = util_read_num("AFL_FRIDA_STATS_INTERVAL");
+ if (getenv("AFL_FRIDA_STATS_TRANSITIONS") != NULL) {
+
+ stats_transitions = TRUE;
+
+ }
+
+ OKF("Stats - file [%s]", filename);
+ OKF("Stats - interval [%" G_GINT64_MODIFIER "u]", stats_interval);
+
+ if (stats_interval != 0 && filename == NULL) {
+
+ FATAL(
+ "AFL_FRIDA_STATS_FILE must be specified if "
+ "AFL_FRIDA_STATS_INTERVAL is");
+
+ }
+
+ if (stats_interval == 0) { stats_interval = 10; }
+
+ if (filename == NULL) { return; }
+
+ if (!stats_is_supported_arch()) {
+
+ FATAL("Stats is not supported on this architecture");
+
+ }
+
+ char *path = NULL;
+
+ if (filename == NULL) { return; }
+
+ if (stats_transitions) { gum_stalker_set_counters_enabled(TRUE); }
+
+ path = g_canonicalize_filename(filename, g_get_current_dir());
+
+ OKF("Stats - path [%s]", path);
+
+ stats_fd = open(path, O_RDWR | O_CREAT | O_TRUNC,
+ S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+
+ if (stats_fd < 0) { FATAL("Failed to open stats file '%s'", path); }
+
+ g_free(path);
+
+ size_t data_size = stats_data_size_arch();
+
+ int shm_id = shmget(IPC_PRIVATE, data_size, IPC_CREAT | IPC_EXCL | 0600);
+ if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); }
+
+ stats_data = shmat(shm_id, NULL, 0);
+ g_assert(stats_data != MAP_FAILED);
+
+ /*
+ * Configure the shared memory region to be removed once the process dies.
+ */
+ if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
+
+ FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
+
+ }
+
+ /* Clear it, not sure it's necessary, just seems like good practice */
+ memset(stats_data, '\0', data_size);
+
+}
+
+void stats_vprint(int fd, char *format, va_list ap) {
+
+ char buffer[4096] = {0};
+ int ret;
+ int len;
+
+ if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; }
+
+ len = strnlen(buffer, sizeof(buffer));
+ IGNORED_RETURN(write(fd, buffer, len));
+
+}
+
+void stats_print_fd(int fd, char *format, ...) {
+
+ va_list ap;
+ va_start(ap, format);
+ stats_vprint(fd, format, ap);
+ va_end(ap);
+
+}
+
+void stats_print(char *format, ...) {
+
+ va_list ap;
+ va_start(ap, format);
+ stats_vprint(stats_fd, format, ap);
+ va_end(ap);
+
+}
+
+void stats_write(void) {
+
+ if (stats_parent_pid == getpid()) { return; }
+
+ GDateTime *date_time = g_date_time_new_now_local();
+ char *date_time_string = g_date_time_format(date_time, "%Y-%m-%e %H:%M:%S");
+
+ stats_print("stats\n");
+ stats_print("-----\n");
+
+ stats_print("Index: %" G_GINT64_MODIFIER "u\n",
+ stats_data->stats_idx++);
+ stats_print("Pid: %d\n", getpid());
+ stats_print("Time: %s\n", date_time_string);
+ stats_print("Blocks: %" G_GINT64_MODIFIER "u\n",
+ stats_data->num_blocks);
+ stats_print("Instructions: %" G_GINT64_MODIFIER "u\n",
+ stats_data->num_instructions);
+ stats_print("Avg Instructions / Block: %" G_GINT64_MODIFIER "u\n",
+ stats_data->num_instructions / stats_data->num_blocks);
+
+ stats_print("\n");
+
+ g_free(date_time_string);
+ g_date_time_unref(date_time);
+
+ stats_write_arch();
+
+ if (stats_transitions) {
+
+ GDateTime *date_time = g_date_time_new_now_local();
+ char *date_time_string = g_date_time_format(date_time, "%Y-%m-%e %H:%M:%S");
+
+ stats_print_fd(STDERR_FILENO, "stats\n");
+ stats_print_fd(STDERR_FILENO, "-----\n");
+ stats_print_fd(STDERR_FILENO, "Index: %" G_GINT64_MODIFIER "u\n",
+ stats_data->transitions_idx++);
+ stats_print_fd(STDERR_FILENO, "Pid: %d\n", getpid());
+ stats_print_fd(STDERR_FILENO, "Time: %s\n", date_time_string);
+
+ g_free(date_time_string);
+ g_date_time_unref(date_time);
+ gum_stalker_dump_counters();
+
+ }
+
+}
+
+static void stats_maybe_write(void) {
+
+ guint64 current_time;
+
+ if (stats_interval == 0) { return; }
+
+ current_time = g_get_monotonic_time();
+
+ if ((current_time - stats_data->stats_last_time) >
+ (stats_interval * MICRO_TO_SEC)) {
+
+ stats_write();
+ stats_data->stats_last_time = current_time;
+
+ }
+
+}
+
+void stats_collect(const cs_insn *instr, gboolean begin) {
+
+ UNUSED_PARAMETER(instr);
+ UNUSED_PARAMETER(begin);
+
+ if (stats_fd < 0) { return; }
+
+ if (begin) { stats_data->num_blocks++; }
+ stats_data->num_instructions++;
+
+ stats_collect_arch(instr);
+
+ stats_maybe_write();
+
+}
+
diff --git a/frida_mode/src/stats/stats_arm.c b/frida_mode/src/stats/stats_arm.c
new file mode 100644
index 00000000..7eea7f91
--- /dev/null
+++ b/frida_mode/src/stats/stats_arm.c
@@ -0,0 +1,36 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "stats.h"
+#include "util.h"
+
+#if defined(__arm__)
+
+gboolean stats_is_supported_arch(void) {
+
+ return FALSE;
+
+}
+
+size_t stats_data_size_arch(void) {
+
+ FATAL("Stats not supported on this architecture");
+
+}
+
+void stats_write_arch(void) {
+
+ FATAL("Stats not supported on this architecture");
+
+}
+
+void stats_collect_arch(const cs_insn *instr) {
+
+ UNUSED_PARAMETER(instr);
+ FATAL("Stats not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/stats/stats_arm64.c b/frida_mode/src/stats/stats_arm64.c
new file mode 100644
index 00000000..592af87a
--- /dev/null
+++ b/frida_mode/src/stats/stats_arm64.c
@@ -0,0 +1,36 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "stats.h"
+#include "util.h"
+
+#if defined(__aarch64__)
+
+gboolean stats_is_supported_arch(void) {
+
+ return FALSE;
+
+}
+
+size_t stats_data_size_arch(void) {
+
+ FATAL("Stats not supported on this architecture");
+
+}
+
+void stats_write_arch(void) {
+
+ FATAL("Stats not supported on this architecture");
+
+}
+
+void stats_collect_arch(const cs_insn *instr) {
+
+ UNUSED_PARAMETER(instr);
+ FATAL("Stats not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/stats/stats_x64.c b/frida_mode/src/stats/stats_x64.c
new file mode 100644
index 00000000..c3e8742a
--- /dev/null
+++ b/frida_mode/src/stats/stats_x64.c
@@ -0,0 +1,307 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "ranges.h"
+#include "stats.h"
+#include "util.h"
+
+#if defined(__x86_64__)
+
+typedef struct {
+
+ stats_data_header_t header;
+
+ guint64 num_call_imm;
+ guint64 num_call_imm_excluded;
+ guint64 num_call_reg;
+ guint64 num_call_mem;
+
+ guint64 num_jmp_imm;
+ guint64 num_jmp_reg;
+ guint64 num_jmp_mem;
+
+ guint64 num_jmp_cond_imm;
+ guint64 num_jmp_cond_reg;
+ guint64 num_jmp_cond_mem;
+
+ guint64 num_jmp_cond_jcxz;
+
+ guint64 num_ret;
+
+ guint64 num_rip_relative;
+
+} stats_data_arch_t;
+
+gboolean stats_is_supported_arch(void) {
+
+ return TRUE;
+
+}
+
+size_t stats_data_size_arch(void) {
+
+ return sizeof(stats_data_arch_t);
+
+}
+
+void stats_write_arch(void) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ guint64 num_instructions = stats_data_arch->header.num_instructions;
+
+ stats_print(
+ "Call Immediates: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_call_imm,
+ ((float)(stats_data_arch->num_call_imm * 100) / num_instructions));
+ stats_print("Call Immediates Excluded: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_call_imm_excluded,
+ ((float)(stats_data_arch->num_call_imm_excluded * 100) /
+ num_instructions));
+ stats_print(
+ "Call Register: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_call_reg,
+ ((float)(stats_data_arch->num_call_reg * 100) / num_instructions));
+ stats_print(
+ "Call Memory: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_call_mem,
+ ((float)(stats_data_arch->num_call_mem * 100) / num_instructions));
+
+ stats_print("\n");
+
+ stats_print("Jump Immediates: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_imm,
+ ((float)(stats_data_arch->num_jmp_imm * 100) / num_instructions));
+ stats_print("Jump Register: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_reg,
+ ((float)(stats_data_arch->num_jmp_reg * 100) / num_instructions));
+ stats_print("Jump Memory: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_mem,
+ ((float)(stats_data_arch->num_jmp_mem * 100) / num_instructions));
+
+ stats_print("\n");
+
+ stats_print(
+ "Conditional Jump Immediates: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_cond_imm,
+ ((float)(stats_data_arch->num_jmp_cond_imm * 100) / num_instructions));
+ stats_print(
+ "Conditional Jump CX Immediate: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_cond_jcxz,
+ ((float)(stats_data_arch->num_jmp_cond_jcxz * 100) / num_instructions));
+ stats_print(
+ "Conditional Jump Register: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_cond_reg,
+ ((float)(stats_data_arch->num_jmp_cond_reg * 100) / num_instructions));
+ stats_print(
+ "Conditional Jump Memory: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_jmp_cond_mem,
+ ((float)(stats_data_arch->num_jmp_cond_mem * 100) / num_instructions));
+
+ stats_print("\n");
+
+ stats_print("Returns: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_ret,
+ (stats_data_arch->num_ret * 100 / num_instructions));
+
+ stats_print("\n");
+
+ stats_print("Rip Relative: %" G_GINT64_MODIFIER
+ "u "
+ "(%3.2f%%)\n",
+ stats_data_arch->num_rip_relative,
+ (stats_data_arch->num_rip_relative * 100 / num_instructions));
+
+ stats_print("\n");
+ stats_print("\n");
+
+}
+
+static x86_op_type stats_get_operand_type(const cs_insn *instr) {
+
+ cs_x86 * x86 = &instr->detail->x86;
+ cs_x86_op *operand;
+
+ if (x86->op_count != 1) {
+
+ FATAL("Unexpected operand count (%d): %s %s\n", x86->op_count,
+ instr->mnemonic, instr->op_str);
+
+ }
+
+ operand = &x86->operands[0];
+
+ return operand->type;
+
+}
+
+static void stats_collect_call_imm_excluded_arch(const cs_insn *instr) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ cs_x86 * x86 = &instr->detail->x86;
+ cs_x86_op * operand = &x86->operands[0];
+
+ if (range_is_excluded((gpointer)operand->imm)) {
+
+ stats_data_arch->num_call_imm_excluded++;
+
+ }
+
+}
+
+static void stats_collect_call_arch(const cs_insn *instr) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ x86_op_type type = stats_get_operand_type(instr);
+ switch (type) {
+
+ case X86_OP_IMM:
+ stats_data_arch->num_call_imm++;
+ stats_collect_call_imm_excluded_arch(instr);
+ break;
+ case X86_OP_REG:
+ stats_data_arch->num_call_reg++;
+ break;
+ case X86_OP_MEM:
+ stats_data_arch->num_call_mem++;
+ break;
+ default:
+ FATAL("Invalid operand type: %s %s\n", instr->mnemonic, instr->op_str);
+
+ }
+
+}
+
+static void stats_collect_jump_arch(const cs_insn *instr) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ x86_op_type type = stats_get_operand_type(instr);
+ switch (type) {
+
+ case X86_OP_IMM:
+ stats_data_arch->num_jmp_imm++;
+ break;
+ case X86_OP_REG:
+ stats_data_arch->num_jmp_reg++;
+ break;
+ case X86_OP_MEM:
+ stats_data_arch->num_jmp_mem++;
+ break;
+ default:
+ FATAL("Invalid operand type: %s %s\n", instr->mnemonic, instr->op_str);
+
+ }
+
+}
+
+static void stats_collect_jump_cond_arch(const cs_insn *instr) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ x86_op_type type = stats_get_operand_type(instr);
+ switch (type) {
+
+ case X86_OP_IMM:
+ stats_data_arch->num_jmp_cond_imm++;
+ break;
+ case X86_OP_REG:
+ stats_data_arch->num_jmp_cond_reg++;
+ break;
+ case X86_OP_MEM:
+ stats_data_arch->num_jmp_cond_mem++;
+ break;
+ default:
+ FATAL("Invalid operand type: %s %s\n", instr->mnemonic, instr->op_str);
+
+ }
+
+}
+
+static void stats_collect_rip_relative_arch(const cs_insn *instr) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ cs_x86 * x86 = &instr->detail->x86;
+ guint mod;
+ guint rm;
+
+ if (x86->encoding.modrm_offset == 0) { return; }
+
+ mod = (x86->modrm & 0xc0) >> 6;
+ if (mod != 0) { return; }
+
+ rm = (x86->modrm & 0x07) >> 0;
+ if (rm != 5) { return; }
+
+ stats_data_arch->num_rip_relative++;
+
+}
+
+void stats_collect_arch(const cs_insn *instr) {
+
+ stats_data_arch_t *stats_data_arch = (stats_data_arch_t *)stats_data;
+ switch (instr->id) {
+
+ case X86_INS_CALL:
+ stats_collect_call_arch(instr);
+ break;
+ case X86_INS_JMP:
+ stats_collect_jump_arch(instr);
+ break;
+ case X86_INS_JA:
+ case X86_INS_JAE:
+ case X86_INS_JB:
+ case X86_INS_JBE:
+ case X86_INS_JE:
+ case X86_INS_JG:
+ case X86_INS_JGE:
+ case X86_INS_JL:
+ case X86_INS_JLE:
+ case X86_INS_JNE:
+ case X86_INS_JNO:
+ case X86_INS_JNP:
+ case X86_INS_JNS:
+ case X86_INS_JO:
+ case X86_INS_JP:
+ case X86_INS_JS:
+ stats_collect_jump_cond_arch(instr);
+ break;
+ case X86_INS_JECXZ:
+ case X86_INS_JRCXZ:
+ stats_data_arch->num_jmp_cond_jcxz++;
+ break;
+ case X86_INS_RET:
+ stats_data_arch->num_ret++;
+ break;
+ default:
+ stats_collect_rip_relative_arch(instr);
+ break;
+
+ }
+
+}
+
+#endif
+
diff --git a/frida_mode/src/stats/stats_x86.c b/frida_mode/src/stats/stats_x86.c
new file mode 100644
index 00000000..1906e809
--- /dev/null
+++ b/frida_mode/src/stats/stats_x86.c
@@ -0,0 +1,36 @@
+#include "frida-gum.h"
+
+#include "debug.h"
+
+#include "stats.h"
+#include "util.h"
+
+#if defined(__i386__)
+
+gboolean stats_is_supported_arch(void) {
+
+ return FALSE;
+
+}
+
+size_t stats_data_size_arch(void) {
+
+ FATAL("Stats not supported on this architecture");
+
+}
+
+void stats_write_arch(void) {
+
+ FATAL("Stats not supported on this architecture");
+
+}
+
+void stats_collect_arch(const cs_insn *instr) {
+
+ UNUSED_PARAMETER(instr);
+ FATAL("Stats not supported on this architecture");
+
+}
+
+#endif
+
diff --git a/frida_mode/src/util.c b/frida_mode/src/util.c
new file mode 100644
index 00000000..09e8a58b
--- /dev/null
+++ b/frida_mode/src/util.c
@@ -0,0 +1,68 @@
+#include "util.h"
+
+#include "debug.h"
+
+guint64 util_read_address(char *key) {
+
+ char *value_str = getenv(key);
+
+ if (value_str == NULL) { return 0; }
+
+ if (!g_str_has_prefix(value_str, "0x")) {
+
+ FATAL("Invalid address should have 0x prefix: %s=%s\n", key, value_str);
+
+ }
+
+ char *value_str2 = &value_str[2];
+
+ for (char *c = value_str2; *c != '\0'; c++) {
+
+ if (!g_ascii_isxdigit(*c)) {
+
+ FATAL("Invalid address not formed of hex digits: %s=%s ('%c')\n", key,
+ value_str, *c);
+
+ }
+
+ }
+
+ guint64 value = g_ascii_strtoull(value_str2, NULL, 16);
+ if (value == 0) {
+
+ FATAL("Invalid address failed hex conversion: %s=%s\n", key, value_str2);
+
+ }
+
+ return value;
+
+}
+
+guint64 util_read_num(char *key) {
+
+ char *value_str = getenv(key);
+
+ if (value_str == NULL) { return 0; }
+
+ for (char *c = value_str; *c != '\0'; c++) {
+
+ if (!g_ascii_isdigit(*c)) {
+
+ FATAL("Invalid address not formed of decimal digits: %s=%s\n", key,
+ value_str);
+
+ }
+
+ }
+
+ guint64 value = g_ascii_strtoull(value_str, NULL, 10);
+ if (value == 0) {
+
+ FATAL("Invalid address failed numeric conversion: %s=%s\n", key, value_str);
+
+ }
+
+ return value;
+
+}
+
diff --git a/frida_mode/test/cmplog/GNUmakefile b/frida_mode/test/cmplog/GNUmakefile
new file mode 100644
index 00000000..40de6a09
--- /dev/null
+++ b/frida_mode/test/cmplog/GNUmakefile
@@ -0,0 +1,69 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../../)/
+BUILD_DIR:=$(PWD)build/
+
+TEST_CMPLOG_SRC=$(PWD)cmplog.c
+TEST_CMPLOG_OBJ=$(BUILD_DIR)compcovtest
+
+TEST_BIN:=$(PWD)../../build/test
+
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+CMP_LOG_INPUT:=$(TEST_DATA_DIR)in
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+.PHONY: all 32 clean qemu frida format
+
+all: $(TEST_CMPLOG_OBJ)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TEST_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(CMP_LOG_INPUT): | $(TEST_DATA_DIR)
+ echo -n "zzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzzz" > $@
+
+$(TEST_CMPLOG_OBJ): $(TEST_CMPLOG_SRC) | $(BUILD_DIR)
+ $(CXX) -std=c++11 -g $(CFLAGS) $(LDFLAGS) $< -o $@
+
+qemu: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
+ $(ROOT)afl-fuzz \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -c 0 \
+ -l 3AT \
+ -Z \
+ -- \
+ $(TEST_CMPLOG_OBJ) @@
+
+frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
+ $(ROOT)afl-fuzz \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -c 0 \
+ -l 3AT \
+ -Z \
+ -- \
+ $(TEST_CMPLOG_OBJ) @@
+
+debug: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --ex 'r $(CMP_LOG_INPUT)' \
+ --args $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT)
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+format:
+ cd $(ROOT) && echo $(TEST_CMPLOG_SRC) | xargs -L1 ./.custom-format.py -i
diff --git a/frida_mode/test/cmplog/Makefile b/frida_mode/test/cmplog/Makefile
new file mode 100644
index 00000000..606b43a5
--- /dev/null
+++ b/frida_mode/test/cmplog/Makefile
@@ -0,0 +1,22 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+frida:
+ @gmake frida
+
+format:
+ @gmake format
+
+debug:
+ @gmake debug
diff --git a/frida_mode/test/cmplog/cmplog.c b/frida_mode/test/cmplog/cmplog.c
new file mode 100644
index 00000000..99010645
--- /dev/null
+++ b/frida_mode/test/cmplog/cmplog.c
@@ -0,0 +1,100 @@
+/////////////////////////////////////////////////////////////////////////
+//
+// Author: Mateusz Jurczyk (mjurczyk@google.com)
+//
+// Copyright 2019-2020 Google LLC
+//
+// 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
+//
+// Unless required by applicable law or agreed to in writing, software
+// distributed under the License is distributed on an "AS IS" BASIS,
+// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+// See the License for the specific language governing permissions and
+// limitations under the License.
+//
+
+// solution: echo -ne 'The quick brown fox jumps over the lazy
+// dog\xbe\xba\xfe\xca\xbe\xba\xfe\xca\xde\xc0\xad\xde\xef\xbe' | ./compcovtest
+
+#include
+#include
+#include
+#include
+
+int main(int argc, char **argv) {
+
+ char buffer[44] = {/* zero padding */};
+
+ FILE *file = stdin;
+
+ if (argc > 1) {
+
+ if ((file = fopen(argv[1], "r")) == NULL) {
+
+ perror(argv[1]);
+ exit(-1);
+
+ }
+
+ }
+
+ fread(buffer, 1, sizeof(buffer) - 1, file);
+
+ if (memcmp(&buffer[0], "The quick brown fox ", 20) != 0 ||
+ strncmp(&buffer[20], "jumps over ", 11) != 0 ||
+ strcmp(&buffer[31], "the lazy dog") != 0) {
+
+ if (argc > 1) { fclose(file); }
+ return 1;
+
+ }
+
+#if defined(__x86_64__)
+ uint64_t x = 0;
+ fread(&x, sizeof(x), 1, file);
+ if (x != 0xCAFEBABECAFEBABE) {
+
+ if (argc > 1) { fclose(file); }
+ return 2;
+
+ }
+
+#endif
+
+ uint32_t y = 0;
+ fread(&y, sizeof(y), 1, file);
+
+ if (y != 0xDEADC0DE) {
+
+ if (argc > 1) { fclose(file); }
+ return 3;
+
+ }
+
+ uint16_t z = 0;
+ fread(&z, sizeof(z), 1, file);
+
+ switch (z) {
+
+ case 0xBEEF:
+ break;
+
+ default:
+ if (argc > 1) { fclose(file); }
+ return 4;
+
+ }
+
+ printf("Puzzle solved, congrats!\n");
+ abort();
+
+ if (argc > 1) { fclose(file); }
+
+ return 0;
+
+}
+
diff --git a/frida_mode/test/cmplog/get_section_addrs.py b/frida_mode/test/cmplog/get_section_addrs.py
new file mode 100755
index 00000000..f648808b
--- /dev/null
+++ b/frida_mode/test/cmplog/get_section_addrs.py
@@ -0,0 +1,49 @@
+#!/usr/bin/env python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+
+def process_file(file, section, base):
+ with open(file, "rb") as f:
+ for sect in ELFFile(f).iter_sections():
+ if sect.name == section:
+ start = base + sect.header["sh_offset"]
+ end = start + sect.header["sh_size"]
+ print("0x%016x-0x%016x" % (start, end))
+ return
+
+ print("Section '%s' not found in '%s'" % (section, file))
+
+
+def hex_value(x):
+ return int(x, 16)
+
+
+def main():
+ parser = argparse.ArgumentParser(description="Process some integers.")
+ parser.add_argument(
+ "-f", "--file", dest="file", type=str, help="elf file name", required=True
+ )
+ parser.add_argument(
+ "-s",
+ "--section",
+ dest="section",
+ type=str,
+ help="elf section name",
+ required=True,
+ )
+ parser.add_argument(
+ "-b",
+ "--base",
+ dest="base",
+ type=hex_value,
+ help="elf base address",
+ required=True,
+ )
+
+ args = parser.parse_args()
+ process_file(args.file, args.section, args.base)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/frida_mode/test/deferred/GNUmakefile b/frida_mode/test/deferred/GNUmakefile
new file mode 100644
index 00000000..c268ef66
--- /dev/null
+++ b/frida_mode/test/deferred/GNUmakefile
@@ -0,0 +1,71 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000)
+endif
+
+.PHONY: all clean qemu frida
+
+all: $(TESTINSTBIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ AFL_ENTRYPOINT=$(AFL_ENTRYPOINT) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
diff --git a/frida_mode/test/deferred/Makefile b/frida_mode/test/deferred/Makefile
new file mode 100644
index 00000000..07b139e9
--- /dev/null
+++ b/frida_mode/test/deferred/Makefile
@@ -0,0 +1,13 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c
new file mode 100644
index 00000000..8b3688d7
--- /dev/null
+++ b/frida_mode/test/deferred/testinstr.c
@@ -0,0 +1,125 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #define TESTINSTR_SECTION
+#else
+ #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+
+}
+
+int run(char *file) {
+
+ int fd = -1;
+ off_t len;
+ char * buf = NULL;
+ size_t n_read;
+ int result = -1;
+
+ do {
+
+ dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+ 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;
+
+ }
+
+ 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);
+
+ testinstr(buf, len);
+ dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
+
+ result = 0;
+
+ } while (false);
+
+ if (buf != NULL) { free(buf); }
+
+ if (fd != -1) { close(fd); }
+
+ return result;
+
+}
+
+void slow() {
+
+ usleep(100000);
+
+}
+
+TESTINSTR_SECTION int do_run(char * file) {
+ return run(file);
+}
+
+int main(int argc, char **argv) {
+
+ if (argc != 2) { return 1; }
+ slow();
+ return do_run(argv[1]);
+
+}
+
diff --git a/frida_mode/test/entry_point/GNUmakefile b/frida_mode/test/entry_point/GNUmakefile
new file mode 100644
index 00000000..c99bcecb
--- /dev/null
+++ b/frida_mode/test/entry_point/GNUmakefile
@@ -0,0 +1,80 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000)
+endif
+
+.PHONY: all clean qemu frida
+
+all: $(TESTINSTBIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
+
+frida_entry: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ AFL_ENTRYPOINT=$(AFL_ENTRYPOINT) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
diff --git a/frida_mode/test/entry_point/Makefile b/frida_mode/test/entry_point/Makefile
new file mode 100644
index 00000000..75c57e66
--- /dev/null
+++ b/frida_mode/test/entry_point/Makefile
@@ -0,0 +1,16 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
+
+frida_entry:
+ @gmake frida
diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c
new file mode 100644
index 00000000..bd605c52
--- /dev/null
+++ b/frida_mode/test/entry_point/testinstr.c
@@ -0,0 +1,121 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #define TESTINSTR_SECTION
+#else
+ #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+
+}
+
+int run(char *file) {
+
+ int fd = -1;
+ off_t len;
+ char * buf = NULL;
+ size_t n_read;
+ int result = -1;
+
+ do {
+
+ dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+ 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;
+
+ }
+
+ 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);
+
+ testinstr(buf, len);
+ dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
+
+ result = 0;
+
+ } while (false);
+
+ if (buf != NULL) { free(buf); }
+
+ if (fd != -1) { close(fd); }
+
+ return result;
+
+}
+
+void slow() {
+
+ usleep(100000);
+
+}
+
+int main(int argc, char **argv) {
+
+ if (argc != 2) { return 1; }
+ slow();
+ return run(argv[1]);
+
+}
+
diff --git a/frida_mode/test/exe/GNUmakefile b/frida_mode/test/exe/GNUmakefile
new file mode 100644
index 00000000..86e5a461
--- /dev/null
+++ b/frida_mode/test/exe/GNUmakefile
@@ -0,0 +1,53 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+.PHONY: all 32 clean qemu frida
+
+all: $(TESTINSTBIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< -no-pie
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+
+qemu: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ $(ROOT)afl-fuzz \
+ -D \
+ -Q \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
diff --git a/frida_mode/test/exe/Makefile b/frida_mode/test/exe/Makefile
new file mode 100644
index 00000000..4bef1ccb
--- /dev/null
+++ b/frida_mode/test/exe/Makefile
@@ -0,0 +1,16 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+frida:
+ @gmake frida
diff --git a/frida_mode/test/exe/testinstr.c b/frida_mode/test/exe/testinstr.c
new file mode 100644
index 00000000..5e26fc46
--- /dev/null
+++ b/frida_mode/test/exe/testinstr.c
@@ -0,0 +1,112 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #define TESTINSTR_SECTION
+#else
+ #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+
+}
+
+TESTINSTR_SECTION int main(int argc, char **argv) {
+
+ char * file;
+ int fd = -1;
+ off_t len;
+ char * buf = NULL;
+ size_t n_read;
+ int result = -1;
+
+ if (argc != 2) { return 1; }
+
+ do {
+
+ file = argv[1];
+
+ dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+ 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;
+
+ }
+
+ 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);
+
+ testinstr(buf, len);
+ dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
+
+ result = 0;
+
+ } while (false);
+
+ if (buf != NULL) { free(buf); }
+
+ if (fd != -1) { close(fd); }
+
+ return result;
+
+}
+
diff --git a/frida_mode/test/fasan/GNUmakefile b/frida_mode/test/fasan/GNUmakefile
new file mode 100644
index 00000000..08b271de
--- /dev/null
+++ b/frida_mode/test/fasan/GNUmakefile
@@ -0,0 +1,159 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_FILE:=$(TEST_DATA_DIR)in
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+TEST_SRC:=$(PWD)/test.c
+TEST_BIN:=$(BUILD_DIR)test
+
+CFLAGS+=-fPIC \
+ -D_GNU_SOURCE \
+ -g \
+ -fno-omit-frame-pointer \
+ -Wno-stringop-overflow \
+
+LDFLAGS+=-ldl \
+
+ifdef DEBUG
+CFLAGS+=-Werror \
+ -Wall \
+ -Wextra \
+ -Wpointer-arith
+else
+CFLAGS+=-Wno-pointer-arith
+endif
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+ifeq "$(ARCH)" "x86"
+LIBASAN_FILE:=libclang_rt.asan-i386.so
+endif
+
+ifeq "$(ARCH)" "x86_64"
+LIBASAN_FILE:=libclang_rt.asan-x86_64.so
+endif
+
+ifeq "$(ARCH)" "aarch64"
+LIBASAN_FILE:=libclang_rt.asan-aarch64.so
+endif
+
+# LIBASAN:=/usr/lib/llvm-10/lib/clang/10.0.0/lib/linux/libclang_rt.asan-x86_64.so
+# LIBASAN:=/usr/lib/x86_64-linux-gnu/libasan.so.6.0.0
+
+LLVM_CONFIG ?= llvm-config
+ifeq "$(shell test -e '$(shell which $(LLVM_CONFIG))' && echo 1)" "1"
+ $(info Found llvm-config: '$(shell which $(LLVM_CONFIG))')
+else
+ $(warning Cannot find llvm-config)
+endif
+
+LLVM_BINDIR = $(shell $(LLVM_CONFIG) --bindir 2>/dev/null)/
+$(info LLVM_BINDIR: $(LLVM_BINDIR))
+
+CLANG ?= $(LLVM_BINDIR)clang
+ifeq "$(shell test -e '$(CLANG)' && echo 1)" "1"
+ $(info Found clang: '$(CLANG)')
+else
+ $(warning Cannot find clang)
+endif
+
+CLANGVER = $(shell $(CLANG) --version | sed -E -ne '/^.*version\ (1?[0-9]\.[0-9]\.[0-9]).*/s//\1/p')
+$(info Clang version $(CLANGVER))
+
+LLVM_LIBDIR = $(shell $(LLVM_CONFIG) --libdir 2>/dev/null)
+$(info LLVM_LIBDIR: $(LLVM_LIBDIR))
+
+LIBASAN:=$(LLVM_LIBDIR)/clang/$(CLANGVER)/lib/linux/$(LIBASAN_FILE)
+
+ifeq "$(shell test -e '$(LIBASAN)' && echo 1)" "1"
+ $(info Found Address Sanitizer DSO: '$(LIBASAN)')
+else
+ $(error Error cannot find Address Sanitizer DSO)
+endif
+
+
+.PHONY: all 32 clean format frida-noasan frida debug run
+
+############################## ALL #############################################
+
+all: $(TEST_BIN)
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(TEST_BIN): $(TEST_SRC) GNUmakefile | $(BUILD_DIR)
+ $(CC) \
+ $(CFLAGS) \
+ $(LDFLAGS) \
+ -o $@ \
+ $<
+
+$(BUILD_DIR):
+ mkdir -p $(BUILD_DIR)
+
+############################# TESTS ############################################
+
+$(TEST_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
+ echo -n "TUODATM" > $@
+
+frida-noasan: $(TEST_BIN) $(TEST_DATA_FILE)
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN)
+
+
+frida: $(TEST_BIN) $(TEST_DATA_FILE)
+ AFL_PRELOAD=$(LIBASAN) \
+ AFL_USE_FASAN=1 \
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN)
+
+debug: $(TEST_BIN) $(TEST_DATA_FILE)
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(LIBASAN):$(ROOT)afl-frida-trace.so' \
+ --ex 'set environment ASAN_OPTIONS=detect_leaks=false,halt_on_error=0' \
+ --ex 'set environment AFL_USE_FASAN=1' \
+ --ex 'set disassembly-flavor intel' \
+ --ex 'r < $(TEST_DATA_FILE)' \
+ --args $(TEST_BIN) \
+
+run: $(TEST_BIN) $(TEST_DATA_FILE)
+ LD_PRELOAD=$(LIBASAN):$(ROOT)afl-frida-trace.so \
+ ASAN_OPTIONS=detect_leaks=false \
+ AFL_USE_FASAN=1 \
+ $(TEST_BIN) < $(TEST_DATA_FILE)
+
+############################# CLEAN ############################################
+clean:
+ rm -rf $(BUILD_DIR)
+
+############################# FORMAT ###########################################
+format:
+ cd $(ROOT) && echo $(TEST_SRC) | xargs -L1 ./.custom-format.py -i
+
+############################# RUN #############################################
diff --git a/frida_mode/test/fasan/Makefile b/frida_mode/test/fasan/Makefile
new file mode 100644
index 00000000..3b4c71db
--- /dev/null
+++ b/frida_mode/test/fasan/Makefile
@@ -0,0 +1,22 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida-noasan:
+ @gmake frida-noasan
+
+frida:
+ @gmake frida
+
+debug:
+ @gmake debug
+
+run:
+ @gmake run
diff --git a/frida_mode/test/fasan/test.c b/frida_mode/test/fasan/test.c
new file mode 100644
index 00000000..b9a119e6
--- /dev/null
+++ b/frida_mode/test/fasan/test.c
@@ -0,0 +1,90 @@
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define UNUSED_PARAMETER(x) (void)(x)
+
+#define LOG(x) \
+ do { \
+ \
+ char buf[] = x; \
+ write(STDOUT_FILENO, buf, sizeof(buf)); \
+ \
+ } while (false);
+
+void test(char data) {
+
+ char *buf = malloc(10);
+
+ if (buf == NULL) return;
+
+ switch (data) {
+
+ /* Underflow */
+ case 'U':
+ LOG("Underflow\n");
+ buf[-1] = '\0';
+ free(buf);
+ break;
+ /* Overflow */
+ case 'O':
+ LOG("Overflow\n");
+ buf[10] = '\0';
+ free(buf);
+ break;
+ /* Double free */
+ case 'D':
+ LOG("Double free\n");
+ free(buf);
+ free(buf);
+ break;
+ /* Use after free */
+ case 'A':
+ LOG("Use after free\n");
+ free(buf);
+ buf[0] = '\0';
+ break;
+ /* Test Limits (OK) */
+ case 'T':
+ LOG("Test-Limits - No Error\n");
+ buf[0] = 'A';
+ buf[9] = 'I';
+ free(buf);
+ break;
+ case 'M':
+ LOG("Memset too many\n");
+ memset(buf, '\0', 11);
+ free(buf);
+ break;
+ default:
+ LOG("Nop - No Error\n");
+ break;
+
+ }
+
+}
+
+int main(int argc, char **argv) {
+
+ UNUSED_PARAMETER(argc);
+ UNUSED_PARAMETER(argv);
+
+ char input = '\0';
+
+ if (read(STDIN_FILENO, &input, 1) < 0) {
+
+ LOG("Failed to read stdin\n");
+ return 1;
+
+ }
+
+ test(input);
+
+ LOG("DONE\n");
+ return 0;
+
+}
+
diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile
new file mode 100644
index 00000000..e30f2049
--- /dev/null
+++ b/frida_mode/test/libpcap/GNUmakefile
@@ -0,0 +1,188 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c
+AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so
+
+LIBPCAP_BUILD_DIR:=$(BUILD_DIR)libpcap/
+HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/
+PCAPTEST_BUILD_DIR:=$(BUILD_DIR)libpcaptest/
+TCPDUMP_BUILD_DIR:=$(BUILD_DIR)tcpdump/
+
+LIBPCAP_PATCH_URL:=https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libpcap_fuzz_both/patch.diff
+LIBPCAP_PATCH_FILE:=$(LIBPCAP_BUILD_DIR)patch.diff
+LIBPCAP_URL:=https://github.com/the-tcpdump-group/libpcap.git
+LIBPCAP_DIR:=$(LIBPCAP_BUILD_DIR)libpcap/
+LIBPCAP_CMAKEFILE:=$(LIBPCAP_DIR)CMakeLists.txt
+LIBPCAP_MAKEFILE:=$(LIBPCAP_DIR)Makefile
+LIBPCAP_LIB:=$(LIBPCAP_DIR)libpcap.a
+
+HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o
+HARNESS_URL:="https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c"
+
+PCAPTEST_SRC_DIR:=$(LIBPCAP_DIR)testprogs/fuzz/
+PCAPTEST_FILE:=$(PCAPTEST_SRC_DIR)fuzz_both.c
+PCAPTEST_OBJ:=$(PCAPTEST_BUILD_DIR)fuzz_both.o
+
+TCPDUMP_URL:=https://github.com/the-tcpdump-group/tcpdump.git
+TCPDUMP_TESTS_DIR:=$(TCPDUMP_BUILD_DIR)tests/
+
+CFLAGS += -fpermissive
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup
+endif
+
+AFLPP_DRIVER_DUMMY_INPUT:=$(TCPDUMP_TESTS_DIR)in
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000)
+
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000)
+endif
+
+.PHONY: all clean qemu frida hook
+
+all: $(TEST_BIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+######### HARNESS ########
+$(HARNESS_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(HARNESS_FILE): | $(HARNESS_BUILD_DIR)
+ wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_FILE)
+ $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ -c $<
+
+######### PCAPTEST ########
+
+$(PCAPTEST_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(PCAPTEST_FILE): | $(LIBPCAP_CMAKEFILE)
+
+$(PCAPTEST_OBJ): $(PCAPTEST_FILE) | $(PCAPTEST_BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -I $(LIBPCAP_DIR) -o $@ -c $<
+
+######### LIBPCAP ########
+
+$(LIBPCAP_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(LIBPCAP_PATCH_FILE): | $(LIBPCAP_BUILD_DIR)
+ wget -O $@ $(LIBPCAP_PATCH_URL)
+
+$(LIBPCAP_CMAKEFILE): $(LIBPCAP_PATCH_FILE) | $(LIBPCAP_BUILD_DIR)
+ git clone --depth 1 $(LIBPCAP_URL) $(LIBPCAP_DIR)
+ git apply $(LIBPCAP_PATCH_FILE)
+
+$(LIBPCAP_MAKEFILE): $(LIBPCAP_CMAKEFILE)
+ cd $(LIBPCAP_DIR) && cmake .
+
+$(LIBPCAP_LIB): $(LIBPCAP_MAKEFILE) $(LIBPCAP_PATCH_FILE)
+ make -C $(LIBPCAP_DIR)
+
+######## TCPDUMP ######
+
+$(TCPDUMP_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TCPDUMP_TESTS_DIR): | $(TCPDUMP_BUILD_DIR)
+ git clone --depth=1 $(TCPDUMP_URL) $(TCPDUMP_BUILD_DIR)
+
+######### TEST ########
+
+$(TEST_BIN): $(HARNESS_OBJ) $(PCAPTEST_OBJ) $(LIBPCAP_LIB)
+ $(CXX) \
+ $(CFLAGS) \
+ -o $@ \
+ $(HARNESS_OBJ) $(PCAPTEST_OBJ) $(LIBPCAP_LIB) \
+ -lz \
+ $(LDFLAGS) \
+ $(TEST_BIN_LDFLAGS) \
+
+########## HOOK ########
+
+$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR)
+ $(CC) -shared $(CFLAGS) $(LDFLAGS) $< -o $@
+
+########## DUMMY #######
+
+$(AFLPP_DRIVER_DUMMY_INPUT): | $(TCPDUMP_TESTS_DIR)
+ truncate -s 1M $@
+
+###### TEST DATA #######
+
+hook: $(AFLPP_DRIVER_HOOK_OBJ)
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+qemu: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) | $(TCPDUMP_TESTS_DIR)
+ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_GPR=1 \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TCPDUMP_TESTS_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+frida: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) | $(TCPDUMP_TESTS_DIR)
+ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TCPDUMP_TESTS_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+debug:
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
diff --git a/frida_mode/test/libpcap/Makefile b/frida_mode/test/libpcap/Makefile
new file mode 100644
index 00000000..31cacb67
--- /dev/null
+++ b/frida_mode/test/libpcap/Makefile
@@ -0,0 +1,1143 @@
+# CMAKE generated file: DO NOT EDIT!
+# Generated by "Unix Makefiles" Generator, CMake Version 3.16
+
+# Default target executed when no arguments are given to make.
+default_target: all
+
+.PHONY : default_target
+
+# Allow only one "make -f Makefile2" at a time, but pass parallelism.
+.NOTPARALLEL:
+
+
+#=============================================================================
+# Special targets provided by cmake.
+
+# Disable implicit rules so canonical targets will work.
+.SUFFIXES:
+
+
+# Remove some rules from gmake that .SUFFIXES does not remove.
+SUFFIXES =
+
+.SUFFIXES: .hpux_make_needs_suffix_list
+
+
+# Suppress display of executed commands.
+$(VERBOSE).SILENT:
+
+
+# A target that is always out of date.
+cmake_force:
+
+.PHONY : cmake_force
+
+#=============================================================================
+# Set environment variables for the build.
+
+# The shell in which to execute make rules.
+SHELL = /bin/sh
+
+# The CMake executable.
+CMAKE_COMMAND = /usr/bin/cmake
+
+# The command to remove a file.
+RM = /usr/bin/cmake -E remove -f
+
+# Escaping for special characters.
+EQUALS = =
+
+# The top-level source directory on which CMake was run.
+CMAKE_SOURCE_DIR = /home/jon/git/AFLplusplus/frida_mode/test/libpcap/build/libpcap/libpcap
+
+# The top-level build directory on which CMake was run.
+CMAKE_BINARY_DIR = /home/jon/git/AFLplusplus/frida_mode/test/libpcap
+
+#=============================================================================
+# Targets provided globally by CMake.
+
+# Special rule for the target install/strip
+install/strip: preinstall
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
+ /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
+.PHONY : install/strip
+
+# Special rule for the target install/strip
+install/strip/fast: preinstall/fast
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing the project stripped..."
+ /usr/bin/cmake -DCMAKE_INSTALL_DO_STRIP=1 -P cmake_install.cmake
+.PHONY : install/strip/fast
+
+# Special rule for the target install/local
+install/local: preinstall
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
+ /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
+.PHONY : install/local
+
+# Special rule for the target install/local
+install/local/fast: preinstall/fast
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Installing only the local directory..."
+ /usr/bin/cmake -DCMAKE_INSTALL_LOCAL_ONLY=1 -P cmake_install.cmake
+.PHONY : install/local/fast
+
+# Special rule for the target install
+install: preinstall
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+ /usr/bin/cmake -P cmake_install.cmake
+.PHONY : install
+
+# Special rule for the target install
+install/fast: preinstall/fast
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Install the project..."
+ /usr/bin/cmake -P cmake_install.cmake
+.PHONY : install/fast
+
+# Special rule for the target list_install_components
+list_install_components:
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Available install components are: \"Unspecified\""
+.PHONY : list_install_components
+
+# Special rule for the target list_install_components
+list_install_components/fast: list_install_components
+
+.PHONY : list_install_components/fast
+
+# Special rule for the target rebuild_cache
+rebuild_cache:
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "Running CMake to regenerate build system..."
+ /usr/bin/cmake -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR)
+.PHONY : rebuild_cache
+
+# Special rule for the target rebuild_cache
+rebuild_cache/fast: rebuild_cache
+
+.PHONY : rebuild_cache/fast
+
+# Special rule for the target edit_cache
+edit_cache:
+ @$(CMAKE_COMMAND) -E cmake_echo_color --switch=$(COLOR) --cyan "No interactive CMake dialog available..."
+ /usr/bin/cmake -E echo No\ interactive\ CMake\ dialog\ available.
+.PHONY : edit_cache
+
+# Special rule for the target edit_cache
+edit_cache/fast: edit_cache
+
+.PHONY : edit_cache/fast
+
+# The main all target
+all: cmake_check_build_system
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/jon/git/AFLplusplus/frida_mode/test/libpcap/CMakeFiles /home/jon/git/AFLplusplus/frida_mode/test/libpcap/CMakeFiles/progress.marks
+ $(MAKE) -f CMakeFiles/Makefile2 all
+ $(CMAKE_COMMAND) -E cmake_progress_start /home/jon/git/AFLplusplus/frida_mode/test/libpcap/CMakeFiles 0
+.PHONY : all
+
+# The main clean target
+clean:
+ $(MAKE) -f CMakeFiles/Makefile2 clean
+.PHONY : clean
+
+# The main clean target
+clean/fast: clean
+
+.PHONY : clean/fast
+
+# Prepare targets for installation.
+preinstall: all
+ $(MAKE) -f CMakeFiles/Makefile2 preinstall
+.PHONY : preinstall
+
+# Prepare targets for installation.
+preinstall/fast:
+ $(MAKE) -f CMakeFiles/Makefile2 preinstall
+.PHONY : preinstall/fast
+
+# clear depends
+depend:
+ $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 1
+.PHONY : depend
+
+#=============================================================================
+# Target rules for targets named pcap
+
+# Build rule for target.
+pcap: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 pcap
+.PHONY : pcap
+
+# fast build rule for target.
+pcap/fast:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/build
+.PHONY : pcap/fast
+
+#=============================================================================
+# Target rules for targets named uninstall
+
+# Build rule for target.
+uninstall: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 uninstall
+.PHONY : uninstall
+
+# fast build rule for target.
+uninstall/fast:
+ $(MAKE) -f CMakeFiles/uninstall.dir/build.make CMakeFiles/uninstall.dir/build
+.PHONY : uninstall/fast
+
+#=============================================================================
+# Target rules for targets named pcap_static
+
+# Build rule for target.
+pcap_static: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 pcap_static
+.PHONY : pcap_static
+
+# fast build rule for target.
+pcap_static/fast:
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/build
+.PHONY : pcap_static/fast
+
+#=============================================================================
+# Target rules for targets named SerializeTarget
+
+# Build rule for target.
+SerializeTarget: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 SerializeTarget
+.PHONY : SerializeTarget
+
+# fast build rule for target.
+SerializeTarget/fast:
+ $(MAKE) -f CMakeFiles/SerializeTarget.dir/build.make CMakeFiles/SerializeTarget.dir/build
+.PHONY : SerializeTarget/fast
+
+#=============================================================================
+# Target rules for targets named testprogs
+
+# Build rule for target.
+testprogs: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 testprogs
+.PHONY : testprogs
+
+# fast build rule for target.
+testprogs/fast:
+ $(MAKE) -f testprogs/CMakeFiles/testprogs.dir/build.make testprogs/CMakeFiles/testprogs.dir/build
+.PHONY : testprogs/fast
+
+#=============================================================================
+# Target rules for targets named capturetest
+
+# Build rule for target.
+capturetest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 capturetest
+.PHONY : capturetest
+
+# fast build rule for target.
+capturetest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/capturetest.dir/build.make testprogs/CMakeFiles/capturetest.dir/build
+.PHONY : capturetest/fast
+
+#=============================================================================
+# Target rules for targets named findalldevstest
+
+# Build rule for target.
+findalldevstest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 findalldevstest
+.PHONY : findalldevstest
+
+# fast build rule for target.
+findalldevstest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/findalldevstest.dir/build.make testprogs/CMakeFiles/findalldevstest.dir/build
+.PHONY : findalldevstest/fast
+
+#=============================================================================
+# Target rules for targets named filtertest
+
+# Build rule for target.
+filtertest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 filtertest
+.PHONY : filtertest
+
+# fast build rule for target.
+filtertest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/filtertest.dir/build.make testprogs/CMakeFiles/filtertest.dir/build
+.PHONY : filtertest/fast
+
+#=============================================================================
+# Target rules for targets named findalldevstest-perf
+
+# Build rule for target.
+findalldevstest-perf: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 findalldevstest-perf
+.PHONY : findalldevstest-perf
+
+# fast build rule for target.
+findalldevstest-perf/fast:
+ $(MAKE) -f testprogs/CMakeFiles/findalldevstest-perf.dir/build.make testprogs/CMakeFiles/findalldevstest-perf.dir/build
+.PHONY : findalldevstest-perf/fast
+
+#=============================================================================
+# Target rules for targets named can_set_rfmon_test
+
+# Build rule for target.
+can_set_rfmon_test: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 can_set_rfmon_test
+.PHONY : can_set_rfmon_test
+
+# fast build rule for target.
+can_set_rfmon_test/fast:
+ $(MAKE) -f testprogs/CMakeFiles/can_set_rfmon_test.dir/build.make testprogs/CMakeFiles/can_set_rfmon_test.dir/build
+.PHONY : can_set_rfmon_test/fast
+
+#=============================================================================
+# Target rules for targets named opentest
+
+# Build rule for target.
+opentest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 opentest
+.PHONY : opentest
+
+# fast build rule for target.
+opentest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/opentest.dir/build.make testprogs/CMakeFiles/opentest.dir/build
+.PHONY : opentest/fast
+
+#=============================================================================
+# Target rules for targets named reactivatetest
+
+# Build rule for target.
+reactivatetest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 reactivatetest
+.PHONY : reactivatetest
+
+# fast build rule for target.
+reactivatetest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/reactivatetest.dir/build.make testprogs/CMakeFiles/reactivatetest.dir/build
+.PHONY : reactivatetest/fast
+
+#=============================================================================
+# Target rules for targets named writecaptest
+
+# Build rule for target.
+writecaptest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 writecaptest
+.PHONY : writecaptest
+
+# fast build rule for target.
+writecaptest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/writecaptest.dir/build.make testprogs/CMakeFiles/writecaptest.dir/build
+.PHONY : writecaptest/fast
+
+#=============================================================================
+# Target rules for targets named selpolltest
+
+# Build rule for target.
+selpolltest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 selpolltest
+.PHONY : selpolltest
+
+# fast build rule for target.
+selpolltest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/selpolltest.dir/build.make testprogs/CMakeFiles/selpolltest.dir/build
+.PHONY : selpolltest/fast
+
+#=============================================================================
+# Target rules for targets named threadsignaltest
+
+# Build rule for target.
+threadsignaltest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 threadsignaltest
+.PHONY : threadsignaltest
+
+# fast build rule for target.
+threadsignaltest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/threadsignaltest.dir/build.make testprogs/CMakeFiles/threadsignaltest.dir/build
+.PHONY : threadsignaltest/fast
+
+#=============================================================================
+# Target rules for targets named valgrindtest
+
+# Build rule for target.
+valgrindtest: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 valgrindtest
+.PHONY : valgrindtest
+
+# fast build rule for target.
+valgrindtest/fast:
+ $(MAKE) -f testprogs/CMakeFiles/valgrindtest.dir/build.make testprogs/CMakeFiles/valgrindtest.dir/build
+.PHONY : valgrindtest/fast
+
+#=============================================================================
+# Target rules for targets named fuzz_both
+
+# Build rule for target.
+fuzz_both: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 fuzz_both
+.PHONY : fuzz_both
+
+# fast build rule for target.
+fuzz_both/fast:
+ $(MAKE) -f testprogs/fuzz/CMakeFiles/fuzz_both.dir/build.make testprogs/fuzz/CMakeFiles/fuzz_both.dir/build
+.PHONY : fuzz_both/fast
+
+#=============================================================================
+# Target rules for targets named fuzz_filter
+
+# Build rule for target.
+fuzz_filter: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 fuzz_filter
+.PHONY : fuzz_filter
+
+# fast build rule for target.
+fuzz_filter/fast:
+ $(MAKE) -f testprogs/fuzz/CMakeFiles/fuzz_filter.dir/build.make testprogs/fuzz/CMakeFiles/fuzz_filter.dir/build
+.PHONY : fuzz_filter/fast
+
+#=============================================================================
+# Target rules for targets named fuzz_pcap
+
+# Build rule for target.
+fuzz_pcap: cmake_check_build_system
+ $(MAKE) -f CMakeFiles/Makefile2 fuzz_pcap
+.PHONY : fuzz_pcap
+
+# fast build rule for target.
+fuzz_pcap/fast:
+ $(MAKE) -f testprogs/fuzz/CMakeFiles/fuzz_pcap.dir/build.make testprogs/fuzz/CMakeFiles/fuzz_pcap.dir/build
+.PHONY : fuzz_pcap/fast
+
+bpf_dump.o: bpf_dump.c.o
+
+.PHONY : bpf_dump.o
+
+# target to build an object file
+bpf_dump.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_dump.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_dump.c.o
+.PHONY : bpf_dump.c.o
+
+bpf_dump.i: bpf_dump.c.i
+
+.PHONY : bpf_dump.i
+
+# target to preprocess a source file
+bpf_dump.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_dump.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_dump.c.i
+.PHONY : bpf_dump.c.i
+
+bpf_dump.s: bpf_dump.c.s
+
+.PHONY : bpf_dump.s
+
+# target to generate assembly for a file
+bpf_dump.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_dump.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_dump.c.s
+.PHONY : bpf_dump.c.s
+
+bpf_filter.o: bpf_filter.c.o
+
+.PHONY : bpf_filter.o
+
+# target to build an object file
+bpf_filter.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_filter.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_filter.c.o
+.PHONY : bpf_filter.c.o
+
+bpf_filter.i: bpf_filter.c.i
+
+.PHONY : bpf_filter.i
+
+# target to preprocess a source file
+bpf_filter.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_filter.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_filter.c.i
+.PHONY : bpf_filter.c.i
+
+bpf_filter.s: bpf_filter.c.s
+
+.PHONY : bpf_filter.s
+
+# target to generate assembly for a file
+bpf_filter.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_filter.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_filter.c.s
+.PHONY : bpf_filter.c.s
+
+bpf_image.o: bpf_image.c.o
+
+.PHONY : bpf_image.o
+
+# target to build an object file
+bpf_image.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_image.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_image.c.o
+.PHONY : bpf_image.c.o
+
+bpf_image.i: bpf_image.c.i
+
+.PHONY : bpf_image.i
+
+# target to preprocess a source file
+bpf_image.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_image.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_image.c.i
+.PHONY : bpf_image.c.i
+
+bpf_image.s: bpf_image.c.s
+
+.PHONY : bpf_image.s
+
+# target to generate assembly for a file
+bpf_image.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/bpf_image.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/bpf_image.c.s
+.PHONY : bpf_image.c.s
+
+etherent.o: etherent.c.o
+
+.PHONY : etherent.o
+
+# target to build an object file
+etherent.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/etherent.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/etherent.c.o
+.PHONY : etherent.c.o
+
+etherent.i: etherent.c.i
+
+.PHONY : etherent.i
+
+# target to preprocess a source file
+etherent.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/etherent.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/etherent.c.i
+.PHONY : etherent.c.i
+
+etherent.s: etherent.c.s
+
+.PHONY : etherent.s
+
+# target to generate assembly for a file
+etherent.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/etherent.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/etherent.c.s
+.PHONY : etherent.c.s
+
+fad-getad.o: fad-getad.c.o
+
+.PHONY : fad-getad.o
+
+# target to build an object file
+fad-getad.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/fad-getad.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/fad-getad.c.o
+.PHONY : fad-getad.c.o
+
+fad-getad.i: fad-getad.c.i
+
+.PHONY : fad-getad.i
+
+# target to preprocess a source file
+fad-getad.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/fad-getad.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/fad-getad.c.i
+.PHONY : fad-getad.c.i
+
+fad-getad.s: fad-getad.c.s
+
+.PHONY : fad-getad.s
+
+# target to generate assembly for a file
+fad-getad.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/fad-getad.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/fad-getad.c.s
+.PHONY : fad-getad.c.s
+
+fmtutils.o: fmtutils.c.o
+
+.PHONY : fmtutils.o
+
+# target to build an object file
+fmtutils.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/fmtutils.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/fmtutils.c.o
+.PHONY : fmtutils.c.o
+
+fmtutils.i: fmtutils.c.i
+
+.PHONY : fmtutils.i
+
+# target to preprocess a source file
+fmtutils.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/fmtutils.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/fmtutils.c.i
+.PHONY : fmtutils.c.i
+
+fmtutils.s: fmtutils.c.s
+
+.PHONY : fmtutils.s
+
+# target to generate assembly for a file
+fmtutils.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/fmtutils.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/fmtutils.c.s
+.PHONY : fmtutils.c.s
+
+gencode.o: gencode.c.o
+
+.PHONY : gencode.o
+
+# target to build an object file
+gencode.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/gencode.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/gencode.c.o
+.PHONY : gencode.c.o
+
+gencode.i: gencode.c.i
+
+.PHONY : gencode.i
+
+# target to preprocess a source file
+gencode.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/gencode.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/gencode.c.i
+.PHONY : gencode.c.i
+
+gencode.s: gencode.c.s
+
+.PHONY : gencode.s
+
+# target to generate assembly for a file
+gencode.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/gencode.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/gencode.c.s
+.PHONY : gencode.c.s
+
+grammar.o: grammar.c.o
+
+.PHONY : grammar.o
+
+# target to build an object file
+grammar.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/grammar.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/grammar.c.o
+.PHONY : grammar.c.o
+
+grammar.i: grammar.c.i
+
+.PHONY : grammar.i
+
+# target to preprocess a source file
+grammar.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/grammar.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/grammar.c.i
+.PHONY : grammar.c.i
+
+grammar.s: grammar.c.s
+
+.PHONY : grammar.s
+
+# target to generate assembly for a file
+grammar.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/grammar.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/grammar.c.s
+.PHONY : grammar.c.s
+
+missing/strlcat.o: missing/strlcat.c.o
+
+.PHONY : missing/strlcat.o
+
+# target to build an object file
+missing/strlcat.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/missing/strlcat.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/missing/strlcat.c.o
+.PHONY : missing/strlcat.c.o
+
+missing/strlcat.i: missing/strlcat.c.i
+
+.PHONY : missing/strlcat.i
+
+# target to preprocess a source file
+missing/strlcat.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/missing/strlcat.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/missing/strlcat.c.i
+.PHONY : missing/strlcat.c.i
+
+missing/strlcat.s: missing/strlcat.c.s
+
+.PHONY : missing/strlcat.s
+
+# target to generate assembly for a file
+missing/strlcat.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/missing/strlcat.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/missing/strlcat.c.s
+.PHONY : missing/strlcat.c.s
+
+missing/strlcpy.o: missing/strlcpy.c.o
+
+.PHONY : missing/strlcpy.o
+
+# target to build an object file
+missing/strlcpy.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/missing/strlcpy.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/missing/strlcpy.c.o
+.PHONY : missing/strlcpy.c.o
+
+missing/strlcpy.i: missing/strlcpy.c.i
+
+.PHONY : missing/strlcpy.i
+
+# target to preprocess a source file
+missing/strlcpy.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/missing/strlcpy.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/missing/strlcpy.c.i
+.PHONY : missing/strlcpy.c.i
+
+missing/strlcpy.s: missing/strlcpy.c.s
+
+.PHONY : missing/strlcpy.s
+
+# target to generate assembly for a file
+missing/strlcpy.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/missing/strlcpy.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/missing/strlcpy.c.s
+.PHONY : missing/strlcpy.c.s
+
+nametoaddr.o: nametoaddr.c.o
+
+.PHONY : nametoaddr.o
+
+# target to build an object file
+nametoaddr.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/nametoaddr.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/nametoaddr.c.o
+.PHONY : nametoaddr.c.o
+
+nametoaddr.i: nametoaddr.c.i
+
+.PHONY : nametoaddr.i
+
+# target to preprocess a source file
+nametoaddr.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/nametoaddr.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/nametoaddr.c.i
+.PHONY : nametoaddr.c.i
+
+nametoaddr.s: nametoaddr.c.s
+
+.PHONY : nametoaddr.s
+
+# target to generate assembly for a file
+nametoaddr.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/nametoaddr.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/nametoaddr.c.s
+.PHONY : nametoaddr.c.s
+
+optimize.o: optimize.c.o
+
+.PHONY : optimize.o
+
+# target to build an object file
+optimize.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/optimize.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/optimize.c.o
+.PHONY : optimize.c.o
+
+optimize.i: optimize.c.i
+
+.PHONY : optimize.i
+
+# target to preprocess a source file
+optimize.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/optimize.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/optimize.c.i
+.PHONY : optimize.c.i
+
+optimize.s: optimize.c.s
+
+.PHONY : optimize.s
+
+# target to generate assembly for a file
+optimize.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/optimize.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/optimize.c.s
+.PHONY : optimize.c.s
+
+pcap-common.o: pcap-common.c.o
+
+.PHONY : pcap-common.o
+
+# target to build an object file
+pcap-common.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-common.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-common.c.o
+.PHONY : pcap-common.c.o
+
+pcap-common.i: pcap-common.c.i
+
+.PHONY : pcap-common.i
+
+# target to preprocess a source file
+pcap-common.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-common.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-common.c.i
+.PHONY : pcap-common.c.i
+
+pcap-common.s: pcap-common.c.s
+
+.PHONY : pcap-common.s
+
+# target to generate assembly for a file
+pcap-common.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-common.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-common.c.s
+.PHONY : pcap-common.c.s
+
+pcap-linux.o: pcap-linux.c.o
+
+.PHONY : pcap-linux.o
+
+# target to build an object file
+pcap-linux.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-linux.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-linux.c.o
+.PHONY : pcap-linux.c.o
+
+pcap-linux.i: pcap-linux.c.i
+
+.PHONY : pcap-linux.i
+
+# target to preprocess a source file
+pcap-linux.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-linux.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-linux.c.i
+.PHONY : pcap-linux.c.i
+
+pcap-linux.s: pcap-linux.c.s
+
+.PHONY : pcap-linux.s
+
+# target to generate assembly for a file
+pcap-linux.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-linux.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-linux.c.s
+.PHONY : pcap-linux.c.s
+
+pcap-netfilter-linux.o: pcap-netfilter-linux.c.o
+
+.PHONY : pcap-netfilter-linux.o
+
+# target to build an object file
+pcap-netfilter-linux.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-netfilter-linux.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-netfilter-linux.c.o
+.PHONY : pcap-netfilter-linux.c.o
+
+pcap-netfilter-linux.i: pcap-netfilter-linux.c.i
+
+.PHONY : pcap-netfilter-linux.i
+
+# target to preprocess a source file
+pcap-netfilter-linux.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-netfilter-linux.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-netfilter-linux.c.i
+.PHONY : pcap-netfilter-linux.c.i
+
+pcap-netfilter-linux.s: pcap-netfilter-linux.c.s
+
+.PHONY : pcap-netfilter-linux.s
+
+# target to generate assembly for a file
+pcap-netfilter-linux.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-netfilter-linux.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-netfilter-linux.c.s
+.PHONY : pcap-netfilter-linux.c.s
+
+pcap-usb-linux.o: pcap-usb-linux.c.o
+
+.PHONY : pcap-usb-linux.o
+
+# target to build an object file
+pcap-usb-linux.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-usb-linux.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-usb-linux.c.o
+.PHONY : pcap-usb-linux.c.o
+
+pcap-usb-linux.i: pcap-usb-linux.c.i
+
+.PHONY : pcap-usb-linux.i
+
+# target to preprocess a source file
+pcap-usb-linux.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-usb-linux.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-usb-linux.c.i
+.PHONY : pcap-usb-linux.c.i
+
+pcap-usb-linux.s: pcap-usb-linux.c.s
+
+.PHONY : pcap-usb-linux.s
+
+# target to generate assembly for a file
+pcap-usb-linux.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap-usb-linux.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap-usb-linux.c.s
+.PHONY : pcap-usb-linux.c.s
+
+pcap.o: pcap.c.o
+
+.PHONY : pcap.o
+
+# target to build an object file
+pcap.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap.c.o
+.PHONY : pcap.c.o
+
+pcap.i: pcap.c.i
+
+.PHONY : pcap.i
+
+# target to preprocess a source file
+pcap.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap.c.i
+.PHONY : pcap.c.i
+
+pcap.s: pcap.c.s
+
+.PHONY : pcap.s
+
+# target to generate assembly for a file
+pcap.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/pcap.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/pcap.c.s
+.PHONY : pcap.c.s
+
+savefile.o: savefile.c.o
+
+.PHONY : savefile.o
+
+# target to build an object file
+savefile.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/savefile.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/savefile.c.o
+.PHONY : savefile.c.o
+
+savefile.i: savefile.c.i
+
+.PHONY : savefile.i
+
+# target to preprocess a source file
+savefile.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/savefile.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/savefile.c.i
+.PHONY : savefile.c.i
+
+savefile.s: savefile.c.s
+
+.PHONY : savefile.s
+
+# target to generate assembly for a file
+savefile.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/savefile.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/savefile.c.s
+.PHONY : savefile.c.s
+
+scanner.o: scanner.c.o
+
+.PHONY : scanner.o
+
+# target to build an object file
+scanner.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/scanner.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/scanner.c.o
+.PHONY : scanner.c.o
+
+scanner.i: scanner.c.i
+
+.PHONY : scanner.i
+
+# target to preprocess a source file
+scanner.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/scanner.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/scanner.c.i
+.PHONY : scanner.c.i
+
+scanner.s: scanner.c.s
+
+.PHONY : scanner.s
+
+# target to generate assembly for a file
+scanner.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/scanner.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/scanner.c.s
+.PHONY : scanner.c.s
+
+sf-pcap.o: sf-pcap.c.o
+
+.PHONY : sf-pcap.o
+
+# target to build an object file
+sf-pcap.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/sf-pcap.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/sf-pcap.c.o
+.PHONY : sf-pcap.c.o
+
+sf-pcap.i: sf-pcap.c.i
+
+.PHONY : sf-pcap.i
+
+# target to preprocess a source file
+sf-pcap.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/sf-pcap.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/sf-pcap.c.i
+.PHONY : sf-pcap.c.i
+
+sf-pcap.s: sf-pcap.c.s
+
+.PHONY : sf-pcap.s
+
+# target to generate assembly for a file
+sf-pcap.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/sf-pcap.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/sf-pcap.c.s
+.PHONY : sf-pcap.c.s
+
+sf-pcapng.o: sf-pcapng.c.o
+
+.PHONY : sf-pcapng.o
+
+# target to build an object file
+sf-pcapng.c.o:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/sf-pcapng.c.o
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/sf-pcapng.c.o
+.PHONY : sf-pcapng.c.o
+
+sf-pcapng.i: sf-pcapng.c.i
+
+.PHONY : sf-pcapng.i
+
+# target to preprocess a source file
+sf-pcapng.c.i:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/sf-pcapng.c.i
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/sf-pcapng.c.i
+.PHONY : sf-pcapng.c.i
+
+sf-pcapng.s: sf-pcapng.c.s
+
+.PHONY : sf-pcapng.s
+
+# target to generate assembly for a file
+sf-pcapng.c.s:
+ $(MAKE) -f CMakeFiles/pcap.dir/build.make CMakeFiles/pcap.dir/sf-pcapng.c.s
+ $(MAKE) -f CMakeFiles/pcap_static.dir/build.make CMakeFiles/pcap_static.dir/sf-pcapng.c.s
+.PHONY : sf-pcapng.c.s
+
+# Help Target
+help:
+ @echo "The following are some of the valid targets for this Makefile:"
+ @echo "... all (the default if no target is provided)"
+ @echo "... clean"
+ @echo "... depend"
+ @echo "... install/strip"
+ @echo "... install/local"
+ @echo "... install"
+ @echo "... list_install_components"
+ @echo "... rebuild_cache"
+ @echo "... edit_cache"
+ @echo "... pcap"
+ @echo "... uninstall"
+ @echo "... pcap_static"
+ @echo "... SerializeTarget"
+ @echo "... testprogs"
+ @echo "... capturetest"
+ @echo "... findalldevstest"
+ @echo "... filtertest"
+ @echo "... findalldevstest-perf"
+ @echo "... can_set_rfmon_test"
+ @echo "... opentest"
+ @echo "... reactivatetest"
+ @echo "... writecaptest"
+ @echo "... selpolltest"
+ @echo "... threadsignaltest"
+ @echo "... valgrindtest"
+ @echo "... fuzz_both"
+ @echo "... fuzz_filter"
+ @echo "... fuzz_pcap"
+ @echo "... bpf_dump.o"
+ @echo "... bpf_dump.i"
+ @echo "... bpf_dump.s"
+ @echo "... bpf_filter.o"
+ @echo "... bpf_filter.i"
+ @echo "... bpf_filter.s"
+ @echo "... bpf_image.o"
+ @echo "... bpf_image.i"
+ @echo "... bpf_image.s"
+ @echo "... etherent.o"
+ @echo "... etherent.i"
+ @echo "... etherent.s"
+ @echo "... fad-getad.o"
+ @echo "... fad-getad.i"
+ @echo "... fad-getad.s"
+ @echo "... fmtutils.o"
+ @echo "... fmtutils.i"
+ @echo "... fmtutils.s"
+ @echo "... gencode.o"
+ @echo "... gencode.i"
+ @echo "... gencode.s"
+ @echo "... grammar.o"
+ @echo "... grammar.i"
+ @echo "... grammar.s"
+ @echo "... missing/strlcat.o"
+ @echo "... missing/strlcat.i"
+ @echo "... missing/strlcat.s"
+ @echo "... missing/strlcpy.o"
+ @echo "... missing/strlcpy.i"
+ @echo "... missing/strlcpy.s"
+ @echo "... nametoaddr.o"
+ @echo "... nametoaddr.i"
+ @echo "... nametoaddr.s"
+ @echo "... optimize.o"
+ @echo "... optimize.i"
+ @echo "... optimize.s"
+ @echo "... pcap-common.o"
+ @echo "... pcap-common.i"
+ @echo "... pcap-common.s"
+ @echo "... pcap-linux.o"
+ @echo "... pcap-linux.i"
+ @echo "... pcap-linux.s"
+ @echo "... pcap-netfilter-linux.o"
+ @echo "... pcap-netfilter-linux.i"
+ @echo "... pcap-netfilter-linux.s"
+ @echo "... pcap-usb-linux.o"
+ @echo "... pcap-usb-linux.i"
+ @echo "... pcap-usb-linux.s"
+ @echo "... pcap.o"
+ @echo "... pcap.i"
+ @echo "... pcap.s"
+ @echo "... savefile.o"
+ @echo "... savefile.i"
+ @echo "... savefile.s"
+ @echo "... scanner.o"
+ @echo "... scanner.i"
+ @echo "... scanner.s"
+ @echo "... sf-pcap.o"
+ @echo "... sf-pcap.i"
+ @echo "... sf-pcap.s"
+ @echo "... sf-pcapng.o"
+ @echo "... sf-pcapng.i"
+ @echo "... sf-pcapng.s"
+.PHONY : help
+
+
+
+#=============================================================================
+# Special targets to cleanup operation of make.
+
+# Special rule to run CMake to check the build system integrity.
+# No rule that depends on this can have commands that come from listfiles
+# because they might be regenerated.
+cmake_check_build_system:
+ $(CMAKE_COMMAND) -S$(CMAKE_SOURCE_DIR) -B$(CMAKE_BINARY_DIR) --check-build-system CMakeFiles/Makefile.cmake 0
+.PHONY : cmake_check_build_system
+
diff --git a/frida_mode/test/libpcap/aflpp_qemu_driver_hook.c b/frida_mode/test/libpcap/aflpp_qemu_driver_hook.c
new file mode 100644
index 00000000..059d438d
--- /dev/null
+++ b/frida_mode/test/libpcap/aflpp_qemu_driver_hook.c
@@ -0,0 +1,97 @@
+#include
+#include
+
+#if defined(__x86_64__)
+
+struct x86_64_regs {
+
+ uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14,
+ r15;
+
+ union {
+
+ uint64_t rip;
+ uint64_t pc;
+
+ };
+
+ union {
+
+ uint64_t rsp;
+ uint64_t sp;
+
+ };
+
+ union {
+
+ uint64_t rflags;
+ uint64_t flags;
+
+ };
+
+ uint8_t zmm_regs[32][64];
+
+};
+
+void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
+ memcpy((void *)regs->rdi, input_buf, input_buf_len);
+ regs->rsi = input_buf_len;
+
+}
+
+#elif defined(__i386__)
+
+struct x86_regs {
+
+ uint32_t eax, ebx, ecx, edx, edi, esi, ebp;
+
+ union {
+
+ uint32_t eip;
+ uint32_t pc;
+
+ };
+
+ union {
+
+ uint32_t esp;
+ uint32_t sp;
+
+ };
+
+ union {
+
+ uint32_t eflags;
+ uint32_t flags;
+
+ };
+
+ uint8_t xmm_regs[8][16];
+
+};
+
+void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
+ void **esp = (void **)regs->esp;
+ void * arg1 = esp[1];
+ void **arg2 = &esp[2];
+ memcpy(arg1, input_buf, input_buf_len);
+ *arg2 = (void *)input_buf_len;
+
+}
+
+#else
+ #pragma error "Unsupported architecture"
+#endif
+
+int afl_persistent_hook_init(void) {
+
+ // 1 for shared memory input (faster), 0 for normal input (you have to use
+ // read(), input_buf will be NULL)
+ return 1;
+
+}
+
diff --git a/frida_mode/test/libpcap/get_symbol_addr.py b/frida_mode/test/libpcap/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/libpcap/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+ with open(file, 'rb') as f:
+ elf = ELFFile(f)
+ symtab = elf.get_section_by_name('.symtab')
+ mains = symtab.get_symbol_by_name(symbol)
+ if len(mains) != 1:
+ print ("Failed to find main")
+ return 1
+
+ main_addr = mains[0]['st_value']
+ main = base + main_addr
+ print ("0x%016x" % main)
+ return 0
+
+def hex_value(x):
+ return int(x, 16)
+
+def main():
+ parser = argparse.ArgumentParser(description='Process some integers.')
+ parser.add_argument('-f', '--file', dest='file', type=str,
+ help='elf file name', required=True)
+ parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+ help='symbol name', required=True)
+ parser.add_argument('-b', '--base', dest='base', type=hex_value,
+ help='elf base address', required=True)
+
+ args = parser.parse_args()
+ return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+ ret = main()
+ exit(ret)
diff --git a/frida_mode/test/output/GNUmakefile b/frida_mode/test/output/GNUmakefile
new file mode 100644
index 00000000..eaa1c4dc
--- /dev/null
+++ b/frida_mode/test/output/GNUmakefile
@@ -0,0 +1,47 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+.PHONY: all 32 clean qemu frida
+
+all: $(TESTINSTBIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ AFL_FRIDA_OUTPUT_STDOUT=frida_stdout.txt \
+ AFL_FRIDA_OUTPUT_STDERR=frida_stderr.txt \
+ AFL_FRIDA_STATS_FILE=frida_stats.txt \
+ AFL_FRIDA_STATS_INTERVAL=1 \
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
diff --git a/frida_mode/test/output/Makefile b/frida_mode/test/output/Makefile
new file mode 100644
index 00000000..07b139e9
--- /dev/null
+++ b/frida_mode/test/output/Makefile
@@ -0,0 +1,13 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
diff --git a/frida_mode/test/output/frida_stderr.txt b/frida_mode/test/output/frida_stderr.txt
new file mode 100644
index 00000000..103216cf
--- /dev/null
+++ b/frida_mode/test/output/frida_stderr.txt
@@ -0,0 +1,2824 @@
+
+
+total_transitions: 9
+ call_imms: 1
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 1
+ jmp_mems: 2
+ jmp_regs: 0
+
+ jmp_cond_imms: 2
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 19
+ call_imms: 4
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 2
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 1
+ jmp_mems: 3
+ jmp_regs: 0
+
+ jmp_cond_imms: 6
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 29
+ call_imms: 6
+ call_regs: 1
+ call_mems: 0
+ post_call_invokes: 3
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 2
+ jmp_mems: 3
+ jmp_regs: 0
+
+ jmp_cond_imms: 11
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 39
+ call_imms: 6
+ call_regs: 2
+ call_mems: 0
+ post_call_invokes: 5
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 2
+ jmp_mems: 3
+ jmp_regs: 0
+
+ jmp_cond_imms: 18
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 49
+ call_imms: 7
+ call_regs: 2
+ call_mems: 1
+ post_call_invokes: 6
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 2
+ jmp_mems: 3
+ jmp_regs: 0
+
+ jmp_cond_imms: 25
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 59
+ call_imms: 8
+ call_regs: 2
+ call_mems: 3
+ post_call_invokes: 6
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 3
+ jmp_mems: 3
+ jmp_regs: 0
+
+ jmp_cond_imms: 31
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 69
+ call_imms: 9
+ call_regs: 2
+ call_mems: 3
+ post_call_invokes: 7
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 3
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 38
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 79
+ call_imms: 10
+ call_regs: 2
+ call_mems: 3
+ post_call_invokes: 7
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 4
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 46
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 89
+ call_imms: 10
+ call_regs: 2
+ call_mems: 3
+ post_call_invokes: 7
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 4
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 56
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 99
+ call_imms: 11
+ call_regs: 2
+ call_mems: 3
+ post_call_invokes: 9
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 4
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 63
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 109
+ call_imms: 12
+ call_regs: 2
+ call_mems: 3
+ post_call_invokes: 12
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 5
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 68
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 119
+ call_imms: 12
+ call_regs: 2
+ call_mems: 4
+ post_call_invokes: 14
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 6
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 74
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 129
+ call_imms: 14
+ call_regs: 2
+ call_mems: 4
+ post_call_invokes: 16
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 6
+ jmp_mems: 4
+ jmp_regs: 0
+
+ jmp_cond_imms: 80
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 139
+ call_imms: 14
+ call_regs: 2
+ call_mems: 5
+ post_call_invokes: 17
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 6
+ jmp_mems: 5
+ jmp_regs: 0
+
+ jmp_cond_imms: 87
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 149
+ call_imms: 14
+ call_regs: 2
+ call_mems: 6
+ post_call_invokes: 17
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 6
+ jmp_mems: 5
+ jmp_regs: 0
+
+ jmp_cond_imms: 96
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 159
+ call_imms: 15
+ call_regs: 2
+ call_mems: 6
+ post_call_invokes: 18
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 8
+ jmp_mems: 5
+ jmp_regs: 0
+
+ jmp_cond_imms: 102
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 170
+ call_imms: 15
+ call_regs: 2
+ call_mems: 6
+ post_call_invokes: 18
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 10
+ jmp_mems: 5
+ jmp_regs: 0
+
+ jmp_cond_imms: 111
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 180
+ call_imms: 15
+ call_regs: 2
+ call_mems: 6
+ post_call_invokes: 20
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 11
+ jmp_mems: 5
+ jmp_regs: 0
+
+ jmp_cond_imms: 118
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 190
+ call_imms: 16
+ call_regs: 2
+ call_mems: 6
+ post_call_invokes: 20
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 11
+ jmp_mems: 6
+ jmp_regs: 1
+
+ jmp_cond_imms: 125
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 201
+ call_imms: 16
+ call_regs: 2
+ call_mems: 7
+ post_call_invokes: 21
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 13
+ jmp_mems: 6
+ jmp_regs: 1
+
+ jmp_cond_imms: 132
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 211
+ call_imms: 17
+ call_regs: 2
+ call_mems: 7
+ post_call_invokes: 22
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 14
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 138
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 223
+ call_imms: 18
+ call_regs: 2
+ call_mems: 8
+ post_call_invokes: 24
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 15
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 145
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 233
+ call_imms: 18
+ call_regs: 2
+ call_mems: 8
+ post_call_invokes: 25
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 16
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 153
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 244
+ call_imms: 19
+ call_regs: 2
+ call_mems: 9
+ post_call_invokes: 26
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 16
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 161
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+
+
+total_transitions: 254
+ call_imms: 20
+ call_regs: 2
+ call_mems: 9
+ post_call_invokes: 27
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 18
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 167
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 264
+ call_imms: 20
+ call_regs: 2
+ call_mems: 9
+ post_call_invokes: 29
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 20
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 173
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 275
+ call_imms: 21
+ call_regs: 2
+ call_mems: 10
+ post_call_invokes: 30
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 22
+ jmp_mems: 7
+ jmp_regs: 1
+
+ jmp_cond_imms: 179
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 285
+ call_imms: 22
+ call_regs: 2
+ call_mems: 10
+ post_call_invokes: 30
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 23
+ jmp_mems: 8
+ jmp_regs: 1
+
+ jmp_cond_imms: 186
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 295
+ call_imms: 22
+ call_regs: 2
+ call_mems: 10
+ post_call_invokes: 30
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 23
+ jmp_mems: 8
+ jmp_regs: 1
+
+ jmp_cond_imms: 196
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 305
+ call_imms: 22
+ call_regs: 2
+ call_mems: 10
+ post_call_invokes: 30
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 24
+ jmp_mems: 8
+ jmp_regs: 1
+
+ jmp_cond_imms: 205
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 315
+ call_imms: 22
+ call_regs: 2
+ call_mems: 10
+ post_call_invokes: 31
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 26
+ jmp_mems: 8
+ jmp_regs: 1
+
+ jmp_cond_imms: 212
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 326
+ call_imms: 22
+ call_regs: 3
+ call_mems: 10
+ post_call_invokes: 32
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 27
+ jmp_mems: 8
+ jmp_regs: 1
+
+ jmp_cond_imms: 220
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 337
+ call_imms: 23
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 36
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 27
+ jmp_mems: 9
+ jmp_regs: 1
+
+ jmp_cond_imms: 224
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 348
+ call_imms: 24
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 38
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 27
+ jmp_mems: 10
+ jmp_regs: 1
+
+ jmp_cond_imms: 231
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 362
+ call_imms: 26
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 39
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 28
+ jmp_mems: 11
+ jmp_regs: 1
+
+ jmp_cond_imms: 240
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 375
+ call_imms: 27
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 40
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 28
+ jmp_mems: 12
+ jmp_regs: 1
+
+ jmp_cond_imms: 250
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 387
+ call_imms: 28
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 41
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 28
+ jmp_mems: 12
+ jmp_regs: 3
+
+ jmp_cond_imms: 258
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 397
+ call_imms: 29
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 42
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 30
+ jmp_mems: 12
+ jmp_regs: 3
+
+ jmp_cond_imms: 264
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 407
+ call_imms: 29
+ call_regs: 4
+ call_mems: 10
+ post_call_invokes: 42
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 31
+ jmp_mems: 12
+ jmp_regs: 3
+
+ jmp_cond_imms: 273
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 418
+ call_imms: 29
+ call_regs: 4
+ call_mems: 11
+ post_call_invokes: 43
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 32
+ jmp_mems: 12
+ jmp_regs: 3
+
+ jmp_cond_imms: 281
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+
+
+total_transitions: 430
+ call_imms: 32
+ call_regs: 4
+ call_mems: 11
+ post_call_invokes: 45
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 33
+ jmp_mems: 13
+ jmp_regs: 3
+
+ jmp_cond_imms: 286
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 441
+ call_imms: 32
+ call_regs: 4
+ call_mems: 12
+ post_call_invokes: 46
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 33
+ jmp_mems: 13
+ jmp_regs: 3
+
+ jmp_cond_imms: 295
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+
+
+total_transitions: 453
+ call_imms: 33
+ call_regs: 4
+ call_mems: 12
+ post_call_invokes: 49
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 34
+ jmp_mems: 13
+ jmp_regs: 3
+
+ jmp_cond_imms: 302
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 465
+ call_imms: 35
+ call_regs: 4
+ call_mems: 12
+ post_call_invokes: 50
+ excluded_call_imms: 2
+ ret_slow_paths: 1
+
+ jmp_imms: 35
+ jmp_mems: 15
+ jmp_regs: 3
+
+ jmp_cond_imms: 308
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 475
+ call_imms: 38
+ call_regs: 4
+ call_mems: 12
+ post_call_invokes: 51
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 35
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 310
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 485
+ call_imms: 38
+ call_regs: 5
+ call_mems: 12
+ post_call_invokes: 52
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 36
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 317
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 495
+ call_imms: 38
+ call_regs: 5
+ call_mems: 13
+ post_call_invokes: 52
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 38
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 324
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 506
+ call_imms: 38
+ call_regs: 5
+ call_mems: 13
+ post_call_invokes: 53
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 39
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 333
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 516
+ call_imms: 40
+ call_regs: 5
+ call_mems: 13
+ post_call_invokes: 53
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 40
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 340
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 526
+ call_imms: 40
+ call_regs: 5
+ call_mems: 13
+ post_call_invokes: 54
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 40
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 349
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 540
+ call_imms: 42
+ call_regs: 5
+ call_mems: 13
+ post_call_invokes: 55
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 42
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 358
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 552
+ call_imms: 43
+ call_regs: 5
+ call_mems: 13
+ post_call_invokes: 57
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 43
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 366
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 563
+ call_imms: 43
+ call_regs: 5
+ call_mems: 14
+ post_call_invokes: 58
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 43
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 375
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 573
+ call_imms: 43
+ call_regs: 5
+ call_mems: 15
+ post_call_invokes: 59
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 44
+ jmp_mems: 16
+ jmp_regs: 3
+
+ jmp_cond_imms: 382
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 583
+ call_imms: 44
+ call_regs: 5
+ call_mems: 15
+ post_call_invokes: 59
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 45
+ jmp_mems: 17
+ jmp_regs: 3
+
+ jmp_cond_imms: 389
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 593
+ call_imms: 45
+ call_regs: 5
+ call_mems: 15
+ post_call_invokes: 60
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 46
+ jmp_mems: 17
+ jmp_regs: 3
+
+ jmp_cond_imms: 396
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 603
+ call_imms: 46
+ call_regs: 6
+ call_mems: 15
+ post_call_invokes: 64
+ excluded_call_imms: 3
+ ret_slow_paths: 3
+
+ jmp_imms: 46
+ jmp_mems: 17
+ jmp_regs: 3
+
+ jmp_cond_imms: 400
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 615
+ call_imms: 46
+ call_regs: 7
+ call_mems: 17
+ post_call_invokes: 64
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 46
+ jmp_mems: 17
+ jmp_regs: 3
+
+ jmp_cond_imms: 407
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 626
+ call_imms: 48
+ call_regs: 8
+ call_mems: 18
+ post_call_invokes: 66
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 46
+ jmp_mems: 18
+ jmp_regs: 3
+
+ jmp_cond_imms: 411
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 637
+ call_imms: 50
+ call_regs: 9
+ call_mems: 19
+ post_call_invokes: 68
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 47
+ jmp_mems: 19
+ jmp_regs: 3
+
+ jmp_cond_imms: 414
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 648
+ call_imms: 52
+ call_regs: 9
+ call_mems: 20
+ post_call_invokes: 70
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 47
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 419
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 660
+ call_imms: 52
+ call_regs: 10
+ call_mems: 20
+ post_call_invokes: 72
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 49
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 426
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 672
+ call_imms: 52
+ call_regs: 10
+ call_mems: 20
+ post_call_invokes: 72
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 51
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 436
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 683
+ call_imms: 53
+ call_regs: 11
+ call_mems: 21
+ post_call_invokes: 73
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 52
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 442
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 697
+ call_imms: 53
+ call_regs: 11
+ call_mems: 22
+ post_call_invokes: 74
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 53
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 453
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 709
+ call_imms: 53
+ call_regs: 13
+ call_mems: 22
+ post_call_invokes: 77
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 53
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 460
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 720
+ call_imms: 53
+ call_regs: 13
+ call_mems: 22
+ post_call_invokes: 77
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 55
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 469
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 730
+ call_imms: 54
+ call_regs: 13
+ call_mems: 24
+ post_call_invokes: 77
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 56
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 475
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 740
+ call_imms: 54
+ call_regs: 13
+ call_mems: 24
+ post_call_invokes: 80
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 57
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 481
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 753
+ call_imms: 54
+ call_regs: 14
+ call_mems: 24
+ post_call_invokes: 81
+ excluded_call_imms: 5
+ ret_slow_paths: 3
+
+ jmp_imms: 58
+ jmp_mems: 20
+ jmp_regs: 3
+
+ jmp_cond_imms: 491
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+
+
+total_transitions: 3
+ call_imms: 0
+ call_regs: 0
+ call_mems: 0
+ post_call_invokes: 0
+ excluded_call_imms: 0
+ ret_slow_paths: 0
+
+ jmp_imms: 1
+ jmp_mems: 1
+ jmp_regs: 0
+
+ jmp_cond_imms: 1
+ jmp_cond_mems: 0
+ jmp_cond_regs: 0
+ jmp_cond_jcxzs: 0
+
+ jmp_continuations: 0
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input
+Running: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
+Done: /home/jon/git/AFLplusplus/frida_mode/test/output/build/frida-out/default/.cur_input: (3 bytes)
diff --git a/frida_mode/test/output/frida_stdout.txt b/frida_mode/test/output/frida_stdout.txt
new file mode 100644
index 00000000..8832681d
--- /dev/null
+++ b/frida_mode/test/output/frida_stdout.txt
@@ -0,0 +1,349 @@
+OG Range - 0x00007FFFF7FFE000 - 0x00007FFFF7FFF000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FFD000 - 0x00007FFFF7FFE000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FFC000 - 0x00007FFFF7FFD000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FF3000 - 0x00007FFFF7FFB000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FD0000 - 0x00007FFFF7FF3000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FCF000 - 0x00007FFFF7FD0000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FCE000 - 0x00007FFFF7FCF000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7FCB000 - 0x00007FFFF7FCE000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7DC4000 - 0x00007FFFF7FCB000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7DBC000 - 0x00007FFFF7DC4000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7DB0000 - 0x00007FFFF7DBC000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7A94000 - 0x00007FFFF7DB0000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7942000 - 0x00007FFFF7A94000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF78BF000 - 0x00007FFFF7942000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF78AF000 - 0x00007FFFF78BF000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF78AA000 - 0x00007FFFF78AB000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF78A9000 - 0x00007FFFF78AA000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF78A2000 - 0x00007FFFF78A6000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF789F000 - 0x00007FFFF78A2000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF789C000 - 0x00007FFFF789F000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7851000 - 0x00007FFFF789B000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76DB000 - 0x00007FFFF7851000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76DA000 - 0x00007FFFF76DB000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76D9000 - 0x00007FFFF76DA000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76B4000 - 0x00007FFFF76D9000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76B0000 - 0x00007FFFF76B4000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76AF000 - 0x00007FFFF76B0000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76AE000 - 0x00007FFFF76AF000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF76A9000 - 0x00007FFFF76AE000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7698000 - 0x00007FFFF76A9000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7691000 - 0x00007FFFF7698000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF768F000 - 0x00007FFFF7691000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF768E000 - 0x00007FFFF768F000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF768D000 - 0x00007FFFF768E000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7689000 - 0x00007FFFF768C000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7679000 - 0x00007FFFF7689000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7675000 - 0x00007FFFF7679000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7674000 - 0x00007FFFF7675000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7673000 - 0x00007FFFF7674000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7672000 - 0x00007FFFF7673000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF7670000 - 0x00007FFFF7672000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF766F000 - 0x00007FFFF7670000[0m
+[1;92m[+] [0mCMPLOG Range - 0x00007FFFF766D000 - 0x00007FFFF766F000[0m
+[1;92m[+] [0mRedirect 1 -> '/home/jon/git/AFLplusplus/frida_mode/test/output/frida_stdout.txt'[0m
+[1;92m[+] [0mRedirect 2 -> '/home/jon/git/AFLplusplus/frida_mode/test/output/frida_stderr.txt'[0m
+[1;92m[+] [0mInstrumentation - persistent mode [ ] (0x0000000000000000)[0m
+[1;92m[+] [0mInstrumentation - persistent count [ ] (0)[0m
+[1;92m[+] [0mInstrumentation - hook [(null)][0m
+[1;92m[+] [0mInstrumentation - persistent ret [ ] (0x0000000000000000)[0m
+[1;92m[+] [0mInstrumentation - persistent ret offset [ ] (0)[0m
+[1;92m[+] [0mInstrumentation - prefetch [X][0m
+[1;92m[+] [0mRange: Modules Length: 54[0m
+[1;92m[+] [0mRange: Modules Idx: 0 - 0x0000555555554000-0x0000555555555000[0m
+[1;92m[+] [0mRange: Modules Idx: 1 - 0x0000555555555000-0x0000555555556000[0m
+[1;92m[+] [0mRange: Modules Idx: 2 - 0x0000555555556000-0x0000555555557000[0m
+[1;92m[+] [0mRange: Modules Idx: 3 - 0x0000555555557000-0x0000555555558000[0m
+[1;92m[+] [0mRange: Modules Idx: 4 - 0x0000555555558000-0x0000555555559000[0m
+[1;92m[+] [0mRange: Modules Idx: 5 - 0x0000555555559000-0x000055555557a000[0m
+[1;92m[+] [0mRange: Modules Idx: 6 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: Modules Idx: 7 - 0x00007ffff766d000-0x00007ffff766f000[0m
+[1;92m[+] [0mRange: Modules Idx: 8 - 0x00007ffff766f000-0x00007ffff7670000[0m
+[1;92m[+] [0mRange: Modules Idx: 9 - 0x00007ffff7670000-0x00007ffff7672000[0m
+[1;92m[+] [0mRange: Modules Idx: 10 - 0x00007ffff7672000-0x00007ffff7673000[0m
+[1;92m[+] [0mRange: Modules Idx: 11 - 0x00007ffff7673000-0x00007ffff7674000[0m
+[1;92m[+] [0mRange: Modules Idx: 12 - 0x00007ffff7674000-0x00007ffff7675000[0m
+[1;92m[+] [0mRange: Modules Idx: 13 - 0x00007ffff7675000-0x00007ffff7679000[0m
+[1;92m[+] [0mRange: Modules Idx: 14 - 0x00007ffff7679000-0x00007ffff7689000[0m
+[1;92m[+] [0mRange: Modules Idx: 15 - 0x00007ffff7689000-0x00007ffff768c000[0m
+[1;92m[+] [0mRange: Modules Idx: 16 - 0x00007ffff768c000-0x00007ffff768d000[0m
+[1;92m[+] [0mRange: Modules Idx: 17 - 0x00007ffff768d000-0x00007ffff768e000[0m
+[1;92m[+] [0mRange: Modules Idx: 18 - 0x00007ffff768e000-0x00007ffff768f000[0m
+[1;92m[+] [0mRange: Modules Idx: 19 - 0x00007ffff768f000-0x00007ffff7691000[0m
+[1;92m[+] [0mRange: Modules Idx: 20 - 0x00007ffff7691000-0x00007ffff7698000[0m
+[1;92m[+] [0mRange: Modules Idx: 21 - 0x00007ffff7698000-0x00007ffff76a9000[0m
+[1;92m[+] [0mRange: Modules Idx: 22 - 0x00007ffff76a9000-0x00007ffff76ae000[0m
+[1;92m[+] [0mRange: Modules Idx: 23 - 0x00007ffff76ae000-0x00007ffff76af000[0m
+[1;92m[+] [0mRange: Modules Idx: 24 - 0x00007ffff76af000-0x00007ffff76b0000[0m
+[1;92m[+] [0mRange: Modules Idx: 25 - 0x00007ffff76b0000-0x00007ffff76b4000[0m
+[1;92m[+] [0mRange: Modules Idx: 26 - 0x00007ffff76b4000-0x00007ffff76d9000[0m
+[1;92m[+] [0mRange: Modules Idx: 27 - 0x00007ffff76d9000-0x00007ffff76da000[0m
+[1;92m[+] [0mRange: Modules Idx: 28 - 0x00007ffff76da000-0x00007ffff76db000[0m
+[1;92m[+] [0mRange: Modules Idx: 29 - 0x00007ffff76db000-0x00007ffff7851000[0m
+[1;92m[+] [0mRange: Modules Idx: 30 - 0x00007ffff7851000-0x00007ffff789b000[0m
+[1;92m[+] [0mRange: Modules Idx: 31 - 0x00007ffff789b000-0x00007ffff789c000[0m
+[1;92m[+] [0mRange: Modules Idx: 32 - 0x00007ffff789c000-0x00007ffff789f000[0m
+[1;92m[+] [0mRange: Modules Idx: 33 - 0x00007ffff789f000-0x00007ffff78a2000[0m
+[1;92m[+] [0mRange: Modules Idx: 34 - 0x00007ffff78a2000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: Modules Idx: 35 - 0x00007ffff78a9000-0x00007ffff78aa000[0m
+[1;92m[+] [0mRange: Modules Idx: 36 - 0x00007ffff78aa000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: Modules Idx: 37 - 0x00007ffff78af000-0x00007ffff78bf000[0m
+[1;92m[+] [0mRange: Modules Idx: 38 - 0x00007ffff78bf000-0x00007ffff7942000[0m
+[1;92m[+] [0mRange: Modules Idx: 39 - 0x00007ffff7942000-0x00007ffff7a94000[0m
+[1;92m[+] [0mRange: Modules Idx: 40 - 0x00007ffff7a94000-0x00007ffff7db0000[0m
+[1;92m[+] [0mRange: Modules Idx: 41 - 0x00007ffff7db0000-0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: Modules Idx: 42 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: Modules Idx: 43 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: Modules Idx: 44 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: Modules Idx: 45 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: Modules Idx: 46 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: Modules Idx: 47 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: Modules Idx: 48 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: Modules Idx: 49 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: Modules Idx: 50 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: Modules Idx: 51 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: Modules Idx: 52 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: Modules Idx: 53 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: AFL_INST_LIBS Length: 1[0m
+[1;92m[+] [0mRange: AFL_INST_LIBS Idx: 0 - 0x0000555555555160-0x0000555555555335[0m
+[1;92m[+] [0mRange: step1 Length: 1[0m
+[1;92m[+] [0mRange: step1 Idx: 0 - 0x0000555555555160-0x0000555555555335[0m
+[1;92m[+] [0mRange: step2 Length: 1[0m
+[1;92m[+] [0mRange: step2 Idx: 0 - 0x0000555555555160-0x0000555555555335[0m
+[1;92m[+] [0mRange: step3 Length: 1[0m
+[1;92m[+] [0mRange: step3 Idx: 0 - 0x0000555555555160-0x0000555555555335[0m
+[1;92m[+] [0mRange: step4 Length: 55[0m
+[1;92m[+] [0mRange: step4 Idx: 0 - 0x0000555555554000-0x0000555555555000[0m
+[1;92m[+] [0mRange: step4 Idx: 1 - 0x0000555555555000-0x0000555555555160[0m
+[1;92m[+] [0mRange: step4 Idx: 2 - 0x0000555555555335-0x0000555555556000[0m
+[1;92m[+] [0mRange: step4 Idx: 3 - 0x0000555555556000-0x0000555555557000[0m
+[1;92m[+] [0mRange: step4 Idx: 4 - 0x0000555555557000-0x0000555555558000[0m
+[1;92m[+] [0mRange: step4 Idx: 5 - 0x0000555555558000-0x0000555555559000[0m
+[1;92m[+] [0mRange: step4 Idx: 6 - 0x0000555555559000-0x000055555557a000[0m
+[1;92m[+] [0mRange: step4 Idx: 7 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: step4 Idx: 8 - 0x00007ffff766d000-0x00007ffff766f000[0m
+[1;92m[+] [0mRange: step4 Idx: 9 - 0x00007ffff766f000-0x00007ffff7670000[0m
+[1;92m[+] [0mRange: step4 Idx: 10 - 0x00007ffff7670000-0x00007ffff7672000[0m
+[1;92m[+] [0mRange: step4 Idx: 11 - 0x00007ffff7672000-0x00007ffff7673000[0m
+[1;92m[+] [0mRange: step4 Idx: 12 - 0x00007ffff7673000-0x00007ffff7674000[0m
+[1;92m[+] [0mRange: step4 Idx: 13 - 0x00007ffff7674000-0x00007ffff7675000[0m
+[1;92m[+] [0mRange: step4 Idx: 14 - 0x00007ffff7675000-0x00007ffff7679000[0m
+[1;92m[+] [0mRange: step4 Idx: 15 - 0x00007ffff7679000-0x00007ffff7689000[0m
+[1;92m[+] [0mRange: step4 Idx: 16 - 0x00007ffff7689000-0x00007ffff768c000[0m
+[1;92m[+] [0mRange: step4 Idx: 17 - 0x00007ffff768c000-0x00007ffff768d000[0m
+[1;92m[+] [0mRange: step4 Idx: 18 - 0x00007ffff768d000-0x00007ffff768e000[0m
+[1;92m[+] [0mRange: step4 Idx: 19 - 0x00007ffff768e000-0x00007ffff768f000[0m
+[1;92m[+] [0mRange: step4 Idx: 20 - 0x00007ffff768f000-0x00007ffff7691000[0m
+[1;92m[+] [0mRange: step4 Idx: 21 - 0x00007ffff7691000-0x00007ffff7698000[0m
+[1;92m[+] [0mRange: step4 Idx: 22 - 0x00007ffff7698000-0x00007ffff76a9000[0m
+[1;92m[+] [0mRange: step4 Idx: 23 - 0x00007ffff76a9000-0x00007ffff76ae000[0m
+[1;92m[+] [0mRange: step4 Idx: 24 - 0x00007ffff76ae000-0x00007ffff76af000[0m
+[1;92m[+] [0mRange: step4 Idx: 25 - 0x00007ffff76af000-0x00007ffff76b0000[0m
+[1;92m[+] [0mRange: step4 Idx: 26 - 0x00007ffff76b0000-0x00007ffff76b4000[0m
+[1;92m[+] [0mRange: step4 Idx: 27 - 0x00007ffff76b4000-0x00007ffff76d9000[0m
+[1;92m[+] [0mRange: step4 Idx: 28 - 0x00007ffff76d9000-0x00007ffff76da000[0m
+[1;92m[+] [0mRange: step4 Idx: 29 - 0x00007ffff76da000-0x00007ffff76db000[0m
+[1;92m[+] [0mRange: step4 Idx: 30 - 0x00007ffff76db000-0x00007ffff7851000[0m
+[1;92m[+] [0mRange: step4 Idx: 31 - 0x00007ffff7851000-0x00007ffff789b000[0m
+[1;92m[+] [0mRange: step4 Idx: 32 - 0x00007ffff789b000-0x00007ffff789c000[0m
+[1;92m[+] [0mRange: step4 Idx: 33 - 0x00007ffff789c000-0x00007ffff789f000[0m
+[1;92m[+] [0mRange: step4 Idx: 34 - 0x00007ffff789f000-0x00007ffff78a2000[0m
+[1;92m[+] [0mRange: step4 Idx: 35 - 0x00007ffff78a2000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: step4 Idx: 36 - 0x00007ffff78a9000-0x00007ffff78aa000[0m
+[1;92m[+] [0mRange: step4 Idx: 37 - 0x00007ffff78aa000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: step4 Idx: 38 - 0x00007ffff78af000-0x00007ffff78bf000[0m
+[1;92m[+] [0mRange: step4 Idx: 39 - 0x00007ffff78bf000-0x00007ffff7942000[0m
+[1;92m[+] [0mRange: step4 Idx: 40 - 0x00007ffff7942000-0x00007ffff7a94000[0m
+[1;92m[+] [0mRange: step4 Idx: 41 - 0x00007ffff7a94000-0x00007ffff7db0000[0m
+[1;92m[+] [0mRange: step4 Idx: 42 - 0x00007ffff7db0000-0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
+0x00007ffff7dbc000[0m
+[1;92m[+] [0mRange: step4 Idx: 43 - 0x00007ffff7dbc000-0x00007ffff7dc4000[0m
+[1;92m[+] [0mRange: step4 Idx: 44 - 0x00007ffff7dc4000-0x00007ffff7fcb000[0m
+[1;92m[+] [0mRange: step4 Idx: 45 - 0x00007ffff7fcb000-0x00007ffff7fce000[0m
+[1;92m[+] [0mRange: step4 Idx: 46 - 0x00007ffff7fce000-0x00007ffff7fcf000[0m
+[1;92m[+] [0mRange: step4 Idx: 47 - 0x00007ffff7fcf000-0x00007ffff7fd0000[0m
+[1;92m[+] [0mRange: step4 Idx: 48 - 0x00007ffff7fd0000-0x00007ffff7ff3000[0m
+[1;92m[+] [0mRange: step4 Idx: 49 - 0x00007ffff7ff3000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: step4 Idx: 50 - 0x00007ffff7ffc000-0x00007ffff7ffd000[0m
+[1;92m[+] [0mRange: step4 Idx: 51 - 0x00007ffff7ffd000-0x00007ffff7ffe000[0m
+[1;92m[+] [0mRange: step4 Idx: 52 - 0x00007ffff7ffe000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: step4 Idx: 53 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: step4 Idx: 54 - 0xffffffffff600000-0xffffffffff601000[0m
+[1;92m[+] [0mRange: final Length: 9[0m
+[1;92m[+] [0mRange: final Idx: 0 - 0x0000555555554000-0x0000555555555160[0m
+[1;92m[+] [0mRange: final Idx: 1 - 0x0000555555555335-0x000055555557a000[0m
+[1;92m[+] [0mRange: final Idx: 2 - 0x00007ffff7615000-0x00007ffff7625000[0m
+[1;92m[+] [0mRange: final Idx: 3 - 0x00007ffff766d000-0x00007ffff78a6000[0m
+[1;92m[+] [0mRange: final Idx: 4 - 0x00007ffff78a9000-0x00007ffff78ab000[0m
+[1;92m[+] [0mRange: final Idx: 5 - 0x00007ffff78af000-0x00007ffff7ffb000[0m
+[1;92m[+] [0mRange: final Idx: 6 - 0x00007ffff7ffc000-0x00007ffff7fff000[0m
+[1;92m[+] [0mRange: final Idx: 7 - 0x00007ffffffdd000-0x00007ffffffff000[0m
+[1;92m[+] [0mRange: final Idx: 8 - 0xffffffffff600000-0xffffffffff601000[0m
+Looks like a zero to me!
diff --git a/frida_mode/test/output/testinstr.c b/frida_mode/test/output/testinstr.c
new file mode 100644
index 00000000..5e26fc46
--- /dev/null
+++ b/frida_mode/test/output/testinstr.c
@@ -0,0 +1,112 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #define TESTINSTR_SECTION
+#else
+ #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+
+}
+
+TESTINSTR_SECTION int main(int argc, char **argv) {
+
+ char * file;
+ int fd = -1;
+ off_t len;
+ char * buf = NULL;
+ size_t n_read;
+ int result = -1;
+
+ if (argc != 2) { return 1; }
+
+ do {
+
+ file = argv[1];
+
+ dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+ 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;
+
+ }
+
+ 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);
+
+ testinstr(buf, len);
+ dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
+
+ result = 0;
+
+ } while (false);
+
+ if (buf != NULL) { free(buf); }
+
+ if (fd != -1) { close(fd); }
+
+ return result;
+
+}
+
diff --git a/frida_mode/test/persistent_ret/GNUmakefile b/frida_mode/test/persistent_ret/GNUmakefile
new file mode 100644
index 00000000..df48d065
--- /dev/null
+++ b/frida_mode/test/persistent_ret/GNUmakefile
@@ -0,0 +1,105 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s main -b 0x0000aaaaaaaaa000)
+ AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s main -b 0x0000555555554000)
+ AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s main -b 0x56555000)
+ AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x56555000)
+endif
+
+AFL_FRIDA_PERSISTENT_RETADDR_OFFSET:=0x50
+
+.PHONY: all 32 clean qemu frida
+
+all: $(TESTINSTBIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
+
+frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \
+ AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
+
+debug: $(TESTINSTR_DATA_FILE)
+ gdb \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET)' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET)' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_DEBUG=1' \
+ --ex 'set environment AFL_DEBUG_CHILD=1' \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+
+run: $(TESTINSTR_DATA_FILE)
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \
+ AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \
+ AFL_DEBUG_CHILD=1 \
+ LD_PRELOAD=$(ROOT)afl-frida-trace.so \
+ $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
diff --git a/frida_mode/test/persistent_ret/Makefile b/frida_mode/test/persistent_ret/Makefile
new file mode 100644
index 00000000..e3deddbd
--- /dev/null
+++ b/frida_mode/test/persistent_ret/Makefile
@@ -0,0 +1,22 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
+
+frida_ret:
+ @gmake frida_ret
+
+debug:
+ @gmake debug
+
+run:
+ @gmake run
diff --git a/frida_mode/test/persistent_ret/get_symbol_addr.py b/frida_mode/test/persistent_ret/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/persistent_ret/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+ with open(file, 'rb') as f:
+ elf = ELFFile(f)
+ symtab = elf.get_section_by_name('.symtab')
+ mains = symtab.get_symbol_by_name(symbol)
+ if len(mains) != 1:
+ print ("Failed to find main")
+ return 1
+
+ main_addr = mains[0]['st_value']
+ main = base + main_addr
+ print ("0x%016x" % main)
+ return 0
+
+def hex_value(x):
+ return int(x, 16)
+
+def main():
+ parser = argparse.ArgumentParser(description='Process some integers.')
+ parser.add_argument('-f', '--file', dest='file', type=str,
+ help='elf file name', required=True)
+ parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+ help='symbol name', required=True)
+ parser.add_argument('-b', '--base', dest='base', type=hex_value,
+ help='elf base address', required=True)
+
+ args = parser.parse_args()
+ return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+ ret = main()
+ exit(ret)
diff --git a/frida_mode/test/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c
new file mode 100644
index 00000000..6cb88a50
--- /dev/null
+++ b/frida_mode/test/persistent_ret/testinstr.c
@@ -0,0 +1,120 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #define TESTINSTR_SECTION
+#else
+ #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+
+}
+
+void slow() {
+
+ usleep(100000);
+
+}
+
+TESTINSTR_SECTION int main(int argc, char **argv) {
+
+ char * file;
+ int fd = -1;
+ off_t len;
+ char * buf = NULL;
+ size_t n_read;
+ int result = -1;
+
+ if (argc != 2) { return 1; }
+
+ do {
+
+ file = argv[1];
+
+ dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+ 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;
+
+ }
+
+ 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);
+
+ testinstr(buf, len);
+ dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
+
+ slow();
+
+ result = 0;
+
+ } while (false);
+
+ if (buf != NULL) { free(buf); }
+
+ if (fd != -1) { close(fd); }
+
+ return result;
+
+}
+
diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile
new file mode 100644
index 00000000..e05bade2
--- /dev/null
+++ b/frida_mode/test/png/GNUmakefile
@@ -0,0 +1,114 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+
+LIBPNG_BUILD_DIR:=$(BUILD_DIR)libpng/
+HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/
+PNGTEST_BUILD_DIR:=$(BUILD_DIR)pngtest/
+
+LIBPNG_FILE:=$(LIBPNG_BUILD_DIR)libpng-1.2.56.tar.gz
+LIBPNG_URL:=https://downloads.sourceforge.net/project/libpng/libpng12/older-releases/1.2.56/libpng-1.2.56.tar.gz
+LIBPNG_DIR:=$(LIBPNG_BUILD_DIR)libpng-1.2.56/
+LIBPNG_MAKEFILE:=$(LIBPNG_DIR)Makefile
+LIBPNG_LIB:=$(LIBPNG_DIR).libs/libpng12.a
+
+HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o
+HARNESS_URL:="https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c"
+
+PNGTEST_FILE:=$(PNGTEST_BUILD_DIR)target.cc
+PNGTEST_OBJ:=$(PNGTEST_BUILD_DIR)target.o
+PNGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libpng-1.2.56/target.cc"
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup
+endif
+
+TEST_DATA_DIR:=$(LIBPNG_DIR)contrib/pngsuite/
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+.PHONY: all clean qemu frida
+
+all: $(TEST_BIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+######### HARNESS ########
+$(HARNESS_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(HARNESS_FILE): | $(HARNESS_BUILD_DIR)
+ wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_FILE)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ -c $<
+
+######### PNGTEST ########
+
+$(PNGTEST_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(PNGTEST_FILE): | $(PNGTEST_BUILD_DIR)
+ wget -O $@ $(PNGTEST_URL)
+
+$(PNGTEST_OBJ): $(PNGTEST_FILE) | $(LIBPNG_DIR)
+ $(CXX) $(CFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBPNG_DIR) -o $@ -c $<
+
+######### LIBPNG ########
+
+$(LIBPNG_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(LIBPNG_FILE): | $(LIBPNG_BUILD_DIR)
+ wget -O $@ $(LIBPNG_URL)
+
+$(LIBPNG_DIR): $(LIBPNG_FILE)
+ tar zxvf $(LIBPNG_FILE) -C $(LIBPNG_BUILD_DIR)
+
+$(LIBPNG_MAKEFILE): | $(LIBPNG_DIR)
+ cd $(LIBPNG_DIR) && ./configure
+
+$(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
+ make -C $(LIBPNG_DIR)
+
+######### TEST ########
+
+$(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB)
+ $(CXX) \
+ $(CFLAGS) \
+ $(LDFLAGS) \
+ -o $@ \
+ $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \
+ -lz \
+ $(TEST_BIN_LDFLAGS) \
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+qemu: $(TEST_BIN)
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) @@
+
+frida: $(TEST_BIN)
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) @@
diff --git a/frida_mode/test/png/Makefile b/frida_mode/test/png/Makefile
new file mode 100644
index 00000000..4bef1ccb
--- /dev/null
+++ b/frida_mode/test/png/Makefile
@@ -0,0 +1,16 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+frida:
+ @gmake frida
diff --git a/frida_mode/test/png/persistent/GNUmakefile b/frida_mode/test/png/persistent/GNUmakefile
new file mode 100644
index 00000000..ca6f0ff2
--- /dev/null
+++ b/frida_mode/test/png/persistent/GNUmakefile
@@ -0,0 +1,98 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../../..)/
+BUILD_DIR:=$(PWD)build/
+
+TEST_BIN:=$(PWD)../build/test
+TEST_DATA_DIR:=../build/libpng/libpng-1.2.56/contrib/pngsuite/
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x4000000000)
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x56555000)
+endif
+
+.PHONY: all 32 clean qemu qemu_entry frida frida_entry
+
+all:
+ make -C $(ROOT)frida_mode/test/png/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+qemu: | $(BUILD_DIR)
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_GPR=1 \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) @@
+
+qemu_entry: | $(BUILD_DIR)
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_GPR=1 \
+ AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) @@
+
+frida: | $(BUILD_DIR)
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) @@
+
+frida_entry: | $(BUILD_DIR)
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) @@
+
+clean:
+ rm -rf $(BUILD_DIR)
diff --git a/frida_mode/test/png/persistent/Makefile b/frida_mode/test/png/persistent/Makefile
new file mode 100644
index 00000000..cde0cf30
--- /dev/null
+++ b/frida_mode/test/png/persistent/Makefile
@@ -0,0 +1,22 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+qemu_entry:
+ @gmake qemu_entry
+
+frida:
+ @gmake frida
+
+frida_entry:
+ @gmake frida_entry
diff --git a/frida_mode/test/png/persistent/get_symbol_addr.py b/frida_mode/test/png/persistent/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/png/persistent/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+ with open(file, 'rb') as f:
+ elf = ELFFile(f)
+ symtab = elf.get_section_by_name('.symtab')
+ mains = symtab.get_symbol_by_name(symbol)
+ if len(mains) != 1:
+ print ("Failed to find main")
+ return 1
+
+ main_addr = mains[0]['st_value']
+ main = base + main_addr
+ print ("0x%016x" % main)
+ return 0
+
+def hex_value(x):
+ return int(x, 16)
+
+def main():
+ parser = argparse.ArgumentParser(description='Process some integers.')
+ parser.add_argument('-f', '--file', dest='file', type=str,
+ help='elf file name', required=True)
+ parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+ help='symbol name', required=True)
+ parser.add_argument('-b', '--base', dest='base', type=hex_value,
+ help='elf base address', required=True)
+
+ args = parser.parse_args()
+ return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+ ret = main()
+ exit(ret)
diff --git a/frida_mode/test/png/persistent/hook/GNUmakefile b/frida_mode/test/png/persistent/hook/GNUmakefile
new file mode 100644
index 00000000..82f08fa4
--- /dev/null
+++ b/frida_mode/test/png/persistent/hook/GNUmakefile
@@ -0,0 +1,141 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../../../..)/
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c
+AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so
+
+CFLAGS+=-O3 \
+ -funroll-loops \
+ -g \
+ -fPIC \
+ -funroll-loops \
+
+LDFLAGS+=-shared \
+
+TEST_BIN:=$(PWD)../../build/test
+TEST_DATA_DIR:=../../build/libpng/libpng-1.2.56/contrib/pngsuite/
+
+AFLPP_DRIVER_DUMMY_INPUT:=$(BUILD_DIR)in
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000)
+
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000)
+endif
+
+.PHONY: all 32 clean format qemu qemu_entry frida frida_entry debug
+
+all: $(AFLPP_DRIVER_HOOK_OBJ)
+ make -C $(ROOT)frida_mode/test/png/persistent/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+.PHONY: all clean qemu qemu_entry frida frida_entry
+
+all:
+ make -C $(ROOT)frida_mode/test/png/persistent/
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TEST_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR)
+ truncate -s 1M $@
+
+$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@
+
+qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR)
+ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_GPR=1 \
+ $(ROOT)/afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+qemu_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR)
+ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_GPR=1 \
+ $(ROOT)/afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+frida: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR)
+ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+
+frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR)
+ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+debug:
+ echo $(AFL_FRIDA_PERSISTENT_ADDR)
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ)' \
+ --ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+format:
+ cd $(ROOT) && echo $(AFLPP_DRIVER_HOOK_SRC) | xargs -L1 ./.custom-format.py -i
+
diff --git a/frida_mode/test/png/persistent/hook/Makefile b/frida_mode/test/png/persistent/hook/Makefile
new file mode 100644
index 00000000..983d009e
--- /dev/null
+++ b/frida_mode/test/png/persistent/hook/Makefile
@@ -0,0 +1,28 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+format:
+ @gmake format
+
+qemu:
+ @gmake qemu
+
+qemu_entry:
+ @gmake qemu_entry
+
+frida:
+ @gmake frida
+
+frida_entry:
+ @gmake frida_entry
+
+debug:
+ @gmake debug
diff --git a/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c b/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c
new file mode 100644
index 00000000..059d438d
--- /dev/null
+++ b/frida_mode/test/png/persistent/hook/aflpp_qemu_driver_hook.c
@@ -0,0 +1,97 @@
+#include
+#include
+
+#if defined(__x86_64__)
+
+struct x86_64_regs {
+
+ uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14,
+ r15;
+
+ union {
+
+ uint64_t rip;
+ uint64_t pc;
+
+ };
+
+ union {
+
+ uint64_t rsp;
+ uint64_t sp;
+
+ };
+
+ union {
+
+ uint64_t rflags;
+ uint64_t flags;
+
+ };
+
+ uint8_t zmm_regs[32][64];
+
+};
+
+void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
+ memcpy((void *)regs->rdi, input_buf, input_buf_len);
+ regs->rsi = input_buf_len;
+
+}
+
+#elif defined(__i386__)
+
+struct x86_regs {
+
+ uint32_t eax, ebx, ecx, edx, edi, esi, ebp;
+
+ union {
+
+ uint32_t eip;
+ uint32_t pc;
+
+ };
+
+ union {
+
+ uint32_t esp;
+ uint32_t sp;
+
+ };
+
+ union {
+
+ uint32_t eflags;
+ uint32_t flags;
+
+ };
+
+ uint8_t xmm_regs[8][16];
+
+};
+
+void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
+ void **esp = (void **)regs->esp;
+ void * arg1 = esp[1];
+ void **arg2 = &esp[2];
+ memcpy(arg1, input_buf, input_buf_len);
+ *arg2 = (void *)input_buf_len;
+
+}
+
+#else
+ #pragma error "Unsupported architecture"
+#endif
+
+int afl_persistent_hook_init(void) {
+
+ // 1 for shared memory input (faster), 0 for normal input (you have to use
+ // read(), input_buf will be NULL)
+ return 1;
+
+}
+
diff --git a/frida_mode/test/re2/GNUmakefile b/frida_mode/test/re2/GNUmakefile
new file mode 100644
index 00000000..9f0b31d3
--- /dev/null
+++ b/frida_mode/test/re2/GNUmakefile
@@ -0,0 +1,170 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c
+AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so
+
+LIBRE2_BUILD_DIR:=$(BUILD_DIR)libre2/
+HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/
+RE2TEST_BUILD_DIR:=$(BUILD_DIR)re2test/
+
+LIBRE2_URL:=https://github.com/google/re2.git
+LIBRE2_DIR:=$(LIBRE2_BUILD_DIR)libre2/
+LIBRE2_MAKEFILE:=$(LIBRE2_DIR)Makefile
+LIBRE2_LIB:=$(LIBRE2_DIR)obj/libre2.a
+
+HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o
+HARNESS_URL:="https://raw.githubusercontent.com/llvm/llvm-project/main/compiler-rt/lib/fuzzer/standalone/StandaloneFuzzTargetMain.c"
+
+RE2TEST_FILE:=$(RE2TEST_BUILD_DIR)target.cc
+RE2TEST_OBJ:=$(RE2TEST_BUILD_DIR)target.o
+RE2TEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/re2-2014-12-09/target.cc"
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+AFLPP_DRIVER_DUMMY_INPUT:=$(TEST_DATA_DIR)in
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000)
+
+ifeq "$(ARCH)" "aarch64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000aaaaaaaaa000)
+endif
+
+ifeq "$(ARCH)" "x86_64"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000)
+endif
+
+.PHONY: all clean qemu frida hook
+
+all: $(TEST_BIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+######### HARNESS ########
+$(HARNESS_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(HARNESS_FILE): | $(HARNESS_BUILD_DIR)
+ wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_FILE)
+ $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ -c $<
+
+######### RE2TEST ########
+
+$(RE2TEST_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(RE2TEST_FILE): | $(RE2TEST_BUILD_DIR)
+ wget -O $@ $(RE2TEST_URL)
+
+$(RE2TEST_OBJ): $(RE2TEST_FILE) | $(LIBRE2_MAKEFILE)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBRE2_DIR) -o $@ -c $<
+
+######### LIBRE2 ########
+
+$(LIBRE2_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(LIBRE2_MAKEFILE): $(LIBRE2_BUILD_DIR)
+ git clone https://github.com/google/re2.git $(LIBRE2_DIR)
+ cd $(LIBRE2_DIR) && git checkout 499ef7eff7455ce9c9fae86111d4a77b6ac335de
+
+$(LIBRE2_LIB): $(LIBRE2_MAKEFILE)
+ make -C $(LIBRE2_DIR) -j $(shell nproc)
+
+######### TEST ########
+
+$(TEST_BIN): $(HARNESS_OBJ) $(RE2TEST_OBJ) $(LIBRE2_LIB)
+ $(CXX) \
+ $(CFLAGS) \
+ -o $@ \
+ $(HARNESS_OBJ) $(RE2TEST_OBJ) $(LIBRE2_LIB) \
+ -lz \
+ $(LDFLAGS) \
+ $(TEST_BIN_LDFLAGS) \
+
+########## HOOK ########
+
+$(AFLPP_DRIVER_HOOK_OBJ): $(AFLPP_DRIVER_HOOK_SRC) | $(BUILD_DIR)
+ $(CC) -shared $(CFLAGS) $(LDFLAGS) $< -o $@
+
+########## DUMMY #######
+
+$(TEST_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(AFLPP_DRIVER_DUMMY_INPUT): | $(TEST_DATA_DIR)
+ truncate -s 1M $@
+
+###### TEST DATA #######
+
+hook: $(AFLPP_DRIVER_HOOK_OBJ)
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+qemu: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT)
+ AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \
+ AFL_QEMU_PERSISTENT_GPR=1 \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -Q \
+ -i $(TEST_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+frida: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT)
+ AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \
+ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \
+ $(ROOT)afl-fuzz \
+ -D \
+ -V 30 \
+ -O \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT)
+
+debug:
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TEST_BIN) $(TEST_DATA_DIR)basn0g01.re2
diff --git a/frida_mode/test/re2/Makefile b/frida_mode/test/re2/Makefile
new file mode 100644
index 00000000..00b2b287
--- /dev/null
+++ b/frida_mode/test/re2/Makefile
@@ -0,0 +1,22 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+frida:
+ @gmake frida
+
+debug:
+ @gmake debug
+
+hook:
+ @gmake hook
diff --git a/frida_mode/test/re2/aflpp_qemu_driver_hook.c b/frida_mode/test/re2/aflpp_qemu_driver_hook.c
new file mode 100644
index 00000000..059d438d
--- /dev/null
+++ b/frida_mode/test/re2/aflpp_qemu_driver_hook.c
@@ -0,0 +1,97 @@
+#include
+#include
+
+#if defined(__x86_64__)
+
+struct x86_64_regs {
+
+ uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14,
+ r15;
+
+ union {
+
+ uint64_t rip;
+ uint64_t pc;
+
+ };
+
+ union {
+
+ uint64_t rsp;
+ uint64_t sp;
+
+ };
+
+ union {
+
+ uint64_t rflags;
+ uint64_t flags;
+
+ };
+
+ uint8_t zmm_regs[32][64];
+
+};
+
+void afl_persistent_hook(struct x86_64_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
+ memcpy((void *)regs->rdi, input_buf, input_buf_len);
+ regs->rsi = input_buf_len;
+
+}
+
+#elif defined(__i386__)
+
+struct x86_regs {
+
+ uint32_t eax, ebx, ecx, edx, edi, esi, ebp;
+
+ union {
+
+ uint32_t eip;
+ uint32_t pc;
+
+ };
+
+ union {
+
+ uint32_t esp;
+ uint32_t sp;
+
+ };
+
+ union {
+
+ uint32_t eflags;
+ uint32_t flags;
+
+ };
+
+ uint8_t xmm_regs[8][16];
+
+};
+
+void afl_persistent_hook(struct x86_regs *regs, uint64_t guest_base,
+ uint8_t *input_buf, uint32_t input_buf_len) {
+
+ void **esp = (void **)regs->esp;
+ void * arg1 = esp[1];
+ void **arg2 = &esp[2];
+ memcpy(arg1, input_buf, input_buf_len);
+ *arg2 = (void *)input_buf_len;
+
+}
+
+#else
+ #pragma error "Unsupported architecture"
+#endif
+
+int afl_persistent_hook_init(void) {
+
+ // 1 for shared memory input (faster), 0 for normal input (you have to use
+ // read(), input_buf will be NULL)
+ return 1;
+
+}
+
diff --git a/frida_mode/test/re2/get_symbol_addr.py b/frida_mode/test/re2/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/re2/get_symbol_addr.py
@@ -0,0 +1,36 @@
+#!/usr/bin/python3
+import argparse
+from elftools.elf.elffile import ELFFile
+
+def process_file(file, symbol, base):
+ with open(file, 'rb') as f:
+ elf = ELFFile(f)
+ symtab = elf.get_section_by_name('.symtab')
+ mains = symtab.get_symbol_by_name(symbol)
+ if len(mains) != 1:
+ print ("Failed to find main")
+ return 1
+
+ main_addr = mains[0]['st_value']
+ main = base + main_addr
+ print ("0x%016x" % main)
+ return 0
+
+def hex_value(x):
+ return int(x, 16)
+
+def main():
+ parser = argparse.ArgumentParser(description='Process some integers.')
+ parser.add_argument('-f', '--file', dest='file', type=str,
+ help='elf file name', required=True)
+ parser.add_argument('-s', '--symbol', dest='symbol', type=str,
+ help='symbol name', required=True)
+ parser.add_argument('-b', '--base', dest='base', type=hex_value,
+ help='elf base address', required=True)
+
+ args = parser.parse_args()
+ return process_file (args.file, args.symbol, args.base)
+
+if __name__ == "__main__":
+ ret = main()
+ exit(ret)
diff --git a/frida_mode/test/testinstr/GNUmakefile b/frida_mode/test/testinstr/GNUmakefile
new file mode 100644
index 00000000..a35073ab
--- /dev/null
+++ b/frida_mode/test/testinstr/GNUmakefile
@@ -0,0 +1,59 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/
+TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in
+
+TESTINSTBIN:=$(BUILD_DIR)testinstr
+TESTINSTSRC:=$(PWD)testinstr.c
+
+QEMU_OUT:=$(BUILD_DIR)qemu-out
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+.PHONY: all 32 clean qemu frida
+
+all: $(TESTINSTBIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+$(TESTINSTR_DATA_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR)
+ echo -n "000" > $@
+
+$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR)
+ $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $<
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+
+qemu: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ $(ROOT)afl-fuzz \
+ -D \
+ -Q \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(QEMU_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
+
+frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
+ $(ROOT)afl-fuzz \
+ -D \
+ -O \
+ -i $(TESTINSTR_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -- \
+ $(TESTINSTBIN) @@
+
+debug:
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
diff --git a/frida_mode/test/testinstr/Makefile b/frida_mode/test/testinstr/Makefile
new file mode 100644
index 00000000..f843af19
--- /dev/null
+++ b/frida_mode/test/testinstr/Makefile
@@ -0,0 +1,19 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+qemu:
+ @gmake qemu
+
+frida:
+ @gmake frida
+
+debug:
+ @gmake debug
diff --git a/frida_mode/test/testinstr/testinstr.c b/frida_mode/test/testinstr/testinstr.c
new file mode 100644
index 00000000..5e26fc46
--- /dev/null
+++ b/frida_mode/test/testinstr/testinstr.c
@@ -0,0 +1,112 @@
+/*
+ american fuzzy lop++ - a trivial program to test the build
+ --------------------------------------------------------
+ Originally written by Michal Zalewski
+ Copyright 2014 Google Inc. All rights reserved.
+ Copyright 2019-2020 AFLplusplus Project. All rights reserved.
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at:
+ http://www.apache.org/licenses/LICENSE-2.0
+ */
+
+#include
+#include
+#include
+#include
+#include
+
+#ifdef __APPLE__
+ #define TESTINSTR_SECTION
+#else
+ #define TESTINSTR_SECTION __attribute__((section(".testinstr")))
+#endif
+
+void testinstr(char *buf, int len) {
+
+ if (len < 1) return;
+ buf[len] = 0;
+
+ // we support three input cases
+ if (buf[0] == '0')
+ printf("Looks like a zero to me!\n");
+ else if (buf[0] == '1')
+ printf("Pretty sure that is a one!\n");
+ else
+ printf("Neither one or zero? How quaint!\n");
+
+}
+
+TESTINSTR_SECTION int main(int argc, char **argv) {
+
+ char * file;
+ int fd = -1;
+ off_t len;
+ char * buf = NULL;
+ size_t n_read;
+ int result = -1;
+
+ if (argc != 2) { return 1; }
+
+ do {
+
+ file = argv[1];
+
+ dprintf(STDERR_FILENO, "Running: %s\n", file);
+
+ 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;
+
+ }
+
+ 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);
+
+ testinstr(buf, len);
+ dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read);
+
+ result = 0;
+
+ } while (false);
+
+ if (buf != NULL) { free(buf); }
+
+ if (fd != -1) { close(fd); }
+
+ return result;
+
+}
+
diff --git a/frida_mode/update_frida_version.sh b/frida_mode/update_frida_version.sh
new file mode 100755
index 00000000..7d938712
--- /dev/null
+++ b/frida_mode/update_frida_version.sh
@@ -0,0 +1,13 @@
+#!/bin/sh
+test -n "$1" && { echo This script has no options. It updates the referenced Frida version in GNUmakefile to the most current one. ; exit 1 ; }
+
+OLD=$(egrep '^GUM_DEVKIT_VERSION=' GNUmakefile 2>/dev/null|awk -F= '{print$2}')
+NEW=$(curl https://github.com/frida/frida/releases/ 2>/dev/null|egrep 'frida-gum-devkit-[0-9.]*-linux-x86_64'|head -n 1|sed 's/.*frida-gum-devkit-//'|sed 's/-linux.*//')
+
+echo Current set version: $OLD
+echo Newest available version: $NEW
+
+test -z "$OLD" -o -z "$NEW" -o "$OLD" = "$NEW" && { echo Nothing to be done. ; exit 0 ; }
+
+sed -i "s/=$OLD/=$NEW/" GNUmakefile || exit 1
+echo Successfully updated GNUmakefile
diff --git a/include/afl-fuzz.h b/include/afl-fuzz.h
index 565e9afd..4aba3bdf 100644
--- a/include/afl-fuzz.h
+++ b/include/afl-fuzz.h
@@ -384,13 +384,15 @@ typedef struct afl_env_vars {
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_cycle_schedules, afl_expand_havoc, afl_statsd, afl_cmplog_only_new,
+ afl_exit_on_seed_issues, afl_try_affinity;
u8 *afl_tmpdir, *afl_custom_mutator_library, *afl_python_module, *afl_path,
- *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_skip_crashes, *afl_preload,
+ *afl_hang_tmout, *afl_forksrv_init_tmout, *afl_preload,
*afl_max_det_extras, *afl_statsd_host, *afl_statsd_port,
*afl_crash_exitcode, *afl_statsd_tags_flavor, *afl_testcache_size,
- *afl_testcache_entries, *afl_kill_signal, *afl_target_env;
+ *afl_testcache_entries, *afl_kill_signal, *afl_target_env,
+ *afl_persistent_record, *afl_exit_on_time;
} afl_env_vars_t;
@@ -482,7 +484,6 @@ typedef struct afl_state {
no_unlink, /* do not unlink cur_input */
debug, /* Debug mode */
custom_only, /* Custom mutator only mode */
- python_only, /* Python-only mode */
is_main_node, /* if this is the main node */
is_secondary_node; /* if this is a secondary instance */
@@ -571,9 +572,11 @@ typedef struct afl_state {
blocks_eff_select, /* Blocks selected as fuzzable */
start_time, /* Unix start time (ms) */
last_sync_time, /* Time of last sync */
+ last_sync_cycle, /* Cycle no. of the last sync */
last_path_time, /* Time for most recent path (ms) */
last_crash_time, /* Time for most recent crash (ms) */
- last_hang_time; /* Time for most recent hang (ms) */
+ last_hang_time, /* Time for most recent hang (ms) */
+ exit_on_time; /* Delay to exit if no new paths */
u32 slowest_exec_ms, /* Slowest testcase non hang in ms */
subseq_tmouts; /* Number of timeouts in a row */
@@ -1132,6 +1135,7 @@ void check_if_tty(afl_state_t *);
void setup_signal_handlers(void);
void save_cmdline(afl_state_t *, u32, char **);
void read_foreign_testcases(afl_state_t *, int);
+void write_crash_readme(afl_state_t *afl);
/* CmpLog */
diff --git a/include/android-ashmem.h b/include/android-ashmem.h
index 91699b27..1bfd3220 100644
--- a/include/android-ashmem.h
+++ b/include/android-ashmem.h
@@ -2,26 +2,27 @@
#ifndef _ANDROID_ASHMEM_H
#define _ANDROID_ASHMEM_H
+ #define _GNU_SOURCE
+ #include
+ #include
#include
#include
#include
#include
-
- #if __ANDROID_API__ >= 26
- #define shmat bionic_shmat
- #define shmctl bionic_shmctl
- #define shmdt bionic_shmdt
- #define shmget bionic_shmget
- #endif
#include
- #undef shmat
- #undef shmctl
- #undef shmdt
- #undef shmget
#include
-
#define ASHMEM_DEVICE "/dev/ashmem"
+int shmdt(const void *address) {
+
+ #if defined(SYS_shmdt)
+ return syscall(SYS_shmdt, address);
+ #else
+ return syscall(SYS_ipc, SHMDT, 0, 0, 0, address, 0);
+ #endif
+
+}
+
int shmctl(int __shmid, int __cmd, struct shmid_ds *__buf) {
int ret = 0;
diff --git a/include/config.h b/include/config.h
index c93a6d51..a1fdd789 100644
--- a/include/config.h
+++ b/include/config.h
@@ -26,7 +26,7 @@
/* Version string: */
// c = release, a = volatile github dev, e = experimental branch
-#define VERSION "++3.12c"
+#define VERSION "++3.13c"
/******************************************************
* *
@@ -71,7 +71,17 @@
/* Maximum allowed fails per CMP value. Default: 128 */
#define CMPLOG_FAIL_MAX 96
+/* -------------------------------------*/
/* Now non-cmplog configuration options */
+/* -------------------------------------*/
+
+/* If a persistent target keeps state and found crashes are not reproducable
+ then enable this option and set the AFL_PERSISTENT_RECORD env variable
+ to a number. These number of testcases prior and including the crash case
+ will be kept and written to the crash/ directory as RECORD:... files.
+ Note that every crash will be written, not only unique ones! */
+
+//#define AFL_PERSISTENT_RECORD
/* console output colors: There are three ways to configure its behavior
* 1. default: colored outputs fixed on: defined USE_COLOR && defined
@@ -144,7 +154,7 @@
cases that show variable behavior): */
#define CAL_CYCLES 8U
-#define CAL_CYCLES_LONG 40U
+#define CAL_CYCLES_LONG 20U
/* Number of subsequent timeouts before abandoning an input file: */
@@ -153,7 +163,7 @@
/* Maximum number of unique hangs or crashes to record: */
#define KEEP_UNIQUE_HANG 500U
-#define KEEP_UNIQUE_CRASH 5000U
+#define KEEP_UNIQUE_CRASH 10000U
/* Baseline number of random tweaks during a single 'havoc' stage: */
@@ -396,6 +406,10 @@
#define MSAN_ERROR 86
+/* Distinctive exit code used to indicate LSAN trip condition: */
+
+#define LSAN_ERROR 23
+
/* Designated file descriptors for forkserver commands (the application will
use FORKSRV_FD and FORKSRV_FD + 1): */
diff --git a/include/debug.h b/include/debug.h
index fc1f39cb..f8df5711 100644
--- a/include/debug.h
+++ b/include/debug.h
@@ -362,7 +362,12 @@ static inline const char *colorfilter(const char *x) {
\
s32 _len = (s32)(len); \
s32 _res = write(_fd, (buf), _len); \
- if (_res != _len) RPFATAL(_res, "Short write to %s, fd %d", fn, _fd); \
+ if (_res != _len) { \
+ \
+ RPFATAL(_res, "Short write to %s, fd %d (%d of %d bytes)", fn, _fd, \
+ _res, _len); \
+ \
+ } \
\
} while (0)
diff --git a/include/envs.h b/include/envs.h
index d7578045..15116fc1 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -26,6 +26,7 @@ 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",
@@ -48,8 +49,28 @@ static char *afl_environment_variables[] = {
"AFL_DUMB_FORKSRV",
"AFL_ENTRYPOINT",
"AFL_EXIT_WHEN_DONE",
+ "AFL_EXIT_ON_TIME",
+ "AFL_EXIT_ON_SEED_ISSUES",
"AFL_FAST_CAL",
"AFL_FORCE_UI",
+ "AFL_FRIDA_DEBUG_MAPS",
+ "AFL_FRIDA_EXCLUDE_RANGES",
+ "AFL_FRIDA_INST_DEBUG_FILE",
+ "AFL_FRIDA_INST_NO_OPTIMIZE",
+ "AFL_FRIDA_INST_NO_PREFETCH",
+ "AFL_FRIDA_INST_RANGES",
+ "AFL_FRIDA_INST_TRACE",
+ "AFL_FRIDA_OUTPUT_STDOUT",
+ "AFL_FRIDA_OUTPUT_STDERR",
+ "AFL_FRIDA_PERSISTENT_ADDR",
+ "AFL_FRIDA_PERSISTENT_CNT",
+ "AFL_FRIDA_PERSISTENT_DEBUG",
+ "AFL_FRIDA_PERSISTENT_HOOK",
+ "AFL_FRIDA_PERSISTENT_RET",
+ "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET",
+ "AFL_FRIDA_STATS_FILE",
+ "AFL_FRIDA_STATS_INTERVAL",
+ "AFL_FRIDA_STATS_TRANSITIONS",
"AFL_FUZZER_ARGS", // oss-fuzz
"AFL_GDB",
"AFL_GCC_ALLOWLIST",
@@ -105,8 +126,10 @@ static char *afl_environment_variables[] = {
"AFL_NGRAM_SIZE",
"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_STARTID",
"AFL_LLVM_LTO_DONTWRITEID",
"AFL_NO_ARITH",
@@ -130,6 +153,7 @@ static char *afl_environment_variables[] = {
"AFL_PASSTHROUGH",
"AFL_PATH",
"AFL_PERFORMANCE_FILE",
+ "AFL_PERSISTENT_RECORD",
"AFL_PRELOAD",
"AFL_TARGET_ENV",
"AFL_PYTHON_MODULE",
@@ -173,10 +197,13 @@ static char *afl_environment_variables[] = {
"AFL_USE_TRACE_PC",
"AFL_USE_UBSAN",
"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",
NULL
};
diff --git a/include/forkserver.h b/include/forkserver.h
index ac027f81..2baa6f0a 100644
--- a/include/forkserver.h
+++ b/include/forkserver.h
@@ -77,6 +77,10 @@ typedef struct afl_forkserver {
bool qemu_mode; /* if running in qemu mode or not */
+ bool frida_mode; /* if running in frida mode or not */
+
+ bool frida_asan; /* if running with asan in frida mode */
+
bool use_stdin; /* use stdin for sending data */
bool no_unlink; /* do not unlink cur_input */
@@ -94,6 +98,17 @@ typedef struct afl_forkserver {
char *cmplog_binary; /* the name of the cmplog binary */
+ /* persistent mode replay functionality */
+ u32 persistent_record; /* persistent replay setting */
+#ifdef AFL_PERSISTENT_RECORD
+ u32 persistent_record_idx; /* persistent replay cache ptr */
+ u32 persistent_record_cnt; /* persistent replay counter */
+ u8 * persistent_record_dir;
+ u8 **persistent_record_data;
+ u32 *persistent_record_len;
+ s32 persistent_record_pid;
+#endif
+
/* Function to kick off the forkserver child */
void (*init_child_func)(struct afl_forkserver *fsrv, char **argv);
diff --git a/instrumentation/LLVMInsTrim.so.cc b/instrumentation/LLVMInsTrim.so.cc
deleted file mode 100644
index 62de6ec5..00000000
--- a/instrumentation/LLVMInsTrim.so.cc
+++ /dev/null
@@ -1,599 +0,0 @@
-#include
-#include
-#include
-#include
-
-#include "llvm/Config/llvm-config.h"
-#if LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR < 5
-typedef long double max_align_t;
-#endif
-
-#include "llvm/ADT/DenseMap.h"
-#include "llvm/ADT/DenseSet.h"
-#if LLVM_VERSION_MAJOR > 3 || \
- (LLVM_VERSION_MAJOR == 3 && LLVM_VERSION_MINOR > 4)
- #include "llvm/IR/CFG.h"
- #include "llvm/IR/Dominators.h"
- #include "llvm/IR/DebugInfo.h"
-#else
- #include "llvm/Support/CFG.h"
- #include "llvm/Analysis/Dominators.h"
- #include "llvm/DebugInfo.h"
-#endif
-#include "llvm/IR/IRBuilder.h"
-#include "llvm/IR/Instructions.h"
-#include "llvm/IR/LegacyPassManager.h"
-#include "llvm/IR/Module.h"
-#include "llvm/Pass.h"
-#include "llvm/Support/raw_ostream.h"
-#include "llvm/Support/CommandLine.h"
-#include "llvm/Transforms/IPO/PassManagerBuilder.h"
-#include "llvm/Transforms/Utils/BasicBlockUtils.h"
-#include "llvm/IR/BasicBlock.h"
-#include
-#include
-#include
-#include
-#include
-
-#include "MarkNodes.h"
-#include "afl-llvm-common.h"
-#include "llvm-alternative-coverage.h"
-
-#include "config.h"
-#include "debug.h"
-
-using namespace llvm;
-
-static cl::opt MarkSetOpt("markset", cl::desc("MarkSet"),
- cl::init(false));
-static cl::opt LoopHeadOpt("loophead", cl::desc("LoopHead"),
- cl::init(false));
-
-namespace {
-
-struct InsTrim : public ModulePass {
-
- protected:
- uint32_t function_minimum_size = 1;
- char * skip_nozero = NULL;
-
- private:
- std::mt19937 generator;
- int total_instr = 0;
-
- unsigned int genLabel() {
-
- return generator() & (MAP_SIZE - 1);
-
- }
-
- public:
- static char ID;
-
- InsTrim() : ModulePass(ID), generator(0) {
-
- initInstrumentList();
-
- }
-
- void getAnalysisUsage(AnalysisUsage &AU) const override {
-
- AU.addRequired();
-
- }
-
-#if LLVM_VERSION_MAJOR < 4
- const char *
-#else
- StringRef
-#endif
- getPassName() const override {
-
- return "InstTrim Instrumentation";
-
- }
-
-#if LLVM_VERSION_MAJOR > 4 || \
- (LLVM_VERSION_MAJOR == 4 && LLVM_VERSION_PATCH >= 1)
- #define AFL_HAVE_VECTOR_INTRINSICS 1
-#endif
-
- bool runOnModule(Module &M) override {
-
- setvbuf(stdout, NULL, _IONBF, 0);
-
- if ((isatty(2) && !getenv("AFL_QUIET")) || getenv("AFL_DEBUG") != NULL) {
-
- SAYF(cCYA "LLVMInsTrim" VERSION cRST " by csienslab\n");
-
- } else
-
- be_quiet = 1;
-
- if (getenv("AFL_DEBUG") != NULL) debug = 1;
-
- LLVMContext &C = M.getContext();
-
- IntegerType *Int8Ty = IntegerType::getInt8Ty(C);
- IntegerType *Int32Ty = IntegerType::getInt32Ty(C);
-
-#if LLVM_VERSION_MAJOR < 9
- char *neverZero_counters_str;
- if ((neverZero_counters_str = getenv("AFL_LLVM_NOT_ZERO")) != NULL)
- if (!be_quiet) OKF("LLVM neverZero activated (by hexcoder)\n");
-#endif
- skip_nozero = getenv("AFL_LLVM_SKIP_NEVERZERO");
-
- if (getenv("AFL_LLVM_INSTRIM_LOOPHEAD") != NULL ||
- getenv("LOOPHEAD") != NULL) {
-
- LoopHeadOpt = true;
-
- }
-
- unsigned int PrevLocSize = 0;
- char * ngram_size_str = getenv("AFL_LLVM_NGRAM_SIZE");
- if (!ngram_size_str) ngram_size_str = getenv("AFL_NGRAM_SIZE");
- char *caller_str = getenv("AFL_LLVM_CALLER");
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- unsigned int ngram_size = 0;
- /* Decide previous location vector size (must be a power of two) */
- VectorType *PrevLocTy = NULL;
-
- if (ngram_size_str)
- if (sscanf(ngram_size_str, "%u", &ngram_size) != 1 || ngram_size < 2 ||
- ngram_size > NGRAM_SIZE_MAX)
- FATAL(
- "Bad value of AFL_NGRAM_SIZE (must be between 2 and NGRAM_SIZE_MAX "
- "(%u))",
- NGRAM_SIZE_MAX);
-
- if (ngram_size)
- PrevLocSize = ngram_size - 1;
- else
-#else
- if (ngram_size_str)
- #ifdef LLVM_VERSION_STRING
- FATAL(
- "Sorry, NGRAM branch coverage is not supported with llvm version %s!",
- LLVM_VERSION_STRING);
- #else
- #ifndef LLVM_VERSION_PATCH
- FATAL(
- "Sorry, NGRAM branch coverage is not supported with llvm version "
- "%d.%d.%d!",
- LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, 0);
- #else
- FATAL(
- "Sorry, NGRAM branch coverage is not supported with llvm version "
- "%d.%d.%d!",
- LLVM_VERSION_MAJOR, LLVM_VERSION_MINOR, LLVM_VERISON_PATCH);
- #endif
- #endif
-#endif
- PrevLocSize = 1;
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- // IntegerType *Int64Ty = IntegerType::getInt64Ty(C);
- int PrevLocVecSize = PowerOf2Ceil(PrevLocSize);
- IntegerType *IntLocTy =
- IntegerType::getIntNTy(C, sizeof(PREV_LOC_T) * CHAR_BIT);
- if (ngram_size)
- PrevLocTy = VectorType::get(IntLocTy, PrevLocVecSize
- #if LLVM_VERSION_MAJOR >= 12
- ,
- false
- #endif
- );
-#endif
-
- /* Get globals for the SHM region and the previous location. Note that
- __afl_prev_loc is thread-local. */
-
- GlobalVariable *AFLMapPtr =
- new GlobalVariable(M, PointerType::get(Int8Ty, 0), false,
- GlobalValue::ExternalLinkage, 0, "__afl_area_ptr");
- GlobalVariable *AFLPrevLoc;
- GlobalVariable *AFLContext = NULL;
- LoadInst * PrevCaller = NULL; // for CALLER sensitive coverage
-
- if (caller_str)
-#if defined(__ANDROID__) || defined(__HAIKU__)
- AFLContext = new GlobalVariable(
- M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx");
-#else
- AFLContext = new GlobalVariable(
- M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_ctx",
- 0, GlobalVariable::GeneralDynamicTLSModel, 0, false);
-#endif
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- if (ngram_size)
- #if defined(__ANDROID__) || defined(__HAIKU__)
- AFLPrevLoc = new GlobalVariable(
- M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
- /* Initializer */ nullptr, "__afl_prev_loc");
- #else
- AFLPrevLoc = new GlobalVariable(
- M, PrevLocTy, /* isConstant */ false, GlobalValue::ExternalLinkage,
- /* Initializer */ nullptr, "__afl_prev_loc",
- /* InsertBefore */ nullptr, GlobalVariable::GeneralDynamicTLSModel,
- /* AddressSpace */ 0, /* IsExternallyInitialized */ false);
- #endif
- else
-#endif
-#if defined(__ANDROID__) || defined(__HAIKU__)
- AFLPrevLoc = new GlobalVariable(
- M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc");
-#else
- AFLPrevLoc = new GlobalVariable(
- M, Int32Ty, false, GlobalValue::ExternalLinkage, 0, "__afl_prev_loc", 0,
- GlobalVariable::GeneralDynamicTLSModel, 0, false);
-#endif
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- /* Create the vector shuffle mask for updating the previous block history.
- Note that the first element of the vector will store cur_loc, so just set
- it to undef to allow the optimizer to do its thing. */
-
- SmallVector PrevLocShuffle = {UndefValue::get(Int32Ty)};
-
- for (unsigned I = 0; I < PrevLocSize - 1; ++I)
- PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, I));
-
- for (int I = PrevLocSize; I < PrevLocVecSize; ++I)
- PrevLocShuffle.push_back(ConstantInt::get(Int32Ty, PrevLocSize));
-
- Constant *PrevLocShuffleMask = ConstantVector::get(PrevLocShuffle);
-#endif
-
- // this is our default
- MarkSetOpt = true;
-
- ConstantInt *Zero = ConstantInt::get(Int8Ty, 0);
- ConstantInt *One = ConstantInt::get(Int8Ty, 1);
-
- u64 total_rs = 0;
- u64 total_hs = 0;
-
- scanForDangerousFunctions(&M);
-
- for (Function &F : M) {
-
- if (debug) {
-
- uint32_t bb_cnt = 0;
-
- for (auto &BB : F)
- if (BB.size() > 0) ++bb_cnt;
- DEBUGF("Function %s size %zu %u\n", F.getName().str().c_str(), F.size(),
- bb_cnt);
-
- }
-
- if (!isInInstrumentList(&F)) continue;
-
- // if the function below our minimum size skip it (1 or 2)
- if (F.size() < function_minimum_size) { continue; }
-
- std::unordered_set MS;
- if (!MarkSetOpt) {
-
- for (auto &BB : F) {
-
- MS.insert(&BB);
-
- }
-
- total_rs += F.size();
-
- } else {
-
- auto Result = markNodes(&F);
- auto RS = Result.first;
- auto HS = Result.second;
-
- MS.insert(RS.begin(), RS.end());
- if (!LoopHeadOpt) {
-
- MS.insert(HS.begin(), HS.end());
- total_rs += MS.size();
-
- } else {
-
- DenseSet> EdgeSet;
- DominatorTreeWrapperPass * DTWP =
- &getAnalysis(F);
- auto DT = &DTWP->getDomTree();
-
- total_rs += RS.size();
- total_hs += HS.size();
-
- for (BasicBlock *BB : HS) {
-
- bool Inserted = false;
- for (auto BI = pred_begin(BB), BE = pred_end(BB); BI != BE; ++BI) {
-
- auto Edge = BasicBlockEdge(*BI, BB);
- if (Edge.isSingleEdge() && DT->dominates(Edge, BB)) {
-
- EdgeSet.insert({*BI, BB});
- Inserted = true;
- break;
-
- }
-
- }
-
- if (!Inserted) {
-
- MS.insert(BB);
- total_rs += 1;
- total_hs -= 1;
-
- }
-
- }
-
- for (auto I = EdgeSet.begin(), E = EdgeSet.end(); I != E; ++I) {
-
- auto PredBB = I->first;
- auto SuccBB = I->second;
- auto NewBB =
- SplitBlockPredecessors(SuccBB, {PredBB}, ".split", DT, nullptr,
-#if LLVM_VERSION_MAJOR >= 8
- nullptr,
-#endif
- false);
- MS.insert(NewBB);
-
- }
-
- }
-
- for (BasicBlock &BB : F) {
-
- if (MS.find(&BB) == MS.end()) { continue; }
- IRBuilder<> IRB(&*BB.getFirstInsertionPt());
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- if (ngram_size) {
-
- LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
- PrevLoc->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- Value *ShuffledPrevLoc = IRB.CreateShuffleVector(
- PrevLoc, UndefValue::get(PrevLocTy), PrevLocShuffleMask);
- Value *UpdatedPrevLoc = IRB.CreateInsertElement(
- ShuffledPrevLoc, ConstantInt::get(Int32Ty, genLabel()),
- (uint64_t)0);
-
- IRB.CreateStore(UpdatedPrevLoc, AFLPrevLoc)
- ->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- } else
-
-#endif
- {
-
- IRB.CreateStore(ConstantInt::get(Int32Ty, genLabel()), AFLPrevLoc);
-
- }
-
- }
-
- }
-
- int has_calls = 0;
- for (BasicBlock &BB : F) {
-
- auto PI = pred_begin(&BB);
- auto PE = pred_end(&BB);
- IRBuilder<> IRB(&*BB.getFirstInsertionPt());
- Value * L = NULL;
- unsigned int cur_loc;
-
- // Context sensitive coverage
- if (caller_str && &BB == &F.getEntryBlock()) {
-
- PrevCaller = IRB.CreateLoad(AFLContext);
- PrevCaller->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- // does the function have calls? and is any of the calls larger than
- // one basic block?
- has_calls = 0;
- for (auto &BB2 : F) {
-
- if (has_calls) break;
- for (auto &IN : BB2) {
-
- CallInst *callInst = nullptr;
- if ((callInst = dyn_cast(&IN))) {
-
- Function *Callee = callInst->getCalledFunction();
- if (!Callee || Callee->size() < function_minimum_size)
- continue;
- else {
-
- has_calls = 1;
- break;
-
- }
-
- }
-
- }
-
- }
-
- // if yes we store a context ID for this function in the global var
- if (has_calls) {
-
- ConstantInt *NewCtx = ConstantInt::get(Int32Ty, genLabel());
- StoreInst * StoreCtx = IRB.CreateStore(NewCtx, AFLContext);
- StoreCtx->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- }
-
- } // END of caller_str
-
- if (MarkSetOpt && MS.find(&BB) == MS.end()) { continue; }
-
- if (PI == PE) {
-
- cur_loc = genLabel();
- L = ConstantInt::get(Int32Ty, cur_loc);
-
- } else {
-
- auto *PN = PHINode::Create(Int32Ty, 0, "", &*BB.begin());
- DenseMap PredMap;
- for (PI = pred_begin(&BB), PE = pred_end(&BB); PI != PE; ++PI) {
-
- BasicBlock *PBB = *PI;
- auto It = PredMap.insert({PBB, genLabel()});
- unsigned Label = It.first->second;
- // cur_loc = Label;
- PN->addIncoming(ConstantInt::get(Int32Ty, Label), PBB);
-
- }
-
- L = PN;
-
- }
-
- /* Load prev_loc */
- LoadInst *PrevLoc = IRB.CreateLoad(AFLPrevLoc);
- PrevLoc->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
- Value *PrevLocTrans;
-
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- /* "For efficiency, we propose to hash the tuple as a key into the
- hit_count map as (prev_block_trans << 1) ^ curr_block_trans, where
- prev_block_trans = (block_trans_1 ^ ... ^ block_trans_(n-1)" */
-
- if (ngram_size)
- PrevLocTrans =
- IRB.CreateZExt(IRB.CreateXorReduce(PrevLoc), IRB.getInt32Ty());
- else
-#endif
- PrevLocTrans = IRB.CreateZExt(PrevLoc, IRB.getInt32Ty());
-
- if (caller_str)
- PrevLocTrans =
- IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, PrevCaller), Int32Ty);
-
- /* Load SHM pointer */
- LoadInst *MapPtr = IRB.CreateLoad(AFLMapPtr);
- MapPtr->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
- Value *MapPtrIdx;
-#ifdef AFL_HAVE_VECTOR_INTRINSICS
- if (ngram_size)
- MapPtrIdx = IRB.CreateGEP(
- MapPtr, IRB.CreateZExt(IRB.CreateXor(PrevLocTrans, L), Int32Ty));
- else
-#endif
- MapPtrIdx = IRB.CreateGEP(MapPtr, IRB.CreateXor(PrevLocTrans, L));
-
- /* Update bitmap */
- LoadInst *Counter = IRB.CreateLoad(MapPtrIdx);
- Counter->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
- Value *Incr = IRB.CreateAdd(Counter, One);
-
-#if LLVM_VERSION_MAJOR < 9
- if (neverZero_counters_str !=
- NULL) // with llvm 9 we make this the default as the bug in llvm is
- // then fixed
-#else
- if (!skip_nozero)
-#endif
- {
-
- /* hexcoder: Realize a counter that skips zero during overflow.
- * Once this counter reaches its maximum value, it next increments to
- * 1
- *
- * Instead of
- * Counter + 1 -> Counter
- * we inject now this
- * Counter + 1 -> {Counter, OverflowFlag}
- * Counter + OverflowFlag -> Counter
- */
- auto cf = IRB.CreateICmpEQ(Incr, Zero);
- auto carry = IRB.CreateZExt(cf, Int8Ty);
- Incr = IRB.CreateAdd(Incr, carry);
-
- }
-
- IRB.CreateStore(Incr, MapPtrIdx)
- ->setMetadata(M.getMDKindID("nosanitize"), MDNode::get(C, None));
-
- if (caller_str && has_calls) {
-
- // in CALLER mode we have to restore the original context for the
- // caller - she might be calling other functions which need the
- // correct CALLER
- Instruction *Inst = BB.getTerminator();
- if (isa(Inst) || isa(Inst)) {
-
- IRBuilder<> Post_IRB(Inst);
- StoreInst * RestoreCtx =
- Post_IRB.CreateStore(PrevCaller, AFLContext);
- RestoreCtx->setMetadata(M.getMDKindID("nosanitize"),
- MDNode::get(C, None));
-
- }
-
- }
-
- total_instr++;
-
- }
-
- }
-
- if (!be_quiet) {
-
- char modeline[100];
- snprintf(modeline, sizeof(modeline), "%s%s%s%s%s",
- getenv("AFL_HARDEN") ? "hardened" : "non-hardened",
- getenv("AFL_USE_ASAN") ? ", ASAN" : "",
- getenv("AFL_USE_MSAN") ? ", MSAN" : "",
- getenv("AFL_USE_CFISAN") ? ", CFISAN" : "",
- getenv("AFL_USE_UBSAN") ? ", UBSAN" : "");
-
- OKF("Instrumented %d locations (%llu, %llu) (%s mode)\n", total_instr,
- total_rs, total_hs, modeline);
-
- }
-
- return false;
-
- }
-
-}; // end of struct InsTrim
-
-} // end of anonymous namespace
-
-char InsTrim::ID = 0;
-
-static void registerAFLPass(const PassManagerBuilder &,
- legacy::PassManagerBase &PM) {
-
- PM.add(new InsTrim());
-
-}
-
-static RegisterStandardPasses RegisterAFLPass(
- PassManagerBuilder::EP_OptimizerLast, registerAFLPass);
-
-static RegisterStandardPasses RegisterAFLPass0(
- PassManagerBuilder::EP_EnabledOnOptLevel0, registerAFLPass);
-
diff --git a/instrumentation/MarkNodes.cc b/instrumentation/MarkNodes.cc
deleted file mode 100644
index b77466d9..00000000
--- a/instrumentation/MarkNodes.cc
+++ /dev/null
@@ -1,481 +0,0 @@
-#include
-#include