diff options
author | Maik Betka <9078425+voidptr127@users.noreply.github.com> | 2023-04-21 11:31:22 +0200 |
---|---|---|
committer | Maik Betka <9078425+voidptr127@users.noreply.github.com> | 2023-04-21 11:31:22 +0200 |
commit | 7101ffa1ae79e15d70905b09decbe69cdf53367b (patch) | |
tree | fd34b5686a4522dd6d29c9a40cee3d9826b2c7c6 /frida_mode/src | |
parent | 9ab902402cd33156257fc0355c0105e7e03f5ba3 (diff) | |
parent | 4e5f42cab6b8c501eeaf76ec7ca920089f6e0f3a (diff) | |
download | afl++-7101ffa1ae79e15d70905b09decbe69cdf53367b.tar.gz |
Merge remote-tracking branch 'origin/dev' into atnwalk
# Conflicts: # include/afl-fuzz.h # src/afl-fuzz-run.c
Diffstat (limited to 'frida_mode/src')
-rw-r--r-- | frida_mode/src/cmplog/cmplog_arm64.c | 5 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog_x64.c | 5 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog_x86.c | 5 | ||||
-rw-r--r-- | frida_mode/src/ctx/ctx_arm32.c | 2 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument.c | 5 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm32.c | 90 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm64.c | 65 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x64.c | 49 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x86.c | 51 | ||||
-rw-r--r-- | frida_mode/src/js/api.js | 7 | ||||
-rw-r--r-- | frida_mode/src/js/js.c | 8 | ||||
-rw-r--r-- | frida_mode/src/js/js_api.c | 7 | ||||
-rw-r--r-- | frida_mode/src/prefetch.c | 1 | ||||
-rw-r--r-- | frida_mode/src/stats/stats_arm32.c | 1 |
14 files changed, 247 insertions, 54 deletions
diff --git a/frida_mode/src/cmplog/cmplog_arm64.c b/frida_mode/src/cmplog/cmplog_arm64.c index 5792cbfa..095dc242 100644 --- a/frida_mode/src/cmplog/cmplog_arm64.c +++ b/frida_mode/src/cmplog/cmplog_arm64.c @@ -204,10 +204,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, gsize address = context->pc; - register uintptr_t k = (uintptr_t)address; - - k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 1; + register uintptr_t k = instrument_get_offset_hash(GUM_ADDRESS(address)); if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) __afl_cmp_map->headers[k].hits = 0; diff --git a/frida_mode/src/cmplog/cmplog_x64.c b/frida_mode/src/cmplog/cmplog_x64.c index 17912648..ce6b8681 100644 --- a/frida_mode/src/cmplog/cmplog_x64.c +++ b/frida_mode/src/cmplog/cmplog_x64.c @@ -188,10 +188,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, gsize address = ctx_read_reg(context, X86_REG_RIP); - register uintptr_t k = (uintptr_t)address; - - k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 7; + register uintptr_t k = instrument_get_offset_hash(GUM_ADDRESS(address)); if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) __afl_cmp_map->headers[k].hits = 0; diff --git a/frida_mode/src/cmplog/cmplog_x86.c b/frida_mode/src/cmplog/cmplog_x86.c index a3a02457..fa06d611 100644 --- a/frida_mode/src/cmplog/cmplog_x86.c +++ b/frida_mode/src/cmplog/cmplog_x86.c @@ -193,10 +193,7 @@ static void cmplog_handle_cmp_sub(GumCpuContext *context, gsize operand1, gsize address = ctx_read_reg(context, X86_REG_EIP); - register uintptr_t k = (uintptr_t)address; - - k = (k >> 4) ^ (k << 8); - k &= CMP_MAP_W - 1; + register uintptr_t k = instrument_get_offset_hash(GUM_ADDRESS(address)); if (__afl_cmp_map->headers[k].type != CMP_TYPE_INS) __afl_cmp_map->headers[k].hits = 0; diff --git a/frida_mode/src/ctx/ctx_arm32.c b/frida_mode/src/ctx/ctx_arm32.c index 28fc706b..0e5b25a4 100644 --- a/frida_mode/src/ctx/ctx_arm32.c +++ b/frida_mode/src/ctx/ctx_arm32.c @@ -7,6 +7,8 @@ gsize ctx_read_reg(GumArmCpuContext *ctx, arm_reg reg) { + UNUSED_PARAMETER(ctx); + UNUSED_PARAMETER(reg); FFATAL("ctx_read_reg unimplemented for this architecture"); } diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index e1e4ac22..a6aac666 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -27,6 +27,7 @@ gboolean instrument_optimize = false; gboolean instrument_unique = false; guint64 instrument_hash_zero = 0; guint64 instrument_hash_seed = 0; +gboolean instrument_suppress = false; gboolean instrument_use_fixed_seed = FALSE; guint64 instrument_fixed_seed = 0; @@ -290,6 +291,7 @@ void instrument_config(void) { (getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE")); instrument_coverage_insn = (getenv("AFL_FRIDA_INST_INSN") != NULL); instrument_regs_filename = getenv("AFL_FRIDA_INST_REGS_FILE"); + instrument_suppress = (getenv("AFL_FRIDA_INST_NO_SUPPRESS") == NULL); instrument_debug_config(); instrument_coverage_config(); @@ -321,6 +323,9 @@ void instrument_init(void) { FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]", instrument_coverage_insn ? 'X' : ' '); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "suppression:" cYEL " [%c]", + instrument_suppress ? 'X' : ' '); + if (instrument_tracing && instrument_optimize) { WARNF("AFL_FRIDA_INST_TRACE implies AFL_FRIDA_INST_NO_OPTIMIZE"); diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index f2e825ee..51f78a35 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -1,6 +1,7 @@ #include "frida-gumjs.h" #include "instrument.h" +#include "stalker.h" #include "util.h" #if defined(__arm__) @@ -8,8 +9,9 @@ #define PAGE_MASK (~(GUM_ADDRESS(0xfff))) #define PAGE_ALIGNED(x) ((GUM_ADDRESS(x) & PAGE_MASK) == GUM_ADDRESS(x)) -gboolean instrument_cache_enabled = FALSE; -gsize instrument_cache_size = 0; +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; +static GHashTable *coverage_blocks = NULL; extern __thread guint64 instrument_previous_pc; @@ -22,7 +24,24 @@ typedef struct { // shared_mem[cur_location ^ prev_location]++; // prev_location = cur_location >> 1; - /* We can remove this branch when we add support for branch suppression */ + // str r0, [sp, #-128] ; 0xffffff80 + // str r1, [sp, #-132] ; 0xffffff7c + // ldr r0, [pc, #-20] ; 0xf691b29c + // ldrh r1, [r0] + // movw r0, #33222 ; 0x81c6 + // eor r0, r0, r1 + // ldr r1, [pc, #-40] ; 0xf691b298 + // add r1, r1, r0 + // ldrb r0, [r1] + // add r0, r0, #1 + // add r0, r0, r0, lsr #8 + // strb r0, [r1] + // movw r0, #49379 ; 0xc0e3 + // ldr r1, [pc, #-64] ; 0xf691b29c + // strh r0, [r1] + // ldr r1, [sp, #-132] ; 0xffffff7c + // ldr r0, [sp, #-128] ; 0xffffff80 + uint32_t b_code; /* b imm */ uint8_t *shared_mem; uint64_t *prev_location; @@ -115,6 +134,46 @@ gboolean instrument_is_coverage_optimize_supported(void) { } +static void instrument_coverage_switch(GumStalkerObserver *self, + gpointer from_address, + gpointer start_address, void *from_insn, + gpointer *target) { + + UNUSED_PARAMETER(self); + UNUSED_PARAMETER(from_address); + UNUSED_PARAMETER(start_address); + UNUSED_PARAMETER(from_insn); + + if (!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target))) { + + return; + + } + + *target = + (guint8 *)*target + G_STRUCT_OFFSET(afl_log_code_asm_t, str_r0_sp_rz); + +} + +static void instrument_coverage_suppress_init(void) { + + static gboolean initialized = false; + if (initialized) { return; } + initialized = true; + + GumStalkerObserver *observer = stalker_get_observer(); + GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer); + iface->switch_callback = instrument_coverage_switch; + + coverage_blocks = g_hash_table_new(g_direct_hash, g_direct_equal); + if (coverage_blocks == NULL) { + + FATAL("Failed to g_hash_table_new, errno: %d", errno); + + } + +} + static void patch_t3_insn(uint32_t *insn, uint16_t val) { uint32_t orig = GUINT32_FROM_LE(*insn); @@ -135,14 +194,17 @@ void instrument_coverage_optimize(const cs_insn *instr, guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); gsize map_size_pow2; gsize area_offset_ror; - GumAddress code_addr = 0; - // gum_arm64_writer_put_brk_imm(cw, 0x0); - - code_addr = cw->pc; + instrument_coverage_suppress_init(); block_start = GSIZE_TO_POINTER(GUM_ADDRESS(cw->code)); + if (!g_hash_table_add(coverage_blocks, block_start)) { + + FATAL("Failed - g_hash_table_add"); + + } + code.code = template; g_assert(PAGE_ALIGNED(__afl_area_ptr)); @@ -211,7 +273,19 @@ void instrument_flush(GumStalkerOutput *output) { gpointer instrument_cur(GumStalkerOutput *output) { - return gum_arm_writer_cur(output->writer.arm); + gpointer curr = NULL; + + if (output->encoding == GUM_INSTRUCTION_SPECIAL) { + + curr = gum_thumb_writer_cur(output->writer.thumb); + + } else { + + curr = gum_arm_writer_cur(output->writer.arm); + + } + + return curr; } diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 87811b38..4372861d 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -156,26 +156,55 @@ static gboolean instrument_is_deterministic(const cs_insn *from_insn) { } +cs_insn *instrument_disassemble(gconstpointer address) { + + csh capstone; + cs_insn *insn = NULL; + + cs_open(CS_ARCH_ARM64, GUM_DEFAULT_CS_ENDIAN, &capstone); + cs_option(capstone, CS_OPT_DETAIL, CS_OPT_ON); + + cs_disasm(capstone, address, 16, GPOINTER_TO_SIZE(address), 1, &insn); + + cs_close(&capstone); + + return insn; + +} + static void instrument_coverage_switch(GumStalkerObserver *self, gpointer from_address, - gpointer start_address, - const cs_insn *from_insn, - gpointer *target) { + gpointer start_address, void *from_insn, + gpointer *target) { UNUSED_PARAMETER(self); UNUSED_PARAMETER(from_address); UNUSED_PARAMETER(start_address); - gsize fixup_offset; + cs_insn *insn = NULL; + gboolean deterministic = FALSE; + gsize fixup_offset; if (!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target)) && - !g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target + 4))) { + !g_hash_table_contains(coverage_blocks, + GSIZE_TO_POINTER((guint8 *)*target + 4))) { return; } - if (instrument_is_deterministic(from_insn)) { return; } + insn = instrument_disassemble(from_insn); + deterministic = instrument_is_deterministic(insn); + cs_free(insn, 1); + + /* + * If the branch is deterministic, then we should start execution at the + * begining of the block. From here, we will branch and skip the coverage + * code and jump right to the target code of the instrumented block. + * Otherwise, if the branch is non-deterministic, then we need to branch + * part way into the block to where the coverage instrumentation starts. + */ + if (deterministic) { return; } /* * Since each block is prefixed with a restoration prologue, we need to be @@ -208,7 +237,7 @@ static void instrument_coverage_switch(GumStalkerObserver *self, */ fixup_offset = GUM_RESTORATION_PROLOG_SIZE + G_STRUCT_OFFSET(afl_log_code_asm_t, restoration_prolog); - *target += fixup_offset; + *target = (guint8 *)*target + fixup_offset; } @@ -284,7 +313,7 @@ void instrument_coverage_optimize(const cs_insn *instr, // gum_arm64_writer_put_brk_imm(cw, 0x0); - instrument_coverage_suppress_init(); + if (instrument_suppress) { instrument_coverage_suppress_init(); } code_addr = cw->pc; @@ -304,9 +333,13 @@ void instrument_coverage_optimize(const cs_insn *instr, block_start = GSIZE_TO_POINTER(GUM_ADDRESS(cw->code) - GUM_RESTORATION_PROLOG_SIZE); - if (!g_hash_table_add(coverage_blocks, block_start)) { + if (instrument_suppress) { + + if (!g_hash_table_add(coverage_blocks, block_start)) { - FATAL("Failed - g_hash_table_add"); + FATAL("Failed - g_hash_table_add"); + + } } @@ -342,7 +375,17 @@ void instrument_coverage_optimize(const cs_insn *instr, code.code.mov_x1_curr_loc_shr_1 |= (area_offset_ror << 5); - gum_arm64_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); + 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); + + } } diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index 13ced4a3..8338f8e7 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -171,11 +171,11 @@ void instrument_coverage_optimize_init(void) { } -static void instrument_coverage_switch(GumStalkerObserver *self, - gpointer from_address, - gpointer start_address, - const cs_insn *from_insn, - gpointer *target) { +static void instrument_coverage_switch_insn(GumStalkerObserver *self, + gpointer from_address, + gpointer start_address, + const cs_insn *from_insn, + gpointer *target) { UNUSED_PARAMETER(self); UNUSED_PARAMETER(from_address); @@ -224,6 +224,35 @@ static void instrument_coverage_switch(GumStalkerObserver *self, } +cs_insn *instrument_disassemble(gconstpointer address) { + + csh capstone; + cs_insn *insn = NULL; + + cs_open(CS_ARCH_X86, GUM_CPU_MODE, &capstone); + cs_option(capstone, CS_OPT_DETAIL, CS_OPT_ON); + + cs_disasm(capstone, address, 16, GPOINTER_TO_SIZE(address), 1, &insn); + + cs_close(&capstone); + + return insn; + +} + +static void instrument_coverage_switch(GumStalkerObserver *self, + gpointer from_address, + gpointer start_address, void *from_insn, + gpointer *target) { + + if (from_insn == NULL) { return; } + cs_insn *insn = instrument_disassemble(from_insn); + instrument_coverage_switch_insn(self, from_address, start_address, insn, + target); + cs_free(insn, 1); + +} + static void instrument_coverage_suppress_init(void) { static gboolean initialized = false; @@ -351,11 +380,15 @@ void instrument_coverage_optimize(const cs_insn *instr, } - instrument_coverage_suppress_init(); + if (instrument_suppress) { + + instrument_coverage_suppress_init(); + + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { - if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + FATAL("Failed - g_hash_table_add"); - FATAL("Failed - g_hash_table_add"); + } } diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index eabd5be4..4667ea29 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -83,11 +83,11 @@ gboolean instrument_is_coverage_optimize_supported(void) { } -static void instrument_coverage_switch(GumStalkerObserver *self, - gpointer from_address, - gpointer start_address, - const cs_insn *from_insn, - gpointer *target) { +static void instrument_coverage_switch_insn(GumStalkerObserver *self, + gpointer from_address, + gpointer start_address, + const cs_insn *from_insn, + gpointer *target) { UNUSED_PARAMETER(self); UNUSED_PARAMETER(from_address); @@ -130,6 +130,35 @@ static void instrument_coverage_switch(GumStalkerObserver *self, } +cs_insn *instrument_disassemble(gconstpointer address) { + + csh capstone; + cs_insn *insn = NULL; + + cs_open(CS_ARCH_X86, GUM_CPU_MODE, &capstone); + cs_option(capstone, CS_OPT_DETAIL, CS_OPT_ON); + + cs_disasm(capstone, address, 16, GPOINTER_TO_SIZE(address), 1, &insn); + + cs_close(&capstone); + + return insn; + +} + +static void instrument_coverage_switch(GumStalkerObserver *self, + gpointer from_address, + gpointer start_address, void *from_insn, + gpointer *target) { + + if (from_insn == NULL) { return; } + cs_insn *insn = instrument_disassemble(from_insn); + instrument_coverage_switch_insn(self, from_address, start_address, insn, + target); + cs_free(insn, 1); + +} + static void instrument_coverage_suppress_init(void) { static gboolean initialized = false; @@ -174,13 +203,17 @@ void instrument_coverage_optimize(const cs_insn *instr, code.code = template; - instrument_coverage_suppress_init(); + if (instrument_suppress) { + + instrument_coverage_suppress_init(); + + // gum_x86_writer_put_breakpoint(cw); - // gum_x86_writer_put_breakpoint(cw); + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { - if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + FATAL("Failed - g_hash_table_add"); - FATAL("Failed - g_hash_table_add"); + } } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index fce7a5d7..f9ea1ffb 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -170,6 +170,12 @@ class Afl { static setInstrumentSeed(seed) { Afl.jsApiSetInstrumentSeed(seed); } + /* + * See `AFL_FRIDA_INST_NO_SUPPRESS` + */ + static setInstrumentSuppressDisable() { + Afl.jsApiSetInstrumentSuppressDisable(); + } /** * See `AFL_FRIDA_INST_TRACE_UNIQUE`. */ @@ -339,6 +345,7 @@ Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_li 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"]); +Afl.jsApiSetInstrumentSuppressDisable = Afl.jsApiGetFunction("js_api_set_instrument_suppress_disable", "void", []); Afl.jsApiSetInstrumentTrace = Afl.jsApiGetFunction("js_api_set_instrument_trace", "void", []); Afl.jsApiSetInstrumentTraceUnique = Afl.jsApiGetFunction("js_api_set_instrument_trace_unique", "void", []); Afl.jsApiSetInstrumentUnstableCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_unstable_coverage_file", "void", ["pointer"]); diff --git a/frida_mode/src/js/js.c b/frida_mode/src/js/js.c index 6bc31864..25187694 100644 --- a/frida_mode/src/js/js.c +++ b/frida_mode/src/js/js.c @@ -18,10 +18,8 @@ static GumScriptScheduler *scheduler; static GMainContext *context; static GMainLoop *main_loop; -static void js_msg(GumScript *script, const gchar *message, GBytes *data, - gpointer user_data) { +static void js_msg(const gchar *message, GBytes *data, gpointer user_data) { - UNUSED_PARAMETER(script); UNUSED_PARAMETER(data); UNUSED_PARAMETER(user_data); FOKF("%s", message); @@ -124,8 +122,8 @@ void js_start(void) { main_loop = g_main_loop_new(context, true); g_main_context_push_thread_default(context); - gum_script_backend_create(backend, "example", source, cancellable, create_cb, - &error); + gum_script_backend_create(backend, "example", source, NULL, cancellable, + create_cb, &error); while (g_main_context_pending(context)) g_main_context_iteration(context, FALSE); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 01bba4ff..2e996c1c 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -289,6 +289,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_cache_size( } +__attribute__((visibility("default"))) void +js_api_set_instrument_suppress_disable(void) { + + instrument_suppress = false; + +} + __attribute__((visibility("default"))) void js_api_set_js_main_hook( const js_main_hook_t hook) { diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index 905e0ae9..f093cd53 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -29,7 +29,6 @@ gboolean prefetch_enable = TRUE; gboolean prefetch_backpatch = TRUE; static prefetch_data_t *prefetch_data = NULL; -static int prefetch_shm_id = -1; static GHashTable *cant_prefetch = NULL; diff --git a/frida_mode/src/stats/stats_arm32.c b/frida_mode/src/stats/stats_arm32.c index bd652aa3..6c72a476 100644 --- a/frida_mode/src/stats/stats_arm32.c +++ b/frida_mode/src/stats/stats_arm32.c @@ -13,6 +13,7 @@ void starts_arch_init(void) { void stats_write_arch(stats_data_t *data) { + UNUSED_PARAMETER(data); FFATAL("Stats not supported on this architecture"); } |