diff options
Diffstat (limited to 'frida_mode/src/cmplog/cmplog.c')
-rw-r--r-- | frida_mode/src/cmplog/cmplog.c | 91 |
1 files changed, 47 insertions, 44 deletions
diff --git a/frida_mode/src/cmplog/cmplog.c b/frida_mode/src/cmplog/cmplog.c index c65b98d0..8814f7f3 100644 --- a/frida_mode/src/cmplog/cmplog.c +++ b/frida_mode/src/cmplog/cmplog.c @@ -1,7 +1,9 @@ #include <errno.h> #include <fcntl.h> #include <limits.h> -#include <syscall.h> +#include <sys/mman.h> +#include <sys/syscall.h> +#include <unistd.h> #include "frida-gum.h" @@ -13,12 +15,13 @@ #define MAX_MEMFD_SIZE (64UL << 10) extern struct cmp_map *__afl_cmp_map; -static GArray *cmplog_ranges = NULL; -static GHashTable * hash = NULL; +static GArray * cmplog_ranges = NULL; +static GHashTable * hash_yes = NULL; +static GHashTable * hash_no = NULL; -static int memfd = -1; -static size_t memfd_size = 0; -static u8 scratch[MAX_MEMFD_SIZE] = {0}; +static long page_size = 0; +static long page_offset_mask = 0; +static long page_mask = 0; static gboolean cmplog_range(const GumRangeDetails *details, gpointer user_data) { @@ -41,19 +44,10 @@ static void cmplog_get_ranges(void) { OKF("CMPLOG - Collecting ranges"); - cmplog_ranges = - g_array_sized_new(false, false, sizeof(GumMemoryRange), 100); + cmplog_ranges = g_array_sized_new(false, false, sizeof(GumMemoryRange), 100); gum_process_enumerate_ranges(GUM_PAGE_READ, cmplog_range, cmplog_ranges); g_array_sort(cmplog_ranges, cmplog_sort); - for (guint i = 0; i < cmplog_ranges->len; i++) { - - GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i); - - } - - g_array_free(cmplog_ranges, TRUE); - } void cmplog_init(void) { @@ -71,16 +65,22 @@ void cmplog_init(void) { } - memfd = syscall(__NR_memfd_create, "cmplog_memfd", 0); - if (memfd < 0) { + page_size = sysconf(_SC_PAGE_SIZE); + page_offset_mask = page_size - 1; + page_mask = ~(page_offset_mask); + + hash_yes = g_hash_table_new(g_direct_hash, g_direct_equal); + if (hash_yes == NULL) { - FATAL("Failed to create_memfd, errno: %d", errno); + FATAL("Failed to g_hash_table_new, errno: %d", errno); } - hash = g_hash_table_new (g_direct_hash, g_direct_equal); - if (hash == NULL) { + hash_no = g_hash_table_new(g_direct_hash, g_direct_equal); + if (hash_no == NULL) { + FATAL("Failed to g_hash_table_new, errno: %d", errno); + } } @@ -94,38 +94,41 @@ static gboolean cmplog_contains(GumAddress inner_base, GumAddress inner_limit, gboolean cmplog_test_addr(guint64 addr, size_t size) { - if (g_hash_table_contains(hash, (gpointer)addr)) { return true; } + if (g_hash_table_contains(hash_yes, (gpointer)addr)) { return true; } + if (g_hash_table_contains(hash_no, (gpointer)addr)) { return false; } - if (memfd_size > MAX_MEMFD_SIZE) { - if (lseek(memfd, 0, SEEK_SET) < 0) { - FATAL("CMPLOG - Failed lseek, errno: %d", errno); - } - } + void * page_addr = (void *)(addr & page_mask); + size_t page_offset = addr & page_offset_mask; + + /* If it spans a page, then bail */ + if (page_size - page_offset < size) { return false; } /* - * Our address map can change (e.g. stack growth), use write as a fallback to + * Our address map can change (e.g. stack growth), use msync as a fallback to * validate our address. */ - ssize_t written = syscall(SYS_write, memfd, (void *)addr, size); - if (written < 0 && errno != EFAULT && errno != 0) { - FATAL("CMPLOG - Failed __NR_write, errno: %d", errno); - } - /* - * If the write succeeds, then the buffer must be valid otherwise it would - * return EFAULT - */ - if (written > 0) { memfd_size += written; } + if (msync(page_addr, page_offset + size, MS_ASYNC) < 0) { + + if (!g_hash_table_add(hash_no, (gpointer)addr)) { - if ((size_t)written == size) { - if (!g_hash_table_add (hash, (gpointer)addr)) { FATAL("Failed - g_hash_table_add"); + } - return true; - } + return false; + } else { + + if (!g_hash_table_add(hash_yes, (gpointer)addr)) { + + FATAL("Failed - g_hash_table_add"); + + } + + return true; + + } - return false; } gboolean cmplog_is_readable(guint64 addr, size_t size) { @@ -152,8 +155,8 @@ gboolean cmplog_is_readable(guint64 addr, size_t size) { GumMemoryRange *range = &g_array_index(cmplog_ranges, GumMemoryRange, i); - GumAddress outer_base = range->base_address; - GumAddress outer_limit = outer_base + range->size; + GumAddress outer_base = range->base_address; + GumAddress outer_limit = outer_base + range->size; if (cmplog_contains(inner_base, inner_limit, outer_base, outer_limit)) return true; |