GumAddress gum_module_find_export_by_name (const gchar * module_name, const gchar * symbol_name) { if (module_name == NULL) { GumFindExportContext ctx; ctx.symbol_name = symbol_name; ctx.result = 0; gum_process_enumerate_modules (gum_store_address_if_module_has_export, &ctx); return ctx.result; } else { HMODULE module; module = get_module_handle_utf8 (module_name); if (module == NULL) return 0; return GUM_ADDRESS (GetProcAddress (module, symbol_name)); } }
static void gum_on_ffi_deallocate (void * base_address, size_t size) { GumMemoryRange range; range.base_address = GUM_ADDRESS (base_address); range.size = size; gum_cloak_remove_range (&range); }
void gum_module_enumerate_ranges (const gchar * module_name, GumPageProtection prot, GumFoundRangeFunc func, gpointer user_data) { HANDLE this_process = GetCurrentProcess (); HMODULE module; MODULEINFO mi; guint8 * cur_base_address, * end_address; module = get_module_handle_utf8 (module_name); if (module == NULL) return; if (!GetModuleInformation (this_process, module, &mi, sizeof (mi))) return; cur_base_address = (guint8 *) mi.lpBaseOfDll; end_address = (guint8 *) mi.lpBaseOfDll + mi.SizeOfImage; do { MEMORY_BASIC_INFORMATION mbi; SIZE_T ret; ret = VirtualQuery (cur_base_address, &mbi, sizeof (mbi)); g_assert (ret != 0); if (mbi.Protect != 0) { GumPageProtection cur_prot; cur_prot = gum_page_protection_from_windows (mbi.Protect); if ((cur_prot & prot) == prot) { GumMemoryRange range; GumRangeDetails details; range.base_address = GUM_ADDRESS (cur_base_address); range.size = mbi.RegionSize; details.range = ⦥ details.prot = cur_prot; details.file = NULL; /* TODO */ if (!func (&details, user_data)) return; } } cur_base_address += mbi.RegionSize; } while (cur_base_address < end_address); }
void gum_module_enumerate_exports (const gchar * module_name, GumFoundExportFunc func, gpointer user_data) { gpointer module; const guint8 * mod_base; const IMAGE_DOS_HEADER * dos_hdr; const IMAGE_NT_HEADERS * nt_hdrs; const IMAGE_DATA_DIRECTORY * entry; const IMAGE_EXPORT_DIRECTORY * exp; const guint8 * exp_begin, * exp_end; module = get_module_handle_utf8 (module_name); if (module == NULL) return; mod_base = (const guint8 *) module; dos_hdr = (const IMAGE_DOS_HEADER *) module; nt_hdrs = (const IMAGE_NT_HEADERS *) &mod_base[dos_hdr->e_lfanew]; entry = &nt_hdrs->OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_EXPORT]; exp = (const IMAGE_EXPORT_DIRECTORY *)(mod_base + entry->VirtualAddress); exp_begin = mod_base + entry->VirtualAddress; exp_end = exp_begin + entry->Size - 1; if (exp->AddressOfNames != 0) { const DWORD * name_rvas, * func_rvas; const WORD * ord_rvas; DWORD index; name_rvas = (const DWORD *) &mod_base[exp->AddressOfNames]; ord_rvas = (const WORD *) &mod_base[exp->AddressOfNameOrdinals]; func_rvas = (const DWORD *) &mod_base[exp->AddressOfFunctions]; for (index = 0; index < exp->NumberOfNames; index++) { DWORD func_rva; const guint8 * func_address; func_rva = func_rvas[ord_rvas[index]]; func_address = &mod_base[func_rva]; if (func_address < exp_begin || func_address > exp_end) { GumExportDetails details; details.type = GUM_EXPORT_FUNCTION; /* TODO: data exports */ details.name = (const gchar *) &mod_base[name_rvas[index]]; details.address = GUM_ADDRESS (func_address); if (!func (&details, user_data)) return; } } } }
GumAddress gum_module_find_base_address (const gchar * module_name) { gpointer address, slide; if (!find_image_address_and_slide (module_name, &address, &slide)) return 0; return GUM_ADDRESS (address); }
void gum_module_enumerate_ranges (const gchar * module_name, GumPageProtection prot, GumFoundRangeFunc func, gpointer user_data) { gpointer address, slide; gum_mach_header_t * header; guint8 * p; guint cmd_index; if (!find_image_address_and_slide (module_name, &address, &slide)) return; header = address; p = (guint8 *) (header + 1); for (cmd_index = 0; cmd_index != header->ncmds; cmd_index++) { struct load_command * lc = (struct load_command *) p; if (lc->cmd == GUM_LC_SEGMENT) { gum_segment_command_t * segcmd = (gum_segment_command_t *) lc; GumPageProtection cur_prot; cur_prot = gum_page_protection_from_mach (segcmd->initprot); if ((cur_prot & prot) == prot) { GumMemoryRange range; GumRangeDetails details; range.base_address = GUM_ADDRESS ( GSIZE_TO_POINTER (segcmd->vmaddr) + GPOINTER_TO_SIZE (slide)); range.size = segcmd->vmsize; details.range = ⦥ details.prot = cur_prot; if (!func (&details, user_data)) return; } } p += lc->cmdsize; } }
static void test_memory_access_monitor_fixture_setup (TestMAMonitorFixture * fixture, gconstpointer data) { fixture->range.base_address = GUM_ADDRESS (gum_alloc_n_pages (2, GUM_PAGE_RWX)); fixture->range.size = 2 * gum_query_page_size (); fixture->offset_in_first_page = gum_query_page_size () / 2; fixture->offset_in_second_page = fixture->offset_in_first_page + gum_query_page_size (); *((guint8 *) fixture->range.base_address) = 0xc3; /* ret instruction */ fixture->nop_function_in_first_page = GUM_POINTER_TO_FUNCPTR (GCallback, fixture->range.base_address); fixture->number_of_notifies = 0; fixture->monitor = NULL; }
void gum_process_enumerate_modules (GumFoundModuleFunc func, gpointer user_data) { const struct dyld_all_image_infos * all_info; guint count, i; if (get_all_image_infos_impl == NULL) { void * syslib; syslib = dlopen ("/usr/lib/libSystem.dylib", RTLD_LAZY | RTLD_GLOBAL); get_all_image_infos_impl = dlsym (syslib, "_dyld_get_all_image_infos"); g_assert (get_all_image_infos_impl != NULL); dlclose (syslib); } all_info = get_all_image_infos_impl (); count = all_info->infoArrayCount; for (i = 0; i != count; i++) { const struct dyld_image_info * info = &all_info->infoArray[i]; gchar * name; GumMemoryRange range; GumModuleDetails details; gboolean carry_on; name = g_path_get_basename (info->imageFilePath); range.base_address = GUM_ADDRESS (info->imageLoadAddress); range.size = find_image_size (info->imageFilePath); details.name = name; details.range = ⦥ details.path = info->imageFilePath; carry_on = func (&details, user_data); g_free (name); if (!carry_on) break; } }
void gum_process_enumerate_ranges (GumPageProtection prot, GumFoundRangeFunc func, gpointer user_data) { guint8 * cur_base_address; cur_base_address = NULL; while (TRUE) { MEMORY_BASIC_INFORMATION mbi; SIZE_T ret; ret = VirtualQuery (cur_base_address, &mbi, sizeof (mbi)); if (ret == 0) break; if (mbi.Protect != 0 && (mbi.Protect & PAGE_GUARD) == 0) { GumPageProtection cur_prot; cur_prot = gum_page_protection_from_windows (mbi.Protect); if ((cur_prot & prot) == prot) { GumMemoryRange range; GumRangeDetails details; range.base_address = GUM_ADDRESS (cur_base_address); range.size = mbi.RegionSize; details.range = ⦥ details.prot = cur_prot; details.file = NULL; /* TODO */ if (!func (&details, user_data)) return; } } cur_base_address += mbi.RegionSize; } }
static void gum_memory_access_monitor_enumerate_live_ranges (GumMemoryAccessMonitor * self, GumFoundLiveRangeFunc func, gpointer user_data) { GumMemoryAccessMonitorPrivate * priv = self->priv; guint i; gboolean carry_on = TRUE; for (i = 0; i != priv->num_ranges && carry_on; i++) { GumMemoryRange * r = &priv->ranges[i]; gpointer cur = GSIZE_TO_POINTER (r->base_address); gpointer end = GSIZE_TO_POINTER (r->base_address + r->size); do { MEMORY_BASIC_INFORMATION mbi; SIZE_T size; GumLiveRangeDetails details; GumMemoryRange range; size = VirtualQuery (cur, &mbi, sizeof (mbi)); if (size == 0) break; /* force the iteration one page at a time */ size = MIN (mbi.RegionSize, self->priv->page_size); details.range = ⦥ details.prot = mbi.Protect; details.range_index = i; range.base_address = GUM_ADDRESS (cur); range.size = MIN ((gsize) ((guint8 *) end - (guint8 *) cur), size - ((guint8 *) cur - (guint8 *) mbi.BaseAddress)); carry_on = func (&details, user_data); cur = (guint8 *) mbi.BaseAddress + size; } while (cur < end && carry_on); } }
gboolean gum_symbol_details_from_address (gpointer address, GumSymbolDetails * details) { GumSymbolInfo si = { 0, }; IMAGEHLP_LINE64 li = { 0, }; DWORD displacement_dw; DWORD64 displacement_qw; BOOL has_sym_info, has_file_info; memset (details, 0, sizeof (GumSymbolDetails)); details->address = GUM_ADDRESS (address); si.sym_info.SizeOfStruct = sizeof (SYMBOL_INFO); si.sym_info.MaxNameLen = sizeof (si.sym_name_buf); li.SizeOfStruct = sizeof (li); dbghelp->Lock (); has_sym_info = dbghelp->SymFromAddr (GetCurrentProcess (), (DWORD64) address, &displacement_qw, &si.sym_info); if (has_sym_info) { HMODULE mod = GSIZE_TO_POINTER (si.sym_info.ModBase); GetModuleBaseNameA (GetCurrentProcess (), mod, details->module_name, sizeof (details->module_name) - 1); strcpy_s (details->symbol_name, sizeof (details->symbol_name), si.sym_info.Name); } has_file_info = dbghelp->SymGetLineFromAddr64 (GetCurrentProcess (), (DWORD64) address, &displacement_dw, &li); if (has_file_info) { strcpy_s (details->file_name, sizeof (details->file_name), li.FileName); details->line_number = li.LineNumber; } dbghelp->Unlock (); return (has_sym_info || has_file_info); }
void frida_agent_auto_ignorer_intercept_thread_creation (FridaAgentAutoIgnorer * self, GumInvocationContext * ic) { NativeThreadFunc thread_func; thread_func = GUM_POINTER_TO_FUNCPTR (NativeThreadFunc, gum_invocation_context_get_nth_argument (ic, 2)); if (GUM_MEMORY_RANGE_INCLUDES (&self->agent_range, GUM_ADDRESS (thread_func))) { FridaAutoInterceptContext * ctx; ctx = g_slice_new (FridaAutoInterceptContext); ctx->interceptor = g_object_ref (self->interceptor); ctx->thread_func = thread_func; ctx->thread_data = gum_invocation_context_get_nth_argument (ic, 3); gum_invocation_context_replace_nth_argument (ic, 2, GUM_FUNCPTR_TO_POINTER (frida_agent_auto_ignorer_thread_create_proxy)); gum_invocation_context_replace_nth_argument (ic, 3, ctx); } }
static void gum_code_deflector_dispatcher_free (GumCodeDeflectorDispatcher * dispatcher) { gum_memory_patch_code (dispatcher->address, dispatcher->original_size, (GumMemoryPatchApplyFunc) gum_remove_deflector, dispatcher); if (dispatcher->thunk != NULL) { GumMemoryRange range; gum_memory_release (dispatcher->thunk, dispatcher->thunk_size); range.base_address = GUM_ADDRESS (dispatcher->thunk); range.size = dispatcher->thunk_size; gum_cloak_remove_range (&range); } g_free (dispatcher->original_data); g_slist_foreach (dispatcher->callers, (GFunc) gum_code_deflector_free, NULL); g_slist_free (dispatcher->callers); g_slice_free (GumCodeDeflectorDispatcher, dispatcher); }
static gboolean gum_module_do_enumerate_exports (const gchar * module_name, GumFoundExportFunc func, gpointer user_data) { gboolean carry_on = TRUE; gpointer address, slide; gsize vmaddr, fileoff; GSList * text_section_ids = NULL; const struct symtab_command * sc; guint8 * table_base; gum_nlist_t * symbase, * sym; gchar * strbase; guint symbol_idx; if (!find_image_address_and_slide (module_name, &address, &slide)) goto beach; if (!find_image_vmaddr_and_fileoff (address, &vmaddr, &fileoff)) goto beach; text_section_ids = find_image_text_section_ids (address); if (!find_image_symtab_command (address, &sc)) goto beach; table_base = GSIZE_TO_POINTER (vmaddr - fileoff + GPOINTER_TO_SIZE (slide)); symbase = (gum_nlist_t *) (table_base + sc->symoff); strbase = (gchar *) (table_base + sc->stroff); for (symbol_idx = 0, sym = symbase; symbol_idx != sc->nsyms; symbol_idx++, sym++) { GumExportDetails details; if (SYMBOL_IS_UNDEFINED_DEBUG_OR_LOCAL (sym)) continue; details.type = g_slist_find (text_section_ids, GSIZE_TO_POINTER (sym->n_sect)) != NULL ? GUM_EXPORT_FUNCTION : GUM_EXPORT_VARIABLE; details.name = gum_symbol_name_from_darwin (strbase + sym->n_un.n_strx); details.address = GUM_ADDRESS ( GSIZE_TO_POINTER (sym->n_value) + GPOINTER_TO_SIZE (slide)); if ((sym->n_desc & N_ARM_THUMB_DEF) != 0) details.address++; carry_on = func (&details, user_data); if (!carry_on) goto beach; } { gum_mach_header_t * header = address; guint8 * p; guint cmd_index; p = (guint8 *) (header + 1); for (cmd_index = 0; cmd_index != header->ncmds; cmd_index++) { struct load_command * lc = (struct load_command *) p; if (lc->cmd == LC_REEXPORT_DYLIB) { struct dylib_command * dc = (struct dylib_command *) lc; const char * name = (const char *) (((guint8 *) dc) + dc->dylib.name.offset); if (!gum_module_do_enumerate_exports (name, func, user_data)) return FALSE; } p += lc->cmdsize; } } beach: g_slist_free (text_section_ids); return carry_on; }
static void gum_write_thunk (gpointer thunk, GumCodeDeflectorDispatcher * dispatcher) { # if defined (HAVE_ARM) GumThumbWriter tw; gum_thumb_writer_init (&tw, thunk); tw.pc = GUM_ADDRESS (dispatcher->thunk); gum_thumb_writer_put_push_regs (&tw, 2, ARM_REG_R9, ARM_REG_R12); gum_thumb_writer_put_call_address_with_arguments (&tw, GUM_ADDRESS (gum_code_deflector_dispatcher_lookup), 2, GUM_ARG_ADDRESS, GUM_ADDRESS (dispatcher), GUM_ARG_REGISTER, ARM_REG_LR); gum_thumb_writer_put_pop_regs (&tw, 2, ARM_REG_R9, ARM_REG_R12); gum_thumb_writer_put_bx_reg (&tw, ARM_REG_R0); gum_thumb_writer_clear (&tw); # elif defined (HAVE_ARM64) GumArm64Writer aw; gum_arm64_writer_init (&aw, thunk); aw.pc = GUM_ADDRESS (dispatcher->thunk); /* push {q0-q7} */ gum_arm64_writer_put_instruction (&aw, 0xadbf1fe6); gum_arm64_writer_put_instruction (&aw, 0xadbf17e4); gum_arm64_writer_put_instruction (&aw, 0xadbf0fe2); gum_arm64_writer_put_instruction (&aw, 0xadbf07e0); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X17, ARM64_REG_X18); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X15, ARM64_REG_X16); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X13, ARM64_REG_X14); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X11, ARM64_REG_X12); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X9, ARM64_REG_X10); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X7, ARM64_REG_X8); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X5, ARM64_REG_X6); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X3, ARM64_REG_X4); gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X1, ARM64_REG_X2); gum_arm64_writer_put_call_address_with_arguments (&aw, GUM_ADDRESS (gum_code_deflector_dispatcher_lookup), 2, GUM_ARG_ADDRESS, GUM_ADDRESS (dispatcher), GUM_ARG_REGISTER, ARM64_REG_LR); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X1, ARM64_REG_X2); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X3, ARM64_REG_X4); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X5, ARM64_REG_X6); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X7, ARM64_REG_X8); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X9, ARM64_REG_X10); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X11, ARM64_REG_X12); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X13, ARM64_REG_X14); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X15, ARM64_REG_X16); gum_arm64_writer_put_pop_reg_reg (&aw, ARM64_REG_X17, ARM64_REG_X18); /* pop {q0-q7} */ gum_arm64_writer_put_instruction (&aw, 0xacc107e0); gum_arm64_writer_put_instruction (&aw, 0xacc10fe2); gum_arm64_writer_put_instruction (&aw, 0xacc117e4); gum_arm64_writer_put_instruction (&aw, 0xacc11fe6); gum_arm64_writer_put_br_reg (&aw, ARM64_REG_X0); gum_arm64_writer_clear (&aw); # else (void) gum_code_deflector_dispatcher_lookup; # endif }
static void gum_insert_deflector (gpointer cave, GumInsertDeflectorContext * ctx) { # if defined (HAVE_ARM) GumCodeDeflectorDispatcher * dispatcher = ctx->dispatcher; GumThumbWriter tw; if (ctx->dedicated_target != NULL) { gboolean owner_is_arm; owner_is_arm = (GPOINTER_TO_SIZE (ctx->return_address) & 1) == 0; if (owner_is_arm) { GumArmWriter aw; gum_arm_writer_init (&aw, cave); aw.pc = ctx->pc; gum_arm_writer_put_ldr_reg_address (&aw, ARM_REG_PC, GUM_ADDRESS (ctx->dedicated_target)); gum_arm_writer_flush (&aw); g_assert (gum_arm_writer_offset (&aw) <= ctx->max_size); gum_arm_writer_clear (&aw); dispatcher->trampoline = GSIZE_TO_POINTER (ctx->pc); return; } gum_thumb_writer_init (&tw, cave); tw.pc = ctx->pc; gum_thumb_writer_put_ldr_reg_address (&tw, ARM_REG_PC, GUM_ADDRESS (ctx->dedicated_target)); } else { gum_thumb_writer_init (&tw, cave); tw.pc = ctx->pc; gum_thumb_writer_put_ldr_reg_address (&tw, ARM_REG_PC, GUM_ADDRESS (dispatcher->thunk) + 1); } gum_thumb_writer_flush (&tw); g_assert (gum_thumb_writer_offset (&tw) <= ctx->max_size); gum_thumb_writer_clear (&tw); dispatcher->trampoline = GSIZE_TO_POINTER (ctx->pc + 1); # elif defined (HAVE_ARM64) GumCodeDeflectorDispatcher * dispatcher = ctx->dispatcher; GumArm64Writer aw; gum_arm64_writer_init (&aw, cave); aw.pc = ctx->pc; if (ctx->dedicated_target != NULL) { gum_arm64_writer_put_push_reg_reg (&aw, ARM64_REG_X0, ARM64_REG_LR); gum_arm64_writer_put_ldr_reg_address (&aw, ARM64_REG_X0, GUM_ADDRESS (ctx->dedicated_target)); gum_arm64_writer_put_br_reg (&aw, ARM64_REG_X0); } else { gum_arm64_writer_put_ldr_reg_address (&aw, ARM64_REG_X0, GUM_ADDRESS (dispatcher->thunk)); gum_arm64_writer_put_br_reg (&aw, ARM64_REG_X0); } gum_arm64_writer_flush (&aw); g_assert (gum_arm64_writer_offset (&aw) <= ctx->max_size); gum_arm64_writer_clear (&aw); dispatcher->trampoline = GSIZE_TO_POINTER (ctx->pc); # else (void) gum_code_deflector_dispatcher_lookup; # endif }
GumAddress gum_module_find_base_address (const gchar * module_name) { return GUM_ADDRESS (get_module_handle_utf8 (module_name)); }
static void gum_x86_backtracer_generate (GumBacktracer * backtracer, const GumCpuContext * cpu_context, GumReturnAddressArray * return_addresses) { GumX86Backtracer * self = GUM_X86_BACKTRACER_CAST (backtracer); GumX86BacktracerPrivate * priv = self->priv; GumInvocationStack * invocation_stack; gsize * start_address; gsize first_address = 0; guint i; gsize * p; invocation_stack = gum_interceptor_get_current_stack (); if (cpu_context != NULL) start_address = GSIZE_TO_POINTER (GUM_CPU_CONTEXT_XSP (cpu_context)); else start_address = (gsize *) &backtracer; for (i = 0, p = start_address; p < start_address + 2048; p++) { gboolean valid = FALSE; gsize value; GumMemoryRange vr; if ((GPOINTER_TO_SIZE (p) & (4096 - 1)) == 0) { GumMemoryRange next_range; next_range.base_address = GUM_ADDRESS (p); next_range.size = 4096; if (!gum_memory_map_contains (priv->writable, &next_range)) break; } value = *p; vr.base_address = value - 6; vr.size = 6; if (value != first_address && value > 4096 + 6 && gum_memory_map_contains (priv->code, &vr)) { gsize translated_value; translated_value = GPOINTER_TO_SIZE (gum_invocation_stack_translate ( invocation_stack, GSIZE_TO_POINTER (value))); if (translated_value != value) { value = translated_value; valid = TRUE; } else { guint8 * code_ptr = GSIZE_TO_POINTER (value); if (*(code_ptr - 5) == OPCODE_CALL_NEAR_RELATIVE || *(code_ptr - 6) == OPCODE_CALL_NEAR_ABS_INDIRECT || *(code_ptr - 3) == OPCODE_CALL_NEAR_ABS_INDIRECT || *(code_ptr - 2) == OPCODE_CALL_NEAR_ABS_INDIRECT) { valid = TRUE; } } } if (valid) { return_addresses->items[i++] = GSIZE_TO_POINTER (value); if (i == G_N_ELEMENTS (return_addresses->items)) break; if (first_address == 0) first_address = value; } } return_addresses->len = i; }
static GumCodeDeflectorDispatcher * gum_code_deflector_dispatcher_new (const GumAddressSpec * caller, gpointer return_address, gpointer dedicated_target) { #if defined (HAVE_DARWIN) || (defined (HAVE_LINUX) && GLIB_SIZEOF_VOID_P == 4) GumCodeDeflectorDispatcher * dispatcher; GumProbeRangeForCodeCaveContext probe_ctx; GumInsertDeflectorContext insert_ctx; probe_ctx.caller = caller; probe_ctx.cave.base_address = 0; probe_ctx.cave.size = 0; gum_process_enumerate_modules (gum_probe_module_for_code_cave, &probe_ctx); if (probe_ctx.cave.base_address == 0) return NULL; dispatcher = g_slice_new0 (GumCodeDeflectorDispatcher); dispatcher->address = GSIZE_TO_POINTER (probe_ctx.cave.base_address); dispatcher->original_data = g_memdup (dispatcher->address, probe_ctx.cave.size); dispatcher->original_size = probe_ctx.cave.size; if (dedicated_target == NULL) { gsize thunk_size; GumMemoryRange range; thunk_size = gum_query_page_size (); dispatcher->thunk = gum_memory_allocate (NULL, thunk_size, thunk_size, GUM_PAGE_RW); dispatcher->thunk_size = thunk_size; gum_memory_patch_code (dispatcher->thunk, GUM_MAX_CODE_DEFLECTOR_THUNK_SIZE, (GumMemoryPatchApplyFunc) gum_write_thunk, dispatcher); range.base_address = GUM_ADDRESS (dispatcher->thunk); range.size = thunk_size; gum_cloak_add_range (&range); } insert_ctx.pc = GUM_ADDRESS (dispatcher->address); insert_ctx.max_size = dispatcher->original_size; insert_ctx.return_address = return_address; insert_ctx.dedicated_target = dedicated_target; insert_ctx.dispatcher = dispatcher; gum_memory_patch_code (dispatcher->address, dispatcher->original_size, (GumMemoryPatchApplyFunc) gum_insert_deflector, &insert_ctx); return dispatcher; #else (void) gum_insert_deflector; (void) gum_write_thunk; (void) gum_probe_module_for_code_cave; return NULL; #endif }
void gum_process_enumerate_modules (GumFoundModuleFunc func, gpointer user_data) { HANDLE this_process; HMODULE first_module; DWORD modules_size = 0; HMODULE * modules = NULL; guint mod_idx; this_process = GetCurrentProcess (); if (!EnumProcessModules (this_process, &first_module, sizeof (first_module), &modules_size)) { goto beach; } modules = (HMODULE *) g_malloc (modules_size); if (!EnumProcessModules (this_process, modules, modules_size, &modules_size)) { goto beach; } for (mod_idx = 0; mod_idx != modules_size / sizeof (HMODULE); mod_idx++) { MODULEINFO mi; WCHAR module_path_utf16[MAX_PATH]; gchar * module_path, * module_name; GumMemoryRange range; GumModuleDetails details; gboolean carry_on; if (!GetModuleInformation (this_process, modules[mod_idx], &mi, sizeof (mi))) { continue; } GetModuleFileNameW (modules[mod_idx], module_path_utf16, MAX_PATH); module_path_utf16[MAX_PATH - 1] = '\0'; module_path = g_utf16_to_utf8 ((const gunichar2 *) module_path_utf16, -1, NULL, NULL, NULL); module_name = strrchr (module_path, '\\') + 1; range.base_address = GUM_ADDRESS (mi.lpBaseOfDll); range.size = mi.SizeOfImage; details.name = module_name; details.range = ⦥ details.path = module_path; carry_on = func (&details, user_data); g_free (module_path); if (!carry_on) break; } beach: g_free (modules); }