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>
This commit is contained in:
WorksButNotTested
2021-06-16 20:53:57 +01:00
committed by GitHub
parent 35153e9b49
commit 58747f9f4f
11 changed files with 742 additions and 77 deletions

View File

@ -10,18 +10,20 @@
#include "util.h" #include "util.h"
#define DEFAULT_MMAP_MIN_ADDR (32UL << 10) #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; extern struct cmp_map *__afl_cmp_map;
static GArray *cmplog_ranges = NULL; static GArray *cmplog_ranges = NULL;
static int fd_tmp = -1; static GHashTable * hash = NULL;
static ssize_t fd_tmp_size = 0;
static int memfd = -1;
static size_t memfd_size = 0;
static u8 scratch[MAX_MEMFD_SIZE] = {0};
static gboolean cmplog_range(const GumRangeDetails *details, static gboolean cmplog_range(const GumRangeDetails *details,
gpointer user_data) { gpointer user_data) {
UNUSED_PARAMETER(user_data); GArray * cmplog_ranges = (GArray *)user_data;
GumMemoryRange range = *details->range; GumMemoryRange range = *details->range;
g_array_append_val(cmplog_ranges, range); g_array_append_val(cmplog_ranges, range);
return TRUE; return TRUE;
@ -35,37 +37,22 @@ 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 - Collecting ranges");
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);
if (fd < 0) { 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);
FATAL("Failed to create temp file: %s, errno: %d", fname, errno); for (guint i = 0; i < cmplog_ranges->len; i++) {
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);
}
if (ftruncate(fd, 0) < 0) {
FATAL("Failed to ftruncate temp file: %s (%d), errno: %d", fname, fd,
errno);
}
g_free(fname);
return fd;
} }
@ -73,25 +60,28 @@ void cmplog_init(void) {
if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); } if (__afl_cmp_map != NULL) { OKF("CMPLOG mode enabled"); }
cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100); cmplog_get_ranges();
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++) { for (guint i = 0; i < cmplog_ranges->len; i++) {
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i); GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
OKF("CMPLOG Range - 0x%016" G_GINT64_MODIFIER "X - 0x%016" G_GINT64_MODIFIER OKF("CMPLOG Range - %3u: 0x%016" G_GINT64_MODIFIER
"X", "X - 0x%016" G_GINT64_MODIFIER "X",
range->base_address, range->base_address + range->size); i, range->base_address, range->base_address + range->size);
} }
/* memfd = syscall(__NR_memfd_create, "cmplog_memfd", 0);
* We can't use /dev/null or /dev/zero for this since it appears that they if (memfd < 0) {
* 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. FATAL("Failed to create_memfd, errno: %d", errno);
*/
fd_tmp = cmplog_create_temp(); }
hash = g_hash_table_new (g_direct_hash, g_direct_equal);
if (hash == NULL) {
FATAL("Failed to g_hash_table_new, errno: %d", errno);
}
} }
@ -102,6 +92,42 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit,
} }
gboolean cmplog_test_addr(guint64 addr, size_t 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);
}
}
/*
* 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
*/
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;
}
return false;
}
gboolean cmplog_is_readable(guint64 addr, size_t size) { gboolean cmplog_is_readable(guint64 addr, size_t size) {
if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized"); if (cmplog_ranges == NULL) FATAL("CMPLOG not initialized");
@ -125,6 +151,7 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
for (guint i = 0; i < cmplog_ranges->len; i++) { for (guint i = 0; i < cmplog_ranges->len; i++) {
GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i); GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i);
GumAddress outer_base = range->base_address; GumAddress outer_base = range->base_address;
GumAddress outer_limit = outer_base + range->size; GumAddress outer_limit = outer_base + range->size;
@ -133,37 +160,7 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) {
} }
/* if (cmplog_test_addr(addr, size)) { return true; }
* 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; }
}
return false; return false;

View File

@ -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_BL, ctx->rbx)
X86_REG_8L(X86_REG_CL, ctx->rcx) X86_REG_8L(X86_REG_CL, ctx->rcx)
X86_REG_8L(X86_REG_DL, ctx->rdx) 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_BPL, ctx->rbp)
X86_REG_8L(X86_REG_SIL, ctx->rsi) X86_REG_8L(X86_REG_SIL, ctx->rsi)
X86_REG_8L(X86_REG_DIL, ctx->rdi) 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_AH, ctx->rax)
X86_REG_8H(X86_REG_BH, ctx->rbx) 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_BX, ctx->rbx)
X86_REG_16(X86_REG_CX, ctx->rcx) X86_REG_16(X86_REG_CX, ctx->rcx)
X86_REG_16(X86_REG_DX, ctx->rdx) 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_DI, ctx->rdi)
X86_REG_16(X86_REG_SI, ctx->rsi) 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_EAX, ctx->rax)
X86_REG_32(X86_REG_EBX, ctx->rbx)
X86_REG_32(X86_REG_ECX, ctx->rcx) X86_REG_32(X86_REG_ECX, ctx->rcx)
X86_REG_32(X86_REG_EDX, ctx->rdx) 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_ESP, ctx->rsp)
X86_REG_32(X86_REG_EBP, ctx->rbp) X86_REG_32(X86_REG_EBP, ctx->rbp)
X86_REG_32(X86_REG_ESI, ctx->rsi) X86_REG_32(X86_REG_ESI, ctx->rsi)

View File

@ -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_BL, ctx->ebx)
X86_REG_8L(X86_REG_CL, ctx->ecx) X86_REG_8L(X86_REG_CL, ctx->ecx)
X86_REG_8L(X86_REG_DL, ctx->edx) 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_BPL, ctx->ebp)
X86_REG_8L(X86_REG_SIL, ctx->esi) X86_REG_8L(X86_REG_SIL, ctx->esi)
X86_REG_8L(X86_REG_DIL, ctx->edi) 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_BX, ctx->ebx)
X86_REG_16(X86_REG_CX, ctx->ecx) X86_REG_16(X86_REG_CX, ctx->ecx)
X86_REG_16(X86_REG_DX, ctx->edx) 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_DI, ctx->edi)
X86_REG_16(X86_REG_SI, ctx->esi) 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_EAX, ctx->eax)
X86_REG_32(X86_REG_EBX, ctx->ebx)
X86_REG_32(X86_REG_ECX, ctx->ecx) X86_REG_32(X86_REG_ECX, ctx->ecx)
X86_REG_32(X86_REG_EDX, ctx->edx) 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_ESP, ctx->esp)
X86_REG_32(X86_REG_EBP, ctx->ebp) X86_REG_32(X86_REG_EBP, ctx->ebp)
X86_REG_32(X86_REG_ESI, ctx->esi) X86_REG_32(X86_REG_ESI, ctx->esi)

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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