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/entry.c26
-rw-r--r--frida_mode/src/instrument/instrument.c1
-rw-r--r--frida_mode/src/instrument/instrument_arm32.c2
-rw-r--r--frida_mode/src/instrument/instrument_arm64.c241
-rw-r--r--frida_mode/src/instrument/instrument_x64.c289
-rw-r--r--frida_mode/src/lib/lib.c6
-rw-r--r--frida_mode/src/lib/lib_apple.c4
-rw-r--r--frida_mode/src/main.c53
-rw-r--r--frida_mode/src/ranges.c2
9 files changed, 495 insertions, 129 deletions
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c
index 05af7ebb..fc49b4d7 100644
--- a/frida_mode/src/entry.c
+++ b/frida_mode/src/entry.c
@@ -78,31 +78,7 @@ void entry_init(void) {
 
 void entry_start(void) {
 
-  if (persistent_start == 0) {
-
-    ranges_exclude();
-    stalker_trust();
-
-  }
-
-  if (entry_point == 0) { entry_launch(); }
-
-}
-
-static void entry_callout(GumCpuContext *cpu_context, gpointer user_data) {
-
-  UNUSED_PARAMETER(cpu_context);
-  UNUSED_PARAMETER(user_data);
-  entry_compiled = TRUE;
-  entry_launch();
-
-}
-
-void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
-
-  UNUSED_PARAMETER(output);
   FVERBOSE("AFL_ENTRYPOINT reached");
-
   if (persistent_start == 0) {
 
     ranges_exclude();
@@ -110,7 +86,7 @@ void entry_prologue(GumStalkerIterator *iterator, GumStalkerOutput *output) {
 
   }
 
-  gum_stalker_iterator_put_callout(iterator, entry_callout, NULL, NULL);
+  entry_launch();
 
 }
 
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c
index a6aac666..db73d845 100644
--- a/frida_mode/src/instrument/instrument.c
+++ b/frida_mode/src/instrument/instrument.c
@@ -169,7 +169,6 @@ static void instrument_basic_block(GumStalkerIterator *iterator,
 
     if (unlikely(begin)) { instrument_debug_start(instr->address, output); }
 
-    if (instr->address == entry_point) { entry_prologue(iterator, output); }
     if (instr->address == persistent_start) { persistent_prologue(output); }
     if (instr->address == persistent_ret) { persistent_epilogue(output); }
 
diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c
index 51f78a35..c1e3f187 100644
--- a/frida_mode/src/instrument/instrument_arm32.c
+++ b/frida_mode/src/instrument/instrument_arm32.c
@@ -15,7 +15,7 @@ static GHashTable *coverage_blocks = NULL;
 
 extern __thread guint64 instrument_previous_pc;
 
-__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
+__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_INITIAL_SIZE];
 
   #pragma pack(push, 1)
 typedef struct {
diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c
index 4372861d..1147275f 100644
--- a/frida_mode/src/instrument/instrument_arm64.c
+++ b/frida_mode/src/instrument/instrument_arm64.c
@@ -22,7 +22,7 @@ gboolean           instrument_cache_enabled = FALSE;
 gsize              instrument_cache_size = 0;
 static GHashTable *coverage_blocks = NULL;
 
-__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE];
+__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_INITIAL_SIZE];
 
   #pragma pack(push, 1)
 typedef struct {
@@ -76,6 +76,45 @@ typedef struct {
 
 } afl_log_code_asm_t;
 
+typedef struct {
+
+  uint32_t b_imm8;                                          /* br #XX (end) */
+
+  uint32_t restoration_prolog;                 /* ldp x16, x17, [sp], #0x90 */
+
+  uint32_t stp_x0_x1;                           /* stp x0, x1, [sp, #-0xa0] */
+
+  uint32_t ldr_x0_p_prev_loc_1;                          /* ldr x0, #0xXXXX */
+  uint32_t ldr_x1_ptr_x0;                                   /* ldr x1, [x0] */
+
+  uint32_t ldr_x0_p_area_offset;                         /* ldr x0, #0xXXXX */
+  uint32_t eor_x0_x1_x0;                                  /* eor x0, x1, x0 */
+  uint32_t ldr_x1_p_area_ptr;                            /* ldr x1, #0xXXXX */
+  uint32_t add_x0_x1_x0;                                  /* add x0, x1, x0 */
+
+  uint32_t ldrb_w1_x0;                                     /* ldrb w1, [x0] */
+  uint32_t add_w1_w1_1;                                   /* add w1, w1, #1 */
+  uint32_t add_w1_w1_w1_lsr_8;                    /* add x1, x1, x1, lsr #8 */
+
+  uint32_t strb_w1_ptr_x0;                                 /* strb w1, [x0] */
+
+  uint32_t ldr_x0_p_prev_loc_2;                          /* ldr x0, #0xXXXX */
+  uint32_t ldr_x1_p_area_offset_ror;                     /* ldr x1, #0xXXXX */
+  uint32_t str_x1_ptr_x0;                                   /* str x1, [x0] */
+
+  uint32_t ldp_x0_x1;                           /* ldp x0, x1, [sp, #-0xa0] */
+
+  uint32_t b_end;                                          /* skip the data */
+
+  uint64_t area_ptr;
+  uint64_t prev_loc_ptr;
+  uint64_t area_offset;
+  uint64_t area_offset_ror;
+
+  uint8_t end[0];
+
+} afl_log_code_asm_long_t;
+
   #pragma pack(pop)
 
 typedef union {
@@ -85,6 +124,13 @@ typedef union {
 
 } afl_log_code;
 
+typedef union {
+
+  afl_log_code_asm_long_t code;
+  uint8_t                 bytes[0];
+
+} afl_log_code_long;
+
 static const afl_log_code_asm_t template =
     {
 
@@ -119,6 +165,46 @@ static const afl_log_code_asm_t template =
 
 ;
 
+static const afl_log_code_asm_long_t template_long =
+    {.b_imm8 = 0x1400001a,
+
+     .restoration_prolog = 0xa8c947f0,         /* ldp x16, x17, [sp], #0x90 */
+
+     .stp_x0_x1 = 0xa93607e0,                   /* stp x0, x1, [sp, #-0xa0] */
+
+     .ldr_x0_p_prev_loc_1 = 0x58000220,                  /* ldr x0, #0xXXXX */
+     .ldr_x1_ptr_x0 = 0xf9400001,                           /* ldr x1, [x0] */
+
+     .ldr_x0_p_area_offset = 0x58000220,                 /* ldr x0, #0xXXXX */
+     .eor_x0_x1_x0 = 0xca000020,                          /* eor x0, x1, x0 */
+     .ldr_x1_p_area_ptr = 0x58000161,                    /* ldr x1, #0xXXXX */
+     .add_x0_x1_x0 = 0x8b000020,                          /* add x0, x1, x0 */
+
+     .ldrb_w1_x0 = 0x39400001,                             /* ldrb w1, [x0] */
+     .add_w1_w1_1 = 0x11000421,                           /* add w1, w1, #1 */
+     .add_w1_w1_w1_lsr_8 = 0x8b412021,            /* add x1, x1, x1, lsr #8 */
+
+     .strb_w1_ptr_x0 = 0x39000001,                         /* strb w1, [x0] */
+
+     .ldr_x0_p_prev_loc_2 = 0x580000e0,                  /* ldr x0, #0xXXXX */
+     .ldr_x1_p_area_offset_ror = 0x58000141,             /* ldr x1, #0xXXXX */
+     .str_x1_ptr_x0 = 0xf9000001,                           /* str x1, [x0] */
+
+     .ldp_x0_x1 = 0xa97607e0,                   /* ldp x0, x1, [sp, #-0xa0] */
+
+     .b_end = 0x14000009,                                  /* skip the data */
+
+     .area_ptr = 0x0,
+     .prev_loc_ptr = 0x0,
+     .area_offset = 0x0,
+     .area_offset_ror = 0x0,
+
+     .end = {}
+
+}
+
+;
+
 gboolean instrument_is_coverage_optimize_supported(void) {
 
   return true;
@@ -266,16 +352,22 @@ static gboolean instrument_coverage_in_range(gssize offset) {
 
 }
 
-static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
+static bool instrument_patch_ardp(guint32 *patch, GumAddress insn,
                                   GumAddress target) {
 
-  if (!PAGE_ALIGNED(target)) { FATAL("Target not page aligned"); }
+  if (!PAGE_ALIGNED(target)) {
+
+    FWARNF("Target not page aligned");
+    return false;
+
+  }
 
   gssize distance = target - (GUM_ADDRESS(insn) & PAGE_MASK);
   if (!instrument_coverage_in_range(distance)) {
 
-    FATAL("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target,
-          distance);
+    FVERBOSE("Patch out of range 0x%016lX->0x%016lX = 0x%016lX", insn, target,
+             distance);
+    return false;
 
   }
 
@@ -283,6 +375,103 @@ static void instrument_patch_ardp(guint32 *patch, GumAddress insn,
   guint32 imm_high = ((distance >> 14) & 0x7FFFF) << 5;
   *patch |= imm_low;
   *patch |= imm_high;
+  return true;
+
+}
+
+bool instrument_write_inline(GumArm64Writer *cw, GumAddress code_addr,
+                             guint64 area_offset, gsize area_offset_ror) {
+
+  afl_log_code code = {0};
+  code.code = template;
+
+  /*
+   * Given our map is allocated on a 64KB boundary and our map is a multiple of
+   * 64KB in size, then it should also end on a 64 KB boundary. It is followed
+   * by our previous_pc, so this too should be 64KB aligned.
+   */
+  g_assert(PAGE_ALIGNED(instrument_previous_pc_addr));
+  g_assert(PAGE_ALIGNED(__afl_area_ptr));
+
+  if (!instrument_patch_ardp(
+          &code.code.adrp_x0_prev_loc1,
+          code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1),
+          GUM_ADDRESS(instrument_previous_pc_addr))) {
+
+    return false;
+
+  }
+
+  /*
+   * The mov instruction supports up to a 16-bit offset. If our offset is out of
+   * range, then it can end up clobbering the op-code portion of the instruction
+   * rather than just the operands. So return false and fall back to the
+   * alternative instrumentation.
+   */
+  if (area_offset > UINT16_MAX) { return false; }
+
+  code.code.mov_x0_curr_loc |= area_offset << 5;
+
+  if (!instrument_patch_ardp(
+          &code.code.adrp_x1_area_ptr,
+          code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr),
+          GUM_ADDRESS(__afl_area_ptr))) {
+
+    return false;
+
+  }
+
+  if (!instrument_patch_ardp(
+          &code.code.adrp_x0_prev_loc2,
+          code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2),
+          GUM_ADDRESS(instrument_previous_pc_addr))) {
+
+    return false;
+
+  }
+
+  code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5);
+
+  if (instrument_suppress) {
+
+    gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
+
+  } else {
+
+    size_t offset = offsetof(afl_log_code, code.stp_x0_x1);
+    gum_arm64_writer_put_bytes(cw, &code.bytes[offset],
+                               sizeof(afl_log_code) - offset);
+
+  }
+
+  return true;
+
+}
+
+bool instrument_write_inline_long(GumArm64Writer *cw, GumAddress code_addr,
+                                  guint64 area_offset, gsize area_offset_ror) {
+
+  afl_log_code_long code = {0};
+  code.code = template_long;
+
+  code.code.area_ptr = GUM_ADDRESS(__afl_area_ptr);
+  code.code.prev_loc_ptr = GUM_ADDRESS(instrument_previous_pc_addr);
+  code.code.area_offset = area_offset;
+  code.code.area_offset_ror = GUM_ADDRESS(area_offset_ror);
+
+  if (instrument_suppress) {
+
+    gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code_long));
+
+  } else {
+
+    size_t offset = offsetof(afl_log_code_long, code.stp_x0_x1);
+    gum_arm64_writer_put_bytes(cw, &code.bytes[offset],
+                               sizeof(afl_log_code_long) - offset);
+
+  }
+
+  return true;
 
 }
 
