aboutsummaryrefslogtreecommitdiff
path: root/frida_mode/src
diff options
context:
space:
mode:
authorvan Hauser <vh@thc.org>2021-07-19 10:31:56 +0200
committerGitHub <noreply@github.com>2021-07-19 10:31:56 +0200
commit939729e504ea269dd6d7252c363b160e01d1be1a (patch)
tree808710139e53d9958cdb660d61680d48e64e8c3a /frida_mode/src
parent458eb0813a6f7d63eed97f18696bca8274533123 (diff)
parent18fd97fc5ffc5ad94e735cfbfa0d500463dcb585 (diff)
downloadafl++-939729e504ea269dd6d7252c363b160e01d1be1a.tar.gz
Merge pull request #1023 from AFLplusplus/dev
push to stable
Diffstat (limited to 'frida_mode/src')
-rw-r--r--frida_mode/src/ctx/ctx_arm32.c2
-rw-r--r--frida_mode/src/entry.c19
-rw-r--r--frida_mode/src/instrument/instrument.c99
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c16
-rw-r--r--frida_mode/src/instrument/instrument_x64.c36
-rw-r--r--frida_mode/src/instrument/instrument_x86.c22
-rw-r--r--frida_mode/src/js/api.js14
-rw-r--r--frida_mode/src/js/js.c62
-rw-r--r--frida_mode/src/js/js_api.c97
-rw-r--r--frida_mode/src/main.c2
-rw-r--r--frida_mode/src/persistent/persistent.c20
-rw-r--r--frida_mode/src/persistent/persistent_arm32.c4
-rw-r--r--frida_mode/src/persistent/persistent_arm64.c6
-rw-r--r--frida_mode/src/persistent/persistent_x64.c6
-rw-r--r--frida_mode/src/persistent/persistent_x86.c6
-rw-r--r--frida_mode/src/ranges.c89
-rw-r--r--frida_mode/src/stalker.c8
-rw-r--r--frida_mode/src/stats/stats.c6
-rw-r--r--frida_mode/src/stats/stats_x64.c18
19 files changed, 407 insertions, 125 deletions
diff --git a/frida_mode/src/ctx/ctx_arm32.c b/frida_mode/src/ctx/ctx_arm32.c
index a354c117..9fc70fb4 100644
--- a/frida_mode/src/ctx/ctx_arm32.c
+++ b/frida_mode/src/ctx/ctx_arm32.c
@@ -6,7 +6,7 @@
#if defined(__arm__)
-gsize ctx_read_reg(GumIA32CpuContext *ctx, x86_reg reg) {
+gsize ctx_read_reg(GumArmCpuContext *ctx, arm_reg reg) {
FATAL("ctx_read_reg unimplemented for this architecture");
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c
index e95b923b..a0ffd028 100644
--- a/frida_mode/src/entry.c
+++ b/frida_mode/src/entry.c
@@ -4,12 +4,16 @@
#include "entry.h"
#include "instrument.h"
+#include "persistent.h"
+#include "ranges.h"
#include "stalker.h"
+#include "stats.h"
#include "util.h"
extern void __afl_manual_init();
-guint64 entry_point = 0;
+guint64 entry_point = 0;
+gboolean entry_reached = FALSE;
static void entry_launch(void) {
@@ -17,7 +21,8 @@ static void entry_launch(void) {
__afl_manual_init();
/* Child here */
- instrument_previous_pc = 0;
+ instrument_on_fork();
+ stats_on_fork();
}
@@ -50,6 +55,16 @@ static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) {
void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
UNUSED_PARAMETER(output);
+ OKF("AFL_ENTRYPOINT reached");
+
+ if (persistent_start == 0) {
+
+ entry_reached = TRUE;
+ ranges_exclude();
+ stalker_trust();
+
+ }
+
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 2a217d96..67aafa5a 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -1,11 +1,13 @@
#include <unistd.h>
#include <sys/shm.h>
#include <sys/mman.h>
+#include <sys/syscall.h>
#include "frida-gumjs.h"
#include "config.h"
#include "debug.h"
+#include "hash.h"
#include "asan.h"
#include "entry.h"
@@ -22,10 +24,15 @@
gboolean instrument_tracing = false;
gboolean instrument_optimize = false;
gboolean instrument_unique = false;
+guint64 instrument_hash_zero = 0;
+guint64 instrument_hash_seed = 0;
+
+gboolean instrument_use_fixed_seed = FALSE;
+guint64 instrument_fixed_seed = 0;
static GumStalkerTransformer *transformer = NULL;
-__thread uint64_t instrument_previous_pc = 0;
+__thread guint64 instrument_previous_pc = 0;
static GumAddress previous_rip = 0;
static u8 * edges_notified = NULL;
@@ -49,21 +56,18 @@ static void trace_debug(char *format, ...) {
}
-__attribute__((hot)) static void on_basic_block(GumCpuContext *context,
- gpointer user_data) {
+guint64 instrument_get_offset_hash(GumAddress current_rip) {
- UNUSED_PARAMETER(context);
+ guint64 area_offset = hash64((unsigned char *)&current_rip,
+ sizeof(GumAddress), instrument_hash_seed);
+ return area_offset &= MAP_SIZE - 1;
- GumAddress current_rip = GUM_ADDRESS(user_data);
- GumAddress current_pc;
- GumAddress edge;
- uint8_t * cursor;
- uint64_t value;
+}
- current_pc = (current_rip >> 4) ^ (current_rip << 8);
- current_pc &= MAP_SIZE - 1;
+__attribute__((hot)) static void instrument_increment_map(GumAddress edge) {
- edge = current_pc ^ instrument_previous_pc;
+ uint8_t *cursor;
+ uint64_t value;
cursor = &__afl_area_ptr[edge];
value = *cursor;
@@ -79,7 +83,21 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
}
*cursor = value;
- instrument_previous_pc = current_pc >> 1;
+
+}
+
+__attribute__((hot)) static void on_basic_block(GumCpuContext *context,
+ gpointer user_data) {
+
+ UNUSED_PARAMETER(context);
+
+ GumAddress current_rip = GUM_ADDRESS(user_data);
+ guint64 current_pc = instrument_get_offset_hash(current_rip);
+ guint64 edge;
+
+ edge = current_pc ^ instrument_previous_pc;
+
+ instrument_increment_map(edge);
if (unlikely(instrument_tracing)) {
@@ -98,6 +116,9 @@ __attribute__((hot)) static void on_basic_block(GumCpuContext *context,
}
+ instrument_previous_pc =
+ ((current_pc & (MAP_SIZE - 1) >> 1)) | ((current_pc & 0x1) << 15);
+
}
static void instrument_basic_block(GumStalkerIterator *iterator,
@@ -149,7 +170,13 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
if (unlikely(begin)) {
- prefetch_write(GSIZE_TO_POINTER(instr->address));
+ instrument_debug_start(instr->address, output);
+
+ if (likely(entry_reached)) {
+
+ prefetch_write(GSIZE_TO_POINTER(instr->address));
+
+ }
if (likely(!excluded)) {
@@ -197,6 +224,8 @@ void instrument_config(void) {
instrument_optimize = (getenv("AFL_FRIDA_INST_NO_OPTIMIZE") == NULL);
instrument_tracing = (getenv("AFL_FRIDA_INST_TRACE") != NULL);
instrument_unique = (getenv("AFL_FRIDA_INST_TRACE_UNIQUE") != NULL);
+ instrument_use_fixed_seed = (getenv("AFL_FRIDA_INST_SEED") != NULL);
+ instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED");
instrument_debug_config();
asan_config();
@@ -211,16 +240,20 @@ void instrument_init(void) {
OKF("Instrumentation - optimize [%c]", instrument_optimize ? 'X' : ' ');
OKF("Instrumentation - tracing [%c]", instrument_tracing ? 'X' : ' ');
OKF("Instrumentation - unique [%c]", instrument_unique ? 'X' : ' ');
+ OKF("Instrumentation - fixed seed [%c] [0x%016" G_GINT64_MODIFIER "x]",
+ instrument_use_fixed_seed ? 'X' : ' ', instrument_fixed_seed);
if (instrument_tracing && instrument_optimize) {
- FATAL("AFL_FRIDA_INST_TRACE requires AFL_FRIDA_INST_NO_OPTIMIZE");
+ WARNF("AFL_FRIDA_INST_TRACE implies AFL_FRIDA_INST_NO_OPTIMIZE");
+ instrument_optimize = FALSE;
}
if (instrument_unique && instrument_optimize) {
- FATAL("AFL_FRIDA_INST_TRACE_UNIQUE requires AFL_FRIDA_INST_NO_OPTIMIZE");
+ WARNF("AFL_FRIDA_INST_TRACE_UNIQUE implies AFL_FRIDA_INST_NO_OPTIMIZE");
+ instrument_optimize = FALSE;
}
@@ -244,7 +277,8 @@ void instrument_init(void) {
g_assert(edges_notified != MAP_FAILED);
/*
- * Configure the shared memory region to be removed once the process dies.
+ * Configure the shared memory region to be removed once the process
+ * dies.
*/
if (shmctl(shm_id, IPC_RMID, NULL) < 0) {
@@ -257,6 +291,31 @@ void instrument_init(void) {
}
+ if (instrument_use_fixed_seed) {
+
+ /*
+ * This configuration option may be useful for diagnostics or
+ * debugging.
+ */
+ instrument_hash_seed = instrument_fixed_seed;
+
+ } else {
+
+ /*
+ * By using a different seed value for the hash, we can make different
+ * instances have edge collisions in different places when carrying out
+ * parallel fuzzing. The seed itself, doesn't have to be random, it
+ * just needs to be different for each instance.
+ */
+ instrument_hash_seed = g_get_monotonic_time() ^
+ (((guint64)getpid()) << 32) ^ syscall(SYS_gettid);
+
+ }
+
+ OKF("Instrumentation - seed [0x%016" G_GINT64_MODIFIER "x]",
+ instrument_hash_seed);
+ instrument_hash_zero = instrument_get_offset_hash(0);
+
instrument_debug_init();
asan_init();
cmplog_init();
@@ -270,3 +329,9 @@ GumStalkerTransformer *instrument_get_transformer(void) {
}
+void instrument_on_fork() {
+
+ instrument_previous_pc = instrument_hash_zero;
+
+}
+
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index 17f97c97..cf37e048 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -12,15 +12,15 @@ static GumAddress current_log_impl = GUM_ADDRESS(0);
static const guint8 afl_log_code[] = {
// __afl_area_ptr[current_pc ^ previous_pc]++;
- // previous_pc = current_pc >> 1;
+ // previous_pc = current_pc ROR 1;
0xE1, 0x0B, 0xBF, 0xA9, // stp x1, x2, [sp, -0x10]!
0xE3, 0x13, 0xBF, 0xA9, // stp x3, x4, [sp, -0x10]!
// x0 = current_pc
- 0xe1, 0x01, 0x00, 0x58, // ldr x1, #0x3c, =&__afl_area_ptr
+ 0x21, 0x02, 0x00, 0x58, // ldr x1, #0x44, =&__afl_area_ptr
0x21, 0x00, 0x40, 0xf9, // ldr x1, [x1] (=__afl_area_ptr)
- 0xe2, 0x01, 0x00, 0x58, // ldr x2, #0x3c, =&previous_pc
+ 0x22, 0x02, 0x00, 0x58, // ldr x2, #0x44, =&previous_pc
0x42, 0x00, 0x40, 0xf9, // ldr x2, [x2] (=previous_pc)
// __afl_area_ptr[current_pc ^ previous_pc]++;
@@ -30,8 +30,11 @@ static const guint8 afl_log_code[] = {
0x63, 0x00, 0x1f, 0x9a, // adc x3, x3, xzr
0x23, 0x68, 0x22, 0xf8, // str x3, [x1, x2]
- // previous_pc = current_pc >> 1;
- 0xe0, 0x07, 0x40, 0x8b, // add x0, xzr, x0, LSR #1
+ // previous_pc = current_pc ROR 1;
+ 0xe4, 0x07, 0x40, 0x8b, // add x4, xzr, x0, LSR #1
+ 0xe0, 0xff, 0x00, 0x8b, // add x0, xzr, x0, LSL #63
+ 0x80, 0xc0, 0x40, 0x8b, // add x0, x4, x0, LSR #48
+
0xe2, 0x00, 0x00, 0x58, // ldr x2, #0x1c, =&previous_pc
0x40, 0x00, 0x00, 0xf9, // str x0, [x2]
@@ -54,8 +57,7 @@ void instrument_coverage_optimize(const cs_insn * instr,
GumStalkerOutput *output) {
guint64 current_pc = instr->address;
- guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
- area_offset &= MAP_SIZE - 1;
+ guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
GumArm64Writer *cw = output->writer.arm64;
if (current_log_impl == 0 ||
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index a38b5b14..fec8afbb 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -10,23 +10,21 @@ static GumAddress current_log_impl = GUM_ADDRESS(0);
static const guint8 afl_log_code[] = {
- // 0xcc,
-
0x9c, /* pushfq */
0x51, /* push rcx */
0x52, /* push rdx */
- 0x48, 0x8b, 0x0d, 0x28,
+ 0x48, 0x8b, 0x0d, 0x26,
0x00, 0x00, 0x00, /* mov rcx, sym.&previous_pc */
0x48, 0x8b, 0x11, /* mov rdx, qword [rcx] */
0x48, 0x31, 0xfa, /* xor rdx, rdi */
- 0x48, 0x03, 0x15, 0x13,
+ 0x48, 0x03, 0x15, 0x11,
0x00, 0x00, 0x00, /* add rdx, sym._afl_area_ptr_ptr */
0x80, 0x02, 0x01, /* add byte ptr [rdx], 1 */
0x80, 0x12, 0x00, /* adc byte ptr [rdx], 0 */
- 0x48, 0xd1, 0xef, /* shr rdi, 1 */
+ 0x66, 0xd1, 0xcf, /* ror di, 1 */
0x48, 0x89, 0x39, /* mov qword [rcx], rdi */
0x5a, /* pop rdx */
@@ -34,7 +32,8 @@ static const guint8 afl_log_code[] = {
0x9d, /* popfq */
0xc3, /* ret */
- 0x90, 0x90, 0x90 /* nop pad */
+
+ 0x90
/* Read-only data goes here: */
/* uint8_t* __afl_area_ptr */
@@ -48,12 +47,11 @@ gboolean instrument_is_coverage_optimize_supported(void) {
}
-void instrument_coverage_optimize(const cs_insn * instr,
- GumStalkerOutput *output) {
+static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90};
- guint64 current_pc = instr->address;
- guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
- area_offset &= MAP_SIZE - 1;
+static void instrument_coverate_write_function(GumStalkerOutput *output) {
+
+ guint64 misalign = 0;
GumX86Writer *cw = output->writer.x86;
if (current_log_impl == 0 ||
@@ -65,6 +63,13 @@ void instrument_coverage_optimize(const cs_insn * instr,
gum_x86_writer_put_jmp_near_label(cw, after_log_impl);
+ misalign = (cw->pc & 0x7);
+ if (misalign != 0) {
+
+ gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign);
+
+ }
+
current_log_impl = cw->pc;
gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code));
@@ -78,6 +83,15 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
+}
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output) {
+
+ GumX86Writer *cw = output->writer.x86;
+ guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
+ instrument_coverate_write_function(output);
+
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_RDI);
diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c
index 3c3dc272..7bf48f96 100644
--- a/frida_mode/src/instrument/instrument_x86.c
+++ b/frida_mode/src/instrument/instrument_x86.c
@@ -30,7 +30,8 @@ static void instrument_coverage_function(GumX86Writer *cw) {
uint8_t adc_byte_ptr_edx_0[] = {0x80, 0x12, 0x00};
gum_x86_writer_put_bytes(cw, adc_byte_ptr_edx_0, sizeof(adc_byte_ptr_edx_0));
- gum_x86_writer_put_shr_reg_u8(cw, GUM_REG_EDI, 1);
+ uint8_t ror_di_1[] = {0x66, 0xd1, 0xcf};
+ gum_x86_writer_put_bytes(cw, ror_di_1, sizeof(ror_di_1));
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_ECX, GUM_REG_EDI);
gum_x86_writer_put_pop_reg(cw, GUM_REG_EDX);
@@ -46,15 +47,8 @@ gboolean instrument_is_coverage_optimize_supported(void) {
}
-void instrument_coverage_optimize(const cs_insn * instr,
- GumStalkerOutput *output) {
-
- UNUSED_PARAMETER(instr);
- UNUSED_PARAMETER(output);
+static void instrument_coverate_write_function(GumStalkerOutput *output) {
- guint64 current_pc = instr->address;
- guint64 area_offset = (current_pc >> 4) ^ (current_pc << 8);
- area_offset &= MAP_SIZE - 1;
GumX86Writer *cw = output->writer.x86;
if (current_log_impl == 0 ||
@@ -73,7 +67,15 @@ void instrument_coverage_optimize(const cs_insn * instr,
}
- // gum_x86_writer_put_breakpoint(cw);
+}
+
+void instrument_coverage_optimize(const cs_insn * instr,
+ GumStalkerOutput *output) {
+
+ GumX86Writer *cw = output->writer.x86;
+ guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address));
+ instrument_coverate_write_function(output);
+
gum_x86_writer_put_push_reg(cw, GUM_REG_EDI);
gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDI, area_offset);
gum_x86_writer_put_call_address(cw, current_log_impl);
diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js
index 4cb04704..b8f2d39a 100644
--- a/frida_mode/src/js/api.js
+++ b/frida_mode/src/js/api.js
@@ -100,6 +100,12 @@ class Afl {
Afl.jsApiSetInstrumentTrace();
}
/**
+ * See `AFL_FRIDA_INST_JIT`.
+ */
+ static setInstrumentJit() {
+ Afl.jsApiSetInstrumentJit();
+ }
+ /**
* See `AFL_INST_LIBS`.
*/
static setInstrumentLibraries() {
@@ -111,6 +117,12 @@ class Afl {
static setInstrumentNoOptimize() {
Afl.jsApiSetInstrumentNoOptimize();
}
+ /*
+ * See `AFL_FRIDA_INST_SEED`
+ */
+ static setInstrumentSeed(seed) {
+ Afl.jsApiSetInstrumentSeed(seed);
+ }
/**
* See `AFL_FRIDA_INST_TRACE_UNIQUE`.
*/
@@ -222,8 +234,10 @@ Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]);
Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []);
Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]);
Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]);
+Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []);
Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []);
Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []);
+Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]);
Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []);
Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []);
Afl.jsApiSetPersistentAddress = Afl.jsApiGetFunction("js_api_set_persistent_address", "void", ["pointer"]);
diff --git a/frida_mode/src/js/js.c b/frida_mode/src/js/js.c
index ed378d2c..e3cd4933 100644
--- a/frida_mode/src/js/js.c
+++ b/frida_mode/src/js/js.c
@@ -9,12 +9,15 @@ static char * js_script = NULL;
gboolean js_done = FALSE;
js_api_stalker_callback_t js_user_callback = NULL;
-static gchar * filename = "afl.js";
-static gchar * contents;
-static GumScriptBackend *backend;
-static GCancellable * cancellable = NULL;
-static GError * error = NULL;
-static GumScript * script;
+static gchar * filename = "afl.js";
+static gchar * contents;
+static GumScriptBackend * backend;
+static GCancellable * cancellable = NULL;
+static GError * error = NULL;
+static GumScript * script;
+static GumScriptScheduler *scheduler;
+static GMainContext * context;
+static GMainLoop * main_loop;
static void js_msg(GumScript *script, const gchar *message, GBytes *data,
gpointer user_data) {
@@ -80,31 +83,48 @@ static void js_print_script(gchar *source) {
}
-void js_start(void) {
+static void load_cb(GObject *source_object, GAsyncResult *result,
+ gpointer user_data) {
- GMainContext *context;
+ UNUSED_PARAMETER(source_object);
+ UNUSED_PARAMETER(user_data);
+ gum_script_load_finish(script, result);
+ if (error != NULL) { FATAL("Failed to load script - %s", error->message); }
- gchar *source = js_get_script();
- if (source == NULL) { return; }
- js_print_script(source);
+}
- backend = gum_script_backend_obtain_qjs();
+static void create_cb(GObject *source_object, GAsyncResult *result,
+ gpointer user_data) {
- script = gum_script_backend_create_sync(backend, "example", source,
- cancellable, &error);
+ UNUSED_PARAMETER(source_object);
+ UNUSED_PARAMETER(user_data);
+ script = gum_script_backend_create_finish(backend, result, &error);
+ if (error != NULL) { FATAL("Failed to create script: %s", error->message); }
- if (error != NULL) {
+ gum_script_set_message_handler(script, js_msg, NULL, NULL);
- g_printerr("%s\n", error->message);
- FATAL("Error processing script");
+ gum_script_load(script, cancellable, load_cb, NULL);
- }
+}
- gum_script_set_message_handler(script, js_msg, NULL, NULL);
+void js_start(void) {
+
+ gchar *source = js_get_script();
+ if (source == NULL) { return; }
+ js_print_script(source);
+
+ scheduler = gum_script_backend_get_scheduler();
+ gum_script_scheduler_disable_background_thread(scheduler);
+
+ backend = gum_script_backend_obtain_qjs();
+
+ context = gum_script_scheduler_get_js_context(scheduler);
+ main_loop = g_main_loop_new(context, true);
+ g_main_context_push_thread_default(context);
- gum_script_load_sync(script, cancellable);
+ gum_script_backend_create(backend, "example", source, cancellable, create_cb,
+ &error);
- context = g_main_context_get_thread_default();
while (g_main_context_pending(context))
g_main_context_iteration(context, FALSE);
diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c
index 91dccab2..930a6dc0 100644
--- a/frida_mode/src/js/js_api.c
+++ b/frida_mode/src/js/js_api.c
@@ -9,142 +9,191 @@
#include "ranges.h"
#include "stats.h"
#include "util.h"
-
-void js_api_done() {
+__attribute__((visibility("default"))) void js_api_done() {
js_done = TRUE;
}
-void js_api_error(char *msg) {
+__attribute__((visibility("default"))) void js_api_error(char *msg) {
FATAL("%s", msg);
}
-void js_api_set_entrypoint(void *address) {
+__attribute__((visibility("default"))) void js_api_set_entrypoint(
+ void *address) {
+
+ if (address == NULL) {
+
+ js_api_error("js_api_set_entrypoint called with NULL");
+
+ }
entry_point = GPOINTER_TO_SIZE(address);
}
-void js_api_set_persistent_address(void *address) {
+__attribute__((visibility("default"))) void js_api_set_persistent_address(
+ void *address) {
+
+ if (address == NULL) {
+
+ js_api_error("js_api_set_persistent_address called with NULL");
+
+ }
persistent_start = GPOINTER_TO_SIZE(address);
}
-void js_api_set_persistent_return(void *address) {
+__attribute__((visibility("default"))) void js_api_set_persistent_return(
+ void *address) {
+
+ if (address == NULL) {
+
+ js_api_error("js_api_set_persistent_return called with NULL");
+
+ }
persistent_ret = GPOINTER_TO_SIZE(address);
}
-void js_api_set_persistent_count(uint64_t count) {
+__attribute__((visibility("default"))) void js_api_set_persistent_count(
+ uint64_t count) {
persistent_count = count;
}
-void js_api_set_persistent_debug() {
+__attribute__((visibility("default"))) void js_api_set_persistent_debug() {
persistent_debug = TRUE;
}
-void js_api_set_debug_maps() {
+__attribute__((visibility("default"))) void js_api_set_debug_maps() {
ranges_debug_maps = TRUE;
}
-void js_api_add_include_range(void *address, gsize size) {
+__attribute__((visibility("default"))) void js_api_add_include_range(
+ void *address, gsize size) {
GumMemoryRange range = {.base_address = GUM_ADDRESS(address), .size = size};
ranges_add_include(&range);
}
-void js_api_add_exclude_range(void *address, gsize size) {
+__attribute__((visibility("default"))) void js_api_add_exclude_range(
+ void *address, gsize size) {
GumMemoryRange range = {.base_address = GUM_ADDRESS(address), .size = size};
ranges_add_exclude(&range);
}
-void js_api_set_instrument_libraries() {
+__attribute__((visibility("default"))) void js_api_set_instrument_jit() {
+
+ ranges_inst_jit = TRUE;
+
+}
+
+__attribute__((visibility("default"))) void js_api_set_instrument_libraries() {
ranges_inst_libs = TRUE;
}
-void js_api_set_instrument_debug_file(char *path) {
+__attribute__((visibility("default"))) void js_api_set_instrument_debug_file(
+ char *path) {
instrument_debug_filename = g_strdup(path);
}
-void js_api_set_prefetch_disable(void) {
+__attribute__((visibility("default"))) void js_api_set_prefetch_disable(void) {
prefetch_enable = FALSE;
}
-void js_api_set_instrument_no_optimize(void) {
+__attribute__((visibility("default"))) void js_api_set_instrument_no_optimize(
+ void) {
instrument_optimize = FALSE;
}
-void js_api_set_instrument_trace(void) {
+__attribute__((visibility("default"))) void js_api_set_instrument_seed(
+ guint64 seed) {
+
+ instrument_use_fixed_seed = TRUE;
+ instrument_fixed_seed = seed;
+
+}
+
+__attribute__((visibility("default"))) void js_api_set_instrument_trace(void) {
instrument_tracing = TRUE;
}
-void js_api_set_instrument_trace_unique(void) {
+__attribute__((visibility("default"))) void js_api_set_instrument_trace_unique(
+ void) {
instrument_unique = TRUE;
}
-void js_api_set_stdout(char *file) {
+__attribute__((visibility("default"))) void js_api_set_stdout(char *file) {
output_stdout = g_strdup(file);
}
-void js_api_set_stderr(char *file) {
+__attribute__((visibility("default"))) void js_api_set_stderr(char *file) {
output_stderr = g_strdup(file);
}
-void js_api_set_stats_file(char *file) {
+__attribute__((visibility("default"))) void js_api_set_stats_file(char *file) {
stats_filename = g_strdup(file);
}
-void js_api_set_stats_interval(uint64_t interval) {
+__attribute__((visibility("default"))) void js_api_set_stats_interval(
+ uint64_t interval) {
stats_interval = interval;
}
-void js_api_set_stats_transitions() {
+__attribute__((visibility("default"))) void js_api_set_stats_transitions() {
stats_transitions = TRUE;
}
-void js_api_set_persistent_hook(void *address) {
+__attribute__((visibility("default"))) void js_api_set_persistent_hook(
+ void *address) {
+
+ if (address == NULL) {
+
+ js_api_error("js_api_set_persistent_hook called with NULL");
+
+ }
persistent_hook = address;
}
-void js_api_set_stalker_callback(const js_api_stalker_callback_t callback) {
+__attribute__((visibility("default"))) void js_api_set_stalker_callback(
+ const js_api_stalker_callback_t callback) {
js_user_callback = callback;
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index 85b0bbf3..91687046 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -163,7 +163,7 @@ static void afl_print_env(void) {
}
-void afl_frida_start(void) {
+__attribute__((visibility("default"))) void afl_frida_start(void) {
afl_print_cmdline();
afl_print_env();
diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c
index bcc59ea7..639a694e 100644
--- a/frida_mode/src/persistent/persistent.c
+++ b/frida_mode/src/persistent/persistent.c
@@ -5,7 +5,10 @@
#include "config.h"
#include "debug.h"
+#include "entry.h"
#include "persistent.h"
+#include "ranges.h"
+#include "stalker.h"
#include "util.h"
int __afl_sharedmem_fuzzing = 0;
@@ -83,3 +86,20 @@ void persistent_init(void) {
}
+void persistent_prologue(GumStalkerOutput *output) {
+
+ OKF("AFL_FRIDA_PERSISTENT_ADDR reached");
+ entry_reached = TRUE;
+ ranges_exclude();
+ stalker_trust();
+ persistent_prologue_arch(output);
+
+}
+
+void persistent_epilogue(GumStalkerOutput *output) {
+
+ OKF("AFL_FRIDA_PERSISTENT_RET reached");
+ persistent_epilogue_arch(output);
+
+}
+
diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c
index f12f1af8..769f1505 100644
--- a/frida_mode/src/persistent/persistent_arm32.c
+++ b/frida_mode/src/persistent/persistent_arm32.c
@@ -61,14 +61,14 @@ gboolean persistent_is_supported(void) {
}
-void persistent_prologue(GumStalkerOutput *output) {
+void persistent_prologue_arch(GumStalkerOutput *output) {
UNUSED_PARAMETER(output);
FATAL("Persistent mode not supported on this architecture");
}
-void persistent_epilogue(GumStalkerOutput *output) {
+void persistent_epilogue_arch(GumStalkerOutput *output) {
UNUSED_PARAMETER(output);
FATAL("Persistent mode not supported on this architecture");
diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c
index 003f058a..3cd61cd5 100644
--- a/frida_mode/src/persistent/persistent_arm64.c
+++ b/frida_mode/src/persistent/persistent_arm64.c
@@ -237,7 +237,7 @@ static void instrument_exit(GumArm64Writer *cw) {
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
- instrument_previous_pc = 0;
+ instrument_previous_pc = instrument_hash_zero;
return ret;
}
@@ -299,7 +299,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
}
-void persistent_prologue(GumStalkerOutput *output) {
+void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE REGS
@@ -366,7 +366,7 @@ void persistent_prologue(GumStalkerOutput *output) {
}
-void persistent_epilogue(GumStalkerOutput *output) {
+void persistent_epilogue_arch(GumStalkerOutput *output) {
GumArm64Writer *cw = output->writer.arm64;
diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c
index b2186db1..c0bd9a09 100644
--- a/frida_mode/src/persistent/persistent_x64.c
+++ b/frida_mode/src/persistent/persistent_x64.c
@@ -174,7 +174,7 @@ static void instrument_exit(GumX86Writer *cw) {
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
- instrument_previous_pc = 0;
+ instrument_previous_pc = instrument_hash_zero;
return ret;
}
@@ -244,7 +244,7 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
}
-void persistent_prologue(GumStalkerOutput *output) {
+void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE REGS
@@ -313,7 +313,7 @@ void persistent_prologue(GumStalkerOutput *output) {
}
-void persistent_epilogue(GumStalkerOutput *output) {
+void persistent_epilogue_arch(GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c
index f50bccb0..b911676a 100644
--- a/frida_mode/src/persistent/persistent_x86.c
+++ b/frida_mode/src/persistent/persistent_x86.c
@@ -130,7 +130,7 @@ static void instrument_exit(GumX86Writer *cw) {
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
- instrument_previous_pc = 0;
+ instrument_previous_pc = instrument_hash_zero;
return ret;
}
@@ -184,7 +184,7 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
}
-void persistent_prologue(GumStalkerOutput *output) {
+void persistent_prologue_arch(GumStalkerOutput *output) {
/*
* SAVE REGS
@@ -251,7 +251,7 @@ void persistent_prologue(GumStalkerOutput *output) {
}
-void persistent_epilogue(GumStalkerOutput *output) {
+void persistent_epilogue_arch(GumStalkerOutput *output) {
GumX86Writer *cw = output->writer.x86;
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
index 534f202b..6fdd65a7 100644
--- a/frida_mode/src/ranges.c
+++ b/frida_mode/src/ranges.c
@@ -19,9 +19,11 @@ typedef struct {
gboolean ranges_debug_maps = FALSE;
gboolean ranges_inst_libs = FALSE;
+gboolean ranges_inst_jit = FALSE;
static GArray *module_ranges = NULL;
static GArray *libs_ranges = NULL;
+static GArray *jit_ranges = NULL;
static GArray *include_ranges = NULL;
static GArray *exclude_ranges = NULL;
static GArray *ranges = NULL;
@@ -145,11 +147,13 @@ static void convert_name_token(gchar *token, GumMemoryRange *range) {
static void convert_token(gchar *token, GumMemoryRange *range) {
- if (g_strrstr(token, "-")) {
+ if (g_str_has_prefix(token, "0x")) {
convert_address_token(token, range);
- } else {
+ }
+
+ else {
convert_name_token(token, range);
@@ -172,19 +176,27 @@ 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",
+ OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER
+ "X %c%c%c",
details->range->base_address,
- details->range->base_address + details->range->size);
+ details->range->base_address + details->range->size,
+ details->protection & GUM_PAGE_READ ? 'R' : '-',
+ details->protection & GUM_PAGE_WRITE ? 'W' : '-',
+ details->protection & GUM_PAGE_EXECUTE ? 'X' : '-');
} else {
OKF("MAP - 0x%016" G_GINT64_MODIFIER "x - 0x%016" G_GINT64_MODIFIER
- "X %s(0x%016" G_GINT64_MODIFIER "x)",
+ "X %c%c%c %s(0x%016" G_GINT64_MODIFIER "x)",
details->range->base_address,
details->range->base_address + details->range->size,
- details->file->path, details->file->offset);
+ details->protection & GUM_PAGE_READ ? 'R' : '-',
+ details->protection & GUM_PAGE_WRITE ? 'W' : '-',
+ details->protection & GUM_PAGE_EXECUTE ? 'X' : '-', details->file->path,
+ details->file->offset);
}
@@ -329,6 +341,39 @@ static GArray *collect_libs_ranges(void) {
}
+static gboolean collect_jit_ranges_callback(const GumRangeDetails *details,
+ gpointer user_data) {
+
+ GArray *ranges = (GArray *)user_data;
+
+ /* If the executable code isn't backed by a file, it's probably JIT */
+ if (details->file == NULL) {
+
+ GumMemoryRange range = *details->range;
+ g_array_append_val(ranges, range);
+
+ }
+
+ return TRUE;
+
+}
+
+static GArray *collect_jit_ranges(void) {
+
+ GArray *result;
+ result = g_array_new(false, false, sizeof(GumMemoryRange));
+ if (!ranges_inst_jit) {
+
+ gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, collect_jit_ranges_callback,
+ result);
+
+ }
+
+ print_ranges("JIT", result);
+ return result;
+
+}
+
static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra,
GumMemoryRange *rb) {
@@ -508,6 +553,14 @@ void ranges_config(void) {
if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; }
if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; }
+ if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; }
+
+ if (ranges_debug_maps) {
+
+ gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
+ NULL);
+
+ }
include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES");
exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES");
@@ -521,13 +574,13 @@ void ranges_init(void) {
GArray * step2;
GArray * step3;
GArray * step4;
+ GArray * step5;
- if (ranges_debug_maps) {
-
- gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback,
- NULL);
+ OKF("Ranges - Instrument jit [%c]", ranges_inst_jit ? 'X' : ' ');
+ OKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' ');
- }
+ print_ranges("AFL_FRIDA_INST_RANGES", include_ranges);
+ print_ranges("AFL_FRIDA_EXCLUDE_RANGES", exclude_ranges);
OKF("Ranges - Instrument libraries [%c]", ranges_inst_libs ? 'X' : ' ');
@@ -536,6 +589,7 @@ void ranges_init(void) {
module_ranges = collect_module_ranges();
libs_ranges = collect_libs_ranges();
+ jit_ranges = collect_jit_ranges();
/* If include ranges is empty, then assume everything is included */
if (include_ranges->len == 0) {
@@ -558,17 +612,20 @@ void ranges_init(void) {
step3 = subtract_ranges(step2, exclude_ranges);
print_ranges("step3", step3);
+ step4 = subtract_ranges(step3, jit_ranges);
+ print_ranges("step4", step4);
+
/*
- * After step3, we have the total ranges to be instrumented, we now subtract
+ * After step4, we have the total ranges to be instrumented, we now subtract
* that from the original ranges of the modules to configure stalker.
*/
+ step5 = subtract_ranges(module_ranges, step4);
+ print_ranges("step5", step5);
- step4 = subtract_ranges(module_ranges, step3);
- print_ranges("step4", step4);
-
- ranges = merge_ranges(step4);
+ ranges = merge_ranges(step5);
print_ranges("final", ranges);
+ g_array_free(step5, TRUE);
g_array_free(step4, TRUE);
g_array_free(step3, TRUE);
g_array_free(step2, TRUE);
diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c
index 98483cde..5df0386f 100644
--- a/frida_mode/src/stalker.c
+++ b/frida_mode/src/stalker.c
@@ -38,7 +38,7 @@ void stalker_init(void) {
stalker = gum_stalker_new();
if (stalker == NULL) { FATAL("Failed to initialize stalker"); }
- gum_stalker_set_trust_threshold(stalker, 0);
+ gum_stalker_set_trust_threshold(stalker, -1);
/* *NEVER* stalk the stalker, only bad things will ever come of this! */
gum_process_enumerate_ranges(GUM_PAGE_EXECUTE, stalker_exclude_self, NULL);
@@ -59,3 +59,9 @@ void stalker_start(void) {
}
+void stalker_trust(void) {
+
+ gum_stalker_set_trust_threshold(stalker, 0);
+
+}
+
diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c
index 0dd8be70..91a58741 100644
--- a/frida_mode/src/stats/stats.c
+++ b/frida_mode/src/stats/stats.c
@@ -178,10 +178,12 @@ void stats_write(void) {
}
-static void stats_maybe_write(void) {
+void stats_on_fork(void) {
guint64 current_time;
+ if (stats_filename == NULL) { return; }
+
if (stats_interval == 0) { return; }
current_time = g_get_monotonic_time();
@@ -208,7 +210,5 @@ void stats_collect(const cs_insn *instr, gboolean begin) {
stats_collect_arch(instr);
- stats_maybe_write();
-
}
diff --git a/frida_mode/src/stats/stats_x64.c b/frida_mode/src/stats/stats_x64.c
index 7c3a90d7..11464a2a 100644
--- a/frida_mode/src/stats/stats_x64.c
+++ b/frida_mode/src/stats/stats_x64.c
@@ -31,6 +31,9 @@ typedef struct {
guint64 num_rip_relative;
+ guint64 num_rip_relative_type[X86_INS_ENDING];
+ char name_rip_relative_type[X86_INS_ENDING][CS_MNEMONIC_SIZE];
+
} stats_data_arch_t;
gboolean stats_is_supported_arch(void) {
@@ -136,6 +139,18 @@ void stats_write_arch(void) {
stats_data_arch->num_rip_relative,
(stats_data_arch->num_rip_relative * 100 / num_instructions));
+ for (size_t i = 0; i < X86_INS_ENDING; i++) {
+
+ if (stats_data_arch->num_rip_relative_type[i] != 0) {
+
+ stats_print(" %10d %s\n",
+ stats_data_arch->num_rip_relative_type[i],
+ stats_data_arch->name_rip_relative_type[i]);
+
+ }
+
+ }
+
stats_print("\n");
stats_print("\n");
@@ -256,6 +271,9 @@ static void stats_collect_rip_relative_arch(const cs_insn *instr) {
if (rm != 5) { return; }
stats_data_arch->num_rip_relative++;
+ stats_data_arch->num_rip_relative_type[instr->id]++;
+ memcpy(stats_data_arch->name_rip_relative_type[instr->id], instr->mnemonic,
+ CS_MNEMONIC_SIZE);
}