diff options
Diffstat (limited to 'frida_mode/src')
-rw-r--r-- | frida_mode/src/asan/asan.c | 21 | ||||
-rw-r--r-- | frida_mode/src/asan/asan_arm64.c | 2 | ||||
-rw-r--r-- | frida_mode/src/asan/asan_x64.c | 2 | ||||
-rw-r--r-- | frida_mode/src/asan/asan_x86.c | 2 | ||||
-rw-r--r-- | frida_mode/src/cmplog/cmplog.c | 18 | ||||
-rw-r--r-- | frida_mode/src/ctx/ctx_arm32.c | 1 | ||||
-rw-r--r-- | frida_mode/src/ctx/ctx_arm64.c | 1 | ||||
-rw-r--r-- | frida_mode/src/ctx/ctx_x86.c | 1 | ||||
-rw-r--r-- | frida_mode/src/entry.c | 2 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_coverage.c | 56 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x64.c | 101 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x86.c | 202 | ||||
-rw-r--r-- | frida_mode/src/js/api.js | 15 | ||||
-rw-r--r-- | frida_mode/src/js/js.c | 3 | ||||
-rw-r--r-- | frida_mode/src/js/js_api.c | 20 | ||||
-rw-r--r-- | frida_mode/src/main.c | 20 | ||||
-rw-r--r-- | frida_mode/src/persistent/persistent_x86.c | 1 | ||||
-rw-r--r-- | frida_mode/src/ranges.c | 20 | ||||
-rw-r--r-- | frida_mode/src/seccomp/seccomp_event.c | 6 | ||||
-rw-r--r-- | frida_mode/src/seccomp/seccomp_filter.c | 6 | ||||
-rw-r--r-- | frida_mode/src/stalker.c | 33 |
21 files changed, 391 insertions, 142 deletions
diff --git a/frida_mode/src/asan/asan.c b/frida_mode/src/asan/asan.c index d649bd76..884bec53 100644 --- a/frida_mode/src/asan/asan.c +++ b/frida_mode/src/asan/asan.c @@ -1,6 +1,7 @@ #include "frida-gumjs.h" #include "asan.h" +#include "ranges.h" #include "util.h" static gboolean asan_enabled = FALSE; @@ -32,3 +33,23 @@ void asan_init(void) { } +static gboolean asan_exclude_module(const GumModuleDetails *details, + gpointer user_data) { + + gchar * symbol_name = (gchar *)user_data; + GumAddress address; + + address = gum_module_find_export_by_name(details->name, symbol_name); + if (address == 0) { 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/asan/asan_arm64.c b/frida_mode/src/asan/asan_arm64.c index 88c76535..b2adfa52 100644 --- a/frida_mode/src/asan/asan_arm64.c +++ b/frida_mode/src/asan/asan_arm64.c @@ -88,6 +88,8 @@ void asan_arch_init(void) { } + asan_exclude_module_by_symbol("__asan_loadN"); + } #endif diff --git a/frida_mode/src/asan/asan_x64.c b/frida_mode/src/asan/asan_x64.c index c7b70967..a287ea34 100644 --- a/frida_mode/src/asan/asan_x64.c +++ b/frida_mode/src/asan/asan_x64.c @@ -85,6 +85,8 @@ void asan_arch_init(void) { } + asan_exclude_module_by_symbol("__asan_loadN"); + } #endif diff --git a/frida_mode/src/asan/asan_x86.c b/frida_mode/src/asan/asan_x86.c index afc89936..331d026b 100644 --- a/frida_mode/src/asan/asan_x86.c +++ b/frida_mode/src/asan/asan_x86.c @@ -85,6 +85,8 @@ void asan_arch_init(void) { } + asan_exclude_module_by_symbol("__asan_loadN"); + } #endif diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c index 81e1a4b0..443baa1d 100644 --- a/frida_mode/src/cmplog/cmplog.c +++ b/frida_mode/src/cmplog/cmplog.c @@ -33,8 +33,22 @@ static gboolean cmplog_range(const GumRangeDetails *details, static gint cmplog_sort(gconstpointer a, gconstpointer b) { - return ((GumMemoryRange *)b)->base_address - - ((GumMemoryRange *)a)->base_address; + GumMemoryRange *ra = (GumMemoryRange *)a; + GumMemoryRange *rb = (GumMemoryRange *)b; + + if (ra->base_address < rb->base_address) { + + return -1; + + } else if (ra->base_address > rb->base_address) { + + return 1; + + } else { + + return 0; + + } } diff --git a/frida_mode/src/ctx/ctx_arm32.c b/frida_mode/src/ctx/ctx_arm32.c index 049b5548..28fc706b 100644 --- a/frida_mode/src/ctx/ctx_arm32.c +++ b/frida_mode/src/ctx/ctx_arm32.c @@ -1,6 +1,7 @@ #include "frida-gumjs.h" #include "ctx.h" +#include "util.h" #if defined(__arm__) diff --git a/frida_mode/src/ctx/ctx_arm64.c b/frida_mode/src/ctx/ctx_arm64.c index 01f321e3..63b6cf09 100644 --- a/frida_mode/src/ctx/ctx_arm64.c +++ b/frida_mode/src/ctx/ctx_arm64.c @@ -1,6 +1,7 @@ #include "frida-gumjs.h" #include "ctx.h" +#include "util.h" #if defined(__aarch64__) diff --git a/frida_mode/src/ctx/ctx_x86.c b/frida_mode/src/ctx/ctx_x86.c index abfeafc8..438e1fde 100644 --- a/frida_mode/src/ctx/ctx_x86.c +++ b/frida_mode/src/ctx/ctx_x86.c @@ -1,6 +1,7 @@ #include "frida-gumjs.h" #include "ctx.h" +#include "util.h" #if defined(__i386__) diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index a36daf88..562e74eb 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -36,7 +36,7 @@ static void entry_launch(void) { } -#if defined(__linux__) && !defined(__ANDROID__) +#if defined(__linux__) && defined(PR_SET_PTRACER) && !defined(__ANDROID__) void entry_on_fork(void) { if (traceable) { diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c index 95a24808..c1984eb2 100644 --- a/frida_mode/src/instrument/instrument_coverage.c +++ b/frida_mode/src/instrument/instrument_coverage.c @@ -237,7 +237,7 @@ static void instrument_coverage_mark(void *key, void *value, void *user_data) { } -static void coverage_write(void *data, size_t size) { +static void coverage_write(int fd, void *data, size_t size) { ssize_t written; size_t remain = size; @@ -245,7 +245,7 @@ static void coverage_write(void *data, size_t size) { for (char *cursor = (char *)data; remain > 0; remain -= written, cursor += written) { - written = write(normal_coverage_fd, cursor, remain); + written = write(fd, cursor, remain); if (written < 0) { @@ -257,7 +257,7 @@ static void coverage_write(void *data, size_t size) { } -static void coverage_format(char *format, ...) { +static void coverage_format(int fd, char *format, ...) { va_list ap; char buffer[4096] = {0}; @@ -272,11 +272,11 @@ static void coverage_format(char *format, ...) { len = strnlen(buffer, sizeof(buffer)); - coverage_write(buffer, len); + coverage_write(fd, buffer, len); } -static void coverage_write_modules(GArray *coverage_modules) { +static void coverage_write_modules(int fd, GArray *coverage_modules) { guint emitted = 0; for (guint i = 0; i < coverage_modules->len; i++) { @@ -285,16 +285,16 @@ static void coverage_write_modules(GArray *coverage_modules) { &g_array_index(coverage_modules, coverage_range_t, i); if (module->count == 0) continue; - coverage_format("%3u, ", emitted); - coverage_format("%016" G_GINT64_MODIFIER "X, ", module->base_address); - coverage_format("%016" G_GINT64_MODIFIER "X, ", module->limit); + coverage_format(fd, "%3u, ", emitted); + coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", module->base_address); + coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", module->limit); /* entry */ - coverage_format("%016" G_GINT64_MODIFIER "X, ", 0); + coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0); /* checksum */ - coverage_format("%016" G_GINT64_MODIFIER "X, ", 0); + coverage_format(fd, "%016" G_GINT64_MODIFIER "X, ", 0); /* timestamp */ - coverage_format("%08" G_GINT32_MODIFIER "X, ", 0); - coverage_format("%s\n", module->path); + coverage_format(fd, "%08" G_GINT32_MODIFIER "X, ", 0); + coverage_format(fd, "%s\n", module->path); emitted++; } @@ -304,7 +304,7 @@ static void coverage_write_modules(GArray *coverage_modules) { static void coverage_write_events(void *key, void *value, void *user_data) { UNUSED_PARAMETER(key); - UNUSED_PARAMETER(user_data); + int fd = *((int *)user_data); normal_coverage_data_t *val = (normal_coverage_data_t *)value; if (val->module == NULL) { return; } @@ -317,20 +317,20 @@ static void coverage_write_events(void *key, void *value, void *user_data) { }; - coverage_write(&evt, sizeof(coverage_event_t)); + coverage_write(fd, &evt, sizeof(coverage_event_t)); } -static void coverage_write_header(guint coverage_marked_modules) { +static void coverage_write_header(int fd, guint coverage_marked_modules) { char version[] = "DRCOV VERSION: 2\n"; char flavour[] = "DRCOV FLAVOR: frida\n"; char columns[] = "Columns: id, base, end, entry, checksum, timestamp, path\n"; - coverage_write(version, sizeof(version) - 1); - coverage_write(flavour, sizeof(flavour) - 1); - coverage_format("Module Table: version 2, count %u\n", + coverage_write(fd, version, sizeof(version) - 1); + coverage_write(fd, flavour, sizeof(flavour) - 1); + coverage_format(fd, "Module Table: version 2, count %u\n", coverage_marked_modules); - coverage_write(columns, sizeof(columns) - 1); + coverage_write(fd, columns, sizeof(columns) - 1); } @@ -412,10 +412,11 @@ static void instrument_coverage_normal_run() { instrument_coverage_print("Coverage - Marked Modules: %u\n", coverage_marked_modules); - coverage_write_header(coverage_marked_modules); - coverage_write_modules(coverage_modules); - coverage_format("BB Table: %u bbs\n", ctx.count); - g_hash_table_foreach(coverage_hash, coverage_write_events, NULL); + 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); @@ -636,10 +637,11 @@ static void instrument_coverage_unstable_run(void) { instrument_coverage_print("Coverage - Marked Modules: %u\n", coverage_marked_modules); - coverage_write_header(coverage_marked_modules); - coverage_write_modules(coverage_modules); - coverage_format("BB Table: %u bbs\n", ctx.count); - g_hash_table_foreach(unstable_blocks, coverage_write_events, NULL); + 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); diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index c474d034..41162f2a 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -5,7 +5,7 @@ #if defined(__linux__) #if !defined(__ANDROID__) - #include <asm/prctl.h> + #include <sys/prctl.h> #include <sys/syscall.h> #else #include <linux/ashmem.h> @@ -52,54 +52,41 @@ typedef struct { // shared_mem[cur_location ^ prev_location]++; // prev_location = cur_location >> 1; - // 0x7ffff6cbb9b6: lea rsp,[rsp-0x80] - // - // 0x7ffff6cbb9bb: push rax - // 0x7ffff6cbb9bc: lahf - // 0x7ffff6cbb9bd: push rax - // 0x7ffff6cbb9be: push rbx - // - // 0x7ffff6cbb9bf: mov eax,DWORD PTR [rip+0x33bd7b] - // 0x7ffff6cbb9c5: xor eax,0x3f77 - // 0x7ffff6cbb9ca: add eax,0x10000 - // 0x7ffff6cbb9cf: mov bl,BYTE PTR [rax] - // 0x7ffff6cbb9d1: add bl,0x1 - // 0x7ffff6cbb9d4: adc bl,0x0 - // 0x7ffff6cbb9d7: mov BYTE PTR [rax],bl - // - // 0x7ffff6cbb9d9: mov DWORD PTR [rip+0x33bd5d],0x9fbb - // - // 0x7ffff6cbb9e3: pop rbx - // 0x7ffff6cbb9e4: pop rax - // 0x7ffff6cbb9e5: sahf - // 0x7ffff6cbb9e6: pop rax - // - // 0x7ffff6cbb9e7: lea rsp,[rsp+0x80] - - uint8_t lea_rsp_rsp_sub_rz[5]; - - uint8_t push_rax; + // mov QWORD PTR [rsp-0x80],rax + // lahf + // mov QWORD PTR [rsp-0x88],rax + // mov QWORD PTR [rsp-0x90],rbx + // mov eax,DWORD PTR [rip+0x333d5a] # 0x7ffff6ff2740 + // mov DWORD PTR [rip+0x333d3c],0x9fbb # 0x7ffff6ff2740 + // xor eax,0x103f77 + // mov bl,BYTE PTR [rax] + // add bl,0x1 + // adc bl,0x0 + // mov BYTE PTR [rax],bl + // mov rbx,QWORD PTR [rsp-0x90] + // mov rax,QWORD PTR [rsp-0x88] + // sahf + // mov rax,QWORD PTR [rsp-0x80] + + uint8_t mov_rax_rsp_88[8]; uint8_t lahf; - uint8_t push_rax2; - uint8_t push_rbx; + uint8_t mov_rax_rsp_90[8]; + uint8_t mov_rbx_rsp_98[8]; uint8_t mov_eax_prev_loc[6]; + uint8_t mov_prev_loc_curr_loc_shr1[10]; + uint8_t xor_eax_curr_loc[5]; - uint8_t add_eax_afl_area[5]; uint8_t mov_rbx_ptr_rax[2]; uint8_t add_bl_1[3]; uint8_t adc_bl_0[3]; uint8_t mov_ptr_rax_rbx[2]; - uint8_t mov_prev_loc_curr_loc_shr1[10]; - - uint8_t pop_rbx; - uint8_t pop_rax2; + uint8_t mov_rsp_98_rbx[8]; + uint8_t mov_rsp_90_rax[8]; uint8_t sahf; - uint8_t pop_rax; - - uint8_t lsa_rsp_rsp_add_rz[8]; + uint8_t mov_rsp_88_rax[8]; } afl_log_code_asm_t; @@ -115,29 +102,24 @@ typedef union { static const afl_log_code_asm_t template = { - .lea_rsp_rsp_sub_rz = {0x48, 0x8D, 0x64, 0x24, 0x80}, - .push_rax = 0x50, + .mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, .lahf = 0x9f, - .push_rax2 = 0x50, - .push_rbx = 0x53, + .mov_rax_rsp_90 = {0x48, 0x89, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF}, + .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF}, .mov_eax_prev_loc = {0x8b, 0x05}, - .xor_eax_curr_loc = {0x35}, + .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, - .add_eax_afl_area = {0x05}, + .xor_eax_curr_loc = {0x35}, .mov_rbx_ptr_rax = {0x8a, 0x18}, .add_bl_1 = {0x80, 0xc3, 0x01}, .adc_bl_0 = {0x80, 0xd3, 0x00}, .mov_ptr_rax_rbx = {0x88, 0x18}, - .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, - - .pop_rbx = 0x5b, - .pop_rax2 = 0x58, + .mov_rsp_98_rbx = {0x48, 0x8B, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF}, + .mov_rsp_90_rax = {0x48, 0x8B, 0x84, 0x24, 0x70, 0xFF, 0xFF, 0xFF}, .sahf = 0x9e, - .pop_rax = 0x58, - - .lsa_rsp_rsp_add_rz = {0x48, 0x8D, 0xA4, 0x24, 0x80, 0x00, 0x00, 0x00}, + .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, } @@ -162,7 +144,13 @@ static gboolean instrument_coverage_find_low(const GumRangeDetails *details, } - last_limit = details->range->base_address + details->range->size; + /* + * Align our buffer on a 64k boundary so that the low 16-bits of the address + * are zero, then we can just XOR the base address in, when we XOR with the + * current block ID. + */ + last_limit = GUM_ALIGN_SIZE( + details->range->base_address + details->range->size, (64ULL << 10)); return TRUE; } @@ -421,13 +409,8 @@ void instrument_coverage_optimize(const cs_insn * instr, sizeof(code.code.xor_eax_curr_loc) - sizeof(guint32); - *((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)(area_offset); - - gssize lea_rax_offset = offsetof(afl_log_code, code.add_eax_afl_area) + - sizeof(code.code.add_eax_afl_area) - sizeof(guint32); - - *((guint32 *)&code.bytes[lea_rax_offset]) = - (guint32)GPOINTER_TO_SIZE(__afl_area_ptr); + *((guint32 *)&code.bytes[xor_curr_loc_offset]) = + (guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset); gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index 79664afa..ad837e2d 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -1,67 +1,144 @@ #include "frida-gumjs.h" #include "instrument.h" +#include "stalker.h" #include "util.h" #if defined(__i386__) -static GumAddress current_log_impl = GUM_ADDRESS(0); +static GHashTable *coverage_blocks = NULL; -static void instrument_coverage_function(GumX86Writer *cw) { + #pragma pack(push, 1) +typedef struct { - gum_x86_writer_put_pushfx(cw); - gum_x86_writer_put_push_reg(cw, GUM_REG_ECX); - gum_x86_writer_put_push_reg(cw, GUM_REG_EDX); + // cur_location = (block_address >> 4) ^ (block_address << 8); + // shared_mem[cur_location ^ prev_location]++; + // prev_location = cur_location >> 1; - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_ECX, - GUM_ADDRESS(&instrument_previous_pc)); - gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_EDX, GUM_REG_ECX); - gum_x86_writer_put_xor_reg_reg(cw, GUM_REG_EDX, GUM_REG_EDI); + uint8_t mov_eax_esp_4[4]; + uint8_t lahf; + uint8_t mov_eax_esp_8[4]; + uint8_t mov_ebx_esp_c[4]; - gum_x86_writer_put_add_reg_imm(cw, GUM_REG_EDX, GUM_ADDRESS(__afl_area_ptr)); + uint8_t mov_eax_prev_loc[5]; + uint8_t mov_prev_loc_curr_loc_shr1[10]; - /* add byte ptr [edx], 1 */ - uint8_t add_byte_ptr_edx_1[] = {0x80, 0x02, 0x01}; - gum_x86_writer_put_bytes(cw, add_byte_ptr_edx_1, sizeof(add_byte_ptr_edx_1)); + uint8_t xor_eax_curr_loc[5]; + uint8_t add_eax_area_ptr[5]; - /* adc byte ptr [edx], 0 */ - uint8_t adc_byte_ptr_edx_0[] = {0x80, 0x12, 0x00}; - gum_x86_writer_put_bytes(cw, adc_byte_ptr_edx_0, sizeof(adc_byte_ptr_edx_0)); + uint8_t mov_ebx_ptr_eax[2]; + uint8_t add_bl_1[3]; + uint8_t adc_bl_0[3]; + uint8_t mov_ptr_eax_ebx[2]; - uint8_t ror_di_1[] = {0x66, 0xd1, 0xcf}; - gum_x86_writer_put_bytes(cw, ror_di_1, sizeof(ror_di_1)); - gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_ECX, GUM_REG_EDI); + uint8_t mov_esp_c_ebx[4]; + uint8_t mov_esp_8_eax[4]; + uint8_t sahf; + uint8_t mov_esp_4_eax[4]; - gum_x86_writer_put_pop_reg(cw, GUM_REG_EDX); - gum_x86_writer_put_pop_reg(cw, GUM_REG_ECX); - gum_x86_writer_put_popfx(cw); - gum_x86_writer_put_ret(cw); +} afl_log_code_asm_t; + + #pragma pack(pop) + +typedef union { + + afl_log_code_asm_t code; + uint8_t bytes[0]; + +} afl_log_code; + +static const afl_log_code_asm_t template = + { + + .mov_eax_esp_4 = {0x89, 0x44, 0x24, 0xFC}, + .lahf = 0x9f, + .mov_eax_esp_8 = {0x89, 0x44, 0x24, 0xF8}, + .mov_ebx_esp_c = {0x89, 0x5C, 0x24, 0xF4}, + + .mov_eax_prev_loc = {0xA1}, + .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, + + .xor_eax_curr_loc = {0x35}, + .add_eax_area_ptr = {0x05}, + .mov_ebx_ptr_eax = {0x8a, 0x18}, + .add_bl_1 = {0x80, 0xc3, 0x01}, + .adc_bl_0 = {0x80, 0xd3, 0x00}, + .mov_ptr_eax_ebx = {0x88, 0x18}, + + .mov_esp_c_ebx = {0x8B, 0x5C, 0x24, 0xF4}, + .mov_esp_8_eax = {0x8B, 0x44, 0x24, 0xF8}, + .sahf = 0x9e, + .mov_esp_4_eax = {0x8B, 0x44, 0x24, 0xFC}, } +; + gboolean instrument_is_coverage_optimize_supported(void) { return true; } -static void instrument_coverate_write_function(GumStalkerOutput *output) { +static void instrument_coverage_switch(GumStalkerObserver *self, + gpointer start_address, + const cs_insn * from_insn, + gpointer * target) { - GumX86Writer *cw = output->writer.x86; + UNUSED_PARAMETER(self); + UNUSED_PARAMETER(start_address); + + cs_x86 * x86; + cs_x86_op *op; + if (from_insn == NULL) { return; } + + x86 = &from_insn->detail->x86; + op = x86->operands; + + if (!g_hash_table_contains(coverage_blocks, GSIZE_TO_POINTER(*target))) { + + return; + + } + + switch (from_insn->id) { + + case X86_INS_CALL: + case X86_INS_JMP: + if (x86->op_count != 1) { + + FATAL("Unexpected operand count: %d", x86->op_count); + + } + + if (op[0].type != X86_OP_IMM) { return; } + + break; + case X86_INS_RET: + break; + default: + return; - if (current_log_impl == 0 || - !gum_x86_writer_can_branch_directly_between(cw->pc, current_log_impl) || - !gum_x86_writer_can_branch_directly_between(cw->pc + 128, - current_log_impl)) { + } + + *target = (guint8 *)*target + sizeof(afl_log_code); + +} + +static void instrument_coverage_suppress_init(void) { - gconstpointer after_log_impl = cw->code + 1; + static gboolean initialized = false; + if (initialized) { return; } + initialized = true; - gum_x86_writer_put_jmp_near_label(cw, after_log_impl); + GumStalkerObserver * observer = stalker_get_observer(); + GumStalkerObserverInterface *iface = GUM_STALKER_OBSERVER_GET_IFACE(observer); + iface->switch_callback = instrument_coverage_switch; - current_log_impl = cw->pc; - instrument_coverage_function(cw); + coverage_blocks = g_hash_table_new(g_direct_hash, g_direct_equal); + if (coverage_blocks == NULL) { - gum_x86_writer_put_label(cw, after_log_impl); + FATAL("Failed to g_hash_table_new, errno: %d", errno); } @@ -70,14 +147,61 @@ static void instrument_coverate_write_function(GumStalkerOutput *output) { void instrument_coverage_optimize(const cs_insn * instr, GumStalkerOutput *output) { + afl_log_code code = {0}; GumX86Writer *cw = output->writer.x86; guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); - instrument_coverate_write_function(output); + gsize map_size_pow2; + gsize area_offset_ror; + + code.code = template; + + instrument_coverage_suppress_init(); + + // gum_x86_writer_put_breakpoint(cw); + + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + + FATAL("Failed - g_hash_table_add"); + + } + + gssize prev_loc_value_offset2 = + offsetof(afl_log_code, code.mov_eax_prev_loc) + + sizeof(code.code.mov_eax_prev_loc) - sizeof(gint); + + *((gint *)&code.bytes[prev_loc_value_offset2]) = + (gint)GPOINTER_TO_SIZE(&instrument_previous_pc); + + gssize curr_loc_shr_1_offset = + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) + + sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(guint32); + + map_size_pow2 = util_log2(__afl_map_size); + area_offset_ror = util_rotate(area_offset, 1, map_size_pow2); + + *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = (guint32)(area_offset_ror); + + gssize prev_loc_value_offset = + offsetof(afl_log_code, code.mov_prev_loc_curr_loc_shr1) + + sizeof(code.code.mov_prev_loc_curr_loc_shr1) - sizeof(gint) - + sizeof(guint32); + + *((gint *)&code.bytes[prev_loc_value_offset]) = + (gint)GPOINTER_TO_SIZE(&instrument_previous_pc); + + gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) + + sizeof(code.code.xor_eax_curr_loc) - + sizeof(guint32); + + *((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)area_offset; + + gssize add_area_ptr_offset = offsetof(afl_log_code, code.add_eax_area_ptr) + + sizeof(code.code.add_eax_area_ptr) - + sizeof(guint32); + + *((guint32 *)&code.bytes[add_area_ptr_offset]) = (guint32)__afl_area_ptr; - gum_x86_writer_put_push_reg(cw, GUM_REG_EDI); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_EDI, area_offset); - gum_x86_writer_put_call_address(cw, current_log_impl); - gum_x86_writer_put_pop_reg(cw, GUM_REG_EDI); + gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); } diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 5db62389..215fbdaf 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -151,6 +151,13 @@ class Afl { const buf = Memory.allocUtf8String(file); Afl.jsApiSetInstrumentUnstableCoverageFile(buf); } + /* + * Set a callback to be called in place of the usual `main` function. This see + * `Scripting.md` for details. + */ + static setJsMainHook(address) { + Afl.jsApiSetJsMainHook(address); + } /** * This is equivalent to setting `AFL_FRIDA_PERSISTENT_ADDR`, again a * `NativePointer` should be provided as it's argument. @@ -205,6 +212,12 @@ class Afl { const buf = Memory.allocUtf8String(file); Afl.jsApiSetSeccompFile(buf); } + /** + * See `AFL_FRIDA_STALKER_ADJACENT_BLOCKS`. + */ + static setStalkerAdjacentBlocks(val) { + Afl.jsApiSetStalkerAdjacentBlocks(val); + } /* * Set a function to be called for each instruction which is instrumented * by AFL FRIDA mode. @@ -285,6 +298,7 @@ Afl.jsApiSetInstrumentSeed = Afl.jsApiGetFunction("js_api_set_instrument_seed", 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"]); +Afl.jsApiSetJsMainHook = Afl.jsApiGetFunction("js_api_set_js_main_hook", "void", ["pointer"]); Afl.jsApiSetPersistentAddress = Afl.jsApiGetFunction("js_api_set_persistent_address", "void", ["pointer"]); Afl.jsApiSetPersistentCount = Afl.jsApiGetFunction("js_api_set_persistent_count", "void", ["uint64"]); Afl.jsApiSetPersistentDebug = Afl.jsApiGetFunction("js_api_set_persistent_debug", "void", []); @@ -293,6 +307,7 @@ Afl.jsApiSetPersistentReturn = Afl.jsApiGetFunction("js_api_set_persistent_retur Afl.jsApiSetPrefetchBackpatchDisable = Afl.jsApiGetFunction("js_api_set_prefetch_backpatch_disable", "void", []); Afl.jsApiSetPrefetchDisable = Afl.jsApiGetFunction("js_api_set_prefetch_disable", "void", []); Afl.jsApiSetSeccompFile = Afl.jsApiGetFunction("js_api_set_seccomp_file", "void", ["pointer"]); +Afl.jsApiSetStalkerAdjacentBlocks = Afl.jsApiGetFunction("js_api_set_stalker_adjacent_blocks", "void", ["uint32"]); Afl.jsApiSetStalkerCallback = Afl.jsApiGetFunction("js_api_set_stalker_callback", "void", ["pointer"]); Afl.jsApiSetStalkerIcEntries = Afl.jsApiGetFunction("js_api_set_stalker_ic_entries", "void", ["uint32"]); Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", ["pointer"]); diff --git a/frida_mode/src/js/js.c b/frida_mode/src/js/js.c index 37cd377b..5f477388 100644 --- a/frida_mode/src/js/js.c +++ b/frida_mode/src/js/js.c @@ -3,10 +3,11 @@ #include "js.h" #include "util.h" -static char * js_script = NULL; gboolean js_done = FALSE; js_api_stalker_callback_t js_user_callback = NULL; +js_main_hook_t js_main_hook = NULL; +static char * js_script = NULL; static gchar * filename = "afl.js"; static gchar * contents; static GumScriptBackend * backend; diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 570da335..5021b531 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -11,6 +11,10 @@ #include "stats.h" #include "util.h" +typedef uint8_t u8; + +extern void __afl_set_persistent_mode(u8 mode); + __attribute__((visibility("default"))) void js_api_done() { js_done = TRUE; @@ -47,6 +51,8 @@ __attribute__((visibility("default"))) void js_api_set_persistent_address( persistent_start = GPOINTER_TO_SIZE(address); + __afl_set_persistent_mode(1); + } __attribute__((visibility("default"))) void js_api_set_persistent_return( @@ -242,3 +248,17 @@ __attribute__((visibility("default"))) void js_api_set_backpatch_disable(void) { } +__attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks( + guint val) { + + stalker_adjacent_blocks = val; + +} + +__attribute__((visibility("default"))) void js_api_set_js_main_hook( + const js_main_hook_t hook) { + + js_main_hook = hook; + +} + diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index cb88eabe..913e3a46 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -36,13 +36,13 @@ extern mach_port_t mach_task_self(); extern GumAddress gum_darwin_find_entrypoint(mach_port_t task); #else -extern int __libc_start_main(int *(main)(int, char **, char **), int argc, +extern int __libc_start_main(int (*main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void(*stack_end)); #endif -typedef int *(*main_fn_t)(int argc, char **argv, char **envp); +typedef int (*main_fn_t)(int argc, char **argv, char **envp); static main_fn_t main_fn = NULL; @@ -217,7 +217,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) { } -static int *on_main(int argc, char **argv, char **envp) { +static int on_main(int argc, char **argv, char **envp) { on_main_os(argc, argv, envp); @@ -225,12 +225,20 @@ static int *on_main(int argc, char **argv, char **envp) { afl_frida_start(); - return main_fn(argc, argv, envp); + if (js_main_hook != NULL) { + + return js_main_hook(argc, argv, envp); + + } else { + + return main_fn(argc, argv, envp); + + } } #if defined(EMBEDDED) -extern int *main(int argc, char **argv, char **envp); +extern int main(int argc, char **argv, char **envp); static void intercept_main(void) { @@ -253,7 +261,7 @@ static void intercept_main(void) { } #else -static int on_libc_start_main(int *(main)(int, char **, char **), int argc, +static int on_libc_start_main(int (*main)(int, char **, char **), int argc, char **ubp_av, void (*init)(void), void (*fini)(void), void (*rtld_fini)(void), void(*stack_end)) { diff --git a/frida_mode/src/persistent/persistent_x86.c b/frida_mode/src/persistent/persistent_x86.c index 902274b3..5425b01b 100644 --- a/frida_mode/src/persistent/persistent_x86.c +++ b/frida_mode/src/persistent/persistent_x86.c @@ -4,6 +4,7 @@ #include "instrument.h" #include "persistent.h" +#include "util.h" #if defined(__i386__) diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 027417ee..9844c74c 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -166,8 +166,22 @@ static void convert_token(gchar *token, GumMemoryRange *range) { gint range_sort(gconstpointer a, gconstpointer b) { - return ((GumMemoryRange *)a)->base_address - - ((GumMemoryRange *)b)->base_address; + GumMemoryRange *ra = (GumMemoryRange *)a; + GumMemoryRange *rb = (GumMemoryRange *)b; + + if (ra->base_address < rb->base_address) { + + return -1; + + } else if (ra->base_address > rb->base_address) { + + return 1; + + } else { + + return 0; + + } } @@ -249,7 +263,7 @@ static void check_for_overlaps(GArray *array) { GumAddress curr_limit = curr->base_address + curr->size; if (prev_limit > curr->base_address) { - FFATAL("OVerlapping ranges 0x%016" G_GINT64_MODIFIER + FFATAL("Overlapping ranges 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "x 0x%016" G_GINT64_MODIFIER "x-0x%016" G_GINT64_MODIFIER "x", prev->base_address, prev_limit, curr->base_address, curr_limit); diff --git a/frida_mode/src/seccomp/seccomp_event.c b/frida_mode/src/seccomp/seccomp_event.c index aca0967a..0907eff8 100644 --- a/frida_mode/src/seccomp/seccomp_event.c +++ b/frida_mode/src/seccomp/seccomp_event.c @@ -10,7 +10,13 @@ int seccomp_event_create(void) { +#ifdef SYS_eventfd int fd = syscall(SYS_eventfd, 0, 0); +#else +# ifdef SYS_eventfd2 + int fd = syscall(SYS_eventfd2, 0, 0); +# endif +#endif if (fd < 0) { FFATAL("seccomp_event_create"); } return fd; diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c index a7c0926c..5aee398f 100644 --- a/frida_mode/src/seccomp/seccomp_filter.c +++ b/frida_mode/src/seccomp/seccomp_filter.c @@ -72,7 +72,13 @@ static struct sock_filter filter[] = { /* Allow us to make anonymous maps */ BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, nr))), +#ifdef __NR_mmap BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mmap, 0, 3), +#else +# ifdef __NR_mmap2 + BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, __NR_mmap2, 0, 3), +# endif +#endif BPF_STMT(BPF_LD | BPF_W | BPF_ABS, (offsetof(struct seccomp_data, args[4]))), BPF_JUMP(BPF_JMP | BPF_JEQ | BPF_K, -1, 0, 1), diff --git a/frida_mode/src/stalker.c b/frida_mode/src/stalker.c index 35a9d856..b4dd5a47 100644 --- a/frida_mode/src/stalker.c +++ b/frida_mode/src/stalker.c @@ -7,6 +7,7 @@ guint stalker_ic_entries = 0; gboolean backpatch_enable = TRUE; +guint stalker_adjacent_blocks = 0; static GumStalker *stalker = NULL; @@ -60,7 +61,9 @@ void stalker_config(void) { backpatch_enable = (getenv("AFL_FRIDA_INST_NO_BACKPATCH") == NULL); - stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES"); + stalker_ic_entries = util_read_num("AFL_FRIDA_STALKER_ADJACENT_BLOCKS"); + + stalker_adjacent_blocks = util_read_num("AFL_FRIDA_STALKER_IC_ENTRIES"); observer = g_object_new(GUM_TYPE_AFL_STALKER_OBSERVER, NULL); @@ -92,6 +95,7 @@ void stalker_init(void) { FOKF("Instrumentation - backpatch [%c]", backpatch_enable ? 'X' : ' '); FOKF("Stalker - ic_entries [%u]", stalker_ic_entries); + FOKF("Stalker - adjacent_blocks [%u]", stalker_adjacent_blocks); #if !(defined(__x86_64__) || defined(__i386__)) if (stalker_ic_entries != 0) { @@ -100,13 +104,34 @@ void stalker_init(void) { } -#endif + if (stalker_adjacent_blocks != 0) { + FFATAL("AFL_FRIDA_STALKER_ADJACENT_BLOCKS not supported"); + + } + +#endif if (stalker_ic_entries == 0) { stalker_ic_entries = 32; } + if (instrument_coverage_filename == NULL) { + + if (stalker_adjacent_blocks == 0) { stalker_adjacent_blocks = 32; } + + } else { + + if (stalker_adjacent_blocks != 0) { + + FFATAL( + "AFL_FRIDA_STALKER_ADJACENT_BLOCKS and AFL_FRIDA_INST_COVERAGE_FILE " + "are incompatible"); + + } + + } + #if defined(__x86_64__) || defined(__i386__) - stalker = - g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries, NULL); + stalker = g_object_new(GUM_TYPE_STALKER, "ic-entries", stalker_ic_entries, + "adjacent-blocks", stalker_adjacent_blocks, NULL); #else stalker = gum_stalker_new(); #endif |