@@ -312,6 +501,8 @@ void instrument_coverage_optimize(const cs_insn    *instr,
   }
 
   // gum_arm64_writer_put_brk_imm(cw, 0x0);
+  // uint32_t jmp_dot = 0x14000000;
+  // gum_arm64_writer_put_bytes(cw, (guint8 *)&jmp_dot, sizeof(jmp_dot));
 
   if (instrument_suppress) { instrument_coverage_suppress_init(); }
 
@@ -343,47 +534,19 @@ void instrument_coverage_optimize(const cs_insn    *instr,
 
   }
 
-  code.code = template;
-
-  /*
-   * Given our map is allocated on a 64KB boundary and our map is a multiple of
-   * 64KB in size, then it should also end on a 64 KB boundary. It is followed
-   * by our previous_pc, so this too should be 64KB aligned.
-   */
-  g_assert(PAGE_ALIGNED(instrument_previous_pc_addr));
-  g_assert(PAGE_ALIGNED(__afl_area_ptr));
-
-  instrument_patch_ardp(
-      &code.code.adrp_x0_prev_loc1,
-      code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc1),
-      GUM_ADDRESS(instrument_previous_pc_addr));
-
-  code.code.mov_x0_curr_loc |= area_offset << 5;
-
-  instrument_patch_ardp(
-      &code.code.adrp_x1_area_ptr,
-      code_addr + offsetof(afl_log_code, code.adrp_x1_area_ptr),
-      GUM_ADDRESS(__afl_area_ptr));
-
   map_size_pow2 = util_log2(__afl_map_size);
   area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
 
