Esempio n. 1
0
File: map.c Progetto: kejiewei/eresi
/**
 * Called from elfsh_fixup_symtab
 * When trying to inject part of the libc, some bss symbols have a wrong sctndx 
 * @param symtab
 * @return
 */
elfshsect_t   *elfsh_fixup_sctndx(elfshsect_t *symtab)
{
  int	        index;
  elfsh_Sym     *sym;
  elfsh_SAddr	offset;
  elfsh_Shdr	*shdr;
  elfshsect_t	*sct;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  //return (symtab); // XXX

  sym = symtab->data;
  shdr = symtab->parent->sht + symtab->index;

  for (index = 0; index < shdr->sh_size / sizeof(elfsh_Sym); index++)
  {
    if (elfsh_get_symbol_link(sym + index) != SHN_COMMON)
    {
      if (elfsh_get_symbol_type(sym + index) == STT_SECTION)
        continue;

      sct = elfsh_get_parent_section(symtab->parent, 
                                     elfsh_get_symbol_value(sym + index), 
                                     &offset);

      if (sct == NULL)
      {
        sct = elfsh_get_section_by_index(symtab->parent, 
                                         elfsh_get_symbol_link(sym + index), 
                                         NULL, 
                                         NULL);
        if (sct && elfsh_get_section_type(sct->shdr) == SHT_NOBITS)
        {

#if	__DEBUG_MAP__
          printf(" [*] Symbol [%s] sctndx changed from %u to SHN_COMMON\n", 
                 elfsh_get_symbol_name(symtab->parent, sym + index), 
                 elfsh_get_symbol_link(sym + index));
#endif

          elfsh_set_symbol_link(sym + index, SHN_COMMON);
          continue;
        }

      }

      if (sct && elfsh_get_section_type(sct->shdr) == SHT_NOBITS)
      {
        elfsh_set_symbol_link(sym + index, SHN_COMMON);
#if	__DEBUG_MAP__		  
        printf(" [*] Symbol [%s] sctndx changed to SHN_COMMON\n", 
               elfsh_get_symbol_name(symtab->parent, sym + index));
#endif
      }
    }
  }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, symtab);
}
Esempio n. 2
0
/**
 * Retreive the file offset giving the virtual address
 * @param file
 * @param sym
 * @return
 */
int		elfsh_get_symbol_foffset(elfshobj_t *file, elfsh_Sym *sym)
{
  elfshsect_t	*sect;
  char		*name;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* If the symbol is a section, then look at the sht instead */
  if (elfsh_get_symbol_type(sym) == STT_SECTION)
    {
      name = elfsh_get_symbol_name(file, sym);
      sect = elfsh_get_section_by_name(file, name, NULL, NULL, NULL);
      PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 
			 (sect ? elfsh_get_section_foffset(sect->shdr) : 0));
    }

  /* get our parent section and compute the file offset */
  if (sym == NULL || file == NULL || NULL == sym->st_value)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
  sect = elfsh_get_parent_section(file, sym->st_value, NULL);
  if (sect == NULL)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 
		     (sect->shdr->sh_offset + 
		      (sym->st_value - sect->shdr->sh_addr)));
}
Esempio n. 3
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);
}
Esempio n. 4
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);
}
Esempio n. 5
0
/**
 * Match functions from an addrtable
 * @param func_list function list pointer
 * @param count position on the list
 */
int			trace_match_addrtable(elfshobj_t *curfile, char ***func_list, u_int *count)
{
  eresi_Addr		*alist = NULL;
  u_int			index;
  char			**f_list;
  u_int			cnum;
  char			tmpstr[256];
  elfsh_Sym		*sym;
  char			*toadd;
  
  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

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

  f_list = *func_list;
  cnum = *count;
  
  /* Retrieve all called address in this binary */
  if (elfsh_addr_get_func_list(curfile, &alist) < 0)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Can't get call function list", -1);

  for (index = 0; alist[index]; index++)
    {
      sym = elfsh_get_symbol_by_value(curfile, alist[index], 
				      0, ELFSH_EXACTSYM);
      
      /* Find a symbol for this address */
      if (sym)
	{
	  toadd = elfsh_get_symbol_name(curfile, sym);
	}
      else
	{
	  snprintf(tmpstr, 255, TRACE_PRE_FUNC "" AFMT, 
		   alist[index]);
	  toadd = tmpstr;
	}

      /* Do we need to realloc ? */
      if (((cnum+1) % TRACE_MATCH_ALLOCSTEP) == 0)
	{
	  XREALLOC(__FILE__, __FUNCTION__, __LINE__, f_list, f_list, 
		   sizeof(char*) * (cnum + 1 + TRACE_MATCH_ALLOCSTEP), -1);

	  /* Blank new elements */
	  memset(&f_list[cnum], 0x00, TRACE_MATCH_ALLOCSTEP*sizeof(char*));
	  
	  /* Update the pointer, data can move during a reallocation */
	  *func_list = f_list;
	}

      /* If its temp string, strdup it */
      if (toadd == tmpstr)
	toadd = strdup(tmpstr);

      f_list[cnum] = toadd;

      *count = ++cnum;
    }

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); 
}
Esempio n. 6
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);
}
Esempio n. 7
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);
}
Esempio n. 8
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);
}