aboutsummaryrefslogtreecommitdiff
path: root/frida_mode/src
diff options
context:
space:
mode:
authorWorksButNotTested <62701594+WorksButNotTested@users.noreply.github.com>2021-06-11 09:51:47 +0100
committerGitHub <noreply@github.com>2021-06-11 10:51:47 +0200
commitb9f260452e69834c4eeb3be136474463d8fa6b70 (patch)
tree27ae5ad79c79052d8cf03bc809fb4e1f1ac17fe9 /frida_mode/src
parent8dd30947cb6431b1805e68aa3aeba4ae7aefa4d4 (diff)
downloadafl++-b9f260452e69834c4eeb3be136474463d8fa6b70.tar.gz
Improve tracing support to include real addresses and edge ids and also support logging edges only once (#972)
Co-authored-by: Your Name <you@example.com>
Diffstat (limited to 'frida_mode/src')
-rw-r--r--frida_mode/src/instrument/instrument.c111
1 files changed, 84 insertions, 27 deletions
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index f261e79a..ba82b89f 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -1,4 +1,6 @@
#include <unistd.h>
+#include <sys/shm.h>
+#include <sys/mman.h>
#include "frida-gum.h"
@@ -18,44 +20,50 @@
static gboolean tracing = false;
static gboolean optimize = false;
+static gboolean unique = false;
static GumStalkerTransformer *transformer = NULL;
__thread uint64_t previous_pc = 0;
+static GumAddress previous_rip = 0;
+static u8 * edges_notified = NULL;
+
+static void trace_debug(char *format, ...) {
+
+ va_list ap;
+ char buffer[4096] = {0};
+ int ret;
+ int len;
+
+ va_start(ap, format);
+ ret = vsnprintf(buffer, sizeof(buffer) - 1, format, ap);
+ va_end(ap);
+
+ if (ret < 0) { return; }
+
+ len = strnlen(buffer, sizeof(buffer));
+
+ IGNORED_RETURN(write(STDOUT_FILENO, buffer, len));
+
+}
+
__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
- * the critical path with additional stack adjustments if tracing is not
- * enabled. If tracing is enabled, then we're printing a load of diagnostic
- * information so this overhead is unlikely to be noticeable.
- */
- static char buffer[200];
- int len;
- GumAddress current_pc = GUM_ADDRESS(user_data);
- uint8_t * cursor;
- uint64_t value;
- if (unlikely(tracing)) {
-
- /* Avoid any functions which may cause an allocation since the target app
- * may already be running inside malloc and it isn't designed to be
- * re-entrant on a single thread */
- len = snprintf(buffer, sizeof(buffer),
- "current_pc: 0x%016" G_GINT64_MODIFIER
- "x, previous_pc: 0x%016" G_GINT64_MODIFIER "x\n",
- current_pc, previous_pc);
- IGNORED_RETURN(write(STDOUT_FILENO, buffer, len + 1));
+ GumAddress current_rip = GUM_ADDRESS(user_data);
+ GumAddress current_pc;
+ GumAddress edge;
+ uint8_t * cursor;
+ uint64_t value;
- }
-
- current_pc = (current_pc >> 4) ^ (current_pc << 8);
+ current_pc = (current_rip >> 4) ^ (current_rip << 8);
current_pc &= MAP_SIZE - 1;
- cursor = &__afl_area_ptr[current_pc ^ previous_pc];
+ edge = current_pc ^ previous_pc;
+
+ cursor = &__afl_area_ptr[edge];
value = *cursor;
if (value == 0xff) {
@@ -71,6 +79,23 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
*cursor = value;
previous_pc = current_pc >> 1;
+ if (unlikely(tracing)) {
+
+ if (!unique || edges_notified[edge] == 0) {
+
+ trace_debug("TRACE: edge: %10" G_GINT64_MODIFIER
+ "d, current_rip: 0x%016" G_GINT64_MODIFIER
+ "x, previous_rip: 0x%016" G_GINT64_MODIFIER "x\n",
+ edge, current_rip, previous_rip);
+
+ }
+
+ if (unique) { edges_notified[edge] = 1; }
+
+ previous_rip = current_rip;
+
+ }
+
}
static void instr_basic_block(GumStalkerIterator *iterator,
@@ -164,18 +189,28 @@ void instrument_init(void) {
optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
+ unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
if (!instrument_is_coverage_optimize_supported()) optimize = false;
OKF("Instrumentation - optimize [%c]", optimize ? 'X' : ' ');
OKF("Instrumentation - tracing [%c]", tracing ? 'X' : ' ');
+ OKF("Instrumentation - unique [%c]", unique ? 'X' : ' ');
if (tracing && optimize) {
- FATAL("AFL_FRIDA_INST_OPTIMIZE and AFL_FRIDA_INST_TRACE are incompatible");
+ FATAL("AFL_FRIDA_INST_TRACE requires AFL_FRIDA_INST_NO_OPTIMIZE");
+
+ }
+
+ if (unique && optimize) {
+
+ FATAL("AFL_FRIDA_INST_TRACE_UNIQUE requires AFL_FRIDA_INST_NO_OPTIMIZE");
}
+ if (unique) { tracing = TRUE; }
+
if (__afl_map_size != 0x10000) {
FATAL("Bad map size: 0x%08x", __afl_map_size);
@@ -185,6 +220,28 @@ void instrument_init(void) {
transformer =
gum_stalker_transformer_make_from_callback(instr_basic_block, NULL, NULL);
+ if (unique) {
+
+ int shm_id = shmget(IPC_PRIVATE, MAP_SIZE, IPC_CREAT | IPC_EXCL | 0600);
+ if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); }
+
+ edges_notified = shmat(shm_id, NULL, 0);
+ g_assert(edges_notified != MAP_FAILED);
+
+ /*
+ * Configure the shared memory region to be removed once the process dies.
+ */
+ if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
+
+ FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno);
+
+ }
+
+ /* Clear it, not sure it's necessary, just seems like good practice */
+ memset(edges_notified, '\0', MAP_SIZE);
+
+ }
+
instrument_debug_init();
asan_init();
cmplog_init();