예제 #1
0
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));
  }
}
예제 #2
0
파일: gum.c 프로젝트: frida/frida-gum
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);
}
예제 #3
0
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);
}
예제 #4
0
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;
      }
    }
  }
}
예제 #5
0
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);
}
예제 #6
0
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 = &range;
        details.prot = cur_prot;

        if (!func (&details, user_data))
          return;
      }
    }

    p += lc->cmdsize;
  }
}
예제 #7
0
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;
}
예제 #8
0
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 = &range;
    details.path = info->imageFilePath;

    carry_on = func (&details, user_data);

    g_free (name);

    if (!carry_on)
      break;
  }
}
예제 #9
0
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 = &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 = &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);
  }
}
예제 #11
0
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);
}
예제 #12
0
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);
  }
}
예제 #13
0
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);
}
예제 #14
0
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;
}
예제 #15
0
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
}
예제 #16
0
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
}
예제 #17
0
GumAddress
gum_module_find_base_address (const gchar * module_name)
{
  return GUM_ADDRESS (get_module_handle_utf8 (module_name));
}
예제 #18
0
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;
}
예제 #19
0
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
}
예제 #20
0
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 = &range;
    details.path = module_path;

    carry_on = func (&details, user_data);

    g_free (module_path);

    if (!carry_on)
      break;
  }

beach:
  g_free (modules);
}