Example #1
0
/** 
 * Display the symbol table 
 */
int		cmd_sym()
{
  elfshsect_t	*sct;
  elfsh_Sym	*symtab;
  regex_t	*tmp;
  int		num;
  char		logbuf[BUFSIZ];
  int		ret;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  symtab = elfsh_get_symtab(world.curjob->curfile, &num);
  if (symtab == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Can't retrieve symtab", -1);

  sct = elfsh_get_section_by_type(world.curjob->curfile, 
				  SHT_SYMTAB, 0, NULL, NULL, 0);
  snprintf(logbuf, BUFSIZ, " [SYMBOL TABLE]\n [Object %s]\n\n",
	   world.curjob->curfile->name);
  revm_output(logbuf);
  FIRSTREGX(tmp);
  
  ret = ds(world.curjob->curfile, sct, 
	   num, tmp, elfsh_get_symbol_name);
  
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ret);
}
Example #2
0
/**
 * Return the used offset in .strtab or -1 if failed 
 * @param file
 * @param s
 * @param name
 * @return
 */
int			elfsh_set_symbol_name(elfshobj_t	*file,
					      elfsh_Sym		*s,
					      char		*name)
{
  elfshsect_t		*sct;
  char			*str;
  u_int			len;
  u_int			new_len;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sanity checks */
  if (file == NULL || s == NULL || name == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		      "Invalid NULL parameter", -1);
  if (file->secthash[ELFSH_SECTION_SYMTAB] == NULL &&
      elfsh_get_symtab(file, NULL) == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Cannot retreive symbol table", -1);

  /* Also change the section name in .shstrtab if symbol is STT_SECTION */
  if (elfsh_get_symbol_type(s) == STT_SECTION)
    {
      sct = elfsh_get_section_from_sym(file, s);
      if (sct != NULL && elfsh_set_section_name(file, sct, name) < 0)
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
			  "Unable to get section from its symbol", -1);
    }


  /* Else use the symbol string table */
  if (file->secthash[ELFSH_SECTION_STRTAB]       == NULL || 
      file->secthash[ELFSH_SECTION_STRTAB]->data == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "No STRTAB available", NULL);

  /* Change the name */
  str = file->secthash[ELFSH_SECTION_STRTAB]->data;
  str += s->st_name;
  len = strlen(str);
  new_len = strlen(name);

  /* Do not allocate new place if possible */
  if (len > new_len)
    strncpy(str, name, new_len + 1);
  /* Append the name to .strtab */
  else
    s->st_name = elfsh_insert_in_strtab(file, name);

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (s->st_name));
}
Example #3
0
/**
 * sect name
 * sym  name 
 */
int		cmd_remove()
{
  elfshsect_t	*symtab;
  char		*name;
  int		err;
  char		logbuf[BUFSIZ];

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Checks (needed because the command takes variable amount of params) */
  if (!world.curjob->curcmd->param[0] || !world.curjob->curcmd->param[1])
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid parameters", -1);

  /* Lookup object name */
  name = revm_lookup_string(world.curjob->curcmd->param[1]);

  /* Remove a section */
  if (!strcmp(world.curjob->curcmd->param[0], "sect"))
    err = elfsh_remove_section(world.curjob->curfile, name);

  /* Remove a symbol after looking up symbol value */
  else if (!strcmp(world.curjob->curcmd->param[0], "sym"))
    {
      symtab = elfsh_get_symtab(world.curjob->curfile, NULL);
      if (!symtab)
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			  "Cannot find symbol table", -1);
      symtab = world.curjob->curfile->secthash[ELFSH_SECTION_SYMTAB];
      err = elfsh_remove_symbol(symtab, name);
    }

  /* Remove a segment */
  else if (!strcmp(world.curjob->curcmd->param[0], "phdr"))
    err = elfsh_remove_phdr(world.curjob->curfile, atoi(name));

  /* Error */
  else
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Unknown object type", -1);

  /* Report result */
  if (!world.state.revm_quiet)
    {
      snprintf(logbuf, BUFSIZ - 1,
	       " [*] Object removing %s.\n\n",
	       (err < 0 ? "failed" : "succesfull"));
      revm_output(logbuf);
    }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #4
0
/**
 * Fill symtab and dynsym hash table for _get_*_by_name functions
 * @param file target file
 * @return
 */