-  instrument_patch_ardp(
-      &code.code.adrp_x0_prev_loc2,
-      code_addr + offsetof(afl_log_code, code.adrp_x0_prev_loc2),
-      GUM_ADDRESS(instrument_previous_pc_addr));
-
-  code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5);
+  code.code = template;
 
-  if (instrument_suppress) {
+  if (!instrument_write_inline(cw, code_addr, area_offset, area_offset_ror)) {
 
-    gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
+    if (!instrument_write_inline_long(cw, code_addr, area_offset,
+                                      area_offset_ror)) {
 
-  } else {
+      FATAL("Failed to write inline instrumentation");
 
-    size_t offset = offsetof(afl_log_code, code.stp_x0_x1);
-    gum_arm64_writer_put_bytes(cw, &code.bytes[offset],
-                               sizeof(afl_log_code) - offset);
+    }
 
   }
 
diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c
index 8338f8e7..3983c3ba 100644
--- a/frida_mode/src/instrument/instrument_x64.c
+++ b/frida_mode/src/instrument/instrument_x64.c
@@ -58,6 +58,7 @@ typedef union {
 } jcc_insn;
 
 static GHashTable *coverage_blocks = NULL;
+static GHashTable *coverage_blocks_long = NULL;
 
 gboolean instrument_is_coverage_optimize_supported(void) {
 
@@ -127,6 +128,64 @@ typedef struct {
 
 } afl_log_code_asm_t;
 
+typedef struct {
+
+  // cur_location = (block_address >> 4) ^ (block_address << 8);
+  // shared_mem[cur_location ^ prev_location]++;
+  // prev_location = cur_location >> 1;
+
+  // mov    QWORD PTR [rsp-0x88],rax
+  // lahf
+  // mov    QWORD PTR [rsp-0x90],rax
+  // mov    QWORD PTR [rsp-0x98],rbx
+
+  // mov    rax, 0xXXXXXXXXXXXXXXXXX                          /* p_prev_loc */
+  // mov    eax, dword ptr [rax]                                /* prev_loc */
+  // xor    eax,0x3f77                                           /* cur_loc */
+
+  // mov    rbx, 0xXXXXXXXXXXXXXXXXX                                 /* map */
+  // add    rax,rbx
+
+  // mov    bl,BYTE PTR [rax]
+  // add    bl,0x1
+  // adc    bl,0x0
+  // mov    BYTE PTR [rax],bl
+
+  // mov    rax, 0xXXXXXXXXXXXXXXXXX                          /* p_prev_loc */
+  // mov    dword ptr [rax], 0xXXXXXXXXX                        /* prev_loc */
+
+  // mov    rbx,QWORD PTR [rsp-0x98]
+  // mov    rax,QWORD PTR [rsp-0x90]
+  // sahf
+  // mov    rax,QWORD PTR [rsp-0x88]
+
+  uint8_t mov_rax_rsp_88[8];
+  uint8_t lahf;
+  uint8_t mov_rax_rsp_90[8];
+  uint8_t mov_rbx_rsp_98[8];
+
+  uint8_t mov_rax_prev_loc_ptr1[10];
+  uint8_t mov_eax_prev_loc[2];
+  uint8_t xor_eax_curr_loc[5];
+
+  uint8_t mov_rbx_map_ptr[10];
+  uint8_t add_rax_rbx[3];
+
+  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_rax_prev_loc_ptr2[10];
+  uint8_t mov_prev_loc_curr_loc_shr1[6];
+
+  uint8_t mov_rsp_98_rbx[8];
+  uint8_t mov_rsp_90_rax[8];
+  uint8_t sahf;
+  uint8_t mov_rsp_88_rax[8];
+
+} afl_log_code_asm_long_t;
+
   #pragma pack(pop)
 
 static const afl_log_code_asm_t template =
@@ -158,6 +217,41 @@ static const afl_log_code_asm_t template =
 
 ;
 
+static const afl_log_code_asm_long_t template_long =
+    {
+
+        .mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
+        .lahf = 0x9f,
+        .mov_rax_rsp_90 = {0x48, 0x89, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
+        .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
+
+        .mov_rax_prev_loc_ptr1 = {0x48, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                                  0xFF, 0xFF, 0xFF},
+        .mov_eax_prev_loc = {0x8b, 0x00},
+        .xor_eax_curr_loc = {0x35},
+
+        .mov_rbx_map_ptr = {0x48, 0xBB, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                            0xFF, 0xFF},
+        .add_rax_rbx = {0x48, 0x01, 0xd8},
+
+        .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_rax_prev_loc_ptr2 = {0x48, 0xB8, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
+                                  0xFF, 0xFF, 0xFF},
+        .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x00, 0xFF, 0xFF, 0xFF, 0xFF},
+
+        .mov_rsp_98_rbx = {0x48, 0x8B, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF},
+        .mov_rsp_90_rax = {0x48, 0x8B, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF},
+        .sahf = 0x9e,
+        .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF},
+
+}
+
+;
+
 typedef union {
 
   afl_log_code_asm_t code;
@@ -165,6 +259,13 @@ typedef union {
 
 } afl_log_code;
 
+typedef union {
+
+  afl_log_code_asm_long_t code;
+  uint8_t                 bytes[0];
+
+} afl_log_code_long;
+
 void instrument_coverage_optimize_init(void) {
 
   FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr);
@@ -182,16 +283,19 @@ static void instrument_coverage_switch_insn(GumStalkerObserver *self,
 
   cs_x86    *x86;
   cs_x86_op *op;
+  bool       is_short = false;
+  bool       is_long = false;
+
   if (from_insn == NULL) { return; }
 
   x86 = &from_insn->detail->x86;
   op = x86->operands;
 
-  if (!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target))) {
-
-    return;
+  is_short = g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target));
+  is_long =
+      g_hash_table_contains(coverage_blocks_long, GSIZE_TO_POINTER(*target));
 
