From 98e883875548c12d022adf556f9a95babb38c200 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Aug 2022 18:46:29 +0100 Subject: [PATCH 01/12] Fix formatting --- frida_mode/hook/frida_hook.c | 2 +- frida_mode/include/instrument.h | 2 +- frida_mode/src/instrument/instrument.c | 11 ++++++++++- frida_mode/src/instrument/instrument_arm32.c | 2 ++ frida_mode/src/instrument/instrument_arm64.c | 2 ++ frida_mode/src/instrument/instrument_debug.c | 2 ++ frida_mode/src/instrument/instrument_x64.c | 2 ++ frida_mode/src/instrument/instrument_x86.c | 2 ++ frida_mode/src/js/js_api.c | 2 ++ 9 files changed, 24 insertions(+), 3 deletions(-) diff --git a/frida_mode/hook/frida_hook.c b/frida_mode/hook/frida_hook.c index 3bfdb207..86c6f9d4 100644 --- a/frida_mode/hook/frida_hook.c +++ b/frida_mode/hook/frida_hook.c @@ -31,7 +31,7 @@ __attribute__((visibility("default"))) void afl_persistent_hook( // do a length check matching the target! void **esp = (void **)regs->esp; - void * arg1 = esp[0]; + void *arg1 = esp[0]; void **arg2 = &esp[1]; memcpy(arg1, input_buf, input_buf_len); *arg2 = (void *)input_buf_len; diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index b85aa571..4b268e81 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -13,7 +13,7 @@ extern gboolean instrument_unique; extern guint64 instrument_hash_zero; extern char *instrument_coverage_unstable_filename; extern gboolean instrument_coverage_insn; -extern char * instrument_regs_filename; +extern char *instrument_regs_filename; extern gboolean instrument_use_fixed_seed; extern guint64 instrument_fixed_seed; diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 93c498e8..0e286eab 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -33,7 +33,7 @@ gboolean instrument_use_fixed_seed = FALSE; guint64 instrument_fixed_seed = 0; char *instrument_coverage_unstable_filename = NULL; gboolean instrument_coverage_insn = FALSE; -char * instrument_regs_filename = NULL; +char *instrument_regs_filename = NULL; static GumStalkerTransformer *transformer = NULL; @@ -237,9 +237,12 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } if (unlikely(instrument_regs_filename != NULL)) { + gum_stalker_iterator_put_callout(iterator, instrument_write_regs, (void *)(size_t)regs_fd, NULL); + } + } } @@ -274,6 +277,7 @@ static void instrument_basic_block(GumStalkerIterator *iterator, instrument_flush(output); instrument_debug_end(output); instrument_coverage_end(instr->address + instr->size); + } void instrument_config(void) { @@ -404,6 +408,7 @@ void instrument_init(void) { instrument_regs_filename == NULL ? " " : instrument_regs_filename); if (instrument_regs_filename != NULL) { + char *path = g_canonicalize_filename(instrument_regs_filename, g_get_current_dir()); @@ -415,6 +420,7 @@ void instrument_init(void) { if (regs_fd < 0) { FFATAL("Failed to open regs file '%s'", path); } g_free(path); + } asan_init(); @@ -444,6 +450,7 @@ void instrument_on_fork() { } void instrument_regs_format(int fd, char *format, ...) { + va_list ap; char buffer[4096] = {0}; int ret; @@ -458,4 +465,6 @@ void instrument_regs_format(int fd, char *format, ...) { len = strnlen(buffer, sizeof(buffer)); IGNORED_RETURN(write(fd, buffer, len)); + } + diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 73923326..4525e83d 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -81,6 +81,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { } void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { + int fd = (int)user_data; instrument_regs_format(fd, "r0 : 0x%08x, r1 : 0x%08x, r2 : 0x%08x, r3 : 0x%08x\n", @@ -97,6 +98,7 @@ void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { fd, "r12: 0x%08x, sp : 0x%08x, lr : 0x%08x, pc : 0x%08x\n", cpu_context->r12, cpu_context->sp, cpu_context->lr, cpu_context->pc); instrument_regs_format(fd, "cpsr: 0x%08x\n\n", cpu_context->cpsr); + } #endif diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 9157f8f5..87811b38 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -407,6 +407,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { } void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { + int fd = (int)(size_t)user_data; instrument_regs_format( fd, "x0 : 0x%016x, x1 : 0x%016x, x2 : 0x%016x, x3 : 0x%016x\n", @@ -440,6 +441,7 @@ void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { fd, "x28: 0x%016x, fp : 0x%016x, lr : 0x%016x, sp : 0x%016x\n", cpu_context->x[28], cpu_context->fp, cpu_context->lr, cpu_context->sp); instrument_regs_format(fd, "pc : 0x%016x\n\n", cpu_context->pc); + } #endif diff --git a/frida_mode/src/instrument/instrument_debug.c b/frida_mode/src/instrument/instrument_debug.c index 17245d65..5577a588 100644 --- a/frida_mode/src/instrument/instrument_debug.c +++ b/frida_mode/src/instrument/instrument_debug.c @@ -63,12 +63,14 @@ static void instrument_disasm(guint8 *start, guint8 *end, count = cs_disasm(capstone, curr, size, GPOINTER_TO_SIZE(curr), 0, &insn); if (insn == NULL) { + instrument_debug("\t0x%" G_GINT64_MODIFIER "x\t* 0x%016" G_GSIZE_MODIFIER "x\n", (uint64_t)(size_t)curr, *(size_t *)curr); len += sizeof(size_t); continue; + } for (i = 0; i != count; i++) { diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index 9d754082..13ced4a3 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -469,6 +469,7 @@ gpointer instrument_cur(GumStalkerOutput *output) { } void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { + int fd = (int)(size_t)user_data; instrument_regs_format( fd, "rax: 0x%016x, rbx: 0x%016x, rcx: 0x%016x, rdx: 0x%016x\n", @@ -483,6 +484,7 @@ void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { fd, "r12: 0x%016x, r13: 0x%016x, r14: 0x%016x, r15: 0x%016x\n", cpu_context->r12, cpu_context->r13, cpu_context->r14, cpu_context->r15); instrument_regs_format(fd, "rip: 0x%016x\n\n", cpu_context->rip); + } #endif diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index eb0c7184..eabd5be4 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -271,6 +271,7 @@ void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { } void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { + int fd = (int)(size_t)user_data; instrument_regs_format( fd, "eax: 0x%08x, ebx: 0x%08x, ecx: 0x%08x, edx: 0x%08x\n", @@ -279,6 +280,7 @@ void instrument_write_regs(GumCpuContext *cpu_context, gpointer user_data) { fd, "esi: 0x%08x, edi: 0x%08x, ebp: 0x%08x, esp: 0x%08x\n", cpu_context->esi, cpu_context->edi, cpu_context->ebp, cpu_context->esp); instrument_regs_format(fd, "eip: 0x%08x\n\n", cpu_context->eip); + } #endif diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index d0c0aa60..249f9c96 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -158,7 +158,9 @@ __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize( __attribute__((visibility("default"))) void js_api_set_instrument_regs_file( char *path) { + instrument_regs_filename = g_strdup(path); + } __attribute__((visibility("default"))) void js_api_set_instrument_seed( From 3562de440e53fca7109a314dcc7fe9ab07794e56 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Aug 2022 18:46:29 +0100 Subject: [PATCH 02/12] Changes to add option for absolute coverage data --- frida_mode/README.md | 2 + frida_mode/frida.map | 1 + frida_mode/include/instrument.h | 1 + .../src/instrument/instrument_coverage.c | 150 ++++++++++++++---- frida_mode/src/js/api.js | 7 + frida_mode/src/js/js_api.c | 7 + frida_mode/test/unstable/unstable.c | 7 +- frida_mode/ts/lib/afl.ts | 13 ++ include/envs.h | 1 + 9 files changed, 159 insertions(+), 30 deletions(-) diff --git a/frida_mode/README.md b/frida_mode/README.md index 29f7968b..bfe0948b 100644 --- a/frida_mode/README.md +++ b/frida_mode/README.md @@ -146,6 +146,8 @@ instances run CMPLOG mode and instrumentation of the binary is less frequent QEMU driver to provide a `main` loop for a user provided `LLVMFuzzerTestOneInput`, this option configures the driver to read input from `stdin` rather than using in-memory test cases. +* `AFL_FRIDA_INST_COVERAGE_ABSOLUTE` - Generate coverage files using absolute + virtual addresses rather than relative virtual addresses. * `AFL_FRIDA_INST_COVERAGE_FILE` - File to write DynamoRIO format coverage information (e.g., to be loaded within IDA lighthouse). * `AFL_FRIDA_INST_DEBUG_FILE` - File to write raw assembly of original blocks diff --git a/frida_mode/frida.map b/frida_mode/frida.map index 8e956460..73fff686 100644 --- a/frida_mode/frida.map +++ b/frida_mode/frida.map @@ -13,6 +13,7 @@ js_api_set_debug_maps; js_api_set_entrypoint; js_api_set_instrument_cache_size; + js_api_set_instrument_coverage_absolute; js_api_set_instrument_coverage_file; js_api_set_instrument_debug_file; js_api_set_instrument_jit; diff --git a/frida_mode/include/instrument.h b/frida_mode/include/instrument.h index 4b268e81..8c93d881 100644 --- a/frida_mode/include/instrument.h +++ b/frida_mode/include/instrument.h @@ -7,6 +7,7 @@ extern char *instrument_debug_filename; extern char *instrument_coverage_filename; +extern bool instrument_coverage_absolute; extern gboolean instrument_tracing; extern gboolean instrument_optimize; extern gboolean instrument_unique; diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c index 07d4d622..25913585 100644 --- a/frida_mode/src/instrument/instrument_coverage.c +++ b/frida_mode/src/instrument/instrument_coverage.c @@ -9,6 +9,7 @@ #include "util.h" char *instrument_coverage_filename = NULL; +bool instrument_coverage_absolute = false; static int normal_coverage_fd = -1; static int normal_coverage_pipes[2] = {-1, -1}; @@ -237,6 +238,18 @@ static void instrument_coverage_mark(void *key, void *value, void *user_data) { } +static void instrument_coverage_mark_first(void *key, void *value, + void *user_data) { + + UNUSED_PARAMETER(key); + coverage_range_t * module = (coverage_range_t *)user_data; + normal_coverage_data_t *val = (normal_coverage_data_t *)value; + + val->module = module; + module->count++; + +} + static void coverage_write(int fd, void *data, size_t size) { ssize_t written; @@ -404,28 +417,69 @@ static void instrument_coverage_normal_run() { instrument_coverage_print("Coverage - Preparing\n"); - GArray *coverage_modules = coverage_get_modules(); + if (instrument_coverage_absolute) { - guint size = g_hash_table_size(coverage_hash); - instrument_coverage_print("Coverage - Total Entries: %u\n", size); + guint size = g_hash_table_size(coverage_hash); + instrument_coverage_print("Coverage - Total Entries: %u\n", size); - coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0}; + coverage_range_t module = { - g_hash_table_foreach(coverage_hash, instrument_coverage_mark, &ctx); - instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count); + .base_address = GUM_ADDRESS(0), + .limit = GUM_ADDRESS(-1), + .size = GUM_ADDRESS(-1), + .path = "absolute", + .offset = 0, + .is_executable = true, + .count = size, + .id = 0, - guint coverage_marked_modules = coverage_mark_modules(coverage_modules); - instrument_coverage_print("Coverage - Marked Modules: %u\n", - coverage_marked_modules); + }; - coverage_write_header(normal_coverage_fd, coverage_marked_modules); - coverage_write_modules(normal_coverage_fd, coverage_modules); - coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", ctx.count); - g_hash_table_foreach(coverage_hash, coverage_write_events, - &normal_coverage_fd); + instrument_coverage_print("Coverage Module - 0x%016" G_GINT64_MODIFIER + "X - 0x%016" G_GINT64_MODIFIER "X (%s)\n", + module.base_address, module.limit, module.path); + + GArray *coverage_modules = + g_array_sized_new(false, false, sizeof(coverage_range_t), 1); + g_array_append_val(coverage_modules, module); + + g_hash_table_foreach(coverage_hash, instrument_coverage_mark_first, + &module); + + coverage_write_header(normal_coverage_fd, 1); + coverage_write_modules(normal_coverage_fd, coverage_modules); + coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", size); + g_hash_table_foreach(coverage_hash, coverage_write_events, + &normal_coverage_fd); + + } else { + + GArray *coverage_modules = coverage_get_modules(); + + guint size = g_hash_table_size(coverage_hash); + instrument_coverage_print("Coverage - Total Entries: %u\n", size); + + coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0}; + + /* For each coverage event in the hashtable associate it with a module and + * count the number of entries per module */ + g_hash_table_foreach(coverage_hash, instrument_coverage_mark, &ctx); + instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count); + + /* For each module with coverage events assign it an incrementing number */ + guint coverage_marked_modules = coverage_mark_modules(coverage_modules); + instrument_coverage_print("Coverage - Marked Modules: %u\n", + coverage_marked_modules); + + coverage_write_header(normal_coverage_fd, coverage_marked_modules); + coverage_write_modules(normal_coverage_fd, coverage_modules); + coverage_format(normal_coverage_fd, "BB Table: %u bbs\n", ctx.count); + g_hash_table_foreach(coverage_hash, coverage_write_events, + &normal_coverage_fd); + + } g_hash_table_unref(coverage_hash); - instrument_coverage_print("Coverage - Completed\n"); } @@ -622,8 +676,6 @@ static void instrument_coverage_unstable_run(void) { instrument_coverage_print("Coverage - Preparing\n"); - GArray *coverage_modules = coverage_get_modules(); - instrument_coverage_print("Found edges: %u\n", edges); GArray *unstable_edge_ids = instrument_coverage_unstable_read_unstable_ids(); @@ -634,20 +686,60 @@ static void instrument_coverage_unstable_run(void) { guint size = g_hash_table_size(unstable_blocks); instrument_coverage_print("Unstable blocks: %u\n", size); - coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0}; + if (instrument_coverage_absolute) { - g_hash_table_foreach(unstable_blocks, instrument_coverage_mark, &ctx); - instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count); + instrument_coverage_print("Coverage - Total Entries: %u\n", size); - guint coverage_marked_modules = coverage_mark_modules(coverage_modules); - instrument_coverage_print("Coverage - Marked Modules: %u\n", - coverage_marked_modules); + coverage_range_t module = { - coverage_write_header(unstable_coverage_fd, coverage_marked_modules); - coverage_write_modules(unstable_coverage_fd, coverage_modules); - coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", ctx.count); - g_hash_table_foreach(unstable_blocks, coverage_write_events, - &unstable_coverage_fd); + .base_address = GUM_ADDRESS(0), + .limit = GUM_ADDRESS(-1), + .size = GUM_ADDRESS(-1), + .path = "absolute", + .offset = 0, + .is_executable = true, + .count = size, + .id = 0, + + }; + + instrument_coverage_print("Coverage Module - 0x%016" G_GINT64_MODIFIER + "X - 0x%016" G_GINT64_MODIFIER "X (%s)\n", + module.base_address, module.limit, module.path); + + GArray *coverage_modules = + g_array_sized_new(false, false, sizeof(coverage_range_t), 1); + g_array_append_val(coverage_modules, module); + + g_hash_table_foreach(unstable_blocks, instrument_coverage_mark_first, + &module); + + coverage_write_header(unstable_coverage_fd, 1); + coverage_write_modules(unstable_coverage_fd, coverage_modules); + coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", size); + g_hash_table_foreach(unstable_blocks, coverage_write_events, + &unstable_coverage_fd); + + } else { + + GArray *coverage_modules = coverage_get_modules(); + + coverage_mark_ctx_t ctx = {.modules = coverage_modules, .count = 0}; + + g_hash_table_foreach(unstable_blocks, instrument_coverage_mark, &ctx); + instrument_coverage_print("Coverage - Marked Entries: %u\n", ctx.count); + + guint coverage_marked_modules = coverage_mark_modules(coverage_modules); + instrument_coverage_print("Coverage - Marked Modules: %u\n", + coverage_marked_modules); + + coverage_write_header(unstable_coverage_fd, coverage_marked_modules); + coverage_write_modules(unstable_coverage_fd, coverage_modules); + coverage_format(unstable_coverage_fd, "BB Table: %u bbs\n", ctx.count); + g_hash_table_foreach(unstable_blocks, coverage_write_events, + &unstable_coverage_fd); + + } g_hash_table_unref(unstable_blocks); g_array_free(unstable_edge_ids, TRUE); @@ -660,6 +752,8 @@ static void instrument_coverage_unstable_run(void) { void instrument_coverage_config(void) { instrument_coverage_filename = getenv("AFL_FRIDA_INST_COVERAGE_FILE"); + instrument_coverage_absolute = + (getenv("AFL_FRIDA_INST_COVERAGE_ABSOLUTE") != NULL); } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 721ef82c..fce7a5d7 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -104,6 +104,12 @@ class Afl { static setInstrumentCacheSize(size) { Afl.jsApiSetInstrumentCacheSize(size); } + /** + * See `AFL_FRIDA_INST_COVERAGE_ABSOLUTE`. + */ + static setInstrumentCoverageAbsolute() { + Afl.jsApiSetInstrumentCoverageAbsolute(); + } /** * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * as an argument. @@ -324,6 +330,7 @@ Afl.jsApiSetCacheDisable = Afl.jsApiGetFunction("js_api_set_cache_disable", "voi Afl.jsApiSetDebugMaps = Afl.jsApiGetFunction("js_api_set_debug_maps", "void", []); Afl.jsApiSetEntryPoint = Afl.jsApiGetFunction("js_api_set_entrypoint", "void", ["pointer"]); Afl.jsApiSetInstrumentCacheSize = Afl.jsApiGetFunction("js_api_set_instrument_cache_size", "void", ["size_t"]); +Afl.jsApiSetInstrumentCoverageAbsolute = Afl.jsApiGetFunction("js_api_set_instrument_coverage_absolute", "void", []); Afl.jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction("js_api_set_instrument_coverage_file", "void", ["pointer"]); Afl.jsApiSetInstrumentDebugFile = Afl.jsApiGetFunction("js_api_set_instrument_debug_file", "void", ["pointer"]); Afl.jsApiSetInstrumentInstructions = Afl.jsApiGetFunction("js_api_set_instrument_instructions", "void", []); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 249f9c96..01bba4ff 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -115,6 +115,13 @@ __attribute__((visibility("default"))) void js_api_set_instrument_libraries() { } +__attribute__((visibility("default"))) void +js_api_set_instrument_coverage_absolute(void) { + + instrument_coverage_absolute = true; + +} + __attribute__((visibility("default"))) void js_api_set_instrument_coverage_file( char *path) { diff --git a/frida_mode/test/unstable/unstable.c b/frida_mode/test/unstable/unstable.c index 915e283f..7d16c26c 100644 --- a/frida_mode/test/unstable/unstable.c +++ b/frida_mode/test/unstable/unstable.c @@ -14,6 +14,7 @@ #include #include #include +#include #ifdef __APPLE__ #define TESTINSTR_SECTION @@ -25,8 +26,10 @@ void LLVMFuzzerTestOneInput(const uint8_t* data, size_t size) { if (size < 1) return; - int r = rand(); - if ((r % 2) == 0) { + struct timeval tv = {0}; + if (gettimeofday(&tv, NULL) < 0) return; + + if ((tv.tv_usec % 2) == 0) { printf ("Hooray all even\n"); } else { printf ("Hmm that's odd\n"); diff --git a/frida_mode/ts/lib/afl.ts b/frida_mode/ts/lib/afl.ts index 455d4305..7a83c0fb 100644 --- a/frida_mode/ts/lib/afl.ts +++ b/frida_mode/ts/lib/afl.ts @@ -125,6 +125,13 @@ class Afl { Afl.jsApiSetInstrumentCacheSize(size); } + /** + * See `AFL_FRIDA_INST_COVERAGE_ABSOLUTE`. + */ + public static setInstrumentCoverageAbsolute(): void { + Afl.jsApiSetInstrumentCoverageAbsolute(); + } + /** * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * as an argument. @@ -398,6 +405,12 @@ class Afl { "void", ["size_t"]); + private static readonly jsApiSetInstrumentCoverageAbsolute = Afl.jsApiGetFunction( + "js_api_set_instrument_coverage_absolute", + "void", + [] + ); + private static readonly jsApiSetInstrumentCoverageFile = Afl.jsApiGetFunction( "js_api_set_instrument_coverage_file", "void", diff --git a/include/envs.h b/include/envs.h index 853edbd9..52f2d09b 100644 --- a/include/envs.h +++ b/include/envs.h @@ -58,6 +58,7 @@ static char *afl_environment_variables[] = { "AFL_FRIDA_DRIVER_NO_HOOK", "AFL_FRIDA_EXCLUDE_RANGES", "AFL_FRIDA_INST_CACHE_SIZE", + "AFL_FRIDA_INST_COVERAGE_ABSOLUTE", "AFL_FRIDA_INST_COVERAGE_FILE", "AFL_FRIDA_INST_DEBUG_FILE", "AFL_FRIDA_INST_INSN", From 7bdb22c70cd1ffcc06786f117c92326f430650b2 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Aug 2022 18:46:29 +0100 Subject: [PATCH 03/12] Added build of FRIDA mode shared library to enable embedding --- frida_mode/GNUmakefile | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index bc7df6c0..256bea02 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -43,10 +43,12 @@ endif FRIDA_BUILD_DIR:=$(BUILD_DIR)frida/ FRIDA_TRACE:=$(BUILD_DIR)afl-frida-trace.so +FRIDA_TRACE_LIB:=$(BUILD_DIR)libafl-frida-trace.a FRIDA_TRACE_EMBEDDED:=$(BUILD_DIR)afl-frida-trace-embedded TARGET_CC?=$(CC) TARGET_CXX?=$(CXX) +TARGET_AR?=$(AR) HOST_CC?=$(CC) HOST_CXX?=$(CXX) @@ -110,6 +112,7 @@ endif ifeq "$(ARCH)" "armhf" TARGET_CC:=arm-linux-gnueabihf-gcc TARGET_CXX:=arm-linux-gnueabihf-g++ + TARGET_AR:=arm-linux-gnueabihf-ar endif ifndef OS @@ -157,7 +160,7 @@ BIN2C_SRC:=$(PWD)util/bin2c.c ############################## ALL ############################################# -all: $(FRIDA_TRACE) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN) +all: $(FRIDA_TRACE) $(FRIDA_TRACE_LIB) $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) $(ADDR_BIN) 32: CFLAGS="-m32" LDFLAGS="-m32" ARCH="x86" make all @@ -353,6 +356,15 @@ $(FRIDA_TRACE): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL cp -v $(FRIDA_TRACE) $(ROOT) +$(FRIDA_TRACE_LIB): $(GUM_DEVIT_LIBRARY) $(GUM_DEVIT_HEADER) $(OBJS) $(JS_OBJ) $(AFL_COMPILER_RT_OBJ) $(AFL_PERFORMANCE_OBJ) GNUmakefile | $(BUILD_DIR) + $(TARGET_AR) \ + -rcs \ + $@ \ + $(OBJS) \ + $(JS_OBJ) \ + $(AFL_COMPILER_RT_OBJ) \ + $(AFL_PERFORMANCE_OBJ) \ + ############################# HOOK ############################################# $(AFLPP_FRIDA_DRIVER_HOOK_OBJ): $(AFLPP_FRIDA_DRIVER_HOOK_SRC) $(GUM_DEVIT_HEADER) | $(BUILD_DIR) From 7c50ec5d055508ebb4220976fd54c553224a01eb Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Aug 2022 18:46:29 +0100 Subject: [PATCH 04/12] Added support for ARM32 persistent mode --- frida_mode/src/persistent/persistent_arm32.c | 284 ++++++++++++++++--- 1 file changed, 238 insertions(+), 46 deletions(-) diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index b4e50897..a2b63652 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -1,76 +1,268 @@ #include "frida-gumjs.h" +#include "instrument.h" #include "persistent.h" #include "util.h" #if defined(__arm__) -struct arm_regs { +// struct _GumArmCpuContext { +// guint32 pc; +// guint32 sp; +// guint32 cpsr; - uint32_t r0, r1, r2, r3, r4, r5, r6, r7, r8, r9, r10; +// guint32 r8; +// guint32 r9; +// guint32 r10; +// guint32 r11; +// guint32 r12; - union { +// GumArmVectorReg v[16]; - uint32_t r11; - uint32_t fp; +// guint32 _padding; - }; +// guint32 r[8]; +// guint32 lr; +// }; - union { +// r11 - fp +// r12 - ip +// r13 - sp +// r14 - lr +// r15 - pc - uint32_t r12; - uint32_t ip; - - }; - - union { - - uint32_t r13; - uint32_t sp; - - }; - - union { - - uint32_t r14; - uint32_t lr; - - }; - - union { - - uint32_t r15; - uint32_t pc; - - }; - - uint32_t cpsr; - - uint8_t vfp_zregs[32][16]; - uint32_t vfp_xregs[16]; - -}; - -typedef struct arm_regs arch_api_regs; +static GumCpuContext saved_regs = {0}; +static gpointer saved_lr = NULL; gboolean persistent_is_supported(void) { + return true; +} - return false; +static void instrument_persitent_save_regs(GumArmWriter * cw, + GumCpuContext *regs) { + /* Save Regs */ + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP, + GUM_RED_ZONE_SIZE + sizeof(guint32)); + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs)); + + /* Save r1-r7 */ + for (size_t i = ARM_REG_R1; i < ARM_REG_R8; i++) { + gum_arm_writer_put_str_reg_reg_offset( + cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0])); + } + + /* Save r8-r12 */ + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R8, ARM_REG_R0, + offsetof(GumCpuContext, r8)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R9, ARM_REG_R0, + offsetof(GumCpuContext, r9)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R10, ARM_REG_R0, + offsetof(GumCpuContext, r10)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R11, ARM_REG_R0, + offsetof(GumCpuContext, r11)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R12, ARM_REG_R0, + offsetof(GumCpuContext, r12)); + + /* Save sp & lr */ + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_SP, ARM_REG_R0, + offsetof(GumCpuContext, sp)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, + offsetof(GumCpuContext, lr)); + + /* Save r0 (load from stack into r1) */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, r[0])); + + /* Save CPSR */ + gum_arm_writer_put_mov_reg_cpsr(cw, ARM_REG_R1); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, cpsr)); + + /* Save PC */ + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R1, + GUM_ADDRESS(persistent_start)); + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, pc)); + + /* Restore Regs */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_SP, + GUM_RED_ZONE_SIZE + sizeof(guint32)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); +} + +static void instrument_persitent_restore_regs(GumArmWriter * cw, + GumCpuContext *regs) { + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs)); + + /* Restore CPSR */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R0, + offsetof(GumCpuContext, cpsr)); + gum_arm_writer_put_mov_cpsr_reg(cw, ARM_REG_R1); + + /* Restore sp & lr */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_SP, ARM_REG_R0, + offsetof(GumCpuContext, sp)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_LR, ARM_REG_R0, + offsetof(GumCpuContext, lr)); + + /* Restore r8-r12 */ + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R8, ARM_REG_R0, + offsetof(GumCpuContext, r8)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R9, ARM_REG_R0, + offsetof(GumCpuContext, r9)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R10, ARM_REG_R0, + offsetof(GumCpuContext, r10)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R11, ARM_REG_R0, + offsetof(GumCpuContext, r11)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R12, ARM_REG_R0, + offsetof(GumCpuContext, r12)); + + /* Restore r7-r0 */ + for (size_t i = ARM_REG_R7; i >= ARM_REG_R0; i--) { + gum_arm_writer_put_ldr_reg_reg_offset( + cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0])); + } +} + +static void instrument_exit(GumArmWriter *cw) { + gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0); + 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) { + FATAL("instrument_previous_pc_addr uninitialized"); + } + + *instrument_previous_pc_addr = instrument_hash_zero; + return ret; +} + +static void instrument_afl_persistent_loop(GumArmWriter *cw) { + gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); + gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); +} + +static void persistent_prologue_hook(GumArmWriter *cw, GumCpuContext *regs) { + if (persistent_hook == NULL) return; + + gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R2, + GUM_ADDRESS(&__afl_fuzz_len)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R2, ARM_REG_R2, 0); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R2, ARM_REG_R2, 0); + + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R1, + GUM_ADDRESS(&__afl_fuzz_ptr)); + gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R1, ARM_REG_R1, 0); + + gum_arm_writer_put_call_address_with_arguments( + cw, GUM_ADDRESS(persistent_hook), 3, GUM_ARG_ADDRESS, GUM_ADDRESS(regs), + GUM_ARG_REGISTER, ARM_REG_R1, GUM_ARG_REGISTER, ARM_REG_R2); + + gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, + GUM_RED_ZONE_SIZE); +} + +static void instrument_persitent_save_lr(GumArmWriter *cw) { + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, + GUM_RED_ZONE_SIZE); + + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(&saved_lr)); + 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_RED_ZONE_SIZE); } void persistent_prologue_arch(GumStalkerOutput *output) { + /* + * SAVE REGS + * SAVE RET + * POP RET + * loop: + * CALL instrument_afl_persistent_loop + * TEST EAX, EAX + * JZ end: + * call hook (optionally) + * RESTORE REGS + * call original + * jmp loop: + * + * end: + * JMP SAVED RET + * + * original: + * INSTRUMENTED PERSISTENT FUNC + */ - UNUSED_PARAMETER(output); - FFATAL("Persistent mode not supported on this architecture"); + GumArmWriter *cw = output->writer.arm; + gconstpointer loop = cw->code + 1; + + FVERBOSE("Persistent loop reached"); + + instrument_persitent_save_regs(cw, &saved_regs); + + /* loop: */ + gum_arm_writer_put_label(cw, loop); + + /* call instrument_prologue_func */ + 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 */ + persistent_prologue_hook(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); } } void persistent_epilogue_arch(GumStalkerOutput *output) { + GumArmWriter *cw = output->writer.arm; - UNUSED_PARAMETER(output); - FFATAL("Persistent mode not supported on this architecture"); + 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_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0); + + gum_arm_writer_put_bx_reg(cw, ARM_REG_R0); } #endif From 1e524d1f43bba638b000da5fa6fb094ebcc9bb83 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Aug 2022 18:46:29 +0100 Subject: [PATCH 05/12] Added support for ARM32 inline assembly --- frida_mode/src/instrument/instrument_arm32.c | 156 ++++++++++++++++++- 1 file changed, 148 insertions(+), 8 deletions(-) diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 4525e83d..0ff69952 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -5,22 +5,150 @@ #if defined(__arm__) + #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; +extern __thread guint64 instrument_previous_pc; + +__attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE]; + + #pragma pack(push, 1) +typedef struct { + // cur_location = (block_address >> 4) ^ (block_address << 8); + // shared_mem[cur_location ^ prev_location]++; + // prev_location = cur_location >> 1; + + /* We can remove this branch when we add support for branch suppression */ + uint32_t b_code; /* b imm */ + uint8_t * shared_mem; + uint64_t *prev_location; + + /* code */ + + /* save regs */ + uint32_t str_r0_sp_rz; /* str r0, [sp - RED_ZONE] */ + uint32_t str_r1_sp_rz_4; /* str r1, [sp - (RED_ZONE + 4)] */ + + /* load prev */ + uint32_t ldr_r0_pprev; /* ldr r0, [pc-x] */ + uint32_t ldrh_r1_r0; /* ldrh r1, [r0] */ + + /* load curr */ + uint32_t mov_r0_block_id; /* mov r0, #imm16 */ + + /* calculate new */ + uint32_t eor_r0_r0_r1; /* eor r0, r0, r1 */ + + /* load map */ + uint32_t ldr_r1_pmap; /* ldr r1, [pc-x] */ + + /* calculate offset */ + uint32_t add_r1_r1_r0; /* add r1, r1, r0 */ + + /* Load the value */ + uint32_t ldrb_r0_r1; /* ldrb r0, [r1] */ + + /* Increment the value */ + uint32_t add_r0_r0_1; /* add r0, r0, #1 */ + uint32_t add_r0_r0_r0_lsr_8; /* add r0, r0, r0, lsr #8 */ + + /* Save the value */ + uint32_t strb_r0_r1; /* strb r0, [r1] */ + + /* load curr shifted */ + uint32_t mov_r0_block_id_shr_1; /* mov r0, #imm16 >> 1*/ + + /* Update prev */ + uint32_t ldr_r1_pprev; /* ldr r1, [pc-x] */ + uint32_t strh_r0_r1; /* strh r0, [r1] */ + + /* restore regs */ + uint32_t ldr_r1_sp_rz_4; /* ldr r1, [sp - (RED_ZONE + 4)] */ + uint32_t ldr_r0_sp_rz; /* ldr r0, [sp - RED_ZONE] */ + +} afl_log_code_asm_t; + +typedef union { + afl_log_code_asm_t code; + uint8_t bytes[0]; + +} afl_log_code; + + #pragma pack(pop) + +static const afl_log_code_asm_t template = + { + .b_code = GUINT32_TO_LE(0xea000001), + .shared_mem = (uint8_t *)GUINT32_TO_LE(0xcefaadde), + .prev_location = (uint64_t *)GUINT32_TO_LE(0xadba0df0), + .str_r0_sp_rz = GUINT32_TO_LE(0xe50d0080), + .str_r1_sp_rz_4 = GUINT32_TO_LE(0xe50d1084), + .ldr_r0_pprev = GUINT32_TO_LE(0xe51f0014), + .ldrh_r1_r0 = GUINT32_TO_LE(0xe1d010b0), + .mov_r0_block_id = GUINT32_TO_LE(0xe3000000), + .eor_r0_r0_r1 = GUINT32_TO_LE(0xe0200001), + .ldr_r1_pmap = GUINT32_TO_LE(0xe51f1028), + .add_r1_r1_r0 = GUINT32_TO_LE(0xe0811000), + .ldrb_r0_r1 = GUINT32_TO_LE(0xe5d10000), + .add_r0_r0_1 = GUINT32_TO_LE(0xe2800001), + .add_r0_r0_r0_lsr_8 = GUINT32_TO_LE(0xe0800420), + .strb_r0_r1 = GUINT32_TO_LE(0xe5c10000), + .mov_r0_block_id_shr_1 = GUINT32_TO_LE(0xe3000000), + .ldr_r1_pprev = GUINT32_TO_LE(0xe51f1040), + .strh_r0_r1 = GUINT32_TO_LE(0xe1c100b0), + .ldr_r1_sp_rz_4 = GUINT32_TO_LE(0xe51d1084), + .ldr_r0_sp_rz = GUINT32_TO_LE(0xe51d0080), +} + +; + gboolean instrument_is_coverage_optimize_supported(void) { + return true; +} - return false; - +static void patch_t3_insn(uint32_t *insn, uint16_t val) { + uint32_t orig = GUINT32_FROM_LE(*insn); + uint32_t imm12 = (val & 0xfff); + uint32_t imm4 = (val >> 12); + orig |= imm12; + orig |= (imm4 << 16); + *insn = GUINT32_TO_LE(orig); } void instrument_coverage_optimize(const cs_insn *instr, GumStalkerOutput *output) { + afl_log_code code = {0}; + GumArmWriter *cw = output->writer.arm; + gpointer block_start; + guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); + gsize map_size_pow2; + gsize area_offset_ror; + GumAddress code_addr = 0; - UNUSED_PARAMETER(instr); - UNUSED_PARAMETER(output); - FFATAL("Optimized coverage not supported on this architecture"); + // gum_arm64_writer_put_brk_imm(cw, 0x0); + code_addr = cw->pc; + + block_start = GSIZE_TO_POINTER(GUM_ADDRESS(cw->code)); + + code.code = template; + + g_assert(PAGE_ALIGNED(__afl_area_ptr)); + + map_size_pow2 = util_log2(__afl_map_size); + area_offset_ror = util_rotate(area_offset, 1, map_size_pow2); + + code.code.shared_mem = __afl_area_ptr; + code.code.prev_location = instrument_previous_pc_addr; + + patch_t3_insn(&code.code.mov_r0_block_id, (uint16_t)area_offset); + patch_t3_insn(&code.code.mov_r0_block_id_shr_1, (uint16_t)area_offset_ror); + + // gum_arm_writer_put_breakpoint(cw); + gum_arm_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); } void instrument_coverage_optimize_insn(const cs_insn *instr, @@ -28,14 +156,26 @@ void instrument_coverage_optimize_insn(const cs_insn *instr, UNUSED_PARAMETER(instr); UNUSED_PARAMETER(output); - FFATAL("Optimized coverage not supported on this architecture"); - } void instrument_coverage_optimize_init(void) { + char *shm_env = getenv(SHM_ENV_VAR); + FVERBOSE("SHM_ENV_VAR: %s", shm_env); - FWARNF("Optimized coverage not supported on this architecture"); + if (shm_env == NULL) { + FWARNF("SHM_ENV_VAR not set, using dummy for debugging purposes"); + __afl_area_ptr = area_ptr_dummy; + memset(area_ptr_dummy, '\0', sizeof(area_ptr_dummy)); + } + + FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); + + if (instrument_previous_pc_addr == NULL) { + instrument_previous_pc_addr = &instrument_previous_pc; + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + } } void instrument_flush(GumStalkerOutput *output) { From 9d5a2d1b8e6f4ead25a857d106b37fd85950aff3 Mon Sep 17 00:00:00 2001 From: Your Name Date: Thu, 4 Aug 2022 18:46:29 +0100 Subject: [PATCH 06/12] Add support for using hook on ARM32 --- frida_mode/hook/frida_hook.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/frida_mode/hook/frida_hook.c b/frida_mode/hook/frida_hook.c index 86c6f9d4..79e2348d 100644 --- a/frida_mode/hook/frida_hook.c +++ b/frida_mode/hook/frida_hook.c @@ -50,6 +50,16 @@ __attribute__((visibility("default"))) void afl_persistent_hook( } +#elif defined(__arm__) + +__attribute__((visibility("default"))) void afl_persistent_hook( + GumCpuContext *regs, uint8_t *input_buf, uint32_t input_buf_len) { + // do a length check matching the target! + + memcpy((void *)regs->r[0], input_buf, input_buf_len); + regs->r[1] = input_buf_len; +} + #else #pragma error "Unsupported architecture" #endif From 7b6743f14ceb426e282900a9d5ee35b1ac820013 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Aug 2022 08:10:45 +0100 Subject: [PATCH 07/12] Android fixes --- frida_mode/GNUmakefile | 88 ++++++++++++++++++++++++-------- frida_mode/include/seccomp.h | 2 +- frida_mode/src/main.c | 31 +++++++++++ frida_mode/src/prefetch.c | 4 ++ frida_mode/src/seccomp/seccomp.c | 6 ++- 5 files changed, 108 insertions(+), 23 deletions(-) diff --git a/frida_mode/GNUmakefile b/frida_mode/GNUmakefile index 256bea02..43b8932a 100644 --- a/frida_mode/GNUmakefile +++ b/frida_mode/GNUmakefile @@ -13,6 +13,16 @@ JS_SRC:=$(BUILD_DIR)api.c JS_OBJ:=$(BUILD_DIR)api.o SOURCES:=$(wildcard $(SRC_DIR)**/*.c) $(wildcard $(SRC_DIR)*.c) OBJS:=$(foreach src,$(SOURCES),$(OBJ_DIR)$(notdir $(patsubst %.c, %.o, $(src)))) + +TARGET_CC?=$(CC) +TARGET_CXX?=$(CXX) +HOST_CC?=$(CC) +HOST_CXX?=$(CXX) +IS_ANDROID:=$(findstring android, $(shell $(TARGET_CC) --version 2>/dev/null)) +IS_x86:=$(findstring i686, $(shell $(TARGET_CC) --version 2>/dev/null)) +IS_x86_64:=$(findstring x86_64, $(shell $(TARGET_CC) --version 2>/dev/null)) +IS_ARM:=$(findstring arm, $(shell $(TARGET_CC) --version 2>/dev/null)) +IS_ARM64:=$(findstring aarch64, $(shell $(TARGET_CC) --version 2>/dev/null)) CFLAGS+=-fPIC \ -D_GNU_SOURCE \ -D_FORTIFY_SOURCE=2 \ @@ -21,6 +31,10 @@ CFLAGS+=-fPIC \ -funroll-loops \ -ffunction-sections \ +ifdef IS_ANDROID +CFLAGS+=-DANDROID +endif + AFL_CFLAGS:=-Wno-unused-parameter \ -Wno-sign-compare \ -Wno-unused-function \ @@ -28,9 +42,16 @@ AFL_CFLAGS:=-Wno-unused-parameter \ -Wno-int-to-pointer-cast \ -Wno-pointer-sign +ifdef IS_ANDROID +LDFLAGS+= -static-libstdc++ \ + -DANDROID \ + -llog \ + -shared +else LDFLAGS+=-shared \ -lpthread \ -lresolv +endif ifdef DEBUG CFLAGS+=-Werror \ @@ -78,11 +99,11 @@ else ifdef DEBUG AFL_CFLAGS:=$(AFL_CFLAGS) -Wno-prio-ctor-dtor endif + LDFLAGS+= -z noexecstack \ -Wl,--gc-sections \ -Wl,--exclude-libs,ALL \ - -ldl \ - -lrt + -ldl LDSCRIPT:=-Wl,--version-script=$(PWD)frida.map endif @@ -93,22 +114,24 @@ ifeq "$(shell uname)" "Linux" endif endif -ifneq "$(findstring android, $(shell $(CC) --version 2>/dev/null))" "" + +ifdef IS_ANDROID OS:=android - ifneq "$(findstring aarch64, $(shell $(CC) --version 2>/dev/null))" "" - ARCH:=arm64 + ifdef IS_x86 + ARCH:=x86 endif - ifneq "$(findstring arm, $(shell $(CC) --version 2>/dev/null))" "" + ifdef IS_x86 + ARCH:=x86_64 + endif + ifdef IS_ARM ARCH:=arm endif - ifneq "$(findstring x86_64, $(shell $(CC) --version 2>/dev/null))" "" - ARCH:=x86_64 - endif - ifneq "$(findstring i686, $(shell $(CC) --version 2>/dev/null))" "" - ARCH:=x86 + ifdef IS_ARM64 + ARCH:=arm64 endif endif + ifeq "$(ARCH)" "armhf" TARGET_CC:=arm-linux-gnueabihf-gcc TARGET_CXX:=arm-linux-gnueabihf-g++ @@ -224,10 +247,22 @@ else ifeq "$(ARCH)" "arm64" CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-$(OS)-$(ARCH)/include/frida-1.0 \ -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/glib-2.0/ \ - -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \ -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/capstone/ \ -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \ +ifeq "$(OS)" "android" + CFLAGS += -static-libstdc++ +endif +else +CFLAGS+=-I $(FRIDA_DIR)build/frida_thin-$(OS)-$(ARCH)/include/frida-1.0 \ + -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/glib-2.0/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/capstone/ \ + -I $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \ + +endif + TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \ $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \ $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libsqlite3.a \ @@ -245,13 +280,15 @@ TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \ $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/liblzma.a \ $(FRIDA_DIR)build/frida_thin-sdk-$(OS)-$(ARCH)/lib/libz.a \ -else - CFLAGS+=-I $(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/include/frida-1.0 \ -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/glib-2.0/ \ -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/glib-2.0/include/ \ -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/capstone/ \ - -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ \ + -I $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/include/json-glib-1.0/ + +ifeq "$(OS)" "android" + CFLAGS += -static-libstdc++ +endif TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \ $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libsoup-2.4.a \ @@ -270,11 +307,6 @@ TRACE_LDFLAGS+=$(FRIDA_DIR)build/frida-$(OS)-$(ARCH)/lib/libfrida-gum-1.0.a \ $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/liblzma.a \ $(FRIDA_DIR)build/sdk-$(OS)-$(ARCH)/lib/libz.a \ -endif - - - - else $(GUM_DEVKIT_TARBALL): | $(FRIDA_BUILD_DIR) @@ -376,6 +408,7 @@ $(AFLPP_QEMU_DRIVER_HOOK_OBJ): $(AFLPP_QEMU_DRIVER_HOOK_SRC) | $(BUILD_DIR) hook: $(AFLPP_FRIDA_DRIVER_HOOK_OBJ) $(AFLPP_QEMU_DRIVER_HOOK_OBJ) ############################# ADDR ############################################# +ifneq "$(OS)" "android" $(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR) -$(TARGET_CC) \ $(CFLAGS) \ @@ -389,7 +422,20 @@ $(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR) -ldl \ -lrt \ $< -o $@ - +else +$(ADDR_BIN): $(ADDR_SRC) | $(BUILD_DIR) + -$(TARGET_CC) \ + $(CFLAGS) \ + -Werror \ + -Wall \ + -Wextra \ + -Wpointer-arith \ + -z noexecstack \ + -Wl,--gc-sections \ + -Wl,--exclude-libs,ALL \ + -ldl \ + $< -o $@ +endif addr: $(ADDR_BIN) ############################# CLEAN ############################################ diff --git a/frida_mode/include/seccomp.h b/frida_mode/include/seccomp.h index 0cd90bc2..0886759c 100644 --- a/frida_mode/include/seccomp.h +++ b/frida_mode/include/seccomp.h @@ -1,7 +1,7 @@ #ifndef _SECCOMP_H #define _SECCOMP_H -#ifndef __APPLE__ +#if !defined(__APPLE__) && !defined(__ANDROID__) #include #include diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index 844c42b9..1bbcec28 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -36,6 +36,17 @@ #ifdef __APPLE__ extern mach_port_t mach_task_self(); extern GumAddress gum_darwin_find_entrypoint(mach_port_t task); +#elif defined(__ANDROID__) +typedef struct { + void (**preinit_array)(void); + void (**init_array)(void); + void (**fini_array)(void); +} structors_array_t; + +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), @@ -69,7 +80,11 @@ static void on_main_os(int argc, char **argv, char **envp) { GumInterceptor *interceptor = gum_interceptor_obtain(); gum_interceptor_begin_transaction(interceptor); + #if defined(__ANDROID__) + gum_interceptor_revert(interceptor, __libc_init); + #else gum_interceptor_revert(interceptor, __libc_start_main); + #endif gum_interceptor_end_transaction(interceptor); gum_interceptor_flush(interceptor); @@ -275,6 +290,22 @@ static void intercept_main(void) { main_fn = main; intercept_hook(main, on_main, NULL); +} +#elif defined(__ANDROID__) +static void on_libc_init(void* raw_args, + void (*onexit)(void) __unused, + int (*slingshot)(int, char**, char**), + structors_array_t const * const structors){ + main_fn = slingshot; + intercept_unhook_self(); + intercept_hook(slingshot, on_main, NULL); + return __libc_init(raw_args, onexit, slingshot, structors); + +} +static void intercept_main(void) { + + intercept_hook(__libc_init, on_libc_init, NULL); + } #else diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index 5621a685..b2c516f5 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -298,12 +298,16 @@ void prefetch_init(void) { /* * Configure the shared memory region to be removed once the process dies. + * This doesn't work on Android, so we skip it. Would could end up leaking + * shared memory regions though. */ + #ifndef __ANDROID__ if (shmctl(prefetch_shm_id, IPC_RMID, NULL) < 0) { FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); } +#endif /* Clear it, not sure it's necessary, just seems like good practice */ memset(prefetch_data, '\0', sizeof(prefetch_data_t)); diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c index 984a3990..72443831 100644 --- a/frida_mode/src/seccomp/seccomp.c +++ b/frida_mode/src/seccomp/seccomp.c @@ -11,7 +11,9 @@ void seccomp_on_fork(void) { #ifdef __APPLE__ FFATAL("Seccomp not supported on OSX"); -#else +#elif defined(__ANDROID__) + FFATAL("Seccomp not supported on Android"); +#else seccomp_callback_parent(); #endif @@ -32,6 +34,8 @@ void seccomp_init(void) { #ifdef __APPLE__ FFATAL("Seccomp not supported on OSX"); +#elif defined(__ANDROID__) + FFATAL("Seccomp not supported on Android"); #else seccomp_callback_initialize(); #endif From e9cb939956557b1f10bbab289d965f84702962eb Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Aug 2022 08:10:45 +0100 Subject: [PATCH 08/12] Fixes to formatting --- frida_mode/src/main.c | 25 ++++++++++++++----------- frida_mode/src/prefetch.c | 3 ++- frida_mode/src/seccomp/seccomp.c | 2 +- 3 files changed, 17 insertions(+), 13 deletions(-) diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index 1bbcec28..c8c50b37 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -38,15 +38,16 @@ extern mach_port_t mach_task_self(); extern GumAddress gum_darwin_find_entrypoint(mach_port_t task); #elif defined(__ANDROID__) typedef struct { - void (**preinit_array)(void); - void (**init_array)(void); - void (**fini_array)(void); + + void (**preinit_array)(void); + void (**init_array)(void); + void (**fini_array)(void); + } structors_array_t; -extern void __libc_init(void* raw_args, - void (*onexit)(void) __unused, - int (*slingshot)(int, char **, char **), - structors_array_t const * const structors); +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), @@ -291,17 +292,19 @@ static void intercept_main(void) { intercept_hook(main, on_main, NULL); } + #elif defined(__ANDROID__) -static void on_libc_init(void* raw_args, - void (*onexit)(void) __unused, - int (*slingshot)(int, char**, char**), - structors_array_t const * const structors){ +static void on_libc_init(void *raw_args, void (*onexit)(void) __unused, + int (*slingshot)(int, char **, char **), + structors_array_t const *const structors) { + main_fn = slingshot; intercept_unhook_self(); intercept_hook(slingshot, on_main, NULL); return __libc_init(raw_args, onexit, slingshot, structors); } + static void intercept_main(void) { intercept_hook(__libc_init, on_libc_init, NULL); diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index b2c516f5..e20923c4 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -301,12 +301,13 @@ void prefetch_init(void) { * This doesn't work on Android, so we skip it. Would could end up leaking * shared memory regions though. */ - #ifndef __ANDROID__ +#ifndef __ANDROID__ if (shmctl(prefetch_shm_id, IPC_RMID, NULL) < 0) { FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); } + #endif /* Clear it, not sure it's necessary, just seems like good practice */ diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c index 72443831..12b58f4e 100644 --- a/frida_mode/src/seccomp/seccomp.c +++ b/frida_mode/src/seccomp/seccomp.c @@ -13,7 +13,7 @@ void seccomp_on_fork(void) { FFATAL("Seccomp not supported on OSX"); #elif defined(__ANDROID__) FFATAL("Seccomp not supported on Android"); -#else +#else seccomp_callback_parent(); #endif From 00b5d3792de4a7867da9cb5abd08de9fca484db1 Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Aug 2022 08:10:45 +0100 Subject: [PATCH 09/12] Changes to abstract shared memory --- frida_mode/include/shm.h | 9 +++++++ frida_mode/src/instrument/instrument.c | 27 ++----------------- frida_mode/src/prefetch.c | 31 ++-------------------- frida_mode/src/shm.c | 36 ++++++++++++++++++++++++++ frida_mode/src/stats/stats.c | 24 +++-------------- frida_mode/src/stats/stats_arm64.c | 21 ++------------- frida_mode/src/stats/stats_x86_64.c | 21 ++------------- 7 files changed, 56 insertions(+), 113 deletions(-) create mode 100644 frida_mode/include/shm.h create mode 100644 frida_mode/src/shm.c diff --git a/frida_mode/include/shm.h b/frida_mode/include/shm.h new file mode 100644 index 00000000..8338ccba --- /dev/null +++ b/frida_mode/include/shm.h @@ -0,0 +1,9 @@ +#ifndef _SHM_H +#define _SHM_H + +#include + +void *shm_create(size_t size); + +#endif + diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 0e286eab..e1e4ac22 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -1,7 +1,5 @@ #include #include -#include -#include #include #include "frida-gumjs.h" @@ -17,6 +15,7 @@ #include "persistent.h" #include "prefetch.h" #include "ranges.h" +#include "shm.h" #include "stalker.h" #include "stats.h" #include "util.h" @@ -348,29 +347,7 @@ void instrument_init(void) { transformer = gum_stalker_transformer_make_from_callback( instrument_basic_block, NULL, NULL); - if (instrument_unique) { - - int shm_id = - shmget(IPC_PRIVATE, __afl_map_size, IPC_CREAT | IPC_EXCL | 0600); - if (shm_id < 0) { FATAL("shm_id < 0 - errno: %d\n", errno); } - - edges_notified = shmat(shm_id, NULL, 0); - g_assert(edges_notified != MAP_FAILED); - - /* - * Configure the shared memory region to be removed once the process - * dies. - */ - if (shmctl(shm_id, IPC_RMID, NULL) < 0) { - - FATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); - - } - - /* Clear it, not sure it's necessary, just seems like good practice */ - memset(edges_notified, '\0', __afl_map_size); - - } + if (instrument_unique) { edges_notified = shm_create(__afl_map_size); } if (instrument_use_fixed_seed) { diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index e20923c4..905e0ae9 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -1,12 +1,11 @@ #include -#include -#include #include "frida-gumjs.h" #include "entry.h" #include "intercept.h" #include "prefetch.h" +#include "shm.h" #include "stalker.h" #include "util.h" @@ -285,33 +284,7 @@ void prefetch_init(void) { * with the coverage bitmap region and fork will take care of ensuring both * the parent and child see the same consistent memory region. */ - prefetch_shm_id = - shmget(IPC_PRIVATE, sizeof(prefetch_data_t), IPC_CREAT | IPC_EXCL | 0600); - if (prefetch_shm_id < 0) { - - FFATAL("prefetch_shm_id < 0 - errno: %d\n", errno); - - } - - prefetch_data = shmat(prefetch_shm_id, NULL, 0); - g_assert(prefetch_data != MAP_FAILED); - - /* - * Configure the shared memory region to be removed once the process dies. - * This doesn't work on Android, so we skip it. Would could end up leaking - * shared memory regions though. - */ -#ifndef __ANDROID__ - if (shmctl(prefetch_shm_id, IPC_RMID, NULL) < 0) { - - FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); - - } - -#endif - - /* Clear it, not sure it's necessary, just seems like good practice */ - memset(prefetch_data, '\0', sizeof(prefetch_data_t)); + prefetch_data = shm_create(sizeof(prefetch_data_t)); prefetch_hook_fork(); diff --git a/frida_mode/src/shm.c b/frida_mode/src/shm.c new file mode 100644 index 00000000..c76427cb --- /dev/null +++ b/frida_mode/src/shm.c @@ -0,0 +1,36 @@ +#include "shm.h" +#include "util.h" + +#include +#include +#include +#include +#include +#include + +void *shm_create(size_t size) { + + int shm_id = + shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); + if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); } + + void *addr = shmat(shm_id, NULL, 0); + if (addr == MAP_FAILED) { FFATAL("addr == MAP_FAILED - errno: %d\n", errno); } + + /* + * Configure the shared memory region to be removed once the process + * dies. + */ + if (shmctl(shm_id, IPC_RMID, NULL) < 0) { + + FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); + + } + + /* Clear it, not sure it's necessary, just seems like good practice */ + memset(addr, '\0', size); + + return addr; + +} + diff --git a/frida_mode/src/stats/stats.c b/frida_mode/src/stats/stats.c index af08cd71..1d3520bc 100644 --- a/frida_mode/src/stats/stats.c +++ b/frida_mode/src/stats/stats.c @@ -2,17 +2,16 @@ #include #include #include -#include #include #include "frida-gumjs.h" #include "config.h" -#include "util.h" - #include "entry.h" +#include "shm.h" #include "stalker.h" #include "stats.h" +#include "util.h" #define MICRO_TO_SEC 1000000 @@ -360,27 +359,10 @@ void stats_init(void) { g_free(path); - int shm_id = - shmget(IPC_PRIVATE, sizeof(stats_data_t), IPC_CREAT | IPC_EXCL | 0600); - if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); } - - stats_data = shmat(shm_id, NULL, 0); - g_assert(stats_data != MAP_FAILED); - GumStalkerObserver *observer = stalker_get_observer(); stats_observer_init(observer); - /* - * Configure the shared memory region to be removed once the process dies. - */ - if (shmctl(shm_id, IPC_RMID, NULL) < 0) { - - FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); - - } - - /* Clear it, not sure it's necessary, just seems like good practice */ - memset(stats_data, '\0', sizeof(stats_data_t)); + stats_data = shm_create(sizeof(stats_data_t)); starts_arch_init(); diff --git a/frida_mode/src/stats/stats_arm64.c b/frida_mode/src/stats/stats_arm64.c index 313ab47a..ea283dbe 100644 --- a/frida_mode/src/stats/stats_arm64.c +++ b/frida_mode/src/stats/stats_arm64.c @@ -1,9 +1,9 @@ -#include #include #include "frida-gumjs.h" #include "ranges.h" +#include "shm.h" #include "stats.h" #include "util.h" @@ -44,24 +44,7 @@ static stats_data_arch_t *stats_data_arch = NULL; void starts_arch_init(void) { - int shm_id = shmget(IPC_PRIVATE, sizeof(stats_data_arch_t), - IPC_CREAT | IPC_EXCL | 0600); - if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); } - - stats_data_arch = shmat(shm_id, NULL, 0); - g_assert(stats_data_arch != MAP_FAILED); - - /* - * Configure the shared memory region to be removed once the process dies. - */ - if (shmctl(shm_id, IPC_RMID, NULL) < 0) { - - FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); - - } - - /* Clear it, not sure it's necessary, just seems like good practice */ - memset(stats_data_arch, '\0', sizeof(stats_data_arch_t)); + stats_data_arch = shm_create(sizeof(stats_data_arch_t)); } diff --git a/frida_mode/src/stats/stats_x86_64.c b/frida_mode/src/stats/stats_x86_64.c index 761ca133..e2fb7b80 100644 --- a/frida_mode/src/stats/stats_x86_64.c +++ b/frida_mode/src/stats/stats_x86_64.c @@ -1,9 +1,9 @@ -#include #include #include "frida-gumjs.h" #include "ranges.h" +#include "shm.h" #include "stats.h" #include "util.h" @@ -46,24 +46,7 @@ static stats_data_arch_t *stats_data_arch = NULL; void starts_arch_init(void) { - int shm_id = shmget(IPC_PRIVATE, sizeof(stats_data_arch_t), - IPC_CREAT | IPC_EXCL | 0600); - if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); } - - stats_data_arch = shmat(shm_id, NULL, 0); - g_assert(stats_data_arch != MAP_FAILED); - - /* - * Configure the shared memory region to be removed once the process dies. - */ - if (shmctl(shm_id, IPC_RMID, NULL) < 0) { - - FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); - - } - - /* Clear it, not sure it's necessary, just seems like good practice */ - memset(stats_data_arch, '\0', sizeof(stats_data_arch_t)); + stats_data_arch = shm_create(sizeof(stats_data_arch_t)); } From 608ea5f8abbfce9c309d452e2ee3dbb014dc511a Mon Sep 17 00:00:00 2001 From: Your Name Date: Mon, 1 Aug 2022 08:10:45 +0100 Subject: [PATCH 10/12] Add support for Android SHM --- frida_mode/src/asan/asan.c | 17 ++++++--------- frida_mode/src/shm.c | 44 ++++++++++++++++++++++++++++++++++---- 2 files changed, 47 insertions(+), 14 deletions(-) diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c index 3a672d31..bd4062be 100644 --- a/frida_mode/src/asan/asan.c +++ b/frida_mode/src/asan/asan.c @@ -8,23 +8,17 @@ static gboolean asan_enabled = FALSE; gboolean asan_initialized = FALSE; void asan_config(void) { - if (getenv("AFL_USE_FASAN") != NULL) { asan_enabled = TRUE; } - } void asan_init(void) { - FOKF(cBLU "Instrumentation" cRST " - " cGRN "asan:" cYEL " [%c]", asan_enabled ? 'X' : ' '); if (asan_enabled) { - asan_arch_init(); asan_initialized = TRUE; - } - } static gboolean asan_exclude_module(const GumModuleDetails *details, @@ -36,14 +30,17 @@ static gboolean asan_exclude_module(const GumModuleDetails *details, address = gum_module_find_export_by_name(details->name, symbol_name); if (address == 0) { return TRUE; } + /* If the reported address of the symbol is outside of the range of the module + * then ignore it */ + if (address < details->range->base_address) { return TRUE; } + if (address > (details->range->base_address + details->range->size)) { + return TRUE; + } + ranges_add_exclude((GumMemoryRange *)details->range); return FALSE; - } void asan_exclude_module_by_symbol(gchar *symbol_name) { - gum_process_enumerate_modules(asan_exclude_module, symbol_name); - } - diff --git a/frida_mode/src/shm.c b/frida_mode/src/shm.c index c76427cb..5b885b04 100644 --- a/frida_mode/src/shm.c +++ b/frida_mode/src/shm.c @@ -7,9 +7,48 @@ #include #include #include +#ifdef __ANDROID__ + #include + #include +#endif + +#ifdef __ANDROID__ + #define ASHMEM_DEVICE "/dev/ashmem" void *shm_create(size_t size) { + int fd = -1; + char ourkey[11] = {0}; + void * addr = MAP_FAILED; + struct ashmem_pin pin = {0, size}; + fd = open(ASHMEM_DEVICE, O_RDWR); + if (fd < 0) { FFATAL("Failed open /dev/ashmem: %d", errno); } + + if (snprintf(ourkey, sizeof(ourkey) - 1, "%d", IPC_PRIVATE) < 0) { + FFATAL("Failed to generate key: %d", errno); + } + + if (ioctl(fd, ASHMEM_SET_NAME, ourkey) < 0) { + FFATAL("ioctl(ASHMEM_SET_NAME) errno: %d\n", errno); + } + + if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) { + FFATAL("ioctl(ASHMEM_SET_SIZE) errno: %d\n", errno); + } + + addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + if (addr == MAP_FAILED) { FFATAL("mmap failed: %d\n", errno); } + + /* Shared memory pinning has been deprecated. So if the ioctl fails, then + just assume we are running on a version where it has been. Worst case, we + will leak the shared memory region.*/ + ioctl(fd, ASHMEM_UNPIN, &pin); + close(fd); + + return addr; +} +#else +void *shm_create(size_t size) { int shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); } @@ -22,15 +61,12 @@ void *shm_create(size_t size) { * dies. */ if (shmctl(shm_id, IPC_RMID, NULL) < 0) { - FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); - } /* Clear it, not sure it's necessary, just seems like good practice */ memset(addr, '\0', size); return addr; - } - +#endif From 7b6ee28291c13e293c59489d4f2e37c78bad96fb Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Sat, 6 Aug 2022 09:07:49 +0200 Subject: [PATCH 11/12] code format --- docs/Changelog.md | 2 + frida_mode/src/asan/asan.c | 12 ++++ frida_mode/src/instrument/instrument_arm32.c | 55 ++++++++++++------- .../src/instrument/instrument_coverage.c | 2 +- frida_mode/src/persistent/persistent_arm32.c | 31 ++++++++++- frida_mode/src/shm.c | 17 +++++- 6 files changed, 96 insertions(+), 23 deletions(-) diff --git a/docs/Changelog.md b/docs/Changelog.md index 05bbe827..9ee1a7fc 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -19,6 +19,8 @@ sending a mail to . - Adacore submitted CMPLOG support to the gcc_plugin! :-) - llvm_mode: - laf cmp splitting fixed for more comparison types + - frida_mode: + - now works on Android! ### Version ++4.01c (release) diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c index bd4062be..ad171337 100644 --- a/frida_mode/src/asan/asan.c +++ b/frida_mode/src/asan/asan.c @@ -8,17 +8,23 @@ static gboolean asan_enabled = FALSE; gboolean asan_initialized = FALSE; void asan_config(void) { + if (getenv("AFL_USE_FASAN") != NULL) { asan_enabled = TRUE; } + } void asan_init(void) { + FOKF(cBLU "Instrumentation" cRST " - " cGRN "asan:" cYEL " [%c]", asan_enabled ? 'X' : ' '); if (asan_enabled) { + asan_arch_init(); asan_initialized = TRUE; + } + } static gboolean asan_exclude_module(const GumModuleDetails *details, @@ -34,13 +40,19 @@ static gboolean asan_exclude_module(const GumModuleDetails *details, * then ignore it */ if (address < details->range->base_address) { return TRUE; } if (address > (details->range->base_address + details->range->size)) { + return TRUE; + } ranges_add_exclude((GumMemoryRange *)details->range); return FALSE; + } void asan_exclude_module_by_symbol(gchar *symbol_name) { + gum_process_enumerate_modules(asan_exclude_module, symbol_name); + } + diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 0ff69952..f2e825ee 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -17,61 +17,63 @@ __attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE]; #pragma pack(push, 1) typedef struct { + // cur_location = (block_address >> 4) ^ (block_address << 8); // shared_mem[cur_location ^ prev_location]++; // prev_location = cur_location >> 1; /* We can remove this branch when we add support for branch suppression */ - uint32_t b_code; /* b imm */ - uint8_t * shared_mem; + uint32_t b_code; /* b imm */ + uint8_t *shared_mem; uint64_t *prev_location; /* code */ /* save regs */ - uint32_t str_r0_sp_rz; /* str r0, [sp - RED_ZONE] */ - uint32_t str_r1_sp_rz_4; /* str r1, [sp - (RED_ZONE + 4)] */ + uint32_t str_r0_sp_rz; /* str r0, [sp - RED_ZONE] */ + uint32_t str_r1_sp_rz_4; /* str r1, [sp - (RED_ZONE + 4)] */ /* load prev */ - uint32_t ldr_r0_pprev; /* ldr r0, [pc-x] */ - uint32_t ldrh_r1_r0; /* ldrh r1, [r0] */ + uint32_t ldr_r0_pprev; /* ldr r0, [pc-x] */ + uint32_t ldrh_r1_r0; /* ldrh r1, [r0] */ /* load curr */ - uint32_t mov_r0_block_id; /* mov r0, #imm16 */ + uint32_t mov_r0_block_id; /* mov r0, #imm16 */ /* calculate new */ - uint32_t eor_r0_r0_r1; /* eor r0, r0, r1 */ + uint32_t eor_r0_r0_r1; /* eor r0, r0, r1 */ /* load map */ - uint32_t ldr_r1_pmap; /* ldr r1, [pc-x] */ + uint32_t ldr_r1_pmap; /* ldr r1, [pc-x] */ /* calculate offset */ - uint32_t add_r1_r1_r0; /* add r1, r1, r0 */ + uint32_t add_r1_r1_r0; /* add r1, r1, r0 */ /* Load the value */ - uint32_t ldrb_r0_r1; /* ldrb r0, [r1] */ + uint32_t ldrb_r0_r1; /* ldrb r0, [r1] */ /* Increment the value */ - uint32_t add_r0_r0_1; /* add r0, r0, #1 */ - uint32_t add_r0_r0_r0_lsr_8; /* add r0, r0, r0, lsr #8 */ + uint32_t add_r0_r0_1; /* add r0, r0, #1 */ + uint32_t add_r0_r0_r0_lsr_8; /* add r0, r0, r0, lsr #8 */ /* Save the value */ - uint32_t strb_r0_r1; /* strb r0, [r1] */ + uint32_t strb_r0_r1; /* strb r0, [r1] */ /* load curr shifted */ - uint32_t mov_r0_block_id_shr_1; /* mov r0, #imm16 >> 1*/ + uint32_t mov_r0_block_id_shr_1; /* mov r0, #imm16 >> 1*/ /* Update prev */ - uint32_t ldr_r1_pprev; /* ldr r1, [pc-x] */ - uint32_t strh_r0_r1; /* strh r0, [r1] */ + uint32_t ldr_r1_pprev; /* ldr r1, [pc-x] */ + uint32_t strh_r0_r1; /* strh r0, [r1] */ /* restore regs */ - uint32_t ldr_r1_sp_rz_4; /* ldr r1, [sp - (RED_ZONE + 4)] */ - uint32_t ldr_r0_sp_rz; /* ldr r0, [sp - RED_ZONE] */ + uint32_t ldr_r1_sp_rz_4; /* ldr r1, [sp - (RED_ZONE + 4)] */ + uint32_t ldr_r0_sp_rz; /* ldr r0, [sp - RED_ZONE] */ } afl_log_code_asm_t; typedef union { + afl_log_code_asm_t code; uint8_t bytes[0]; @@ -81,6 +83,7 @@ typedef union { static const afl_log_code_asm_t template = { + .b_code = GUINT32_TO_LE(0xea000001), .shared_mem = (uint8_t *)GUINT32_TO_LE(0xcefaadde), .prev_location = (uint64_t *)GUINT32_TO_LE(0xadba0df0), @@ -101,25 +104,31 @@ static const afl_log_code_asm_t template = .strh_r0_r1 = GUINT32_TO_LE(0xe1c100b0), .ldr_r1_sp_rz_4 = GUINT32_TO_LE(0xe51d1084), .ldr_r0_sp_rz = GUINT32_TO_LE(0xe51d0080), + } ; gboolean instrument_is_coverage_optimize_supported(void) { + return true; + } static void patch_t3_insn(uint32_t *insn, uint16_t val) { + uint32_t orig = GUINT32_FROM_LE(*insn); uint32_t imm12 = (val & 0xfff); uint32_t imm4 = (val >> 12); orig |= imm12; orig |= (imm4 << 16); *insn = GUINT32_TO_LE(orig); + } void instrument_coverage_optimize(const cs_insn *instr, GumStalkerOutput *output) { + afl_log_code code = {0}; GumArmWriter *cw = output->writer.arm; gpointer block_start; @@ -149,6 +158,7 @@ void instrument_coverage_optimize(const cs_insn *instr, // gum_arm_writer_put_breakpoint(cw); gum_arm_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); + } void instrument_coverage_optimize_insn(const cs_insn *instr, @@ -156,26 +166,33 @@ void instrument_coverage_optimize_insn(const cs_insn *instr, UNUSED_PARAMETER(instr); UNUSED_PARAMETER(output); + } void instrument_coverage_optimize_init(void) { + char *shm_env = getenv(SHM_ENV_VAR); FVERBOSE("SHM_ENV_VAR: %s", shm_env); if (shm_env == NULL) { + FWARNF("SHM_ENV_VAR not set, using dummy for debugging purposes"); __afl_area_ptr = area_ptr_dummy; memset(area_ptr_dummy, '\0', sizeof(area_ptr_dummy)); + } FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); if (instrument_previous_pc_addr == NULL) { + instrument_previous_pc_addr = &instrument_previous_pc; *instrument_previous_pc_addr = instrument_hash_zero; FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + } + } void instrument_flush(GumStalkerOutput *output) { diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c index 25913585..ff2f4024 100644 --- a/frida_mode/src/instrument/instrument_coverage.c +++ b/frida_mode/src/instrument/instrument_coverage.c @@ -242,7 +242,7 @@ static void instrument_coverage_mark_first(void *key, void *value, void *user_data) { UNUSED_PARAMETER(key); - coverage_range_t * module = (coverage_range_t *)user_data; + coverage_range_t *module = (coverage_range_t *)user_data; normal_coverage_data_t *val = (normal_coverage_data_t *)value; val->module = module; diff --git a/frida_mode/src/persistent/persistent_arm32.c b/frida_mode/src/persistent/persistent_arm32.c index a2b63652..dbe51eb5 100644 --- a/frida_mode/src/persistent/persistent_arm32.c +++ b/frida_mode/src/persistent/persistent_arm32.c @@ -7,6 +7,7 @@ #if defined(__arm__) // struct _GumArmCpuContext { + // guint32 pc; // guint32 sp; // guint32 cpsr; @@ -35,11 +36,14 @@ static GumCpuContext saved_regs = {0}; static gpointer saved_lr = NULL; gboolean persistent_is_supported(void) { + return true; + } -static void instrument_persitent_save_regs(GumArmWriter * cw, +static void instrument_persitent_save_regs(GumArmWriter *cw, GumCpuContext *regs) { + /* Save Regs */ gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, GUM_RED_ZONE_SIZE); @@ -50,8 +54,10 @@ static void instrument_persitent_save_regs(GumArmWriter * cw, /* Save r1-r7 */ for (size_t i = ARM_REG_R1; i < ARM_REG_R8; i++) { + gum_arm_writer_put_str_reg_reg_offset( cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0])); + } /* Save r8-r12 */ @@ -94,10 +100,12 @@ static void instrument_persitent_save_regs(GumArmWriter * cw, GUM_RED_ZONE_SIZE + sizeof(guint32)); gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, GUM_RED_ZONE_SIZE); + } -static void instrument_persitent_restore_regs(GumArmWriter * cw, +static void instrument_persitent_restore_regs(GumArmWriter *cw, GumCpuContext *regs) { + gum_arm_writer_put_ldr_reg_address(cw, ARM_REG_R0, GUM_ADDRESS(regs)); /* Restore CPSR */ @@ -125,37 +133,49 @@ static void instrument_persitent_restore_regs(GumArmWriter * cw, /* Restore r7-r0 */ for (size_t i = ARM_REG_R7; i >= ARM_REG_R0; i--) { + gum_arm_writer_put_ldr_reg_reg_offset( cw, i, ARM_REG_R0, offsetof(GumCpuContext, r[i - ARM_REG_R0])); + } + } static void instrument_exit(GumArmWriter *cw) { + gum_arm_writer_put_sub_reg_reg_reg(cw, ARM_REG_R0, ARM_REG_R0, ARM_REG_R0); 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) { + FATAL("instrument_previous_pc_addr uninitialized"); + } *instrument_previous_pc_addr = instrument_hash_zero; return ret; + } static void instrument_afl_persistent_loop(GumArmWriter *cw) { + gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, GUM_RED_ZONE_SIZE); gum_arm_writer_put_call_address_with_arguments( cw, GUM_ADDRESS(instrument_afl_persistent_loop_func), 0); gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, GUM_RED_ZONE_SIZE); + } static void persistent_prologue_hook(GumArmWriter *cw, GumCpuContext *regs) { + if (persistent_hook == NULL) return; gum_arm_writer_put_sub_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, @@ -175,9 +195,11 @@ static void persistent_prologue_hook(GumArmWriter *cw, GumCpuContext *regs) { gum_arm_writer_put_add_reg_reg_imm(cw, ARM_REG_SP, ARM_REG_SP, GUM_RED_ZONE_SIZE); + } static void instrument_persitent_save_lr(GumArmWriter *cw) { + gum_arm_writer_put_str_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, GUM_RED_ZONE_SIZE); @@ -186,9 +208,11 @@ static void instrument_persitent_save_lr(GumArmWriter *cw) { gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_SP, GUM_RED_ZONE_SIZE); + } void persistent_prologue_arch(GumStalkerOutput *output) { + /* * SAVE REGS * SAVE RET @@ -251,9 +275,11 @@ void persistent_prologue_arch(GumStalkerOutput *output) { instrument_persitent_save_lr(cw); if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } + } void persistent_epilogue_arch(GumStalkerOutput *output) { + GumArmWriter *cw = output->writer.arm; if (persistent_debug) { gum_arm_writer_put_breakpoint(cw); } @@ -263,6 +289,7 @@ void persistent_epilogue_arch(GumStalkerOutput *output) { gum_arm_writer_put_ldr_reg_reg_offset(cw, ARM_REG_R0, ARM_REG_R0, 0); gum_arm_writer_put_bx_reg(cw, ARM_REG_R0); + } #endif diff --git a/frida_mode/src/shm.c b/frida_mode/src/shm.c index 5b885b04..282526e8 100644 --- a/frida_mode/src/shm.c +++ b/frida_mode/src/shm.c @@ -16,24 +16,31 @@ #define ASHMEM_DEVICE "/dev/ashmem" void *shm_create(size_t size) { + int fd = -1; char ourkey[11] = {0}; - void * addr = MAP_FAILED; + void *addr = MAP_FAILED; struct ashmem_pin pin = {0, size}; fd = open(ASHMEM_DEVICE, O_RDWR); if (fd < 0) { FFATAL("Failed open /dev/ashmem: %d", errno); } if (snprintf(ourkey, sizeof(ourkey) - 1, "%d", IPC_PRIVATE) < 0) { + FFATAL("Failed to generate key: %d", errno); + } if (ioctl(fd, ASHMEM_SET_NAME, ourkey) < 0) { + FFATAL("ioctl(ASHMEM_SET_NAME) errno: %d\n", errno); + } if (ioctl(fd, ASHMEM_SET_SIZE, size) < 0) { + FFATAL("ioctl(ASHMEM_SET_SIZE) errno: %d\n", errno); + } addr = mmap(NULL, size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); @@ -46,9 +53,12 @@ void *shm_create(size_t size) { close(fd); return addr; + } + #else void *shm_create(size_t size) { + int shm_id = shmget(IPC_PRIVATE, size, IPC_CREAT | IPC_EXCL | S_IRUSR | S_IWUSR); if (shm_id < 0) { FFATAL("shm_id < 0 - errno: %d\n", errno); } @@ -61,12 +71,17 @@ void *shm_create(size_t size) { * dies. */ if (shmctl(shm_id, IPC_RMID, NULL) < 0) { + FFATAL("shmctl (IPC_RMID) < 0 - errno: %d\n", errno); + } /* Clear it, not sure it's necessary, just seems like good practice */ memset(addr, '\0', size); return addr; + } + #endif + From 1f06b55a8b558bd8da0296134c29c21c4849a4bd Mon Sep 17 00:00:00 2001 From: vanhauser-thc Date: Mon, 8 Aug 2022 15:26:56 +0200 Subject: [PATCH 12/12] 4.02c --- README.md | 4 ++-- docs/Changelog.md | 8 ++++---- include/config.h | 2 +- 3 files changed, 7 insertions(+), 7 deletions(-) diff --git a/README.md b/README.md index 53b2b8d0..921fc0c6 100644 --- a/README.md +++ b/README.md @@ -2,9 +2,9 @@ AFL++ logo -Release version: [4.01c](https://github.com/AFLplusplus/AFLplusplus/releases) +Release version: [4.02c](https://github.com/AFLplusplus/AFLplusplus/releases) -GitHub version: 4.02a +GitHub version: 4.02c Repository: [https://github.com/AFLplusplus/AFLplusplus](https://github.com/AFLplusplus/AFLplusplus) diff --git a/docs/Changelog.md b/docs/Changelog.md index 9ee1a7fc..957f6206 100644 --- a/docs/Changelog.md +++ b/docs/Changelog.md @@ -8,10 +8,7 @@ Want to stay in the loop on major new features? Join our mailing list by sending a mail to . -### Version ++4.02a (dev) - - afl-fuzz: - - change post_process hook to allow returning NULL and 0 length to - tell afl-fuzz to skip this mutated input +### Version ++4.02c (release) - afl-cc: - important fix for the default pcguard mode when LLVM IR vector selects are produced, thanks to @juppytt for reporting! @@ -21,6 +18,9 @@ sending a mail to . - laf cmp splitting fixed for more comparison types - frida_mode: - now works on Android! + - afl-fuzz: + - change post_process hook to allow returning NULL and 0 length to + tell afl-fuzz to skip this mutated input ### Version ++4.01c (release) diff --git a/include/config.h b/include/config.h index 0ae6c271..d7a08428 100644 --- a/include/config.h +++ b/include/config.h @@ -26,7 +26,7 @@ /* Version string: */ // c = release, a = volatile github dev, e = experimental branch -#define VERSION "++4.02a" +#define VERSION "++4.02c" /****************************************************** * *