Merge pull request #2119 from WorksButNotTested/frida-persistent

Frida persistent
This commit is contained in:
van Hauser
2024-06-10 22:24:25 +02:00
committed by GitHub
7 changed files with 88 additions and 222 deletions

View File

@ -214,6 +214,9 @@ all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QE
arm: arm:
CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all CFLAGS="-marm" LDFLAGS="-marm" ARCH="armhf" TARGET_CC=arm-linux-gnueabihf-gcc TARGET_CXX=arm-linux-gnueabihf-g++ make all
arm64:
ARCH="arm64" TARGET_CC=aarch64-linux-gnu-gcc TARGET_CXX=aarch64-linux-gnu-g++ make all
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $(BUILD_DIR) mkdir -p $(BUILD_DIR)

View File

@ -31,8 +31,8 @@ __attribute__((visibility("default"))) void afl_persistent_hook(
// do a length check matching the target! // do a length check matching the target!
void **esp = (void **)regs->esp; void **esp = (void **)regs->esp;
void *arg1 = esp[0]; void *arg1 = esp[1];
void **arg2 = &esp[1]; void **arg2 = &esp[2];
memcpy(arg1, input_buf, input_buf_len); memcpy(arg1, input_buf, input_buf_len);
*arg2 = (void *)input_buf_len; *arg2 = (void *)input_buf_len;

View File

@ -33,7 +33,7 @@
// r15 - pc // r15 - pc
static GumCpuContext saved_regs = {0}; static GumCpuContext saved_regs = {0};
static gpointer saved_lr = NULL; static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) { gboolean persistent_is_supported(void) {
@ -141,17 +141,10 @@ static void instrument_persitent_restore_regs(GumArmWriter *cw,
} }
static void instrument_exit(GumArmWriter *cw) { static void instrument_afl_persistent_loop_func(void) {
gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
gum_arm_writer_put_call_address_with_arguments(cw, GUM_ADDRESS(_exit), 1,
GUM_ARG_REGISTER, ARM_REG_R0);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); FATAL("instrument_previous_pc_addr uninitialized");
@ -159,7 +152,6 @@ static int instrument_afl_persistent_loop_func(void) {
} }
*instrument_previous_pc_addr = instrument_hash_zero; *instrument_previous_pc_addr = instrument_hash_zero;
return ret;
} }
@ -203,7 +195,8 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
GUM_RED_ZONE_SIZE); GUM_RED_ZONE_SIZE);
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
GUM_ADDRESS(&persistent_ret));
gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0); gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, 0);
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP,
@ -214,65 +207,35 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumArmWriter *cw = output->writer.arm; GumArmWriter *cw = output->writer.arm;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_arm_writer_put_label(cw, loop); persistent_loop = gum_arm_writer_cur(cw);
/* call instrument_prologue_func */ /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw); instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_arm_writer_put_cmp_reg_imm(cw, ARM_REG_R0, 0);
gum_arm_writer_put_b_cond_label(cw, ARM_CC_EQ, done);
/* Optionally call the persistent hook */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_arm_writer_put_bl_label(cw, original);
/* jmp loop */
gum_arm_writer_put_b_label(cw, loop);
/* done: */
gum_arm_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_arm_writer_put_label(cw, original);
instrument_persitent_save_lr(cw);
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
@ -284,7 +247,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); }
gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0,
GUM_ADDRESS(&persistent_loop));
gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0); gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0);

View File