-  }
+  if (!is_short && !is_long) { return; }
 
   switch (from_insn->id) {
 
@@ -212,15 +316,41 @@ static void instrument_coverage_switch_insn(GumStalkerObserver *self,
 
       break;
     case X86_INS_RET:
-      instrument_cache_insert(start_address,
-                              (guint8 *)*target + sizeof(afl_log_code));
+      if (is_short) {
+
+        instrument_cache_insert(start_address,
+                                (guint8 *)*target + sizeof(afl_log_code));
+
+      } else if (is_long) {
+
+        instrument_cache_insert(start_address,
+                                (guint8 *)*target + sizeof(afl_log_code_long));
+
+      } else {
+
+        FATAL("Something has gone wrong here!");
+
+      }
+
       break;
     default:
       return;
 
   }
 
-  *target = (guint8 *)*target + sizeof(afl_log_code);
+  if (is_short) {
+
+    *target = (guint8 *)*target + sizeof(afl_log_code);
+
+  } else if (is_long) {
+
+    *target = (guint8 *)*target + sizeof(afl_log_code_long);
+
+  } else {
+
+    FATAL("Something has gone wrong here!");
+
+  }
 
 }
 
@@ -270,22 +400,22 @@ static void instrument_coverage_suppress_init(void) {
 
   }
 
