diff options
Diffstat (limited to 'frida_mode/src')
21 files changed, 619 insertions, 253 deletions
diff --git a/frida_mode/src/entry.c b/frida_mode/src/entry.c index 186ddd3a..c51e202f 100644 --- a/frida_mode/src/entry.c +++ b/frida_mode/src/entry.c @@ -1,5 +1,9 @@ #include <dlfcn.h> +#if defined(__linux__) && !defined(__ANDROID__) + #include <sys/prctl.h> +#endif + #include "frida-gumjs.h" #include "debug.h" @@ -16,6 +20,7 @@ extern void __afl_manual_init(); guint64 entry_point = 0; +gboolean traceable = FALSE; gboolean entry_compiled = FALSE; gboolean entry_run = FALSE; @@ -26,21 +31,48 @@ static void entry_launch(void) { /* Child here */ entry_run = TRUE; + entry_on_fork(); instrument_on_fork(); seccomp_on_fork(); stats_on_fork(); } +#if defined(__linux__) && !defined(__ANDROID__) +void entry_on_fork(void) { + + if (traceable) { + + if (prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY) < 0) { + + FATAL("Failed to PR_SET_PTRACER"); + + } + + } + +} + +#else +void entry_on_fork(void) { + + if (traceable) { WARNF("AFL_FRIDA_TRACEABLE unsupported"); } + +} + +#endif + void entry_config(void) { entry_point = util_read_address("AFL_ENTRYPOINT"); + if (getenv("AFL_FRIDA_TRACEABLE") != NULL) { traceable = TRUE; } } void entry_init(void) { OKF("entry_point: 0x%016" G_GINT64_MODIFIER "X", entry_point); + OKF("dumpable: [%c]", traceable ? 'X' : ' '); if (dlopen(NULL, RTLD_NOW) == NULL) { FATAL("Failed to dlopen: %d", errno); } diff --git a/frida_mode/src/instrument/instrument.c b/frida_mode/src/instrument/instrument.c index fd0982f8..81d85aa1 100644 --- a/frida_mode/src/instrument/instrument.c +++ b/frida_mode/src/instrument/instrument.c @@ -341,8 +341,14 @@ void instrument_init(void) { * parallel fuzzing. The seed itself, doesn't have to be random, it * just needs to be different for each instance. */ + guint64 tid; +#if defined(__APPLE__) + pthread_threadid_np(NULL, &tid); +#else + tid = syscall(SYS_gettid); +#endif instrument_hash_seed = g_get_monotonic_time() ^ - (((guint64)getpid()) << 32) ^ syscall(SYS_gettid); + (((guint64)getpid()) << 32) ^ tid; } @@ -350,6 +356,7 @@ void instrument_init(void) { instrument_hash_seed); instrument_hash_zero = instrument_get_offset_hash(0); + instrument_coverage_optimize_init(); instrument_debug_init(); instrument_coverage_init(); asan_init(); diff --git a/frida_mode/src/instrument/instrument_arm32.c b/frida_mode/src/instrument/instrument_arm32.c index 0e15940a..4b0a648e 100644 --- a/frida_mode/src/instrument/instrument_arm32.c +++ b/frida_mode/src/instrument/instrument_arm32.c @@ -22,6 +22,10 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_init(void) { + WARNF("Optimized coverage not supported on this architecture"); +} + void instrument_flush(GumStalkerOutput *output) { gum_arm_writer_flush(output->writer.arm); diff --git a/frida_mode/src/instrument/instrument_arm64.c b/frida_mode/src/instrument/instrument_arm64.c index cf37e048..80d1d845 100644 --- a/frida_mode/src/instrument/instrument_arm64.c +++ b/frida_mode/src/instrument/instrument_arm64.c @@ -95,6 +95,9 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_init(void) { +} + void instrument_flush(GumStalkerOutput *output) { gum_arm64_writer_flush(output->writer.arm64); diff --git a/frida_mode/src/instrument/instrument_coverage.c b/frida_mode/src/instrument/instrument_coverage.c index 46c816bc..513df29a 100644 --- a/frida_mode/src/instrument/instrument_coverage.c +++ b/frida_mode/src/instrument/instrument_coverage.c @@ -711,7 +711,6 @@ void instrument_coverage_normal_init(void) { void instrument_coverage_unstable_find_output(void) { - pid_t parent = getpid(); gchar *fds_name = g_strdup_printf("/proc/%d/fd/", getppid()); gchar *root = g_file_read_link("/proc/self/root", NULL); diff --git a/frida_mode/src/instrument/instrument_x64.c b/frida_mode/src/instrument/instrument_x64.c index fec8afbb..a7eb650a 100644 --- a/frida_mode/src/instrument/instrument_x64.c +++ b/frida_mode/src/instrument/instrument_x64.c @@ -1,105 +1,307 @@ +#include <fcntl.h> +#include <stddef.h> +#include <sys/mman.h> +#include <sys/shm.h> + +#if defined(__linux__) +#if !defined(__ANDROID__) +#include <asm/prctl.h> +#include <sys/syscall.h> +#else +#include <linux/ashmem.h> +#endif +#endif + #include "frida-gumjs.h" #include "config.h" +#include "debug.h" #include "instrument.h" +#include "ranges.h" #if defined(__x86_64__) -static GumAddress current_log_impl = GUM_ADDRESS(0); +#ifndef MAP_FIXED_NOREPLACE + #ifdef MAP_EXCL + #define MAP_FIXED_NOREPLACE MAP_EXCL | MAP_FIXED + #else + #define MAP_FIXED_NOREPLACE MAP_FIXED + #endif +#endif -static const guint8 afl_log_code[] = { +gboolean instrument_is_coverage_optimize_supported(void) { - 0x9c, /* pushfq */ - 0x51, /* push rcx */ - 0x52, /* push rdx */ + return true; - 0x48, 0x8b, 0x0d, 0x26, - 0x00, 0x00, 0x00, /* mov rcx, sym.&previous_pc */ - 0x48, 0x8b, 0x11, /* mov rdx, qword [rcx] */ - 0x48, 0x31, 0xfa, /* xor rdx, rdi */ +} - 0x48, 0x03, 0x15, 0x11, - 0x00, 0x00, 0x00, /* add rdx, sym._afl_area_ptr_ptr */ +static gboolean instrument_coverage_in_range(gssize offset) { - 0x80, 0x02, 0x01, /* add byte ptr [rdx], 1 */ - 0x80, 0x12, 0x00, /* adc byte ptr [rdx], 0 */ - 0x66, 0xd1, 0xcf, /* ror di, 1 */ - 0x48, 0x89, 0x39, /* mov qword [rcx], rdi */ + return (offset >= G_MININT32 && offset <= G_MAXINT32); - 0x5a, /* pop rdx */ - 0x59, /* pop rcx */ - 0x9d, /* popfq */ +} - 0xc3, /* ret */ + #pragma pack(push, 1) +typedef struct { - 0x90 + // cur_location = (block_address >> 4) ^ (block_address << 8); + // shared_mem[cur_location ^ prev_location]++; + // prev_location = cur_location >> 1; - /* Read-only data goes here: */ - /* uint8_t* __afl_area_ptr */ - /* uint64_t* &previous_pc */ + // => 0x7ffff6cfb086: lea rsp,[rsp-0x80] + // 0x7ffff6cfb08b: pushf + // 0x7ffff6cfb08c: push rsi + // 0x7ffff6cfb08d: mov rsi,0x228 + // 0x7ffff6cfb094: xchg QWORD PTR [rip+0x3136a5],rsi # 0x7ffff700e740 + // 0x7ffff6cfb09b: xor rsi,0x451 + // 0x7ffff6cfb0a2: add BYTE PTR [rsi+0x10000],0x1 + // 0x7ffff6cfb0a9: adc BYTE PTR [rsi+0x10000],0x0 + // 0x7ffff6cfb0b0: pop rsi + // 0x7ffff6cfb0b1: popf + // 0x7ffff6cfb0b2: lea rsp,[rsp+0x80] -}; -gboolean instrument_is_coverage_optimize_supported(void) { + uint8_t lea_rsp_rsp_sub_rz[5]; + uint8_t push_fq; + uint8_t push_rsi; - return true; + uint8_t mov_rsi_curr_loc_shr_1[7]; + uint8_t xchg_rsi_prev_loc_curr_loc[7]; + uint8_t xor_rsi_curr_loc[7]; + + uint8_t add_rsi_1[7]; + uint8_t adc_rsi_0[7]; + + uint8_t pop_rsi; + uint8_t pop_fq; + uint8_t lsa_rsp_rsp_add_rz[8]; + +} 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 = + { + + .lea_rsp_rsp_sub_rz = {0x48, 0x8D, 0x64, 0x24, 0x80}, + .push_fq = 0x9c, + .push_rsi = 0x56, + + .mov_rsi_curr_loc_shr_1 = {0x48, 0xC7, 0xC6}, + .xchg_rsi_prev_loc_curr_loc = {0x48, 0x87, 0x35}, + .xor_rsi_curr_loc = {0x48, 0x81, 0xF6}, + + .add_rsi_1 = {0x80, 0x86, 0x00, 0x00, 0x00, 0x00, 0x01}, + .adc_rsi_0 = {0x80, 0x96, 0x00, 0x00, 0x00, 0x00, 0x00}, + + .pop_rsi = 0x5E, + .pop_fq = 0x9D, + .lsa_rsp_rsp_add_rz = {0x48, 0x8D, 0xA4, 0x24, 0x80, 0x00, 0x00, 0x00}, } -static guint8 align_pad[] = {0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90, 0x90}; +; -static void instrument_coverate_write_function(GumStalkerOutput *output) { +static gboolean instrument_coverage_find_low(const GumRangeDetails *details, + gpointer user_data) { - guint64 misalign = 0; - GumX86Writer *cw = output->writer.x86; + static GumAddress last_limit = (64ULL << 10); + gpointer * address = (gpointer *)user_data; - 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)) { + if ((details->range->base_address - last_limit) > __afl_map_size) { - gconstpointer after_log_impl = cw->code + 1; + *address = GSIZE_TO_POINTER(last_limit); + return FALSE; - gum_x86_writer_put_jmp_near_label(cw, after_log_impl); + } - misalign = (cw->pc & 0x7); - if (misalign != 0) { + if (details->range->base_address > ((2ULL << 20) - __afl_map_size)) { - gum_x86_writer_put_bytes(cw, align_pad, 8 - misalign); + return FALSE; - } + } + + last_limit = details->range->base_address + details->range->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"); } + +} - current_log_impl = cw->pc; - gum_x86_writer_put_bytes(cw, afl_log_code, sizeof(afl_log_code)); +static void instrument_coverage_optimize_map_shm(guint64 shm_env_val, + gpointer address) { - uint64_t *afl_prev_loc_ptr = &instrument_previous_pc; - gum_x86_writer_put_bytes(cw, (const guint8 *)&__afl_area_ptr, - sizeof(__afl_area_ptr)); - gum_x86_writer_put_bytes(cw, (const guint8 *)&afl_prev_loc_ptr, - sizeof(afl_prev_loc_ptr)); + if (shmdt(__afl_area_ptr) != 0) { - gum_x86_writer_put_label(cw, after_log_impl); + 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); + + OKF("Low address: %p", low_address); + + if (low_address == 0 || + GPOINTER_TO_SIZE(low_address) > ((2UL << 20) - __afl_map_size)) { + + FATAL("Invalid low_address: %p", low_address); + + } + + ranges_print_debug_maps(); + + char *shm_env = getenv(SHM_ENV_VAR); + OKF("SHM_ENV_VAR: %s", shm_env); + + if (shm_env == NULL) { + + WARNF("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); + + } + + } + + OKF("__afl_area_ptr: %p", __afl_area_ptr); + OKF("instrument_previous_pc: %p", &instrument_previous_pc); + +} + 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); - - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - -GUM_RED_ZONE_SIZE); - gum_x86_writer_put_push_reg(cw, GUM_REG_RDI); - gum_x86_writer_put_mov_reg_address(cw, GUM_REG_RDI, area_offset); - gum_x86_writer_put_call_address(cw, current_log_impl); - gum_x86_writer_put_pop_reg(cw, GUM_REG_RDI); - gum_x86_writer_put_lea_reg_reg_offset(cw, GUM_REG_RSP, GUM_REG_RSP, - GUM_RED_ZONE_SIZE); + GumAddress code_addr = 0; + + // gum_x86_writer_put_breakpoint(cw); + code_addr = cw->pc; + code.code = template; + + gssize curr_loc_shr_1_offset = + offsetof(afl_log_code, code.mov_rsi_curr_loc_shr_1) + + sizeof(code.code.mov_rsi_curr_loc_shr_1) - sizeof(guint32); + + *((guint32 *)&code.bytes[curr_loc_shr_1_offset]) = + (guint32)(area_offset >> 1); + + gssize prev_loc_value = + GPOINTER_TO_SIZE(&instrument_previous_pc) - + (code_addr + offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) + + sizeof(code.code.xchg_rsi_prev_loc_curr_loc)); + gssize prev_loc_value_offset = + offsetof(afl_log_code, code.xchg_rsi_prev_loc_curr_loc) + + sizeof(code.code.xchg_rsi_prev_loc_curr_loc) - sizeof(gint); + if (!instrument_coverage_in_range(prev_loc_value)) { + + FATAL("Patch out of range (current_pc_value1): 0x%016lX", prev_loc_value); + + } + + *((gint *)&code.bytes[prev_loc_value_offset]) = (gint)prev_loc_value; + + gssize xor_curr_loc_offset = offsetof(afl_log_code, code.xor_rsi_curr_loc) + + sizeof(code.code.xor_rsi_curr_loc) - + sizeof(guint32); + + *((guint32 *)&code.bytes[xor_curr_loc_offset]) = (guint32)(area_offset); + + gssize add_rsi_1_offset = offsetof(afl_log_code, code.add_rsi_1) + + sizeof(code.code.add_rsi_1) - sizeof(guint32) - 1; + + *((guint32 *)&code.bytes[add_rsi_1_offset]) = + (guint32)GPOINTER_TO_SIZE(__afl_area_ptr); + + gssize adc_rsi_0_ffset = offsetof(afl_log_code, code.adc_rsi_0) + + sizeof(code.code.adc_rsi_0) - sizeof(guint32) - 1; + + *((guint32 *)&code.bytes[adc_rsi_0_ffset]) = + (guint32)GPOINTER_TO_SIZE(__afl_area_ptr); + + 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 7bf48f96..1ff5c920 100644 --- a/frida_mode/src/instrument/instrument_x86.c +++ b/frida_mode/src/instrument/instrument_x86.c @@ -83,6 +83,9 @@ void instrument_coverage_optimize(const cs_insn * instr, } +void instrument_coverage_optimize_init(void) { +} + void instrument_flush(GumStalkerOutput *output) { gum_x86_writer_flush(output->writer.x86); diff --git a/frida_mode/src/js/api.js b/frida_mode/src/js/api.js index 40bb4a16..6f9f05d8 100644 --- a/frida_mode/src/js/api.js +++ b/frida_mode/src/js/api.js @@ -243,6 +243,12 @@ class Afl { const buf = Memory.allocUtf8String(file); Afl.jsApiSetStdOut(buf); } + /** + * See `AFL_FRIDA_TRACEABLE`. + */ + static setTraceable() { + Afl.jsApiSetTraceable(); + } static jsApiGetFunction(name, retType, argTypes) { const addr = Afl.module.getExportByName(name); return new NativeFunction(addr, retType, argTypes); @@ -286,6 +292,7 @@ Afl.jsApiSetStatsFile = Afl.jsApiGetFunction("js_api_set_stats_file", "void", [" Afl.jsApiSetStatsInterval = Afl.jsApiGetFunction("js_api_set_stats_interval", "void", ["uint64"]); Afl.jsApiSetStdErr = Afl.jsApiGetFunction("js_api_set_stderr", "void", ["pointer"]); Afl.jsApiSetStdOut = Afl.jsApiGetFunction("js_api_set_stdout", "void", ["pointer"]); +Afl.jsApiSetTraceable = Afl.jsApiGetFunction("js_api_set_traceable", "void", []); Afl.jsApiWrite = new NativeFunction( /* tslint:disable-next-line:no-null-keyword */ Module.getExportByName(null, "write"), "int", ["int", "pointer", "int"]); diff --git a/frida_mode/src/js/js_api.c b/frida_mode/src/js/js_api.c index 9dba79aa..f3d81a32 100644 --- a/frida_mode/src/js/js_api.c +++ b/frida_mode/src/js/js_api.c @@ -231,3 +231,9 @@ __attribute__((visibility("default"))) void js_api_set_stalker_ic_entries( } +__attribute__((visibility("default"))) void js_api_set_traceable(void) { + + traceable = TRUE; + +} + diff --git a/frida_mode/src/main.c b/frida_mode/src/main.c index c0de9c6b..c8183d8f 100644 --- a/frida_mode/src/main.c +++ b/frida_mode/src/main.c @@ -6,6 +6,7 @@ #ifdef __APPLE__ #include <mach/mach.h> #include <mach-o/dyld_images.h> + #include <crt_externs.h> #else #include <sys/wait.h> #include <sys/personality.h> @@ -90,6 +91,7 @@ static void embedded_init(void) { static void afl_print_cmdline(void) { +#if defined(__linux__) char * buffer = g_malloc0(PROC_MAX); gchar *fname = g_strdup_printf("/proc/%d/cmdline", getppid()); int fd = open(fname, O_RDONLY); @@ -123,6 +125,17 @@ static void afl_print_cmdline(void) { close(fd); g_free(fname); g_free(buffer); +#elif defined(__APPLE__) + int idx; + char **argv = *_NSGetArgv(); + int nargv = *_NSGetArgc(); + + for (idx = 0; idx < nargv; idx ++) { + + OKF("AFL - COMMANDLINE: argv[%d] = %s", idx, argv[idx]); + + } +#endif } diff --git a/frida_mode/src/prefetch.c b/frida_mode/src/prefetch.c index 0efbc9bf..c30ca65c 100644 --- a/frida_mode/src/prefetch.c +++ b/frida_mode/src/prefetch.c @@ -44,8 +44,9 @@ static void gum_afl_stalker_backpatcher_notify(GumStalkerObserver *self, sizeof(prefetch_data->backpatch_data) - prefetch_data->backpatch_size; if (sizeof(gsize) + size > remaining) { return; } - *(gsize *)(&prefetch_data->backpatch_data[prefetch_data->backpatch_size]) = - size; + gsize *dst_backpatch_size = (gsize *) + &prefetch_data->backpatch_data[prefetch_data->backpatch_size]; + *dst_backpatch_size = size; prefetch_data->backpatch_size += sizeof(gsize); memcpy(&prefetch_data->backpatch_data[prefetch_data->backpatch_size], @@ -115,7 +116,8 @@ static void prefetch_read_patches(void) { remaining > sizeof(gsize); remaining = prefetch_data->backpatch_size - offset) { - gsize size = *(gsize *)(&prefetch_data->backpatch_data[offset]); + gsize *src_backpatch_data = (gsize *)&prefetch_data->backpatch_data[offset]; + gsize size = *src_backpatch_data; offset += sizeof(gsize); if (prefetch_data->backpatch_size - offset < size) { diff --git a/frida_mode/src/ranges.c b/frida_mode/src/ranges.c index 5b6eb462..1b666fce 100644 --- a/frida_mode/src/ranges.c +++ b/frida_mode/src/ranges.c @@ -549,18 +549,19 @@ static GArray *merge_ranges(GArray *a) { } +void ranges_print_debug_maps(void) { + + gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, NULL); + +} + void ranges_config(void) { if (getenv("AFL_FRIDA_DEBUG_MAPS") != NULL) { ranges_debug_maps = TRUE; } if (getenv("AFL_INST_LIBS") != NULL) { ranges_inst_libs = TRUE; } if (getenv("AFL_FRIDA_INST_JIT") != NULL) { ranges_inst_jit = TRUE; } - if (ranges_debug_maps) { - - gum_process_enumerate_ranges(GUM_PAGE_NO_ACCESS, print_ranges_callback, - NULL); - - } + if (ranges_debug_maps) { ranges_print_debug_maps(); } include_ranges = collect_ranges("AFL_FRIDA_INST_RANGES"); exclude_ranges = collect_ranges("AFL_FRIDA_EXCLUDE_RANGES"); diff --git a/frida_mode/src/seccomp/seccomp.c b/frida_mode/src/seccomp/seccomp.c index 7683cd71..99111591 100644 --- a/frida_mode/src/seccomp/seccomp.c +++ b/frida_mode/src/seccomp/seccomp.c @@ -1,9 +1,3 @@ -#include <execinfo.h> -#include <fcntl.h> -#include <linux/seccomp.h> -#include <stdio.h> -#include <unistd.h> - #include "frida-gumjs.h" #include "debug.h" @@ -13,111 +7,15 @@ char *seccomp_filename = NULL; -static void seccomp_vprint(int fd, char *format, va_list ap) { - - char buffer[4096] = {0}; - int len; - - if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; } - - len = strnlen(buffer, sizeof(buffer)); - IGNORED_RETURN(write(fd, buffer, len)); - -} - -void seccomp_print(char *format, ...) { - - va_list ap; - va_start(ap, format); - seccomp_vprint(SECCOMP_OUTPUT_FILE_FD, format, ap); - va_end(ap); - -} - -static void seccomp_filter_callback(struct seccomp_notif * req, - struct seccomp_notif_resp *resp, - GumReturnAddressArray * frames) { - - GumDebugSymbolDetails details = {0}; - if (req->data.nr == SYS_OPENAT) { - - seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]); - - } - - seccomp_print( - "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx " - "0x%llx ]\n", - req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr), - req->data.args[0], req->data.args[1], req->data.args[2], - req->data.args[3], req->data.args[4], req->data.args[5]); - - seccomp_print("FRAMES: (%u)\n", frames->len); - char **syms = backtrace_symbols(frames->items, frames->len); - if (syms == NULL) { FATAL("Failed to get symbols"); } - - for (guint i = 0; i < frames->len; i++) { - - if (gum_symbol_details_from_address(frames->items[i], &details)) { - - seccomp_print("\t%3d. %s!%s\n", i, details.module_name, - details.symbol_name); - - } else { - - seccomp_print("\t%3d. %s\n", i, syms[i]); - - } - - } - - free(syms); - - resp->error = 0; - resp->val = 0; - resp->id = req->id; - resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE; - -} - -static void seccomp_child(int signal_parent, void *ctx) { - - int sock_fd = *((int *)ctx); - int fd = seccomp_socket_recv(sock_fd); - - if (close(sock_fd) < 0) { FATAL("child - close"); } - - seccomp_event_signal(signal_parent); - seccomp_filter_child_install(); - seccomp_filter_run(fd, seccomp_filter_callback); - -} - void seccomp_on_fork(void) { - int sock[2] = {-1, -1}; - pid_t child = -1; - int child_fd = -1; - if (seccomp_filename == NULL) { return; } - seccomp_socket_create(sock); - seccomp_child_run(seccomp_child, sock, &child, &child_fd); - - if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); } - - if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); } - - if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); } - - int fd = seccomp_filter_install(child); - seccomp_socket_send(sock[STDOUT_FILENO], fd); - - if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); } - - if (close(fd) < 0) { FATAL("grandparent - close (4)"); } - - seccomp_child_wait(SECCOMP_PARENT_EVENT_FD); +#ifdef __APPLE__ + FATAL("Seccomp not supported on OSX"); +#else + seccomp_callback_parent(); +#endif } @@ -129,29 +27,15 @@ void seccomp_config(void) { void seccomp_init(void) { - char *path = NULL; - int fd; - OKF("Seccomp - file [%s]", seccomp_filename); if (seccomp_filename == NULL) { return; } - path = g_canonicalize_filename(seccomp_filename, g_get_current_dir()); - - OKF("Seccomp - path [%s]", path); - - fd = open(path, O_RDWR | O_CREAT | O_TRUNC, - S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); - - if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) { - - FATAL("Failed to duplicate seccomp output file"); - - } - - if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); } - - g_free(path); +#ifdef __APPLE__ + FATAL("Seccomp not supported on OSX"); +#else + seccomp_callback_initialize(); +#endif } diff --git a/frida_mode/src/seccomp/seccomp_atomic.c b/frida_mode/src/seccomp/seccomp_atomic.c index 1720a726..c2042f97 100644 --- a/frida_mode/src/seccomp/seccomp_atomic.c +++ b/frida_mode/src/seccomp/seccomp_atomic.c @@ -1,7 +1,9 @@ -#include <stdbool.h> -#include <stdio.h> +#if defined(__linux__) && !defined(__ANDROID__) -#include "debug.h" + #include <stdbool.h> + #include <stdio.h> + + #include "debug.h" void seccomp_atomic_set(volatile bool *ptr, bool val) { @@ -26,3 +28,5 @@ void seccomp_atomic_wait(volatile bool *ptr, bool val) { } +#endif + diff --git a/frida_mode/src/seccomp/seccomp_callback.c b/frida_mode/src/seccomp/seccomp_callback.c new file mode 100644 index 00000000..4232d842 --- /dev/null +++ b/frida_mode/src/seccomp/seccomp_callback.c @@ -0,0 +1,144 @@ +#if defined(__linux__) && !defined(__ANDROID__) + +#if !defined(__MUSL__) + #include <execinfo.h> +#endif + #include <fcntl.h> + + #include "seccomp.h" + + #include "debug.h" + +static void seccomp_callback_filter(struct seccomp_notif * req, + struct seccomp_notif_resp *resp, + GumReturnAddressArray * frames) { + + GumDebugSymbolDetails details = {0}; + if (req->data.nr == SYS_OPENAT) { + +#if UINTPTR_MAX == 0xffffffffffffffffu + seccomp_print("SYS_OPENAT: (%s)\n", (char *)req->data.args[1]); +#endif +#if UINTPTR_MAX == 0xffffffff + seccomp_print("SYS_OPENAT: (%s)\n", (char *)(__u32)req->data.args[1]); +#endif + } + + seccomp_print( + "\nID (%#llx) for PID %d - %d (%s) [0x%llx 0x%llx 0x%llx 0x%llx 0x%llx " + "0x%llx ]\n", + req->id, req->pid, req->data.nr, seccomp_syscall_lookup(req->data.nr), + req->data.args[0], req->data.args[1], req->data.args[2], + req->data.args[3], req->data.args[4], req->data.args[5]); + +#if !defined(__MUSL__) + seccomp_print("FRAMES: (%u)\n", frames->len); + char **syms = backtrace_symbols(frames->items, frames->len); + if (syms == NULL) { FATAL("Failed to get symbols"); } + + for (guint i = 0; i < frames->len; i++) { + + if (gum_symbol_details_from_address(frames->items[i], &details)) { + + seccomp_print("\t%3d. %s!%s\n", i, details.module_name, + details.symbol_name); + + } else { + + seccomp_print("\t%3d. %s\n", i, syms[i]); + + } + + } + + free(syms); +#else + void **syms = (void **)__builtin_frame_address(0); + void *framep = __builtin_frame_address(1); + int i = 0; + + syms = framep; + while (syms) { + + framep = *syms; + syms = framep; + + if (!syms) break; + + seccomp_print("\%3d. %s\n", i ++, (char *)framep); + + } +#endif + + resp->error = 0; + resp->val = 0; + resp->id = req->id; + resp->flags = SECCOMP_USER_NOTIF_FLAG_CONTINUE; + +} + +static void seccomp_callback_child(int signal_parent, void *ctx) { + + int sock_fd = *((int *)ctx); + int fd = seccomp_socket_recv(sock_fd); + + if (close(sock_fd) < 0) { FATAL("child - close"); } + + seccomp_event_signal(signal_parent); + seccomp_filter_child_install(); + seccomp_filter_run(fd, seccomp_callback_filter); + +} + +void seccomp_callback_parent(void) { + + int sock[2] = {-1, -1}; + pid_t child = -1; + int child_fd = -1; + + seccomp_socket_create(sock); + seccomp_child_run(seccomp_callback_child, sock, &child, &child_fd); + + if (dup2(child_fd, SECCOMP_PARENT_EVENT_FD) < 0) { FATAL("dup2"); } + + if (close(child_fd) < 0) { FATAL("seccomp_on_fork - close (1)"); } + + if (close(sock[STDIN_FILENO]) < 0) { FATAL("grandparent - close (2)"); } + + int fd = seccomp_filter_install(child); + seccomp_socket_send(sock[STDOUT_FILENO], fd); + + if (close(sock[STDOUT_FILENO]) < 0) { FATAL("grandparent - close (3)"); } + + if (close(fd) < 0) { FATAL("grandparent - close (4)"); } + + seccomp_child_wait(SECCOMP_PARENT_EVENT_FD); + +} + +void seccomp_callback_initialize(void) { + + char *path = NULL; + int fd; + + path = g_canonicalize_filename(seccomp_filename, g_get_current_dir()); + + OKF("Seccomp - path [%s]", path); + + fd = open(path, O_RDWR | O_CREAT | O_TRUNC, + S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP); + + if (dup2(fd, SECCOMP_OUTPUT_FILE_FD) < 0) { + + FATAL("Failed to duplicate seccomp output file"); + + } + + if (close(fd) < 0) { FATAL("Failed to close seccomp output file fd"); } + + g_free(path); + +} + +#endif + diff --git a/frida_mode/src/seccomp/seccomp_child.c b/frida_mode/src/seccomp/seccomp_child.c index 4d494137..43a79894 100644 --- a/frida_mode/src/seccomp/seccomp_child.c +++ b/frida_mode/src/seccomp/seccomp_child.c @@ -1,18 +1,20 @@ -#include <fcntl.h> -#include <sched.h> -#include <signal.h> -#include <stdio.h> -#include <stdlib.h> -#include <sys/mman.h> -#include <sys/prctl.h> -#include <sys/types.h> -#include <unistd.h> +#if defined(__linux__) && !defined(__ANDROID__) -#include "debug.h" + #include <fcntl.h> + #include <sched.h> + #include <signal.h> + #include <stdio.h> + #include <stdlib.h> + #include <sys/mman.h> + #include <sys/prctl.h> + #include <sys/types.h> + #include <unistd.h> -#include "seccomp.h" + #include "debug.h" -#define SECCOMP_CHILD_STACK_SIZE (1UL << 20) + #include "seccomp.h" + + #define SECCOMP_CHILD_STACK_SIZE (1UL << 20) typedef void (*seccomp_child_func_t)(int event_fd, void *ctx); @@ -67,3 +69,5 @@ void seccomp_child_wait(int event_fd) { } +#endif + diff --git a/frida_mode/src/seccomp/seccomp_event.c b/frida_mode/src/seccomp/seccomp_event.c index ecb9be32..e2f592ca 100644 --- a/frida_mode/src/seccomp/seccomp_event.c +++ b/frida_mode/src/seccomp/seccomp_event.c @@ -1,15 +1,17 @@ -#include <stdint.h> -#include <stdio.h> -#include <sys/eventfd.h> -#include <unistd.h> +#if defined(__linux__) && !defined(__ANDROID__) -#include "debug.h" + #include <stdint.h> + #include <stdio.h> + #include <sys/syscall.h> + #include <unistd.h> -#include "seccomp.h" + #include "debug.h" + + #include "seccomp.h" int seccomp_event_create(void) { - int fd = eventfd(0, 0); + int fd = syscall(SYS_eventfd, 0, 0); if (fd < 0) { FATAL("seccomp_event_create"); } return fd; @@ -43,3 +45,5 @@ void seccomp_event_destroy(int fd) { } +#endif + diff --git a/frida_mode/src/seccomp/seccomp_filter.c b/frida_mode/src/seccomp/seccomp_filter.c index c16e7ebd..7ee5ead1 100644 --- a/frida_mode/src/seccomp/seccomp_filter.c +++ b/frida_mode/src/seccomp/seccomp_filter.c @@ -1,27 +1,30 @@ -#include <alloca.h> -#include <errno.h> -#include <execinfo.h> -#include <linux/filter.h> -#include <linux/seccomp.h> -#include <sys/ioctl.h> -#include <sys/prctl.h> -#include <sys/syscall.h> -#include <signal.h> -#include <stdbool.h> -#include <stddef.h> -#include <stdio.h> -#include <stdlib.h> -#include <string.h> -#include <unistd.h> - -#include "debug.h" - -#include "frida-gumjs.h" - -#include "seccomp.h" -#include "util.h" - -#define SECCOMP_FILTER_NUM_FRAMES 512 +#if defined(__linux__) && !defined(__ANDROID__) + + #include <alloca.h> + #include <errno.h> +#if !defined(__MUSL__) + #include <execinfo.h> +#endif + #include <linux/filter.h> + #include <sys/ioctl.h> + #include <sys/prctl.h> + #include <sys/syscall.h> + #include <signal.h> + #include <stdbool.h> + #include <stddef.h> + #include <stdio.h> + #include <stdlib.h> + #include <string.h> + #include <unistd.h> + + #include "debug.h" + + #include "frida-gumjs.h" + + #include "seccomp.h" + #include "util.h" + + #define SECCOMP_FILTER_NUM_FRAMES 512 extern void gum_linux_parse_ucontext(const ucontext_t *uc, GumCpuContext *ctx); @@ -127,7 +130,10 @@ static GumBacktracer * seccomp_filter_backtracer = NULL; static void seccomp_filter_child_handler(int sig, siginfo_t *info, void *ucontext) { - GumCpuContext cpu_context; + UNUSED_PARAMETER(sig); + UNUSED_PARAMETER(info); + UNUSED_PARAMETER(ucontext); + if (seccomp_filter_backtracer == NULL) { seccomp_filter_backtracer = gum_backtracer_make_fuzzy(); @@ -150,7 +156,8 @@ static void seccomp_filter_parent_handler(int sig, siginfo_t *info, ucontext_t *uc = (ucontext_t *)ucontext; gum_linux_parse_ucontext(uc, &seccomp_filter_cpu_context); - if (tgkill(seccomp_filter_child, seccomp_filter_child, SIGUSR1) < 0) { + if (syscall(SYS_tgkill, seccomp_filter_child, seccomp_filter_child, SIGUSR1) < + 0) { FATAL("kill"); @@ -256,3 +263,5 @@ void seccomp_filter_run(int fd, seccomp_filter_callback_t callback) { } +#endif + diff --git a/frida_mode/src/seccomp/seccomp_print.c b/frida_mode/src/seccomp/seccomp_print.c new file mode 100644 index 00000000..3cea1239 --- /dev/null +++ b/frida_mode/src/seccomp/seccomp_print.c @@ -0,0 +1,30 @@ +#if defined(__linux__) && !defined(__ANDROID__) + + #include <stdarg.h> + + #include "seccomp.h" + #include "util.h" + +static void seccomp_print_v(int fd, char *format, va_list ap) { + + char buffer[4096] = {0}; + int len; + + if (vsnprintf(buffer, sizeof(buffer) - 1, format, ap) < 0) { return; } + + len = strnlen(buffer, sizeof(buffer)); + IGNORED_RETURN(write(fd, buffer, len)); + +} + +void seccomp_print(char *format, ...) { + + va_list ap; + va_start(ap, format); + seccomp_print_v(SECCOMP_OUTPUT_FILE_FD, format, ap); + va_end(ap); + +} + +#endif + diff --git a/frida_mode/src/seccomp/seccomp_socket.c b/frida_mode/src/seccomp/seccomp_socket.c index ca42e158..ef937420 100644 --- a/frida_mode/src/seccomp/seccomp_socket.c +++ b/frida_mode/src/seccomp/seccomp_socket.c @@ -1,11 +1,13 @@ -#include <stdio.h> -#include <string.h> -#include <sys/socket.h> -#include <unistd.h> +#if defined(__linux__) && !defined(__ANDROID__) -#include "debug.h" + #include <stdio.h> + #include <string.h> + #include <sys/socket.h> + #include <unistd.h> -#include "seccomp.h" + #include "debug.h" + + #include "seccomp.h" union cmsg { @@ -119,3 +121,5 @@ int seccomp_socket_recv(int sockfd) { } +#endif + diff --git a/frida_mode/src/seccomp/seccomp_syscall.c b/frida_mode/src/seccomp/seccomp_syscall.c index b2c084c8..8335b93c 100644 --- a/frida_mode/src/seccomp/seccomp_syscall.c +++ b/frida_mode/src/seccomp/seccomp_syscall.c @@ -1,9 +1,11 @@ -#include <limits.h> -#include <stdio.h> +#if defined(__linux__) && !defined(__ANDROID__) -#include "debug.h" + #include <limits.h> + #include <stdio.h> -#include "seccomp.h" + #include "debug.h" + + #include "seccomp.h" typedef struct { @@ -333,3 +335,5 @@ char *seccomp_syscall_lookup(int id) { } +#endif + |