Skip to content

Commit

Permalink
Add initial CoreSight mode support
Browse files Browse the repository at this point in the history
The original code is:
https://github.com/RICSecLab/AFLplusplus-cs/tree/retrage/coresight-mode-pr

Signed-off-by: Akira Moroo <retrage01@gmail.com>
  • Loading branch information
retrage committed Nov 11, 2021
1 parent 2623851 commit 9100f3c
Show file tree
Hide file tree
Showing 19 changed files with 397 additions and 17 deletions.
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ afl-g++-fast
afl-gotcpu
afl-ld
afl-ld-lto
afl-cs-proxy
afl-qemu-trace
afl-showmap
afl-tmin
Expand Down Expand Up @@ -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
6 changes: 6 additions & 0 deletions .gitmodules
Original file line number Diff line number Diff line change
Expand Up @@ -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
16 changes: 13 additions & 3 deletions GNUmakefile
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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
Expand Down Expand Up @@ -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"
Expand Down
2 changes: 2 additions & 0 deletions coresight_mode/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.local
glibc*
59 changes: 59 additions & 0 deletions coresight_mode/GNUmakefile
Original file line number Diff line number Diff line change
@@ -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 changes: 21 additions & 0 deletions coresight_mode/Makefile
Original file line number Diff line number Diff line change
@@ -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 changes: 58 additions & 0 deletions coresight_mode/README.md
Original file line number Diff line number Diff line change
@@ -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).
1 change: 1 addition & 0 deletions coresight_mode/coresight-trace
Submodule coresight-trace added at ec0fd6
1 change: 1 addition & 0 deletions coresight_mode/patchelf
Submodule patchelf added at 7ec8ed
117 changes: 117 additions & 0 deletions coresight_mode/patches/0001-Add-AFL-forkserver.patch
Original file line number Diff line number Diff line change
@@ -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);
}
}
1 change: 1 addition & 0 deletions include/common.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
2 changes: 2 additions & 0 deletions include/forkserver.h
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down
Loading

0 comments on commit 9100f3c

Please sign in to comment.