int		elfsh_init_symbol_hashtables(elfshobj_t *file)
{
  elfsh_Sym	*sym;
  int		idx;
  int		size;
  char		*actual;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  // THIS FUNCTION IS DISABLED (TEST)
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);

  if (file == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Invalid NULL parameter", -1);

  printf("Init symbol hash tables ! \n");

  hash_init(&file->symhash, ELFSH_SYMHASH_NAME, 100, ASPECT_TYPE_INT);
  hash_init(&file->dynsymhash, ELFSH_DYNSYMHASH_NAME, 100, ASPECT_TYPE_INT);

  /* Symtab */
  if (elfsh_get_symtab(file, &size))
    {
      sym = (elfsh_Sym *) file->secthash[ELFSH_SECTION_SYMTAB]->data;
      
      for (idx = 0; idx < size; idx++)
	{
	  actual = elfsh_get_symbol_name(file, sym + idx);
	  if (actual)
	    hash_add(&file->symhash, strdup(actual), (void *) idx);
	}
    }

  sym = (elfsh_Sym *) elfsh_get_dynsymtab(file, &size);
  
  /* Dynsym */
  if (sym)
    {
      for (idx = 0; idx < size; idx++)
	{
	  actual = elfsh_get_dynsymbol_name(file, sym + idx);
	  if (actual)
	    hash_add(&file->dynsymhash, strdup(actual), (void *) idx);
	}
    }

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #5
0
/**
 * Get symtab entry by vaddr 
 * @param file
 * @param vaddr
 * @param off
 * @param mode
 * @return
 */
elfsh_Sym	  *elfsh_get_symbol_by_value(elfshobj_t	*file,
					     eresi_Addr	vaddr,
					     int	*off,
					     int	mode)
{
  int		  num;
  elfsh_Sym	  *data;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  data = elfsh_get_symtab(file, &num);
  if (data == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Cannot retreive SYMTAB", NULL);

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 
		     (elfsh_get_sym_by_value(data, num, vaddr, off, mode)));
}
Example #6
0
/**
 * Return the symbol name giving its index in the symbol string table
 * No special case for SECTION symbol because the section names strings
 * have been duplicated in the symbol table.
 * @param file
 * @param s
 * @return
 */
char		*elfsh_get_symbol_name(elfshobj_t *file, elfsh_Sym *s)
{
  elfshsect_t	*sect;
  void		*data;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sanity checks */
  if (file == NULL || s == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", NULL);

  /* Load symtab if needed */
  if (file->secthash[ELFSH_SECTION_SYMTAB] == NULL &&
      elfsh_get_symtab(file, NULL) == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		      "Cannot retreive symbol table", NULL);

  /* Else use the symbol string table */
  sect = file->secthash[ELFSH_SECTION_STRTAB];
  if (!sect || !sect->data)
    {
      sect = elfsh_get_strtab(file, 0);
      if (!sect)
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		     "Unable to get STRTAB", NULL);
      data = sect->data;
    }
  else
    data = sect->data;
  
  /* A last check to avoid getting killed on corrupted symbol tables */
  if (!data)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, "<unreadable>");
  else if ((unsigned int) s->st_name > 
	   (unsigned int) file->secthash[ELFSH_SECTION_STRTAB]->shdr->sh_size)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, "<corrupted>");
  
  /* Return name */
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, ((char *) data + s->st_name));
}
Example #7
0
/**
 * The intermediate pass of theglobal algorithm for ET_REL injection
 * We fuze symbol tables from the ET_REL and the host binary
 *
 * @param file
 * @param rel
 * @return
 */
