diff options
author | van Hauser <vh@thc.org> | 2023-06-06 17:36:04 +0300 |
---|---|---|
committer | GitHub <noreply@github.com> | 2023-06-06 17:36:04 +0300 |
commit | 4deb45f3b3e9f53880596d21432069b05553bcb3 (patch) | |
tree | 2dcf56dd0b540a4387f050c32ba5f50e7f42d666 /frida_mode/src | |
parent | 8de7f6131d48e27d53e894b65bd11e0dc3817639 (diff) | |
parent | 2f6b54e4410738d92c4981a700541f15e4fbe938 (diff) | |
download | afl++-4deb45f3b3e9f53880596d21432069b05553bcb3.tar.gz |
Merge pull request #1759 from AFLplusplus/dev
Dev
Diffstat (limited to 'frida_mode/src')
-rw-r--r-- | frida_mode/src/entry.c | 26 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument.c | 1 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm64.c | 231 | ||||
-rw-r--r-- | frida_mode/src/js/api.js | 7 | ||||
-rw-r--r-- | frida_mode/src/js/js_api.c | 7 | ||||
-rw-r--r-- | frida_mode/src/lib/lib_apple.c | 4 | ||||
-rw-r--r-- | frida_mode/src/main.c | 41 | ||||
-rw-r--r-- | frida_mode/src/ranges.c | 39 |
8 files changed, 282 insertions, 74 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_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 4372861d..131eb4c5 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -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,95 @@ 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; + + } + + 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 +493,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 +526,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/js/api.js b/frida_mode/src/js/api.js index f9ea1ffb..a65d32df 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -151,6 +151,12 @@ class Afl { Afl.jsApiSetInstrumentLibraries(); } /** + * See `AFL_FRIDA_INST_NO_DYNAMIC_LOAD` + */ + static setInstrumentNoDynamicLoad() { + Afl.jsApiSetInstrumentNoDynamicLoad(); + } + /** * See `AFL_FRIDA_INST_NO_OPTIMIZE` */ static setInstrumentNoOptimize() { @@ -342,6 +348,7 @@ Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_de Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []); Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []); Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); +Afl.jsApiSetInstrumentNoDynamicLoad = Afl.jsApiGetFunction("js_api_set_instrument_no_dynamic_load", "void", []); Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); Afl.jsApiSetInstrumentRegsFile = Afl.jsApiGetFunction("js_api_set_instrument_regs_file", "void", ["pointer"]); Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", "void", ["uint64"]); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 2e996c1c..288aec95 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -156,6 +156,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_instructions( } +__attribute__((visibility("default"))) void +js_api_set_instrument_no_dynamic_load(void) { + + ranges_inst_dynamic_load = FALSE; + +} + __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize( void) { 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..f11c4b25 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -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 72cb9730..e9fc3b4e 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -18,6 +18,7 @@ typedef struct { gboolean ranges_debug_maps = FALSE; gboolean ranges_inst_libs = FALSE; gboolean ranges_inst_jit = FALSE; +gboolean ranges_inst_dynamic_load = TRUE; static GArray *module_ranges = NULL; static GArray *libs_ranges = NULL; @@ -25,6 +26,7 @@ static GArray *jit_ranges = NULL; static GArray *include_ranges = NULL; static GArray *exclude_ranges = NULL; static GArray *ranges = NULL; +static GArray *whole_memory_ranges = NULL; static void convert_address_token(gchar *token, GumMemoryRange *range) { @@ -387,6 +389,21 @@ static GArray *collect_jit_ranges(void) { } +static GArray *collect_whole_mem_ranges(void) { + + GArray *result; + GumMemoryRange range; + result = g_array_new(false, false, sizeof(GumMemoryRange)); + + range.base_address = 0; + range.size = G_MAXULONG; + + g_array_append_val(result, range); + + return result; + +} + static gboolean intersect_range(GumMemoryRange *rr, GumMemoryRange *ra, GumMemoryRange *rb) { @@ -574,11 +591,17 @@ 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 (getenv("AFL_FRIDA_INST_NO_DYNAMIC_LOAD") != NULL) { + + ranges_inst_dynamic_load = FALSE; + + } if (ranges_debug_maps) { ranges_print_debug_maps(); } include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES"); + whole_memory_ranges = collect_whole_mem_ranges(); } @@ -628,10 +651,20 @@ void ranges_init(void) { print_ranges("step4", step4); /* - * After step4, we have the total ranges to be instrumented, we now subtract - * that from the original ranges of the modules to configure stalker. + * 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. */ - step5 = subtract_ranges(module_ranges, step4); + if (ranges_inst_dynamic_load) { + + step5 = subtract_ranges(module_ranges, step4); + + } else { + + step5 = subtract_ranges(whole_memory_ranges, step4); + + } + print_ranges("step5", step5); ranges = merge_ranges(step5); |