diff options
Diffstat (limited to 'frida_mode/src')
-rw-r--r-- | frida_mode/src/instrument/instrument.c | 45 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_debug.c | 128 | ||||
-rw-r--r-- | frida_mode/src/main.c | 3 | ||||
-rw-r--r-- | frida_mode/src/ranges.c | 67 |
4 files changed, 221 insertions, 22 deletions
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 67eadc3f..f21849a6 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -47,7 +47,7 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context, "x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n", current_pc, previous_pc); - IGNORED_RERURN(write(STDOUT_FILENO, buffer, len + 1)); + IGNORED_RETURN(write(STDOUT_FILENO, buffer, len + 1)); } @@ -79,17 +79,48 @@ static void instr_basic_block(GumStalkerIterator *iterator, const cs_insn *instr; gboolean begin = TRUE; + gboolean excluded; + 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) { + /* + * Until we reach AFL_ENTRYPOINT (assumed to be main if not specified) or + * AFL_FRIDA_PERSISTENT_ADDR (if specified), we don't mark our ranges + * excluded as we wish to remain inside stalker at all times so that we can + * instrument our entry point and persistent loop (if present). This allows + * the user to exclude ranges which would be traversed between main and the + * AFL_ENTRYPOINT, but which they don't want included in their coverage + * information when fuzzing. + * + * Since we have no means to discard the instrumented copies of blocks + * (setting the trust threshold simply causes a new copy to be made on each + * execution), we instead ensure that we honour the additional + * instrumentation requested (e.g. coverage, asan and complog) when a block + * is compiled no matter where we are during initialization. We will end up + * re-using these blocks if the code under test calls a block which is also + * used during initialization. + * + * Coverage data generated during initialization isn't a problem since the + * map is zeroed each time the target is forked or each time the persistent + * loop is run. + * + * Lastly, we don't enable pre-fetching back to the parent until we reach + * our AFL_ENTRYPOINT, since it is not until then that we start the + * fork-server and thus start executing in the child. + */ + excluded = range_is_excluded(GSIZE_TO_POINTER(instr->address)); + if (unlikely(begin)) { + + instrument_debug_start(instr->address, output); prefetch_write(GSIZE_TO_POINTER(instr->address)); - if (!range_is_excluded(GSIZE_TO_POINTER(instr->address))) { - if (optimize) { + if (likely(!excluded)) { + + if (likely(optimize)) { instrument_coverage_optimize(instr, output); @@ -106,7 +137,9 @@ static void instr_basic_block(GumStalkerIterator *iterator, } - if (!range_is_excluded(GSIZE_TO_POINTER(instr->address))) { + instrument_debug_instruction(instr->address, instr->size); + + if (likely(!excluded)) { asan_instrument(instr, iterator); cmplog_instrument(instr, iterator); @@ -117,6 +150,8 @@ static void instr_basic_block(GumStalkerIterator *iterator, } + instrument_debug_end(output); + } void instrument_init(void) { diff --git a/frida_mode/src/instrument/instrument_debug.c b/frida_mode/src/instrument/instrument_debug.c new file mode 100644 index 00000000..3a554ad0 --- /dev/null +++ b/frida_mode/src/instrument/instrument_debug.c @@ -0,0 +1,128 @@ +#include <stdarg.h> +#include <stdio.h> +#include <unistd.h> + +#include "frida-gum.h" + +#include "util.h" + +#ifdef FRIDA_DEBUG + +static gpointer instrument_gen_start = NULL; + +static void instrument_debug(char *format, ...) { + + va_list ap; + char buffer[4096] = {0}; + + va_start(ap, format); + + vsnprintf(buffer, sizeof(buffer) - 1, format, ap); + va_end(ap); + + IGNORED_RETURN(write(STDOUT_FILENO, buffer, sizeof(buffer))); + +} + +static void instrument_disasm(guint8 *code, guint size) { + + csh capstone; + cs_err err; + cs_insn *insn; + size_t count, i; + + err = cs_open(GUM_DEFAULT_CS_ARCH, + GUM_DEFAULT_CS_MODE | GUM_DEFAULT_CS_ENDIAN, &capstone); + g_assert(err == CS_ERR_OK); + + count = cs_disasm(capstone, code, size, GPOINTER_TO_SIZE(code), 0, &insn); + g_assert(insn != NULL); + + for (i = 0; i != count; i++) { + + instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t%s %s\n", insn[i].address, + insn[i].mnemonic, insn[i].op_str); + + } + + cs_free(insn, count); + + cs_close(&capstone); + +} + +static gpointer instrument_cur(GumStalkerOutput *output) { + + #if defined(__i386__) || defined(__x86_64__) + return gum_x86_writer_cur(output->writer.x86); + #elif defined(__aarch64__) + return gum_arm64_writer_cur(output->writer.arm64); + #elif defined(__arm__) + return gum_arm_writer_cur(output->writer.arm); + #else + #error "Unsupported architecture" + #endif + +} + +void instrument_debug_start(uint64_t address, GumStalkerOutput *output) { + + GumDebugSymbolDetails details; + + instrument_gen_start = instrument_cur(output); + + if (gum_symbol_details_from_address(GSIZE_TO_POINTER(address), &details)) { + + instrument_debug("\n\n***\n\nCreating block for 0x%" G_GINT64_MODIFIER + "x (%s!%s):\n", + address, details.module_name, details.symbol_name); + + } else { + + instrument_debug( + "\n\n***\n\nCreating block for 0x%" G_GINT64_MODIFIER "x:\n", address); + + } + +} + +void instrument_debug_instruction(uint64_t address, uint16_t size) { + + uint8_t *start = (uint8_t *)GSIZE_TO_POINTER(address); + instrument_disasm(start, size); + +} + +void instrument_debug_end(GumStalkerOutput *output) { + + gpointer instrument_gen_end = instrument_cur(output); + uint16_t size = GPOINTER_TO_SIZE(instrument_gen_end) - + GPOINTER_TO_SIZE(instrument_gen_start); + + instrument_debug("\nGenerated block %p\n", instrument_gen_start); + instrument_disasm(instrument_gen_start, size); + +} + +#else +void instrument_debug_start(void *address) { + + UNUSED_PARAMETER(address); + +} + +void instrument_debug_instruction(uint64_t address, uint16_t size) { + + UNUSED_PARAMETER(address); + UNUSED_PARAMETER(size); + +} + +void instrument_debug_end(GumStalkerOutput *output) { + + UNUSED_PARAMETER(output); + +} + +#endif + diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index 21073cbe..e8015905 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -1,3 +1,4 @@ +#include <errno.h> #include <unistd.h> #include <sys/types.h> @@ -58,10 +59,10 @@ static void on_main_os(int argc, char **argv, char **envp) { 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); + if (persona == -1) { WARNF("Failed to set ADDR_NO_RANDOMIZE: %d", errno); } if ((persona & ADDR_NO_RANDOMIZE) == 0) { execvpe(argv[0], argv, envp); } GumInterceptor *interceptor = gum_interceptor_obtain(); diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index e3f09f9e..aa140708 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -480,15 +480,40 @@ static GArray *merge_ranges(GArray *a) { } +static gboolean exclude_ranges_callback(const GumRangeDetails *details, + gpointer user_data) { + + UNUSED_PARAMETER(user_data); + gchar * name; + gboolean found; + GumStalker *stalker; + if (details->file == NULL) { return TRUE; } + name = g_path_get_basename(details->file->path); + + found = (g_strcmp0(name, "afl-frida-trace.so") == 0); + g_free(name); + if (!found) { return TRUE; } + + stalker = stalker_get(); + gum_stalker_exclude(stalker, details->range); + + return FALSE; + +} + +static void ranges_exclude_self(void) { + + gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, exclude_ranges_callback, NULL); + +} + void ranges_init(void) { - GumMemoryRange ri; - GArray * step1; - GArray * step2; - GArray * step3; - GArray * step4; - GumMemoryRange *r; - GumStalker * stalker; + GumMemoryRange ri; + GArray * step1; + GArray * step2; + GArray * step3; + GArray * step4; if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { @@ -535,20 +560,14 @@ void ranges_init(void) { ranges = merge_ranges(step4); print_ranges("final", ranges); - stalker = stalker_get(); - - for (guint i = 0; i < ranges->len; i++) { - - r = &g_array_index(ranges, GumMemoryRange, i); - gum_stalker_exclude(stalker, r); - - } - g_array_free(step4, TRUE); g_array_free(step3, TRUE); g_array_free(step2, TRUE); g_array_free(step1, TRUE); + /* *NEVER* stalk the stalker, only bad things will ever come of this! */ + ranges_exclude_self(); + } gboolean range_is_excluded(gpointer address) { @@ -572,3 +591,19 @@ gboolean range_is_excluded(gpointer address) { } +void ranges_exclude() { + + GumMemoryRange *r; + GumStalker * stalker = stalker_get(); + + OKF("Excluding ranges"); + + for (guint i = 0; i < ranges->len; i++) { + + r = &g_array_index(ranges, GumMemoryRange, i); + gum_stalker_exclude(stalker, r); + + } + +} + |