about summary refs log tree commit diff
path: root/frida_mode/src
diff options
context:
space:
mode:
Diffstat (limited to 'frida_mode/src')
-rw-r--r--frida_mode/src/instrument/instrument.c45
-rw-r--r--frida_mode/src/instrument/instrument_debug.c128
-rw-r--r--frida_mode/src/main.c3
-rw-r--r--frida_mode/src/ranges.c67
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);
+
+  }
+
+}
+