Add initial CoreSight mode support

The original code is:
https://github.com/RICSecLab/AFLplusplus-cs/tree/retrage/coresight-mode-pr

Signed-off-by: Akira Moroo <retrage01@gmail.com>
This commit is contained in:
Akira Moroo
2021-06-22 05:34:20 +00:00
parent 2623851680
commit 9100f3c416
19 changed files with 397 additions and 17 deletions

3
.gitignore vendored
View File

@ -30,6 +30,7 @@ afl-g++-fast
afl-gotcpu afl-gotcpu
afl-ld afl-ld
afl-ld-lto afl-ld-lto
afl-cs-proxy
afl-qemu-trace afl-qemu-trace
afl-showmap afl-showmap
afl-tmin afl-tmin
@ -94,3 +95,5 @@ utils/optimin/optimin
utils/persistent_mode/persistent_demo utils/persistent_mode/persistent_demo
utils/persistent_mode/persistent_demo_new utils/persistent_mode/persistent_demo_new
utils/persistent_mode/test-instr utils/persistent_mode/test-instr
!coresight_mode
!coresight_mode/coresight-trace

6
.gitmodules vendored
View File

@ -13,3 +13,9 @@
[submodule "utils/optimin/EvalMaxSAT"] [submodule "utils/optimin/EvalMaxSAT"]
path = utils/optimin/EvalMaxSAT path = utils/optimin/EvalMaxSAT
url = https://github.com/FlorentAvellaneda/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

View File

@ -346,7 +346,7 @@ help:
@echo "HELP --- the following make targets exist:" @echo "HELP --- the following make targets exist:"
@echo "==========================================" @echo "=========================================="
@echo "all: just the main afl++ binaries" @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 "source-only: everything for source code fuzzing: gcc_plugin, libdislocator, libtokencap"
@echo "distrib: everything (for both binary-only and source code fuzzing)" @echo "distrib: everything (for both binary-only and source code fuzzing)"
@echo "man: creates simple man pages from the help option of the programs" @echo "man: creates simple man pages from the help option of the programs"
@ -564,7 +564,7 @@ all_done: test_build
.PHONY: clean .PHONY: clean
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.llvm clean
-$(MAKE) -f GNUmakefile.gcc_plugin clean -$(MAKE) -f GNUmakefile.gcc_plugin clean
$(MAKE) -C utils/libdislocator clean $(MAKE) -C utils/libdislocator clean
@ -579,19 +579,23 @@ clean:
$(MAKE) -C qemu_mode/libqasan clean $(MAKE) -C qemu_mode/libqasan clean
-$(MAKE) -C frida_mode clean -$(MAKE) -C frida_mode clean
ifeq "$(IN_REPO)" "1" 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 qemu_mode/qemuafl/Makefile && $(MAKE) -C qemu_mode/qemuafl clean || true
test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true test -e unicorn_mode/unicornafl/Makefile && $(MAKE) -C unicorn_mode/unicornafl clean || true
else else
rm -rf coresight_mode/coresight_trace
rm -rf qemu_mode/qemuafl rm -rf qemu_mode/qemuafl
rm -rf unicorn_mode/unicornafl rm -rf unicorn_mode/unicornafl
endif endif
.PHONY: deepclean .PHONY: deepclean
deepclean: clean deepclean: clean
rm -rf coresight_mode/coresight-trace
rm -rf unicorn_mode/unicornafl rm -rf unicorn_mode/unicornafl
rm -rf qemu_mode/qemuafl rm -rf qemu_mode/qemuafl
ifeq "$(IN_REPO)" "1" ifeq "$(IN_REPO)" "1"
# NEVER EVER ACTIVATE THAT!!!!! git reset --hard >/dev/null 2>&1 || true # 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 unicorn_mode/unicornafl
git checkout qemu_mode/qemuafl git checkout qemu_mode/qemuafl
endif endif
@ -610,6 +614,9 @@ endif
# -$(MAKE) -C utils/plot_ui # -$(MAKE) -C utils/plot_ui
-$(MAKE) -C frida_mode -$(MAKE) -C frida_mode
ifneq "$(SYS)" "Darwin" ifneq "$(SYS)" "Darwin"
ifeq "$(ARCH)" "aarch64"
-$(MAKE) -C coresight_mode
endif
-cd qemu_mode && sh ./build_qemu_support.sh -cd qemu_mode && sh ./build_qemu_support.sh
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh -cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif endif
@ -624,6 +631,9 @@ binary-only: test_shm test_python ready $(PROGS)
# -$(MAKE) -C utils/plot_ui # -$(MAKE) -C utils/plot_ui
-$(MAKE) -C frida_mode -$(MAKE) -C frida_mode
ifneq "$(SYS)" "Darwin" ifneq "$(SYS)" "Darwin"
ifeq "$(ARCH)" "aarch64"
-$(MAKE) -C coresight_mode
endif
-cd qemu_mode && sh ./build_qemu_support.sh -cd qemu_mode && sh ./build_qemu_support.sh
-cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh -cd unicorn_mode && unset CFLAGS && sh ./build_unicorn_support.sh
endif endif
@ -695,7 +705,7 @@ endif
.PHONY: uninstall .PHONY: uninstall
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 -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 -rm -rf $${DESTDIR}$(MISC_PATH)/testcases $${DESTDIR}$(MISC_PATH)/dictionaries
-sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f" -sh -c "ls docs/*.md | sed 's|^docs/|$${DESTDIR}$(DOC_PATH)/|' | xargs rm -f"

2
coresight_mode/.gitignore vendored Normal file
View File

@ -0,0 +1,2 @@
.local
glibc*

View File

@ -0,0 +1,59 @@
#!/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
GLIBC_VER:=2.33
GLIBC_NAME:=glibc-$(GLIBC_VER)
GLIBC_URL_BASE:=http://ftp.gnu.org/gnu/glibc
GLIBC_PATCH:=patches/0002-glibc-Add-AFL-forkserver.patch
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
patch -p1 < $(GLIBC_PATCH)
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

21
coresight_mode/Makefile Normal file
View File

@ -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

58
coresight_mode/README.md Normal file
View File

@ -0,0 +1,58 @@
# 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`.
## Acknowledgements
This project has received funding from the Acquisition, Technology & Logistics Agency (ATLA) under the National Security Technology Research Promotion Fund 2021 (JPJ004596).

View File

@ -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);
}
}

View File

@ -46,6 +46,7 @@ void check_environment_vars(char **env);
char **argv_cpy_dup(int argc, char **argv); char **argv_cpy_dup(int argc, char **argv);
void argv_cpy_free(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_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_wine_argv(u8 *own_loc, u8 **target_path_p, int argc, char **argv);
char * get_afl_env(char *env); char * get_afl_env(char *env);

View File

@ -82,6 +82,8 @@ typedef struct afl_forkserver {
bool frida_asan; /* if running with asan in frida mode */ 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 use_stdin; /* use stdin for sending data */
bool no_unlink; /* do not unlink cur_input */ bool no_unlink; /* do not unlink cur_input */

