about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--frida_mode/README.md4
-rw-r--r--frida_mode/src/persistent/persistent.c13
-rw-r--r--frida_mode/src/persistent/persistent_arm64.c12
-rw-r--r--frida_mode/src/persistent/persistent_x64.c53
-rw-r--r--frida_mode/src/persistent/persistent_x86.c40
-rw-r--r--frida_mode/test/persistent_ret/GNUmakefile5
-rw-r--r--include/envs.h1
7 files changed, 81 insertions, 47 deletions
diff --git a/frida_mode/README.md b/frida_mode/README.md
index d7dd72a0..9b316cb9 100644
--- a/frida_mode/README.md
+++ b/frida_mode/README.md
@@ -75,7 +75,6 @@ following options are currently supported:
 * `AFL_FRIDA_PERSISTENT_CNT` - See `AFL_QEMU_PERSISTENT_CNT`
 * `AFL_FRIDA_PERSISTENT_HOOK` - See `AFL_QEMU_PERSISTENT_HOOK`
 * `AFL_FRIDA_PERSISTENT_RET` - See `AFL_QEMU_PERSISTENT_RET`
-* `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` - See `AFL_QEMU_PERSISTENT_RETADDR_OFFSET`
 
 To enable the powerful CMPLOG mechanism, set `-c 0` for `afl-fuzz`.
 
@@ -164,8 +163,7 @@ application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`)
 application to the named file (supersedes the setting of `AFL_DEBUG_CHILD`)
 * `AFL_FRIDA_PERSISTENT_DEBUG` - Insert a Breakpoint into the instrumented code
 at `AFL_FRIDA_PERSISTENT_HOOK` and `AFL_FRIDA_PERSISTENT_RET` to allow the user
-to determine the value of `AFL_FRIDA_PERSISTENT_RETADDR_OFFSET` using a
-debugger.
+to detect issues in the persistent loop using a debugger.
 
 ```
 
diff --git a/frida_mode/src/persistent/persistent.c b/frida_mode/src/persistent/persistent.c
index 2ec5b9cc..243d501d 100644
--- a/frida_mode/src/persistent/persistent.c
+++ b/frida_mode/src/persistent/persistent.c
@@ -13,7 +13,6 @@ afl_persistent_hook_fn hook = NULL;
 guint64                persistent_start = 0;
 guint64                persistent_count = 0;
 guint64                persistent_ret = 0;
