diff options
Diffstat (limited to 'frida_mode/src/module.c')
-rw-r--r-- | frida_mode/src/module.c | 106 |
1 files changed, 106 insertions, 0 deletions
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 + +} + |