From 39ad3b89467d6de12cbb9d08ccd77d331c0d1f9e Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Wed, 28 Apr 2021 09:25:26 +0100 Subject: Frida persistent (#880) * Added x64 support for persistent mode (function call only), in-memory teest cases and complog * Review changes, fix NeverZero and code to parse the .text section of the main executable. Excluded ranges TBC * Various minor fixes and finished support for AFL_INST_LIBS * Review changes Co-authored-by: Your Name --- frida_mode/src/persistent/persistent_x64.c | 337 +++++++++++++++++++++++++++++ 1 file changed, 337 insertions(+) create mode 100644 frida_mode/src/persistent/persistent_x64.c (limited to 'frida_mode/src/persistent/persistent_x64.c') diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c new file mode 100644 index 00000000..0cabbf24 --- /dev/null +++ b/frida_mode/src/persistent/persistent_x64.c @@ -0,0 +1,337 @@ +#include "frida-gum.h" + +#include "config.h" + +#include "instrument.h" +#include "persistent.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]; + +}; + +typedef struct x86_64_regs arch_api_regs; + +static arch_api_regs saved_regs = {0}; +static void * saved_return = NULL; + +gboolean persistent_is_supported(void) { + + return true; + +} + +static void instrument_persitent_save_regs(GumX86Writer * cw, + struct x86_64_regs *regs) { + + GumAddress regs_address = GUM_ADDRESS(regs); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + + /* Should be pushing FPU here, but meh */ + gum_x86_writer_put_pushfx(cw); + gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address); + + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 1), + GUM_REG_RBX); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 2), + GUM_REG_RCX); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 3), + GUM_REG_RDX); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 4), + GUM_REG_RDI); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 5), + GUM_REG_RSI); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 6), + GUM_REG_RBP); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 7), + GUM_REG_R8); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 8), + GUM_REG_R9); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 9), + GUM_REG_R10); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 10), + GUM_REG_R11); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 11), + GUM_REG_R12); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 12), + GUM_REG_R13); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 13), + GUM_REG_R14); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 14), + GUM_REG_R15); + + /* Store RIP */ + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RBX, + GUM_ADDRESS(persistent_start)); + + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 15), + GUM_REG_RBX); + + /* Store adjusted RSP */ + gum_x86_writer_put_mov_reg_reg(cw, GUM_REG_RBX, GUM_REG_RSP); + + /* RED_ZONE + Saved flags, RAX, alignment */ + gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX, + GUM_RED_ZONE_SIZE + (0x8 * 3)); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 16), + GUM_REG_RBX); + + /* Save the flags */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x8); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 17), + GUM_REG_RBX); + + /* Save the RAX */ + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, 0x0); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 0), + GUM_REG_RBX); + + /* Pop the saved values */ + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 0x10); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + (GUM_RED_ZONE_SIZE)); + +} + +static void instrument_persitent_restore_regs(GumX86Writer * cw, + struct x86_64_regs *regs) { + + GumAddress regs_address = GUM_ADDRESS(regs); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, regs_address); + + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RAX, + (0x8 * 2)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RAX, + (0x8 * 3)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDI, GUM_REG_RAX, + (0x8 * 4)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSI, GUM_REG_RAX, + (0x8 * 5)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBP, GUM_REG_RAX, + (0x8 * 6)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R8, GUM_REG_RAX, + (0x8 * 7)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R9, GUM_REG_RAX, + (0x8 * 8)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R10, GUM_REG_RAX, + (0x8 * 9)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R11, GUM_REG_RAX, + (0x8 * 10)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R12, GUM_REG_RAX, + (0x8 * 11)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R13, GUM_REG_RAX, + (0x8 * 12)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R14, GUM_REG_RAX, + (0x8 * 13)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX, + (0x8 * 14)); + + /* Don't restore RIP or RSP */ + + /* Restore RBX, RAX & Flags */ + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, + (0x8 * 1)); + gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); + + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, + (0x8 * 0)); + gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RAX, + (0x8 * 17)); + gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); + + gum_x86_writer_put_popfx(cw); + gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + (GUM_RED_ZONE_SIZE)); + +} + +static void instrument_save_ret(GumX86Writer *cw, void **saved_return_ptr) { + + GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); + gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, saved_return_address); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, + GUM_RED_ZONE_SIZE + 0x10); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, 0, GUM_REG_RBX); + + gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + (GUM_RED_ZONE_SIZE)); + +} + +static void instrument_jump_ret(GumX86Writer *cw, void **saved_return_ptr) { + + GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + + /* Place holder for ret */ + gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); + gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, saved_return_address); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RAX, GUM_REG_RAX, 0); + + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RSP, 0x8, GUM_REG_RAX); + gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); + gum_x86_writer_put_ret_imm(cw, GUM_RED_ZONE_SIZE); + +} + +static int instrument_afl_persistent_loop_func(void) { + + int ret = __afl_persistent_loop(persistent_count); + previous_pc = 0; + return ret; + +} + +static int instrument_afl_persistent_loop(GumX86Writer *cw) { + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + gum_x86_writer_put_call_address_with_arguments( + cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); + gum_x86_writer_put_test_reg_reg(cw, GUM_REG_RAX, GUM_REG_RAX); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + (GUM_RED_ZONE_SIZE)); + +} + +static void persistent_prologue_hook(GumX86Writer * cw, + struct x86_64_regs *regs) { + + if (hook == NULL) return; + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + -(GUM_RED_ZONE_SIZE)); + + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RCX, + GUM_ADDRESS(__afl_fuzz_len)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); + gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_RDI, 0xffffffff); + gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RCX, GUM_REG_RDI); + + gum_x86_writer_put_call_address_with_arguments( + cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 4, GUM_ARG_ADDRESS, + GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_ADDRESS, + GUM_ADDRESS(__afl_fuzz_ptr), GUM_ARG_REGISTER, GUM_REG_RCX); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + (GUM_RED_ZONE_SIZE)); + +} + +void persistent_prologue(GumStalkerOutput *output) { + + /* + * SAVE REGS + * SAVE RET + * POP RET + * loop: + * CALL instrument_afl_persistent_loop + * TEST EAX, EAX + * JZ end: + * call hook (optionally) + * RESTORE REGS + * call original + * jmp loop: + * + * end: + * JMP SAVED RET + * + * original: + * INSTRUMENTED PERSISTENT FUNC + */ + + GumX86Writer *cw = output->writer.x86; + + gconstpointer loop = cw->code + 1; + // gum_x86_writer_put_breakpoint(cw); + + /* Stack must be 16-byte aligned per ABI */ + instrument_persitent_save_regs(cw, &saved_regs); + + /* Stash and pop the return value */ + instrument_save_ret(cw, &saved_return); + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (8)); + + /* loop: */ + gum_x86_writer_put_label(cw, loop); + + /* call instrument_prologue_func */ + instrument_afl_persistent_loop(cw); + + /* jz done */ + gconstpointer done = cw->code + 1; + gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY); + + /* Optionally call the persistent hook */ + persistent_prologue_hook(cw, &saved_regs); + + instrument_persitent_restore_regs(cw, &saved_regs); + gconstpointer original = cw->code + 1; + /* call original */ + gum_x86_writer_put_call_near_label(cw, original); + /* jmp loop */ + gum_x86_writer_put_jmp_near_label(cw, loop); + + /* done: */ + gum_x86_writer_put_label(cw, done); + + instrument_jump_ret(cw, &saved_return); + + /* original: */ + gum_x86_writer_put_label(cw, original); + + gum_x86_writer_flush(cw); + +} + +#endif + -- cgit 1.4.1 From 3a0d4fe0d0a585d152a59ca4601d1981cedbf113 Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Wed, 28 Apr 2021 18:26:19 +0100 Subject: Bumped warnings up to the max and fixed remaining issues (#890) Co-authored-by: Your Name --- frida_mode/GNUmakefile | 64 +++++++++++++++++++++++++----- frida_mode/include/complog.h | 5 +++ frida_mode/include/instrument.h | 11 +++-- frida_mode/include/interceptor.h | 5 +++ frida_mode/include/lib.h | 5 +++ frida_mode/include/persistent.h | 8 ++-- frida_mode/include/prefetch.h | 5 +++ frida_mode/include/ranges.h | 5 +++ frida_mode/include/stalker.h | 5 +++ frida_mode/include/util.h | 8 ++++ frida_mode/src/complog/complog.c | 3 ++ frida_mode/src/complog/complog_x64.c | 50 ++++++++++------------- frida_mode/src/instrument/instrument.c | 9 +++-- frida_mode/src/interceptor.c | 2 +- frida_mode/src/main.c | 7 ++-- frida_mode/src/persistent/persistent.c | 3 ++ frida_mode/src/persistent/persistent_x64.c | 2 +- frida_mode/src/ranges.c | 19 ++++----- frida_mode/test/png/GNUmakefile | 1 - 19 files changed, 153 insertions(+), 64 deletions(-) (limited to 'frida_mode/src/persistent/persistent_x64.c') diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 6b193806..e317237a 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -3,9 +3,25 @@ ROOT:=$(shell realpath $(PWD)..)/ INC_DIR:=$(PWD)include/ SRC_DIR:=$(PWD)src/ INCLUDES:=$(wildcard $(INC_DIR)*.h) -SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c) BUILD_DIR:=$(PWD)build/ -CFLAGS+=-fPIC -D_GNU_SOURCE -Wno-prio-ctor-dtor -fcommon -Wl,--allow-multiple-definition +OBJ_DIR:=$(BUILD_DIR)obj/ +SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c) +OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src)))) +CFLAGS+=-fPIC \ + -D_GNU_SOURCE \ + -D_FORTIFY_SOURCE=2 \ + -Werror \ + -Wall \ + -Wextra \ + -Wpointer-arith \ + -g \ + -O3 \ + -funroll-loops \ + +LDFLAGS+=-shared \ + -lpthread \ + -lresolv \ + -ldl \ FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/ FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so @@ -36,7 +52,8 @@ GUM_DEVKIT_TARBALL:=$(FRIDA_BUILD_DIR)$(GUM_DEVKIT_FILENAME) GUM_DEVIT_LIBRARY=$(FRIDA_BUILD_DIR)libfrida-gum.a GUM_DEVIT_HEADER=$(FRIDA_BUILD_DIR)frida-gum.h -TEST_BUILD_DIR:=$(BUILD_DIR)test/ +AFL_COMPILER_RT_SRC:=$(ROOT)instrumentation/afl-compiler-rt.o.c +AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o .PHONY: all clean format @@ -49,6 +66,9 @@ all: $(FRIDA_TRACE) $(BUILD_DIR): mkdir -p $(BUILD_DIR) +$(OBJ_DIR): | $(BUILD_DIR) + mkdir -p $@ + $(FRIDA_BUILD_DIR): | $(BUILD_DIR) mkdir -p $@ @@ -61,18 +81,40 @@ $(GUM_DEVIT_LIBRARY): | $(GUM_DEVKIT_TARBALL) $(GUM_DEVIT_HEADER): | $(GUM_DEVKIT_TARBALL) tar Jxvf $(GUM_DEVKIT_TARBALL) -C $(FRIDA_BUILD_DIR) -$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(SOURCES) $(QEMU_INC_API) Makefile | $(BUILD_DIR) - $(CC) -shared \ +$(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC) + $(CC) \ $(CFLAGS) \ - -o $@ \ - $(SOURCES) \ - $(GUM_DEVIT_LIBRARY) \ - -I $(FRIDA_BUILD_DIR) \ -I $(ROOT) \ -I $(ROOT)include \ + -Wno-unused-parameter \ + -Wno-sign-compare \ + -Wno-unused-function \ + -Wno-prio-ctor-dtor \ + -Wno-unused-result \ + -o $@ \ + -c $< + + +define BUILD_SOURCE = +$(2): $(1) GNUmakefile | $(OBJ_DIR) + $(CC) \ + $(CFLAGS) \ + -I $(ROOT)include \ + -I $(FRIDA_BUILD_DIR) \ -I $(INC_DIR) \ - $(ROOT)instrumentation/afl-compiler-rt.o.c -# -lpthread -ldl -lresolv -lelf + -c $1 \ + -o $2 +endef + +$(foreach src,$(SOURCES),$(eval $(call BUILD_SOURCE,$(src),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src)))))) + +$(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(AFL_COMPILER_RT_OBJ) GNUmakefile | $(BUILD_DIR) + $(CC) \ + -o $@ \ + $(OBJS) \ + $(GUM_DEVIT_LIBRARY) \ + $(AFL_COMPILER_RT_OBJ) \ + $(LDFLAGS) \ cp -v $(FRIDA_TRACE) $(ROOT) diff --git a/frida_mode/include/complog.h b/frida_mode/include/complog.h index 094b7b93..1c1adb6d 100644 --- a/frida_mode/include/complog.h +++ b/frida_mode/include/complog.h @@ -1,3 +1,6 @@ +#ifndef _COMPLOG_H +#define _COMPLOG_H + extern struct cmp_map *__afl_cmp_map; void complog_init(void); @@ -7,3 +10,5 @@ void complog_instrument(const cs_insn *instr, GumStalkerIterator *iterator); gboolean complog_is_readable(void *addr, size_t size); +#endif + diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index 1b6c6bba..03fd33e5 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -1,10 +1,13 @@ +#ifndef _INSTRUMENT_H +#define _INSTRUMENT_H + #include "frida-gum.h" #include "config.h" -extern uint64_t __thread previous_pc; -extern uint8_t *__afl_area_ptr; -extern uint32_t __afl_map_size; +extern __thread uint64_t previous_pc; +extern uint8_t * __afl_area_ptr; +extern uint32_t __afl_map_size; void instrument_init(void); @@ -16,3 +19,5 @@ gboolean instrument_is_coverage_optimize_supported(void); void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output); +#endif + diff --git a/frida_mode/include/interceptor.h b/frida_mode/include/interceptor.h index 49c0630a..0ff754a4 100644 --- a/frida_mode/include/interceptor.h +++ b/frida_mode/include/interceptor.h @@ -1,6 +1,11 @@ +#ifndef _INTERCEPTOR_H +#define _INTERCEPTOR_H + #include "frida-gum.h" void intercept(void *address, gpointer replacement, gpointer user_data); void unintercept(void *address); void unintercept_self(void); +#endif + diff --git a/frida_mode/include/lib.h b/frida_mode/include/lib.h index 1dc426a2..237aecb0 100644 --- a/frida_mode/include/lib.h +++ b/frida_mode/include/lib.h @@ -1,3 +1,6 @@ +#ifndef _LIB_H +#define _LIB_H + #include "frida-gum.h" void lib_init(void); @@ -6,3 +9,5 @@ guint64 lib_get_text_base(void); guint64 lib_get_text_limit(void); +#endif + diff --git a/frida_mode/include/persistent.h b/frida_mode/include/persistent.h index 017c26c7..e58c5301 100644 --- a/frida_mode/include/persistent.h +++ b/frida_mode/include/persistent.h @@ -1,6 +1,5 @@ #ifndef _PERSISTENT_H - #define _PERSISTENT_H #include "frida-gum.h" @@ -17,9 +16,9 @@ extern int __afl_persistent_loop(unsigned int max_cnt); extern unsigned int * __afl_fuzz_len; extern unsigned char *__afl_fuzz_ptr; -guint64 persistent_start; -guint64 persistent_count; -afl_persistent_hook_fn hook; +extern guint64 persistent_start; +extern guint64 persistent_count; +extern afl_persistent_hook_fn hook; void persistent_init(void); @@ -29,3 +28,4 @@ gboolean persistent_is_supported(void); void persistent_prologue(GumStalkerOutput *output); #endif + diff --git a/frida_mode/include/prefetch.h b/frida_mode/include/prefetch.h index 110f717f..8f0cee68 100644 --- a/frida_mode/include/prefetch.h +++ b/frida_mode/include/prefetch.h @@ -1,6 +1,11 @@ +#ifndef _PREFETCH_H +#define _PREFETCH_H + #include "frida-gum.h" void prefetch_init(void); void prefetch_write(void *addr); void prefetch_read(void); +#endif + diff --git a/frida_mode/include/ranges.h b/frida_mode/include/ranges.h index a021f35c..f652eb8a 100644 --- a/frida_mode/include/ranges.h +++ b/frida_mode/include/ranges.h @@ -1,6 +1,11 @@ +#ifndef _RANGES_H +#define _RANGES_H + #include "frida-gum.h" void ranges_init(void); gboolean range_is_excluded(gpointer address); +#endif + diff --git a/frida_mode/include/stalker.h b/frida_mode/include/stalker.h index 1962eec9..1f1abb6b 100644 --- a/frida_mode/include/stalker.h +++ b/frida_mode/include/stalker.h @@ -1,3 +1,6 @@ +#ifndef _STALKER_H +#define _STALKER_H + #include "frida-gum.h" void stalker_init(void); @@ -6,3 +9,5 @@ void stalker_start(void); void stalker_pause(void); void stalker_resume(void); +#endif + diff --git a/frida_mode/include/util.h b/frida_mode/include/util.h index 5b4ea76b..afd0b9c1 100644 --- a/frida_mode/include/util.h +++ b/frida_mode/include/util.h @@ -1,6 +1,14 @@ +#ifndef _UTIL_H +#define _UTIL_H + #include "frida-gum.h" +#define UNUSED_PARAMETER(x) (void)(x) +#define IGNORED_RERURN(x) (void)!(x) + guint64 util_read_address(char *key); guint64 util_read_num(char *key); +#endif + diff --git a/frida_mode/src/complog/complog.c b/frida_mode/src/complog/complog.c index 3b679a5c..1857ea3b 100644 --- a/frida_mode/src/complog/complog.c +++ b/frida_mode/src/complog/complog.c @@ -2,6 +2,7 @@ #include "debug.h" #include "cmplog.h" +#include "util.h" extern struct cmp_map *__afl_cmp_map; @@ -10,8 +11,10 @@ static GArray *complog_ranges = NULL; static gboolean complog_range(const GumRangeDetails *details, gpointer user_data) { + UNUSED_PARAMETER(user_data); GumMemoryRange range = *details->range; g_array_append_val(complog_ranges, range); + return TRUE; } diff --git a/frida_mode/src/complog/complog_x64.c b/frida_mode/src/complog/complog_x64.c index 253ec041..28010e7f 100644 --- a/frida_mode/src/complog/complog_x64.c +++ b/frida_mode/src/complog/complog_x64.c @@ -4,6 +4,7 @@ #include "cmplog.h" #include "complog.h" +#include "util.h" #if defined(__x86_64__) @@ -148,7 +149,27 @@ static guint64 complog_read_mem(GumX64CpuContext *ctx, x86_op_mem *mem) { } -static void complog_handle_call(GumCpuContext *context, guint64 target) { +static guint64 cmplog_get_operand_value(GumCpuContext *context, + complog_ctx_t *ctx) { + + switch (ctx->type) { + + case X86_OP_REG: + return complog_read_reg(context, ctx->reg); + case X86_OP_IMM: + return ctx->imm; + case X86_OP_MEM: + return complog_read_mem(context, &ctx->mem); + default: + FATAL("Invalid operand type: %d\n", ctx->type); + + } + +} + +static void complog_call_callout(GumCpuContext *context, gpointer user_data) { + + UNUSED_PARAMETER(user_data); guint64 address = complog_read_reg(context, X86_REG_RIP); guint64 rdi = complog_read_reg(context, X86_REG_RDI); @@ -179,33 +200,6 @@ static void complog_handle_call(GumCpuContext *context, guint64 target) { } -static guint64 cmplog_get_operand_value(GumCpuContext *context, - complog_ctx_t *ctx) { - - switch (ctx->type) { - - case X86_OP_REG: - return complog_read_reg(context, ctx->reg); - case X86_OP_IMM: - return ctx->imm; - case X86_OP_MEM: - return complog_read_mem(context, &ctx->mem); - default: - FATAL("Invalid operand type: %d\n", ctx->type); - - } - -} - -static void complog_call_callout(GumCpuContext *context, gpointer user_data) { - - complog_ctx_t *ctx = (complog_ctx_t *)user_data; - - guint64 target = cmplog_get_operand_value(context, ctx); - complog_handle_call(context, target); - -} - static void complog_instrument_put_operand(complog_ctx_t *ctx, cs_x86_op * operand) { diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 81080bee..3806136a 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -11,17 +11,18 @@ #include "prefetch.h" #include "ranges.h" #include "stalker.h" +#include "util.h" static gboolean tracing = false; static gboolean optimize = false; -static gboolean strict = false; static GumStalkerTransformer *transformer = NULL; -uint64_t __thread previous_pc = 0; +__thread uint64_t previous_pc = 0; __attribute__((hot)) static void on_basic_block(GumCpuContext *context, gpointer user_data) { + UNUSED_PARAMETER(context); /* * This function is performance critical as it is called to instrument every * basic block. By moving our print buffer to a global, we avoid it affecting @@ -44,7 +45,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context, "x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n", current_pc, previous_pc); - write(STDOUT_FILENO, buffer, len + 1); + IGNORED_RERURN(write(STDOUT_FILENO, buffer, len + 1)); } @@ -72,6 +73,8 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context, static void instr_basic_block(GumStalkerIterator *iterator, GumStalkerOutput *output, gpointer user_data) { + UNUSED_PARAMETER(user_data); + const cs_insn *instr; gboolean begin = TRUE; while (gum_stalker_iterator_next(iterator, &instr)) { diff --git a/frida_mode/src/interceptor.c b/frida_mode/src/interceptor.c index 8d41b075..d2802752 100644 --- a/frida_mode/src/interceptor.c +++ b/frida_mode/src/interceptor.c @@ -10,7 +10,7 @@ void intercept(void *address, gpointer replacement, gpointer user_data) { gum_interceptor_begin_transaction(interceptor); GumReplaceReturn ret = gum_interceptor_replace(interceptor, address, replacement, user_data); - if (ret != GUM_ATTACH_OK) { FATAL("gum_interceptor_attach: %d", ret); } + if (ret != GUM_REPLACE_OK) { FATAL("gum_interceptor_attach: %d", ret); } gum_interceptor_end_transaction(interceptor); } diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index f712a8c0..11cf041c 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -21,6 +21,7 @@ #include "prefetch.h" #include "ranges.h" #include "stalker.h" +#include "util.h" #ifdef __APPLE__ extern mach_port_t mach_task_self(); @@ -36,8 +37,6 @@ typedef int *(*main_fn_t)(int argc, char **argv, char **envp); static main_fn_t main_fn = NULL; -static GumMemoryRange code_range = {0}; - extern void __afl_manual_init(); static int on_fork(void) { @@ -55,6 +54,8 @@ static void on_main_os(int argc, char **argv, char **envp) { #else static void on_main_os(int argc, char **argv, char **envp) { + UNUSED_PARAMETER(argc); + /* Personality doesn't affect the current process, it only takes effect on * evec */ int persona = personality(ADDR_NO_RANDOMIZE); @@ -97,7 +98,7 @@ static int *on_main(int argc, char **argv, char **envp) { /* Child here */ previous_pc = 0; stalker_resume(); - main_fn(argc, argv, envp); + return main_fn(argc, argv, envp); } diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c index 34e4093e..fe3a1d20 100644 --- a/frida_mode/src/persistent/persistent.c +++ b/frida_mode/src/persistent/persistent.c @@ -9,6 +9,9 @@ #include "util.h" int __afl_sharedmem_fuzzing = 0; +afl_persistent_hook_fn hook = NULL; +guint64 persistent_start = 0; +guint64 persistent_count = 0; void persistent_init(void) { diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index 0cabbf24..5b8493b2 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -231,7 +231,7 @@ static int instrument_afl_persistent_loop_func(void) { } -static int instrument_afl_persistent_loop(GumX86Writer *cw) { +static void instrument_afl_persistent_loop(GumX86Writer *cw) { gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -(GUM_RED_ZONE_SIZE)); diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 6fcbd258..e3f09f9e 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -5,6 +5,7 @@ #include "lib.h" #include "ranges.h" #include "stalker.h" +#include "util.h" #define MAX_RANGES 20 @@ -167,6 +168,7 @@ gint range_sort(gconstpointer a, gconstpointer b) { static gboolean print_ranges_callback(const GumRangeDetails *details, gpointer user_data) { + UNUSED_PARAMETER(user_data); if (details->file == NULL) { OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER "X", @@ -190,7 +192,7 @@ static gboolean print_ranges_callback(const GumRangeDetails *details, static void print_ranges(char *key, GArray *ranges) { OKF("Range: %s Length: %d", key, ranges->len); - for (int i = 0; i < ranges->len; i++) { + for (guint i = 0; i < ranges->len; i++) { GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i); GumAddress curr_limit = curr->base_address + curr->size; @@ -345,10 +347,10 @@ static GArray *intersect_ranges(GArray *a, GArray *b) { result = g_array_new(false, false, sizeof(GumMemoryRange)); - for (int i = 0; i < a->len; i++) { + for (guint i = 0; i < a->len; i++) { ra = &g_array_index(a, GumMemoryRange, i); - for (int j = 0; j < b->len; j++) { + for (guint j = 0; j < b->len; j++) { rb = &g_array_index(b, GumMemoryRange, j); @@ -377,11 +379,11 @@ static GArray *subtract_ranges(GArray *a, GArray *b) { result = g_array_new(false, false, sizeof(GumMemoryRange)); - for (int i = 0; i < a->len; i++) { + for (guint i = 0; i < a->len; i++) { ra = &g_array_index(a, GumMemoryRange, i); ral = ra->base_address + ra->size; - for (int j = 0; j < b->len; j++) { + for (guint j = 0; j < b->len; j++) { rb = &g_array_index(b, GumMemoryRange, j); @@ -453,7 +455,7 @@ static GArray *merge_ranges(GArray *a) { rp = g_array_index(a, GumMemoryRange, 0); - for (int i = 1; i < a->len; i++) { + for (guint i = 1; i < a->len; i++) { r = &g_array_index(a, GumMemoryRange, i); @@ -535,7 +537,7 @@ void ranges_init(void) { stalker = stalker_get(); - for (int i = 0; i < ranges->len; i++) { + for (guint i = 0; i < ranges->len; i++) { r = &g_array_index(ranges, GumMemoryRange, i); gum_stalker_exclude(stalker, r); @@ -551,12 +553,11 @@ void ranges_init(void) { gboolean range_is_excluded(gpointer address) { - int i; GumAddress test = GUM_ADDRESS(address); if (ranges == NULL) { return false; } - for (i = 0; i < ranges->len; i++) { + for (guint i = 0; i < ranges->len; i++) { GumMemoryRange *curr = &g_array_index(ranges, GumMemoryRange, i); GumAddress curr_limit = curr->base_address + curr->size; diff --git a/frida_mode/test/png/GNUmakefile b/frida_mode/test/png/GNUmakefile index c381f5ab..7de3e85a 100644 --- a/frida_mode/test/png/GNUmakefile +++ b/frida_mode/test/png/GNUmakefile @@ -80,7 +80,6 @@ $(TEST_BIN): $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) -o $@ \ $(HARNESS_OBJ) $(PNGTEST_OBJ) $(LIBPNG_LIB) \ -lz \ - $(TEST_LDFLAGS) clean: rm -rf $(BUILD_DIR) -- cgit 1.4.1 From c6e8314446344d3a65b828feb31f627ce11ba352 Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Fri, 30 Apr 2021 22:42:50 +0100 Subject: Support for AFL_ENTRYPOINT (#898) Co-authored-by: Your Name --- frida_mode/GNUmakefile | 2 +- frida_mode/include/entry.h | 15 +++ frida_mode/include/stalker.h | 2 - frida_mode/src/entry.c | 50 ++++++++++ frida_mode/src/instrument/instrument.c | 2 + frida_mode/src/main.c | 12 +-- frida_mode/src/persistent/persistent_x64.c | 11 ++- frida_mode/src/stalker.c | 19 ---- frida_mode/test/entry_point/GNUmakefile | 61 ++++++++++++ frida_mode/test/entry_point/Makefile | 12 +++ frida_mode/test/entry_point/testinstr.c | 119 ++++++++++++++++++++++++ frida_mode/test/fuzzbench/fuzzer | Bin 0 -> 1703936 bytes frida_mode/test/libxml/xml | Bin 0 -> 1849872 bytes frida_mode/test/png/persistent/GNUmakefile | 27 +++++- frida_mode/test/png/persistent/Makefile | 8 +- frida_mode/test/png/persistent/hook/GNUmakefile | 30 +++++- frida_mode/test/png/persistent/hook/Makefile | 8 +- 17 files changed, 341 insertions(+), 37 deletions(-) create mode 100644 frida_mode/include/entry.h create mode 100644 frida_mode/src/entry.c create mode 100644 frida_mode/test/entry_point/GNUmakefile create mode 100644 frida_mode/test/entry_point/Makefile create mode 100644 frida_mode/test/entry_point/testinstr.c create mode 100755 frida_mode/test/fuzzbench/fuzzer create mode 100755 frida_mode/test/libxml/xml (limited to 'frida_mode/src/persistent/persistent_x64.c') diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 8199b337..7284cf86 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -137,7 +137,7 @@ $(AFL_COMPILER_RT_OBJ): $(AFL_COMPILER_RT_SRC) ############################# SOURCE ########################################### define BUILD_SOURCE -$(2): $(1) GNUmakefile | $(OBJ_DIR) +$(2): $(1) $(INCLUDES) GNUmakefile | $(OBJ_DIR) $(CC) \ $(CFLAGS) \ -I $(ROOT)include \ diff --git a/frida_mode/include/entry.h b/frida_mode/include/entry.h new file mode 100644 index 00000000..967831af --- /dev/null +++ b/frida_mode/include/entry.h @@ -0,0 +1,15 @@ +#ifndef _ENTRY_H +#define _ENTRY_H + +#include "frida-gum.h" + +extern guint64 entry_start; + +void entry_init(void); + +void entry_run(void); + +void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output); + +#endif + diff --git a/frida_mode/include/stalker.h b/frida_mode/include/stalker.h index 1f1abb6b..186ead11 100644 --- a/frida_mode/include/stalker.h +++ b/frida_mode/include/stalker.h @@ -6,8 +6,6 @@ void stalker_init(void); GumStalker *stalker_get(void); void stalker_start(void); -void stalker_pause(void); -void stalker_resume(void); #endif diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c new file mode 100644 index 00000000..e71386a0 --- /dev/null +++ b/frida_mode/src/entry.c @@ -0,0 +1,50 @@ +#include "frida-gum.h" + +#include "debug.h" + +#include "entry.h" +#include "instrument.h" +#include "stalker.h" +#include "util.h" + +extern void __afl_manual_init(); + +guint64 entry_start = 0; + +static void entry_launch(void) { + + __afl_manual_init(); + + /* Child here */ + previous_pc = 0; + +} + +void entry_init(void) { + + entry_start = util_read_address("AFL_ENTRYPOINT"); + OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_start); + +} + +void entry_run(void) { + + if (entry_start == 0) { entry_launch(); } + +} + +static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) { + + UNUSED_PARAMETER(cpu_context); + UNUSED_PARAMETER(user_data); + entry_launch(); + +} + +void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) { + + UNUSED_PARAMETER(output); + gum_stalker_iterator_put_callout(iterator, entry_callout, NULL, NULL); + +} + diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index d93f37c7..971f80c0 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -5,6 +5,7 @@ #include "config.h" #include "debug.h" +#include "entry.h" #include "frida_cmplog.h" #include "instrument.h" #include "persistent.h" @@ -79,6 +80,7 @@ static void instr_basic_block(GumStalkerIterator *iterator, gboolean begin = TRUE; while (gum_stalker_iterator_next(iterator, &instr)) { + if (instr->address == entry_start) { entry_prologue(iterator, output); } if (instr->address == persistent_start) { persistent_prologue(output); } if (begin) { diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index 5c64d192..e031dbed 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -14,6 +14,7 @@ #include "config.h" #include "debug.h" +#include "entry.h" #include "instrument.h" #include "interceptor.h" #include "lib.h" @@ -37,8 +38,6 @@ typedef int *(*main_fn_t)(int argc, char **argv, char **envp); static main_fn_t main_fn = NULL; -extern void __afl_manual_init(); - static int on_fork(void) { prefetch_read(); @@ -79,6 +78,7 @@ static void on_main_os(int argc, char **argv, char **envp) { static int *on_main(int argc, char **argv, char **envp) { void *fork_addr; + on_main_os(argc, argv, envp); unintercept_self(); @@ -86,6 +86,7 @@ static int *on_main(int argc, char **argv, char **envp) { stalker_init(); lib_init(); + entry_init(); instrument_init(); persistent_init(); prefetch_init(); @@ -95,13 +96,8 @@ static int *on_main(int argc, char **argv, char **envp) { intercept(fork_addr, on_fork, NULL); stalker_start(); - stalker_pause(); - - __afl_manual_init(); + entry_run(); - /* Child here */ - previous_pc = 0; - stalker_resume(); return main_fn(argc, argv, envp); } diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index 5b8493b2..49f1988c 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -252,15 +252,20 @@ static void persistent_prologue_hook(GumX86Writer * cw, -(GUM_RED_ZONE_SIZE)); gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RCX, - GUM_ADDRESS(__afl_fuzz_len)); + GUM_ADDRESS(&__afl_fuzz_len)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RCX, GUM_REG_RCX, 0); gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_RDI, 0xffffffff); gum_x86_writer_put_and_reg_reg(cw, GUM_REG_RCX, GUM_REG_RDI); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDX, + GUM_ADDRESS(&__afl_fuzz_ptr)); + gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RDX, GUM_REG_RDX, 0); + gum_x86_writer_put_call_address_with_arguments( cw, GUM_CALL_CAPI, GUM_ADDRESS(hook), 4, GUM_ARG_ADDRESS, - GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_ADDRESS, - GUM_ADDRESS(__afl_fuzz_ptr), GUM_ARG_REGISTER, GUM_REG_RCX); + GUM_ADDRESS(regs), GUM_ARG_ADDRESS, GUM_ADDRESS(0), GUM_ARG_REGISTER, + GUM_REG_RDX, GUM_ARG_REGISTER, GUM_REG_RCX); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (GUM_RED_ZONE_SIZE)); diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c index 5ee519ba..81973e9c 100644 --- a/frida_mode/src/stalker.c +++ b/frida_mode/src/stalker.c @@ -21,12 +21,6 @@ GumStalker *stalker_get(void) { } -__attribute__((noinline)) static void stalker_activation(void) { - - asm volatile(""); - -} - void stalker_start(void) { GumStalkerTransformer *transformer = instrument_get_transformer(); @@ -34,16 +28,3 @@ void stalker_start(void) { } -void stalker_pause(void) { - - gum_stalker_deactivate(stalker); - -} - -void stalker_resume(void) { - - gum_stalker_activate(stalker, stalker_activation); - stalker_activation(); - -} - diff --git a/frida_mode/test/entry_point/GNUmakefile b/frida_mode/test/entry_point/GNUmakefile new file mode 100644 index 00000000..891827eb --- /dev/null +++ b/frida_mode/test/entry_point/GNUmakefile @@ -0,0 +1,61 @@ +PWD:=$(shell pwd)/ +ROOT:=$(shell realpath $(PWD)../../..)/ +BUILD_DIR:=$(PWD)build/ +TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/ +TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in + +TESTINSTBIN:=$(BUILD_DIR)testinstr +TESTINSTSRC:=$(PWD)testinstr.c + +QEMU_OUT:=$(BUILD_DIR)qemu-out +FRIDA_OUT:=$(BUILD_DIR)frida-out + +GET_SYMBOL_ADDR:=$(ROOT)frida_mode/test/png/persistent/get_symbol_addr.py + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000aaaaaaaaa000) +endif + +ifeq "$(ARCH)" "x86_64" + AFL_ENTRYPOINT=$(shell $(GET_SYMBOL_ADDR) -f $(TESTINSTBIN) -s run -b 0x0000555555554000) +endif + +.PHONY: all clean qemu frida + +all: $(TESTINSTBIN) + make -C $(ROOT)frida_mode/ + +$(BUILD_DIR): + mkdir -p $@ + +$(TESTINSTR_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) + echo -n "000" > $@ + +$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) + $(CC) -o $@ $< + +clean: + rm -rf $(BUILD_DIR) + +frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) @@ + +frida_entry: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + AFL_ENTRYPOINT=$(AFL_ENTRYPOINT) \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) @@ \ No newline at end of file diff --git a/frida_mode/test/entry_point/Makefile b/frida_mode/test/entry_point/Makefile new file mode 100644 index 00000000..3b41b94e --- /dev/null +++ b/frida_mode/test/entry_point/Makefile @@ -0,0 +1,12 @@ +all: + @echo trying to use GNU make... + @gmake all || echo please install GNUmake + +clean: + @gmake clean + +frida: + @gmake frida + +frida_entry: + @gmake frida \ No newline at end of file diff --git a/frida_mode/test/entry_point/testinstr.c b/frida_mode/test/entry_point/testinstr.c new file mode 100644 index 00000000..a6c655f9 --- /dev/null +++ b/frida_mode/test/entry_point/testinstr.c @@ -0,0 +1,119 @@ +/* + american fuzzy lop++ - a trivial program to test the build + -------------------------------------------------------- + Originally written by Michal Zalewski + Copyright 2014 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ + #define TESTINSTR_SECTION +#else + #define TESTINSTR_SECTION __attribute__((section(".testinstr"))) +#endif + +void testinstr(char *buf, int len) { + + if (len < 1) return; + buf[len] = 0; + + // we support three input cases + if (buf[0] == '0') + printf("Looks like a zero to me!\n"); + else if (buf[0] == '1') + printf("Pretty sure that is a one!\n"); + else + printf("Neither one or zero? How quaint!\n"); + +} + +int run(char *file) { + + int fd = -1; + off_t len; + char * buf = NULL; + size_t n_read; + int result = -1; + + do { + + dprintf(STDERR_FILENO, "Running: %s\n", file); + + fd = open(file, O_RDONLY); + if (fd < 0) { + + perror("open"); + break; + + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + + perror("lseek (SEEK_END)"); + break; + + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + + perror("lseek (SEEK_SET)"); + break; + + } + + buf = malloc(len); + if (buf == NULL) { + + perror("malloc"); + break; + + } + + n_read = read(fd, buf, len); + if (n_read != len) { + + perror("read"); + break; + + } + + dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); + + testinstr(buf, len); + dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); + + result = 0; + + } while (false); + + if (buf != NULL) { free(buf); } + + if (fd != -1) { close(fd); } + + return result; + +} + +void slow() { + usleep(100000); +} + +int main(int argc, char **argv) { + + if (argc != 2) { return 1; } + slow(); + return run(argv[1]); + +} + diff --git a/frida_mode/test/fuzzbench/fuzzer b/frida_mode/test/fuzzbench/fuzzer new file mode 100755 index 00000000..5e8b7f70 Binary files /dev/null and b/frida_mode/test/fuzzbench/fuzzer differ diff --git a/frida_mode/test/libxml/xml b/frida_mode/test/libxml/xml new file mode 100755 index 00000000..fb5c7c76 Binary files /dev/null and b/frida_mode/test/libxml/xml differ diff --git a/frida_mode/test/png/persistent/GNUmakefile b/frida_mode/test/png/persistent/GNUmakefile index 25ddc782..531f9bce 100644 --- a/frida_mode/test/png/persistent/GNUmakefile +++ b/frida_mode/test/png/persistent/GNUmakefile @@ -19,7 +19,7 @@ ifeq "$(ARCH)" "x86_64" AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TEST_BIN) -s main -b 0x0000555555554000) endif -.PHONY: all clean qemu frida +.PHONY: all clean qemu qemu_entry frida frida_entry all: make -C $(ROOT)frida_mode/test/png/ @@ -39,6 +39,19 @@ qemu: | $(BUILD_DIR) -- \ $(TEST_BIN) @@ +qemu_entry: | $(BUILD_DIR) + AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ + AFL_QEMU_PERSISTENT_GPR=1 \ + AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -D \ + -V 30 \ + -Q \ + -i $(TEST_DATA_DIR) \ + -o $(QEMU_OUT) \ + -- \ + $(TEST_BIN) @@ + frida: | $(BUILD_DIR) AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ $(ROOT)afl-fuzz \ @@ -50,5 +63,17 @@ frida: | $(BUILD_DIR) -- \ $(TEST_BIN) @@ +frida_entry: | $(BUILD_DIR) + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -D \ + -V 30 \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TEST_BIN) @@ + clean: rm -rf $(BUILD_DIR) \ No newline at end of file diff --git a/frida_mode/test/png/persistent/Makefile b/frida_mode/test/png/persistent/Makefile index f322d1f5..5fde63c2 100644 --- a/frida_mode/test/png/persistent/Makefile +++ b/frida_mode/test/png/persistent/Makefile @@ -8,5 +8,11 @@ clean: qemu: @gmake qemu +qemu_entry: + @gmake qemu_entry + frida: - @gmake frida \ No newline at end of file + @gmake frida + +frida_entry: + @gmake frida_entry \ No newline at end of file diff --git a/frida_mode/test/png/persistent/hook/GNUmakefile b/frida_mode/test/png/persistent/hook/GNUmakefile index 2457287d..4f55fe98 100644 --- a/frida_mode/test/png/persistent/hook/GNUmakefile +++ b/frida_mode/test/png/persistent/hook/GNUmakefile @@ -23,7 +23,7 @@ ifeq "$(ARCH)" "x86_64" AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)../get_symbol_addr.py -f $(TEST_BIN) -s LLVMFuzzerTestOneInput -b 0x0000555555554000) endif -.PHONY: all clean qemu frida +.PHONY: all clean qemu qemu_entry frida frida_entry all: make -C $(ROOT)frida_mode/test/png/persistent/ @@ -53,6 +53,20 @@ qemu: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) +qemu_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) + AFL_QEMU_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ + AFL_QEMU_PERSISTENT_ADDR=$(AFL_QEMU_PERSISTENT_ADDR) \ + AFL_ENTRYPOINT=$(AFL_QEMU_PERSISTENT_ADDR) \ + AFL_QEMU_PERSISTENT_GPR=1 \ + $(ROOT)/afl-fuzz \ + -D \ + -V 30 \ + -Q \ + -i $(TEST_DATA_DIR) \ + -o $(QEMU_OUT) \ + -- \ + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + frida: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) AFL_FRIDA_PERSISTENT_HOOK=$(AFLPP_DRIVER_HOOK_OBJ) \ AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ @@ -65,6 +79,20 @@ frida: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) -- \ $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + +frida_entry: $(AFLPP_DRIVER_DUMMY_INPUT) $(AFLPP_DRIVER_HOOK_OBJ) | $(BUILD_DIR) + 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 \ + -D \ + -V 30 \ + -O \ + -i $(TEST_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TEST_BIN) $(AFLPP_DRIVER_DUMMY_INPUT) + clean: rm -rf $(BUILD_DIR) diff --git a/frida_mode/test/png/persistent/hook/Makefile b/frida_mode/test/png/persistent/hook/Makefile index f322d1f5..5fde63c2 100644 --- a/frida_mode/test/png/persistent/hook/Makefile +++ b/frida_mode/test/png/persistent/hook/Makefile @@ -8,5 +8,11 @@ clean: qemu: @gmake qemu +qemu_entry: + @gmake qemu_entry + frida: - @gmake frida \ No newline at end of file + @gmake frida + +frida_entry: + @gmake frida_entry \ No newline at end of file -- cgit 1.4.1 From a1458ea6715e8801bf28fec0ac66f06b96eb1e66 Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Thu, 20 May 2021 18:16:58 +0100 Subject: Changes to have persistent mode exit at the end of the loop (#928) Co-authored-by: Your Name --- frida_mode/GNUmakefile | 1 - frida_mode/src/persistent/persistent_x64.c | 46 ++++-------------------------- frida_mode/src/persistent/persistent_x86.c | 40 +++++--------------------- 3 files changed, 13 insertions(+), 74 deletions(-) (limited to 'frida_mode/src/persistent/persistent_x64.c') diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index bc77a451..a0387cac 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -93,7 +93,6 @@ AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o ############################## ALL ############################################# all: $(FRIDA_TRACE) - make -C $(ROOT) 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index 49f1988c..aa772b7f 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -40,7 +40,6 @@ struct x86_64_regs { typedef struct x86_64_regs arch_api_regs; static arch_api_regs saved_regs = {0}; -static void * saved_return = NULL; gboolean persistent_is_supported(void) { @@ -183,43 +182,11 @@ static void instrument_persitent_restore_regs(GumX86Writer * cw, } -static void instrument_save_ret(GumX86Writer *cw, void **saved_return_ptr) { +static void instrument_exit(GumX86Writer *cw) { - GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - -(GUM_RED_ZONE_SIZE)); - gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); - gum_x86_writer_put_push_reg(cw, GUM_REG_RBX); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, saved_return_address); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP, - GUM_RED_ZONE_SIZE + 0x10); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, 0, GUM_REG_RBX); - - gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); - - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - (GUM_RED_ZONE_SIZE)); - -} - -static void instrument_jump_ret(GumX86Writer *cw, void **saved_return_ptr) { - - GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - -(GUM_RED_ZONE_SIZE)); - - /* Place holder for ret */ - gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); - gum_x86_writer_put_push_reg(cw, GUM_REG_RAX); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, saved_return_address); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RAX, GUM_REG_RAX, 0); - - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RSP, 0x8, GUM_REG_RAX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX); - gum_x86_writer_put_ret_imm(cw, GUM_RED_ZONE_SIZE); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(_exit)); + gum_x86_writer_put_mov_reg_u32(cw, GUM_REG_RDI, 0); + gum_x86_writer_put_call_reg(cw, GUM_REG_RAX); } @@ -302,8 +269,7 @@ void persistent_prologue(GumStalkerOutput *output) { /* Stack must be 16-byte aligned per ABI */ instrument_persitent_save_regs(cw, &saved_regs); - /* Stash and pop the return value */ - instrument_save_ret(cw, &saved_return); + /* pop the return value */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (8)); /* loop: */ @@ -329,7 +295,7 @@ void persistent_prologue(GumStalkerOutput *output) { /* done: */ gum_x86_writer_put_label(cw, done); - instrument_jump_ret(cw, &saved_return); + instrument_exit(cw); /* original: */ gum_x86_writer_put_label(cw, original); diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index bd7171b9..20a3dc42 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -39,7 +39,6 @@ struct x86_regs { typedef struct x86_regs arch_api_regs; static arch_api_regs saved_regs = {0}; -static void * saved_return = NULL; gboolean persistent_is_supported(void) { @@ -138,36 +137,12 @@ static void instrument_persitent_restore_regs(GumX86Writer * cw, } -static void instrument_save_ret(GumX86Writer *cw, void **saved_return_ptr) { +static void instrument_exit(GumX86Writer *cw) { - GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); - - gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); - gum_x86_writer_put_push_reg(cw, GUM_REG_EBX); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, saved_return_address); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP, 0x8); - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_EAX, 0, GUM_REG_EBX); - - gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); - -} - -static void instrument_jump_ret(GumX86Writer *cw, void **saved_return_ptr) { - - GumAddress saved_return_address = GUM_ADDRESS(saved_return_ptr); - - /* Place holder for ret */ - gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); - gum_x86_writer_put_push_reg(cw, GUM_REG_EAX); - - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, saved_return_address); - gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EAX, GUM_REG_EAX, 0); - - gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_ESP, 0x4, GUM_REG_EAX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX); - gum_x86_writer_put_ret(cw); + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(_exit)); + gum_x86_writer_put_mov_reg_u32(cw, GUM_REG_EDI, 0); + gum_x86_writer_put_push_reg(cw, GUM_REG_EDI); + gum_x86_writer_put_call_reg(cw, GUM_REG_EAX); } @@ -238,8 +213,7 @@ void persistent_prologue(GumStalkerOutput *output) { /* Stack must be 16-byte aligned per ABI */ instrument_persitent_save_regs(cw, &saved_regs); - /* Stash and pop the return value */ - instrument_save_ret(cw, &saved_return); + /* Pop the return value */ gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4)); /* loop: */ @@ -265,7 +239,7 @@ void persistent_prologue(GumStalkerOutput *output) { /* done: */ gum_x86_writer_put_label(cw, done); - instrument_jump_ret(cw, &saved_return); + instrument_exit(cw); /* original: */ gum_x86_writer_put_label(cw, original); -- cgit 1.4.1 From f677be5e86a096edbba74cb8c739e8b10850a379 Mon Sep 17 00:00:00 2001 From: WorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com> Date: Thu, 27 May 2021 21:33:44 +0100 Subject: Support for AFL_FRIDA_PERSISTENT_RET (#941) Co-authored-by: Your Name --- frida_mode/GNUmakefile | 7 +- frida_mode/include/persistent.h | 4 + frida_mode/src/instrument/instrument.c | 1 + frida_mode/src/persistent/persistent.c | 34 +++++- frida_mode/src/persistent/persistent_arm32.c | 7 ++ frida_mode/src/persistent/persistent_arm64.c | 7 ++ frida_mode/src/persistent/persistent_x64.c | 19 +++- frida_mode/src/persistent/persistent_x86.c | 15 +++ frida_mode/src/util.c | 13 +-- frida_mode/test/persistent_ret/GNUmakefile | 105 +++++++++++++++++++ frida_mode/test/persistent_ret/Makefile | 22 ++++ frida_mode/test/persistent_ret/get_symbol_addr.py | 36 +++++++ frida_mode/test/persistent_ret/testinstr.c | 120 ++++++++++++++++++++++ include/envs.h | 3 + 14 files changed, 382 insertions(+), 11 deletions(-) create mode 100644 frida_mode/test/persistent_ret/GNUmakefile create mode 100644 frida_mode/test/persistent_ret/Makefile create mode 100755 frida_mode/test/persistent_ret/get_symbol_addr.py create mode 100644 frida_mode/test/persistent_ret/testinstr.c (limited to 'frida_mode/src/persistent/persistent_x64.c') diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 20fbb544..f9c0f1f7 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -36,6 +36,10 @@ else CFLAGS+=-Wno-pointer-arith endif +ifdef FRIDA_DEBUG +CFLAGS += -DFRIDA_DEBUG +endif + FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/ FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded @@ -94,9 +98,6 @@ AFL_COMPILER_RT_OBJ:=$(OBJ_DIR)afl-compiler-rt.o all: $(FRIDA_TRACE) -32: - CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all - 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all diff --git a/frida_mode/include/persistent.h b/frida_mode/include/persistent.h index e58c5301..25b44ab0 100644 --- a/frida_mode/include/persistent.h +++ b/frida_mode/include/persistent.h @@ -18,6 +18,9 @@ extern unsigned char *__afl_fuzz_ptr; extern guint64 persistent_start; extern guint64 persistent_count; +extern guint64 persistent_ret; +extern guint64 persistent_ret_offset; +extern gboolean persistent_debug; extern afl_persistent_hook_fn hook; void persistent_init(void); @@ -26,6 +29,7 @@ void persistent_init(void); gboolean persistent_is_supported(void); void persistent_prologue(GumStalkerOutput *output); +void persistent_epilogue(GumStalkerOutput *output); #endif diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index f21849a6..c4f18797 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -85,6 +85,7 @@ static void instr_basic_block(GumStalkerIterator *iterator, if (instr->address == entry_start) { entry_prologue(iterator, output); } if (instr->address == persistent_start) { persistent_prologue(output); } + if (instr->address == persistent_ret) { persistent_epilogue(output); } /* * Until we reach AFL_ENTRYPOINT (assumed to be main if not specified) or diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c index 918ff153..2ec5b9cc 100644 --- a/frida_mode/src/persistent/persistent.c +++ b/frida_mode/src/persistent/persistent.c @@ -12,6 +12,9 @@ int __afl_sharedmem_fuzzing = 0; afl_persistent_hook_fn hook = NULL; guint64 persistent_start = 0; guint64 persistent_count = 0; +guint64 persistent_ret = 0; +guint64 persistent_ret_offset = 0; +gboolean persistent_debug = FALSE; void persistent_init(void) { @@ -19,12 +22,36 @@ void persistent_init(void) { persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR"); persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT"); + persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET"); + persistent_ret_offset = + util_read_address("AFL_FRIDA_PERSISTENT_RETADDR_OFFSET"); + + if (getenv("AFL_FRIDA_PERSISTENT_DEBUG") != NULL) { persistent_debug = TRUE; } + + if (persistent_count != 0 && persistent_start == 0) { - if (persistent_count != 0 && persistent_start == 0) FATAL( "AFL_FRIDA_PERSISTENT_ADDR must be specified if " "AFL_FRIDA_PERSISTENT_CNT is"); + } + + if (persistent_ret != 0 && persistent_start == 0) { + + FATAL( + "AFL_FRIDA_PERSISTENT_ADDR must be specified if " + "AFL_FRIDA_PERSISTENT_RET is"); + + } + + if (persistent_ret_offset != 0 && persistent_ret == 0) { + + FATAL( + "AFL_FRIDA_PERSISTENT_RET must be specified if " + "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET is"); + + } + if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000; if (persistent_count != 0 && persistent_count < 100) @@ -39,6 +66,11 @@ void persistent_init(void) { persistent_start == 0 ? ' ' : 'X', persistent_count); OKF("Instrumentation - hook [%s]", hook_name); + OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)", + persistent_ret == 0 ? ' ' : 'X', persistent_ret); + OKF("Instrumentation - persistent ret offset [%c] (%" G_GINT64_MODIFIER "d)", + persistent_ret_offset == 0 ? ' ' : 'X', persistent_ret_offset); + if (hook_name != NULL) { void *hook_obj = dlopen(hook_name, RTLD_NOW); diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index bc021ff3..6a3c06fa 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -68,5 +68,12 @@ void persistent_prologue(GumStalkerOutput *output) { } +void persistent_epilogue(GumStalkerOutput *output) { + + UNUSED_PARAMETER(output); + FATAL("Persistent mode not supported on this architecture"); + +} + #endif diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c index c198da69..1215d8da 100644 --- a/frida_mode/src/persistent/persistent_arm64.c +++ b/frida_mode/src/persistent/persistent_arm64.c @@ -111,5 +111,12 @@ void persistent_prologue(GumStalkerOutput *output) { } +void persistent_epilogue(GumStalkerOutput *output) { + + UNUSED_PARAMETER(output); + FATAL("Persistent mode not supported on this architecture"); + +} + #endif diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index aa772b7f..4c495d47 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -1,9 +1,11 @@ #include "frida-gum.h" #include "config.h" +#include "debug.h" #include "instrument.h" #include "persistent.h" +#include "util.h" #if defined(__x86_64__) @@ -264,7 +266,6 @@ void persistent_prologue(GumStalkerOutput *output) { GumX86Writer *cw = output->writer.x86; gconstpointer loop = cw->code + 1; - // gum_x86_writer_put_breakpoint(cw); /* Stack must be 16-byte aligned per ABI */ instrument_persitent_save_regs(cw, &saved_regs); @@ -288,7 +289,9 @@ void persistent_prologue(GumStalkerOutput *output) { instrument_persitent_restore_regs(cw, &saved_regs); gconstpointer original = cw->code + 1; /* call original */ + gum_x86_writer_put_call_near_label(cw, original); + /* jmp loop */ gum_x86_writer_put_jmp_near_label(cw, loop); @@ -300,9 +303,23 @@ void persistent_prologue(GumStalkerOutput *output) { /* original: */ gum_x86_writer_put_label(cw, original); + if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + gum_x86_writer_flush(cw); } +void persistent_epilogue(GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + + if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, + persistent_ret_offset); + gum_x86_writer_put_ret(cw); + +} + #endif diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index 20a3dc42..b30dfadf 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -244,9 +244,24 @@ void persistent_prologue(GumStalkerOutput *output) { /* original: */ gum_x86_writer_put_label(cw, original); + if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + gum_x86_writer_flush(cw); } +void persistent_epilogue(GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + + if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, + persistent_ret_offset); + + gum_x86_writer_put_ret(cw); + +} + #endif diff --git a/frida_mode/src/util.c b/frida_mode/src/util.c index 86b94970..09e8a58b 100644 --- a/frida_mode/src/util.c +++ b/frida_mode/src/util.c @@ -10,7 +10,7 @@ guint64 util_read_address(char *key) { if (!g_str_has_prefix(value_str, "0x")) { - FATAL("Invalid address should have 0x prefix: %s\n", value_str); + FATAL("Invalid address should have 0x prefix: %s=%s\n", key, value_str); } @@ -20,8 +20,8 @@ guint64 util_read_address(char *key) { if (!g_ascii_isxdigit(*c)) { - FATAL("Invalid address not formed of hex digits: %s ('%c')\n", value_str, - *c); + FATAL("Invalid address not formed of hex digits: %s=%s ('%c')\n", key, + value_str, *c); } @@ -30,7 +30,7 @@ guint64 util_read_address(char *key) { guint64 value = g_ascii_strtoull(value_str2, NULL, 16); if (value == 0) { - FATAL("Invalid address failed hex conversion: %s\n", value_str2); + FATAL("Invalid address failed hex conversion: %s=%s\n", key, value_str2); } @@ -48,7 +48,8 @@ guint64 util_read_num(char *key) { if (!g_ascii_isdigit(*c)) { - FATAL("Invalid address not formed of decimal digits: %s\n", value_str); + FATAL("Invalid address not formed of decimal digits: %s=%s\n", key, + value_str); } @@ -57,7 +58,7 @@ guint64 util_read_num(char *key) { guint64 value = g_ascii_strtoull(value_str, NULL, 10); if (value == 0) { - FATAL("Invalid address failed numeric conversion: %s\n", value_str); + FATAL("Invalid address failed numeric conversion: %s=%s\n", key, value_str); } diff --git a/frida_mode/test/persistent_ret/GNUmakefile b/frida_mode/test/persistent_ret/GNUmakefile new file mode 100644 index 00000000..df48d065 --- /dev/null +++ b/frida_mode/test/persistent_ret/GNUmakefile @@ -0,0 +1,105 @@ +PWD:=$(shell pwd)/ +ROOT:=$(shell realpath $(PWD)../../..)/ +BUILD_DIR:=$(PWD)build/ +TESTINSTR_DATA_DIR:=$(BUILD_DIR)in/ +TESTINSTR_DATA_FILE:=$(TESTINSTR_DATA_DIR)in + +TESTINSTBIN:=$(BUILD_DIR)testinstr +TESTINSTSRC:=$(PWD)testinstr.c + +QEMU_OUT:=$(BUILD_DIR)qemu-out +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 + +ARCH=$(shell uname -m) +ifeq "$(ARCH)" "aarch64" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s main -b 0x0000aaaaaaaaa000) + AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x0000aaaaaaaaa000) +endif + +ifeq "$(ARCH)" "x86_64" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s main -b 0x0000555555554000) + AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x0000555555554000) +endif + +ifeq "$(ARCH)" "x86" + AFL_FRIDA_PERSISTENT_ADDR=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s main -b 0x56555000) + AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x56555000) +endif + +AFL_FRIDA_PERSISTENT_RETADDR_OFFSET:=0x50 + +.PHONY: all 32 clean qemu frida + +all: $(TESTINSTBIN) + make -C $(ROOT)frida_mode/ + +32: + CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all + +$(BUILD_DIR): + mkdir -p $@ + +$(TESTINSTR_DATA_DIR): | $(BUILD_DIR) + mkdir -p $@ + +$(TESTINSTR_DATA_FILE): | $(TESTINSTR_DATA_DIR) + echo -n "000" > $@ + +$(TESTINSTBIN): $(TESTINSTSRC) | $(BUILD_DIR) + $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $< + +clean: + rm -rf $(BUILD_DIR) + +frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) @@ + +frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \ + AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \ + $(ROOT)afl-fuzz \ + -D \ + -O \ + -i $(TESTINSTR_DATA_DIR) \ + -o $(FRIDA_OUT) \ + -- \ + $(TESTINSTBIN) @@ + +debug: $(TESTINSTR_DATA_FILE) + gdb \ + --ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \ + --ex 'set environment AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET)' \ + --ex 'set environment AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET)' \ + --ex 'set environment AFL_FRIDA_PERSISTENT_DEBUG=1' \ + --ex 'set environment AFL_DEBUG_CHILD=1' \ + --ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \ + --ex 'set disassembly-flavor intel' \ + --args $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) + +run: $(TESTINSTR_DATA_FILE) + AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \ + AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \ + AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \ + AFL_DEBUG_CHILD=1 \ + LD_PRELOAD=$(ROOT)afl-frida-trace.so \ + $(TESTINSTBIN) $(TESTINSTR_DATA_FILE) diff --git a/frida_mode/test/persistent_ret/Makefile b/frida_mode/test/persistent_ret/Makefile new file mode 100644 index 00000000..e3deddbd --- /dev/null +++ b/frida_mode/test/persistent_ret/Makefile @@ -0,0 +1,22 @@ +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 + +frida_ret: + @gmake frida_ret + +debug: + @gmake debug + +run: + @gmake run diff --git a/frida_mode/test/persistent_ret/get_symbol_addr.py b/frida_mode/test/persistent_ret/get_symbol_addr.py new file mode 100755 index 00000000..1c46e010 --- /dev/null +++ b/frida_mode/test/persistent_ret/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/persistent_ret/testinstr.c b/frida_mode/test/persistent_ret/testinstr.c new file mode 100644 index 00000000..6cb88a50 --- /dev/null +++ b/frida_mode/test/persistent_ret/testinstr.c @@ -0,0 +1,120 @@ +/* + american fuzzy lop++ - a trivial program to test the build + -------------------------------------------------------- + Originally written by Michal Zalewski + Copyright 2014 Google Inc. All rights reserved. + Copyright 2019-2020 AFLplusplus Project. All rights reserved. + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at: + http://www.apache.org/licenses/LICENSE-2.0 + */ + +#include +#include +#include +#include +#include + +#ifdef __APPLE__ + #define TESTINSTR_SECTION +#else + #define TESTINSTR_SECTION __attribute__((section(".testinstr"))) +#endif + +void testinstr(char *buf, int len) { + + if (len < 1) return; + buf[len] = 0; + + // we support three input cases + if (buf[0] == '0') + printf("Looks like a zero to me!\n"); + else if (buf[0] == '1') + printf("Pretty sure that is a one!\n"); + else + printf("Neither one or zero? How quaint!\n"); + +} + +void slow() { + + usleep(100000); + +} + +TESTINSTR_SECTION int main(int argc, char **argv) { + + char * file; + int fd = -1; + off_t len; + char * buf = NULL; + size_t n_read; + int result = -1; + + if (argc != 2) { return 1; } + + do { + + file = argv[1]; + + dprintf(STDERR_FILENO, "Running: %s\n", file); + + fd = open(file, O_RDONLY); + if (fd < 0) { + + perror("open"); + break; + + } + + len = lseek(fd, 0, SEEK_END); + if (len < 0) { + + perror("lseek (SEEK_END)"); + break; + + } + + if (lseek(fd, 0, SEEK_SET) != 0) { + + perror("lseek (SEEK_SET)"); + break; + + } + + buf = malloc(len); + if (buf == NULL) { + + perror("malloc"); + break; + + } + + n_read = read(fd, buf, len); + if (n_read != len) { + + perror("read"); + break; + + } + + dprintf(STDERR_FILENO, "Running: %s: (%zd bytes)\n", file, n_read); + + testinstr(buf, len); + dprintf(STDERR_FILENO, "Done: %s: (%zd bytes)\n", file, n_read); + + slow(); + + result = 0; + + } while (false); + + if (buf != NULL) { free(buf); } + + if (fd != -1) { close(fd); } + + return result; + +} + diff --git a/include/envs.h b/include/envs.h index e7162c0f..73cd82a8 100644 --- a/include/envs.h +++ b/include/envs.h @@ -62,7 +62,10 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_INST_TRACE", "AFL_FRIDA_PERSISTENT_ADDR", "AFL_FRIDA_PERSISTENT_CNT", + "AFL_FRIDA_PERSISTENT_DEBUG", "AFL_FRIDA_PERSISTENT_HOOK", + "AFL_FRIDA_PERSISTENT_RET", + "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET", "AFL_FUZZER_ARGS", // oss-fuzz "AFL_GDB", "AFL_GCC_ALLOWLIST", -- cgit 1.4.1 From 1a2da67ed0505c9ac0aa1048ba3d607f3c1aa639 Mon Sep 17 00:00:00 2001 From: hexcoder- Date: Sun, 30 May 2021 21:21:37 +0200 Subject: add missing include for _exit() --- frida_mode/src/persistent/persistent_x64.c | 1 + 1 file changed, 1 insertion(+) (limited to 'frida_mode/src/persistent/persistent_x64.c') diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c index 4c495d47..4cb960fc 100644 --- a/frida_mode/src/persistent/persistent_x64.c +++ b/frida_mode/src/persistent/persistent_x64.c @@ -1,3 +1,4 @@ +#include #include "frida-gum.h" #include "config.h" -- cgit 1.4.1