From 9100f3c416707d926fc100d4441cf32bb1da6dd6 Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Tue, 22 Jun 2021 05:34:20 +0000 Subject: 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 --- coresight_mode/.gitignore | 2 + coresight_mode/GNUmakefile | 59 +++++++++++ coresight_mode/Makefile | 21 ++++ coresight_mode/README.md | 58 ++++++++++ coresight_mode/coresight-trace | 1 + coresight_mode/patchelf | 1 + .../patches/0001-Add-AFL-forkserver.patch | 117 +++++++++++++++++++++ 7 files changed, 259 insertions(+) create mode 100644 coresight_mode/.gitignore create mode 100644 coresight_mode/GNUmakefile create mode 100644 coresight_mode/Makefile create mode 100644 coresight_mode/README.md create mode 160000 coresight_mode/coresight-trace create mode 160000 coresight_mode/patchelf create mode 100644 coresight_mode/patches/0001-Add-AFL-forkserver.patch (limited to 'coresight_mode') 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..69b72f91 --- /dev/null +++ b/coresight_mode/GNUmakefile @@ -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 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..e08421ed --- /dev/null +++ b/coresight_mode/README.md @@ -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). diff --git a/coresight_mode/coresight-trace b/coresight_mode/coresight-trace new file mode 160000 index 00000000..ec0fd610 --- /dev/null +++ b/coresight_mode/coresight-trace @@ -0,0 +1 @@ +Subproject commit ec0fd6104720ac0b59967616363dc18209adc02e diff --git a/coresight_mode/patchelf b/coresight_mode/patchelf new file mode 160000 index 00000000..7ec8edbe --- /dev/null +++ b/coresight_mode/patchelf @@ -0,0 +1 @@ +Subproject commit 7ec8edbe094ee13c91dadca191f92b9dfac8c0f9 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 ++#include ++#include ++#include ++#include ++ ++#include ++#include ++ ++#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); + } + } -- cgit 1.4.1 From 2d4b18f98ea15cef30a47d62319a10defda45237 Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Tue, 16 Nov 2021 02:00:03 +0000 Subject: Fix finding glibc patches Signed-off-by: Akira Moroo --- coresight_mode/GNUmakefile | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'coresight_mode') diff --git a/coresight_mode/GNUmakefile b/coresight_mode/GNUmakefile index 69b72f91..9ab30ff7 100644 --- a/coresight_mode/GNUmakefile +++ b/coresight_mode/GNUmakefile @@ -9,10 +9,11 @@ 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_PATCH:=patches/0002-glibc-Add-AFL-forkserver.patch GLIBC_LDSO?=$(PREFIX)/lib/ld-linux-aarch64.so.1 OUTPUT?="$(TARGET).patched" @@ -43,7 +44,9 @@ $(PATCHELF): patchelf $(GLIBC_LDSO): | $(GLIBC_NAME).tar.xz tar -xf $(GLIBC_NAME).tar.xz - patch -p1 < $(GLIBC_PATCH) + 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) && \ -- cgit 1.4.1 From 3f864fa129c821ff35771ad0fe74c9e1ec88ee08 Mon Sep 17 00:00:00 2001 From: Akira Moroo Date: Tue, 16 Nov 2021 02:31:12 +0000 Subject: coresight_mode: Add TODO list to README.md Signed-off-by: Akira Moroo --- coresight_mode/README.md | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'coresight_mode') diff --git a/coresight_mode/README.md b/coresight_mode/README.md index e08421ed..31e77d92 100644 --- a/coresight_mode/README.md +++ b/coresight_mode/README.md @@ -53,6 +53,12 @@ There are AFL++ CoreSight mode-specific environment variables for run-time confi * `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). -- cgit 1.4.1