aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorWorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>2021-06-16 20:53:57 +0100
committerGitHub <noreply@github.com>2021-06-16 21:53:57 +0200
commit58747f9f4fe960cf97d40dd6d6db0f2f7f13b505 (patch)
treed2823cdaefb1f4af9f8c0a64c600dee7cbb12643
parent35153e9b495e3f61c032a3d911e4906fed0b50d6 (diff)
downloadafl++-58747f9f4fe960cf97d40dd6d6db0f2f7f13b505.tar.gz
Perf regression4 (#979)
* Added test for libjpeg * Added proj4 test * Added missing members to x86/64 context * Changes to use memfd and hashtable cache * Removed redundant check Co-authored-by: Your Name <you@example.com>
-rw-r--r--frida_mode/src/cmplog/cmplog.c139
-rw-r--r--frida_mode/src/ctx/ctx_x64.c22
-rw-r--r--frida_mode/src/ctx/ctx_x86.c6
-rw-r--r--frida_mode/test/jpeg/GNUmakefile172
-rw-r--r--frida_mode/test/jpeg/Makefile19
-rw-r--r--frida_mode/test/jpeg/aflpp_qemu_driver_hook.c97
-rwxr-xr-xfrida_mode/test/jpeg/get_symbol_addr.py36
-rw-r--r--frida_mode/test/proj4/GNUmakefile172
-rw-r--r--frida_mode/test/proj4/Makefile19
-rw-r--r--frida_mode/test/proj4/aflpp_qemu_driver_hook.c97
-rwxr-xr-xfrida_mode/test/proj4/get_symbol_addr.py36
11 files changed, 740 insertions, 75 deletions
diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c
index 3df7d13d..a6c95ab0 100644
--- a/frida_mode/src/cmplog/cmplog.c
+++ b/frida_mode/src/cmplog/cmplog.c
@@ -10,18 +10,20 @@
#include "util.h"
#define DEFAULT_MMAP_MIN_ADDR (32UL << 10)
-#define FD_TMP_MAX_SIZE 65536
+#define MAX_MEMFD_SIZE (64UL << 10)
extern struct cmp_map *__afl_cmp_map;
-
static GArray *cmplog_ranges = NULL;
-static int fd_tmp = -1;
-static ssize_t fd_tmp_size = 0;
+static GHashTable * hash = NULL;
+
+static int memfd = -1;
+static size_t memfd_size = 0;
+static u8 scratch[MAX_MEMFD_SIZE] = {0};
static gboolean cmplog_range(const GumRangeDetails *details,
gpointer user_data) {
- UNUSED_PARAMETER(user_data);
+ GArray * cmplog_ranges = (GArray *)user_data;
GumMemoryRange range = *details->range;
g_array_append_val(cmplog_ranges, range);
return TRUE;
@@ -35,71 +37,95 @@ static gint cmplog_sort(gconstpointer a, gconstpointer b) {
}
-static int cmplog_create_temp(void) {
+static void cmplog_get_ranges(void) {
- const char *tmpdir = g_get_tmp_dir();
- OKF("CMPLOG Temporary directory: %s", tmpdir);
- gchar *fname = g_strdup_printf("%s/frida-cmplog-XXXXXX", tmpdir);
- OKF("CMPLOG Temporary file template: %s", fname);
- int fd = mkstemp(fname);
- OKF("CMPLOG Temporary file: %s", fname);
+ 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);
- if (fd < 0) {
+ for (guint i = 0; i < cmplog_ranges->len; i++) {
- FATAL("Failed to create temp file: %s, errno: %d", fname, errno);
+ GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
}
- if (unlink(fname) < 0) {
+ g_array_free(cmplog_ranges, TRUE);
- FATAL("Failed to unlink temp file: %s (%d), errno: %d", fname, fd, errno);
+}
- }
+void cmplog_init(void) {
+
+ if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
+
+ cmplog_get_ranges();
- if (ftruncate(fd, 0) < 0) {
+ for (guint i = 0; i < cmplog_ranges->len; i++) {
- FATAL("Failed to ftruncate temp file: %s (%d), errno: %d", fname, fd,
- errno);
+ 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);
}
- g_free(fname);
+ memfd = syscall(__NR_memfd_create, "cmplog_memfd", 0);
+ if (memfd < 0) {
- return fd;
+ FATAL("Failed to create_memfd, errno: %d", errno);
+
+ }
+
+ hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+ if (hash == NULL) {
+ FATAL("Failed to g_hash_table_new, errno: %d", errno);
+ }
}
-void cmplog_init(void) {
+static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
+ GumAddress outer_base, GumAddress outer_limit) {
- if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
+ return (inner_base >= outer_base && inner_limit <= outer_limit);
- 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++) {
+gboolean cmplog_test_addr(guint64 addr, size_t size) {
- GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
- OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER
- "X",
- range->base_address, range->base_address + range->size);
+ if (g_hash_table_contains(hash, (gpointer)addr)) { return true; }
+ if (memfd_size > MAX_MEMFD_SIZE) {
+ if (lseek(memfd, 0, SEEK_SET) < 0) {
+ FATAL("CMPLOG - Failed lseek, errno: %d", errno);
+ }
}
/*
- * We can't use /dev/null or /dev/zero for this since it appears that they
- * don't validate the input buffer. Persumably as an optimization because they
- * don't actually write any data. The file will be deleted on close.
+ * Our address map can change (e.g. stack growth), use write as a fallback to
+ * validate our address.
+ */
+ ssize_t written = syscall(__NR_write, memfd, (void *)addr, size);
+ if (written < 0 && errno != EFAULT && errno != 0) {
+ FATAL("CMPLOG - Failed __NR_write, errno: %d", errno);
+ }
+ /*
+ * If the write succeeds, then the buffer must be valid otherwise it would
+ * return EFAULT
*/
- fd_tmp = cmplog_create_temp();
+ if (written > 0) { memfd_size += written; }
-}
+ if ((size_t)written == size) {
+ if (!g_hash_table_add (hash, (gpointer)addr)) {
+ FATAL("Failed - g_hash_table_add");
+ }
+ return true;
+ }
-static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
- GumAddress outer_base, GumAddress outer_limit) {
- return (inner_base >= outer_base && inner_limit <= outer_limit);
+ return false;
}
gboolean cmplog_is_readable(guint64 addr, size_t size) {
@@ -125,6 +151,7 @@ gboolean cmplog_is_readable(guint64 addr, size_t 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;
@@ -133,37 +160,7 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
}
- /*
- * Our address map can change (e.g. stack growth), use write as a fallback to
- * validate our address.
- */
- ssize_t written = syscall(__NR_write, fd_tmp, (void *)addr, size);
-
- /*
- * If the write succeeds, then the buffer must be valid otherwise it would
- * return EFAULT
- */
- if (written > 0) {
-
- fd_tmp_size += written;
- if (fd_tmp_size > FD_TMP_MAX_SIZE) {
-
- /*
- * Truncate the file, we don't want our temp file to continue growing!
- */
- if (ftruncate(fd_tmp, 0) < 0) {
-
- FATAL("Failed to truncate fd_tmp (%d), errno: %d", fd_tmp, errno);
-
- }
-
- fd_tmp_size = 0;
-
- }
-
- if ((size_t)written == size) { return true; }
-
- }
+ if (cmplog_test_addr(addr, size)) { return true; }
return false;
diff --git a/frida_mode/src/ctx/ctx_x64.c b/frida_mode/src/ctx/ctx_x64.c
index c5900533..1772a252 100644
--- a/frida_mode/src/ctx/ctx_x64.c
+++ b/frida_mode/src/ctx/ctx_x64.c
@@ -49,9 +49,18 @@ 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)
@@ -62,14 +71,23 @@ 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_BP, ctx->rbp)
+ 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_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 45308272..9b50cb52 100644
--- a/frida_mode/src/ctx/ctx_x86.c
+++ b/frida_mode/src/ctx/ctx_x86.c
@@ -42,6 +42,7 @@ 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)
@@ -55,14 +56,15 @@ 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/test/jpeg/GNUmakefile b/frida_mode/test/jpeg/GNUmakefile
new file mode 100644
index 00000000..689fce3d
--- /dev/null
+++ b/frida_mode/test/jpeg/GNUmakefile
@@ -0,0 +1,172 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c
+AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so
+
+LIBJPEG_BUILD_DIR:=$(BUILD_DIR)libjpeg/
+HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/
+JPEGTEST_BUILD_DIR:=$(BUILD_DIR)jpegtest/
+
+LIBJPEG_URL:=https://github.com/libjpeg-turbo/libjpeg-turbo.git
+LIBJPEG_DIR:=$(LIBJPEG_BUILD_DIR)libjpeg/
+LIBJPEG_CONFIGURE:=$(LIBJPEG_DIR)configure.ac
+LIBJPEG_MAKEFILE:=$(LIBJPEG_DIR)Makefile
+LIBJPEG_LIB:=$(LIBJPEG_DIR).libs/libturbojpeg.a
+
+HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o
+HARNESS_URL:="https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/aflpp_driver/aflpp_qemu_driver.c"
+
+JPEGTEST_FILE:=$(JPEGTEST_BUILD_DIR)target.cc
+JPEGTEST_OBJ:=$(JPEGTEST_BUILD_DIR)target.o
+JPEGTEST_URL:="https://raw.githubusercontent.com/google/fuzzbench/master/benchmarks/libjpeg-turbo-07-2017/libjpeg_turbo_fuzzer.cc"
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed
+
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+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 $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000)
+endif
+
+.PHONY: all clean frida hook
+
+all: $(TEST_BIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+######### HARNESS ########
+$(HARNESS_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(HARNESS_FILE): | $(HARNESS_BUILD_DIR)
+ wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_FILE)
+ $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ -c $<
+
+######### JPEGTEST ########
+
+$(JPEGTEST_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(JPEGTEST_FILE): | $(JPEGTEST_BUILD_DIR)
+ wget -O $@ $(JPEGTEST_URL)
+
+$(JPEGTEST_OBJ): $(JPEGTEST_FILE) | $(LIBJPEG_MAKEFILE)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBJPEG_DIR) -o $@ -c $<
+
+######### LIBJPEG ########
+
+$(LIBJPEG_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(LIBJPEG_CONFIGURE): $(LIBJPEG_BUILD_DIR)
+ git clone $(LIBJPEG_URL) $(LIBJPEG_DIR)
+ cd $(LIBJPEG_DIR) && git checkout b0971e47d76fdb81270e93bbf11ff5558073350d
+
+$(LIBJPEG_MAKEFILE): $(LIBJPEG_CONFIGURE)
+ cd $(LIBJPEG_DIR) && autoreconf -fiv
+ cd $(LIBJPEG_DIR) && ./configure
+
+$(LIBJPEG_LIB): $(LIBJPEG_MAKEFILE)
+ make -C $(LIBJPEG_DIR) -j $(shell nproc)
+
+######### TEST ########
+
+$(TEST_BIN): $(HARNESS_OBJ) $(JPEGTEST_OBJ) $(LIBJPEG_LIB)
+ $(CXX) \
+ $(CFLAGS) \
+ -o $@ \
+ $(HARNESS_OBJ) $(JPEGTEST_OBJ) $(LIBJPEG_LIB) \
+ -lz \
+ $(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)
+ mkdir -p $@
+
+$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
+ echo "hi" > $(TEST_DATA_FILE)
+
+###### TEST DATA #######
+
+hook: $(AFLPP_DRIVER_HOOK_OBJ)
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
+ AFL_DEBUG_CHILD=1 \
+ AFL_DISABLE_TRIM=1 \
+ AFL_FRIDA_PERSISTENT_CNT=1000000 \
+ AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
+ AFL_NO_AFFINITY=1 \
+ X__AFL_NO_UI=1 \
+ AFL_PATH=/out \
+ AFL_SHUFFLE_QUEUE=1 \
+ AFL_SKIP_CPUFREQ=1 \
+ AFL_SKIP_CRASHES=1 \
+ AFL_TESTCACHE_SIZE=2 \
+ 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 \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -m none \
+ -t 1000+ \
+ -d \
+ -O \
+ -c 0\
+ -V 30 \
+ -- \
+ $(TEST_BIN) 2147483647
+
+debug:
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TEST_BIN) $(TEST_DATA_DIR)basn0g01.jpeg
diff --git a/frida_mode/test/jpeg/Makefile b/frida_mode/test/jpeg/Makefile
new file mode 100644
index 00000000..863438cf
--- /dev/null
+++ b/frida_mode/test/jpeg/Makefile
@@ -0,0 +1,19 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
+
+debug:
+ @gmake debug
+
+hook:
+ @gmake hook
diff --git a/frida_mode/test/jpeg/aflpp_qemu_driver_hook.c b/frida_mode/test/jpeg/aflpp_qemu_driver_hook.c
new file mode 100644
index 00000000..059d438d
--- /dev/null
+++ b/frida_mode/test/jpeg/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/jpeg/get_symbol_addr.py b/frida_mode/test/jpeg/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/jpeg/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/proj4/GNUmakefile b/frida_mode/test/proj4/GNUmakefile
new file mode 100644
index 00000000..09112cd5
--- /dev/null
+++ b/frida_mode/test/proj4/GNUmakefile
@@ -0,0 +1,172 @@
+PWD:=$(shell pwd)/
+ROOT:=$(shell realpath $(PWD)../../..)/
+BUILD_DIR:=$(PWD)build/
+
+AFLPP_DRIVER_HOOK_SRC=$(PWD)aflpp_qemu_driver_hook.c
+AFLPP_DRIVER_HOOK_OBJ=$(BUILD_DIR)aflpp_qemu_driver_hook.so
+
+LIBPROJ4_BUILD_DIR:=$(BUILD_DIR)libproj4/
+HARNESS_BUILD_DIR:=$(BUILD_DIR)harness/
+PROJ4TEST_BUILD_DIR:=$(BUILD_DIR)proj4test/
+
+LIBPROJ4_URL:=https://github.com/OSGeo/PROJ
+LIBPROJ4_DIR:=$(LIBPROJ4_BUILD_DIR)libproj4/
+LIBPROJ4_CONFIGURE:=$(LIBPROJ4_DIR)configure.ac
+LIBPROJ4_MAKEFILE:=$(LIBPROJ4_DIR)Makefile
+LIBPROJ4_LIB:=$(LIBPROJ4_DIR)src/.libs/libproj.a
+
+HARNESS_FILE:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.c
+HARNESS_OBJ:=$(HARNESS_BUILD_DIR)StandaloneFuzzTargetMain.o
+HARNESS_URL:="https://raw.githubusercontent.com/AFLplusplus/AFLplusplus/stable/utils/aflpp_driver/aflpp_qemu_driver.c"
+
+PROJ4TEST_FILE:=$(PROJ4TEST_BUILD_DIR)target.cc
+PROJ4TEST_OBJ:=$(PROJ4TEST_BUILD_DIR)target.o
+PROJ4TEST_URL:="https://raw.githubusercontent.com/OSGeo/PROJ/d00501750b210a73f9fb107ac97a683d4e3d8e7a/test/fuzzers/standard_fuzzer.cpp"
+
+LDFLAGS += -lpthread
+
+TEST_BIN:=$(BUILD_DIR)test
+ifeq "$(shell uname)" "Darwin"
+TEST_BIN_LDFLAGS:=-undefined dynamic_lookup
+endif
+
+TEST_DATA_DIR:=$(BUILD_DIR)in/
+TEST_DATA_FILE:=$(TEST_DATA_DIR)default_seed
+
+FRIDA_OUT:=$(BUILD_DIR)frida-out
+
+ifndef ARCH
+
+ARCH=$(shell uname -m)
+ifeq "$(ARCH)" "aarch64"
+ ARCH:=arm64
+endif
+
+ifeq "$(ARCH)" "i686"
+ ARCH:=x86
+endif
+endif
+
+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 $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000)
+endif
+
+ifeq "$(ARCH)" "x86"
+ AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x56555000)
+endif
+
+.PHONY: all clean frida hook
+
+all: $(TEST_BIN)
+ make -C $(ROOT)frida_mode/
+
+32:
+ CXXFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all
+
+$(BUILD_DIR):
+ mkdir -p $@
+
+######### HARNESS ########
+$(HARNESS_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(HARNESS_FILE): | $(HARNESS_BUILD_DIR)
+ wget -O $@ $(HARNESS_URL)
+
+$(HARNESS_OBJ): $(HARNESS_FILE)
+ $(CC) $(CXXFLAGS) $(LDFLAGS) -o $@ -c $<
+
+######### PROJ4TEST ########
+
+$(PROJ4TEST_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(PROJ4TEST_FILE): | $(PROJ4TEST_BUILD_DIR)
+ wget -O $@ $(PROJ4TEST_URL)
+
+$(PROJ4TEST_OBJ): $(PROJ4TEST_FILE) | $(LIBPROJ4_MAKEFILE)
+ $(CXX) $(CXXFLAGS) $(LDFLAGS) -std=c++11 -I $(LIBPROJ4_DIR)src/ -o $@ -c $<
+
+######### LIBPROJ4 ########
+
+$(LIBPROJ4_BUILD_DIR): | $(BUILD_DIR)
+ mkdir -p $@
+
+$(LIBPROJ4_CONFIGURE): $(LIBPROJ4_BUILD_DIR)
+ git clone $(LIBPROJ4_URL) $(LIBPROJ4_DIR)
+ cd $(LIBPROJ4_DIR) && git checkout d00501750b210a73f9fb107ac97a683d4e3d8e7a
+
+$(LIBPROJ4_MAKEFILE): $(LIBPROJ4_CONFIGURE)
+ cd $(LIBPROJ4_DIR) && ./autogen.sh
+ cd $(LIBPROJ4_DIR) && ./configure
+
+$(LIBPROJ4_LIB): $(LIBPROJ4_MAKEFILE)
+ make -C $(LIBPROJ4_DIR) -j $(shell nproc)
+
+######### TEST ########
+
+$(TEST_BIN): $(HARNESS_OBJ) $(PROJ4TEST_OBJ) $(LIBPROJ4_LIB)
+ $(CXX) \
+ $(CFLAGS) \
+ -o $@ \
+ $(HARNESS_OBJ) $(PROJ4TEST_OBJ) $(LIBPROJ4_LIB) \
+ -lz \
+ $(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)
+ mkdir -p $@
+
+$(TEST_DATA_FILE): | $(TEST_DATA_DIR)
+ echo "hi" > $(TEST_DATA_FILE)
+
+###### TEST DATA #######
+
+hook: $(AFLPP_DRIVER_HOOK_OBJ)
+
+clean:
+ rm -rf $(BUILD_DIR)
+
+frida: $(TEST_BIN) $(AFLPP_DRIVER_HOOK_OBJ) $(TEST_DATA_FILE)
+ AFL_DEBUG_CHILD=1 \
+ AFL_DISABLE_TRIM=1 \
+ AFL_FRIDA_PERSISTENT_CNT=1000000 \
+ AFL_I_DONT_CARE_ABOUT_MISSING_CRASHES=1 \
+ AFL_NO_AFFINITY=1 \
+ X__AFL_NO_UI=1 \
+ AFL_PATH=/out \
+ AFL_SHUFFLE_QUEUE=1 \
+ AFL_SKIP_CPUFREQ=1 \
+ AFL_SKIP_CRASHES=1 \
+ AFL_TESTCACHE_SIZE=2 \
+ 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 \
+ -i $(TEST_DATA_DIR) \
+ -o $(FRIDA_OUT) \
+ -m none \
+ -t 1000+ \
+ -d \
+ -O \
+ -c 0\
+ -V 30 \
+ -- \
+ $(TEST_BIN) 2147483647
+
+debug:
+ gdb \
+ --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
+ --ex 'set disassembly-flavor intel' \
+ --args $(TEST_BIN) $(TEST_DATA_DIR)basn0g01.proj4
diff --git a/frida_mode/test/proj4/Makefile b/frida_mode/test/proj4/Makefile
new file mode 100644
index 00000000..863438cf
--- /dev/null
+++ b/frida_mode/test/proj4/Makefile
@@ -0,0 +1,19 @@
+all:
+ @echo trying to use GNU make...
+ @gmake all || echo please install GNUmake
+
+32:
+ @echo trying to use GNU make...
+ @gmake 32 || echo please install GNUmake
+
+clean:
+ @gmake clean
+
+frida:
+ @gmake frida
+
+debug:
+ @gmake debug
+
+hook:
+ @gmake hook
diff --git a/frida_mode/test/proj4/aflpp_qemu_driver_hook.c b/frida_mode/test/proj4/aflpp_qemu_driver_hook.c
new file mode 100644
index 00000000..059d438d
--- /dev/null
+++ b/frida_mode/test/proj4/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/proj4/get_symbol_addr.py b/frida_mode/test/proj4/get_symbol_addr.py
new file mode 100755
index 00000000..1c46e010
--- /dev/null
+++ b/frida_mode/test/proj4/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)