diff options
-rw-r--r-- | .gitignore | 3 | ||||
-rw-r--r-- | .gitmodules | 6 | ||||
-rw-r--r-- | GNUmakefile | 16 | ||||
-rw-r--r-- | coresight_mode/.gitignore | 2 | ||||
-rw-r--r-- | coresight_mode/GNUmakefile | 62 | ||||
-rw-r--r-- | coresight_mode/Makefile | 21 | ||||
-rw-r--r-- | coresight_mode/README.md | 64 | ||||
m--------- | coresight_mode/coresight-trace | 0 | ||||
m--------- | coresight_mode/patchelf | 0 | ||||
-rw-r--r-- | coresight_mode/patches/0001-Add-AFL-forkserver.patch | 117 | ||||
-rw-r--r-- | include/common.h | 1 | ||||
-rw-r--r-- | include/forkserver.h | 2 | ||||
-rw-r--r-- | src/afl-analyze.c | 22 | ||||
-rw-r--r-- | src/afl-common.c | 29 | ||||
-rw-r--r-- | src/afl-fuzz-init.c | 5 | ||||
-rw-r--r-- | src/afl-fuzz-stats.c | 9 | ||||
-rw-r--r-- | src/afl-fuzz.c | 51 | ||||
-rw-r--r-- | src/afl-showmap.c | 25 | ||||
-rw-r--r-- | src/afl-tmin.c | 21 |
19 files changed, 439 insertions, 17 deletions
diff --git a/.gitignore b/.gitignore index 5268bb37..22ee6bf1 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ afl-g++-fast afl-gotcpu afl-ld afl-ld-lto +afl-cs-proxy afl-qemu-trace afl-showmap afl-tmin @@ -94,3 +95,5 @@ utils/optimin/optimin utils/persistent_mode/persistent_demo utils/persistent_mode/persistent_demo_new utils/persistent_mode/test-instr +!coresight_mode +!coresight_mode/coresight-trace diff --git a/.gitmodules b/.gitmodules index 200f3ecc..cd9d73e9 100644 --- a/.gitmodules +++ b/.gitmodules @@ -13,3 +13,9 @@ [submodule "utils/optimin/EvalMaxSAT"] path = utils/optimin/EvalMaxSAT url = https://github.com/FlorentAvellaneda/EvalMaxSAT +[submodule "coresight_mode/patchelf"] + path = coresight_mode/patchelf + url = https://github.com/NixOS/patchelf.git +[submodule "coresight_mode/coresight-trace"] + path = coresight_mode/coresight-trace + url = git@github.com:RICSecLab/coresight-trace.git diff --git a/GNUmakefile b/GNUmakefile index 06840786..ab57e7ad 100644 --- a/GNUmakefile +++ b/GNUmakefile @@ -346,7 +346,7 @@ help: @echo "HELP --- the following make targets exist:" @echo "==========================================" @echo "all: just the main afl++ binaries" - @echo "binary-only: everything for binary-only fuzzing: qemu_mode, unicorn_mode, libdislocator, libtokencap" + @echo "binary-only: everything for binary-only fuzzing: coresight_mode, qemu_mode, unicorn_mode, libdislocator, libtokencap" @echo "source-only: everything for source code fuzzing: gcc_plugin, libdislocator, libtokencap" @echo "distrib: everything (for both binary-only and source code fuzzing)" @echo "man: creates simple man pages from the help option of the programs" @@ -564,7 +564,7 @@ all_done: test_build .PHONY: clean clean: - rm -rf $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM + rm -rf $(PROGS) libradamsa.so afl-fuzz-document afl-as as afl-g++ afl-clang afl-clang++ *.o src/*.o *~ a.out core core.[1-9][0-9]* *.stackdump .test .test1 .test2 test-instr .test-instr0 .test-instr1 afl-cs-proxy afl-qemu-trace afl-gcc-fast afl-gcc-pass.so afl-g++-fast ld *.so *.8 test/unittests/*.o test/unittests/unit_maybe_alloc test/unittests/preallocable .afl-* afl-gcc afl-g++ afl-clang afl-clang++ test/unittests/unit_hash test/unittests/unit_rand *.dSYM -$(MAKE) -f GNUmakefile.llvm clean -$(MAKE) -f GNUmakefile.gcc_plugin clean $(MAKE) -C utils/libdislocator clean @@ -579,19 +579,23 @@ clean: $(MAKE) -C qemu_mode/libqasan clean -$(MAKE) -C frida_mode clean ifeq "$(IN_REPO)" "1" + -test -e coresight_mode/coresight-trace/Makefile && $(MAKE) -C coresight_mode/coresight-trace clean || true -test -e qemu_mode/qemuafl/Makefile && $(MAKE) -C qemu_mode/qemuafl clean || true test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true else + rm -rf coresight_mode/coresight_trace rm -rf qemu_mode/qemuafl rm -rf unicorn_mode/unicornafl endif .PHONY: deepclean deepclean: clean + rm -rf coresight_mode/coresight-trace rm -rf unicorn_mode/unicornafl rm -rf qemu_mode/qemuafl ifeq "$(IN_REPO)" "1" # NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true + git checkout coresight_mode/coresight-trace git checkout unicorn_mode/unicornafl git checkout qemu_mode/qemuafl endif @@ -610,6 +614,9 @@ endif # -$(MAKE) -C utils/plot_ui -$(MAKE) -C frida_mode ifneq "$(SYS)" "Darwin" +ifeq "$(ARCH)" "aarch64" + -$(MAKE) -C coresight_mode +endif -cd qemu_mode && sh ./build_qemu_support.sh -cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh endif @@ -624,6 +631,9 @@ binary-only: test_shm test_python ready $(PROGS) # -$(MAKE) -C utils/plot_ui -$(MAKE) -C frida_mode ifneq "$(SYS)" "Darwin" +ifeq "$(ARCH)" "aarch64" + -$(MAKE) -C coresight_mode +endif -cd qemu_mode && sh ./build_qemu_support.sh -cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh endif @@ -695,7 +705,7 @@ endif .PHONY: uninstall uninstall: - -cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto* + -cd $${DESTDIR}$(BIN_PATH) && rm -f $(PROGS) $(SH_PROGS) afl-cs-proxy afl-qemu-trace afl-plot-ui afl-fuzz-document afl-network-server afl-g* afl-plot.sh afl-as afl-ld-lto afl-c* afl-lto* -cd $${DESTDIR}$(HELPER_PATH) && rm -f afl-g*.*o afl-llvm-*.*o afl-compiler-*.*o libdislocator.so libtokencap.so libcompcov.so libqasan.so afl-frida-trace.so socketfuzz*.so argvfuzz*.so libAFLDriver.a libAFLQemuDriver.a as afl-as SanitizerCoverage*.so compare-transform-pass.so cmplog-*-pass.so split-*-pass.so dynamic_list.txt -rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries -sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f" diff --git a/coresight_mode/.gitignore b/coresight_mode/.gitignore new file mode 100644 index 00000000..dedb1613 --- /dev/null +++ b/coresight_mode/.gitignore @@ -0,0 +1,2 @@ +.local +glibc* diff --git a/coresight_mode/GNUmakefile b/coresight_mode/GNUmakefile new file mode 100644 index 00000000..9ab30ff7 --- /dev/null +++ b/coresight_mode/GNUmakefile @@ -0,0 +1,62 @@ +#!/usr/bin/env make +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2021 Ricerca Security, Inc. All rights reserved. + +SHELL:=bash +PREFIX?=$(shell pwd)/.local + +CS_TRACE:=coresight-trace + +PATCHELF?=$(PREFIX)/bin/patchelf + +PATCH_DIR:=patches + +GLIBC_VER:=2.33 +GLIBC_NAME:=glibc-$(GLIBC_VER) +GLIBC_URL_BASE:=http://ftp.gnu.org/gnu/glibc +GLIBC_LDSO?=$(PREFIX)/lib/ld-linux-aarch64.so.1 + +OUTPUT?="$(TARGET).patched" + +all: build + +build: + git submodule update --init --recursive $(CS_TRACE) + $(MAKE) -C $(CS_TRACE) + cp $(CS_TRACE)/cs-proxy ../afl-cs-proxy + +patch: | $(PATCHELF) $(GLIBC_LDSO) + @if test -z "$(TARGET)"; then echo "TARGET is not set"; exit 1; fi + $(PATCHELF) \ + --set-interpreter $(GLIBC_LDSO) \ + --set-rpath $(dir $(GLIBC_LDSO)) \ + --output $(OUTPUT) \ + $(TARGET) + +$(PATCHELF): patchelf + git submodule update --init $< + cd $< && \ + ./bootstrap.sh && \ + ./configure --prefix=$(PREFIX) && \ + $(MAKE) && \ + $(MAKE) check && \ + $(MAKE) install + +$(GLIBC_LDSO): | $(GLIBC_NAME).tar.xz + tar -xf $(GLIBC_NAME).tar.xz + for file in $(shell find $(PATCH_DIR) -maxdepth 1 -type f); do \ + patch -p1 < $$file ; \ + done + mkdir -p $(GLIBC_NAME)/build + cd $(GLIBC_NAME)/build && \ + ../configure --prefix=$(PREFIX) && \ + $(MAKE) && \ + $(MAKE) install + +$(GLIBC_NAME).tar.xz: + wget -O $@ $(GLIBC_URL_BASE)/$@ + +clean: + $(MAKE) -C $(CS_TRACE) clean + +.PHONY: all build patch clean diff --git a/coresight_mode/Makefile b/coresight_mode/Makefile new file mode 100644 index 00000000..fb8990b9 --- /dev/null +++ b/coresight_mode/Makefile @@ -0,0 +1,21 @@ +#!/usr/bin/env make +# SPDX-License-Identifier: Apache-2.0 +# Copyright 2021 Ricerca Security, Inc. All rights reserved. + +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +build: + @echo trying to use GNU make... + @gmake build || echo please install GNUmake + +patch: + @echo trying to use GNU make... + @gmake patch || echo please install GNUmake + +clean: + @echo trying to use GNU make... + @gmake clean || echo please install GNUmake + +.PHONY: all build patch clean diff --git a/coresight_mode/README.md b/coresight_mode/README.md new file mode 100644 index 00000000..31e77d92 --- /dev/null +++ b/coresight_mode/README.md @@ -0,0 +1,64 @@ +# AFL++ CoreSight mode + +CoreSight mode enables binary-only fuzzing on ARM64 Linux using CoreSight. + +NOTE: CoreSight mode is in the early development stage. Not applicable for production use. + +## Getting started + +Please read the [RICSec/coresight-trace README](https://github.com/RICSecLab/coresight-trace/blob/master/README.md) and check the prerequisites before getting started. + +CoreSight mode supports the AFL fork server mode to reduce `exec` system call overhead. To support it for binary-only fuzzing, it needs to modify the target ELF binary to re-link to the patched glibc. We employ this design from [PTrix](https://github.com/junxzm1990/afl-pt). + +Check out all the git submodules in the `cs_mode` directory: + +```bash +git submodule update --init --recursive +``` + +### Build coresight-trace + +There are some notes on building coresight-trace. Refer to the [README](https://github.com/RICSecLab/coresight-trace/blob/master/README.md) for the details. Run make in the `cs_mode` directory: + +```bash +make build +``` + +Make sure `cs-proxy` is placed in the AFL++ root directory as `afl-cs-proxy`. + +### Patch COTS binary + +The fork server mode requires patchelf and the patched glibc. The dependency build can be done by just run make: + +```bash +make patch TARGET=$BIN +``` + +The above make command builds and installs the dependencies to `$PREFIX` (default to `$PWD/.local`) at the first time. Then, it runs `patchelf` to `$BIN` with output `$OUTPUT` (`$BIN.patched` by default). + +### Run afl-fuzz + +Run `afl-fuzz` with `-A` option to use CoreSight mode. + +```bash +sudo afl-fuzz -A -i input -o output -- $OUTPUT @@ +``` + +## Environment Variables + +There are AFL++ CoreSight mode-specific environment variables for run-time configuration. + +* `AFL_CS_CUSTOM_BIN` overrides the proxy application path. `afl-cs-proxy` will be used if not defined. + +* `AFLCS_COV` specifies coverage type on CoreSight trace decoding. `edge` and `path` is supported. The default value is `edge`. +* `AFLCS_UDMABUF` is the u-dma-buf device number used to store trace data in the DMA region. The default value is `0`. + +## TODO List + +* Change `afl-showmap` ARM CoreSight mode option to `-A` without conflict +* Eliminate modified glibc dependency +* Support parallel fuzzing + +## Acknowledgements + +This project has received funding from the Acquisition, Technology & Logistics Agency (ATLA) under the National Security Technology Research Promotion Fund 2021 (JPJ004596). diff --git a/coresight_mode/coresight-trace b/coresight_mode/coresight-trace new file mode 160000 +Subproject ec0fd6104720ac0b59967616363dc18209adc02 diff --git a/coresight_mode/patchelf b/coresight_mode/patchelf new file mode 160000 +Subproject 7ec8edbe094ee13c91dadca191f92b9dfac8c0f diff --git a/coresight_mode/patches/0001-Add-AFL-forkserver.patch b/coresight_mode/patches/0001-Add-AFL-forkserver.patch new file mode 100644 index 00000000..51c242c4 --- /dev/null +++ b/coresight_mode/patches/0001-Add-AFL-forkserver.patch @@ -0,0 +1,117 @@ +diff --git a/glibc-2.33/elf/rtld.c b/glibc-2.33/elf/rtld.c +index 596b6ac3..2ee270d4 100644 +--- a/glibc-2.33/elf/rtld.c ++++ b/glibc-2.33/elf/rtld.c +@@ -169,6 +169,99 @@ uintptr_t __pointer_chk_guard_local + strong_alias (__pointer_chk_guard_local, __pointer_chk_guard) + #endif + ++#define AFLCS_RTLD 1 ++ ++#if AFLCS_RTLD ++ ++#include <sys/shm.h> ++#include <sys/types.h> ++#include <sys/wait.h> ++#include <dlfcn.h> ++#include <signal.h> ++ ++#include <asm/unistd.h> ++#include <unistd.h> ++ ++#define FORKSRV_FD 198 ++ ++#define AFLCS_ENABLE "__AFLCS_ENABLE" ++ ++/* We use this additional AFLCS_# AFLCS_#+1 pair to communicate with proxy */ ++#define AFLCS_FORKSRV_FD (FORKSRV_FD - 3) ++#define AFLCS_RTLD_SNIPPET do { __cs_start_forkserver(); } while(0) ++ ++/* Fork server logic, invoked before we return from _dl_start. */ ++ ++static void __cs_start_forkserver(void) { ++ int status; ++ pid_t child_pid; ++ static char tmp[4] = {0, 0, 0, 0}; ++ ++ if (!getenv(AFLCS_ENABLE)) { ++ return; ++ } ++ ++ if (write(AFLCS_FORKSRV_FD + 1, tmp, 4) != 4) { ++ _exit(-1); ++ } ++ ++ /* All right, let's await orders... */ ++ while (1) { ++ /* Whoops, parent dead? */ ++ if (read(AFLCS_FORKSRV_FD, tmp, 4) != 4) { ++ _exit(1); ++ } ++ ++ child_pid = INLINE_SYSCALL(clone, 5, ++ CLONE_CHILD_SETTID | CLONE_CHILD_CLEARTID | SIGCHLD, 0, ++ NULL, NULL, &THREAD_SELF->tid); ++ if (child_pid < 0) { ++ _exit(4); ++ } ++ if (!child_pid) { ++ /* Child process. Wait for parent start tracing */ ++ kill(getpid(), SIGSTOP); ++ /* Close descriptors and run free. */ ++ close(AFLCS_FORKSRV_FD); ++ close(AFLCS_FORKSRV_FD + 1); ++ return; ++ } ++ ++ /* Parent. */ ++ if (write(AFLCS_FORKSRV_FD + 1, &child_pid, 4) != 4) { ++ _exit(5); ++ } ++ ++ /* Wait until SIGCONT is signaled. */ ++ if (waitpid(child_pid, &status, WCONTINUED) < 0) { ++ _exit(6); ++ } ++ if (!WIFCONTINUED(status)) { ++ /* Relay status to proxy. */ ++ if (write(AFLCS_FORKSRV_FD + 1, &status, 4) != 4) { ++ _exit(7); ++ } ++ continue; ++ } ++ while (1) { ++ /* Get status. */ ++ if (waitpid(child_pid, &status, WUNTRACED) < 0) { ++ _exit(8); ++ } ++ /* Relay status to proxy. */ ++ if (write(AFLCS_FORKSRV_FD + 1, &status, 4) != 4) { ++ _exit(9); ++ } ++ if (!(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP)) { ++ /* The child process is exited. */ ++ break; ++ } ++ } ++ } ++} ++ ++#endif /* AFLCS_RTLD */ ++ + /* Check that AT_SECURE=0, or that the passed name does not contain + directories and is not overly long. Reject empty names + unconditionally. */ +@@ -588,6 +681,12 @@ _dl_start (void *arg) + # define ELF_MACHINE_START_ADDRESS(map, start) (start) + #endif + ++ /* AFL-CS-START */ ++#if AFLCS_RTLD ++ AFLCS_RTLD_SNIPPET; ++#endif ++ /* AFL-CS-END */ ++ + return ELF_MACHINE_START_ADDRESS (GL(dl_ns)[LM_ID_BASE]._ns_loaded, entry); + } + } diff --git a/include/common.h b/include/common.h index e3997aa4..6c8e3b3a 100644 --- a/include/common.h +++ b/include/common.h @@ -46,6 +46,7 @@ void check_environment_vars(char **env); char **argv_cpy_dup(int argc, char **argv); void argv_cpy_free(char **argv); +char **get_cs_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char **get_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv); char * get_afl_env(char *env); diff --git a/include/forkserver.h b/include/forkserver.h index 7af01cb2..464f208d 100644 --- a/include/forkserver.h +++ b/include/forkserver.h @@ -82,6 +82,8 @@ typedef struct afl_forkserver { bool frida_asan; /* if running with asan in frida mode */ + bool cs_mode; /* if running in CoreSight mode or not */ + bool use_stdin; /* use stdin for sending data */ bool no_unlink; /* do not unlink cur_input */ diff --git a/src/afl-analyze.c b/src/afl-analyze.c index d52a6d6e..bc562c15 100644 --- a/src/afl-analyze.c +++ b/src/afl-analyze.c @@ -77,6 +77,7 @@ static volatile u8 stop_soon; /* Ctrl-C pressed? */ static u8 *target_path; static u8 frida_mode; static u8 qemu_mode; +static u8 cs_mode; static u32 map_size = MAP_SIZE; static afl_forkserver_t fsrv = {0}; /* The forkserver */ @@ -790,6 +791,8 @@ static void set_up_environment(char **argv) { } else { + /* CoreSight mode uses the default behavior. */ + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); @@ -845,6 +848,7 @@ static void usage(u8 *argv0) { " -f file - input file read by the tested program (stdin)\n" " -t msec - timeout for each run (%u ms)\n" " -m megs - memory limit for child process (%u MB)\n" + " -A - use binary-only instrumentation (ARM CoreSight mode)\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" @@ -890,7 +894,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_init(&fsrv); - while ((opt = getopt(argc, argv, "+i:f:m:t:eOQUWh")) > 0) { + while ((opt = getopt(argc, argv, "+i:f:m:t:eAOQUWh")) > 0) { switch (opt) { @@ -989,6 +993,18 @@ int main(int argc, char **argv_orig, char **envp) { break; + case 'A': /* CoreSight mode */ + +#if !defined(__aarch64__) || !defined(__linux__) + FATAL("-A option is not supported on this platform"); +#endif + + if (cs_mode) { FATAL("Multiple -A options not supported"); } + + cs_mode = 1; + fsrv.cs_mode = cs_mode; + break; + case 'O': /* FRIDA mode */ if (frida_mode) { FATAL("Multiple -O options not supported"); } @@ -1080,6 +1096,10 @@ int main(int argc, char **argv_orig, char **envp) { } + } else if (cs_mode) { + + use_argv = get_cs_argv(argv[0], &target_path, argc - optind, argv + optind); + } else { use_argv = argv + optind; diff --git a/src/afl-common.c b/src/afl-common.c index ec3b2f3f..6c2d0753 100644 --- a/src/afl-common.c +++ b/src/afl-common.c @@ -204,6 +204,35 @@ void argv_cpy_free(char **argv) { } +/* Rewrite argv for CoreSight process tracer. */ + +char **get_cs_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { + + if (unlikely(getenv("AFL_CS_CUSTOM_BIN"))) { + + WARNF( + "AFL_CS_CUSTOM_BIN is enabled. " + "You must run your target under afl-cs-proxy on your own!"); + return argv; + + } + + char **new_argv = ck_alloc(sizeof(char *) * (argc + 4)); + if (unlikely(!new_argv)) { FATAL("Illegal amount of arguments specified"); } + + memcpy(&new_argv[3], &argv[1], (int)(sizeof(char *)) * (argc - 1)); + new_argv[argc + 3] = NULL; + + new_argv[2] = *target_path_p; + new_argv[1] = "--"; + + /* Now we need to actually find the cs-proxy binary to put in argv[0]. */ + + *target_path_p = new_argv[0] = find_afl_binary(own_loc, "afl-cs-proxy"); + return new_argv; + +} + /* Rewrite argv for QEMU. */ char **get_qemu_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv) { diff --git a/src/afl-fuzz-init.c b/src/afl-fuzz-init.c index 9262d718..e5a4d3d1 100644 --- a/src/afl-fuzz-init.c +++ b/src/afl-fuzz-init.c @@ -2645,6 +2645,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { if (afl->afl_env.afl_skip_bin_check || afl->use_wine || afl->unicorn_mode || (afl->fsrv.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) || + (afl->fsrv.cs_mode && getenv("AFL_CS_CUSTOM_BIN")) || afl->non_instrumented_mode) { return; @@ -2721,7 +2722,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { #endif /* ^!__APPLE__ */ if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode && - !afl->non_instrumented_mode && + !afl->fsrv.cs_mode && !afl->non_instrumented_mode && !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST @@ -2752,7 +2753,7 @@ void check_binary(afl_state_t *afl, u8 *fname) { } - if ((afl->fsrv.qemu_mode || afl->fsrv.frida_mode) && + if ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->fsrv.frida_mode) && memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) { SAYF("\n" cLRD "[-] " cRST diff --git a/src/afl-fuzz-stats.c b/src/afl-fuzz-stats.c index 808bf258..426580d2 100644 --- a/src/afl-fuzz-stats.c +++ b/src/afl-fuzz-stats.c @@ -285,7 +285,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, "afl_banner : %s\n" "afl_version : " VERSION "\n" - "target_mode : %s%s%s%s%s%s%s%s%s\n" + "target_mode : %s%s%s%s%s%s%s%s%s%s\n" "command_line : %s\n", (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000, (afl->prev_run_time + cur_time - afl->start_time) / 1000, @@ -321,12 +321,13 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg, afl->q_testcase_cache_count, afl->q_testcase_evictions, afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->fsrv.qemu_mode ? "qemu " : "", + afl->fsrv.cs_mode ? "coresight" : "", afl->non_instrumented_mode ? " non_instrumented " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", afl->persistent_mode ? "persistent " : "", afl->shmem_testcase_mode ? "shmem_testcase " : "", afl->deferred_mode ? "deferred " : "", - (afl->unicorn_mode || afl->fsrv.qemu_mode || + (afl->unicorn_mode || afl->fsrv.qemu_mode || afl->fsrv.cs_mode || afl->non_instrumented_mode || afl->no_forkserver || afl->crash_mode || afl->persistent_mode || afl->deferred_mode) ? "" @@ -1238,7 +1239,9 @@ void show_init_stats(afl_state_t *afl) { // SAYF("\n"); - if (avg_us > ((afl->fsrv.qemu_mode || afl->unicorn_mode) ? 50000 : 10000)) { + if (avg_us > ((afl->fsrv.cs_mode || afl->fsrv.qemu_mode || afl->unicorn_mode) + ? 50000 + : 10000)) { WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.", doc_path); diff --git a/src/afl-fuzz.c b/src/afl-fuzz.c index c08b8fbb..dfd62db8 100644 --- a/src/afl-fuzz.c +++ b/src/afl-fuzz.c @@ -113,6 +113,7 @@ static void usage(u8 *argv0, int more_help) { "maximum.\n" " -m megs - memory limit for child process (%u MB, 0 = no limit " "[default])\n" + " -A - use binary-only instrumentation (ARM CoreSight mode)\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" @@ -434,7 +435,8 @@ int main(int argc, char **argv_orig, char **envp) { while ((opt = getopt( argc, argv, - "+b:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > 0) { + "+Ab:B:c:CdDe:E:hi:I:f:F:l:L:m:M:nNOo:p:RQs:S:t:T:UV:Wx:Z")) > + 0) { switch (opt) { @@ -563,6 +565,12 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->fsrv.cs_mode) { + + FATAL("-M is not supported in ARM CoreSight mode"); + + } + if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); } /* sanity check for argument: should not begin with '-' (possible @@ -609,6 +617,12 @@ int main(int argc, char **argv_orig, char **envp) { } + if (afl->fsrv.cs_mode) { + + FATAL("-S is not supported in ARM CoreSight mode"); + + } + if (afl->sync_id) { FATAL("Multiple -S or -M options not supported"); } /* sanity check for argument: should not begin with '-' (possible @@ -825,6 +839,24 @@ int main(int argc, char **argv_orig, char **envp) { afl->use_banner = optarg; break; + case 'A': /* CoreSight mode */ + + #if !defined(__aarch64__) || !defined(__linux__) + FATAL("-A option is not supported on this platform"); + #endif + + if (afl->is_main_node || afl->is_secondary_node) { + + FATAL("ARM CoreSight mode is not supported with -M / -S"); + + } + + if (afl->fsrv.cs_mode) { FATAL("Multiple -A options not supported"); } + + afl->fsrv.cs_mode = 1; + + break; + case 'O': /* FRIDA mode */ if (afl->fsrv.frida_mode) { @@ -1212,6 +1244,7 @@ int main(int argc, char **argv_orig, char **envp) { if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); } if (afl->fsrv.frida_mode) { FATAL("-O and -n are mutually exclusive"); } if (afl->fsrv.qemu_mode) { FATAL("-Q and -n are mutually exclusive"); } + if (afl->fsrv.cs_mode) { FATAL("-A and -n are mutually exclusive"); } if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); } } @@ -1458,6 +1491,8 @@ int main(int argc, char **argv_orig, char **envp) { } else { + /* CoreSight mode uses the default behavior. */ + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); @@ -1651,7 +1686,7 @@ int main(int argc, char **argv_orig, char **envp) { } - if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && + if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode && !afl->non_instrumented_mode) { check_binary(afl, afl->cmplog_binary); @@ -1697,6 +1732,11 @@ int main(int argc, char **argv_orig, char **envp) { } + } else if (afl->fsrv.cs_mode) { + + use_argv = get_cs_argv(argv[0], &afl->fsrv.target_path, argc - optind, + argv + optind); + } else { use_argv = argv + optind; @@ -1704,7 +1744,7 @@ int main(int argc, char **argv_orig, char **envp) { } if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || - afl->fsrv.frida_mode || afl->unicorn_mode) { + afl->fsrv.frida_mode || afl->fsrv.cs_mode || afl->unicorn_mode) { map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE; afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); @@ -1724,7 +1764,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); if (!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && - !afl->unicorn_mode && !afl->fsrv.frida_mode && + !afl->unicorn_mode && !afl->fsrv.frida_mode && !afl->fsrv.cs_mode && !afl->afl_env.afl_skip_bin_check) { if (map_size <= DEFAULT_SHMEM_SIZE) { @@ -1777,6 +1817,7 @@ int main(int argc, char **argv_orig, char **envp) { afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv); // TODO: this is semi-nice afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits; + afl->cmplog_fsrv.cs_mode = afl->fsrv.cs_mode; afl->cmplog_fsrv.qemu_mode = afl->fsrv.qemu_mode; afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; @@ -1785,7 +1826,7 @@ int main(int argc, char **argv_orig, char **envp) { if ((map_size <= DEFAULT_SHMEM_SIZE || afl->cmplog_fsrv.map_size < map_size) && !afl->non_instrumented_mode && !afl->fsrv.qemu_mode && - !afl->fsrv.frida_mode && !afl->unicorn_mode && + !afl->fsrv.frida_mode && !afl->unicorn_mode && !afl->fsrv.cs_mode && !afl->afl_env.afl_skip_bin_check) { afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE); diff --git a/src/afl-showmap.c b/src/afl-showmap.c index 6c06c476..899baaa0 100644 --- a/src/afl-showmap.c +++ b/src/afl-showmap.c @@ -690,6 +690,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { } else { + /* CoreSight mode uses the default behavior. */ + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); @@ -843,6 +845,7 @@ static void usage(u8 *argv0) { " -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" + " -P - use binary-only instrumentation (ARM CoreSight 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" @@ -917,7 +920,7 @@ int main(int argc, char **argv_orig, char **envp) { if (getenv("AFL_QUIET") != NULL) { be_quiet = true; } - while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOQUWbcrsh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:A:eqCZOPQUWbcrsh")) > 0) { switch (opt) { @@ -1060,6 +1063,19 @@ int main(int argc, char **argv_orig, char **envp) { break; + /* FIXME: We want to use -P for consistency, but it is already unsed for + * undocumenetd feature "Another afl-cmin specific feature." */ + case 'P': /* CoreSight mode */ + +#if !defined(__aarch64__) || !defined(__linux__) + FATAL("-P option is not supported on this platform"); +#endif + + if (fsrv->cs_mode) { FATAL("Multiple -P options not supported"); } + + fsrv->cs_mode = true; + break; + case 'Q': if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } @@ -1204,6 +1220,11 @@ int main(int argc, char **argv_orig, char **envp) { } + } else if (fsrv->cs_mode) { + + use_argv = + get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); + } else { use_argv = argv + optind; @@ -1230,7 +1251,7 @@ int main(int argc, char **argv_orig, char **envp) { fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz = map + sizeof(u32); - if (!fsrv->qemu_mode && !unicorn_mode) { + if (!fsrv->cs_mode && !fsrv->qemu_mode && !unicorn_mode) { u32 save_be_quiet = be_quiet; be_quiet = !debug; diff --git a/src/afl-tmin.c b/src/afl-tmin.c index 3f6f14f9..22383a4e 100644 --- a/src/afl-tmin.c +++ b/src/afl-tmin.c @@ -808,6 +808,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) { } else { + /* CoreSight mode uses the default behavior. */ + setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); @@ -864,6 +866,7 @@ static void usage(u8 *argv0) { " -f file - input file read by the tested program (stdin)\n" " -t msec - timeout for each run (%u ms)\n" " -m megs - memory limit for child process (%u MB)\n" + " -A - use binary-only instrumentation (ARM CoreSight mode)\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" @@ -921,7 +924,7 @@ int main(int argc, char **argv_orig, char **envp) { SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); - while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeOQUWHh")) > 0) { + while ((opt = getopt(argc, argv, "+i:o:f:m:t:B:xeAOQUWHh")) > 0) { switch (opt) { @@ -1033,6 +1036,17 @@ int main(int argc, char **argv_orig, char **envp) { break; + case 'A': /* CoreSight mode */ + +#if !defined(__aarch64__) || !defined(__linux__) + FATAL("-A option is not supported on this platform"); +#endif + + if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); } + + fsrv->cs_mode = 1; + break; + case 'O': /* FRIDA mode */ if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); } @@ -1152,6 +1166,11 @@ int main(int argc, char **argv_orig, char **envp) { } + } else if (fsrv->cs_mode) { + + use_argv = + get_cs_argv(argv[0], &fsrv->target_path, argc - optind, argv + optind); + } else { use_argv = argv + optind; |