+  coverage_blocks_long = g_hash_table_new(g_direct_hash, g_direct_equal);
+  if (coverage_blocks_long == NULL) {
+
+    FATAL("Failed to g_hash_table_new, errno: %d", errno);
+
+  }
+
 }
 
-static void instrument_coverage_write(GumAddress        address,
-                                      GumStalkerOutput *output) {
+bool instrument_write_inline(GumX86Writer *cw, GumAddress code_addr,
+                             guint32 area_offset, guint32 area_offset_ror) {
 
-  afl_log_code  code = {0};
-  GumX86Writer *cw = output->writer.x86;
-  guint64       area_offset = instrument_get_offset_hash(address);
-  gsize         map_size_pow2;
-  gsize         area_offset_ror;
-  GumAddress    code_addr = cw->pc;
+  afl_log_code code = {0};
 
   code.code = template;
 
-  /* mov_prev_loc_curr_loc_shr1 */
-
   gssize prev_loc_value =
       GPOINTER_TO_SIZE(instrument_previous_pc_addr) -
       (code_addr + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
@@ -294,11 +424,7 @@ static void instrument_coverage_write(GumAddress        address,
       offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
       sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(gint) -
       sizeof(guint32);
-  if (!instrument_coverage_in_range(prev_loc_value)) {
-
-    FATAL("Patch out of range (current_pc_value1): 0x%016lX", prev_loc_value);
-
-  }
+  if (!instrument_coverage_in_range(prev_loc_value)) { return false; }
 
   *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value;
 
@@ -311,11 +437,7 @@ static void instrument_coverage_write(GumAddress        address,
   gssize prev_loc_value_offset2 =
       offsetof(afl_log_code, code.mov_eax_prev_loc) +
       sizeof(code.code.mov_eax_prev_loc) - sizeof(gint);
-  if (!instrument_coverage_in_range(prev_loc_value)) {
-
-    FATAL("Patch out of range (current_pc_value1): 0x%016lX", prev_loc_value2);
-
-  }
+  if (!instrument_coverage_in_range(prev_loc_value)) { return false; }
 
   *((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2;
 
@@ -338,12 +460,7 @@ static void instrument_coverage_write(GumAddress        address,
        (code_addr + offsetof(afl_log_code, code.lea_rbx_area_ptr) +
         sizeof(code.code.lea_rbx_area_ptr)));
 
-  if (!instrument_coverage_in_range(lea_rbx_area_ptr_value)) {
-
-    FATAL("Patch out of range (lea_rbx_area_ptr_value): 0x%016lX",
-          lea_rbx_area_ptr_value);
-
-  }
+  if (!instrument_coverage_in_range(lea_rbx_area_ptr_value)) { return false; }
 
   *((guint32 *)&code.bytes[lea_rbx_area_ptr_offset]) = lea_rbx_area_ptr_value;
 
@@ -353,12 +470,100 @@ static void instrument_coverage_write(GumAddress        address,
       offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) +
       sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32);
 
-  map_size_pow2 = util_log2(__afl_map_size);
-  area_offset_ror = util_rotate(area_offset, 1, map_size_pow2);
-
   *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror);
 
+  if (instrument_suppress) {
+
+    if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) {
+
+      FATAL("Failed - g_hash_table_add");
+
+    }
+
+  }
+
   gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code));
+  return true;
+
+}
+
+bool instrument_write_inline_long(GumX86Writer *cw, guint32 area_offset,
+                                  guint32 area_offset_ror) {
+
+  afl_log_code_long code = {0};
+  code.code = template_long;
+
+  /* mov_rax_prev_loc_ptr1 */
+  gssize mov_rax_prev_loc_ptr1_offset =
+      offsetof(afl_log_code_long, code.mov_rax_prev_loc_ptr1) +
+      sizeof(code.code.mov_rax_prev_loc_ptr1) - sizeof(gsize);
+  *((gsize *)&code.bytes[mov_rax_prev_loc_ptr1_offset]) =
+      GPOINTER_TO_SIZE(instrument_previous_pc_addr);
+
+  /* xor_eax_curr_loc */
+  gssize xor_eax_curr_loc_offset =
+      offsetof(afl_log_code_long, code.xor_eax_curr_loc) +
+      sizeof(code.code.xor_eax_curr_loc) - sizeof(guint32);
+  *((guint32 *)&code.bytes[xor_eax_curr_loc_offset]) = area_offset;
+
+  /* mov_rbx_map_ptr */
+  gsize mov_rbx_map_ptr_offset =
+      offsetof(afl_log_code_long, code.mov_rbx_map_ptr) +
+      sizeof(code.code.mov_rbx_map_ptr) - sizeof(gsize);
+  *((gsize *)&code.bytes[mov_rbx_map_ptr_offset]) =
+      GPOINTER_TO_SIZE(__afl_area_ptr);
+
+  /* mov_rax_prev_loc_ptr2 */
+  gssize mov_rax_prev_loc_ptr2_offset =
+      offsetof(afl_log_code_long, code.mov_rax_prev_loc_ptr2) +
+      sizeof(code.code.mov_rax_prev_loc_ptr2) - sizeof(gsize);
+  *((gsize *)&code.bytes[mov_rax_prev_loc_ptr2_offset]) =
+      GPOINTER_TO_SIZE(instrument_previous_pc_addr);
+
+  /* mov_prev_loc_curr_loc_shr1 */
+  gssize mov_prev_loc_curr_loc_shr1_offset =
+      offsetof(afl_log_code_long, code.mov_prev_loc_curr_loc_shr1) +
+      sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32);
+  *((guint32 *)&code.bytes[mov_prev_loc_curr_loc_shr1_offset]) =
+      (guint32)(area_offset_ror);
+
+  if (instrument_suppress) {
+
+    if (!g_hash_table_add(coverage_blocks_long, GSIZE_TO_POINTER(cw->code))) {
+
+      FATAL("Failed - g_hash_table_add");
+
+    }
+
+  }
+
+  gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code_long));
+  return true;
+
+}
+
+static void instrument_coverage_write(GumAddress        address,
+                                      GumStalkerOutput *output) {
+
+  GumX86Writer *cw = output->writer.x86;
+  guint64       area_offset = (guint32)instrument_get_offset_hash(address);
+  gsize         map_size_pow2;
+  guint32       area_offset_ror;
+  GumAddress    code_addr = cw->pc;
+
+  map_size_pow2 = util_log2(__afl_map_size);
+  area_offset_ror = (guint32)util_rotate(instrument_get_offset_hash(address), 1,
+                                         map_size_pow2);
+
+  if (!instrument_write_inline(cw, code_addr, area_offset, area_offset_ror)) {
+
+    if (!instrument_write_inline_long(cw, area_offset, area_offset_ror)) {
+
+      FATAL("Failed to write inline instrumentation");
+
+    }
+
+  }
 
 }
 
