diff options
Diffstat (limited to 'frida_mode/src')
-rw-r--r-- | frida_mode/src/instrument/instrument.c | 14 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm32.c | 34 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_arm64.c | 32 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x64.c | 542 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x64_cache.c | 435 | ||||
-rw-r--r-- | frida_mode/src/instrument/instrument_x86.c | 33 | ||||
-rw-r--r-- | frida_mode/src/js/api.js | 22 | ||||
-rw-r--r-- | frida_mode/src/js/js_api.c | 20 | ||||
-rw-r--r-- | frida_mode/src/main.c | 3 | ||||
-rw-r--r-- | frida_mode/src/module.c | 106 | ||||
-rw-r--r-- | frida_mode/src/ranges.c | 2 |
11 files changed, 928 insertions, 315 deletions
diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index 418b35e8..003c3d00 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -29,6 +29,7 @@ guint64 instrument_hash_seed = 0; gboolean instrument_use_fixed_seed = FALSE; guint64 instrument_fixed_seed = 0; char * instrument_coverage_unstable_filename = NULL; +gboolean instrument_coverage_insn = FALSE; static GumStalkerTransformer *transformer = NULL; @@ -233,6 +234,12 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } + if (instrument_coverage_insn) { + + instrument_coverage_optimize_insn(instr, output); + + } + instrument_debug_instruction(instr->address, instr->size, output); if (likely(!excluded)) { @@ -242,6 +249,8 @@ static void instrument_basic_block(GumStalkerIterator *iterator, } + instrument_cache(instr, output); + if (js_stalker_callback(instr, begin, excluded, output)) { gum_stalker_iterator_keep(iterator); @@ -269,11 +278,13 @@ void instrument_config(void) { instrument_fixed_seed = util_read_num("AFL_FRIDA_INST_SEED", 0); instrument_coverage_unstable_filename = (getenv("AFL_FRIDA_INST_UNSTABLE_COVERAGE_FILE")); + instrument_coverage_insn = (getenv("AFL_FRIDA_INST_INSN") != NULL); instrument_debug_config(); instrument_coverage_config(); asan_config(); cmplog_config(); + instrument_cache_config(); } @@ -294,6 +305,8 @@ void instrument_init(void) { instrument_coverage_unstable_filename == NULL ? " " : instrument_coverage_unstable_filename); + FOKF(cBLU "Instrumentation" cRST " - " cGRN "instructions:" cYEL " [%c]", + instrument_coverage_insn ? 'X' : ' '); if (instrument_tracing && instrument_optimize) { @@ -382,6 +395,7 @@ void instrument_init(void) { instrument_coverage_init(); instrument_coverage_optimize_init(); instrument_debug_init(); + instrument_cache_init(); } diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 16e8eaab..80f3c26d 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -5,6 +5,9 @@ #if defined(__arm__) +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; + gboolean instrument_is_coverage_optimize_supported(void) { return false; @@ -20,6 +23,15 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + FFATAL("Optimized coverage not supported on this architecture"); + +} + void instrument_coverage_optimize_init(void) { FWARNF("Optimized coverage not supported on this architecture"); @@ -46,5 +58,27 @@ gpointer instrument_cur(GumStalkerOutput *output) { } +void instrument_cache_config(void) { + +} + +void instrument_cache_init(void) { + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + UNUSED_PARAMETER(real_address); + UNUSED_PARAMETER(code_address); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + #endif diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index 1a704585..e6251cb4 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -18,6 +18,8 @@ #if defined(__aarch64__) +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; static GHashTable *coverage_blocks = NULL; __attribute__((aligned(0x1000))) static guint8 area_ptr_dummy[MAP_SIZE]; @@ -341,6 +343,14 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + void instrument_coverage_optimize_init(void) { char *shm_env = getenv(SHM_ENV_VAR); @@ -371,5 +381,27 @@ gpointer instrument_cur(GumStalkerOutput *output) { } +void instrument_cache_config(void) { + +} + +void instrument_cache_init(void) { + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + UNUSED_PARAMETER(real_address); + UNUSED_PARAMETER(code_address); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + #endif diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index fb84d6d2..d54c8353 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -23,13 +23,39 @@ #if defined(__x86_64__) - #ifndef MAP_FIXED_NOREPLACE - #ifdef MAP_EXCL - #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED - #else - #define MAP_FIXED_NOREPLACE MAP_FIXED - #endif - #endif +enum jcc_opcodes { + + OPC_JO = 0x70, + OPC_JNO = 0x71, + OPC_JB = 0x72, + OPC_JAE = 0x73, + OPC_JE = 0x74, + OPC_JNE = 0x75, + OPC_JBE = 0x76, + OPC_JA = 0x77, + OPC_JS = 0x78, + OPC_JNS = 0x79, + OPC_JP = 0x7a, + OPC_JNP = 0x7b, + OPC_JL = 0x7c, + OPC_JGE = 0x7d, + OPC_JLE = 0x7e, + OPC_JG = 0x7f, + +}; + +typedef union { + + struct { + + uint8_t opcode; + uint8_t distance; + + }; + + uint8_t bytes[0]; + +} jcc_insn; static GHashTable *coverage_blocks = NULL; @@ -45,8 +71,7 @@ static gboolean instrument_coverage_in_range(gssize offset) { } - #ifdef __APPLE__ - #pragma pack(push, 1) + #pragma pack(push, 1) typedef struct { @@ -54,95 +79,28 @@ typedef struct { // shared_mem[cur_location ^ prev_location]++; // prev_location = cur_location >> 1; - // 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 - // lea rax,[rip + 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 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 leax_eax_curr_loc[7]; + // mov QWORD PTR [rsp-0x88],rax + // lahf + // mov QWORD PTR [rsp-0x90],rax + // mov QWORD PTR [rsp-0x98],rbx - 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]; + // mov eax,DWORD PTR [rip+0x1312334] + // xor eax,0x3f77 - uint8_t mov_rsp_98_rbx[8]; - uint8_t mov_rsp_90_rax[8]; - uint8_t sahf; - uint8_t mov_rsp_88_rax[8]; + // lea rbx,[rip+0x132338] + // add rax,rbx -} afl_log_code_asm_t; + // mov bl,BYTE PTR [rax] + // add bl,0x1 + // adc bl,0x0 + // mov BYTE PTR [rax],bl - #pragma pack(pop) + // mov rbx,QWORD PTR [rsp-0x98] + // mov rax,QWORD PTR [rsp-0x90] + // sahf + // mov rax,QWORD PTR [rsp-0x88] -static const afl_log_code_asm_t template = - { - - .mov_rax_rsp_88 = {0x48, 0x89, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, - .lahf = 0x9f, - .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}, - .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, - - .leax_eax_curr_loc = {0x48, 0x8d, 0x05}, - .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_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, - .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, - -} - -; - - #else - #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; - - // 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] + // mov DWORD PTR [rip+0x13122f8],0x9fbb uint8_t mov_rax_rsp_88[8]; uint8_t lahf; @@ -150,10 +108,11 @@ typedef struct { 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 lea_rbx_area_ptr[7]; + uint8_t add_rax_rbx[3]; + uint8_t mov_rbx_ptr_rax[2]; uint8_t add_bl_1[3]; uint8_t adc_bl_0[3]; @@ -164,9 +123,11 @@ typedef struct { uint8_t sahf; uint8_t mov_rsp_88_rax[8]; + uint8_t mov_prev_loc_curr_loc_shr1[10]; + } afl_log_code_asm_t; - #pragma pack(pop) + #pragma pack(pop) static const afl_log_code_asm_t template = { @@ -177,9 +138,10 @@ static const afl_log_code_asm_t template = .mov_rbx_rsp_98 = {0x48, 0x89, 0x9C, 0x24, 0x68, 0xFF, 0xFF, 0xFF}, .mov_eax_prev_loc = {0x8b, 0x05}, - .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, - .xor_eax_curr_loc = {0x35}, + .lea_rbx_area_ptr = {0x48, 0x8d, 0x1d}, + .add_rax_rbx = {0x48, 0x01, 0xd8}, + .mov_rbx_ptr_rax = {0x8a, 0x18}, .add_bl_1 = {0x80, 0xc3, 0x01}, .adc_bl_0 = {0x80, 0xd3, 0x00}, @@ -190,10 +152,11 @@ static const afl_log_code_asm_t template = .sahf = 0x9e, .mov_rsp_88_rax = {0x48, 0x8B, 0x84, 0x24, 0x78, 0xFF, 0xFF, 0xFF}, + .mov_prev_loc_curr_loc_shr1 = {0xc7, 0x05}, + } ; - #endif typedef union { @@ -202,171 +165,12 @@ typedef union { } afl_log_code; - #ifdef __APPLE__ - void instrument_coverage_optimize_init(void) { -} - - #else - -static gboolean instrument_coverage_find_low(const GumRangeDetails *details, - gpointer user_data) { - - static GumAddress last_limit = (64ULL << 10); - gpointer * address = (gpointer *)user_data; - - last_limit = GUM_ALIGN_SIZE(last_limit, __afl_map_size); - - if ((details->range->base_address - last_limit) > __afl_map_size) { - - *address = GSIZE_TO_POINTER(last_limit); - return FALSE; - - } - - if (details->range->base_address > ((2ULL << 30) - __afl_map_size)) { - - return FALSE; - - } - - /* - * 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, __afl_map_size); - return TRUE; - -} - -static void instrument_coverage_optimize_map_mmap_anon(gpointer address) { - - __afl_area_ptr = - mmap(address, __afl_map_size, PROT_READ | PROT_WRITE, - MAP_FIXED_NOREPLACE | MAP_SHARED | MAP_ANONYMOUS, -1, 0); - if (__afl_area_ptr != address) { - - FATAL("Failed to map mmap __afl_area_ptr: %d", errno); - - } - -} - -static void instrument_coverage_optimize_map_mmap(char * shm_file_path, - gpointer address) { - - int shm_fd = -1; - - if (munmap(__afl_area_ptr, __afl_map_size) != 0) { - - FATAL("Failed to unmap previous __afl_area_ptr"); - - } - - __afl_area_ptr = NULL; - - #if !defined(__ANDROID__) - shm_fd = shm_open(shm_file_path, O_RDWR, DEFAULT_PERMISSION); - if (shm_fd == -1) { FATAL("shm_open() failed\n"); } - #else - shm_fd = open("/dev/ashmem", O_RDWR); - if (shm_fd == -1) { FATAL("open() failed\n"); } - if (ioctl(shm_fd, ASHMEM_SET_NAME, shm_file_path) == -1) { - - FATAL("ioctl(ASHMEM_SET_NAME) failed"); - - } - - if (ioctl(shm_fd, ASHMEM_SET_SIZE, __afl_map_size) == -1) { - - FATAL("ioctl(ASHMEM_SET_SIZE) failed"); - - } - - #endif - - __afl_area_ptr = mmap(address, __afl_map_size, PROT_READ | PROT_WRITE, - MAP_FIXED_NOREPLACE | MAP_SHARED, shm_fd, 0); - if (__afl_area_ptr != address) { - - FATAL("Failed to map mmap __afl_area_ptr: %d", errno); - - } - - if (close(shm_fd) != 0) { FATAL("Failed to close shm_fd"); } - -} - -static void instrument_coverage_optimize_map_shm(guint64 shm_env_val, - gpointer address) { - - if (shmdt(__afl_area_ptr) != 0) { - - FATAL("Failed to detach previous __afl_area_ptr"); - - } - - __afl_area_ptr = shmat(shm_env_val, address, 0); - if (__afl_area_ptr != address) { - - FATAL("Failed to map shm __afl_area_ptr: %d", errno); - - } - -} - -void instrument_coverage_optimize_init(void) { - - gpointer low_address = NULL; - - gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, instrument_coverage_find_low, - &low_address); - - FVERBOSE("Low address: %p", low_address); - - if (low_address == 0 || - GPOINTER_TO_SIZE(low_address) > ((2UL << 30) - __afl_map_size)) { - - FATAL("Invalid low_address: %p", low_address); - - } - - ranges_print_debug_maps(); - - 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 anonymous map for debugging purposes"); - - instrument_coverage_optimize_map_mmap_anon(low_address); - - } else { - - guint64 shm_env_val = g_ascii_strtoull(shm_env, NULL, 10); - - if (shm_env_val == 0) { - - instrument_coverage_optimize_map_mmap(shm_env, low_address); - - } else { - - instrument_coverage_optimize_map_shm(shm_env_val, low_address); - - } - - } - FVERBOSE("__afl_area_ptr: %p", __afl_area_ptr); } - #endif - static void instrument_coverage_switch(GumStalkerObserver *self, gpointer start_address, const cs_insn * from_insn, @@ -398,10 +202,17 @@ static void instrument_coverage_switch(GumStalkerObserver *self, } - if (op[0].type != X86_OP_IMM) { return; } + if (op[0].type != X86_OP_IMM) { + + instrument_cache_insert(start_address, *target); + return; + + } break; case X86_INS_RET: + instrument_cache_insert(start_address, + (guint8 *)*target + sizeof(afl_log_code)); break; default: return; @@ -431,48 +242,19 @@ static void instrument_coverage_suppress_init(void) { } -void instrument_coverage_optimize(const cs_insn * instr, - GumStalkerOutput *output) { +static void instrument_coverage_write(GumAddress address, + GumStalkerOutput *output) { afl_log_code code = {0}; GumX86Writer *cw = output->writer.x86; - guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); - gsize map_size_pow2; - gsize area_offset_ror; - GumAddress code_addr = 0; - if (instrument_previous_pc_addr == NULL) { - - GumAddressSpec spec = {.near_address = cw->code, - .max_distance = 1ULL << 30}; - - instrument_previous_pc_addr = gum_memory_allocate_near( - &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); - *instrument_previous_pc_addr = instrument_hash_zero; - FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); - FVERBOSE("code_addr: %p", cw->code); - - } - - instrument_coverage_suppress_init(); - - // gum_x86_writer_put_breakpoint(cw); - code_addr = cw->pc; - if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { - - FATAL("Failed - g_hash_table_add"); - - } + guint64 area_offset = instrument_get_offset_hash(address); + gsize map_size_pow2; + gsize area_offset_ror; + GumAddress code_addr = cw->pc; code.code = template; - 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); + /* mov_prev_loc_curr_loc_shr1 */ gssize prev_loc_value = GPOINTER_TO_SIZE(instrument_previous_pc_addr) - @@ -490,6 +272,8 @@ void instrument_coverage_optimize(const cs_insn * instr, *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value; + /* mov_eax_prev_loc */ + gssize prev_loc_value2 = GPOINTER_TO_SIZE(instrument_previous_pc_addr) - (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) + @@ -505,40 +289,172 @@ void instrument_coverage_optimize(const cs_insn * instr, *((gint *)&code.bytes[prev_loc_value_offset2]) = (gint)prev_loc_value2; - #ifdef __APPLE__ + /* xor_eax_curr_loc */ - gssize xor_curr_loc_offset = offsetof(afl_log_code, code.leax_eax_curr_loc) + - sizeof(code.code.leax_eax_curr_loc) - + gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) + + sizeof(code.code.xor_eax_curr_loc) - sizeof(guint32); - gssize xor_curr_loc_value = - ((GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset) - - (code_addr + offsetof(afl_log_code, code.mov_eax_prev_loc) + - sizeof(code.code.mov_eax_prev_loc))); + *((guint32 *)&code.bytes[xor_curr_loc_offset]) = area_offset; + + /* lea_rbx_area_ptr */ + + gssize lea_rbx_area_ptr_offset = + offsetof(afl_log_code, code.lea_rbx_area_ptr) + + sizeof(code.code.lea_rbx_area_ptr) - sizeof(guint32); - if (!instrument_coverage_in_range(xor_curr_loc_value)) { + gssize lea_rbx_area_ptr_value = + (GPOINTER_TO_SIZE(__afl_area_ptr) - + (code_addr + offsetof(afl_log_code, code.lea_rbx_area_ptr) + + sizeof(code.code.lea_rbx_area_ptr))); - FATAL("Patch out of range (xor_curr_loc_value): 0x%016lX", - xor_curr_loc_value); + if (!instrument_coverage_in_range(lea_rbx_area_ptr_value)) { + + FATAL("Patch out of range (lea_rbx_area_ptr_value): 0x%016lX", + lea_rbx_area_ptr_value); } - *((guint32 *)&code.bytes[xor_curr_loc_offset]) = xor_curr_loc_value; + *((guint32 *)&code.bytes[lea_rbx_area_ptr_offset]) = lea_rbx_area_ptr_value; - #else + /* mov_prev_loc_curr_loc_shr1 */ - gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_eax_curr_loc) + - sizeof(code.code.xor_eax_curr_loc) - - sizeof(guint32); + 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); - *((guint32 *)&code.bytes[xor_curr_loc_offset]) = - (guint32)(GPOINTER_TO_SIZE(__afl_area_ptr) | area_offset); - #endif + 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); gum_x86_writer_put_bytes(cw, code.bytes, sizeof(afl_log_code)); } +void instrument_coverage_optimize(const cs_insn * instr, + GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + /* guint64 area_offset = instrument_get_offset_hash(GUM_ADDRESS(instr->address)); */ + if (instrument_previous_pc_addr == NULL) { + + GumAddressSpec spec = {.near_address = cw->code, + .max_distance = 1ULL << 30}; + + instrument_previous_pc_addr = gum_memory_allocate_near( + &spec, sizeof(guint64), 0x1000, GUM_PAGE_READ | GUM_PAGE_WRITE); + *instrument_previous_pc_addr = instrument_hash_zero; + FVERBOSE("instrument_previous_pc_addr: %p", instrument_previous_pc_addr); + FVERBOSE("code_addr: %p", cw->code); + + } + + instrument_coverage_suppress_init(); + + if (!g_hash_table_add(coverage_blocks, GSIZE_TO_POINTER(cw->code))) { + + FATAL("Failed - g_hash_table_add"); + + } + + instrument_coverage_write(GUM_ADDRESS(instr->address), output); + +} + +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + jcc_insn taken, not_taken; + + switch (instr->id) { + + case X86_INS_CMOVA: + taken.opcode = OPC_JA; + not_taken.opcode = OPC_JBE; + break; + case X86_INS_CMOVAE: + taken.opcode = OPC_JAE; + not_taken.opcode = OPC_JB; + break; + case X86_INS_CMOVB: + taken.opcode = OPC_JB; + not_taken.opcode = OPC_JAE; + break; + case X86_INS_CMOVBE: + taken.opcode = OPC_JBE; + not_taken.opcode = OPC_JA; + break; + case X86_INS_CMOVE: + taken.opcode = OPC_JE; + not_taken.opcode = OPC_JNE; + break; + case X86_INS_CMOVG: + taken.opcode = OPC_JG; + not_taken.opcode = OPC_JLE; + break; + case X86_INS_CMOVGE: + taken.opcode = OPC_JGE; + not_taken.opcode = OPC_JL; + break; + case X86_INS_CMOVL: + taken.opcode = OPC_JL; + not_taken.opcode = OPC_JGE; + break; + case X86_INS_CMOVLE: + taken.opcode = OPC_JLE; + not_taken.opcode = OPC_JG; + break; + case X86_INS_CMOVNE: + taken.opcode = OPC_JNE; + not_taken.opcode = OPC_JE; + break; + case X86_INS_CMOVNO: + taken.opcode = OPC_JNO; + not_taken.opcode = OPC_JO; + break; + case X86_INS_CMOVNP: + taken.opcode = OPC_JNP; + not_taken.opcode = OPC_JP; + break; + case X86_INS_CMOVNS: + taken.opcode = OPC_JNS; + not_taken.opcode = OPC_JS; + break; + case X86_INS_CMOVO: + taken.opcode = OPC_JO; + not_taken.opcode = OPC_JNO; + break; + case X86_INS_CMOVP: + taken.opcode = OPC_JP; + not_taken.opcode = OPC_JNP; + break; + case X86_INS_CMOVS: + taken.opcode = OPC_JS; + not_taken.opcode = OPC_JNS; + break; + default: + return; + + } + + taken.distance = sizeof(afl_log_code); + not_taken.distance = sizeof(afl_log_code); + + // gum_x86_writer_put_breakpoint(cw); + + gum_x86_writer_put_bytes(cw, taken.bytes, sizeof(jcc_insn)); + instrument_coverage_write(GUM_ADDRESS(instr->address), output); + + gum_x86_writer_put_bytes(cw, not_taken.bytes, sizeof(jcc_insn)); + instrument_coverage_write(GUM_ADDRESS(instr->address + instr->size), output); + + FVERBOSE("Instrument - 0x%016lx: %s %s", instr->address, instr->mnemonic, + instr->op_str); + +} + void instrument_flush(GumStalkerOutput *output) { gum_x86_writer_flush(output->writer.x86); diff --git a/frida_mode/src/instrument/instrument_x64_cache.c b/frida_mode/src/instrument/instrument_x64_cache.c new file mode 100644 index 00000000..3ea4421a --- /dev/null +++ b/frida_mode/src/instrument/instrument_x64_cache.c @@ -0,0 +1,435 @@ +#include <sys/mman.h> +#include <sys/resource.h> + +#include "instrument.h" +#include "util.h" + +#if defined(__x86_64__) + + #define INVALID 1 + #define DEFAULT_CACHE_SIZE (256ULL << 20) + +gboolean instrument_cache_enabled = TRUE; +gsize instrument_cache_size = DEFAULT_CACHE_SIZE; +static gpointer *map_base = MAP_FAILED; + +void instrument_cache_config(void) { + + instrument_cache_enabled = (getenv("AFL_FRIDA_INST_NO_CACHE") == NULL); + + if (getenv("AFL_FRIDA_INST_CACHE_SIZE") != NULL) { + + if (!instrument_cache_enabled) { + + FFATAL( + "AFL_FRIDA_INST_CACHE_SIZE incomatible with " + "AFL_FRIDA_INST_NO_CACHE"); + + } + + instrument_cache_size = + util_read_address("AFL_FRIDA_INST_CACHE_SIZE", DEFAULT_CACHE_SIZE); + util_log2(instrument_cache_size); + + } + +} + +void instrument_cache_init(void) { + + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache:" cYEL " [%c]", + instrument_cache_enabled ? 'X' : ' '); + if (!instrument_cache_enabled) { return; } + + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache size:" cYEL " [0x%016lX]", + instrument_cache_size); + + const struct rlimit data_limit = {.rlim_cur = RLIM_INFINITY, + .rlim_max = RLIM_INFINITY}; + + if (setrlimit(RLIMIT_AS, &data_limit) != 0) { + + FFATAL("Failed to setrlimit: %d", errno); + + } + + map_base = + gum_memory_allocate(NULL, instrument_cache_size, instrument_cache_size, + GUM_PAGE_READ | GUM_PAGE_WRITE); + if (map_base == MAP_FAILED) { FFATAL("Failed to map segment: %d", errno); } + + FOKF(cBLU "Instrumentation" cRST " - " cGRN "cache addr:" cYEL " [0x%016lX]", + GUM_ADDRESS(map_base)); + +} + +static gpointer *instrument_cache_get_addr(gpointer addr) { + + gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1; + return &map_base[GPOINTER_TO_SIZE(addr) & mask]; + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + if (!instrument_cache_enabled) { return; } + + gpointer *target = instrument_cache_get_addr(real_address); + if (*target == code_address) { + + return; + + } else if (*target == NULL) { + + *target = code_address; + + } else { + + *target = GSIZE_TO_POINTER(INVALID); + + } + +} + +static gboolean instrument_cache_relocate(GumAddress old_pc, GumAddress new_pc, + gint32 old_offset, + gint32 *new_offset) { + + guint64 old_target = old_pc + old_offset; + gint64 relocated = old_target - new_pc; + + if (relocated > G_MAXINT32 || relocated < G_MININT32) { return FALSE; } + + *new_offset = relocated; + return TRUE; + +} + +static void instrument_cache_rewrite_branch_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + cs_x86 * x86 = &instr->detail->x86; + guint8 modified[sizeof(instr->bytes)] = {0}; + guint8 offset = 0; + guint8 skip = 0; + + g_assert(sizeof(x86->prefix) == 4); + g_assert(sizeof(x86->opcode) == 4); + + /* + * If the target is simply RAX, we can skip writing the code to load the + * RIP + */ + if (x86->operands[0].type == X86_OP_REG || + x86->operands[0].reg == X86_REG_RAX) { + + return; + + } + + /* Write the prefix */ + for (gsize i = 0; i < sizeof(x86->prefix); i++) { + + if (x86->prefix[i] != 0) { + + if (x86->prefix[i] == 0xf2) { + + skip++; + + } else { + + modified[offset++] = x86->prefix[i]; + skip++; + + } + + } + + } + + /* Write the REX */ + if (x86->rex == 0) { + + /* + * CALL (near) and JMP (near) default to 64-bit operands, MOV does not, + * write REX.W + */ + modified[offset++] = 0x48; + + } else { + + if ((x86->rex & 0xF8) != 0x40) { + + FATAL("Unexpected REX byte: 0x%02x", x86->rex); + + } + + modified[offset++] = x86->rex | 0x08; + skip++; + + } + + /* + * CALL is FF /2, JMP is FF /4. The remaining op-code fields should thus be + * unused + */ + + if (x86->opcode[0] != 0xFF || x86->opcode[1] != 0x00 || + x86->opcode[2] != 0x00 || x86->opcode[3] != 0x00) { + + FFATAL("Unexpected Op-code: 0x%02x 0x%02x 0x%02x 0x%02x", x86->opcode[0], + x86->opcode[1], x86->opcode[2], x86->opcode[3]); + + } + + /* The reg field of the ModRM should be set to 2 for CALL and 4 for JMP */ + guint8 reg = (x86->modrm >> 3) & 7; + if (reg != 0x4 && reg != 0x2) { + + FFATAL("Unexpected Reg: 0x%02x, ModRM: 0x%02x", reg, x86->modrm); + + } + + /* MOV */ + modified[offset++] = 0x8b; + skip++; + + /* Clear the reg field (RAX) */ + modified[offset++] = x86->modrm & 0xc7; + skip++; + + /* Operands */ + guint8 op_len = instr->size - skip; + + /* If our branch was RIP relative, we'll need to fix-up the offset */ + if (x86->operands[0].type == X86_OP_MEM && + x86->operands[0].mem.base == X86_REG_RIP) { + + /* RIP relative offsets should be 32-bits */ + if (op_len != sizeof(gint32)) { + + FFATAL("Unexpected operand length: %d\n", op_len); + + } + + gint32 old_offset = *(gint32 *)&instr->bytes[skip]; + gint32 new_offset = 0; + if (instrument_cache_relocate(instr->address, cw->pc, old_offset, + &new_offset)) { + + gint32 *output = (gint32 *)&modified[offset]; + *output = new_offset; + offset += sizeof(gint32); + + } else { + + GumAddress target = instr->address + old_offset; + gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RAX, target); + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_RAX, GUM_REG_RAX); + return; + + } + + } else { + + for (int i = 0; i < op_len; i++) { + + guint8 val = instr->bytes[i + skip]; + modified[offset++] = val; + + } + + } + + gum_x86_writer_put_bytes(cw, modified, offset); + +} + +static void instrument_cache_write_push_frame(GumX86Writer *cw) { + + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer))), + GUM_REG_XAX); + gum_x86_writer_put_lahf(cw); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer))), + GUM_REG_XAX); + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer))), + GUM_REG_XBX); + +} + +static void instrument_cache_write_pop_frame(GumX86Writer *cw) { + + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XBX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (3 * sizeof(gpointer)))); + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XAX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (2 * sizeof(gpointer)))); + gum_x86_writer_put_sahf(cw); + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XAX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer)))); + +} + +static void instrument_cache_write_lookup(GumX86Writer *cw) { + + /* &map_base[GPOINTER_TO_SIZE(addr) & MAP_MASK]; */ + + gsize mask = (instrument_cache_size / sizeof(gpointer)) - 1; + gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, mask); + gum_x86_writer_put_and_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX); + gum_x86_writer_put_shl_reg_u8(cw, GUM_REG_XAX, util_log2(sizeof(gpointer))); + gum_x86_writer_put_mov_reg_u64(cw, GUM_REG_XBX, GPOINTER_TO_SIZE(map_base)); + gum_x86_writer_put_add_reg_reg(cw, GUM_REG_XAX, GUM_REG_XBX); + + /* Read the return address lookup */ + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XAX); + +} + +void instrument_cache_jmp_call(const cs_insn *instr, GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + cs_x86 * x86 = &instr->detail->x86; + + if (x86->op_count != 1) { FFATAL("Unexpected operand count"); } + + if (x86->operands[0].type == X86_OP_IMM) { return; } + + gconstpointer null = cw->code; + + instrument_cache_write_push_frame(cw); + + /* + * We are about to re-write the CALL or JMP instruction, but replace the + * op-code with that for a MOV into RAX. Since we are keeping the operand from + * the JMP exactly the same, it is imperative that the target register state + * be exactly the same as how the target left it. Since `LAHF` spoils `RAX` we + * must restore it from the stack. We also must avoid adjusting `RSP`, so we + * use `MOV` instructions to store our context into the stack beyond the + * red-zone. + */ + gum_x86_writer_put_mov_reg_reg_offset_ptr( + cw, GUM_REG_XAX, GUM_REG_XSP, + -(GUM_RED_ZONE_SIZE + (1 * sizeof(gpointer)))); + + instrument_cache_rewrite_branch_insn(instr, output); + + instrument_cache_write_lookup(cw); + + /* Test if its set*/ + gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID); + gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY); + + /* If it's set, then stash the address beyond the red-zone */ + gum_x86_writer_put_mov_reg_offset_ptr_reg( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer))), + GUM_REG_XAX); + + if (instr->id == X86_INS_JMP) { + + instrument_cache_write_pop_frame(cw); + gum_x86_writer_put_jmp_reg_offset_ptr( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + (4 * sizeof(gpointer)))); + + } else { + + gum_x86_writer_put_mov_reg_address( + cw, GUM_REG_XAX, GUM_ADDRESS(instr->address + instr->size)); + gum_x86_writer_put_mov_reg_offset_ptr_reg(cw, GUM_REG_XSP, + -sizeof(gpointer), GUM_REG_XAX); + + instrument_cache_write_pop_frame(cw); + + gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_XSP, GUM_REG_XSP, + -sizeof(gpointer)); + gum_x86_writer_put_jmp_reg_offset_ptr( + cw, GUM_REG_XSP, -(GUM_RED_ZONE_SIZE + ((4 - 1) * sizeof(gpointer)))); + + } + + /* Tidy up our mess and let FRIDA handle it */ + gum_x86_writer_put_label(cw, null); + instrument_cache_write_pop_frame(cw); + +} + +void instrument_cache_ret(const cs_insn *instr, GumStalkerOutput *output) { + + GumX86Writer *cw = output->writer.x86; + cs_x86 * x86 = &instr->detail->x86; + guint16 n = 0; + + if (x86->op_count != 0) { + + if (x86->operands[0].type != X86_OP_IMM) { + + FFATAL("Unexpected operand type"); + + } + + n = x86->operands[0].imm; + + } + + gconstpointer null = cw->code; + + instrument_cache_write_push_frame(cw); + + gum_x86_writer_put_mov_reg_reg_ptr(cw, GUM_REG_XAX, GUM_REG_XSP); + + instrument_cache_write_lookup(cw); + + /* Test if its set*/ + gum_x86_writer_put_cmp_reg_i32(cw, GUM_REG_XAX, INVALID); + gum_x86_writer_put_jcc_short_label(cw, X86_INS_JLE, null, GUM_UNLIKELY); + + /* If it's set, then overwrite our return address and return */ + gum_x86_writer_put_mov_reg_ptr_reg(cw, GUM_REG_XSP, GUM_REG_XAX); + instrument_cache_write_pop_frame(cw); + + if (n == 0) { + + gum_x86_writer_put_ret(cw); + + } else { + + gum_x86_writer_put_ret_imm(cw, n); + + } + + /* Tidy up our mess and let FRIDA handle it */ + gum_x86_writer_put_label(cw, null); + instrument_cache_write_pop_frame(cw); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + if (!instrument_cache_enabled) { return; } + + switch (instr->id) { + + case X86_INS_RET: + instrument_cache_ret(instr, output); + break; + + case X86_INS_CALL: + case X86_INS_JMP: + instrument_cache_jmp_call(instr, output); + break; + + default: + return; + + } + +} + +#endif + diff --git a/frida_mode/src/instrument/instrument_x86.c b/frida_mode/src/instrument/instrument_x86.c index c4e93324..6a899248 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -6,6 +6,9 @@ #if defined(__i386__) +gboolean instrument_cache_enabled = FALSE; +gsize instrument_cache_size = 0; + static GHashTable *coverage_blocks = NULL; #pragma pack(push, 1) @@ -218,6 +221,14 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_insn(const cs_insn * instr, + GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + void instrument_coverage_optimize_init(void) { } @@ -234,5 +245,27 @@ gpointer instrument_cur(GumStalkerOutput *output) { } +void instrument_cache_config(void) { + +} + +void instrument_cache_init(void) { + +} + +void instrument_cache_insert(gpointer real_address, gpointer code_address) { + + UNUSED_PARAMETER(real_address); + UNUSED_PARAMETER(code_address); + +} + +void instrument_cache(const cs_insn *instr, GumStalkerOutput *output) { + + UNUSED_PARAMETER(instr); + UNUSED_PARAMETER(output); + +} + #endif diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 52e9e45c..c1c9d36f 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -69,6 +69,12 @@ class Afl { Afl.jsApiSetBackpatchDisable(); } /** + * See `AFL_FRIDA_INST_NO_CACHE`. + */ + static setCacheDisable() { + Afl.jsApiSetCacheDisable(); + } + /** * See `AFL_FRIDA_DEBUG_MAPS`. */ static setDebugMaps() { @@ -92,6 +98,13 @@ class Afl { Afl.jsApiAflSharedMemFuzzing.writeInt(1); } /** + * See `AFL_FRIDA_INST_CACHE_SIZE`. This function takes a single `number` + * as an argument. + */ + static setInstrumentCacheSize(size) { + Afl.jsApiSetInstrumentCacheSize(size); + } + /** * See `AFL_FRIDA_INST_COVERAGE_FILE`. This function takes a single `string` * as an argument. */ @@ -114,6 +127,12 @@ class Afl { Afl.jsApiSetInstrumentTrace(); } /** + * See `AFL_FRIDA_INST_INSN` + */ + static setInstrumentInstructions() { + Afl.jsApiSetInstrumentInstructions(); + } + /** * See `AFL_FRIDA_INST_JIT`. */ static setInstrumentJit() { @@ -293,10 +312,13 @@ Afl.jsApiAflSharedMemFuzzing = Afl.jsApiGetSymbol("__afl_sharedmem_fuzzing"); Afl.jsApiDone = Afl.jsApiGetFunction("js_api_done", "void", []); Afl.jsApiError = Afl.jsApiGetFunction("js_api_error", "void", ["pointer"]); Afl.jsApiSetBackpatchDisable = Afl.jsApiGetFunction("js_api_set_backpatch_disable", "void", []); +Afl.jsApiSetCacheDisable = Afl.jsApiGetFunction("js_api_set_cache_disable", "void", []); 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.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", []); Afl.jsApiSetInstrumentJit = Afl.jsApiGetFunction("js_api_set_instrument_jit", "void", []); Afl.jsApiSetInstrumentLibraries = Afl.jsApiGetFunction("js_api_set_instrument_libraries", "void", []); Afl.jsApiSetInstrumentNoOptimize = Afl.jsApiGetFunction("js_api_set_instrument_no_optimize", "void", []); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 94ec8842..7cc8ffc7 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -142,6 +142,13 @@ js_api_set_prefetch_backpatch_disable(void) { } +__attribute__((visibility("default"))) void js_api_set_instrument_instructions( + void) { + + instrument_coverage_insn = TRUE; + +} + __attribute__((visibility("default"))) void js_api_set_instrument_no_optimize( void) { @@ -255,6 +262,19 @@ __attribute__((visibility("default"))) void js_api_set_stalker_adjacent_blocks( } +__attribute__((visibility("default"))) void js_api_set_cache_disable(void) { + + instrument_cache_enabled = FALSE; + +} + +__attribute__((visibility("default"))) void js_api_set_instrument_cache_size( + gsize size) { + + instrument_cache_size = size; + +} + __attribute__((visibility("default"))) void js_api_set_js_main_hook( const js_main_hook_t hook) { diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index d8521300..bb6e4109 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -21,6 +21,7 @@ #include "intercept.h" #include "js.h" #include "lib.h" +#include "module.h" #include "output.h" #include "persistent.h" #include "prefetch.h" @@ -197,6 +198,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) { instrument_config(); js_config(); lib_config(); + module_config(); output_config(); persistent_config(); prefetch_config(); @@ -214,6 +216,7 @@ __attribute__((visibility("default"))) void afl_frida_start(void) { entry_init(); instrument_init(); lib_init(); + module_init(); persistent_init(); prefetch_init(); seccomp_init(); diff --git a/frida_mode/src/module.c b/frida_mode/src/module.c new file mode 100644 index 00000000..65b394cd --- /dev/null +++ b/frida_mode/src/module.c @@ -0,0 +1,106 @@ +#include "intercept.h" +#include "module.h" +#include "util.h" + +#if defined(__linux__) + #include <dlfcn.h> + #include <link.h> +#endif + +static guint page_size = 0; +static gboolean handle_dlclose = FALSE; + +void module_config(void) { + +#if defined(__linux__) + handle_dlclose = (getenv("AFL_FRIDA_NO_MODULE") == NULL); +#else + FWARNF("AFL_FRIDA_MODULE not supported"); +#endif + +} + +typedef struct { + + GumMemoryRange range; + GumPageProtection protection; + GumFileMapping file; + +} gum_range_t; + +gboolean found_range(const GumRangeDetails *details, gpointer user_data) { + + gum_range_t range = {0}; + GArray * ranges = (GArray *)user_data; + + range.range = *details->range; + range.protection = details->protection; + if (details->file != NULL) { range.file = *details->file; } + + g_array_append_val(ranges, range); + return FALSE; + +} + +#if defined(__linux__) +static int on_dlclose(void *handle) { + + GArray * ranges = NULL; + struct link_map *lm = NULL; + gum_range_t * range = NULL; + GumAddress base; + GumAddress limit; + gpointer mem; + + if (dlinfo(handle, RTLD_DI_LINKMAP, &lm) < 0) { + + FFATAL("Failed to dlinfo: %s", dlerror()); + + } + + FVERBOSE("on_dlclose: %s", lm->l_name); + + ranges = g_array_new(FALSE, TRUE, sizeof(gum_range_t)); + gum_module_enumerate_ranges(lm->l_name, GUM_PAGE_EXECUTE, found_range, + ranges); + + int ret = dlclose(handle); + if (ret != 0) { + + FWARNF("dlclose returned: %d (%s)", ret, dlerror()); + return ret; + + } + + for (guint i = 0; i < ranges->len; i++) { + + range = &g_array_index(ranges, gum_range_t, i); + base = range->range.base_address; + limit = base + range->range.size; + FVERBOSE("Reserving range: 0x%016lx, 0x%016lX", base, limit); + mem = gum_memory_allocate(GSIZE_TO_POINTER(base), range->range.size, + page_size, GUM_PAGE_NO_ACCESS); + if (mem == NULL) { FATAL("Failed to allocate %p (%d)", mem, errno); } + + } + + g_array_free(ranges, TRUE); + return 0; + +} + +#endif + +void module_init(void) { + + FOKF(cBLU "Module" cRST " - " cYEL " [%c]", handle_dlclose ? 'X' : ' '); + +#if defined(__linux__) + if (!handle_dlclose) { return; } + + page_size = gum_query_page_size(); + intercept_hook(dlclose, on_dlclose, NULL); +#endif + +} + diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 84803453..d47d1c14 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -595,8 +595,6 @@ void ranges_init(void) { ranges_inst_jit ? 'X' : ' '); FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]", ranges_inst_libs ? 'X' : ' '); - FOKF(cBLU "Ranges" cRST " - " cGRN "instrument libraries:" cYEL " [%c]", - ranges_inst_libs ? 'X' : ' '); print_ranges("include", include_ranges); print_ranges("exclude", exclude_ranges); |