Ejemplo n.º 1
0
void
gum_darwin_enumerate_exports (mach_port_t task,
                              const gchar * module_name,
                              GumFoundExportFunc func,
                              gpointer user_data)
{
    GumEnumerateExportsContext ctx;

    ctx.task = task;
    ctx.modules = g_hash_table_new_full (g_str_hash, g_str_equal,
                                         g_free, (GDestroyNotify) g_variant_unref);
    ctx.module_name = module_name;
    ctx.func = func;
    ctx.user_data = user_data;

    gum_darwin_enumerate_modules (task, gum_store_module_address, &ctx);

    gum_do_enumerate_exports (&ctx, module_name);

    g_hash_table_unref (ctx.modules);
}
Ejemplo n.º 2
0
static gboolean
gum_do_enumerate_exports (GumEnumerateExportsContext * ctx,
                          const gchar * module_name)
{
  gboolean carry_on = TRUE;
  GVariant * address_value;
  GumAddress address;
  guint8 * chunk = NULL;
  gsize chunk_size;
  struct mach_header * header;
  gint64 slide;
  GumAddress linkedit;
  GSList * text_section_ids = NULL;
  struct symtab_command * sc;
  gsize symbol_size;
  guint8 * symbols = NULL;
  GumAddress strings_address;
  gchar * strings;
  guint8 * cur_sym;
  guint symbol_index;

  address_value = g_hash_table_lookup (ctx->modules, module_name);
  if (address_value == NULL)
    goto beach;

  address = g_variant_get_uint64 (address_value);
  if (address == 0)
    goto beach;

  chunk = gum_darwin_read (ctx->task, address, MAX_MACH_HEADER_SIZE,
      &chunk_size);
  if (chunk == NULL)
    goto beach;
  header = (struct mach_header *) chunk;

  if (!gum_darwin_find_slide (address, chunk, chunk_size, &slide))
    goto beach;

  if (!gum_darwin_find_linkedit (chunk, chunk_size, &linkedit))
    goto beach;
  linkedit += slide;

  text_section_ids = gum_darwin_find_text_section_ids (chunk, chunk_size);

  if (!gum_darwin_find_symtab_command (chunk, chunk_size, &sc))
    goto beach;

  if (header->magic == MH_MAGIC)
    symbol_size = sizeof (struct nlist);
  else
    symbol_size = sizeof (struct nlist_64);
  symbols = gum_darwin_read (ctx->task, linkedit + sc->symoff,
      sc->nsyms * symbol_size, NULL);
  if (symbols == NULL)
    goto beach;

  strings_address = linkedit + sc->stroff;
  strings = g_hash_table_lookup (ctx->strings,
      GSIZE_TO_POINTER (strings_address));
  if (strings == NULL)
  {
    strings = (gchar *) gum_darwin_read (ctx->task,
        strings_address, sc->strsize, NULL);
    if (strings == NULL)
      goto beach;
    g_hash_table_insert (ctx->strings, GSIZE_TO_POINTER (strings_address),
        strings);
  }

  cur_sym = symbols;
  for (symbol_index = 0; symbol_index != sc->nsyms; symbol_index++)
  {
    GumExportDetails details;

    details.name = NULL;

    if (header->magic == MH_MAGIC)
    {
      struct nlist * sym = (struct nlist *) cur_sym;
      if (!SYMBOL_IS_UNDEFINED_DEBUG_OR_LOCAL (sym))
      {
        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 (strings + sym->n_un.n_strx);
        details.address = sym->n_value + slide;
        if ((sym->n_desc & N_ARM_THUMB_DEF) != 0)
          details.address++;
      }
    }
    else
    {
      struct nlist_64 * sym = (struct nlist_64 *) cur_sym;
      if (!SYMBOL_IS_UNDEFINED_DEBUG_OR_LOCAL (sym))
      {
        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 (strings + sym->n_un.n_strx);
        details.address = sym->n_value + slide;
        if ((sym->n_desc & N_ARM_THUMB_DEF) != 0)
          details.address++;
      }
    }

    if (details.name != NULL)
    {
      if (!ctx->func (&details, ctx->user_data))
      {
        carry_on = FALSE;
        break;
      }
    }

    cur_sym += symbol_size;
  }

  if (carry_on)
  {
    guint8 * cur_cmd;
    guint cmd_index;

    if (header->magic == MH_MAGIC)
      cur_cmd = chunk + sizeof (struct mach_header);
    else
      cur_cmd = chunk + sizeof (struct mach_header_64);
    for (cmd_index = 0; cmd_index != header->ncmds; cmd_index++)
    {
      struct load_command * lc = (struct load_command *) cur_cmd;

      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_do_enumerate_exports (ctx, name))
        {
          carry_on = FALSE;
          break;
        }
      }

      cur_cmd += lc->cmdsize;
    }
  }

beach:
  g_free (symbols);
  g_slist_free (text_section_ids);
  g_free (chunk);

  return carry_on;
}