@@ -380,17 +585,7 @@ void instrument_coverage_optimize(const cs_insn    *instr,
 
   }
 
-  if (instrument_suppress) {
-
-    instrument_coverage_suppress_init();
-
-    if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) {
-
-      FATAL("Failed - g_hash_table_add");
-
-    }
-
-  }
+  if (instrument_suppress) { instrument_coverage_suppress_init(); }
 
   instrument_coverage_write(GUM_ADDRESS(instr->address), output);
 
diff --git a/frida_mode/src/lib/lib.c b/frida_mode/src/lib/lib.c
index d563b69b..7fac755a 100644
--- a/frida_mode/src/lib/lib.c
+++ b/frida_mode/src/lib/lib.c
@@ -44,8 +44,10 @@ static gboolean lib_find_exe(const GumModuleDetails *details,
 
   lib_details_t *lib_details = (lib_details_t *)user_data;
 
-  memcpy(lib_details->name, details->name, PATH_MAX);
-  memcpy(lib_details->path, details->path, PATH_MAX);
+  strncpy(lib_details->name, details->name, PATH_MAX);
+  strncpy(lib_details->path, details->path, PATH_MAX);
+  lib_details->name[PATH_MAX] = '\0';
+  lib_details->path[PATH_MAX] = '\0';
   lib_details->base_address = details->range->base_address;
   lib_details->size = details->range->size;
   return FALSE;
diff --git a/frida_mode/src/lib/lib_apple.c b/frida_mode/src/lib/lib_apple.c
index 634e0e30..d29d0303 100644
--- a/frida_mode/src/lib/lib_apple.c
+++ b/frida_mode/src/lib/lib_apple.c
@@ -17,8 +17,8 @@ static gboolean lib_get_main_module(const GumModuleDetails *details,
 
   GumDarwinModule **ret = (GumDarwinModule **)user_data;
   GumDarwinModule  *module = gum_darwin_module_new_from_memory(
-       details->path, mach_task_self(), details->range->base_address,
-       GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
+      details->path, mach_task_self(), details->range->base_address,
+      GUM_DARWIN_MODULE_FLAGS_NONE, NULL);
 
   FVERBOSE("Found main module: %s", module->name);
 
diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c
index c8c50b37..9daf067b 100644
--- a/frida_mode/src/main.c
+++ b/frida_mode/src/main.c
@@ -49,10 +49,10 @@ extern void __libc_init(void *raw_args, void (*onexit)(void) __unused,
                         int (*slingshot)(int, char **, char **),
                         structors_array_t const *const structors);
 #else
-extern int  __libc_start_main(int (*main)(int, char **, char **), int argc,
-                              char **ubp_av, void (*init)(void),
-                              void (*fini)(void), void (*rtld_fini)(void),
-                              void(*stack_end));
+extern int __libc_start_main(int (*main)(int, char **, char **), int argc,
+                             char **ubp_av, void (*init)(void),
+                             void (*fini)(void), void (*rtld_fini)(void),
+                             void(*stack_end));
 #endif
 
 typedef int (*main_fn_t)(int argc, char **argv, char **envp);
@@ -166,7 +166,7 @@ static void afl_print_env(void) {
 
   if (fd < 0) {
 
-    FWARNF("Failed to open /proc/self/cmdline, errno: (%d)", errno);
+    FWARNF("Failed to open /proc/self/environ, errno: (%d)", errno);
     return;
 
   }
@@ -174,7 +174,7 @@ static void afl_print_env(void) {
   ssize_t bytes_read = read(fd, buffer, PROC_MAX - 1);
   if (bytes_read < 0) {
 
-    FFATAL("Failed to read /proc/self/cmdline, errno: (%d)", errno);
+    FFATAL("Failed to read /proc/self/environ, errno: (%d)", errno);
 
   }
 
@@ -197,7 +197,7 @@ static void afl_print_env(void) {
 
 }
 
-__attribute__((visibility("default"))) void afl_frida_start(void) {
+void afl_frida_config(void) {
 
   FOKF(cRED "**********************");
   FOKF(cRED "* " cYEL "******************" cRED " *");
@@ -225,9 +225,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
 
   js_start();
 
-  /* Initialize */
   output_init();
-
   embedded_init();
   entry_init();
   instrument_init();
@@ -240,12 +238,35 @@ __attribute__((visibility("default"))) void afl_frida_start(void) {
   ranges_init();
   stats_init();
 
-  /* Start */
+}
+
+void afl_frida_run(void) {
+
   stalker_start();
   entry_start();
 
 }
 
+__attribute__((visibility("default"))) void afl_frida_start(void) {
+
+  afl_frida_config();
+  afl_frida_run();
+
+}
+
+typedef void *(*entry_func_t)(size_t a1, size_t a2, size_t a3, size_t a4,
+                              size_t a5, size_t a6);
+
+static void *on_entry(size_t a1, size_t a2, size_t a3, size_t a4, size_t a5,
+                      size_t a6) {
+
+  intercept_unhook(GSIZE_TO_POINTER(entry_point));
+  afl_frida_run();
+  entry_func_t entry = (entry_func_t)entry_point;
+  return entry(a1, a2, a3, a4, a5, a6);
+
+}
+
 static int on_main(int argc, char **argv, char **envp) {
 
   int ret;
@@ -254,7 +275,17 @@ static int on_main(int argc, char **argv, char **envp) {
 
   intercept_unhook_self();
 
-  afl_frida_start();
+  afl_frida_config();
+
+  if (entry_point == 0) {
+
+    afl_frida_run();
+
+  } else {
+
+    intercept_hook(GSIZE_TO_POINTER(entry_point), on_entry, NULL);
+
+  }
 
   if (js_main_hook != NULL) {
 
diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c
index e9fc3b4e..269ba59b 100644
--- a/frida_mode/src/ranges.c
+++ b/frida_mode/src/ranges.c
@@ -653,7 +653,7 @@ void ranges_init(void) {
   /*
    * After step 4 we have the total ranges to be instrumented, we now subtract
    * that either from the original ranges of the modules or from the whole
-   * memory if AFL_INST_NO_DYNAMIC_LOAD to configure the stalker.
+   * memory if AFL_FRIDA_INST_NO_DYNAMIC_LOAD to configure the stalker.
    */
   if (ranges_inst_dynamic_load) {