about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--frida_mode/README.md5
-rw-r--r--frida_mode/frida.map1
-rw-r--r--frida_mode/include/stalker.h1
-rw-r--r--frida_mode/src/instrument/instrument_x64.c99
-rw-r--r--frida_mode/src/js/api.js7
-rw-r--r--frida_mode/src/js/js_api.c7
-rw-r--r--frida_mode/src/stalker.c18
-rw-r--r--frida_mode/ts/lib/afl.ts12
-rw-r--r--include/envs.h2
9 files changed, 91 insertions, 61 deletions
diff --git a/frida_mode/README.md b/frida_mode/README.md
index 8211224d..a75324d5 100644
--- a/frida_mode/README.md
+++ b/frida_mode/README.md
@@ -215,6 +215,11 @@ gdb \
 ```
 * `AFL_FRIDA_SECCOMP_FILE` - Write a log of any syscalls made by the target to
 the specified file.
+* `AFL_FRIDA_STALKER_ADJACENT_BLOCKS` - Configure the number of adjacent blocks
+ to fetch when generating instrumented code. By fetching blocks in the same
+ order they appear in the original program, rather than the order of execution
+ should help reduce locallity and adjacency. This includes allowing us to vector
+ between adjancent blocks using a NOP slide rather than an immediate branch.
 * `AFL_FRIDA_STALKER_IC_ENTRIES` - Configure the number of inline cache entries
 stored along-side branch instructions which provide a cache to avoid having to
 call back into FRIDA to find the next block. Default is 32.
diff --git a/frida_mode/frida.map b/frida_mode/frida.map
index 7be41aa0..61eb19ee 100644
--- a/frida_mode/frida.map
+++ b/frida_mode/frida.map
@@ -29,6 +29,7 @@
     js_api_set_prefetch_disable;
     js_api_set_seccomp_file;
     js_api_set_stalker_callback;
+    js_api_set_stalker_adjacent_blocks;
     js_api_set_stalker_ic_entries;
     js_api_set_stats_file;
     js_api_set_stats_interval;
diff --git a/frida_mode/include/stalker.h b/frida_mode/include/stalker.h
index 8a111b90..666787e9 100644
--- a/frida_mode/include/stalker.h
+++ b/frida_mode/include/stalker.h
@@ -5,6 +5,7 @@
 
 extern guint    stalker_ic_entries;
 extern gboolean backpatch_enable;
+extern guint    stalker_adjacent_blocks;
 
 void        stalker_config(void);
 void        stalker_init(void);
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index c474d034..c271adc1 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -52,54 +52,41 @@ typedef struct {
   // shared_mem[cur_location ^ prev_location]++;
   // prev_location = cur_location >> 1;
 
-  //  0x7ffff6cbb9b6:      lea    rsp,[rsp-0x80]
-  //
-  //  0x7ffff6cbb9bb:      push   rax
-  //  0x7ffff6cbb9bc:      lahf
-  //  0x7ffff6cbb9bd:      push   rax
-  //  0x7ffff6cbb9be:      push   rbx
-  //
-  //  0x7ffff6cbb9bf:      mov    eax,DWORD PTR [rip+0x33bd7b]
-  //  0x7ffff6cbb9c5:      xor    eax,0x3f77
-  //  0x7ffff6cbb9ca:      add    eax,0x10000
-  //  0x7ffff6cbb9cf:      mov    bl,BYTE PTR [rax]
-  //  0x7ffff6cbb9d1:      add    bl,0x1
-  //  0x7ffff6cbb9d4:      adc    bl,0x0
-  //  0x7ffff6cbb9d7:      mov    BYTE PTR [rax],bl
-  //
-  //  0x7ffff6cbb9d9:      mov    DWORD PTR [rip+0x33bd5d],0x9fbb
-  //
-  //  0x7ffff6cbb9e3:      pop    rbx
-  //  0x7ffff6cbb9e4:      pop    rax
-  //  0x7ffff6cbb9e5:      sahf
-  //  0x7ffff6cbb9e6:      pop    rax
-  //
-  //  0x7ffff6cbb9e7:      lea    rsp,[rsp+0x80]
-
-  uint8_t lea_rsp_rsp_sub_rz[5];
-
-  uint8_t push_rax;
+  //  mov    QWORD PTR [rsp-0x80],rax
+  //  lahf
+  //  mov    QWORD PTR [rsp-0x88],rax
+  //  mov    QWORD PTR [rsp-0x90],rbx
+  //  mov    eax,DWORD PTR [rip+0x333d5a]        # 0x7ffff6ff2740
+  //  mov    DWORD PTR [rip+0x333d3c],0x9fbb        # 0x7ffff6ff2740
+  //  xor    eax,0x103f77
+  //  mov    bl,BYTE PTR [rax]
+  //  add    bl,0x1
+  //  adc    bl,0x0
+  //  mov    BYTE PTR [rax],bl
+  //  mov    rbx,QWORD PTR [rsp-0x90]
+  //  mov    rax,QWORD PTR [rsp-0x88]
+  //  sahf
+  //  mov    rax,QWORD PTR [rsp-0x80]
+
+  uint8_t mov_rax_rsp_80[5];
   uint8_t lahf;
-  uint8_t push_rax2;
-  uint8_t push_rbx;
+  uint8_t mov_rax_rsp_88[8];
+  uint8_t mov_rbx_rsp_90[8];
 
   uint8_t mov_eax_prev_loc[6];
+  uint8_t mov_prev_loc_curr_loc_shr1[10];
+
   uint8_t xor_eax_curr_loc[5];
-  uint8_t add_eax_afl_area[5];
 
   uint8_t mov_rbx_ptr_rax[2];
   uint8_t add_bl_1[3];
   uint8_t adc_bl_0[3];
   uint8_t mov_ptr_rax_rbx[2];
 
-  uint8_t mov_prev_loc_curr_loc_shr1[10];
-
-  uint8_t pop_rbx;
-  uint8_t pop_rax2;
+  uint8_t mov_rsp_90_rbx[8];
+  uint8_t mov_rsp_88_rax[8];
   uint8_t sahf;
-  uint8_t pop_rax;
-
-  uint8_t lsa_rsp_rsp_add_rz[8];
+  uint8_t mov_rsp_80_rax[5];
 
 } afl_log_code_asm_t;
 
@@ -115,29 +102,24 @@ typedef union {
 static const afl_log_code_asm_t template =
     {
 
-        .lea_rsp_rsp_sub_rz = {0x48, 0x8D, 0x64, 0x24, 0x80},
-        .push_rax = 0x50,
+        .mov_rax_rsp_80 = {0x48, 0x89, 0x44, 0x24, 0x80},
         .lahf = 0x9f,
-        .push_rax2 = 0x50,
-        .push_rbx = 0x53,
+        .mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
+        .mov_rbx_rsp_90 = {0x48, 0x89, 0x9C, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
 
         .mov_eax_prev_loc = {0x8b, 0x05},
-        .xor_eax_curr_loc = {0x35},
+        .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
 
-        .add_eax_afl_area = {0x05},
+        .xor_eax_curr_loc = {0x35},
         .mov_rbx_ptr_rax = {0x8a, 0x18},
         .add_bl_1 = {0x80, 0xc3, 0x01},
         .adc_bl_0 = {0x80, 0xd3, 0x00},
         .mov_ptr_rax_rbx = {0x88, 0x18},
 
-        .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05},
-
-        .pop_rbx = 0x5b,
-        .pop_rax2 = 0x58,
+        .mov_rsp_90_rbx = {0x48, 0x8B, 0x9C, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
+        .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
         .sahf = 0x9e,
-        .pop_rax = 0x58,
-
-        .lsa_rsp_rsp_add_rz = {0x48, 0x8D, 0xA4, 0x24, 0x80, 0x00, 0x00, 0x00},
+        .mov_rsp_80_rax = {0x48, 0x8B, 0x44, 0x24, 0x80},
 
 }
 
@@ -162,7 +144,13 @@ static gboolean instrument_coverage_find_low(const GumRangeDetails *details,
 
   }
 
-  last_limit = details->range->base_address + details->range->size;
+  /*
+   * Align our buffer on a 64k boundary so that the low 16-bits of the address
+   * are zero, then we can just XOR the base address in, when we XOR with the
+   * current block ID.
+   */
+  last_limit = GUM_ALIGN_SIZE(
+      details->range->base_address + details->range->size, (64ULL << 10));
   return TRUE;
 
 }
@@ -421,13 +409,8 @@ void instrument_coverage_optimize(const cs_insn *   instr,
                                sizeof(code.code.xor_eax_curr_loc) -
                                sizeof(guint32);
 
-  *((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)(area_offset);
-
-  gssize lea_rax_offset = offsetof(afl_log_code, code.add_eax_afl_area) +
-                          sizeof(code.code.add_eax_afl_area) - sizeof(guint32);
-
-  *((guint32 *)&code.bytes[lea_rax_offset]) =
-      (guint32)GPOINTER_TO_SIZE(__afl_area_ptr);
+  *((guint32 *)&code.bytes[xor_curr_loc_offset]) =
+      (guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset);
 
   gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
 
diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js
index 5db62389..8e810d09 100644
--- a/frida_mode/src/js/api.js
+++ b/frida_mode/src/js/api.js
@@ -205,6 +205,12 @@ class Afl {
         const buf = Memory.allocUtf8String(file);
         Afl.jsApiSetSeccompFile(buf);
     }
+    /**
+     * See `AFL_FRIDA_STALKER_ADJACENT_BLOCKS`.
+     */
+    static setStalkerAdjacentBlocks(val) {
+        Afl.jsApiSetStalkerAdjacentBlocks(val);
+    }
     /*
      * Set a function to be called for each instruction which is instrumented
      * by AFL FRIDA mode.
@@ -294,6 +300,7 @@ Afl.jsApiSetPrefetchBackpatchDisable = Afl.jsApiGetFunction("js_api_set_prefetch
 Afl.jsApiSetPrefetchDisable = Afl.jsApiGetFunction("js_api_set_prefetch_disable", "void", []);
 Afl.jsApiSetSeccompFile = Afl.jsApiGetFunction("js_api_set_seccomp_file", "void", ["pointer"]);
 Afl.jsApiSetStalkerCallback = Afl.jsApiGetFunction("js_api_set_stalker_callback", "void", ["pointer"]);
+Afl.jsApiSetStalkerAdjacentBlocks = Afl.jsApiGetFunction("js_api_set_stalker_adjacent_blocks", "void", ["uint32"]);
 Afl.jsApiSetStalkerIcEntries = Afl.jsApiGetFunction("js_api_set_stalker_ic_entries", "void", ["uint32"]);
 Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", ["pointer"]);
 Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]);
diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c
index c1f092c9..102423d9 100644
--- a/frida_mode/src/js/js_api.c
+++ b/frida_mode/src/js/js_api.c
@@ -250,3 +250,10 @@ __attribute__((visibility("default"))) void js_api_set_backpatch_disable(void) {
 
 }
 
+__attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks(
+    guint val) {
+
+  stalker_adjacent_blocks = val;
+
+}
+
diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c
index 35a9d856..65ed5d50 100644
--- a/frida_mode/src/stalker.c
+++ b/frida_mode/src/stalker.c
@@ -7,6 +7,7 @@
 
 guint    stalker_ic_entries = 0;
 gboolean backpatch_enable = TRUE;
+guint    stalker_adjacent_blocks = 0;
 
 static GumStalker *stalker = NULL;
 
@@ -60,7 +61,9 @@ void stalker_config(void) {
 
   backpatch_enable = (getenv("AFL_FRIDA_INST_NO_BACKPATCH") == NULL);
 
-  stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES");
+  stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_ADJACENT_BLOCKS");
+
+  stalker_adjacent_blocks = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES");
 
   observer = g_object_new(GUM_TYPE_AFL_STALKER_OBSERVER, NULL);
 
@@ -92,6 +95,7 @@ void stalker_init(void) {
   FOKF("Instrumentation - backpatch [%c]", backpatch_enable ? 'X' : ' ');
 
   FOKF("Stalker - ic_entries [%u]", stalker_ic_entries);
+  FOKF("Stalker - adjacent_blocks [%u]", stalker_adjacent_blocks);
 
 #if !(defined(__x86_64__) || defined(__i386__))
   if (stalker_ic_entries != 0) {
@@ -100,13 +104,21 @@ void stalker_init(void) {
 
   }
 
+  if (stalker_adjacent_blocks != 0) {
+
+    FFATAL("AFL_FRIDA_STALKER_ADJACENT_BLOCKS not supported");
+
+  }
+
 #endif
 
   if (stalker_ic_entries == 0) { stalker_ic_entries = 32; }
 
+  if (stalker_adjacent_blocks == 0) { stalker_adjacent_blocks = 32; }
+
 #if defined(__x86_64__) || defined(__i386__)
-  stalker =
-      g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries, NULL);
+  stalker = g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries,
+                         "adjacent-blocks", stalker_adjacent_blocks, NULL);
 #else
   stalker = gum_stalker_new();
 #endif
diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts
index 3639d670..e20ad3ec 100644
--- a/frida_mode/ts/lib/afl.ts
+++ b/frida_mode/ts/lib/afl.ts
@@ -241,6 +241,13 @@ class Afl {
     Afl.jsApiSetSeccompFile(buf);
   }
 
+  /**
+   * See `AFL_FRIDA_STALKER_ADJACENT_BLOCKS`.
+   */
+  public static setStalkerAdjacentBlocks(val: number): void {
+    Afl.jsApiSetStalkerAdjacentBlocks(val);
+  }
+
   /*
    * Set a function to be called for each instruction which is instrumented
    * by AFL FRIDA mode.
@@ -425,6 +432,11 @@ class Afl {
     "void",
     ["pointer"]);
 
+  private static readonly jsApiSetStalkerAdjacentBlocks = Afl.jsApiGetFunction(
+    "js_api_set_stalker_adjacent_blocks",
+    "void",
+    ["uint32"]);
+
   private static readonly jsApiSetStalkerIcEntries = Afl.jsApiGetFunction(
     "js_api_set_stalker_ic_entries",
     "void",
diff --git a/include/envs.h b/include/envs.h
index 0ba79092..a3ba5e88 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -76,6 +76,8 @@ static char *afl_environment_variables[] = {
     "AFL_FRIDA_PERSISTENT_DEBUG",
     "AFL_FRIDA_PERSISTENT_HOOK",
     "AFL_FRIDA_PERSISTENT_RET",
+    "AFL_FRIDA_STALKER_IC_ENTRIES",
+    "AFL_FRIDA_STALKER_ADJACENT_BLOCKS",
     "AFL_FRIDA_STATS_FILE",
     "AFL_FRIDA_STATS_INTERVAL",
     "AFL_FRIDA_TRACEABLE",