@ -16,7 +16,7 @@ typedef struct {
} persistent_ctx_t; } persistent_ctx_t;
static persistent_ctx_t saved_regs = {0}; static persistent_ctx_t saved_regs = {0};
static gpointer saved_lr = NULL; static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) { gboolean persistent_is_supported(void) {
@ -216,17 +216,10 @@ static void instrument_persitent_restore_regs(GumArm64Writer *cw,
} }
static void instrument_exit(GumArm64Writer *cw) { static void instrument_afl_persistent_loop_func(void) {
gum_arm64_writer_put_mov_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
gum_arm64_writer_put_call_address_with_arguments(
cw, GUM_ADDRESS(_exit), 1, GUM_ARG_REGISTER, ARM64_REG_X0);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); FATAL("instrument_previous_pc_addr uninitialized");
@ -234,7 +227,6 @@ static int instrument_afl_persistent_loop_func(void) {
} }
*instrument_previous_pc_addr = instrument_hash_zero; *instrument_previous_pc_addr = instrument_hash_zero;
return ret;
} }
@ -284,7 +276,7 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
GUM_INDEX_PRE_ADJUST); GUM_INDEX_PRE_ADJUST);
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr)); GUM_ADDRESS(&persistent_ret));
gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0); gum_arm64_writer_put_str_reg_reg_offset(cw, ARM64_REG_LR, ARM64_REG_X0, 0);
@ -297,65 +289,35 @@ static void instrument_persitent_save_lr(GumArm64Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumArm64Writer *cw = output->writer.arm64; GumArm64Writer *cw = output->writer.arm64;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); FVERBOSE("Persistent loop reached");
if (persistent_ret == 0) { instrument_persitent_save_lr(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_arm64_writer_put_label(cw, loop); persistent_loop = gum_arm64_writer_cur(cw);
/* call instrument_prologue_func */ /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw); instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_arm64_writer_put_cmp_reg_reg(cw, ARM64_REG_X0, ARM64_REG_XZR);
gum_arm64_writer_put_b_cond_label(cw, ARM64_CC_EQ, done);
/* Optionally call the persistent hook */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_arm64_writer_put_bl_label(cw, original);
/* jmp loop */
gum_arm64_writer_put_b_label(cw, loop);
/* done: */
gum_arm64_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_arm64_writer_put_label(cw, original);
instrument_persitent_save_lr(cw);
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
@ -368,7 +330,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); } if (persistent_debug) { gum_arm64_writer_put_brk_imm(cw, 0); }
gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0, gum_arm64_writer_put_ldr_reg_address(cw, ARM64_REG_X0,
GUM_ADDRESS(&saved_lr)); GUM_ADDRESS(&persistent_loop));
gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0); gum_arm64_writer_put_ldr_reg_reg_offset(cw, ARM64_REG_X0, ARM64_REG_X0, 0);

View File

@ -17,7 +17,7 @@ typedef struct {
} persistent_ctx_t; } persistent_ctx_t;
static persistent_ctx_t saved_regs = {0}; static persistent_ctx_t saved_regs = {0};
static gpointer saved_ret = NULL; static gpointer persistent_loop = NULL;
gboolean persistent_is_supported(void) { gboolean persistent_is_supported(void) {
@ -162,17 +162,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
} }
static void instrument_exit(GumX86Writer *cw) { static void instrument_afl_persistent_loop_func(void) {
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(_exit)); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); }
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_RDI, 0);
gum_x86_writer_put_call_reg(cw, GUM_X86_RAX);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); FATAL("instrument_previous_pc_addr uninitialized");
@ -180,7 +173,6 @@ static int instrument_afl_persistent_loop_func(void) {
} }
*instrument_previous_pc_addr = instrument_hash_zero; *instrument_previous_pc_addr = instrument_hash_zero;
return ret;
} }
@ -190,7 +182,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
-(GUM_RED_ZONE_SIZE)); -(GUM_RED_ZONE_SIZE));
gum_x86_writer_put_call_address_with_arguments( gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_RAX, GUM_X86_RAX);
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP,
(GUM_RED_ZONE_SIZE)); (GUM_RED_ZONE_SIZE));
@ -235,7 +226,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_X86_RAX); gum_x86_writer_put_push_reg(cw, GUM_X86_RAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_RBX); gum_x86_writer_put_push_reg(cw, GUM_X86_RBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret)); gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
GUM_ADDRESS(&persistent_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP, gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_RBX, GUM_X86_RSP,
offset); offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX); gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_RAX, GUM_X86_RBX);
@ -252,70 +244,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumX86Writer *cw = output->writer.x86; GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); FVERBOSE("Persistent loop reached");
/* Pop the return value */ /*
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, 8); * If we haven't set persistent_ret, then assume that we are dealing with a
* function and we should loop when that function returns.
*/
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_x86_writer_put_label(cw, loop); persistent_loop = gum_x86_writer_cur(cw);
/* call instrument_prologue_func */ /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw); instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
} }
void persistent_epilogue_arch(GumStalkerOutput *output) { void persistent_epilogue_arch(GumStalkerOutput *output) {
@ -331,7 +297,8 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8); gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_RSP, GUM_X86_RSP, -8);
gum_x86_writer_put_label(cw, zero); gum_x86_writer_put_label(cw, zero);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX, GUM_ADDRESS(&saved_ret)); gum_x86_writer_put_mov_reg_address(cw, GUM_X86_RAX,
GUM_ADDRESS(&persistent_loop));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX); gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_RAX);
} }