-guint64                persistent_ret_offset = 0;
 gboolean               persistent_debug = FALSE;
 
 void persistent_init(void) {
@@ -23,8 +22,6 @@ void persistent_init(void) {
   persistent_start = util_read_address("AFL_FRIDA_PERSISTENT_ADDR");
   persistent_count = util_read_num("AFL_FRIDA_PERSISTENT_CNT");
   persistent_ret = util_read_address("AFL_FRIDA_PERSISTENT_RET");
-  persistent_ret_offset =
-      util_read_address("AFL_FRIDA_PERSISTENT_RETADDR_OFFSET");
 
   if (getenv("AFL_FRIDA_PERSISTENT_DEBUG") != NULL) { persistent_debug = TRUE; }
 
@@ -44,14 +41,6 @@ void persistent_init(void) {
 
   }
 
-  if (persistent_ret_offset != 0 && persistent_ret == 0) {
-
-    FATAL(
-        "AFL_FRIDA_PERSISTENT_RET must be specified if "
-        "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET is");
-
-  }
-
   if (persistent_start != 0 && persistent_count == 0) persistent_count = 1000;
 
   if (persistent_count != 0 && persistent_count < 100)
@@ -68,8 +57,6 @@ void persistent_init(void) {
 
   OKF("Instrumentation - persistent ret [%c] (0x%016" G_GINT64_MODIFIER "X)",
       persistent_ret == 0 ? ' ' : 'X', persistent_ret);
-  OKF("Instrumentation - persistent ret offset [%c] (%" G_GINT64_MODIFIER "d)",
-      persistent_ret_offset == 0 ? ' ' : 'X', persistent_ret_offset);
 
   if (hook_name != NULL) {
 
diff --git a/frida_mode/src/persistent/persistent_arm64.c b/frida_mode/src/persistent/persistent_arm64.c
index b23693fe..d7c6c76b 100644
--- a/frida_mode/src/persistent/persistent_arm64.c
+++ b/frida_mode/src/persistent/persistent_arm64.c
@@ -268,13 +268,15 @@ static void instrument_persitent_restore_regs(GumArm64Writer *   cw,
                                               ARM64_REG_X0, (16 * 14),
                                               GUM_INDEX_SIGNED_OFFSET);
 
-  /* Don't restore RIP or RSP, use x1-x3 as clobber */
-
-  /* LR & Adjusted SP (clobber x1) */
+  /* LR & Adjusted SP (use x1 as clobber) */
   gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X30, ARM64_REG_X1,
                                               ARM64_REG_X0, (16 * 15),
                                               GUM_INDEX_SIGNED_OFFSET);
 
+  gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_SP, ARM64_REG_X1);
+
+  /* Don't restore RIP use x1-x3 as clobber */
+
   /* PC (x2) & CPSR (x1) */
   gum_arm64_writer_put_ldp_reg_reg_reg_offset(cw, ARM64_REG_X2, ARM64_REG_X1,
                                               ARM64_REG_X0, (16 * 16),
@@ -404,7 +406,6 @@ void persistent_prologue(GumStalkerOutput *output) {
 
   gconstpointer loop = cw->code + 1;
 
-  /* Stack must be 16-byte aligned per ABI */
   instrument_persitent_save_regs(cw, &saved_regs);
 
   /* loop: */
@@ -450,9 +451,6 @@ void persistent_epilogue(GumStalkerOutput *output) {
 
   if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
 
-  gum_arm64_writer_put_add_reg_reg_imm(cw, ARM64_REG_SP, ARM64_REG_SP,
-                                       persistent_ret_offset);
-
   gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
                                        GUM_ADDRESS(&saved_lr));
 
diff --git a/frida_mode/src/persistent/persistent_x64.c b/frida_mode/src/persistent/persistent_x64.c
index 858ad38e..653acefe 100644
--- a/frida_mode/src/persistent/persistent_x64.c
+++ b/frida_mode/src/persistent/persistent_x64.c
@@ -43,6 +43,7 @@ struct x86_64_regs {
 typedef struct x86_64_regs arch_api_regs;
 
 static arch_api_regs saved_regs = {0};
+static gpointer      saved_ret = NULL;
 
 gboolean persistent_is_supported(void) {
 
@@ -104,7 +105,7 @@ static void instrument_persitent_save_regs(GumX86Writer *      cw,
 
   /* RED_ZONE + Saved flags, RAX, alignment */
   gum_x86_writer_put_add_reg_imm(cw, GUM_REG_RBX,
-                                 GUM_RED_ZONE_SIZE + (0x8 * 3));
+                                 GUM_RED_ZONE_SIZE + (0x8 * 2));
   gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_RAX, (0x8 * 16),
                                             GUM_REG_RBX);
 
@@ -159,7 +160,9 @@ static void instrument_persitent_restore_regs(GumX86Writer *      cw,
   gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_R15, GUM_REG_RAX,
                                             (0x8 * 14));
 
-  /* Don't restore RIP or RSP */
+  /* Don't restore RIP */
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RSP, GUM_REG_RAX,
+                                            (0x8 * 16));
 
   /* Restore RBX, RAX & Flags */
   gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
@@ -242,6 +245,31 @@ static void persistent_prologue_hook(GumX86Writer *      cw,
 
 }
 
+static void instrument_persitent_save_ret(GumX86Writer *cw) {
+
+  /* Stack usage by this function */
+  gssize offset = GUM_RED_ZONE_SIZE + (3 * 8);
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+                                        -(GUM_RED_ZONE_SIZE));
+
+  gum_x86_writer_put_pushfx(cw);
+  gum_x86_writer_put_push_reg(cw, GUM_REG_RAX);
+  gum_x86_writer_put_push_reg(cw, GUM_REG_RBX);
+
+  gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret));
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_RBX, GUM_REG_RSP,
+                                            offset);
+  gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_RAX, GUM_REG_RBX);
+
+  gum_x86_writer_put_pop_reg(cw, GUM_REG_RBX);
+  gum_x86_writer_put_pop_reg(cw, GUM_REG_RAX);
+  gum_x86_writer_put_popfx(cw);
+
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
+                                        (GUM_RED_ZONE_SIZE));
+
+}
+
 void persistent_prologue(GumStalkerOutput *output) {
 
   /*
@@ -268,11 +296,10 @@ void persistent_prologue(GumStalkerOutput *output) {
 
   gconstpointer loop = cw->code + 1;
 
-  /* Stack must be 16-byte aligned per ABI */
-  instrument_persitent_save_regs(cw, &saved_regs);
+  /* Pop the return value */
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, 8);
 
