aboutsummaryrefslogtreecommitdiff
path: root/frida_mode/src
diff options
context:
space:
mode:
authorWorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>2021-05-27 09:49:34 +0100
committerGitHub <noreply@github.com>2021-05-27 10:49:34 +0200
commit14178141dcdc1a81ea4f4461790ec87f60606985 (patch)
tree386009dcf972d03b9c7d5457baf8ba2ddfd16f53 /frida_mode/src
parent9e0370aa997ec8d0729ea695e74f9529baedd3a0 (diff)
downloadafl++-14178141dcdc1a81ea4f4461790ec87f60606985.tar.gz
Frida (#940)
* Added re2 test * Added libpcap test * Fix validation of setting of ADDR_NO_RANDOMIZE * Added support for printing original and instrumented code Co-authored-by: Your Name <you@example.com>
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);
+
+ }
+
+}
+