View File

@ -16,8 +16,7 @@ typedef struct {
} persistent_ctx_t; } persistent_ctx_t;
static persistent_ctx_t saved_regs = {0}; static persistent_ctx_t saved_regs = {0};
static gpointer persistent_loop = NULL;
static gpointer saved_ret = NULL;
gboolean persistent_is_supported(void) { gboolean persistent_is_supported(void) {
@ -118,18 +117,10 @@ static void instrument_persitent_restore_regs(GumX86Writer *cw,
} }
static void instrument_exit(GumX86Writer *cw) { static void instrument_afl_persistent_loop_func(void) {
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(_exit)); if (__afl_persistent_loop(persistent_count) == 0) { _exit(0); };
gum_x86_writer_put_mov_reg_u32(cw, GUM_X86_EDI, 0);
gum_x86_writer_put_push_reg(cw, GUM_X86_EDI);
gum_x86_writer_put_call_reg(cw, GUM_X86_EAX);
}
static int instrument_afl_persistent_loop_func(void) {
int ret = __afl_persistent_loop(persistent_count);
if (instrument_previous_pc_addr == NULL) { if (instrument_previous_pc_addr == NULL) {
FATAL("instrument_previous_pc_addr uninitialized"); FATAL("instrument_previous_pc_addr uninitialized");
@ -137,7 +128,6 @@ static int instrument_afl_persistent_loop_func(void) {
} }
*instrument_previous_pc_addr = instrument_hash_zero; *instrument_previous_pc_addr = instrument_hash_zero;
return ret;
} }
@ -145,7 +135,6 @@ static void instrument_afl_persistent_loop(GumX86Writer *cw) {
gum_x86_writer_put_call_address_with_arguments( gum_x86_writer_put_call_address_with_arguments(
cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); cw, GUM_CALL_CAPI, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0);
gum_x86_writer_put_test_reg_reg(cw, GUM_X86_EAX, GUM_X86_EAX);
} }
@ -179,7 +168,8 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
gum_x86_writer_put_push_reg(cw, GUM_X86_EAX); gum_x86_writer_put_push_reg(cw, GUM_X86_EAX);
gum_x86_writer_put_push_reg(cw, GUM_X86_EBX); gum_x86_writer_put_push_reg(cw, GUM_X86_EBX);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret)); gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
GUM_ADDRESS(&persistent_ret));
gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP, gum_x86_writer_put_mov_reg_reg_offset_ptr(cw, GUM_X86_EBX, GUM_X86_ESP,
offset); offset);
gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX); gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_X86_EAX, GUM_X86_EBX);
@ -193,68 +183,44 @@ static void instrument_persitent_save_ret(GumX86Writer *cw) {
void persistent_prologue_arch(GumStalkerOutput *output) { void persistent_prologue_arch(GumStalkerOutput *output) {
/* /*
* SAVE RET (Used to write the epilogue if persistent_ret is not set)
* SAVE REGS * SAVE REGS
* SAVE RET * loop: (Save address of where the eiplogue should jump back to)
* POP RET
* loop:
* CALL instrument_afl_persistent_loop * CALL instrument_afl_persistent_loop
* TEST EAX, EAX * CALL hook (optionally)
* JZ end:
* call hook (optionally)
* RESTORE REGS * RESTORE REGS
* call original
* jmp loop:
*
* end:
* JMP SAVED RET
*
* original:
* INSTRUMENTED PERSISTENT FUNC * INSTRUMENTED PERSISTENT FUNC
*/ */
GumX86Writer *cw = output->writer.x86; GumX86Writer *cw = output->writer.x86;
gconstpointer loop = cw->code + 1;
FVERBOSE("Persistent loop reached"); FVERBOSE("Persistent loop reached");
/* Pop the return value */ /*
gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_X86_ESP, GUM_X86_ESP, 4); * If we haven't set persistent_ret, then assume that we are dealing with a
* function and we should loop when that function returns.
*/
if (persistent_ret == 0) { instrument_persitent_save_ret(cw); }
/* Save the current context */
instrument_persitent_save_regs(cw, &saved_regs); instrument_persitent_save_regs(cw, &saved_regs);
/* loop: */ /* Store a pointer to where we should return for our next iteration */
gum_x86_writer_put_label(cw, loop); persistent_loop = gum_x86_writer_cur(cw);
/* call instrument_prologue_func */ /* call __afl_persistent_loop and _exit if zero. Also reset our previous_pc */
instrument_afl_persistent_loop(cw); instrument_afl_persistent_loop(cw);
/* jz done */
gconstpointer done = cw->code + 1;
gum_x86_writer_put_jcc_near_label(cw, X86_INS_JE, done, GUM_UNLIKELY);
/* Optionally call the persistent hook */ /* Optionally call the persistent hook */
persistent_prologue_hook(cw, &saved_regs); persistent_prologue_hook(cw, &saved_regs);
/* Restore our CPU context before we continue execution */
instrument_persitent_restore_regs(cw, &saved_regs); instrument_persitent_restore_regs(cw, &saved_regs);
gconstpointer original = cw->code + 1;
/* call original */
gum_x86_writer_put_call_near_label(cw, original);
/* jmp loop */
gum_x86_writer_put_jmp_near_label(cw, loop);
/* done: */
gum_x86_writer_put_label(cw, done);
instrument_exit(cw);
/* original: */
gum_x86_writer_put_label(cw, original);
instrument_persitent_save_ret(cw);
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
/* The original instrumented code is emitted here. */
} }
void persistent_epilogue_arch(GumStalkerOutput *output) { void persistent_epilogue_arch(GumStalkerOutput *output) {
@ -263,7 +229,12 @@ void persistent_epilogue_arch(GumStalkerOutput *output) {
if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); } if (persistent_debug) { gum_x86_writer_put_breakpoint(cw); }
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX, GUM_ADDRESS(&saved_ret)); /* The stack should be aligned when we re-enter our loop */
gum_x86_writer_put_and_reg_u32(cw, GUM_X86_ESP, 0xfffffff0);
gum_x86_writer_put_sub_reg_imm(cw, GUM_X86_ESP, 0x4);
gum_x86_writer_put_mov_reg_address(cw, GUM_X86_EAX,
GUM_ADDRESS(&persistent_loop));
gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX); gum_x86_writer_put_jmp_reg_ptr(cw, GUM_X86_EAX);
} }