-  /* pop the return value */
-  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, (8));
+  instrument_persitent_save_regs(cw, &saved_regs);
 
   /* loop: */
   gum_x86_writer_put_label(cw, loop);
@@ -304,6 +331,8 @@ void persistent_prologue(GumStalkerOutput *output) {
   /* original: */
   gum_x86_writer_put_label(cw, original);
 
+  instrument_persitent_save_ret(cw);
+
   if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
 
 }
@@ -314,9 +343,15 @@ void persistent_epilogue(GumStalkerOutput *output) {
 
   if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
 
-  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP,
-                                        persistent_ret_offset);
-  gum_x86_writer_put_ret(cw);
+  /* The stack should be aligned when we re-enter our loop */
+  gconstpointer zero = cw->code + 1;
+  gum_x86_writer_put_test_reg_u32(cw, GUM_REG_RSP, 0xF);
+  gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, zero, GUM_NO_HINT);
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, -8);
+  gum_x86_writer_put_label(cw, zero);
+
+  gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, GUM_ADDRESS(&saved_ret));
+  gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_RAX);
 
 }
 
diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c
index 0675edf4..7add6e99 100644
--- a/frida_mode/src/persistent/persistent_x86.c
+++ b/frida_mode/src/persistent/persistent_x86.c
@@ -39,6 +39,7 @@ struct x86_regs {
 typedef struct x86_regs arch_api_regs;
 
 static arch_api_regs saved_regs = {0};
+static gpointer      saved_ret = NULL;
 
 gboolean persistent_is_supported(void) {
 
@@ -117,7 +118,9 @@ static void instrument_persitent_restore_regs(GumX86Writer *   cw,
   gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBP, GUM_REG_EAX,
                                             (0x4 * 6));
 
-  /* Don't restore RIP or RSP */
+  /* Don't restore RIP */
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_ESP, GUM_REG_EAX,
+                                            (0x4 * 8));
 
   /* Restore RBX, RAX & Flags */
   gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_EAX,
@@ -184,6 +187,26 @@ static void persistent_prologue_hook(GumX86Writer *cw, struct x86_regs *regs) {
 
 }
 
+static void instrument_persitent_save_ret(GumX86Writer *cw) {
+
+  /* Stack usage by this function */
+  gssize offset = (3 * 4);
+
+  gum_x86_writer_put_pushfx(cw);
+  gum_x86_writer_put_push_reg(cw, GUM_REG_EAX);
+  gum_x86_writer_put_push_reg(cw, GUM_REG_EBX);
+
+  gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret));
+  gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_REG_EBX, GUM_REG_ESP,
+                                            offset);
+  gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_EAX, GUM_REG_EBX);
+
+  gum_x86_writer_put_pop_reg(cw, GUM_REG_EBX);
+  gum_x86_writer_put_pop_reg(cw, GUM_REG_EAX);
+  gum_x86_writer_put_popfx(cw);
+
+}
+
 void persistent_prologue(GumStalkerOutput *output) {
 
   /*
@@ -210,11 +233,10 @@ void persistent_prologue(GumStalkerOutput *output) {
 
   gconstpointer loop = cw->code + 1;
 
-  /* Stack must be 16-byte aligned per ABI */
-  instrument_persitent_save_regs(cw, &saved_regs);
-
   /* Pop the return value */
-  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, (4));
+  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP, 4);
+
+  instrument_persitent_save_regs(cw, &saved_regs);
 
   /* loop: */
   gum_x86_writer_put_label(cw, loop);