int		elfsh_fuse_etrel_symtab(elfshobj_t *file, elfshobj_t *rel)
{
    elfshsect_t	*sect;
    elfsh_Sym	newsym;
    elfsh_Half	type;
    u_int		index;
    char		sctname[BUFSIZ];
    elfsh_Sym	*sym;
    int		symnbr;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    sym = elfsh_get_symtab(rel, &symnbr);
    for (index = 0; index < symnbr; index++)
    {
        type = elfsh_get_symbol_type(sym + index);

        /* Avoid non-injectable symbols */
        if (type != STT_FUNC && type != STT_OBJECT)
            continue;

        if (sym[index].st_shndx >= rel->hdr->e_shnum)
            continue;

        /* Find target section in ET_REL */
        sect = elfsh_get_section_by_index(rel, sym[index].st_shndx, NULL, NULL);
        if (sect == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cant find extracted section in ET_REL\n", -1);

        /* Filter symbols using source section */
        if (sect->shdr->sh_type != SHT_PROGBITS || !sect->shdr->sh_size ||
                !elfsh_get_section_allocflag(sect->shdr))
            continue;

        /* Find corresponding inserted section in ET_EXEC */
        snprintf(sctname, sizeof(sctname), "%s%s", rel->name, sect->name);
        sect = elfsh_get_section_by_name(file, sctname, NULL, NULL, NULL);
        if (sect == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cant find inserted section in ET_EXEC\n", -1);

#if __DEBUG_RELADD__
        printf("[DEBUG_RELADD] Injected ET_REL symbol %-20s ["XFMT"] \n",
               elfsh_get_symbol_name(rel, sym + index),
               (eresi_Addr) (sect->shdr->sh_addr + sym[index].st_value));
#endif

        /* Add symbol in host file */
        newsym = elfsh_create_symbol(sect->shdr->sh_addr + sym[index].st_value,
                                     sym[index].st_size,
                                     elfsh_get_symbol_type(sym + index),
                                     elfsh_get_symbol_bind(sym + index),
                                     0, sect->index);

        if (elfsh_insert_symbol(file->secthash[ELFSH_SECTION_SYMTAB], &newsym,
                                elfsh_get_symbol_name(rel, sym + index)) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Unable to insert ET_REL symbol", -1);
    }

    /* Resynchronize sorted instances of symbol table */
    if (elfsh_sync_sorted_symtab(file->secthash[ELFSH_SECTION_SYMTAB]) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to synchronize host symtab", -1);

    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #8
0
/**
 * Match a list of function from symbol tables
 * @param funcreg Function regex (or not ?)
 * @param func_list the final function list
 */
int			trace_match_funcname(elfshobj_t *curfile, char *funcname, char ***func_list)
{
  regex_t		preg;
  char			**f_list;
  u_int			count = 0;
  elfshsect_t		*sect;
  int			num;
  elfsh_Sym		*symtab;
  elfsh_Sym		*sym;
  char			funcreg[256];
  char			addrname[256];
  size_t		len;
  eresi_Addr		addr;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  if (!funcname || !func_list)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Invalid parameters", -1);

  len = strlen(funcname);

  /* We don't want to strip some part of the submited function
   but if you find a function/regex of this size (for this purpose) ... */
  if (len > 255)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Function name is too long", -1);

  /* An address ? */
  if (IS_VADDR(funcname))
    {
      /* Retrieve the address */
      sscanf(funcname + 2, AFMT, &addr);

      /* Prealloc the list */
      XALLOC(__FILE__, __FUNCTION__, __LINE__, f_list, sizeof(char*)*2, -1);

      sym = elfsh_get_symbol_by_value(curfile, addr, 0, ELFSH_EXACTSYM);
      
      /* We have a symbol for this address */
      if (sym)
	{
	  f_list[0] = elfsh_get_symbol_name(curfile, sym);
	  f_list[1] = NULL;
	}
      else
	{
	  sym = elfsh_get_dynsymbol_by_value(curfile, addr, 0, ELFSH_EXACTSYM);

	  /* We have a dynamic symbol for this address */
	  if (sym)
	    {
	      f_list[0] = elfsh_get_dynsymbol_name(curfile, sym);
	      f_list[1] = NULL;
	    }
	  else
	    {
	      TRACE_GET_FUNC_NAME(addrname, 255, funcname);
	      
	      f_list[0] = strdup(addrname);
	      f_list[1] = NULL;
	    }
	}

      goto end;
    }

  /* Add ^ and $ if needed, else we will check too many things
     For example, someone wanna add "main" function, if we don't
     add those symbols, it will match __libc_start_main which is very
     special function and that can create problems and make the tracer
     useless */
  snprintf(funcreg, 255, "%s%s%s", 
	   funcname[0] != '^' ? "^" : "",
	   funcname,
	   funcname[len-1] != '$' ? "$" : "");

  /* Do we have a regex ? */
  if (regcomp(&preg, funcreg, 0) != 0)
    {
      XALLOC(__FILE__, __FUNCTION__, __LINE__, f_list, sizeof(char*)*2, -1);
      f_list[0] = funcname;
      f_list[1] = NULL;

      goto end;
    }

  /* Preallocation */
  XALLOC(__FILE__, __FUNCTION__, __LINE__, f_list, 
	 sizeof(char*) * TRACE_MATCH_ALLOCSTEP, -1);


  /* Total match case */
  if (TRACE_MATCH_ALL(funcname))
    {
      /* Match everything we can, symbol or not ! */
      trace_match_addrtable(curfile, &f_list, &count);
    }

  /**
   * Match on symbol table
   */
  symtab = elfsh_get_symtab(curfile, &num);
  
  if (symtab != NULL)
    { 
      sect = elfsh_get_section_by_type(curfile, 
				       SHT_SYMTAB, 0, NULL, NULL, 0);
      
      /* Match function regex in the symbol table */
      trace_match_symtab(sect, num, &preg, &f_list, &count, elfsh_get_symbol_name);
    }
      
  /**
   * Match on dynamic symbol table
   */
  symtab = elfsh_get_dynsymtab(curfile, &num);

  if (symtab != NULL)
    { 

      sect = elfsh_get_section_by_name(curfile, 
				      ELFSH_SECTION_NAME_ALTDYNSYM, 
				      NULL, NULL, &num);
      if (!sect)
	sect = elfsh_get_section_by_type(curfile, SHT_DYNSYM, 0, 
					NULL, NULL, &num);

      num /= sizeof(elfsh_Sym);

      /* Match function regex in the dynamic symbol table */
      trace_match_symtab(sect, num, &preg, &f_list, &count, elfsh_get_dynsymbol_name);
    }

  /* Do we get something ? */
  if (count == 0)
    {
      XFREE(__FILE__, __FUNCTION__, __LINE__, f_list);
      PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		   "Can't match a single function", -1);
    }

 end:

  /* Set final pointer */
  *func_list = f_list;
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #9
0
int		remap_cmd()
{
  elfshobj_t	*file;
  elfshsect_t	*cur;
  u_int		new_base;
  u_int		real_base = 0xffffffff;
  int		diff;
  int		i;
  int		cnt;
  u_int		count_raw = 0;
  u_int		count_pht = 0;
  u_int		count_sht = 0;
  u_int		count_ent = 0;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sanity checks */
  i = sscanf(world.curjob->curcmd->param[0], "0x%X", &new_base);
  if (new_base == 0 || i != 1) 
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid new base address", -1);
  file = world.curjob->curfile;

  if (elfsh_read_obj(file) < 0)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                      "Unable to read object file", -1);

  if (elfsh_get_symtab(file, NULL) < 0)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                      "Unable to read symbol table", -1);

  /* Calculate delta */
  real_base = elfsh_get_object_baseaddr(file);
  if (real_base == 0xffffffff)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Base address not found", -1);

  if (new_base & 0xfff)
    {
      revm_output(" [*] Base address adapted to be congruent pagesize \n");
      new_base &= 0xfffff000;
    }
  diff = new_base - real_base;
  printf(" [*] Delta is %08X \n", diff);

  /* Update entry point */
  if (file->hdr->e_entry > real_base)
    {
      file->hdr->e_entry += diff;
      count_ent++;
    }

  /* For all sections of the current object */
  for (cur = file->sectlist; cur != NULL; cur = cur->next) 
    {
      cnt = elfsh_relocate_section(cur, diff);
      if (cnt < 0)
	{
	  printf(" [*] MODREMAP : Section %s wont be relocated\n", cur->name);
	  continue;
	}
      count_raw += cnt;
    }

  /* Fixup SHT */
  count_sht += elfsh_reloc_sht(file, diff);

  /* Fixup PHT */
  count_pht += elfsh_reloc_pht(file, diff);

  /* Print msg */
  printf(" [*] Total number of modified references : %u \n"
         "\t PHT relocation : %u \n"
         "\t SHT relocation : %u \n"
         "\t ENT relocation : %u \n"
         "\t RAW relocation : %u \n",
         count_pht + count_sht + count_ent + count_raw,
         count_pht , count_sht , count_ent , count_raw);
  printf(" [*] Remapping at base %08X -OK-\n\n", new_base);

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #10
0
/**
 * @brief Copy the PLT of an ET_EXEC object for the ALTPLT technique.
 * and the GOT of an ET_EXEC object for the ALTGOT technique.
 * @param file Host file.
 * @param mod Always inject sections with size being a multiple of mod.
 * @return Success (0) or Error (-1).
 */
int		elfsh_relink_plt(elfshobj_t *file, u_int mod)
{
    elfshsect_t	*got;
    elfshsect_t   *plt;
    elfshsect_t	*symtab;
    elfshsect_t	*dynsym;
    elfshsect_t	*prolog;
    elfshsect_t	*extplt = NULL;
    elfshsect_t	*altgot = NULL; /* shut the nice talkative */
    elfshsect_t	*enew    = NULL; /* compiler also know as gcc */
    elfsh_Shdr	hdr;
    elfsh_Sym	*sym;
    elfsh_Sym	newsym;
    char		buf[BUFSIZ];
    u_int		off;
    u_int		entsz;
    int		mode;
    eresi_Addr	addr;
    char		*prologdata;
    u_int		sz;
    char		*name;
    u_char	ostype;
    eresi_Addr	diff;
    u_int		extplt_size;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    /* Get PLT */
    if (file->secthash[ELFSH_SECTION_ALTPLT] != NULL)
        PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
    plt = elfsh_get_plt(file, NULL);
    if (NULL == plt)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "PLT section not found", -1);
    entsz = elfsh_get_pltentsz(file);
    if (entsz < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Failed to get PLT entry size", -1);

    /* Get GOT (recent ld call it .got.plt) */
    got = elfsh_get_gotsct(file);
    if (NULL == got)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "GOT section not found", -1);

    /* Get symtabs */
    if (NULL == elfsh_get_dynsymtab(file, NULL))
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "DYNSYM not found", -1);
    if (NULL == elfsh_get_symtab(file, NULL))
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "SYMTAB not found", -1);

    /* Some fingerprint */
    ostype = elfsh_get_ostype(file);
    if (ostype == ELFSH_OS_ERROR)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Invalid OS target", -1);

    /* Insert alternative .plt */
    dynsym = file->secthash[ELFSH_SECTION_DYNSYM];
    symtab = file->secthash[ELFSH_SECTION_SYMTAB];

    /* FreeBSD and BeoS is incompatible with pre-interp injection */
    /* Solaris needs self-mutating code for ALTPLT technique */
    /* %gp offsets on ALPHA/MIPS requires data injection */
    ELFSH_SELECT_INJECTION(file,NULL,mode);

    /* Map .alt.plt.prolog on ALPHA, or .alt.got.prolog on MIPS */
    if (FILE_IS_MIPS(file) || FILE_IS_ALPHA64(file))
    {
        if (FILE_IS_MIPS(file))
        {
            name = ELFSH_SECTION_NAME_ALTGOTPROLOG;
            sz = 28;
        }
        else
        {
            name = ELFSH_SECTION_NAME_ALTPLTPROLOG;
            sz = 48;
        }
        prolog = elfsh_create_section(name);
        hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_EXECINSTR | SHF_ALLOC,
                                0, 0, sz, 0, 0, 0, 0);

        XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1);

        if (elfsh_insert_mapped_section(file,
                                        prolog, hdr, prologdata,
                                        mode, mod) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         ".alt.{plt,got}.prolog insertion failed", -1);

        enew = elfsh_get_section_by_name(file, name, NULL, NULL, NULL);
        if (enew == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         ".alt.{plt,got}.prolog insertion failed", -1);
        file->secthash[ELFSH_SECTION_ALTPLTPROLOG] = enew;
    }

    /* Map .alt.plt (or .pad.got on MIPS)

       On MIPS we use .pad.got in order to align .alt.got on a 0x1000
       bound boundary.

       On ALPHA and SPARC, .alt.plt will be relocated instead of .plt
    */
    sz = plt->shdr->sh_size;
    if (FILE_IS_MIPS(file))
    {
        addr = enew->shdr->sh_addr + enew->shdr->sh_size;
        if ((addr - (got->shdr->sh_addr)) % 1024)
            sz = 1024 - ((addr - (got->shdr->sh_addr)) % 1024);
        XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1);
        memset(prologdata, 0x00, sz);
        name = ELFSH_SECTION_NAME_PADGOT;
    }
    else
    {
        XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1);
        memcpy(prologdata, elfsh_readmem(plt), sz);
        name = ELFSH_SECTION_NAME_ALTPLT;
    }
    enew = elfsh_create_section(name);
    hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_EXECINSTR | SHF_ALLOC,
                            0, 0, sz, 0, 0, 0, 0);
    if (elfsh_insert_mapped_section(file, enew, hdr, prologdata, mode, mod) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     ".alt.plt|.pad.got insertion failed", -1);
    enew = elfsh_get_section_by_name(file, name, NULL, NULL, NULL);
    if (enew == NULL)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     ".alt.plt|.pad.got insertion failed", -1);
    file->secthash[ELFSH_SECTION_ALTPLT] = enew;


    /* Map .alt.got (all architectures except SPARC) */
    /* On IA32, remap GOT with a doubled size for non-present symbol resolving */
    if (FILE_IS_MIPS(file) || FILE_IS_ALPHA64(file) || FILE_IS_IA32(file))
    {
        sz = (FILE_IS_MIPS(file) ? got->shdr->sh_size     :
              FILE_IS_IA32(file) ? got->shdr->sh_size * 4 :
              plt->shdr->sh_size / elfsh_get_pltentsz(file) * sizeof(eresi_Addr));

        altgot = elfsh_create_section(ELFSH_SECTION_NAME_ALTGOT);
        hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_ALLOC | SHF_WRITE,
                                0, 0, sz, 0, 0, 0, sizeof(eresi_Addr));

        XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, sz, -1);
        memcpy(prologdata, elfsh_readmem(got), got->shdr->sh_size);

        if (elfsh_insert_mapped_section(file, altgot, hdr, prologdata,
                                        ELFSH_DATA_INJECTION, mod) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         ".alt.got insertion failed", -1);

        altgot = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_ALTGOT,
                                           NULL, NULL, NULL);
        if (altgot == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         ".alt.got insertion failed", -1);
        file->secthash[ELFSH_SECTION_ALTGOT] = altgot;
        altgot->curend = got->shdr->sh_size;
        memset(elfsh_readmem(altgot) + got->shdr->sh_size, 0x00, got->shdr->sh_size);
        altgot->shdr->sh_entsize = sizeof(eresi_Addr);
    }


    /* Insert EXTPLT in order to be able to resolve non present symbols */
    if (FILE_IS_IA32(file))
    {
        extplt_size = plt->shdr->sh_size * 2;
        extplt = elfsh_create_section(ELFSH_SECTION_NAME_EXTPLT);
        hdr = elfsh_create_shdr(0, SHT_PROGBITS, SHF_ALLOC | SHF_EXECINSTR,
                                0, 0, extplt_size, 0, 0, 0, 0);

        XALLOC(__FILE__, __FUNCTION__, __LINE__, prologdata, plt->shdr->sh_size, -1);
        memcpy(prologdata, elfsh_readmem(plt), plt->shdr->sh_size);

        if (elfsh_insert_mapped_section(file, extplt, hdr, prologdata,
                                        mode, mod) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         ".ext.plt insertion failed", -1);
        extplt = elfsh_get_section_by_name(file, ELFSH_SECTION_NAME_EXTPLT,
                                           NULL, NULL, NULL);
        if (extplt == NULL)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         ".ext.plt insertion failed", -1);
        file->secthash[ELFSH_SECTION_EXTPLT] = extplt;
        extplt->curend = elfsh_get_first_pltentsz(file);
    }



    /* Loop on .plt and inject 'old_symnam' symbols */
    for (off = 0; off < plt->shdr->sh_size; off += entsz)
    {

        /* SPARC does not have ALTGOT */
        if (FILE_IS_MIPS(file) || FILE_IS_ALPHA64(file) || FILE_IS_IA32(file))
            diff = (uint32_t) altgot->shdr->sh_addr - got->shdr->sh_addr;
        else
            diff = 0;

        /* Special case for the first plt entry */
        if (off == 0 && elfsh_altplt_firstent(enew, &off, symtab, file, extplt, plt, diff) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "ALTPLT on first entry failed", -1);
        else if (off == 0)
            continue;

        /* Get the existing symbol name for this plt entry ... */
        sym = elfsh_get_sym_by_value(elfsh_readmem(dynsym),
                                     dynsym->shdr->sh_size / sizeof(elfsh_Sym),
                                     plt->shdr->sh_addr + off,
                                     NULL, ELFSH_EXACTSYM);

        /* New versions of ld do not fill the vaddr of dynamic symbols,
        do it ourself. Do not insert old symbol in emergency cases */
        if (sym == NULL)
        {
            if ((sym = elfsh_restore_dynsym(file, plt, off, dynsym)) == NULL)
                continue;

            name = elfsh_get_dynsymbol_name(file, sym);

            /* __gmon_start__ should not be resolved
               if it was not already done by gcc */
            if (name && !strcmp(name, "__gmon_start__"))
                sym->st_value = 0x0;
        }

        /* ... and we inject the 'old' occurence symbol pointing in
        .alt.plt (.plt on MIPS) */
        if (!FILE_IS_MIPS(file))
            addr = enew->shdr->sh_addr + off;
        else
            addr = plt->shdr->sh_addr + off;

#if   __BYTE_ORDER == __BIG_ENDIAN
        if (file->hdr->e_ident[EI_DATA] == ELFDATA2LSB)
#elif __BYTE_ORDER == __LITTLE_ENDIAN
        if (file->hdr->e_ident[EI_DATA] == ELFDATA2MSB)
#else
#error Unexpected __BYTE_ORDER !
#endif
            addr = swaplong(addr);

        /* Injection */
        name = elfsh_get_dynsymbol_name(file, sym);
        newsym = elfsh_create_symbol(addr, entsz, STT_FUNC, 0, 0, 0);
        snprintf(buf, BUFSIZ, "old_%s", name);
        if (elfsh_insert_symbol(symtab, &newsym, buf) < 0)
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "old_* symbol injection failed", -1);