View File

@ -48,7 +48,7 @@ all: $(TEST_BIN)
CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN) CFLAGS="-m32" LDFLAGS="-m32" make $(TEST_BIN)
arm: arm:
CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" make $(TEST_BIN) CFLAGS="-marm" LDFLAGS="-marm" CC="arm-linux-gnueabihf-gcc" CXX="arm-linux-gnueabihf-g++" PNG_ARCH="arm" make $(TEST_BIN)
$(BUILD_DIR): $(BUILD_DIR):
mkdir -p $@ mkdir -p $@
@ -93,8 +93,7 @@ $(LIBZ_PC): | $(LIBZ_DIR)
cd $(LIBZ_DIR) && \ cd $(LIBZ_DIR) && \
CFLAGS="$(CFLAGS) -fPIC" \ CFLAGS="$(CFLAGS) -fPIC" \
./configure \ ./configure \
--static \ --static
--archs="$(ARCH)"
$(LIBZ_LIB): | $(LIBZ_PC) $(LIBZ_LIB): | $(LIBZ_PC)
CFLAGS="$(CFLAGS) -fPIC" \ CFLAGS="$(CFLAGS) -fPIC" \
@ -120,7 +119,7 @@ $(LIBPNG_MAKEFILE): $(LIBZ_LIB) | $(LIBPNG_DIR)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \ CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \
LDFLAGS="-L$(LIBZ_DIR)" \ LDFLAGS="-L$(LIBZ_DIR)" \
./configure \ ./configure \
--host="$(ARCH)" --host="$(PNG_ARCH)"
$(LIBPNG_LIB): $(LIBPNG_MAKEFILE) $(LIBPNG_LIB): $(LIBPNG_MAKEFILE)
CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \ CFLAGS="$(CFLAGS) -I$(LIBZ_DIR)" \