diff options
111 files changed, 1487 insertions, 2469 deletions
diff --git a/GNUmakefile.llvm b/GNUmakefile.llvm index 83eb91a9..b7153fd3 100644 --- a/GNUmakefile.llvm +++ b/GNUmakefile.llvm @@ -45,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 '^[0-2]\.|^3.[0-7]\.' && 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 ) @@ -61,7 +61,7 @@ ifeq "$(LLVMVER)" "" endif ifeq "$(LLVM_UNSUPPORTED)" "1" - $(error llvm_mode only supports llvm from version 3.8 onwards) + $(error llvm_mode only supports llvm from version 6.0 onwards) endif ifeq "$(LLVM_TOO_NEW)" "1" @@ -306,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 ./cmplog-switches-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 +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)" "" diff --git a/README.md b/README.md index 8fcc31ff..2facedb6 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ <img align="right" src="https://raw.githubusercontent.com/andreafioraldi/AFLplusplus-website/master/static/logo_256x256.png" alt="AFL++ Logo"> - Release Version: [3.14c](https://github.com/AFLplusplus/AFLplusplus/releases) + Release Version: [3.13c](https://github.com/AFLplusplus/AFLplusplus/releases) - Github Version: 3.15a + Github Version: 3.14a Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) @@ -25,22 +25,12 @@ For comparisons use the fuzzbench `aflplusplus` setup, or use `afl-clang-fast` with `AFL_LLVM_CMPLOG=1`. -## Major behaviour changes in afl++ 3.00 onwards: +## 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.15 we introduced the following changes from previous behaviours: - * Also -M main mode does not do deterministic fuzzing by default anymore - * afl-cmin and afl-showmap -Ci now descent into subdirectories like - afl-fuzz -i does (but note that afl-cmin.bash does not) - -With afl++ 3.14 we introduced the following changes from previous behaviours: - * afl-fuzz: deterministic fuzzing it not a default for -M main anymore - * afl-cmin/afl-showmap -i now descends into subdirectories (afl-cmin.bash - however does not) - 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 with the value given being the maximum timeout. The original meaning of @@ -93,24 +83,24 @@ behaviours and defaults: ## Important features of afl++ - afl++ supports llvm from 3.8 up to version 12, very fast binary fuzzing with QEMU 5.1 + 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 | 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]/arm64 | x86[_64]/arm[64] | x | - | LAF-Intel / CompCov | | x | | | x86[_64]/arm[64] | x86[_64]/arm[64] | - | CmpLog | | x | | x86[_64]/arm64 | 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 | x86[_64]/arm64 | x | x | + | 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 previous llvm versions 2. GCC creates non-performant code, hence it is disabled in gcc_plugin @@ -118,7 +108,7 @@ behaviours and defaults: 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 v4.1 - 7. automatic in LTO mode with LLVM 11 and newer, an extra pass for all LLVM versions that write to a file to use with afl-fuzz' `-x` + 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: @@ -305,7 +295,7 @@ anything below 9 is not recommended. | v +---------------------------------+ -| clang/clang++ 3.8+ 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/++ @@ -704,7 +694,7 @@ 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`) + 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 @@ -944,12 +934,12 @@ 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`) + * 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, zafl, etc. +use a binary rewriter like afl-dyninst, retrowrite, zaflr, etc. For Qemu and Frida mode, check out the persistent mode, it gives a huge speed improvement if it is possible to use. diff --git a/TODO.md b/TODO.md index 1c616b4a..8b5aec5b 100644 --- a/TODO.md +++ b/TODO.md @@ -2,6 +2,7 @@ ## Roadmap 3.00+ + - align map to 64 bytes but keep real IDs - Update afl->pending_not_fuzzed for MOpt - put fuzz target in top line of UI - afl-plot to support multiple plot_data diff --git a/afl-cmin b/afl-cmin index e6f8c175..e71873d3 100755 --- a/afl-cmin +++ b/afl-cmin @@ -122,7 +122,6 @@ function usage() { "AFL_FORKSRV_INIT_TMOUT: time the fuzzer waits for the forkserver to come up\n" \ "AFL_KEEP_TRACES: leave the temporary <out_dir>/.traces directory\n" \ "AFL_KILL_SIGNAL: Signal delivered to child processes on timeout (default: SIGKILL)\n" \ -"AFL_NO_FORKSRV: run target via execve instead of using the forkserver\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" \ diff --git a/afl-plot b/afl-plot index 662c0907..60a351ab 100755 --- a/afl-plot +++ b/afl-plot @@ -127,7 +127,7 @@ set key outside set autoscale xfixmin set autoscale xfixmax -set xlabel "relative time in seconds" font "small" +#set xlabel "all times in UTC" font "small" 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, \\ diff --git a/docs/Changelog.md b/docs/Changelog.md index fcfd2ce8..1887c099 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,43 +8,6 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to <afl-users+subscribe@googlegroups.com>. -### Version ++3.14c (release) - - afl-fuzz: - - fix -F when a '/' was part of the parameter - - fixed a crash for cmplog for very slow inputs - - fix for AFLfast schedule counting - - removed implied -D determinstic from -M main - - if the target becomes unavailable check out out/default/error.txt - for an indicator why - - AFL_CAL_FAST was a dead env, now does the same as AFL_FAST_CAL - - reverse read the queue on resumes (more effective) - - fix custom mutator trimming - - afl-cc: - - Update to COMPCOV/laf-intel that speeds up the instrumentation - process a lot - thanks to Michael Rodler/f0rki for the PR! - - Fix for failures for some sized string instrumentations - - Fix to instrument global namespace functions in c++ - - Fix for llvm 13 - - support partial linking - - do honor AFL_LLVM_{ALLOW/DENY}LIST for LTO autodictionary and DICT2FILE - - We do support llvm versions from 3.8 to 5.0 again - - frida_mode: - - several fixes for cmplog - - remove need for AFL_FRIDA_PERSISTENT_RETADDR_OFFSET - - less coverage collision - - feature parity of aarch64 with intel now (persistent, cmplog, - in-memory testcases, asan) - - afl-cmin and afl-showmap -i do now descend into subdirectories - (like afl-fuzz does) - note that afl-cmin.bash does not! - - afl_analyze: - - fix timeout handling - - add forkserver support for better performance - - ensure afl-compiler-rt is built for gcc_module - - always build aflpp_driver for libfuzzer harnesses - - added `AFL_NO_FORKSRV` env variable support to - afl-cmin, afl-tmin, and afl-showmap, by @jhertz - - removed outdated documents, improved existing documentation - ### 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, diff --git a/docs/INSTALL.md b/docs/INSTALL.md index fc57f546..32616958 100644 --- a/docs/INSTALL.md +++ b/docs/INSTALL.md @@ -130,6 +130,41 @@ 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. +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 <running system> 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/ideas.md b/docs/ideas.md index 0ee69851..e25d3ba6 100644 --- a/docs/ideas.md +++ b/docs/ideas.md @@ -34,12 +34,6 @@ Mentor: any Other programming languages also use llvm hence they could (easily?) supported for fuzzing, e.g. mono, swift, go, kotlin native, fortran, ... -GCC also supports: Objective-C, Fortran, Ada, Go, and D -(according to [Gcc homepage](https://gcc.gnu.org/)) - -LLVM is also used by: Rust, LLGo (Go), kaleidoscope (Haskell), flang (Fortran), emscripten (JavaScript, WASM), ilwasm (CIL (C#)) -(according to [LLVM frontends](https://gist.github.com/axic/62d66fb9d8bccca6cc48fa9841db9241)) - Mentor: vanhauser-thc ## Machine Learning diff --git a/dynamic_list.txt b/dynamic_list.txt index 7293ae77..afb5d91e 100644 --- a/dynamic_list.txt +++ b/dynamic_list.txt @@ -27,8 +27,16 @@ "__afl_selective_coverage"; "__afl_selective_coverage_start_off"; "__afl_selective_coverage_temp"; + "__afl_coverage_discard"; + "__afl_coverage_skip"; + "__afl_coverage_on"; + "__afl_coverage_off"; + "__afl_coverage_interesting"; + "__afl_fuzz_len"; + "__afl_fuzz_ptr"; "__afl_sharedmem_fuzzing"; - "__afl_trace"; + "__sanitizer_cov_trace_pc_guard"; + "__sanitizer_cov_trace_pc_guard_init"; "__cmplog_ins_hook1"; "__cmplog_ins_hook16"; "__cmplog_ins_hook2"; diff --git a/frida_mode/.gitignore b/frida_mode/.gitignore index 32cca51f..956b9911 100644 --- a/frida_mode/.gitignore +++ b/frida_mode/.gitignore @@ -3,5 +3,3 @@ frida_test.dat qemu_test.dat frida_out/** qemu_out/** -ts/dist/ -ts/node_modules/ diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index fad183e1..a0387cac 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -6,11 +6,6 @@ INCLUDES:=$(wildcard $(INC_DIR)*.h) BUILD_DIR:=$(PWD)build/ OBJ_DIR:=$(BUILD_DIR)obj/ -JS_DIR:=$(SRC_DIR)js/ -JS_NAME:=api.js -JS:=$(JS_DIR)$(JS_NAME) -JS_SRC:=$(BUILD_DIR)api.c -JS_OBJ:=$(BUILD_DIR)api.o SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c) OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src)))) CFLAGS+=-fPIC \ @@ -19,19 +14,18 @@ CFLAGS+=-fPIC \ -g \ -O3 \ -funroll-loops \ - -ffunction-sections \ -AFL_CFLAGS:=-Wno-unused-parameter \ +RT_CFLAGS:=-Wno-unused-parameter \ -Wno-sign-compare \ -Wno-unused-function \ -Wno-unused-result \ -Wno-int-to-pointer-cast \ - -Wno-pointer-sign LDFLAGS+=-shared \ -lpthread \ -lresolv \ - -ldl + -ldl \ + -z noexecstack \ ifdef DEBUG CFLAGS+=-Werror \ @@ -53,10 +47,6 @@ ifeq "$(ARCH)" "aarch64" ARCH:=arm64 endif -ifeq "$(ARCH)" "armv7l" - ARCH:=armhf -endif - ifeq "$(ARCH)" "i686" ARCH:=x86 endif @@ -64,15 +54,11 @@ endif ifeq "$(shell uname)" "Darwin" OS:=macos - AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-deprecated-declarations + RT_CFLAGS:=$(RT_CFLAGS) -Wno-deprecated-declarations else ifdef DEBUG - AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor + RT_CFLAGS:=$(RT_CFLAGS) -Wno-prio-ctor-dtor endif -LDFLAGS+= -z noexecstack \ - -Wl,--gc-sections \ - -Wl,--exclude-libs,ALL -LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map endif ifeq "$(shell uname)" "Linux" @@ -83,52 +69,30 @@ ifndef OS $(error "Operating system unsupported") endif -ifeq "$(ARCH)" "arm64" -# 15.0.0 Not released for aarch64 yet -GUM_DEVKIT_VERSION=14.2.18 -else -ifeq "$(ARCH)" "armhf" GUM_DEVKIT_VERSION=14.2.18 -else -GUM_DEVKIT_VERSION=15.0.0 -endif -endif -GUM_DEVKIT_FILENAME=frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar.xz +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-gumjs.a -GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gumjs.h +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-gumjs-1.0.a +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-gumjs.h -FRIDA_GUM_DEVKIT_TARBALL:=$(FRIDA_DIR)build/frida-gumjs-devkit-$(GUM_DEVKIT_VERSION)-$(OS)-$(ARCH).tar +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 -AFL_PERFORMANCE_SRC:=$(ROOT)src/afl-performance.c -AFL_PERFORMANCE_OBJ:=$(OBJ_DIR)afl-performance.o - -HOOK_DIR:=$(PWD)hook/ -AFLPP_FRIDA_DRIVER_HOOK_SRC=$(HOOK_DIR)frida_hook.c -AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(BUILD_DIR)frida_hook.so - -AFLPP_QEMU_DRIVER_HOOK_SRC:=$(HOOK_DIR)qemu_hook.c -AFLPP_QEMU_DRIVER_HOOK_OBJ:=$(BUILD_DIR)qemu_hook.so - -BIN2C:=$(BUILD_DIR)bin2c -BIN2C_SRC:=$(PWD)util/bin2c.c - -.PHONY: all 32 clean format hook $(FRIDA_GUM) +.PHONY: all 32 clean format $(FRIDA_GUM) ############################## ALL ############################################# -all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) +all: $(FRIDA_TRACE) 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all @@ -148,7 +112,7 @@ $(FRIDA_GUM): $(FRIDA_MAKEFILE) cd $(FRIDA_DIR) && make gum-linux-$(ARCH) $(FRIDA_GUM_DEVKIT_HEADER): $(FRIDA_GUM) - $(FRIDA_DIR)releng/devkit.py frida-gumjs linux-$(ARCH) $(FRIDA_DIR)build/gum-devkit/ + $(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) . @@ -169,48 +133,22 @@ $(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR) wget -O $@ $(GUM_DEVKIT_URL) endif -$(GUM_DEVIT_LIBRARY): $(GUM_DEVKIT_TARBALL) - tar Jxvfm $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR) +$(GUM_DEVIT_LIBRARY): | $(GUM_DEVKIT_TARBALL) + tar Jxvf $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR) -$(GUM_DEVIT_HEADER): $(GUM_DEVKIT_TARBALL) - tar Jxvfm $(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) \ - $(AFL_CFLAGS) \ - -I $(ROOT) \ - -I $(ROOT)include \ - -o $@ \ - -c $< - -$(AFL_PERFORMANCE_OBJ): $(AFL_PERFORMANCE_SRC) - $(CC) \ - $(CFLAGS) \ - $(AFL_CFLAGS) \ + $(RT_CFLAGS) \ -I $(ROOT) \ -I $(ROOT)include \ -o $@ \ -c $< -############################### JS ############################################# - -$(BIN2C): $(BIN2C_SRC) - $(CC) -D_GNU_SOURCE -o $@ $< - -$(JS_SRC): $(JS) $(BIN2C)| $(BUILD_DIR) - cd $(JS_DIR) && $(BIN2C) api_js $(JS) $@ - -$(JS_OBJ): $(JS_SRC) GNUmakefile - $(CC) \ - $(CFLAGS) \ - -I $(ROOT)include \ - -I $(FRIDA_BUILD_DIR) \ - -I $(INC_DIR) \ - -c $< \ - -o $@ - ############################# SOURCE ########################################### define BUILD_SOURCE @@ -228,36 +166,23 @@ $(foreach src,$(SOURCES),$(eval $(call BUILD_SOURCE,$(src),$(OBJ_DIR)$(notdir $( ######################## AFL-FRIDA-TRACE ####################################### -$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL_COMPILER_RT_OBJ) $(AFL_PERFORMANCE_OBJ) GNUmakefile | $(BUILD_DIR) - $(CXX) \ +$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR) + $(CC) \ $(OBJS) \ - $(JS_OBJ) \ $(GUM_DEVIT_LIBRARY) \ $(AFL_COMPILER_RT_OBJ) \ - $(AFL_PERFORMANCE_OBJ) \ $(LDFLAGS) \ - $(LDSCRIPT) \ -o $@ \ cp -v $(FRIDA_TRACE) $(ROOT) -############################# HOOK ############################################# - -$(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR) - $(CC) $(CFLAGS) $(LDFLAGS) -I $(FRIDA_BUILD_DIR) $< -o $@ - -$(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR) - $(CC) $(CFLAGS) $(LDFLAGS) $< -o $@ - -hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) - ############################# CLEAN ############################################ clean: rm -rf $(BUILD_DIR) ############################# FORMAT ########################################### format: - cd $(ROOT) && echo $(SOURCES) $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(BIN2C_SRC) | xargs -L1 ./.custom-format.py -i + 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 index 1922c7e6..6cd1a64e 100644 --- a/frida_mode/Makefile +++ b/frida_mode/Makefile @@ -11,6 +11,3 @@ clean: format: @gmake format - -hook: - @gmake hook diff --git a/frida_mode/README.md b/frida_mode/README.md index 3009e171..0103a395 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -21,16 +21,16 @@ perhaps leverage some of its design and implementation. | Feature/Instrumentation | frida-mode | Notes | | -------------------------|:----------:|:--------------------------------------------:| | NeverZero | x | | - | Persistent Mode | x | (x86/x64/aarch64 only) | + | Persistent Mode | x | (x86/x64 only)(Only on function boundaries) | | LAF-Intel / CompCov | - | (CMPLOG is better 90% of the time) | - | CMPLOG | x | (x86/x64/aarch64 only) | + | 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/aarch64 only) | + | In-Memory Test Cases | x | (x86/x64 only) | ## Compatibility Currently FRIDA mode supports Linux and macOS targets on both x86/x64 @@ -75,13 +75,10 @@ following options are currently supported: * `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`. -## Scripting - -One of the more powerful features of FRIDA mode is it's support for configuration by JavaScript, rather than using environment variables. For details of how this works see [here](Scripting.md). - ## Performance Additionally, the intention is to be able to make a direct performance @@ -153,29 +150,22 @@ Generated block 0x7ffff75e98e2 *** ``` -* `AFL_FRIDA_INST_JIT` - Enable the instrumentation of Just-In-Time compiled -code. Code is considered to be JIT if the executable segment is not backed by a -file. * `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_SEED` - Sets the initial seed for the hash function used to -generate block (and hence edge) IDs. Setting this to a constant value may be -useful for debugging purposes, e.g. investigating unstable edges. -* `AFL_FRIDA_INST_TRACE` - Log to stdout the address of executed blocks, -implies `AFL_FRIDA_INST_NO_OPTIMIZE`. -* `AFL_FRIDA_INST_TRACE_UNIQUE` - As per `AFL_FRIDA_INST_TRACE`, but each edge -is logged only once, requires `AFL_FRIDA_INST_NO_OPTIMIZE`. +* `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 detect issues in the persistent loop using a debugger. +to determine the value of `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` using a +debugger. ``` @@ -296,13 +286,9 @@ FASAN then adds instrumentation for any instrucutions which use memory operands then calls into the `__asan_loadN` and `__asan_storeN` functions provided by the DSO to validate memory accesses against the shadow memory. -# Collisions -FRIDA mode has also introduced some improvements to reduce collisions in the map. -See [here](MapDensity.md) for details. - ## TODO -The next features to be added are Aarch32 support as well as looking at +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 index 67d33591..7a8726e0 100644 --- a/frida_mode/include/asan.h +++ b/frida_mode/include/asan.h @@ -1,11 +1,10 @@ #ifndef _ASAN_H #define _ASAN_H -#include "frida-gumjs.h" +#include "frida-gum.h" extern gboolean asan_initialized; -void asan_config(void); void asan_init(void); void asan_arch_init(void); void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator); diff --git a/frida_mode/include/ctx.h b/frida_mode/include/ctx.h index c669478e..cbcc892a 100644 --- a/frida_mode/include/ctx.h +++ b/frida_mode/include/ctx.h @@ -1,17 +1,10 @@ #ifndef _CTX_H #define _CTX_H -#include "frida-gumjs.h" +#include "frida-gum.h" -#if defined(__x86_64__) -gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg); -#elif defined(__i386__) -gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg); -#elif defined(__aarch64__) -gsize ctx_read_reg(GumArm64CpuContext *ctx, arm64_reg reg); -size_t ctx_get_size(const cs_insn *instr, cs_arm64_op *operand); -#elif defined(__arm__) -gsize ctx_read_reg(GumArmCpuContext *ctx, arm_reg reg); +#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 index cbc5c8c7..967831af 100644 --- a/frida_mode/include/entry.h +++ b/frida_mode/include/entry.h @@ -1,16 +1,13 @@ #ifndef _ENTRY_H #define _ENTRY_H -#include "frida-gumjs.h" +#include "frida-gum.h" -extern guint64 entry_point; -extern gboolean entry_reached; - -void entry_config(void); +extern guint64 entry_start; void entry_init(void); -void entry_start(void); +void entry_run(void); void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output); diff --git a/frida_mode/include/frida_cmplog.h b/frida_mode/include/frida_cmplog.h index a665e970..b620a472 100644 --- a/frida_mode/include/frida_cmplog.h +++ b/frida_mode/include/frida_cmplog.h @@ -3,7 +3,6 @@ extern struct cmp_map *__afl_cmp_map; -void cmplog_config(void); void cmplog_init(void); /* Functions to be implemented by the different architectures */ diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index 29f14da9..ed92c25a 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -1,24 +1,13 @@ #ifndef _INSTRUMENT_H #define _INSTRUMENT_H -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" -extern char * instrument_debug_filename; -extern gboolean instrument_tracing; -extern gboolean instrument_optimize; -extern gboolean instrument_unique; -extern __thread guint64 instrument_previous_pc; -extern guint64 instrument_hash_zero; - -extern gboolean instrument_use_fixed_seed; -extern guint64 instrument_fixed_seed; - -extern uint8_t *__afl_area_ptr; -extern uint32_t __afl_map_size; - -void instrument_config(void); +extern __thread uint64_t previous_pc; +extern uint8_t * __afl_area_ptr; +extern uint32_t __afl_map_size; void instrument_init(void); @@ -30,17 +19,9 @@ gboolean instrument_is_coverage_optimize_supported(void); void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output); -void instrument_debug_config(void); -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); -void instrument_flush(GumStalkerOutput *output); -gpointer instrument_cur(GumStalkerOutput *output); - -void instrument_on_fork(); - -guint64 instrument_get_offset_hash(GumAddress current_rip); - +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 index a9d56e4e..237aecb0 100644 --- a/frida_mode/include/lib.h +++ b/frida_mode/include/lib.h @@ -1,9 +1,7 @@ #ifndef _LIB_H #define _LIB_H -#include "frida-gumjs.h" - -void lib_config(void); +#include "frida-gum.h" void lib_init(void); diff --git a/frida_mode/include/output.h b/frida_mode/include/output.h index 743b2fe6..53a9fdd3 100644 --- a/frida_mode/include/output.h +++ b/frida_mode/include/output.h @@ -1,12 +1,8 @@ #ifndef _OUTPUT_H #define _OUTPUT_H -#include "frida-gumjs.h" +#include "frida-gum.h" -extern char *output_stdout; -extern char *output_stderr; - -void output_config(void); void output_init(void); #endif diff --git a/frida_mode/include/persistent.h b/frida_mode/include/persistent.h index c79f0143..25b44ab0 100644 --- a/frida_mode/include/persistent.h +++ b/frida_mode/include/persistent.h @@ -2,7 +2,7 @@ #ifndef _PERSISTENT_H #define _PERSISTENT_H -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" typedef struct arch_api_regs api_regs; @@ -19,10 +19,9 @@ 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 persistent_hook; - -void persistent_config(void); +extern afl_persistent_hook_fn hook; void persistent_init(void); @@ -30,10 +29,7 @@ void persistent_init(void); gboolean persistent_is_supported(void); void persistent_prologue(GumStalkerOutput *output); -void persistent_prologue_arch(GumStalkerOutput *output); - void persistent_epilogue(GumStalkerOutput *output); -void persistent_epilogue_arch(GumStalkerOutput *output); #endif diff --git a/frida_mode/include/prefetch.h b/frida_mode/include/prefetch.h index 835d5e8a..8f0cee68 100644 --- a/frida_mode/include/prefetch.h +++ b/frida_mode/include/prefetch.h @@ -1,11 +1,8 @@ #ifndef _PREFETCH_H #define _PREFETCH_H -#include "frida-gumjs.h" +#include "frida-gum.h" -extern gboolean prefetch_enable; - -void prefetch_config(void); void prefetch_init(void); void prefetch_write(void *addr); void prefetch_read(void); diff --git a/frida_mode/include/ranges.h b/frida_mode/include/ranges.h index 2eb9b355..c623f473 100644 --- a/frida_mode/include/ranges.h +++ b/frida_mode/include/ranges.h @@ -1,21 +1,13 @@ #ifndef _RANGES_H #define _RANGES_H -#include "frida-gumjs.h" +#include "frida-gum.h" -extern gboolean ranges_debug_maps; -extern gboolean ranges_inst_libs; -extern gboolean ranges_inst_jit; - -void ranges_config(void); void ranges_init(void); gboolean range_is_excluded(gpointer address); void ranges_exclude(); -void ranges_add_include(GumMemoryRange *range); -void ranges_add_exclude(GumMemoryRange *range); - #endif diff --git a/frida_mode/include/stalker.h b/frida_mode/include/stalker.h index b5e05d5a..186ead11 100644 --- a/frida_mode/include/stalker.h +++ b/frida_mode/include/stalker.h @@ -1,13 +1,11 @@ #ifndef _STALKER_H #define _STALKER_H -#include "frida-gumjs.h" +#include "frida-gum.h" -void stalker_config(void); void stalker_init(void); GumStalker *stalker_get(void); void stalker_start(void); -void stalker_trust(void); #endif diff --git a/frida_mode/include/stats.h b/frida_mode/include/stats.h index cd2350ea..4271132a 100644 --- a/frida_mode/include/stats.h +++ b/frida_mode/include/stats.h @@ -1,7 +1,7 @@ #ifndef _STATS_H #define _STATS_H -#include "frida-gumjs.h" +#include "frida-gum.h" typedef struct { @@ -15,11 +15,6 @@ typedef struct { extern stats_data_header_t *stats_data; -extern char * stats_filename; -extern guint64 stats_interval; -extern gboolean stats_transitions; - -void stats_config(void); void stats_init(void); void stats_collect(const cs_insn *instr, gboolean begin); void stats_print(char *format, ...); @@ -28,7 +23,6 @@ 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); -void stats_on_fork(void); #endif diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h index 525e9d40..7b443b5e 100644 --- a/frida_mode/include/util.h +++ b/frida_mode/include/util.h @@ -1,7 +1,7 @@ #ifndef _UTIL_H #define _UTIL_H -#include "frida-gumjs.h" +#include "frida-gum.h" #define UNUSED_PARAMETER(x) (void)(x) #define IGNORED_RETURN(x) (void)!(x) diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c index b2e763ca..f78f690c 100644 --- a/frida_mode/src/asan/asan.c +++ b/frida_mode/src/asan/asan.c @@ -1,18 +1,18 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "asan.h" -static gboolean asan_enabled = FALSE; -gboolean asan_initialized = FALSE; +gboolean asan_initialized = FALSE; -void asan_config(void) { +void asan_init(void) { if (getenv("AFL_USE_FASAN") != NULL) { OKF("Frida ASAN mode enabled"); - asan_enabled = TRUE; + asan_arch_init(); + asan_initialized = TRUE; } else { @@ -22,14 +22,3 @@ void asan_config(void) { } -void asan_init(void) { - - if (asan_enabled) { - - asan_arch_init(); - asan_initialized = TRUE; - - } - -} - 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 index 65524e03..6262ee18 100644 --- a/frida_mode/src/asan/asan_arm64.c +++ b/frida_mode/src/asan/asan_arm64.c @@ -1,80 +1,18 @@ -#include <dlfcn.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "asan.h" -#include "ctx.h" #include "util.h" #if defined(__aarch64__) - -typedef struct { - - size_t size; - cs_arm64_op operand; - -} asan_ctx_t; - -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) { - - asan_ctx_t * asan_ctx = (asan_ctx_t *)user_data; - cs_arm64_op * operand = &asan_ctx->operand; - arm64_op_mem *mem = &operand->mem; - gsize base = 0; - gsize index = 0; - gsize address; - - if (mem->base != ARM64_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); } - - if (mem->index != ARM64_REG_INVALID) { - - index = ctx_read_reg(ctx, mem->index); - - } - - address = base + index + mem->disp; - - if ((operand->access & CS_AC_READ) == CS_AC_READ) { - - asan_loadN(address, asan_ctx->size); - - } - - if ((operand->access & CS_AC_WRITE) == CS_AC_WRITE) { - - asan_storeN(address, asan_ctx->size); - - } - -} - void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { + UNUSED_PARAMETER(instr); UNUSED_PARAMETER(iterator); + if (asan_initialized) { - cs_arm64 arm64 = instr->detail->arm64; - cs_arm64_op *operand; - asan_ctx_t * ctx; - - if (!asan_initialized) return; - - for (uint8_t i = 0; i < arm64.op_count; i++) { - - operand = &arm64.operands[i]; - - if (operand->type != ARM64_OP_MEM) { continue; } - - ctx = g_malloc0(sizeof(asan_ctx_t)); - ctx->size = ctx_get_size(instr, &arm64.operands[0]); - memcpy(&ctx->operand, operand, sizeof(cs_arm64_op)); - gum_stalker_iterator_put_callout(iterator, asan_callout, ctx, g_free); + FATAL("ASAN mode not supported on this architecture"); } @@ -82,13 +20,7 @@ void asan_instrument(const cs_insn *instr, GumStalkerIterator *iterator) { 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'"); - - } + FATAL("ASAN mode not supported on this architecture"); } diff --git a/frida_mode/src/asan/asan_x64.c b/frida_mode/src/asan/asan_x64.c index 5c12669f..a2eabe3c 100644 --- a/frida_mode/src/asan/asan_x64.c +++ b/frida_mode/src/asan/asan_x64.c @@ -1,5 +1,5 @@ #include <dlfcn.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" diff --git a/frida_mode/src/asan/asan_x86.c b/frida_mode/src/asan/asan_x86.c index 6d2f9e2b..8490b490 100644 --- a/frida_mode/src/asan/asan_x86.c +++ b/frida_mode/src/asan/asan_x86.c @@ -1,5 +1,5 @@ #include <dlfcn.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c index a2609c8e..7b11c350 100644 --- a/frida_mode/src/cmplog/cmplog.c +++ b/frida_mode/src/cmplog/cmplog.c @@ -1,32 +1,19 @@ -#include <errno.h> -#include <fcntl.h> -#include <limits.h> -#include <sys/mman.h> -#include <sys/syscall.h> -#include <unistd.h> - -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "util.h" #define DEFAULT_MMAP_MIN_ADDR (32UL << 10) -#define MAX_MEMFD_SIZE (64UL << 10) extern struct cmp_map *__afl_cmp_map; -static GArray * cmplog_ranges = NULL; -static GHashTable * hash_yes = NULL; -static GHashTable * hash_no = NULL; -static long page_size = 0; -static long page_offset_mask = 0; -static long page_mask = 0; +static GArray *cmplog_ranges = NULL; static gboolean cmplog_range(const GumRangeDetails *details, gpointer user_data) { - GArray * cmplog_ranges = (GArray *)user_data; + UNUSED_PARAMETER(user_data); GumMemoryRange range = *details->range; g_array_append_val(cmplog_ranges, range); return TRUE; @@ -40,50 +27,20 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) { } -static void cmplog_get_ranges(void) { - - OKF("CMPLOG - Collecting ranges"); - - cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100); - gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges); - g_array_sort(cmplog_ranges, cmplog_sort); - -} - -void cmplog_config(void) { - -} - void cmplog_init(void) { if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); } - cmplog_get_ranges(); + 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 - %3u: 0x%016" G_GINT64_MODIFIER - "X - 0x%016" G_GINT64_MODIFIER "X", - i, range->base_address, range->base_address + range->size); - - } - - page_size = sysconf(_SC_PAGE_SIZE); - page_offset_mask = page_size - 1; - page_mask = ~(page_offset_mask); - - hash_yes = g_hash_table_new(g_direct_hash, g_direct_equal); - if (hash_yes == NULL) { - - FATAL("Failed to g_hash_table_new, errno: %d", errno); - - } - - hash_no = g_hash_table_new(g_direct_hash, g_direct_equal); - if (hash_no == NULL) { - - FATAL("Failed to g_hash_table_new, errno: %d", errno); + OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER + "X", + range->base_address, range->base_address + range->size); } @@ -96,45 +53,6 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit, } -gboolean cmplog_test_addr(guint64 addr, size_t size) { - - if (g_hash_table_contains(hash_yes, GSIZE_TO_POINTER(addr))) { return true; } - if (g_hash_table_contains(hash_no, GSIZE_TO_POINTER(addr))) { return false; } - - void * page_addr = GSIZE_TO_POINTER(addr & page_mask); - size_t page_offset = addr & page_offset_mask; - - /* If it spans a page, then bail */ - if (page_size - page_offset < size) { return false; } - - /* - * Our address map can change (e.g. stack growth), use msync as a fallback to - * validate our address. - */ - if (msync(page_addr, page_offset + size, MS_ASYNC) < 0) { - - if (!g_hash_table_add(hash_no, GSIZE_TO_POINTER(addr))) { - - FATAL("Failed - g_hash_table_add"); - - } - - return false; - - } else { - - if (!g_hash_table_add(hash_yes, GSIZE_TO_POINTER(addr))) { - - FATAL("Failed - g_hash_table_add"); - - } - - return true; - - } - -} - gboolean cmplog_is_readable(guint64 addr, size_t size) { if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized"); @@ -149,26 +67,20 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) { */ if (addr < DEFAULT_MMAP_MIN_ADDR) { return false; } - /* Check our addres/length don't wrap around */ - if (SIZE_MAX - addr < size) { 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; + 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; } - if (cmplog_test_addr(addr, size)) { 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 index dd97f38d..187d0162 100644 --- a/frida_mode/src/cmplog/cmplog_arm64.c +++ b/frida_mode/src/cmplog/cmplog_arm64.c @@ -1,304 +1,17 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" -#include "cmplog.h" -#include "ctx.h" #include "frida_cmplog.h" #include "util.h" #if defined(__aarch64__) - -typedef struct { - - arm64_op_type type; - uint8_t size; - - union { - - arm64_op_mem mem; - arm64_reg reg; - int64_t imm; - - }; - -} cmplog_ctx_t; - -typedef struct { - - cmplog_ctx_t operand1; - cmplog_ctx_t operand2; - size_t size; - -} cmplog_pair_ctx_t; - -static gboolean cmplog_read_mem(GumCpuContext *ctx, uint8_t size, - arm64_op_mem *mem, gsize *val) { - - gsize base = 0; - gsize index = 0; - gsize address; - - if (mem->base != ARM64_REG_INVALID) { base = ctx_read_reg(ctx, mem->base); } - - if (mem->index != ARM64_REG_INVALID) { - - index = ctx_read_reg(ctx, mem->index); - - } - - address = base + index + 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 ARM64_OP_REG: - *val = ctx_read_reg(context, ctx->reg); - return TRUE; - case ARM64_OP_IMM: - *val = ctx->imm; - return TRUE; - case ARM64_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 = context->pc; - gsize x0 = ctx_read_reg(context, ARM64_REG_X0); - gsize x1 = ctx_read_reg(context, ARM64_REG_X1); - - if (((G_MAXULONG - x0) < 32) || ((G_MAXULONG - x1) < 32)) return; - - if (!cmplog_is_readable(x0, 32) || !cmplog_is_readable(x1, 32)) return; - - void *ptr1 = GSIZE_TO_POINTER(x0); - void *ptr2 = GSIZE_TO_POINTER(x1); - - 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_arm64_op * operand) { - - ctx->type = operand->type; - switch (operand->type) { - - case ARM64_OP_REG: - gum_memcpy(&ctx->reg, &operand->reg, sizeof(arm64_reg)); - break; - case ARM64_OP_IMM: - gum_memcpy(&ctx->imm, &operand->imm, sizeof(int64_t)); - break; - case ARM64_OP_MEM: - gum_memcpy(&ctx->mem, &operand->mem, sizeof(arm64_op_mem)); - break; - default: - FATAL("Invalid operand type: %d\n", operand->type); - - } - -} - -static void cmplog_instrument_call(const cs_insn * instr, - GumStalkerIterator *iterator) { - - cs_arm64 arm64 = instr->detail->arm64; - cs_arm64_op *operand; - - switch (instr->id) { - - case ARM64_INS_BL: - case ARM64_INS_BLR: - case ARM64_INS_BLRAA: - case ARM64_INS_BLRAAZ: - case ARM64_INS_BLRAB: - case ARM64_INS_BLRABZ: - break; - default: - return; - - } - - if (arm64.op_count != 1) return; - - operand = &arm64.operands[0]; - - if (operand->type == ARM64_OP_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 = context->pc; - - 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 (!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->size); - -} - -static void cmplog_instrument_cmp_sub_put_callout(GumStalkerIterator *iterator, - cs_arm64_op * operand1, - cs_arm64_op * operand2, - size_t size) { - - 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); - ctx->size = size; - - 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_arm64 arm64 = instr->detail->arm64; - cs_arm64_op *operand1; - cs_arm64_op *operand2; - size_t size; - - switch (instr->id) { - - case ARM64_INS_ADCS: - case ARM64_INS_ADDS: - case ARM64_INS_ANDS: - case ARM64_INS_BICS: - case ARM64_INS_CMN: - case ARM64_INS_CMP: - case ARM64_INS_CMPEQ: - case ARM64_INS_CMPGE: - case ARM64_INS_CMPGT: - case ARM64_INS_CMPHI: - case ARM64_INS_CMPHS: - case ARM64_INS_CMPLE: - case ARM64_INS_CMPLO: - case ARM64_INS_CMPLS: - case ARM64_INS_CMPLT: - case ARM64_INS_CMPNE: - case ARM64_INS_EORS: - case ARM64_INS_NANDS: - case ARM64_INS_NEGS: - case ARM64_INS_NGCS: - case ARM64_INS_NORS: - case ARM64_INS_NOTS: - case ARM64_INS_ORNS: - case ARM64_INS_ORRS: - case ARM64_INS_SBCS: - case ARM64_INS_SUBS: - break; - - default: - return; - - } - - if (arm64.op_count != 2) return; - - operand1 = &arm64.operands[0]; - operand2 = &arm64.operands[1]; - - if (operand1->type == ARM64_OP_INVALID) return; - if (operand2->type == ARM64_OP_INVALID) return; - - size = ctx_get_size(instr, &arm64.operands[0]); - - cmplog_instrument_cmp_sub_put_callout(iterator, operand1, operand2, size); - -} - 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); + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(iterator); + if (__afl_cmp_map == NULL) { return; } + FATAL("CMPLOG mode not supported on this architecture"); } diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c index 0d18767a..9f56c32a 100644 --- a/frida_mode/src/cmplog/cmplog_x64.c +++ b/frida_mode/src/cmplog/cmplog_x64.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "cmplog.h" @@ -177,7 +177,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, register uintptr_t k = (uintptr_t)address; k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 7; + k &= CMP_MAP_W - 1; __afl_cmp_map->headers[k].type = CMP_TYPE_INS; @@ -198,6 +198,8 @@ static void cmplog_cmp_sub_callout(GumCpuContext *context, gpointer 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; } @@ -231,15 +233,6 @@ static void cmplog_instrument_cmp_sub(const cs_insn * instr, case X86_INS_CMP: case X86_INS_SUB: - case X86_INS_SCASB: - case X86_INS_SCASD: - case X86_INS_SCASQ: - case X86_INS_SCASW: - case X86_INS_CMPSB: - case X86_INS_CMPSD: - case X86_INS_CMPSQ: - case X86_INS_CMPSS: - case X86_INS_CMPSW: break; default: return; @@ -254,8 +247,13 @@ static void cmplog_instrument_cmp_sub(const cs_insn * instr, if (operand1->type == X86_OP_INVALID) return; if (operand2->type == X86_OP_INVALID) return; - /* Both operands are the same size */ - if (operand1->size == 1) { 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); diff --git a/frida_mode/src/cmplog/cmplog_x86.c b/frida_mode/src/cmplog/cmplog_x86.c index dd666c34..a27df0af 100644 --- a/frida_mode/src/cmplog/cmplog_x86.c +++ b/frida_mode/src/cmplog/cmplog_x86.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "cmplog.h" diff --git a/frida_mode/src/ctx/ctx_x64.c b/frida_mode/src/ctx/ctx_x64.c index da5cb13a..c5900533 100644 --- a/frida_mode/src/ctx/ctx_x64.c +++ b/frida_mode/src/ctx/ctx_x64.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -49,18 +49,9 @@ gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) { 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_SPL, ctx->rsp) 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_8L(X86_REG_R8B, ctx->r8) - X86_REG_8L(X86_REG_R9B, ctx->r9) - X86_REG_8L(X86_REG_R10B, ctx->r10) - X86_REG_8L(X86_REG_R11B, ctx->r11) - X86_REG_8L(X86_REG_R12B, ctx->r12) - X86_REG_8L(X86_REG_R13B, ctx->r13) - X86_REG_8L(X86_REG_R14B, ctx->r14) - X86_REG_8L(X86_REG_R15B, ctx->r15) X86_REG_8H(X86_REG_AH, ctx->rax) X86_REG_8H(X86_REG_BH, ctx->rbx) @@ -71,23 +62,14 @@ gsize ctx_read_reg(GumX64CpuContext *ctx, x86_reg reg) { 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_SP, ctx->rsp) - X86_REG_16(X86_REG_BP, ctx->rbp) X86_REG_16(X86_REG_DI, ctx->rdi) X86_REG_16(X86_REG_SI, ctx->rsi) - X86_REG_16(X86_REG_R8W, ctx->r8) - X86_REG_16(X86_REG_R9W, ctx->r9) - X86_REG_16(X86_REG_R10W, ctx->r10) - X86_REG_16(X86_REG_R11W, ctx->r11) - X86_REG_16(X86_REG_R12W, ctx->r12) - X86_REG_16(X86_REG_R13W, ctx->r13) - X86_REG_16(X86_REG_R14W, ctx->r14) - X86_REG_16(X86_REG_R15W, ctx->r15) + X86_REG_16(X86_REG_BP, ctx->rbp) X86_REG_32(X86_REG_EAX, ctx->rax) - X86_REG_32(X86_REG_EBX, ctx->rbx) 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) diff --git a/frida_mode/src/ctx/ctx_x86.c b/frida_mode/src/ctx/ctx_x86.c index 1a587702..45308272 100644 --- a/frida_mode/src/ctx/ctx_x86.c +++ b/frida_mode/src/ctx/ctx_x86.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -42,7 +42,6 @@ gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg) { 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_SPL, ctx->esp) X86_REG_8L(X86_REG_BPL, ctx->ebp) X86_REG_8L(X86_REG_SIL, ctx->esi) X86_REG_8L(X86_REG_DIL, ctx->edi) @@ -56,15 +55,14 @@ gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg) { 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_SP, ctx->esp) - X86_REG_16(X86_REG_BP, ctx->ebp) 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_EBX, ctx->ebx) 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) diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index a0ffd028..e71386a0 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -1,46 +1,35 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "entry.h" #include "instrument.h" -#include "persistent.h" -#include "ranges.h" #include "stalker.h" -#include "stats.h" #include "util.h" extern void __afl_manual_init(); -guint64 entry_point = 0; -gboolean entry_reached = FALSE; +guint64 entry_start = 0; static void entry_launch(void) { - OKF("Entry point reached"); __afl_manual_init(); /* Child here */ - instrument_on_fork(); - stats_on_fork(); - -} - -void entry_config(void) { - - entry_point = util_read_address("AFL_ENTRYPOINT"); + previous_pc = 0; } void entry_init(void) { - OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point); + entry_start = util_read_address("AFL_ENTRYPOINT"); + OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_start); } -void entry_start(void) { +void entry_run(void) { - if (entry_point == 0) { entry_launch(); } + if (entry_start == 0) { entry_launch(); } } @@ -55,16 +44,6 @@ static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) { void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) { UNUSED_PARAMETER(output); - OKF("AFL_ENTRYPOINT reached"); - - if (persistent_start == 0) { - - entry_reached = TRUE; - ranges_exclude(); - stalker_trust(); - - } - 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 index 67aafa5a..cd1ac0be 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -1,19 +1,14 @@ #include <unistd.h> -#include <sys/shm.h> -#include <sys/mman.h> -#include <sys/syscall.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" -#include "hash.h" #include "asan.h" #include "entry.h" #include "frida_cmplog.h" #include "instrument.h" -#include "js.h" #include "persistent.h" #include "prefetch.h" #include "ranges.h" @@ -21,55 +16,46 @@ #include "stats.h" #include "util.h" -gboolean instrument_tracing = false; -gboolean instrument_optimize = false; -gboolean instrument_unique = false; -guint64 instrument_hash_zero = 0; -guint64 instrument_hash_seed = 0; - -gboolean instrument_use_fixed_seed = FALSE; -guint64 instrument_fixed_seed = 0; - +static gboolean tracing = false; +static gboolean optimize = false; static GumStalkerTransformer *transformer = NULL; -__thread guint64 instrument_previous_pc = 0; - -static GumAddress previous_rip = 0; -static u8 * edges_notified = NULL; - -static void trace_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(STDOUT_FILENO, buffer, len)); - -} +__thread uint64_t previous_pc = 0; -guint64 instrument_get_offset_hash(GumAddress current_rip) { - - guint64 area_offset = hash64((unsigned char *)¤t_rip, - sizeof(GumAddress), instrument_hash_seed); - return area_offset &= MAP_SIZE - 1; +__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)); -__attribute__((hot)) static void instrument_increment_map(GumAddress edge) { + } - uint8_t *cursor; - uint64_t value; + current_pc = (current_pc >> 4) ^ (current_pc << 8); + current_pc &= MAP_SIZE - 1; - cursor = &__afl_area_ptr[edge]; + cursor = &__afl_area_ptr[current_pc ^ previous_pc]; value = *cursor; if (value == 0xff) { @@ -83,47 +69,12 @@ __attribute__((hot)) static void instrument_increment_map(GumAddress edge) { } *cursor = value; + previous_pc = current_pc >> 1; } -__attribute__((hot)) static void on_basic_block(GumCpuContext *context, - gpointer user_data) { - - UNUSED_PARAMETER(context); - - GumAddress current_rip = GUM_ADDRESS(user_data); - guint64 current_pc = instrument_get_offset_hash(current_rip); - guint64 edge; - - edge = current_pc ^ instrument_previous_pc; - - instrument_increment_map(edge); - - if (unlikely(instrument_tracing)) { - - if (!instrument_unique || edges_notified[edge] == 0) { - - trace_debug("TRACE: edge: %10" G_GINT64_MODIFIER - "d, current_rip: 0x%016" G_GINT64_MODIFIER - "x, previous_rip: 0x%016" G_GINT64_MODIFIER "x\n", - edge, current_rip, previous_rip); - - } - - if (instrument_unique) { edges_notified[edge] = 1; } - - previous_rip = current_rip; - - } - - instrument_previous_pc = - ((current_pc & (MAP_SIZE - 1) >> 1)) | ((current_pc & 0x1) << 15); - -} - -static void instrument_basic_block(GumStalkerIterator *iterator, - GumStalkerOutput * output, - gpointer user_data) { +static void instr_basic_block(GumStalkerIterator *iterator, + GumStalkerOutput *output, gpointer user_data) { UNUSED_PARAMETER(user_data); @@ -133,9 +84,7 @@ static void instrument_basic_block(GumStalkerIterator *iterator, while (gum_stalker_iterator_next(iterator, &instr)) { - if (unlikely(begin)) { instrument_debug_start(instr->address, output); } - - if (instr->address == entry_point) { entry_prologue(iterator, output); } + 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); } @@ -172,15 +121,11 @@ static void instrument_basic_block(GumStalkerIterator *iterator, instrument_debug_start(instr->address, output); - if (likely(entry_reached)) { - - prefetch_write(GSIZE_TO_POINTER(instr->address)); - - } + prefetch_write(GSIZE_TO_POINTER(instr->address)); if (likely(!excluded)) { - if (likely(instrument_optimize)) { + if (likely(optimize)) { instrument_coverage_optimize(instr, output); @@ -193,6 +138,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } + begin = FALSE; + } instrument_debug_instruction(instr->address, instr->size); @@ -204,117 +151,38 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } - if (js_stalker_callback(instr, begin, excluded, output)) { - - gum_stalker_iterator_keep(iterator); - - } - - begin = FALSE; + gum_stalker_iterator_keep(iterator); } - instrument_flush(output); instrument_debug_end(output); } -void instrument_config(void) { - - instrument_optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL); - instrument_tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL); - instrument_unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL); - instrument_use_fixed_seed = (getenv("AFL_FRIDA_INST_SEED") != NULL); - instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED"); - - instrument_debug_config(); - asan_config(); - cmplog_config(); - -} - void instrument_init(void) { - if (!instrument_is_coverage_optimize_supported()) instrument_optimize = false; + optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL); + tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL); - OKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' '); - OKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' '); - OKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' '); - OKF("Instrumentation - fixed seed [%c] [0x%016" G_GINT64_MODIFIER "x]", - instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed); + if (!instrument_is_coverage_optimize_supported()) optimize = false; - if (instrument_tracing && instrument_optimize) { + OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' '); + OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' '); - WARNF("AFL_FRIDA_INST_TRACE implies AFL_FRIDA_INST_NO_OPTIMIZE"); - instrument_optimize = FALSE; - - } + if (tracing && optimize) { - if (instrument_unique && instrument_optimize) { - - WARNF("AFL_FRIDA_INST_TRACE_UNIQUE implies AFL_FRIDA_INST_NO_OPTIMIZE"); - instrument_optimize = FALSE; + FATAL("AFL_FRIDA_INST_OPTIMIZE and AFL_FRIDA_INST_TRACE are incompatible"); } - if (instrument_unique) { instrument_tracing = TRUE; } - if (__afl_map_size != 0x10000) { FATAL("Bad map size: 0x%08x", __afl_map_size); } - transformer = gum_stalker_transformer_make_from_callback( - instrument_basic_block, NULL, NULL); - - if (instrument_unique) { - - int shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600); - if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); } - - edges_notified = shmat(shm_id, NULL, 0); - g_assert(edges_notified != 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(edges_notified, '\0', MAP_SIZE); - - } - - if (instrument_use_fixed_seed) { - - /* - * This configuration option may be useful for diagnostics or - * debugging. - */ - instrument_hash_seed = instrument_fixed_seed; - - } else { - - /* - * By using a different seed value for the hash, we can make different - * instances have edge collisions in different places when carrying out - * parallel fuzzing. The seed itself, doesn't have to be random, it - * just needs to be different for each instance. - */ - instrument_hash_seed = g_get_monotonic_time() ^ - (((guint64)getpid()) << 32) ^ syscall(SYS_gettid); - - } - - OKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]", - instrument_hash_seed); - instrument_hash_zero = instrument_get_offset_hash(0); + transformer = + gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL); instrument_debug_init(); asan_init(); @@ -329,9 +197,3 @@ GumStalkerTransformer *instrument_get_transformer(void) { } -void instrument_on_fork() { - - instrument_previous_pc = instrument_hash_zero; - -} - diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 0e15940a..1a3c40bb 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -22,17 +22,5 @@ void instrument_coverage_optimize(const cs_insn * instr, } -void instrument_flush(GumStalkerOutput *output) { - - gum_arm_writer_flush(output->writer.arm); - -} - -gpointer instrument_cur(GumStalkerOutput *output) { - - return gum_arm_writer_cur(output->writer.arm); - -} - #endif diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index cf37e048..fa3afb48 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" @@ -12,15 +12,15 @@ 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 ROR 1; + // 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 - 0x21, 0x02, 0x00, 0x58, // ldr x1, #0x44, =&__afl_area_ptr + 0xe1, 0x01, 0x00, 0x58, // ldr x1, #0x3c, =&__afl_area_ptr 0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr) - 0x22, 0x02, 0x00, 0x58, // ldr x2, #0x44, =&previous_pc + 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]++; @@ -30,11 +30,8 @@ static const guint8 afl_log_code[] = { 0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr 0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2] - // previous_pc = current_pc ROR 1; - 0xe4, 0x07, 0x40, 0x8b, // add x4, xzr, x0, LSR #1 - 0xe0, 0xff, 0x00, 0x8b, // add x0, xzr, x0, LSL #63 - 0x80, 0xc0, 0x40, 0x8b, // add x0, x4, x0, LSR #48 - + // 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] @@ -57,7 +54,8 @@ void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output) { guint64 current_pc = instr->address; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(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 || @@ -74,7 +72,7 @@ void instrument_coverage_optimize(const cs_insn * instr, 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 = &instrument_previous_pc; + 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, @@ -95,17 +93,5 @@ void instrument_coverage_optimize(const cs_insn * instr, } -void instrument_flush(GumStalkerOutput *output) { - - gum_arm64_writer_flush(output->writer.arm64); - -} - -gpointer instrument_cur(GumStalkerOutput *output) { - - return gum_arm64_writer_cur(output->writer.arm64); - -} - #endif diff --git a/frida_mode/src/instrument/instrument_debug.c b/frida_mode/src/instrument/instrument_debug.c index b8cca634..f8c1df77 100644 --- a/frida_mode/src/instrument/instrument_debug.c +++ b/frida_mode/src/instrument/instrument_debug.c @@ -3,18 +3,15 @@ #include <stdio.h> #include <unistd.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" -#include "instrument.h" #include "util.h" static int debugging_fd = -1; static gpointer instrument_gen_start = NULL; -char *instrument_debug_filename = NULL; - static void instrument_debug(char *format, ...) { va_list ap; @@ -34,44 +31,24 @@ static void instrument_debug(char *format, ...) { } -static void instrument_disasm(guint8 *start, guint8 *end) { +static void instrument_disasm(guint8 *code, guint size) { csh capstone; cs_err err; - uint16_t size; cs_insn *insn; - size_t count = 0; - size_t i; - uint16_t len; + 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); - size = GPOINTER_TO_SIZE(end) - GPOINTER_TO_SIZE(start); - - for (guint8 *curr = start; curr < end; curr += len, size -= len, len = 0) { - - count = cs_disasm(capstone, curr, size, GPOINTER_TO_SIZE(curr), 0, &insn); - if (insn == NULL) { - - instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t* 0x%016" G_GSIZE_MODIFIER - "x\n", - curr, *(size_t *)curr); - - len += sizeof(size_t); - continue; - - } - - 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); + count = cs_disasm(capstone, code, size, GPOINTER_TO_SIZE(code), 0, &insn); + g_assert(insn != NULL); - len += insn[i].size; + 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); } @@ -81,25 +58,32 @@ static void instrument_disasm(guint8 *start, guint8 *end) { } -void instrument_debug_config(void) { +static gpointer instrument_cur(GumStalkerOutput *output) { - instrument_debug_filename = getenv("AFL_FRIDA_INST_DEBUG_FILE"); +#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) { - OKF("Instrumentation debugging - enabled [%c]", - instrument_debug_filename == NULL ? ' ' : 'X'); + char *filename = getenv("AFL_FRIDA_INST_DEBUG_FILE"); + OKF("Instrumentation debugging - enabled [%c]", filename == NULL ? ' ' : 'X'); - if (instrument_debug_filename == NULL) { return; } + if (filename == NULL) { return; } - OKF("Instrumentation debugging - file [%s]", instrument_debug_filename); + OKF("Instrumentation debugging - file [%s]", filename); - if (instrument_debug_filename == NULL) { return; } + if (filename == NULL) { return; } - char *path = - g_canonicalize_filename(instrument_debug_filename, g_get_current_dir()); + char *path = g_canonicalize_filename(filename, g_get_current_dir()); OKF("Instrumentation debugging - path [%s]", path); @@ -127,7 +111,7 @@ 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, start + size); + instrument_disasm(start, size); } @@ -135,10 +119,11 @@ 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-%p\n", instrument_gen_start, - instrument_gen_end); - instrument_disasm(instrument_gen_start, instrument_gen_end); + 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 index fec8afbb..901f3bd0 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" @@ -10,21 +10,23 @@ 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, 0x26, + 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, 0x11, + 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 */ - 0x66, 0xd1, 0xcf, /* ror di, 1 */ + 0x48, 0xd1, 0xef, /* shr rdi, 1 */ 0x48, 0x89, 0x39, /* mov qword [rcx], rdi */ 0x5a, /* pop rdx */ @@ -32,8 +34,7 @@ static const guint8 afl_log_code[] = { 0x9d, /* popfq */ 0xc3, /* ret */ - - 0x90 + 0x90, 0x90, 0x90 /* nop pad */ /* Read-only data goes here: */ /* uint8_t* __afl_area_ptr */ @@ -47,11 +48,12 @@ gboolean instrument_is_coverage_optimize_supported(void) { } -static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; - -static void instrument_coverate_write_function(GumStalkerOutput *output) { +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { - guint64 misalign = 0; + 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 || @@ -63,17 +65,10 @@ static void instrument_coverate_write_function(GumStalkerOutput *output) { gum_x86_writer_put_jmp_near_label(cw, after_log_impl); - misalign = (cw->pc & 0x7); - if (misalign != 0) { - - gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign); - - } - current_log_impl = cw->pc; gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code)); - uint64_t *afl_prev_loc_ptr = &instrument_previous_pc; + 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, @@ -83,15 +78,6 @@ static void instrument_coverate_write_function(GumStalkerOutput *output) { } -} - -void instrument_coverage_optimize(const cs_insn * instr, - GumStalkerOutput *output) { - - GumX86Writer *cw = output->writer.x86; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); - instrument_coverate_write_function(output); - 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); @@ -103,17 +89,5 @@ void instrument_coverage_optimize(const cs_insn * instr, } -void instrument_flush(GumStalkerOutput *output) { - - gum_x86_writer_flush(output->writer.x86); - -} - -gpointer instrument_cur(GumStalkerOutput *output) { - - return gum_x86_writer_cur(output->writer.x86); - -} - #endif diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index 7bf48f96..585bb5b8 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -16,7 +16,7 @@ static void instrument_coverage_function(GumX86Writer *cw) { gum_x86_writer_put_push_reg(cw, GUM_REG_EDX); gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX, - GUM_ADDRESS(&instrument_previous_pc)); + 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); @@ -30,8 +30,7 @@ static void instrument_coverage_function(GumX86Writer *cw) { 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)); - uint8_t ror_di_1[] = {0x66, 0xd1, 0xcf}; - gum_x86_writer_put_bytes(cw, ror_di_1, sizeof(ror_di_1)); + 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); @@ -47,8 +46,15 @@ gboolean instrument_is_coverage_optimize_supported(void) { } -static void instrument_coverate_write_function(GumStalkerOutput *output) { +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 || @@ -67,15 +73,7 @@ static void instrument_coverate_write_function(GumStalkerOutput *output) { } -} - -void instrument_coverage_optimize(const cs_insn * instr, - GumStalkerOutput *output) { - - GumX86Writer *cw = output->writer.x86; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); - instrument_coverate_write_function(output); - + // 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); @@ -83,17 +81,5 @@ void instrument_coverage_optimize(const cs_insn * instr, } -void instrument_flush(GumStalkerOutput *output) { - - gum_x86_writer_flush(output->writer.x86); - -} - -gpointer instrument_cur(GumStalkerOutput *output) { - - return gum_x86_writer_cur(output->writer.x86); - -} - #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 index 59a3fcf9..13a7d1e7 100644 --- a/frida_mode/src/lib/lib.c +++ b/frida_mode/src/lib/lib.c @@ -6,7 +6,7 @@ #include <sys/mman.h> #include <unistd.h> - #include "frida-gumjs.h" + #include "frida-gum.h" #include "debug.h" @@ -151,10 +151,6 @@ static void lib_get_text_section(lib_details_t *details) { } -void lib_config(void) { - -} - void lib_init(void) { lib_details_t lib_details; diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c index 2aa48a13..8f863861 100644 --- a/frida_mode/src/lib/lib_apple.c +++ b/frida_mode/src/lib/lib_apple.c @@ -1,5 +1,5 @@ #ifdef __APPLE__ - #include "frida-gumjs.h" + #include "frida-gum.h" #include "debug.h" @@ -56,10 +56,6 @@ gboolean lib_get_text_section(const GumDarwinSectionDetails *details, } -void lib_config(void) { - -} - void lib_init(void) { GumDarwinModule *module = NULL; diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index 91687046..1ab9993f 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -1,5 +1,4 @@ #include <errno.h> -#include <fcntl.h> #include <unistd.h> #include <sys/types.h> @@ -11,15 +10,14 @@ #include <sys/personality.h> #endif -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" #include "entry.h" #include "instrument.h" -#include "intercept.h" -#include "js.h" +#include "interceptor.h" #include "lib.h" #include "output.h" #include "persistent.h" @@ -29,8 +27,6 @@ #include "stats.h" #include "util.h" -#define PROC_MAX 65536 - #ifdef __APPLE__ extern mach_port_t mach_task_self(); extern GumAddress gum_darwin_find_entrypoint(mach_port_t task); @@ -45,6 +41,13 @@ 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) { @@ -75,7 +78,7 @@ static void on_main_os(int argc, char **argv, char **envp) { #endif -static void embedded_init(void) { +static void embedded_init() { static gboolean initialized = false; if (!initialized) { @@ -87,117 +90,25 @@ static void embedded_init(void) { } -static void afl_print_cmdline(void) { - - char * buffer = g_malloc0(PROC_MAX); - gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid()); - int fd = open(fname, O_RDONLY); - - if (fd < 0) { - - WARNF("Failed to open /proc/self/cmdline, errno: (%d)", errno); - return; - - } - - ssize_t bytes_read = read(fd, buffer, PROC_MAX - 1); - if (bytes_read < 0) { - - FATAL("Failed to read /proc/self/cmdline, errno: (%d)", errno); - - } - - int idx = 0; - - for (ssize_t i = 0; i < bytes_read; i++) { - - if (i == 0 || buffer[i - 1] == '\0') { - - OKF("AFL - COMMANDLINE: argv[%d] = %s", idx++, &buffer[i]); - - } - - } - - close(fd); - g_free(fname); - g_free(buffer); - -} - -static void afl_print_env(void) { - - char * buffer = g_malloc0(PROC_MAX); - gchar *fname = g_strdup_printf("/proc/%d/environ", getppid()); - int fd = open(fname, O_RDONLY); - - if (fd < 0) { - - WARNF("Failed to open /proc/self/cmdline, errno: (%d)", errno); - return; - - } - - ssize_t bytes_read = read(fd, buffer, PROC_MAX - 1); - if (bytes_read < 0) { - - FATAL("Failed to read /proc/self/cmdline, errno: (%d)", errno); - - } - - int idx = 0; - - for (ssize_t i = 0; i < bytes_read; i++) { - - if (i == 0 || buffer[i - 1] == '\0') { - - OKF("AFL - ENVIRONMENT %3d: %s", idx++, &buffer[i]); - - } - - } - - close(fd); - g_free(fname); - g_free(buffer); - -} - -__attribute__((visibility("default"))) void afl_frida_start(void) { - - afl_print_cmdline(); - afl_print_env(); - - /* Configure */ - entry_config(); - instrument_config(); - js_config(); - lib_config(); - output_config(); - persistent_config(); - prefetch_config(); - ranges_config(); - stalker_config(); - stats_config(); - - js_start(); - - /* Initialize */ - output_init(); +void afl_frida_start() { embedded_init(); + stalker_init(); + lib_init(); entry_init(); instrument_init(); - lib_init(); + output_init(); persistent_init(); prefetch_init(); - stalker_init(); ranges_init(); stats_init(); - /* Start */ + void *fork_addr = + GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork")); + intercept(fork_addr, on_fork, NULL); + stalker_start(); - entry_start(); + entry_run(); } @@ -205,7 +116,7 @@ static int *on_main(int argc, char **argv, char **envp) { on_main_os(argc, argv, envp); - intercept_unhook_self(); + unintercept_self(); afl_frida_start(); @@ -219,7 +130,7 @@ extern int *main(int argc, char **argv, char **envp); static void intercept_main(void) { main_fn = main; - intercept_hook(main, on_main, NULL); + intercept(main, on_main, NULL); } @@ -232,7 +143,7 @@ static void intercept_main(void) { OKF("Entry Point: 0x%016" G_GINT64_MODIFIER "x", entry); void *main = GSIZE_TO_POINTER(entry); main_fn = main; - intercept_hook(main, on_main, NULL); + intercept(main, on_main, NULL); } @@ -243,8 +154,8 @@ static int on_libc_start_main(int *(main)(int, char **, char **), int argc, void(*stack_end)) { main_fn = main; - intercept_unhook_self(); - intercept_hook(main, on_main, NULL); + unintercept_self(); + intercept(main, on_main, NULL); return __libc_start_main(main, argc, ubp_av, init, fini, rtld_fini, stack_end); @@ -252,7 +163,7 @@ static int on_libc_start_main(int *(main)(int, char **, char **), int argc, static void intercept_main(void) { - intercept_hook(__libc_start_main, on_libc_start_main, NULL); + intercept(__libc_start_main, on_libc_start_main, NULL); } diff --git a/frida_mode/src/output.c b/frida_mode/src/output.c index e2b744e7..8a222b25 100644 --- a/frida_mode/src/output.c +++ b/frida_mode/src/output.c @@ -2,17 +2,17 @@ #include <fcntl.h> #include <unistd.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" #include "output.h" -char *output_stdout = NULL; -char *output_stderr = NULL; +static int output_fd = -1; -static void output_redirect(int fd, char *filename) { +static void output_redirect(int fd, char *variable) { + char *filename = getenv(variable); char *path = NULL; if (filename == NULL) { return; } @@ -21,8 +21,8 @@ static void output_redirect(int fd, char *filename) { OKF("Redirect %d -> '%s'", fd, path); - int output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + output_fd = open(path, O_RDWR | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); g_free(path); @@ -34,24 +34,12 @@ static void output_redirect(int fd, char *filename) { } - close(output_fd); - -} - -void output_config(void) { - - output_stdout = getenv("AFL_FRIDA_OUTPUT_STDOUT"); - output_stderr = getenv("AFL_FRIDA_OUTPUT_STDERR"); - } void output_init(void) { - OKF("Output - StdOut: %s", output_stdout); - OKF("Output - StdErr: %s", output_stderr); - - output_redirect(STDOUT_FILENO, output_stdout); - output_redirect(STDERR_FILENO, output_stderr); + 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 index 639a694e..2ec5b9cc 100644 --- a/frida_mode/src/persistent/persistent.c +++ b/frida_mode/src/persistent/persistent.c @@ -1,31 +1,30 @@ #include <dlfcn.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" -#include "entry.h" #include "persistent.h" -#include "ranges.h" -#include "stalker.h" #include "util.h" -int __afl_sharedmem_fuzzing = 0; -static char *hook_name = NULL; - -afl_persistent_hook_fn persistent_hook = NULL; +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_config(void) { +void persistent_init(void) { + + char *hook_name = getenv("AFL_FRIDA_PERSISTENT_HOOK"); - 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; } @@ -37,11 +36,6 @@ void persistent_config(void) { } - if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000; - - if (persistent_start != 0 && !persistent_is_supported()) - FATAL("Persistent mode not supported on this architecture"); - if (persistent_ret != 0 && persistent_start == 0) { FATAL( @@ -50,28 +44,21 @@ void persistent_config(void) { } - if (hook_name == NULL) { return; } + if (persistent_ret_offset != 0 && persistent_ret == 0) { - 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); + FATAL( + "AFL_FRIDA_PERSISTENT_RET must be specified if " + "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET is"); - if (afl_persistent_hook_init_ptr() == 0) - FATAL("afl_persistent_hook_init returned a failure"); + } - persistent_hook = - (afl_persistent_hook_fn)dlsym(hook_obj, "afl_persistent_hook"); - if (persistent_hook == NULL) - FATAL("Failed to find afl_persistent_hook in %s", hook_name); + 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)"); -void persistent_init(void) { + 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); @@ -81,25 +68,30 @@ void persistent_init(void) { 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 (persistent_hook != NULL) { __afl_sharedmem_fuzzing = 1; } + 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); -void persistent_prologue(GumStalkerOutput *output) { + 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); - OKF("AFL_FRIDA_PERSISTENT_ADDR reached"); - entry_reached = TRUE; - ranges_exclude(); - stalker_trust(); - persistent_prologue_arch(output); + 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); -void persistent_epilogue(GumStalkerOutput *output) { + __afl_sharedmem_fuzzing = 1; - OKF("AFL_FRIDA_PERSISTENT_RET reached"); - persistent_epilogue_arch(output); + } } diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index 769f1505..6a3c06fa 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -61,14 +61,14 @@ gboolean persistent_is_supported(void) { } -void persistent_prologue_arch(GumStalkerOutput *output) { +void persistent_prologue(GumStalkerOutput *output) { UNUSED_PARAMETER(output); FATAL("Persistent mode not supported on this architecture"); } -void persistent_epilogue_arch(GumStalkerOutput *output) { +void persistent_epilogue(GumStalkerOutput *output) { UNUSED_PARAMETER(output); FATAL("Persistent mode not supported on this architecture"); diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c index 3cd61cd5..1215d8da 100644 --- a/frida_mode/src/persistent/persistent_arm64.c +++ b/frida_mode/src/persistent/persistent_arm64.c @@ -1,383 +1,120 @@ -#include <unistd.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" #include "instrument.h" -#include "persistent.h" #include "util.h" #if defined(__aarch64__) -typedef struct { - GumCpuContext ctx; - uint64_t rflags; +struct arm64_regs { -} persistent_ctx_t; + uint64_t x0, x1, x2, x3, x4, x5, x6, x7, x8, x9, x10; -static persistent_ctx_t saved_regs = {0}; -static gpointer saved_lr = NULL; + union { -gboolean persistent_is_supported(void) { - - return true; - -} - -static void instrument_persitent_save_regs(GumArm64Writer * cw, - persistent_ctx_t *regs) { - - GumAddress regs_address = GUM_ADDRESS(regs); - const guint32 mrs_x1_nzcv = 0xd53b4201; - - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE), - GUM_INDEX_PRE_ADJUST); - gum_arm64_writer_put_stp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, - ARM64_REG_SP, -(16), - GUM_INDEX_PRE_ADJUST); - - gum_arm64_writer_put_instruction(cw, mrs_x1_nzcv); - - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, - GUM_ADDRESS(regs_address)); - - /* Skip x0 & x1 we'll do that later */ - - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, - offsetof(GumCpuContext, x[2]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X0, - offsetof(GumCpuContext, x[4]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X6, ARM64_REG_X7, ARM64_REG_X0, - offsetof(GumCpuContext, x[6]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X0, - offsetof(GumCpuContext, x[8]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X0, - offsetof(GumCpuContext, x[10]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X0, - offsetof(GumCpuContext, x[12]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X14, ARM64_REG_X15, ARM64_REG_X0, - offsetof(GumCpuContext, x[14]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X0, - offsetof(GumCpuContext, x[16]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X0, - offsetof(GumCpuContext, x[18]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X0, - offsetof(GumCpuContext, x[20]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X22, ARM64_REG_X23, ARM64_REG_X0, - offsetof(GumCpuContext, x[22]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X0, - offsetof(GumCpuContext, x[24]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X0, - offsetof(GumCpuContext, x[26]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X28, ARM64_REG_X29, ARM64_REG_X0, - offsetof(GumCpuContext, x[28]), GUM_INDEX_SIGNED_OFFSET); - - /* LR (x30) */ - gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, - offsetof(GumCpuContext, x[30])); - - /* PC & Adjusted SP (31) */ - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, - GUM_ADDRESS(persistent_start)); - gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_X3, ARM64_REG_SP, - (GUM_RED_ZONE_SIZE + 32)); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, offsetof(GumCpuContext, pc), - GUM_INDEX_SIGNED_OFFSET); - - /* CPSR */ - gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, - offsetof(persistent_ctx_t, rflags)); - - /* Q */ - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0, - offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0, - offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0, - offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0, - offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET); - - /* x0 & x1 */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X3, - ARM64_REG_SP, 16, - GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, - offsetof(GumCpuContext, x[0]), GUM_INDEX_SIGNED_OFFSET); - - /* Pop the saved values */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_SP, 16, GUM_INDEX_POST_ADJUST); - - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE, - GUM_INDEX_POST_ADJUST); - -} - -static void instrument_persitent_restore_regs(GumArm64Writer * cw, - persistent_ctx_t *regs) { - - GumAddress regs_address = GUM_ADDRESS(regs); - const guint32 msr_nzcv_x1 = 0xd51b4201; - - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, - GUM_ADDRESS(regs_address)); - - /* Skip x0 - x3 we'll do that last */ - - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X4, ARM64_REG_X5, ARM64_REG_X0, - offsetof(GumCpuContext, x[4]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X6, ARM64_REG_X7, ARM64_REG_X0, - offsetof(GumCpuContext, x[6]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X8, ARM64_REG_X9, ARM64_REG_X0, - offsetof(GumCpuContext, x[8]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X10, ARM64_REG_X11, ARM64_REG_X0, - offsetof(GumCpuContext, x[10]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X12, ARM64_REG_X13, ARM64_REG_X0, - offsetof(GumCpuContext, x[12]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X14, ARM64_REG_X15, ARM64_REG_X0, - offsetof(GumCpuContext, x[14]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X16, ARM64_REG_X17, ARM64_REG_X0, - offsetof(GumCpuContext, x[16]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X18, ARM64_REG_X19, ARM64_REG_X0, - offsetof(GumCpuContext, x[18]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X20, ARM64_REG_X21, ARM64_REG_X0, - offsetof(GumCpuContext, x[20]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X22, ARM64_REG_X23, ARM64_REG_X0, - offsetof(GumCpuContext, x[22]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X24, ARM64_REG_X25, ARM64_REG_X0, - offsetof(GumCpuContext, x[24]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X26, ARM64_REG_X27, ARM64_REG_X0, - offsetof(GumCpuContext, x[26]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X28, ARM64_REG_X29, ARM64_REG_X0, - offsetof(GumCpuContext, x[28]), GUM_INDEX_SIGNED_OFFSET); - - /* LR (x30) */ - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X0, - offsetof(GumCpuContext, x[30])); - - /* Adjusted SP (31) (use x1 as clobber)*/ - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, - offsetof(GumCpuContext, sp)); - gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_SP, ARM64_REG_X1); - - /* CPSR */ - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X0, - offsetof(persistent_ctx_t, rflags)); - gum_arm64_writer_put_instruction(cw, msr_nzcv_x1); - - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_Q0, ARM64_REG_Q1, ARM64_REG_X0, - offsetof(GumCpuContext, q[0]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_Q2, ARM64_REG_Q3, ARM64_REG_X0, - offsetof(GumCpuContext, q[16]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_Q4, ARM64_REG_Q5, ARM64_REG_X0, - offsetof(GumCpuContext, q[32]), GUM_INDEX_SIGNED_OFFSET); - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_Q6, ARM64_REG_Q7, ARM64_REG_X0, - offsetof(GumCpuContext, q[48]), GUM_INDEX_SIGNED_OFFSET); - - /* x2 & x3 */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X2, ARM64_REG_X3, ARM64_REG_X0, - offsetof(GumCpuContext, x[2]), GUM_INDEX_SIGNED_OFFSET); - /* x0 & x1 */ - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_X0, - offsetof(GumCpuContext, x[0]), GUM_INDEX_SIGNED_OFFSET); - -} - -static void instrument_exit(GumArm64Writer *cw) { + uint64_t x11; + uint32_t fp_32; - gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); - gum_arm64_writer_put_call_address_with_arguments( - cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0); + }; -} - -static int instrument_afl_persistent_loop_func(void) { + union { - int ret = __afl_persistent_loop(persistent_count); - instrument_previous_pc = instrument_hash_zero; - return ret; + uint64_t x12; + uint32_t ip_32; -} + }; -static void instrument_afl_persistent_loop(GumArm64Writer *cw) { + union { - gum_arm64_writer_put_sub_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, - GUM_RED_ZONE_SIZE); - gum_arm64_writer_put_call_address_with_arguments( - cw, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); - gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, - GUM_RED_ZONE_SIZE); + uint64_t x13; + uint32_t sp_32; -} + }; -static void persistent_prologue_hook(GumArm64Writer * cw, - persistent_ctx_t *regs) { + union { - if (persistent_hook == NULL) return; + uint64_t x14; + uint32_t lr_32; - gum_arm64_writer_put_sub_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, - GUM_RED_ZONE_SIZE); - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X2, - GUM_ADDRESS(&__afl_fuzz_len)); - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X2, 0); + }; - gum_arm64_writer_put_and_reg_reg_imm(cw, ARM64_REG_X2, ARM64_REG_X2, - G_MAXULONG); + union { - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X1, - GUM_ADDRESS(&__afl_fuzz_ptr)); - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X1, ARM64_REG_X1, 0); + uint64_t x15; + uint32_t pc_32; - gum_arm64_writer_put_call_address_with_arguments( - cw, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, - GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, ARM64_REG_X1, GUM_ARG_REGISTER, - ARM64_REG_X2); + }; - gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP, - GUM_RED_ZONE_SIZE); + union { -} + uint64_t x16; + uint64_t ip0; -static void instrument_persitent_save_lr(GumArm64Writer *cw) { + }; - gum_arm64_writer_put_stp_reg_reg_reg_offset( - cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, -(16 + GUM_RED_ZONE_SIZE), - GUM_INDEX_PRE_ADJUST); + union { - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, - GUM_ADDRESS(&saved_lr)); + uint64_t x17; + uint64_t ip1; - gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0); + }; - gum_arm64_writer_put_ldp_reg_reg_reg_offset( - cw, ARM64_REG_X0, ARM64_REG_X1, ARM64_REG_SP, 16 + GUM_RED_ZONE_SIZE, - GUM_INDEX_POST_ADJUST); + uint64_t x18, x19, x20, x21, x22, x23, x24, x25, x26, x27, x28; -} + union { -void persistent_prologue_arch(GumStalkerOutput *output) { + uint64_t x29; + uint64_t fp; - /* - * 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 - */ + }; - GumArm64Writer *cw = output->writer.arm64; + union { - gconstpointer loop = cw->code + 1; + uint64_t x30; + uint64_t lr; - OKF("Persistent loop reached"); + }; - instrument_persitent_save_regs(cw, &saved_regs); + union { - /* loop: */ - gum_arm64_writer_put_label(cw, loop); + uint64_t x31; + uint64_t sp; - /* call instrument_prologue_func */ - instrument_afl_persistent_loop(cw); + }; - /* jz done */ - gconstpointer done = cw->code + 1; - gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); - gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done); + // the zero register is not saved here ofc - /* Optionally call the persistent hook */ - persistent_prologue_hook(cw, &saved_regs); + uint64_t pc; - instrument_persitent_restore_regs(cw, &saved_regs); - gconstpointer original = cw->code + 1; - /* call original */ + uint32_t cpsr; - gum_arm64_writer_put_bl_label(cw, original); + uint8_t vfp_zregs[32][16 * 16]; + uint8_t vfp_pregs[17][32]; + uint32_t vfp_xregs[16]; - /* jmp loop */ - gum_arm64_writer_put_b_label(cw, loop); +}; - /* done: */ - gum_arm64_writer_put_label(cw, done); +typedef struct arm64_regs arch_api_regs; - instrument_exit(cw); - - /* original: */ - gum_arm64_writer_put_label(cw, original); - - instrument_persitent_save_lr(cw); +gboolean persistent_is_supported(void) { - if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } + return false; } -void persistent_epilogue_arch(GumStalkerOutput *output) { +void persistent_prologue(GumStalkerOutput *output) { - GumArm64Writer *cw = output->writer.arm64; + UNUSED_PARAMETER(output); + FATAL("Persistent mode not supported on this architecture"); - if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } - - gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, - GUM_ADDRESS(&saved_lr)); +} - gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0); +void persistent_epilogue(GumStalkerOutput *output) { - gum_arm64_writer_put_br_reg(cw, ARM64_REG_X0); + UNUSED_PARAMETER(output); + FATAL("Persistent mode not supported on this architecture"); } diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index c0bd9a09..4cb960fc 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -1,5 +1,5 @@ #include <unistd.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" @@ -10,15 +10,39 @@ #if defined(__x86_64__) -typedef struct { +struct x86_64_regs { - GumCpuContext ctx; - uint64_t rflags; + uint64_t rax, rbx, rcx, rdx, rdi, rsi, rbp, r8, r9, r10, r11, r12, r13, r14, + r15; -} persistent_ctx_t; + union { -static persistent_ctx_t saved_regs = {0}; -static gpointer saved_ret = NULL; + 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) { @@ -26,8 +50,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumX86Writer * cw, - persistent_ctx_t *regs) { +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, @@ -39,60 +63,60 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, 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, offsetof(GumCpuContext, rbx), GUM_REG_RBX); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, rcx), GUM_REG_RCX); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, rdx), GUM_REG_RDX); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, rdi), GUM_REG_RDI); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, rsi), GUM_REG_RSI); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, rbp), GUM_REG_RBP); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r8), GUM_REG_R8); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r9), GUM_REG_R9); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r10), GUM_REG_R10); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r11), GUM_REG_R11); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r12), GUM_REG_R12); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r13), GUM_REG_R13); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r14), GUM_REG_R14); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, r15), GUM_REG_R15); + 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, offsetof(GumCpuContext, rip), GUM_REG_RBX); + 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 * 2)); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_RAX, offsetof(GumCpuContext, rsp), 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, offsetof(persistent_ctx_t, rflags), GUM_REG_RBX); + 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, offsetof(GumCpuContext, rax), GUM_REG_RBX); + 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); @@ -102,56 +126,54 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, } -static void instrument_persitent_restore_regs(GumX86Writer * cw, - persistent_ctx_t *regs) { +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, - offsetof(GumCpuContext, rcx)); + (0x8 * 2)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RAX, - offsetof(GumCpuContext, rdx)); + (0x8 * 3)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDI, GUM_REG_RAX, - offsetof(GumCpuContext, rdi)); + (0x8 * 4)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RAX, - offsetof(GumCpuContext, rsi)); + (0x8 * 5)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBP, GUM_REG_RAX, - offsetof(GumCpuContext, rbp)); + (0x8 * 6)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R8, GUM_REG_RAX, - offsetof(GumCpuContext, r8)); + (0x8 * 7)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R9, GUM_REG_RAX, - offsetof(GumCpuContext, r9)); + (0x8 * 8)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R10, GUM_REG_RAX, - offsetof(GumCpuContext, r10)); + (0x8 * 9)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R11, GUM_REG_RAX, - offsetof(GumCpuContext, r11)); + (0x8 * 10)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R12, GUM_REG_RAX, - offsetof(GumCpuContext, r12)); + (0x8 * 11)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R13, GUM_REG_RAX, - offsetof(GumCpuContext, r13)); + (0x8 * 12)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R14, GUM_REG_RAX, - offsetof(GumCpuContext, r14)); + (0x8 * 13)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX, - offsetof(GumCpuContext, r15)); + (0x8 * 14)); - /* Don't restore RIP */ - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSP, GUM_REG_RAX, - offsetof(GumCpuContext, rsp)); + /* 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, - offsetof(GumCpuContext, rbx)); + (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, - offsetof(GumCpuContext, 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, - offsetof(persistent_ctx_t, rflags)); + (0x8 * 17)); gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); gum_x86_writer_put_popfx(cw); @@ -174,7 +196,7 @@ static void instrument_exit(GumX86Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - instrument_previous_pc = instrument_hash_zero; + previous_pc = 0; return ret; } @@ -192,59 +214,35 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { } -static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { +static void persistent_prologue_hook(GumX86Writer * cw, + struct x86_64_regs *regs) { - if (persistent_hook == NULL) return; + 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_RDX, + 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_RDX, GUM_REG_RDX, 0); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); + 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_RDX, GUM_REG_RDI); + gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RCX, GUM_REG_RDI); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RSI, + 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_RSI, GUM_REG_RSI, 0); + 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(persistent_hook), 3, GUM_ARG_ADDRESS, - GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, GUM_REG_RSI, GUM_ARG_REGISTER, - GUM_REG_RDX); + 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)); } -static void instrument_persitent_save_ret(GumX86Writer *cw) { - - /* Stack usage by this function */ - gssize offset = GUM_RED_ZONE_SIZE + (3 * 8); - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - -(GUM_RED_ZONE_SIZE)); - - gum_x86_writer_put_pushfx(cw); - gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); - gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret)); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, - offset); - gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_RAX, GUM_REG_RBX); - - gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); - gum_x86_writer_put_popfx(cw); - - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - (GUM_RED_ZONE_SIZE)); - -} - -void persistent_prologue_arch(GumStalkerOutput *output) { +void persistent_prologue(GumStalkerOutput *output) { /* * SAVE REGS @@ -270,13 +268,12 @@ void persistent_prologue_arch(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - OKF("Persistent loop reached"); - - /* Pop the return value */ - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8); - + /* 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); @@ -307,27 +304,21 @@ void persistent_prologue_arch(GumStalkerOutput *output) { /* original: */ gum_x86_writer_put_label(cw, original); - instrument_persitent_save_ret(cw); - if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + gum_x86_writer_flush(cw); + } -void persistent_epilogue_arch(GumStalkerOutput *output) { +void persistent_epilogue(GumStalkerOutput *output) { GumX86Writer *cw = output->writer.x86; if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } - /* The stack should be aligned when we re-enter our loop */ - gconstpointer zero = cw->code + 1; - gum_x86_writer_put_test_reg_u32(cw, GUM_REG_RSP, 0xF); - gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, zero, GUM_NO_HINT); - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -8); - gum_x86_writer_put_label(cw, zero); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret)); - gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_RAX); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + persistent_ret_offset); + gum_x86_writer_put_ret(cw); } diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index b911676a..b30dfadf 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -1,23 +1,44 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" -#include "debug.h" #include "instrument.h" #include "persistent.h" #if defined(__i386__) -typedef struct { +struct x86_regs { - GumCpuContext ctx; - uint32_t eflags; + uint32_t eax, ebx, ecx, edx, edi, esi, ebp; -} persistent_ctx_t; + union { -static persistent_ctx_t saved_regs = {0}; + uint32_t eip; + uint32_t pc; -static gpointer saved_ret = NULL; + }; + + 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) { @@ -25,8 +46,8 @@ gboolean persistent_is_supported(void) { } -static void instrument_persitent_save_regs(GumX86Writer * cw, - persistent_ctx_t *regs) { +static void instrument_persitent_save_regs(GumX86Writer * cw, + struct x86_regs *regs) { GumAddress regs_address = GUM_ADDRESS(regs); @@ -36,80 +57,78 @@ static void instrument_persitent_save_regs(GumX86Writer * cw, 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, offsetof(GumCpuContext, ebx), GUM_REG_EBX); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_EAX, offsetof(GumCpuContext, ecx), GUM_REG_ECX); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_EAX, offsetof(GumCpuContext, edx), GUM_REG_EDX); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_EAX, offsetof(GumCpuContext, edi), GUM_REG_EDI); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_EAX, offsetof(GumCpuContext, esi), GUM_REG_ESI); - gum_x86_writer_put_mov_reg_offset_ptr_reg( - cw, GUM_REG_EAX, offsetof(GumCpuContext, ebp), GUM_REG_EBP); + 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, offsetof(GumCpuContext, eip), GUM_REG_EBX); + 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, offsetof(GumCpuContext, esp), GUM_REG_EBX); + 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, offsetof(persistent_ctx_t, eflags), GUM_REG_EBX); + 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, offsetof(GumCpuContext, eax), GUM_REG_EBX); + 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, - persistent_ctx_t *regs) { +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, - offsetof(GumCpuContext, ecx)); + (0x4 * 2)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDX, GUM_REG_EAX, - offsetof(GumCpuContext, edx)); + (0x4 * 3)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EDI, GUM_REG_EAX, - offsetof(GumCpuContext, edi)); + (0x4 * 4)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESI, GUM_REG_EAX, - offsetof(GumCpuContext, esi)); + (0x4 * 5)); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX, - offsetof(GumCpuContext, ebp)); + (0x4 * 6)); - /* Don't restore RIP */ - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESP, GUM_REG_EAX, - offsetof(GumCpuContext, esp)); + /* 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, - offsetof(GumCpuContext, ebx)); + (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, - offsetof(GumCpuContext, 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, - offsetof(persistent_ctx_t, eflags)); + (0x4 * 9)); gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); gum_x86_writer_put_popfx(cw); @@ -130,7 +149,7 @@ static void instrument_exit(GumX86Writer *cw) { static int instrument_afl_persistent_loop_func(void) { int ret = __afl_persistent_loop(persistent_count); - instrument_previous_pc = instrument_hash_zero; + previous_pc = 0; return ret; } @@ -143,9 +162,9 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) { } -static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { +static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) { - if (persistent_hook == NULL) return; + if (hook == NULL) return; gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX, GUM_ADDRESS(&__afl_fuzz_len)); @@ -158,33 +177,14 @@ static void persistent_prologue_hook(GumX86Writer *cw, persistent_ctx_t *regs) { /* Base address is 64-bits (hence two zero arguments) */ gum_x86_writer_put_call_address_with_arguments( - cw, GUM_CALL_CAPI, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, - GUM_ADDRESS(®s->ctx), GUM_ARG_REGISTER, GUM_REG_EDX, GUM_ARG_REGISTER, + 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); } -static void instrument_persitent_save_ret(GumX86Writer *cw) { - - /* Stack usage by this function */ - gssize offset = (3 * 4); - - gum_x86_writer_put_pushfx(cw); - gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); - gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret)); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, - offset); - gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_EAX, GUM_REG_EBX); - - gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); - gum_x86_writer_put_popfx(cw); - -} - -void persistent_prologue_arch(GumStalkerOutput *output) { +void persistent_prologue(GumStalkerOutput *output) { /* * SAVE REGS @@ -210,12 +210,11 @@ void persistent_prologue_arch(GumStalkerOutput *output) { gconstpointer loop = cw->code + 1; - OKF("Persistent loop reached"); + /* 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); - - instrument_persitent_save_regs(cw, &saved_regs); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4)); /* loop: */ gum_x86_writer_put_label(cw, loop); @@ -245,20 +244,22 @@ void persistent_prologue_arch(GumStalkerOutput *output) { /* original: */ gum_x86_writer_put_label(cw, original); - instrument_persitent_save_ret(cw); - if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + gum_x86_writer_flush(cw); + } -void persistent_epilogue_arch(GumStalkerOutput *output) { +void persistent_epilogue(GumStalkerOutput *output) { GumX86Writer *cw = output->writer.x86; if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret)); - gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_EAX); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, + persistent_ret_offset); + + gum_x86_writer_put_ret(cw); } diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index 50d10c9e..65c09fba 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -2,11 +2,10 @@ #include <sys/shm.h> #include <sys/mman.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" -#include "intercept.h" #include "prefetch.h" #include "stalker.h" @@ -21,10 +20,9 @@ typedef struct { } prefetch_data_t; -gboolean prefetch_enable = TRUE; - static prefetch_data_t *prefetch_data = NULL; -static int prefetch_shm_id = -1; + +static int prefetch_shm_id = -1; /* * We do this from the transformer since we need one anyway for coverage, this @@ -74,33 +72,14 @@ void prefetch_read(void) { } -void prefetch_config(void) { - - prefetch_enable = (getenv("AFL_FRIDA_INST_NO_PREFETCH") == NULL); - -} - -static int prefetch_on_fork(void) { - - prefetch_read(); - return fork(); - -} - -static void prefetch_hook_fork(void) { - - void *fork_addr = - GSIZE_TO_POINTER(gum_module_find_export_by_name(NULL, "fork")); - intercept_hook(fork_addr, prefetch_on_fork, NULL); - -} - void prefetch_init(void) { g_assert_cmpint(sizeof(prefetch_data_t), ==, PREFETCH_SIZE); - OKF("Instrumentation - prefetch [%c]", prefetch_enable ? 'X' : ' '); + gboolean prefetch = (getenv("AFL_FRIDA_INST_NO_PREFETCH") == NULL); - if (!prefetch_enable) { return; } + 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 @@ -129,7 +108,5 @@ void prefetch_init(void) { /* Clear it, not sure it's necessary, just seems like good practice */ memset(prefetch_data, '\0', sizeof(prefetch_data_t)); - prefetch_hook_fork(); - } diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 6fdd65a7..ef25b371 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -17,16 +17,11 @@ typedef struct { } convert_name_ctx_t; -gboolean ranges_debug_maps = FALSE; -gboolean ranges_inst_libs = FALSE; -gboolean ranges_inst_jit = FALSE; - -static GArray *module_ranges = NULL; -static GArray *libs_ranges = NULL; -static GArray *jit_ranges = NULL; -static GArray *include_ranges = NULL; -static GArray *exclude_ranges = NULL; -static GArray *ranges = NULL; +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) { @@ -147,13 +142,11 @@ static void convert_name_token(gchar *token, GumMemoryRange *range) { static void convert_token(gchar *token, GumMemoryRange *range) { - if (g_str_has_prefix(token, "0x")) { + if (g_strrstr(token, "-")) { convert_address_token(token, range); - } - - else { + } else { convert_name_token(token, range); @@ -176,27 +169,19 @@ 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 %c%c%c", + 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, - details->protection & GUM_PAGE_READ ? 'R' : '-', - details->protection & GUM_PAGE_WRITE ? 'W' : '-', - details->protection & GUM_PAGE_EXECUTE ? 'X' : '-'); + details->range->base_address + details->range->size); } else { OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER - "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)", + "X %s(0x%016" G_GINT64_MODIFIER "x)", details->range->base_address, details->range->base_address + details->range->size, - details->protection & GUM_PAGE_READ ? 'R' : '-', - details->protection & GUM_PAGE_WRITE ? 'W' : '-', - details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path, - details->file->offset); + details->file->path, details->file->offset); } @@ -240,43 +225,6 @@ static GArray *collect_module_ranges(void) { } -static void check_for_overlaps(GArray *array) { - - for (guint i = 1; i < array->len; i++) { - - GumMemoryRange *prev = &g_array_index(array, GumMemoryRange, i - 1); - GumMemoryRange *curr = &g_array_index(array, 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); - - } - - } - -} - -void ranges_add_include(GumMemoryRange *range) { - - g_array_append_val(include_ranges, *range); - g_array_sort(include_ranges, range_sort); - check_for_overlaps(include_ranges); - -} - -void ranges_add_exclude(GumMemoryRange *range) { - - g_array_append_val(exclude_ranges, *range); - g_array_sort(exclude_ranges, range_sort); - check_for_overlaps(exclude_ranges); - -} - static GArray *collect_ranges(char *env_key) { char * env_val; @@ -305,7 +253,23 @@ static GArray *collect_ranges(char *env_key) { g_array_sort(result, range_sort); - check_for_overlaps(result); + /* 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); @@ -321,15 +285,15 @@ static GArray *collect_libs_ranges(void) { GumMemoryRange range; result = g_array_new(false, false, sizeof(GumMemoryRange)); - if (ranges_inst_libs) { + if (getenv("AFL_INST_LIBS") == NULL) { - range.base_address = 0; - range.size = G_MAXULONG; + range.base_address = lib_get_text_base(); + range.size = lib_get_text_limit() - lib_get_text_base(); } else { - range.base_address = lib_get_text_base(); - range.size = lib_get_text_limit() - lib_get_text_base(); + range.base_address = 0; + range.size = G_MAXULONG; } @@ -341,39 +305,6 @@ static GArray *collect_libs_ranges(void) { } -static gboolean collect_jit_ranges_callback(const GumRangeDetails *details, - gpointer user_data) { - - GArray *ranges = (GArray *)user_data; - - /* If the executable code isn't backed by a file, it's probably JIT */ - if (details->file == NULL) { - - GumMemoryRange range = *details->range; - g_array_append_val(ranges, range); - - } - - return TRUE; - -} - -static GArray *collect_jit_ranges(void) { - - GArray *result; - result = g_array_new(false, false, sizeof(GumMemoryRange)); - if (!ranges_inst_jit) { - - gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, collect_jit_ranges_callback, - result); - - } - - print_ranges("JIT", result); - return result; - -} - static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra, GumMemoryRange *rb) { @@ -549,21 +480,30 @@ static GArray *merge_ranges(GArray *a) { } -void ranges_config(void) { +static gboolean exclude_ranges_callback(const GumRangeDetails *details, + gpointer user_data) { - if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; } - if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; } - if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; } + UNUSED_PARAMETER(user_data); + gchar * name; + gboolean found; + GumStalker *stalker; + if (details->file == NULL) { return TRUE; } + name = g_path_get_basename(details->file->path); - if (ranges_debug_maps) { + found = (g_strcmp0(name, "afl-frida-trace.so") == 0); + g_free(name); + if (!found) { return TRUE; } - gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, - NULL); + stalker = stalker_get(); + gum_stalker_exclude(stalker, details->range); - } + return FALSE; - include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); - exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES"); +} + +static void ranges_exclude_self(void) { + + gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, exclude_ranges_callback, NULL); } @@ -574,22 +514,17 @@ void ranges_init(void) { GArray * step2; GArray * step3; GArray * step4; - GArray * step5; - OKF("Ranges - Instrument jit [%c]", ranges_inst_jit ? 'X' : ' '); - OKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' '); + if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { - print_ranges("AFL_FRIDA_INST_RANGES", include_ranges); - print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges); - - OKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' '); + gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, + NULL); - print_ranges("AFL_FRIDA_INST_RANGES", include_ranges); - print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges); + } module_ranges = collect_module_ranges(); libs_ranges = collect_libs_ranges(); - jit_ranges = collect_jit_ranges(); + include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); /* If include ranges is empty, then assume everything is included */ if (include_ranges->len == 0) { @@ -600,6 +535,8 @@ void ranges_init(void) { } + 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); @@ -612,25 +549,25 @@ void ranges_init(void) { step3 = subtract_ranges(step2, exclude_ranges); print_ranges("step3", step3); - step4 = subtract_ranges(step3, jit_ranges); - print_ranges("step4", step4); - /* - * After step4, we have the total ranges to be instrumented, we now subtract + * After step3, we have the total ranges to be instrumented, we now subtract * that from the original ranges of the modules to configure stalker. */ - step5 = subtract_ranges(module_ranges, step4); - print_ranges("step5", step5); - ranges = merge_ranges(step5); + step4 = subtract_ranges(module_ranges, step3); + print_ranges("step4", step4); + + ranges = merge_ranges(step4); print_ranges("final", ranges); - g_array_free(step5, TRUE); 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(); } diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c index 5df0386f..63f3c529 100644 --- a/frida_mode/src/stalker.c +++ b/frida_mode/src/stalker.c @@ -2,46 +2,17 @@ #include "instrument.h" #include "stalker.h" -#include "util.h" static GumStalker *stalker = NULL; -void stalker_config(void) { +void stalker_init(void) { if (!gum_stalker_is_supported()) { FATAL("Failed to initialize embedded"); } -} - -static gboolean stalker_exclude_self(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; - -} - -void stalker_init(void) { - stalker = gum_stalker_new(); if (stalker == NULL) { FATAL("Failed to initialize stalker"); } - gum_stalker_set_trust_threshold(stalker, -1); - - /* *NEVER* stalk the stalker, only bad things will ever come of this! */ - gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, stalker_exclude_self, NULL); + gum_stalker_set_trust_threshold(stalker, 0); } @@ -59,9 +30,3 @@ void stalker_start(void) { } -void stalker_trust(void) { - - gum_stalker_set_trust_threshold(stalker, 0); - -} - diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c index 91a58741..662fb6d5 100644 --- a/frida_mode/src/stats/stats.c +++ b/frida_mode/src/stats/stats.c @@ -5,7 +5,7 @@ #include <sys/shm.h> #include <sys/mman.h> -#include "frida-gumjs.h" +#include "frida-gum.h" #include "config.h" #include "debug.h" @@ -17,16 +17,15 @@ stats_data_header_t *stats_data = NULL; -static int stats_parent_pid = -1; -static int stats_fd = -1; +static int stats_parent_pid = -1; +static int stats_fd = -1; +static gboolean stats_transitions = FALSE; +static guint64 stats_interval = 0; -char * stats_filename = NULL; -guint64 stats_interval = 0; -gboolean stats_transitions = FALSE; - -void stats_config(void) { +void stats_init(void) { - stats_filename = getenv("AFL_FRIDA_STATS_FILE"); + 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) { @@ -34,16 +33,10 @@ void stats_config(void) { } -} - -void stats_init(void) { - - stats_parent_pid = getpid(); - - OKF("Stats - file [%s]", stats_filename); + OKF("Stats - file [%s]", filename); OKF("Stats - interval [%" G_GINT64_MODIFIER "u]", stats_interval); - if (stats_interval != 0 && stats_filename == NULL) { + if (stats_interval != 0 && filename == NULL) { FATAL( "AFL_FRIDA_STATS_FILE must be specified if " @@ -53,7 +46,7 @@ void stats_init(void) { if (stats_interval == 0) { stats_interval = 10; } - if (stats_filename == NULL) { return; } + if (filename == NULL) { return; } if (!stats_is_supported_arch()) { @@ -63,11 +56,11 @@ void stats_init(void) { char *path = NULL; - if (stats_filename == NULL) { return; } + if (filename == NULL) { return; } if (stats_transitions) { gum_stalker_set_counters_enabled(TRUE); } - path = g_canonicalize_filename(stats_filename, g_get_current_dir()); + path = g_canonicalize_filename(filename, g_get_current_dir()); OKF("Stats - path [%s]", path); @@ -103,6 +96,7 @@ void stats_init(void) { 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; } @@ -178,12 +172,10 @@ void stats_write(void) { } -void stats_on_fork(void) { +static void stats_maybe_write(void) { guint64 current_time; - if (stats_filename == NULL) { return; } - if (stats_interval == 0) { return; } current_time = g_get_monotonic_time(); @@ -210,5 +202,7 @@ void stats_collect(const cs_insn *instr, gboolean begin) { 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 index d9d374a4..592af87a 100644 --- a/frida_mode/src/stats/stats_arm64.c +++ b/frida_mode/src/stats/stats_arm64.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" diff --git a/frida_mode/src/stats/stats_x64.c b/frida_mode/src/stats/stats_x64.c index 11464a2a..c3e8742a 100644 --- a/frida_mode/src/stats/stats_x64.c +++ b/frida_mode/src/stats/stats_x64.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" @@ -31,9 +31,6 @@ typedef struct { guint64 num_rip_relative; - guint64 num_rip_relative_type[X86_INS_ENDING]; - char name_rip_relative_type[X86_INS_ENDING][CS_MNEMONIC_SIZE]; - } stats_data_arch_t; gboolean stats_is_supported_arch(void) { @@ -139,18 +136,6 @@ void stats_write_arch(void) { stats_data_arch->num_rip_relative, (stats_data_arch->num_rip_relative * 100 / num_instructions)); - for (size_t i = 0; i < X86_INS_ENDING; i++) { - - if (stats_data_arch->num_rip_relative_type[i] != 0) { - - stats_print(" %10d %s\n", - stats_data_arch->num_rip_relative_type[i], - stats_data_arch->name_rip_relative_type[i]); - - } - - } - stats_print("\n"); stats_print("\n"); @@ -271,9 +256,6 @@ static void stats_collect_rip_relative_arch(const cs_insn *instr) { if (rm != 5) { return; } stats_data_arch->num_rip_relative++; - stats_data_arch->num_rip_relative_type[instr->id]++; - memcpy(stats_data_arch->name_rip_relative_type[instr->id], instr->mnemonic, - CS_MNEMONIC_SIZE); } diff --git a/frida_mode/src/stats/stats_x86.c b/frida_mode/src/stats/stats_x86.c index d9c4f652..1906e809 100644 --- a/frida_mode/src/stats/stats_x86.c +++ b/frida_mode/src/stats/stats_x86.c @@ -1,4 +1,4 @@ -#include "frida-gumjs.h" +#include "frida-gum.h" #include "debug.h" diff --git a/frida_mode/test/cmplog/GNUmakefile b/frida_mode/test/cmplog/GNUmakefile index 4c71bb33..40de6a09 100644 --- a/frida_mode/test/cmplog/GNUmakefile +++ b/frida_mode/test/cmplog/GNUmakefile @@ -13,7 +13,7 @@ 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 frida-nocmplog format +.PHONY: all 32 clean qemu frida format all: $(TEST_CMPLOG_OBJ) make -C $(ROOT)frida_mode/ @@ -55,15 +55,6 @@ frida: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) -- \ $(TEST_CMPLOG_OBJ) @@ -frida-nocmplog: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) - $(ROOT)afl-fuzz \ - -O \ - -i $(TEST_DATA_DIR) \ - -o $(FRIDA_OUT) \ - -Z \ - -- \ - $(TEST_CMPLOG_OBJ) @@ - debug: $(TEST_CMPLOG_OBJ) $(CMP_LOG_INPUT) gdb \ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ diff --git a/frida_mode/test/cmplog/Makefile b/frida_mode/test/cmplog/Makefile index 7ca9a9a5..606b43a5 100644 --- a/frida_mode/test/cmplog/Makefile +++ b/frida_mode/test/cmplog/Makefile @@ -15,10 +15,6 @@ qemu: frida: @gmake frida - -frida-nocmplog: - @gmake frida-nocmplog - format: @gmake format diff --git a/frida_mode/test/cmplog/cmplog.c b/frida_mode/test/cmplog/cmplog.c index ce5cf20e..99010645 100644 --- a/frida_mode/test/cmplog/cmplog.c +++ b/frida_mode/test/cmplog/cmplog.c @@ -53,7 +53,7 @@ int main(int argc, char **argv) { } -#if defined(__x86_64__) || defined(__aarch64__) +#if defined(__x86_64__) uint64_t x = 0; fread(&x, sizeof(x), 1, file); if (x != 0xCAFEBABECAFEBABE) { diff --git a/frida_mode/test/deferred/GNUmakefile b/frida_mode/test/deferred/GNUmakefile index f7520051..c268ef66 100644 --- a/frida_mode/test/deferred/GNUmakefile +++ b/frida_mode/test/deferred/GNUmakefile @@ -10,7 +10,7 @@ TESTINSTSRC:=$(PWD)testinstr.c QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py ifndef ARCH @@ -24,24 +24,20 @@ ifeq "$(ARCH)" "i686" endif endif -ifeq "$(shell uname)" "Darwin" -TEST_BIN_LDFLAGS:=-Wl,-no_pie -endif - ARCH=$(shell uname -m) ifeq "$(ARCH)" "aarch64" - AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) run 0x0000aaaaaaaaa000) + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000) endif ifeq "$(ARCH)" "x86_64" - AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) run 0x0000555555554000) + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000) endif ifeq "$(ARCH)" "x86" - AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) run 0x56555000) + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000) endif -.PHONY: all clean frida +.PHONY: all clean qemu frida all: $(TESTINSTBIN) make -C $(ROOT)frida_mode/ @@ -59,7 +55,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) echo -n "000" > $@ $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) - $(CC) $(CFLAGS) $(LDFLAGS) $(TEST_BIN_LDFLAGS) -o $@ $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< clean: rm -rf $(BUILD_DIR) diff --git a/frida_mode/test/deferred/testinstr.c b/frida_mode/test/deferred/testinstr.c index c7a05ac5..8b3688d7 100644 --- a/frida_mode/test/deferred/testinstr.c +++ b/frida_mode/test/deferred/testinstr.c @@ -51,6 +51,7 @@ int run(char *file) { fd = open(file, O_RDONLY); if (fd < 0) { + perror("open"); break; diff --git a/frida_mode/test/entry_point/GNUmakefile b/frida_mode/test/entry_point/GNUmakefile index 5453c1ad..c99bcecb 100644 --- a/frida_mode/test/entry_point/GNUmakefile +++ b/frida_mode/test/entry_point/GNUmakefile @@ -10,7 +10,7 @@ TESTINSTSRC:=$(PWD)testinstr.c QEMU_OUT:=$(BUILD_DIR)qemu-out FRIDA_OUT:=$(BUILD_DIR)frida-out -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py ifndef ARCH @@ -24,21 +24,17 @@ ifeq "$(ARCH)" "i686" endif endif -ifeq "$(shell uname)" "Darwin" -TEST_BIN_LDFLAGS:=-Wl,-no_pie -endif - ARCH=$(shell uname -m) ifeq "$(ARCH)" "aarch64" - AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) run 0x0000aaaaaaaaa000) + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000) endif ifeq "$(ARCH)" "x86_64" - AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) run 0x0000555555554000) + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000) endif ifeq "$(ARCH)" "x86" - AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) run 0x56555000) + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x56555000) endif .PHONY: all clean qemu frida @@ -59,7 +55,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) echo -n "000" > $@ $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) - $(CC) $(CFLAGS) $(LDFLAGS) $(TEST_BIN_LDFLAGS) -o $@ $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< clean: rm -rf $(BUILD_DIR) diff --git a/frida_mode/test/fasan/GNUmakefile b/frida_mode/test/fasan/GNUmakefile index c971c724..08b271de 100644 --- a/frida_mode/test/fasan/GNUmakefile +++ b/frida_mode/test/fasan/GNUmakefile @@ -46,7 +46,7 @@ ifeq "$(ARCH)" "x86_64" LIBASAN_FILE:=libclang_rt.asan-x86_64.so endif -ifeq "$(ARCH)" "arm64" +ifeq "$(ARCH)" "aarch64" LIBASAN_FILE:=libclang_rt.asan-aarch64.so endif @@ -110,7 +110,7 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) mkdir -p $@ $(TEST_DATA_FILE): | $(TEST_DATA_DIR) - echo -n "XUODATM" > $@ + echo -n "TUODATM" > $@ frida-noasan: $(TEST_BIN) $(TEST_DATA_FILE) $(ROOT)afl-fuzz \ diff --git a/frida_mode/test/libpcap/GNUmakefile b/frida_mode/test/libpcap/GNUmakefile index f1ad06e4..e30f2049 100644 --- a/frida_mode/test/libpcap/GNUmakefile +++ b/frida_mode/test/libpcap/GNUmakefile @@ -2,8 +2,8 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so -AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so +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/ @@ -35,7 +35,7 @@ LDFLAGS += -lpthread TEST_BIN:=$(BUILD_DIR)test ifeq "$(shell uname)" "Darwin" -TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie +TEST_BIN_LDFLAGS:=-undefined dynamic_lookup endif AFLPP_DRIVER_DUMMY_INPUT:=$(TCPDUMP_TESTS_DIR)in @@ -55,20 +55,18 @@ ifeq "$(ARCH)" "i686" endif endif -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh - -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) + 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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + 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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000) endif .PHONY: all clean qemu frida hook @@ -139,6 +137,11 @@ $(TEST_BIN): $(HARNESS_OBJ) $(PCAPTEST_OBJ) $(LIBPCAP_LIB) $(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) @@ -146,11 +149,13 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(TCPDUMP_TESTS_DIR) ###### TEST DATA ####### +hook: $(AFLPP_DRIVER_HOOK_OBJ) + clean: rm -rf $(BUILD_DIR) -qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) | $(TCPDUMP_TESTS_DIR) - AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ +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 \ @@ -163,8 +168,8 @@ qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) | $( -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) | $(TCPDUMP_TESTS_DIR) - AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ +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 \ 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 <stdint.h> +#include <string.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]; + +}; + +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/persistent_ret/GNUmakefile b/frida_mode/test/persistent_ret/GNUmakefile index adcacf5a..df48d065 100644 --- a/frida_mode/test/persistent_ret/GNUmakefile +++ b/frida_mode/test/persistent_ret/GNUmakefile @@ -22,31 +22,23 @@ ifeq "$(ARCH)" "i686" endif endif -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh - -ifeq "$(shell uname)" "Darwin" -TEST_BIN_LDFLAGS:=-Wl,-no_pie -endif - ARCH=$(shell uname -m) ifeq "$(ARCH)" "aarch64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x0000aaaaaaaaa000) - AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x0000aaaaaaaaa000) + 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 $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x0000555555554000) - AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x0000555555554000) + 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 $(GET_SYMBOL_ADDR) $(TESTINSTBIN) main 0x56555000) - AFL_FRIDA_PERSISTENT_RET=$(shell $(GET_SYMBOL_ADDR) $(TESTINSTBIN) slow 0x56555000) + 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 -ifeq "$(shell uname)" "Darwin" -AFL_PRELOAD=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation -endif +AFL_FRIDA_PERSISTENT_RETADDR_OFFSET:=0x50 .PHONY: all 32 clean qemu frida @@ -66,7 +58,7 @@ $(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) echo -n "000" > $@ $(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) - $(CC) $(CFLAGS) $(LDFLAGS) $(TEST_BIN_LDFLAGS) -o $@ $< + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< clean: rm -rf $(BUILD_DIR) @@ -84,6 +76,7 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) 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 \ @@ -92,39 +85,21 @@ frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) -- \ $(TESTINSTBIN) @@ -frida_js: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) - AFL_PRELOAD=$(AFL_PRELOAD) \ - AFL_FRIDA_JS_SCRIPT=test.js \ - $(ROOT)afl-fuzz \ - -D \ - -O \ - -i $(TESTINSTR_DATA_DIR) \ - -o $(FRIDA_OUT) \ - -- \ - $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) - -debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) +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) -debug_js: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) - gdb \ - --ex 'set environment AFL_FRIDA_JS_SCRIPT=test.js' \ - --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: $(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/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 index 42e3519a..6cb88a50 100644 --- a/frida_mode/test/persistent_ret/testinstr.c +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -17,14 +17,13 @@ #include <unistd.h> #ifdef __APPLE__ - #define MAIN_SECTION + #define TESTINSTR_SECTION #else - #define MAIN_SECTION __attribute__((section(".main"))) + #define TESTINSTR_SECTION __attribute__((section(".testinstr"))) #endif -void LLVMFuzzerTestOneInput(char *buf, int len) { +void testinstr(char *buf, int len) { - printf (">>> LLVMFuzzerTestOneInput >>>\n"); if (len < 1) return; buf[len] = 0; @@ -44,7 +43,7 @@ void slow() { } -MAIN_SECTION int main(int argc, char **argv) { +TESTINSTR_SECTION int main(int argc, char **argv) { char * file; int fd = -1; @@ -102,7 +101,7 @@ MAIN_SECTION int main(int argc, char **argv) { dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); - LLVMFuzzerTestOneInput(buf, len); + testinstr(buf, len); dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); slow(); diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile index a1a7f1a5..e05bade2 100644 --- a/frida_mode/test/png/GNUmakefile +++ b/frida_mode/test/png/GNUmakefile @@ -22,7 +22,7 @@ PNGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmar TEST_BIN:=$(BUILD_DIR)test ifeq "$(shell uname)" "Darwin" -TEST_BIN_LDFLAGS:=-undefined dynamic_lookup -Wl,-no_pie +TEST_BIN_LDFLAGS:=-undefined dynamic_lookup endif TEST_DATA_DIR:=$(LIBPNG_DIR)contrib/pngsuite/ @@ -112,9 +112,3 @@ frida: $(TEST_BIN) -o $(FRIDA_OUT) \ -- \ $(TEST_BIN) @@ - -debug: - gdb \ - --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ - --ex 'set disassembly-flavor intel' \ - --args $(TEST_BIN) $(TEST_DATA_DIR)basn0g01.png diff --git a/frida_mode/test/png/Makefile b/frida_mode/test/png/Makefile index f843af19..4bef1ccb 100644 --- a/frida_mode/test/png/Makefile +++ b/frida_mode/test/png/Makefile @@ -14,6 +14,3 @@ qemu: frida: @gmake frida - -debug: - @gmake debug diff --git a/frida_mode/test/png/persistent/GNUmakefile b/frida_mode/test/png/persistent/GNUmakefile index c1ad86e5..ca6f0ff2 100644 --- a/frida_mode/test/png/persistent/GNUmakefile +++ b/frida_mode/test/png/persistent/GNUmakefile @@ -5,7 +5,6 @@ BUILD_DIR:=$(PWD)build/ 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 @@ -21,20 +20,19 @@ ifeq "$(ARCH)" "i686" endif endif -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh +AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x4000000000) -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x4000000000) - -ifeq "$(ARCH)" "arm64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x0000aaaaaaaaa000) +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 $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x0000555555554000) + 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 $(GET_SYMBOL_ADDR) $(TEST_BIN) main 0x56555000) + 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 @@ -48,9 +46,6 @@ all: $(BUILD_DIR): mkdir -p $@ -$(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) - truncate -s 1M $@ - qemu: | $(BUILD_DIR) AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ AFL_QEMU_PERSISTENT_GPR=1 \ @@ -99,12 +94,5 @@ frida_entry: | $(BUILD_DIR) -- \ $(TEST_BIN) @@ -debug: $(AFLPP_DRIVER_DUMMY_INPUT) - gdb \ - --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ - --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) diff --git a/frida_mode/test/png/persistent/Makefile b/frida_mode/test/png/persistent/Makefile index c2bd55f9..cde0cf30 100644 --- a/frida_mode/test/png/persistent/Makefile +++ b/frida_mode/test/png/persistent/Makefile @@ -20,6 +20,3 @@ frida: frida_entry: @gmake frida_entry - -debug: - @gmake debug 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 index ddf63a96..82f08fa4 100644 --- a/frida_mode/test/png/persistent/hook/GNUmakefile +++ b/frida_mode/test/png/persistent/hook/GNUmakefile @@ -2,8 +2,8 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so -AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so +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 \ @@ -32,29 +32,23 @@ ifeq "$(ARCH)" "i686" endif endif -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh +AFL_QEMU_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x4000000000) -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) - -ifeq "$(ARCH)" "arm64" - AFL_FRIDA_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) +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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + 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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) -endif - -ifeq "$(shell uname)" "Darwin" -AFL_PRELOAD=/System/Library/Frameworks/CoreFoundation.framework/CoreFoundation + 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: +all: $(AFLPP_DRIVER_HOOK_OBJ) make -C $(ROOT)frida_mode/test/png/persistent/ 32: @@ -74,8 +68,11 @@ $(TEST_DATA_DIR): | $(BUILD_DIR) $(AFLPP_DRIVER_DUMMY_INPUT): | $(BUILD_DIR) truncate -s 1M $@ -qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) | $(BUILD_DIR) - AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ +$(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 \ @@ -87,8 +84,8 @@ qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) | $(BUILD_DIR) -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -qemu_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) | $(BUILD_DIR) - AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ +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 \ @@ -101,8 +98,8 @@ qemu_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) | $(BUILD_ -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -frida: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) | $(BUILD_DIR) - AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ +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 \ @@ -114,8 +111,8 @@ frida: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) | $(BUILD_DIR) $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) | $(BUILD_DIR) - AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ +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 \ @@ -127,36 +124,11 @@ frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) | $(BUIL -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -frida_js_load: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) | $(BUILD_DIR) - AFL_PRELOAD=$(AFL_PRELOAD) \ - AFL_FRIDA_JS_SCRIPT=load.js \ - $(ROOT)afl-fuzz \ - -D \ - -V 30 \ - -O \ - -i $(TEST_DATA_DIR) \ - -o $(FRIDA_OUT) \ - -t 10000+ \ - -- \ - $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) - -frida_js_cmodule: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) | $(BUILD_DIR) - AFL_PRELOAD=$(AFL_PRELOAD) \ - AFL_FRIDA_JS_SCRIPT=cmodule.js \ - $(ROOT)afl-fuzz \ - -D \ - -V 30 \ - -O \ - -i $(TEST_DATA_DIR) \ - -o $(FRIDA_OUT) \ - -- \ - $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) - -debug: $(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_FRIDA_DRIVER_HOOK_OBJ)' \ + --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) diff --git a/frida_mode/test/png/persistent/hook/Makefile b/frida_mode/test/png/persistent/hook/Makefile index dca51d85..983d009e 100644 --- a/frida_mode/test/png/persistent/hook/Makefile +++ b/frida_mode/test/png/persistent/hook/Makefile @@ -24,8 +24,5 @@ frida: frida_entry: @gmake frida_entry -frida_js: - @gmake frida_js - 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 <stdint.h> +#include <string.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]; + +}; + +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 index ce95df3b..9f0b31d3 100644 --- a/frida_mode/test/re2/GNUmakefile +++ b/frida_mode/test/re2/GNUmakefile @@ -2,8 +2,8 @@ PWD:=$(shell pwd)/ ROOT:=$(shell realpath $(PWD)../../..)/ BUILD_DIR:=$(PWD)build/ -AFLPP_FRIDA_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/frida_hook.so -AFLPP_QEMU_DRIVER_HOOK_OBJ=$(ROOT)frida_mode/build/qemu_hook.so +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/ @@ -47,20 +47,18 @@ ifeq "$(ARCH)" "i686" endif endif -GET_SYMBOL_ADDR:=$(ROOT)frida_mode/util/get_symbol_addr.sh - -AFL_QEMU_PERSISTENT_ADDR=$(shell $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x4000000000) +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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000aaaaaaaaa000) + 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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x0000555555554000) + 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 $(GET_SYMBOL_ADDR) $(TEST_BIN) LLVMFuzzerTestOneInput 0x56555000) + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000) endif .PHONY: all clean qemu frida hook @@ -118,6 +116,11 @@ $(TEST_BIN): $(HARNESS_OBJ) $(RE2TEST_OBJ) $(LIBRE2_LIB) $(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) @@ -128,11 +131,13 @@ $(AFLPP_DRIVER_DUMMY_INPUT): | $(TEST_DATA_DIR) ###### TEST DATA ####### +hook: $(AFLPP_DRIVER_HOOK_OBJ) + clean: rm -rf $(BUILD_DIR) -qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) - AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_QEMU_DRIVER_HOOK_OBJ) \ +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 \ @@ -145,8 +150,8 @@ qemu: $(TEST_BIN) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) -frida: $(TEST_BIN) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_DRIVER_DUMMY_INPUT) - AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_FRIDA_DRIVER_HOOK_OBJ) \ +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 \ diff --git a/frida_mode/test/re2/Makefile b/frida_mode/test/re2/Makefile index 360cdc44..00b2b287 100644 --- a/frida_mode/test/re2/Makefile +++ b/frida_mode/test/re2/Makefile @@ -18,3 +18,5 @@ 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 <stdint.h> +#include <string.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]; + +}; + +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 index 3701ddc8..a35073ab 100644 --- a/frida_mode/test/testinstr/GNUmakefile +++ b/frida_mode/test/testinstr/GNUmakefile @@ -53,13 +53,6 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) $(TESTINSTBIN) @@ debug: - echo $(AFL_FRIDA_PERSISTENT_ADDR) - gdb \ - --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ - --ex 'set disassembly-flavor intel' \ - --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) - -debug: gdb \ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ --ex 'set disassembly-flavor intel' \ diff --git a/include/config.h b/include/config.h index 9d732e53..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.14a" +#define VERSION "++3.13c" /****************************************************** * * diff --git a/include/envs.h b/include/envs.h index 26cc250f..15116fc1 100644 --- a/include/envs.h +++ b/include/envs.h @@ -56,14 +56,10 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_DEBUG_MAPS", "AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_INST_DEBUG_FILE", - "AFL_FRIDA_INST_JIT", "AFL_FRIDA_INST_NO_OPTIMIZE", "AFL_FRIDA_INST_NO_PREFETCH", "AFL_FRIDA_INST_RANGES", - "AFL_FRIDA_INST_SEED", "AFL_FRIDA_INST_TRACE", - "AFL_FRIDA_INST_TRACE_UNIQUE", - "AFL_FRIDA_JS_SCRIPT", "AFL_FRIDA_OUTPUT_STDOUT", "AFL_FRIDA_OUTPUT_STDERR", "AFL_FRIDA_PERSISTENT_ADDR", @@ -71,6 +67,7 @@ static char *afl_environment_variables[] = { "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", diff --git a/instrumentation/README.llvm.md b/instrumentation/README.llvm.md index 2d428e6d..8ce5afb9 100644 --- a/instrumentation/README.llvm.md +++ b/instrumentation/README.llvm.md @@ -6,7 +6,7 @@ ## 1) Introduction -! llvm_mode works with llvm versions 3.8 up to 12 ! +! llvm_mode works with llvm versions 6.0 up to 12 ! The code in this directory allows you to instrument programs for AFL using true compiler-level instrumentation, instead of the more crude diff --git a/instrumentation/SanitizerCoverageLTO.so.cc b/instrumentation/SanitizerCoverageLTO.so.cc index 91b81910..eddbfcc8 100644 --- a/instrumentation/SanitizerCoverageLTO.so.cc +++ b/instrumentation/SanitizerCoverageLTO.so.cc @@ -1514,9 +1514,6 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, if (use_threadsafe_counters) { /* Atomic */ IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, -#if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), -#endif llvm::AtomicOrdering::Monotonic); } else { diff --git a/instrumentation/SanitizerCoveragePCGUARD.so.cc b/instrumentation/SanitizerCoveragePCGUARD.so.cc index 48ad2d02..4a8c9e28 100644 --- a/instrumentation/SanitizerCoveragePCGUARD.so.cc +++ b/instrumentation/SanitizerCoveragePCGUARD.so.cc @@ -1074,9 +1074,6 @@ void ModuleSanitizerCoverage::InjectCoverageAtBlock(Function &F, BasicBlock &BB, if (use_threadsafe_counters) { IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, -#if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), -#endif llvm::AtomicOrdering::Monotonic); } else { diff --git a/instrumentation/afl-compiler-rt.o.c b/instrumentation/afl-compiler-rt.o.c index b01ea987..3fec291c 100644 --- a/instrumentation/afl-compiler-rt.o.c +++ b/instrumentation/afl-compiler-rt.o.c @@ -83,15 +83,14 @@ extern ssize_t _kern_write(int fd, off_t pos, const void *buffer, size_t bufferSize); #endif // HAIKU -static u8 __afl_area_initial[MAP_INITIAL_SIZE]; -static u8 *__afl_area_ptr_dummy = __afl_area_initial; -static u8 *__afl_area_ptr_backup = __afl_area_initial; - -u8 * __afl_area_ptr = __afl_area_initial; -u8 * __afl_dictionary; -u8 * __afl_fuzz_ptr; -static u32 __afl_fuzz_len_dummy; -u32 * __afl_fuzz_len = &__afl_fuzz_len_dummy; +u8 __afl_area_initial[MAP_INITIAL_SIZE]; +u8 * __afl_area_ptr_dummy = __afl_area_initial; +u8 * __afl_area_ptr = __afl_area_initial; +u8 * __afl_area_ptr_backup = __afl_area_initial; +u8 * __afl_dictionary; +u8 * __afl_fuzz_ptr; +u32 __afl_fuzz_len_dummy; +u32 *__afl_fuzz_len = &__afl_fuzz_len_dummy; u32 __afl_final_loc; u32 __afl_map_size = MAP_SIZE; diff --git a/instrumentation/afl-llvm-dict2file.so.cc b/instrumentation/afl-llvm-dict2file.so.cc index 9daa75a8..58f01920 100644 --- a/instrumentation/afl-llvm-dict2file.so.cc +++ b/instrumentation/afl-llvm-dict2file.so.cc @@ -541,12 +541,7 @@ bool AFLdict2filePass::runOnModule(Module &M) { uint64_t literalLength = optLen; optLen = ilen->getZExtValue(); - if (optLen > thestring.length() + 1) { - - optLen = thestring.length() + 1; - - } - + if (optLen > thestring.length()) { optLen = thestring.length(); } if (optLen < 2) { continue; } if (literalLength + 1 == optLen) { // add null byte thestring.append("\0", 1); diff --git a/instrumentation/afl-llvm-lto-instrumentation.so.cc b/instrumentation/afl-llvm-lto-instrumentation.so.cc index 263d947d..46aa388e 100644 --- a/instrumentation/afl-llvm-lto-instrumentation.so.cc +++ b/instrumentation/afl-llvm-lto-instrumentation.so.cc @@ -852,9 +852,6 @@ bool AFLLTOPass::runOnModule(Module &M) { if (use_threadsafe_counters) { IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, -#if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), -#endif llvm::AtomicOrdering::Monotonic); } else { diff --git a/instrumentation/afl-llvm-pass.so.cc b/instrumentation/afl-llvm-pass.so.cc index ecf28f31..b673d815 100644 --- a/instrumentation/afl-llvm-pass.so.cc +++ b/instrumentation/afl-llvm-pass.so.cc @@ -676,12 +676,9 @@ bool AFLCoverage::runOnModule(Module &M) { todo.push_back(MapPtrIdx); } else { - + */ IRB.CreateAtomicRMW(llvm::AtomicRMWInst::BinOp::Add, MapPtrIdx, One, -#if LLVM_VERSION_MAJOR >= 13 - llvm::MaybeAlign(1), -#endif llvm::AtomicOrdering::Monotonic); /* diff --git a/src/afl-analyze.c b/src/afl-analyze.c index dbf2920f..a5cad03c 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -877,8 +877,6 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-analyze" VERSION cRST " by Michal Zalewski\n"); - afl_fsrv_init(&fsrv); - while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) { switch (opt) { @@ -987,6 +985,14 @@ int main(int argc, char **argv_orig, char **envp) { break; + case 'O': /* FRIDA mode */ + + if (frida_mode) { FATAL("Multiple -O options not supported"); } + + frida_mode = 1; + + break; + case 'Q': if (qemu_mode) { FATAL("Multiple -Q options not supported"); } diff --git a/src/afl-cc.c b/src/afl-cc.c index 9899f973..6a60fb85 100644 --- a/src/afl-cc.c +++ b/src/afl-cc.c @@ -637,33 +637,6 @@ static void edit_params(u32 argc, char **argv, char **envp) { } - if (cmplog_mode) { - - if (lto_mode && !have_c) { - - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-instructions-pass.so", obj_path); - cc_params[cc_par_cnt++] = alloc_printf( - "-Wl,-mllvm=-load=%s/cmplog-routines-pass.so", obj_path); - - } else { - - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-instructions-pass.so", obj_path); - - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = "-load"; - cc_params[cc_par_cnt++] = "-Xclang"; - cc_params[cc_par_cnt++] = - alloc_printf("%s/cmplog-routines-pass.so", obj_path); - - } - - } - // cc_params[cc_par_cnt++] = "-Qunused-arguments"; // in case LLVM is installed not via a package manager or "make install" diff --git a/src/afl-forkserver.c b/src/afl-forkserver.c index 5e8fb9b5..8fb8a75a 100644 --- a/src/afl-forkserver.c +++ b/src/afl-forkserver.c @@ -418,7 +418,8 @@ void afl_fsrv_start(afl_forkserver_t *fsrv, char **argv, struct rlimit r; - if (!fsrv->cmplog_binary) { + if (!fsrv->cmplog_binary && fsrv->qemu_mode == false && + fsrv->frida_mode == false) { unsetenv(CMPLOG_SHM_ENV_VAR); // we do not want that in non-cmplog fsrv diff --git a/src/afl-fuzz-one.c b/src/afl-fuzz-one.c index 7274f679..1bc5854e 100644 --- a/src/afl-fuzz-one.c +++ b/src/afl-fuzz-one.c @@ -2102,9 +2102,9 @@ havoc_stage: case 8 ... 9: { - /* Set word to interesting value, little endian. */ + case 8 ... 9: { - if (temp_len < 2) { break; } + /* Set word to interesting value, little endian. */ #ifdef INTROSPECTION snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING16"); @@ -2119,7 +2119,7 @@ havoc_stage: case 10 ... 11: { - /* Set word to interesting value, big endian. */ + /* Set word to interesting value, randomly choosing endian. */ if (temp_len < 2) { break; } @@ -2136,9 +2136,9 @@ havoc_stage: case 12 ... 13: { - /* Set dword to interesting value, little endian. */ + case 12 ... 13: { - if (temp_len < 4) { break; } + /* Set dword to interesting value, little endian. */ #ifdef INTROSPECTION snprintf(afl->m_tmp, sizeof(afl->m_tmp), " INTERESTING32"); @@ -2153,7 +2153,7 @@ havoc_stage: case 14 ... 15: { - /* Set dword to interesting value, big endian. */ + /* Set dword to interesting value, randomly choosing endian. */ if (temp_len < 4) { break; } diff --git a/src/afl-fuzz-run.c b/src/afl-fuzz-run.c index e876beea..fb81522e 100644 --- a/src/afl-fuzz-run.c +++ b/src/afl-fuzz-run.c @@ -424,8 +424,7 @@ u8 calibrate_case(afl_state_t *afl, struct queue_entry *q, u8 *use_mem, } var_detected = 1; - afl->stage_max = - afl->afl_env.afl_cal_fast ? CAL_CYCLES : CAL_CYCLES_LONG; + afl->stage_max = afl->fast_cal ? CAL_CYCLES : CAL_CYCLES_LONG; } else { diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index e0930234..c2294f7c 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -881,6 +881,10 @@ void show_stats(afl_state_t *afl) { strcpy(tmp, "disabled (custom-mutator-only mode)"); + if (unlikely(afl->custom_only)) { + + strcpy(tmp, "disabled (custom-mutator-only mode)"); + } else if (likely(afl->skip_deterministic)) { strcpy(tmp, "disabled (default, enable with -D)"); @@ -1017,10 +1021,9 @@ void show_stats(afl_state_t *afl) { if (unlikely(afl->afl_env.afl_custom_mutator_library)) { strcat(tmp, " "); - strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_CUSTOM_MUTATOR])); + strcat(tmp, u_stringify_int(IB(2), afl->stage_finds[STAGE_PYTHON])); strcat(tmp, "/"); - strcat(tmp, - u_stringify_int(IB(3), afl->stage_cycles[STAGE_CUSTOM_MUTATOR])); + strcat(tmp, u_stringify_int(IB(3), afl->stage_cycles[STAGE_PYTHON])); strcat(tmp, ","); } else { diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 5c899e69..5278c839 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -90,8 +90,7 @@ static bool quiet_mode, /* Hide non-essential messages? */ have_coverage, /* have coverage? */ no_classify, /* do not classify counts */ debug, /* debug mode */ - print_filenames, /* print the current filename */ - wait_for_gdb; + print_filenames; /* print the current filename */ static volatile u8 stop_soon, /* Ctrl-C pressed? */ child_crashed; /* Child crashed? */ @@ -426,6 +425,18 @@ static u32 read_file(u8 *in_file) { } + if (st.st_size > MAX_FILE) { + + WARNF("Input file '%s' is too large, only reading %u bytes.", in_file, + MAX_FILE); + in_len = MAX_FILE; + + } else { + + in_len = st.st_size; + + } + in_data = ck_alloc_nozero(in_len); ck_read(fd, in_data, in_len, in_file); @@ -819,13 +830,13 @@ static void usage(u8 *argv0) { " -o file - file to write the trace data to\n\n" "Execution control settings:\n" - " -t msec - timeout for each run (none)\n" - " -m megs - memory limit for child process (%u MB)\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" - " -W - use qemu-based instrumentation with Wine (Wine mode)\n" - " (Not necessary, here for consistency with other afl-* " + " -t msec - timeout for each run (none)\n" + " -m megs - memory limit for child process (%u MB)\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" + " -W - use qemu-based instrumentation with Wine (Wine mode)\n" + " (Not necessary, here for consistency with other afl-* " "tools)\n\n" "Other settings:\n" " -i dir - process all files below this directory, must be combined " @@ -862,8 +873,7 @@ static void usage(u8 *argv0) { "AFL_PRELOAD: LD_PRELOAD / DYLD_INSERT_LIBRARIES settings for target\n" "AFL_PRINT_FILENAMES: If set, the filename currently processed will be " "printed to stdout\n" - "AFL_QUIET: do not print extra informational output\n" - "AFL_NO_FORKSRV: run target via execve instead of using the forkserver\n", + "AFL_QUIET: do not print extra informational output\n", argv0, MEM_LIMIT, doc_path); exit(1); @@ -1248,7 +1258,15 @@ int main(int argc, char **argv_orig, char **envp) { if (in_dir) { - DIR *dir_in, *dir_out = NULL; + DIR * dir_in, *dir_out = NULL; + struct dirent **file_list; + + // int done = 0; + u8 infile[PATH_MAX], outfile[PATH_MAX]; + u8 wait_for_gdb = 0; +#if !defined(DT_REG) + struct stat statbuf; +#endif if (getenv("AFL_DEBUG_GDB")) wait_for_gdb = true; @@ -1349,12 +1367,28 @@ int main(int argc, char **argv_orig, char **envp) { if (fsrv->support_shmem_fuzz && !fsrv->use_shmem_fuzz) shm_fuzz = deinit_shmem(fsrv, shm_fuzz); - if (execute_testcases(in_dir) == 0) { + int file_count = scandir(in_dir, &file_list, NULL, alphasort); + if (file_count < 0) { + + PFATAL("Failed to read from input dir at %s\n", in_dir); + + } + + for (int i = 0; i < file_count; i++) { + + struct dirent *dir_ent = file_list[i]; + + if (dir_ent->d_name[0] == '.') { + + continue; // skip anything that starts with '.' FATAL("could not read input testcases from %s", in_dir); } + free(file_list); + file_list = NULL; + if (!quiet_mode) { OKF("Processed %llu input files.", fsrv->total_execs); } if (dir_out) { closedir(dir_out); } diff --git a/test/test-llvm.sh b/test/test-llvm.sh index aa40c5ed..f902ffc5 100755 --- a/test/test-llvm.sh +++ b/test/test-llvm.sh @@ -186,29 +186,6 @@ test -e ../afl-clang-fast -a -e ../split-switches-pass.so && { } rm -f test-instr.plain - $ECHO "$GREY[*] llvm_mode laf-intel/compcov testing splitting integer types (this might take some time)" - for testcase in ./test-int_cases.c ./test-uint_cases.c; do - for I in char short int long "long long"; do - for BITS in 8 16 32 64; do - bin="$testcase-split-$I-$BITS.compcov" - AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_COMPARES_BITW=$BITS AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -fsigned-char -DINT_TYPE="$I" -o "$bin" "$testcase" > test.out 2>&1; - if ! test -e "$bin"; then - cat test.out - $ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting failed! ($testcase with type $I split to $BITS)!"; - CODE=1 - break - fi - if ! "$bin"; then - $ECHO "$RED[!] llvm_mode laf-intel/compcov integer splitting resulted in miscompilation (type $I split to $BITS)!"; - CODE=1 - break - fi - rm -f "$bin" test.out || true - done - done - done - rm -f test-int-split*.compcov test.out - AFL_LLVM_INSTRUMENT=AFL AFL_DEBUG=1 AFL_LLVM_LAF_SPLIT_SWITCHES=1 AFL_LLVM_LAF_TRANSFORM_COMPARES=1 AFL_LLVM_LAF_SPLIT_COMPARES=1 ../afl-clang-fast -o test-compcov.compcov test-compcov.c > test.out 2>&1 test -e test-compcov.compcov && test_compcov_binary_functionality ./test-compcov.compcov && { grep --binary-files=text -Eq " [ 123][0-9][0-9] location| [3-9][0-9] location" test.out && { diff --git a/unicorn_mode/UNICORNAFL_VERSION b/unicorn_mode/UNICORNAFL_VERSION index 5db24eec..ffcf3b4c 100644 --- a/unicorn_mode/UNICORNAFL_VERSION +++ b/unicorn_mode/UNICORNAFL_VERSION @@ -1 +1 @@ -0d82727f2b477de82fa355edef9bc158bd25d374 +019b871539fe9ed3f41d882385a8b02c243d49ad diff --git a/utils/aflpp_driver/GNUmakefile b/utils/aflpp_driver/GNUmakefile index c282a9f3..a6abe08c 100644 --- a/utils/aflpp_driver/GNUmakefile +++ b/utils/aflpp_driver/GNUmakefile @@ -29,14 +29,14 @@ aflpp_qemu_driver.o: aflpp_qemu_driver.c -$(LLVM_BINDIR)clang $(CFLAGS) -O0 -funroll-loops -c aflpp_qemu_driver.c libAFLQemuDriver.a: aflpp_qemu_driver.o - @-ar rc libAFLQemuDriver.a aflpp_qemu_driver.o - @-cp -vf libAFLQemuDriver.a ../../ + -ar ru libAFLQemuDriver.a aflpp_qemu_driver.o + -cp -vf libAFLQemuDriver.a ../../ aflpp_qemu_driver_hook.so: aflpp_qemu_driver_hook.o - @-test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." + -test -e aflpp_qemu_driver_hook.o && $(LLVM_BINDIR)clang -shared aflpp_qemu_driver_hook.o -o aflpp_qemu_driver_hook.so || echo "Note: Optional aflpp_qemu_driver_hook.so not built." aflpp_qemu_driver_hook.o: aflpp_qemu_driver_hook.c - @-test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." + -test -e ../../qemu_mode/qemuafl/qemuafl/api.h && $(LLVM_BINDIR)clang $(CFLAGS) -funroll-loops -c aflpp_qemu_driver_hook.c || echo "Note: Optional aflpp_qemu_driver_hook.o not built." test: debug #clang -S -emit-llvm -D_DEBUG=\"1\" -I../../include -Wl,--allow-multiple-definition -funroll-loops -o aflpp_driver_test.ll aflpp_driver_test.c diff --git a/utils/aflpp_driver/README.md b/utils/aflpp_driver/README.md index 4ca59776..f03c2fe3 100644 --- a/utils/aflpp_driver/README.md +++ b/utils/aflpp_driver/README.md @@ -22,8 +22,6 @@ or `@@` as command line parameters. ## aflpp_qemu_driver -Note that you can use the driver too for frida_mode (`-O`). - aflpp_qemu_driver is used for libfuzzer `LLVMFuzzerTestOneInput()` targets that are to be fuzzed in qemu_mode. So we compile them with clang/clang++, without -fsantize=fuzzer or afl-clang-fast, and link in libAFLQemuDriver.a: @@ -36,8 +34,3 @@ Then just do (where the name of the binary is `fuzz`): AFL_QEMU_PERSISTENT_ADDR=0x$(nm fuzz | grep "T LLVMFuzzerTestOneInput" | awk '{print $1}') AFL_QEMU_PERSISTENT_HOOK=/path/to/aflpp_qemu_driver_hook.so afl-fuzz -Q ... -- ./fuzz` ``` - -if you use afl-cmin or `afl-showmap -C` with the aflpp_qemu_driver you need to -set the set same AFL_QEMU_... (or AFL_FRIDA_...) environment variables. -If you want to use afl-showmap (without -C) or afl-cmin.bash then you may not -set these environment variables and rather set `AFL_QEMU_DRIVER_NO_HOOK=1`. diff --git a/utils/aflpp_driver/aflpp_driver.c b/utils/aflpp_driver/aflpp_driver.c index ff42f3b9..c094c425 100644 --- a/utils/aflpp_driver/aflpp_driver.c +++ b/utils/aflpp_driver/aflpp_driver.c @@ -204,23 +204,21 @@ static int ExecuteFilesOnyByOne(int argc, char **argv) { int main(int argc, char **argv) { - if (argc < 2 || strncmp(argv[1], "-h", 2) == 0) - printf( - "============================== INFO ================================\n" - "This binary is built for afl++.\n" - "To use with afl-cmin or afl-cmin.bash pass '-' as single command line " - "option\n" - "To run the target function on individual input(s) execute this:\n" - " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n" - "To fuzz with afl-fuzz execute this:\n" - " afl-fuzz [afl-flags] -- %s [-N]\n" - "afl-fuzz will run N iterations before re-spawning the process " - "(default: " - "INT_MAX)\n" - "For stdin input processing, pass '-' as single command line option.\n" - "For file input processing, pass '@@' as single command line option.\n" - "===================================================================\n", - argv[0], argv[0]); + printf( + "============================== INFO ================================\n" + "This binary is built for afl++.\n" + "To use with afl-cmin or afl-cmin.bash pass '-' as single command line " + "option\n" + "To run the target function on individual input(s) execute this:\n" + " %s INPUT_FILE1 [INPUT_FILE2 ... ]\n" + "To fuzz with afl-fuzz execute this:\n" + " afl-fuzz [afl-flags] -- %s [-N]\n" + "afl-fuzz will run N iterations before re-spawning the process (default: " + "INT_MAX)\n" + "For stdin input processing, pass '-' as single command line option.\n" + "For file input processing, pass '@@' as single command line option.\n" + "===================================================================\n", + argv[0], argv[0]); if (getenv("AFL_GDB")) { |