@@ -244,6 +266,8 @@ void persistent_prologue(GumStalkerOutput *output) {
   /* original: */
   gum_x86_writer_put_label(cw, original);
 
+  instrument_persitent_save_ret(cw);
+
   if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
 
 }
@@ -254,10 +278,8 @@ void persistent_epilogue(GumStalkerOutput *output) {
 
   if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
 
-  gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_ESP, GUM_REG_ESP,
-                                        persistent_ret_offset);
-
-  gum_x86_writer_put_ret(cw);
+  gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EAX, GUM_ADDRESS(&saved_ret));
+  gum_x86_writer_put_jmp_reg_ptr(cw, GUM_REG_EAX);
 
 }
 
diff --git a/frida_mode/test/persistent_ret/GNUmakefile b/frida_mode/test/persistent_ret/GNUmakefile
index 4c9d8a19..2de51d86 100644
--- a/frida_mode/test/persistent_ret/GNUmakefile
+++ b/frida_mode/test/persistent_ret/GNUmakefile
@@ -38,8 +38,6 @@ ifeq "$(ARCH)" "x86"
  AFL_FRIDA_PERSISTENT_RET=$(shell $(PWD)get_symbol_addr.py -f $(TESTINSTBIN) -s slow -b 0x56555000)
 endif
 
-AFL_FRIDA_PERSISTENT_RETADDR_OFFSET:=0x50
-
 .PHONY: all 32 clean qemu frida
 
 all: $(TESTINSTBIN)
@@ -76,7 +74,6 @@ frida: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
 frida_ret: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
 	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
 	AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \
-	AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \
 	$(ROOT)afl-fuzz \
 		-D \
 		-O \
@@ -89,7 +86,6 @@ debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
 	gdb \
 		--ex 'set environment AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR)' \
 		--ex 'set environment AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET)' \
-		--ex 'set environment AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET)' \
 		--ex 'set environment AFL_FRIDA_PERSISTENT_DEBUG=1' \
 		--ex 'set environment AFL_DEBUG_CHILD=1' \
 		--ex 'set environment LD_PRELOAD=$(ROOT)afl-frida-trace.so' \
@@ -99,7 +95,6 @@ debug: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
 run: $(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
 	AFL_FRIDA_PERSISTENT_ADDR=$(AFL_FRIDA_PERSISTENT_ADDR) \
 	AFL_FRIDA_PERSISTENT_RET=$(AFL_FRIDA_PERSISTENT_RET) \
-	AFL_FRIDA_PERSISTENT_RETADDR_OFFSET=$(AFL_FRIDA_PERSISTENT_RETADDR_OFFSET) \
 	AFL_DEBUG_CHILD=1 \
 	LD_PRELOAD=$(ROOT)afl-frida-trace.so \
 		$(TESTINSTBIN) $(TESTINSTR_DATA_FILE)
diff --git a/include/envs.h b/include/envs.h
index 15116fc1..ea912a25 100644
--- a/include/envs.h
+++ b/include/envs.h
@@ -67,7 +67,6 @@ static char *afl_environment_variables[] = {
     "AFL_FRIDA_PERSISTENT_DEBUG",
     "AFL_FRIDA_PERSISTENT_HOOK",
     "AFL_FRIDA_PERSISTENT_RET",
-    "AFL_FRIDA_PERSISTENT_RETADDR_OFFSET",
     "AFL_FRIDA_STATS_FILE",
     "AFL_FRIDA_STATS_INTERVAL",
     "AFL_FRIDA_STATS_TRANSITIONS",