#if __DEBUG_COPYPLT__
        printf("[DEBUG_COPYPLT] Symbol at .plt + %u injected"
               " succesfully (%s) \n", off, buf);
#endif

        /* On ALPHA, shift the relocation offset from .got to .alt.got to avoid
        hooks removing when calling back the original function. */
        if (FILE_IS_ALPHA64(file) &&
                elfsh_shift_alpha_relocs(file, name, altgot, off) < 0)
            continue;

        /* Reencode the PLT entry to use the alternative GOT */
        /* This condition is for compatibility with other archs where EXTPLT
        is not yet supported. For those we do not enter the hook */
        if (FILE_IS_IA32(file))
        {
            diff = (eresi_Addr) altgot->shdr->sh_addr - got->shdr->sh_addr;
            elfsh_encodeplt(file, plt, diff, off);
            if (file->hdr->e_type == ET_DYN)
                elfsh_encodeplt(file, file->secthash[ELFSH_SECTION_ALTPLT],
                                diff, off);
            diff = (eresi_Addr) altgot->shdr->sh_addr - got->shdr->sh_addr +
                   got->shdr->sh_size;
            elfsh_encodeplt(file, extplt, diff, off);
        }
    }

    /* Activate ALTGOT */
    if (elfsh_redirect_pltgot(file, altgot, got, plt, enew) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "PLTGOT redirection failed", -1);

    /* Activate EXTPLT */
    if (elfsh_extplt_mirror_sections(file) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Section mirroring failed", -1);

#if	__DEBUG_COPYPLT__
    printf("[DEBUG_COPYPLT] Section Mirrored Successfully ! \n");
#endif


    /* Everything is 0k4y */
    if (elfsh_sync_sorted_symtab(symtab) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "symtab synchronisation failed", -1);
    if (elfsh_sync_sorted_symtab(dynsym) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "dynsym synchronisation failed", -1);
    elfsh_sync_sectnames(file);
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #11
0
File: map.c Project: kejiewei/eresi
/**
 * Load all the part of the binary.
 * This function should not be used by e2dbg 
 * @param file
 * @return
 */
int		        elfsh_read_obj(elfshobj_t *file)
{
  elfshsect_t		*actual;
  int			index;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  if (file->read)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
  if (file->sht == NULL && NULL == elfsh_get_sht(file, NULL))
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
                 "Unable to grab SHT", -1);
  if (NULL == elfsh_get_pht(file, NULL) && file->hdr->e_type != ET_REL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
                 "Unable to grab PHT", -1);

#if __DEBUG_MAP__
  puts("[DEBUG:read_obj] Loading all known typed sections\n");
#endif

  /* Fill multiple relocation sections */
  for (index = 0; NULL != 
       (actual = elfsh_get_reloc(file, index, NULL)); 
       index++);

  /*
  ** Load sections placed after symtab
  ** Added for Solaris
  */
  elfsh_get_comments(file);
  elfsh_get_dwarf(file);
  elfsh_get_stab(file, NULL);
  
  if (file->hdr->e_type == ET_CORE) 
    {
      elfsh_get_core_notes(file);
      goto out;
    }


  /*
   ** We cannot use simply elfsh_get_anonymous_section() here
   ** because the object's section hash ptrs would not be filled.
   */
  elfsh_get_symtab(file, NULL);

  /* Fixup stuffs in the SHT */
  elfsh_fixup(file);

  elfsh_get_dynsymtab(file, NULL);
  elfsh_get_stab(file, NULL);
  elfsh_get_dynamic(file, NULL);
  elfsh_get_ctors(file, NULL);
  elfsh_get_dtors(file, NULL);
  elfsh_get_got(file, NULL);
  elfsh_get_interp(file);

  elfsh_get_versymtab(file, NULL);
  elfsh_get_verneedtab(file, NULL);
  elfsh_get_verdeftab(file, NULL);
  elfsh_get_hashtable(file, NULL);

  //elfsh_get_comments(file);
  elfsh_get_plt(file, NULL);

  /* Fill the multiple notes sections */
  for (index = 0; NULL != elfsh_get_notes(file, index); index++);

  /* Loop on the section header table and load all unknown-typed sections */
  for (actual = file->sectlist; actual; actual = actual->next)
  {
    /* Fix first section size */
    if (actual->shdr->sh_size == 0 && actual->next &&
        actual->next->shdr->sh_offset != actual->shdr->sh_offset &&
	actual->next->shdr->sh_addr   != actual->shdr->sh_addr)
      actual->shdr->sh_size =
        actual->next->shdr->sh_offset - actual->shdr->sh_offset;

    /* If the section data has to be loaded, load it */
    /* In case of bss, only load if BSS data is inserted in the file */
    if (actual->data == NULL && actual->shdr->sh_size)
    {
      if ((actual->shdr->sh_type == SHT_NOBITS && 
           actual->shdr->sh_offset == actual->next->shdr->sh_offset) ||
          (actual->next != NULL && actual->next->shdr->sh_offset == actual->shdr->sh_offset))
        continue;

#if __DEBUG_MAP__
      printf("[LIBELFSH] Loading anonymous  section %15s \n",
             elfsh_get_section_name(file, actual));
#endif
      elfsh_get_anonymous_section(file, actual);
    }
  }

  /* Fixup various symbols like dynamic ones that are NULL */
  /* Non fatal error */
  if (file->secthash[ELFSH_SECTION_DYNSYM])
    elfsh_fixup_dynsymtab(file->secthash[ELFSH_SECTION_DYNSYM]);

out:
  /* We close the file descriptor after file mapping so we can open more files */
  if (file->fd >= 0) {
#if __DEBUG_MAP__
    printf("[LIBELFSH] Closing descriptor %d \n",
           file->fd);
#endif

    XCLOSE(file->fd, -1);
    /* neutralize file descriptor */
    file->fd = -1;
  }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #12
0
/**
 * Return the symbol entry giving its name 
 * @param file target file
 * @param name symbol name
 * @return symbol pointer or NULL
 */
elfsh_Sym	*elfsh_get_symbol_by_name(elfshobj_t *file, char *name)
{
  elfsh_Sym	*sym;
  int		idx;
  int		size;
  char		*actual;
  elfshsect_t	*sect;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Check arguments */
  if (file == NULL || name == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", NULL);

  /* Setup symtab pointers */
  if (elfsh_get_symtab(file, &size) == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Unable to get SYMTAB", NULL);

  sect = file->secthash[ELFSH_SECTION_SYMTAB];

  /* Invalid section pointer */
  if (sect == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Unable to get SYMTAB (invalid section pointer)", NULL);

  sym = (elfsh_Sym *) sect->data;

  /* Invalid section data */
  if (sym == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Unable to get SYMTAB data", NULL);

  /*
  if (file->symhash.ent)
    {
    //idx is the symbol number in the section
      idx = (int) hash_get(&file->symhash, name);

#if __DEBUG_HASH_BY_NAME__
      printf("[DEBUG_HASH_BY_NAME] SYM HASH Search by name for %s => %d\n",
	     name, idx);
#else
//Check if idx is in the section
      if (idx <= 0 || idx >= sect->shdr->sh_size)
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		     "Symbol not found", NULL);

      PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (sym + idx));
#endif
    }
*/
 

  for (idx = 0; idx < size; idx++)
    {
      actual = elfsh_get_symbol_name(file, sym + idx);
      if (actual && !strcmp(actual, name))
	{
#if __DEBUG_HASH_BY_NAME__
	  printf("[DEBUG_HASH_BY_NAME] SYM ITERATE Search by name for %s => %d\n", 
		 name, idx);
#endif
	  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (sym + idx));
	}
    }

#if __DEBUG_HASH_BY_NAME__
  printf("[DEBUG_HASH_BY_NAME] SYM ITERATE Search by name for %s => NOT FOUND\n", name);
#endif

  PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
	       "Symbol not found", NULL);
}
Example #13
0
/**
 * Return the dynamic symbol name giving its value,
 * Fill 'offset' with the difference between sym->st_value and 'value'
 * @param file
 * @param value
 * @param offset
 * @return
 */
char		*elfsh_reverse_symbol(elfshobj_t	*file,
				      eresi_Addr       	value,
				      elfsh_SAddr      	*offset)
{
  elfshsect_t	*sect;
  elfsh_Sym	*sorted;
  int		num;
  int		index;
  char		*str;
  int		best;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sanity checks */
  if (!value || value == 0xFFFFFFFF)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid parameter", NULL);
  if (file == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", NULL);

  /* handle dynamic case */
  if (elfsh_is_runtime_mode())
    value -= file->rhdr.base;

  /* If there is no symtab, resolve using SHT */
  if (elfsh_get_symtab(file, &num) == NULL)
    {
      sect = elfsh_get_parent_section(file, value, offset);
      if (sect == NULL)
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			  "No parent section", NULL);

      *offset = (elfsh_SAddr) (sect->shdr->sh_addr - value);
      PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (elfsh_get_section_name(file, sect)));
    }

  /* Else use the sorted-by-address symbol table to match what we want */
  if (file->secthash[ELFSH_SECTION_SYMTAB]->altdata == NULL)
    elfsh_sync_sorted_symtab(file->secthash[ELFSH_SECTION_SYMTAB]);
  sorted = file->secthash[ELFSH_SECTION_SYMTAB]->altdata;

  /* Now find the best symbol -- type is more important than offset */
  for (str = NULL, best = index = 0; index < num; index++)
    if (sorted[index].st_value <= value && DUMPABLE(sorted + index))
      {
	if (best && !BESTYPE(sorted + index, sorted + best))
	  continue;

	*offset = (elfsh_SAddr) (value - sorted[index].st_value);
	best = index;
	str = elfsh_get_symbol_name(file, sorted + index);
	if (!*str)
	  str = NULL;
      }

  if (str)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, str);
  PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		    "No valid symbol interval", NULL);
}