View File

@ -77,6 +77,7 @@ static volatile u8 stop_soon; /* Ctrl-C pressed? */
static u8 *target_path; static u8 *target_path;
static u8 frida_mode; static u8 frida_mode;
static u8 qemu_mode; static u8 qemu_mode;
static u8 cs_mode;
static u32 map_size = MAP_SIZE; static u32 map_size = MAP_SIZE;
static afl_forkserver_t fsrv = {0}; /* The forkserver */ static afl_forkserver_t fsrv = {0}; /* The forkserver */
@ -790,6 +791,8 @@ static void set_up_environment(char **argv) {
} else { } else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", 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" " -f file - input file read by the tested program (stdin)\n"
" -t msec - timeout for each run (%u ms)\n" " -t msec - timeout for each run (%u ms)\n"
" -m megs - memory limit for child process (%u MB)\n" " -m megs - memory limit for child process (%u MB)\n"
" -A - use binary-only instrumentation (CoreSight mode)\n"
" -O - use binary-only instrumentation (FRIDA mode)\n" " -O - use binary-only instrumentation (FRIDA mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn 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); 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) { switch (opt) {
@ -989,6 +993,14 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'A': /* CoreSight mode */
if (cs_mode) { FATAL("Multiple -A options not supported"); }
cs_mode = 1;
fsrv.cs_mode = cs_mode;
break;
case 'O': /* FRIDA mode */ case 'O': /* FRIDA mode */
if (frida_mode) { FATAL("Multiple -O options not supported"); } if (frida_mode) { FATAL("Multiple -O options not supported"); }
@ -1080,6 +1092,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 { } else {
use_argv = argv + optind; use_argv = argv + optind;

View File

@ -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. */ /* Rewrite argv for QEMU. */
char **get_qemu_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) {

View File

@ -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 || 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.qemu_mode && getenv("AFL_QEMU_CUSTOM_BIN")) ||
(afl->fsrv.cs_mode && getenv("AFL_CS_CUSTOM_BIN")) ||
afl->non_instrumented_mode) { afl->non_instrumented_mode) {
return; return;
@ -2721,7 +2722,7 @@ void check_binary(afl_state_t *afl, u8 *fname) {
#endif /* ^!__APPLE__ */ #endif /* ^!__APPLE__ */
if (!afl->fsrv.qemu_mode && !afl->fsrv.frida_mode && !afl->unicorn_mode && 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)) { !memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST 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)) { memmem(f_data, f_len, SHM_ENV_VAR, strlen(SHM_ENV_VAR) + 1)) {
SAYF("\n" cLRD "[-] " cRST SAYF("\n" cLRD "[-] " cRST

View File

@ -285,7 +285,7 @@ void write_stats_file(afl_state_t *afl, u32 t_bytes, double bitmap_cvg,
"afl_banner : %s\n" "afl_banner : %s\n"
"afl_version : " VERSION "afl_version : " VERSION
"\n" "\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", "command_line : %s\n",
(afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000, (afl->start_time - afl->prev_run_time) / 1000, cur_time / 1000,
(afl->prev_run_time + cur_time - afl->start_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->q_testcase_cache_count, afl->q_testcase_evictions,
afl->use_banner, afl->unicorn_mode ? "unicorn" : "", afl->use_banner, afl->unicorn_mode ? "unicorn" : "",
afl->fsrv.qemu_mode ? "qemu " : "", afl->fsrv.qemu_mode ? "qemu " : "",
afl->fsrv.cs_mode ? "coresight" : "",
afl->non_instrumented_mode ? " non_instrumented " : "", afl->non_instrumented_mode ? " non_instrumented " : "",
afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "", afl->no_forkserver ? "no_fsrv " : "", afl->crash_mode ? "crash " : "",
afl->persistent_mode ? "persistent " : "", afl->persistent_mode ? "persistent " : "",
afl->shmem_testcase_mode ? "shmem_testcase " : "", afl->shmem_testcase_mode ? "shmem_testcase " : "",
afl->deferred_mode ? "deferred " : "", 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->non_instrumented_mode || afl->no_forkserver ||
afl->crash_mode || afl->persistent_mode || afl->deferred_mode) afl->crash_mode || afl->persistent_mode || afl->deferred_mode)
? "" ? ""
@ -1238,7 +1239,9 @@ void show_init_stats(afl_state_t *afl) {
// SAYF("\n"); // 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.", WARNF(cLRD "The target binary is pretty slow! See %s/perf_tips.md.",
doc_path); doc_path);

View File

@ -113,6 +113,7 @@ static void usage(u8 *argv0, int more_help) {
"maximum.\n" "maximum.\n"
" -m megs - memory limit for child process (%u MB, 0 = no limit " " -m megs - memory limit for child process (%u MB, 0 = no limit "
"[default])\n" "[default])\n"
" -A - use binary-only instrumentation (CoreSight mode)\n"
" -O - use binary-only instrumentation (FRIDA mode)\n" " -O - use binary-only instrumentation (FRIDA mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use unicorn-based instrumentation (Unicorn 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( while ((opt = getopt(
argc, argv, 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) { switch (opt) {
@ -825,6 +827,13 @@ int main(int argc, char **argv_orig, char **envp) {
afl->use_banner = optarg; afl->use_banner = optarg;
break; break;
case 'A': /* CoreSight mode */
if (afl->fsrv.cs_mode) { FATAL("Multiple -A options not supported"); }
afl->fsrv.cs_mode = 1;
break;
case 'O': /* FRIDA mode */ case 'O': /* FRIDA mode */
if (afl->fsrv.frida_mode) { if (afl->fsrv.frida_mode) {
@ -1212,6 +1221,7 @@ int main(int argc, char **argv_orig, char **envp) {
if (afl->crash_mode) { FATAL("-C and -n are mutually exclusive"); } 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.frida_mode) { FATAL("-O and -n are mutually exclusive"); }
if (afl->fsrv.qemu_mode) { FATAL("-Q 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"); } if (afl->unicorn_mode) { FATAL("-U and -n are mutually exclusive"); }
} }
@ -1458,6 +1468,8 @@ int main(int argc, char **argv_orig, char **envp) {
} else { } else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@ -1651,7 +1663,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) { !afl->non_instrumented_mode) {
check_binary(afl, afl->cmplog_binary); check_binary(afl, afl->cmplog_binary);
@ -1697,6 +1709,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 { } else {
use_argv = argv + optind; use_argv = argv + optind;
@ -1704,7 +1721,7 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (afl->non_instrumented_mode || afl->fsrv.qemu_mode || 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; map_size = afl->fsrv.real_map_size = afl->fsrv.map_size = MAP_SIZE;
afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size); afl->virgin_bits = ck_realloc(afl->virgin_bits, map_size);
@ -1724,7 +1741,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode); afl_shm_init(&afl->shm, afl->fsrv.map_size, afl->non_instrumented_mode);
if (!afl->non_instrumented_mode && !afl->fsrv.qemu_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) { !afl->afl_env.afl_skip_bin_check) {
if (map_size <= DEFAULT_SHMEM_SIZE) { if (map_size <= DEFAULT_SHMEM_SIZE) {
@ -1777,6 +1794,7 @@ int main(int argc, char **argv_orig, char **envp) {
afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv); afl_fsrv_init_dup(&afl->cmplog_fsrv, &afl->fsrv);
// TODO: this is semi-nice // TODO: this is semi-nice
afl->cmplog_fsrv.trace_bits = afl->fsrv.trace_bits; 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.qemu_mode = afl->fsrv.qemu_mode;
afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode; afl->cmplog_fsrv.frida_mode = afl->fsrv.frida_mode;
afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary; afl->cmplog_fsrv.cmplog_binary = afl->cmplog_binary;
@ -1785,7 +1803,7 @@ int main(int argc, char **argv_orig, char **envp) {
if ((map_size <= DEFAULT_SHMEM_SIZE || if ((map_size <= DEFAULT_SHMEM_SIZE ||
afl->cmplog_fsrv.map_size < map_size) && afl->cmplog_fsrv.map_size < map_size) &&
!afl->non_instrumented_mode && !afl->fsrv.qemu_mode && !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->afl_env.afl_skip_bin_check) {
afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE); afl->cmplog_fsrv.map_size = MAX(map_size, (u32)DEFAULT_SHMEM_SIZE);

View File

@ -690,6 +690,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} else { } else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", 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" " -t msec - timeout for each run (none)\n"
" -m megs - memory limit for child process (%u MB)\n" " -m megs - memory limit for child process (%u MB)\n"
" -O - use binary-only instrumentation (FRIDA mode)\n" " -O - use binary-only instrumentation (FRIDA mode)\n"
" -P - use binary-only instrumentation (CoreSight mode)\n"
" -Q - use binary-only instrumentation (QEMU mode)\n" " -Q - use binary-only instrumentation (QEMU mode)\n"
" -U - use Unicorn-based instrumentation (Unicorn mode)\n" " -U - use Unicorn-based instrumentation (Unicorn mode)\n"
" -W - use qemu-based instrumentation with Wine (Wine 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; } 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) { switch (opt) {
@ -1060,6 +1063,15 @@ int main(int argc, char **argv_orig, char **envp) {
break; 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 (fsrv->cs_mode) { FATAL("Multiple -P options not supported"); }
fsrv->cs_mode = true;
break;
case 'Q': case 'Q':
if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); } if (fsrv->qemu_mode) { FATAL("Multiple -Q options not supported"); }
@ -1124,6 +1136,7 @@ int main(int argc, char **argv_orig, char **envp) {
} }
if (fsrv->cs_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT; }
if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; } if (fsrv->qemu_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_QEMU; }
if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; } if (unicorn_mode && !mem_limit_given) { fsrv->mem_limit = MEM_LIMIT_UNICORN; }
@ -1204,6 +1217,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 { } else {
use_argv = argv + optind; use_argv = argv + optind;
@ -1230,7 +1248,7 @@ int main(int argc, char **argv_orig, char **envp) {
fsrv->shmem_fuzz_len = (u32 *)map; fsrv->shmem_fuzz_len = (u32 *)map;
fsrv->shmem_fuzz = map + sizeof(u32); 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; u32 save_be_quiet = be_quiet;
be_quiet = !debug; be_quiet = !debug;

View File

@ -808,6 +808,8 @@ static void set_up_environment(afl_forkserver_t *fsrv, char **argv) {
} else { } else {
/* CoreSight mode uses the default behavior. */
setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1); setenv("LD_PRELOAD", getenv("AFL_PRELOAD"), 1);
setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1); setenv("DYLD_INSERT_LIBRARIES", getenv("AFL_PRELOAD"), 1);
@ -921,7 +923,7 @@ int main(int argc, char **argv_orig, char **envp) {
SAYF(cCYA "afl-tmin" VERSION cRST " by Michal Zalewski\n"); 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) { switch (opt) {
@ -1033,6 +1035,13 @@ int main(int argc, char **argv_orig, char **envp) {
break; break;
case 'A': /* CoreSight mode */
if (fsrv->cs_mode) { FATAL("Multiple -A options not supported"); }
fsrv->cs_mode = 1;
break;
case 'O': /* FRIDA mode */ case 'O': /* FRIDA mode */
if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); } if (fsrv->frida_mode) { FATAL("Multiple -O options not supported"); }
@ -1152,6 +1161,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 { } else {
use_argv = argv + optind; use_argv = argv + optind;