Example #1
0
/**
 * @brief Shift relocation tables at some point for allowing non-present symbol resolving 
 * mostly applied on section injection for ET_DYN objects.
 * @param file The host file where shift must happens.
 * @param diff Absolute difference to shift to.
 * @param relplt Section descriptor for the .relplt section.
 * @param limit Upper limit address beyond which shifting must not be performed (or ELFSH_NOLIMIT)
 * @return Always 0.
 */
int			elfsh_shift_ia32_relocs(elfshobj_t *file, 
						eresi_Addr  diff,
						elfshsect_t *relplt,
						eresi_Addr  limit)
{
  elfsh_Rel		*l;
  int			index;
  eresi_Addr		reloff;
  elfshsect_t		*parent;
  elfsh_SAddr		off;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);
  for (index = 0; index < relplt->shdr->sh_size / sizeof(elfsh_Rel); index++)
    {
      l = (elfsh_Rel *) relplt->data + index;
      if (ELFSH_NOLIMIT == limit || elfsh_get_reloffset((elfsh_Rel *) l) >= limit)
	{
	  reloff = elfsh_get_reloffset((elfsh_Rel *) l);
	  reloff += diff;
	  elfsh_set_reloffset((elfsh_Rel *) l, reloff);

	  /* Shifting memory -pointed- by the relative relocation */
	  if (elfsh_get_reltype(l) != R_386_RELATIVE)
	    continue;
	  parent = elfsh_get_parent_section(file, reloff, &off);
	  if (strstr(parent->name, "got") || strstr(parent->name, "bss") ||
	      strstr(parent->name, "elfsh"))
	    continue;
	  *(eresi_Addr *) ((char *) parent->data + off) += diff;
	}
    }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #2
0
/**
 * Remap section's whoose type is a data array (GOT, CTORS, DTORS ..) 
 * @param file
 * @param array
 * @param size
 * @param diff
 * @return
 */
int		elfsh_reloc_array(elfshobj_t *file, 
				  eresi_Addr *array, 
				  u_int      size, 
				  eresi_Addr diff)
{
  elfshsect_t	*parent;
  u_int		index;
  u_int		count;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

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

  for (count = index = 0; index < size; index++)
    {
      parent = elfsh_get_parent_section(file, array[index], NULL);
      if (parent != NULL && parent->shdr->sh_addr != NULL && array[index] != NULL)
	{  
	  array[index] += diff;
	  count++;
	}
    }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (count));
}
Example #3
0
/** 
 * Get the parent object of a breakpoint.
 * Thats needed for the mprotect stuff inside the breakpoint handler 
 * @param addr
 * @return
 */
elfshobj_t      *e2dbg_get_parent_object(eresi_Addr addr)
{
  elfsh_Phdr    *cur;
  elfshobj_t    *curfile;
  elfshsect_t   *cursect;
  char          **keys;
  int           index;
  int           keynbr;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  keys = hash_get_keys(&world.curjob->loaded, &keynbr);
  for (index = 0; index < keynbr; index++)
    {
      curfile = hash_get(&world.curjob->loaded, keys[index]);
      cursect = elfsh_get_parent_section(curfile, addr, NULL);
      if (cursect)
        {
          cur = elfsh_get_parent_segment(curfile, cursect);
          if (cur)
            PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, curfile);
        }
    }
  
  /* Parent object not found */
  PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
	       "Unable to get parent object addr", (NULL));
}
Example #4
0
/**
 * Remap the .dynamic section 
 * @param sect
 * @param diff
 * @return
 */
int		elfsh_reloc_dynamic(elfshsect_t *sect, eresi_Addr diff)
{
  elfshsect_t	*parent;
  elfsh_Dyn	*dyn;
  u_int		index;
  u_int		count;
  eresi_Addr	val;
  u_int		nbr;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  if (sect == NULL || sect->shdr == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", -1);

  else if (sect->shdr->sh_type != SHT_DYNAMIC)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Unexpected section type", -1);

  nbr = sect->shdr->sh_size / sizeof(elfsh_Dyn);
  for (dyn = elfsh_readmem(sect), count = index = 0; index < nbr; index++)
    {
      val = elfsh_get_dynentry_val(dyn + index);
      parent = elfsh_get_parent_section(sect->parent, val, NULL);
      if (val && parent != NULL && parent->shdr->sh_addr != NULL)
	{
	  elfsh_set_dynentry_val(dyn + index, val + diff);
	  count++;
	}
    }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (count));
}
Example #5
0
/**
 * Remap sections of type SHT_REL and SHT_RELA 
 * @param sect
 * @param diff
 * @return
 */
int		elfsh_reloc_rel(elfshsect_t *sect, eresi_Addr diff)
{
  elfshsect_t	*parent;
  elfsh_Rel	*rel;
  u_int		index;
  u_int		count;
  u_int		nbr;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  if (sect == NULL || sect->shdr == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid NULL parameter", -1);

  else if (sect->shdr->sh_type != SHT_REL && sect->shdr->sh_type != SHT_RELA)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Unexpected section type", -1);

  nbr = sect->shdr->sh_size / sizeof(elfsh_Rel);
  for (rel = elfsh_readmem(sect), count = index = 0; index < nbr; index++)
    {
      parent = elfsh_get_parent_section(sect->parent, 
					rel[index].r_offset, 
					NULL);
      if (rel[index].r_offset && parent != NULL && parent->shdr->sh_addr != NULL)
	{
	  rel[index].r_offset += diff;
	  count++;
	}
    }
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (count));
}
Example #6
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)));
}
Example #7
0
File: raw.c Project: kejiewei/eresi
/**
 * @brief Get the buffered address from the real virtual address 
 */
void		*elfsh_get_raw_by_addr(elfshobj_t *current, eresi_Addr addr, void *buf, u_int size)
{
  elfshsect_t	*sect;
  elfsh_SAddr	offset;

  /* This happens when the object is a ERESI variable or when we request
   an address in runtime that is not part of any section */
  sect = elfsh_get_parent_section(current, (eresi_Addr) addr, &offset);
  if (!sect)
    return ((void *) addr);

  /* In debug mode, we return a pointer on the runtime data */
  if (elfsh_is_runtime_mode())
    {
      if (!elfsh_section_is_runtime(sect))
	return ((void *) sect->parent->rhdr.base + sect->shdr->sh_addr + offset);
      else if (!sect->shdr->sh_addr)
	return ((void *) sect->data + offset);
      else
	return ((void *) sect->shdr->sh_addr + offset);
    }

  /* Else we return a pointer on the cache data, doing a copy if requested */
  else
    {
      if (buf && size)
	memcpy(buf, (char *) sect->data + offset, size);
      return ((void *) sect->data + offset);
    }
  
}
Example #8
0
File: map.c Project: 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);
}
Example #9
0
/**
 *  Symbol resolving handler for libasm.
 * Runtime compatible
 * @param data
 * @param vaddr
 * @param buf
 * @param maxlen
 */
void		asm_do_resolve(void *data, eresi_Addr vaddr,
                           char *buf, u_int maxlen)
{
    elfshobj_t	*file;
    elfshsect_t	*parent;
    char		*name;
    elfsh_SAddr	off;
    int		len;
    char		*sep;
    uint32_t	addr;

    /* Retreive the nearest symbol */
    file = data;
    parent = elfsh_get_parent_section(file, vaddr, 0);
    if (NULL != parent && parent->shdr->sh_addr)
        name = revm_resolve(file, vaddr, &off);
    else
        name = NULL;

    /* Print the symbol name in 'buf' so that libasm can print it */
    len = (NULL == name ? 10 : strlen(name) + 25);
    if (name != NULL && *name != 0x00)
    {
        sep = (off > 0 ? " + " : off < 0 ? " - " : "");
        len = snprintf(buf, maxlen - 1, "%s%s%s%s",
                       revm_colorfieldstr("<"),
                       revm_colortypestr(name),
                       (off ? revm_colorfieldstr(sep) : ""),
                       (off ? "" : revm_colorfieldstr(">")));

        if (off)
            snprintf(buf + len, maxlen - len -  1, "%s%s",
                     revm_colornumber("%u", (u_int) off),
                     revm_colorfieldstr(">"));
    }

    /* We currently only disassemble architecture with 32bits address space, even when 64b proc */
    else
    {
        addr = (uint32_t) vaddr;
        snprintf(buf, maxlen, "0x%X", addr);
    }
}
Example #10
0
/**
 * @param str
 * @param bp
 * @param pc
 * @param parent
 * @return
 */
void		bpdebug(char *str, elfshbp_t *bp, eresi_Addr pc, elfshobj_t *parent)
{
  eresi_Addr	addr;
  int		off;
  char		*name;
  elfshsect_t	*sect;
  elfsh_Sym	 *sym;

  off  = (bp ? 0 : e2dbgworld.stoppedthread->count == E2DBG_BREAK_HIT ? 3 : 6);
  addr = (bp ? bp->addr : pc - off);
  
  fprintf(stderr, "%s (PC = %08X) ::: parent = %s (BP DESCRIPTOR = %08X) \n",
	  str, pc, (parent ? parent->name : "NO PARENT NAME"), (eresi_Addr) bp);
  if (!bp)
    return;
  
  sect   = elfsh_get_parent_section(parent, addr, NULL);
  name   = revm_resolve(parent, addr, &off);
  sym    = elfsh_get_metasym_by_value(parent, addr, &off, ELFSH_LOWSYM);
  revm_object_display(sect, sym, 16, off, 0, addr, name, REVM_VIEW_DISASM, 0, 0);
}
Example #11
0
/**
 * @brief Put write capability on the zone 
 * @param file 
 * @param addr
 * @param sz
 * @return
 */
int		elfsh_munprotect_userland(elfshobj_t *file, eresi_Addr addr, uint32_t sz)
{
  elfshsect_t	*sect;
  elfsh_Phdr	*phdr;
  int		retval;
  int		prot;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);
  if (!elfsh_is_runtime_mode())
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);

  sect = elfsh_get_parent_section(file, addr, NULL);
  if (!sect)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			"Cannot find parent section", -1);

  phdr = elfsh_get_parent_segment(file, sect);
  prot = 0;

  if (elfsh_segment_is_readable(phdr))
    prot |= PROT_READ;
  if (elfsh_segment_is_writable(phdr))
    prot |= PROT_WRITE;
  if (elfsh_segment_is_executable(phdr))
    prot |= PROT_EXEC;

  retval = mprotect((void *) (addr - addr % getpagesize()), 
		    getpagesize(), PROT_READ | PROT_WRITE | PROT_EXEC);

  if (retval != 0)
    {
      perror("munprotect");
      PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			"Failed mprotect", -1);
    }

  /* Return the original rights */
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 
		     prot);
}
Example #12
0
/**
 * @brief On MIPS there is no .plt section : call to libraries are done
 * using an indirect jump on .got value directly from .text. If
 * we want to be able to call the original function from the hook
 * function, we need to create a plt-like section and mirror the
 * Global Offset Table (.got).
 *
 * By default, .got points in some code stub standing in .text. This
 * code stubs looks much like a PLT. Indeed, there is a kind of PLT
 * on MIPS but it is embedded in the .text section. What we do in this
 * function is to disambiguize .plt and .text, so that we can apply
 * ALTPLT technique as well on MIPS.
 *
 * Unlike on ALPHA, we cannot move relocations from .got to .alt.got
 * since MIPS binaries have no relocation tables in ET_EXEC objects.
 * What we do instead is changing the processor specific DT_PLTGOT
 * entry in the .dynamic section and continue to rely on the ALTPLT
 * technique (call's the original functions using the injected 'old_'
 * symbol) just like ALTPLT redirection on other architectures. -mm
 *
 * @param file Host file.
 * @return Success (0) or Error (-1).
 */
int		elfsh_build_plt(elfshobj_t *file)
{
    elfshsect_t	*text;
    elfsh_SAddr	off;
    char		buff[16] = {0x00};
    eresi_Addr	pltaddr = 0;
    eresi_Addr	pltend  = 0;
    elfsh_Shdr	start;
    elfsh_Shdr	plt;
    elfshsect_t	*enew;
    eresi_Addr	lsize;
    unsigned int	size;
    char		*data;
    char		*tdata;
    unsigned int	idx;

    PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

    /* First checks */
    text = elfsh_get_parent_section(file, elfsh_get_entrypoint(file->hdr), &off);
    if (!text)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Cannot find parent section from entry point", -1);
    if (!elfsh_get_anonymous_section(file, text))
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Unable to get an anonymous section", -1);


    /*
    ** Find the embedded plt by searching the nop;nop;nop;nop; signature
    ** that delimit the beginning and the end of plt. This is MIPS specific
    ** since only MIPS needs this.
    */
    tdata = elfsh_readmem(text);
    for (off = 0; off < text->shdr->sh_size; off += 4)
        if (!memcmp(tdata + off, buff, sizeof(buff)))
        {
            pltaddr = text->shdr->sh_addr + off + 16;
            for (off += 16; off < text->shdr->sh_size; off += 4)
                if (!memcmp(tdata + off, buff, 16))
                {
                    pltend = text->shdr->sh_addr + off + 16;
                    goto found;
                }
            PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                         "Cannot find PLT end", -1);
        }

found:
    idx = text->index;
    if (!pltaddr)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
                     "Cannot find PLT start", -1);

    /*
    ** Now create additional section header table entries so that we reduce the
    ** MIPS model to our standard ALTPLT/ALTGOT model.
    **
    ** Do not use the elfsh_insert_*_section() since we want no address space
    ** shifting.
    */

    /* .start */
    lsize = pltaddr - text->shdr->sh_addr;
    size  = (unsigned int) lsize;
    start = elfsh_create_shdr(0, SHT_PROGBITS, SHF_EXECINSTR | SHF_ALLOC,
                              text->shdr->sh_addr, text->shdr->sh_offset,
                              size, 0, 0, 0, 0);
    enew = elfsh_create_section(ELFSH_SECTION_NAME_START);
    XALLOC(__FILE__, __FUNCTION__, __LINE__,data, size, -1);
    memcpy(data, tdata, size);
    elfsh_insert_shdr(file, start, idx, enew->name, 0);
    elfsh_add_section(file, enew, idx, data, ELFSH_SHIFTING_MIPSPLT);
    file->secthash[ELFSH_SECTION_MIPSTART] = enew;

    /* .plt */
    lsize = pltend - pltaddr;
    size  = (unsigned int) lsize;
    plt   = elfsh_create_shdr(0, SHT_PROGBITS, SHF_EXECINSTR | SHF_ALLOC,
                              start.sh_addr + start.sh_size,
                              start.sh_offset + start.sh_size,
                              size, 0, 0, 0, 0);
    enew = elfsh_create_section(ELFSH_SECTION_NAME_PLT);
    XALLOC(__FILE__, __FUNCTION__, __LINE__,data, size, -1);
    memcpy(data, tdata + start.sh_size, size);
    elfsh_insert_shdr(file, plt, idx + 1, enew->name, 0);
    elfsh_add_section(file, enew, idx + 1, data, ELFSH_SHIFTING_MIPSPLT);

    /* Shift .text data, sh_offset, sh_addr, and sh_size correctly */
    text->shdr->sh_offset += (start.sh_size + plt.sh_size);
    text->shdr->sh_addr   += (start.sh_size + plt.sh_size);
    memmove(tdata,
            tdata + start.sh_size + plt.sh_size,
            text->shdr->sh_size - (start.sh_size + plt.sh_size));
    text->shdr->sh_size   -= (start.sh_size + plt.sh_size);

    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
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);
}
Example #14
0
/**
 * Search a call for a given address
 * @param file target file
 * @param addr supose to be a function
 */
int			elfsh_addr_is_called(elfshobj_t *file, eresi_Addr addr)
{
  int 			ret;
  int			index;
  asm_instr		instr;
  elfsh_SAddr		foffset;
  elfsh_Word		len;
  char			*base;
  asm_processor		proc;
  eresi_Addr		base_vaddr;
  u_char		found = 0;
  elfshsect_t		*text;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

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

  /* Search entrypoint section, our address must be in this section */
  text = elfsh_get_parent_section(file, elfsh_get_entrypoint(file->hdr), &foffset);

  if (!text)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Cannot find parent section from entry point", -1);
  
  if (!elfsh_get_anonymous_section(file, text))
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		 "Unable to get an anonymous section", -1);
  
  base = elfsh_readmem(text);
  len = text->shdr->sh_size;

  /* Get the virtual address */
  base_vaddr = (elfsh_is_runtime_mode() && !elfsh_section_is_runtime(text) ?
		file->rhdr.base + elfsh_get_section_addr(text->shdr) :
		elfsh_get_section_addr(text->shdr));

  /* Our address is valid ? */
  if (!INTERVAL(base_vaddr, addr, (base_vaddr + len)))
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		 "Not in entrypoint section", -4);

  /* Setup asm_processor structure */
  if (etrace_setup_proc(file, &proc) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		 "Failed during proc structure setup", -1);
  
  /* Despite the fact that we choose the right architecture to init asm,
     Our approach is totally architecture independant as we search using
     global type ASM_TYPE_CALLPROC and we know that op[0].imm will contain a
     relative value. */
  for (index = 0; index < len; index += ret)
    {
      /* Read an instruction */
      if ((ret = asm_read_instr(&instr, (u_char *) (base + index), len -  index, &proc)))
	{
	  /* Global assembler filter */
	  if ((instr.type & ASM_TYPE_CALLPROC)
	      && instr.op[0].imm != 0)
	    {
	      /* Found the correct call */
	      if (base_vaddr + index + instr.op[0].imm + instr.len == addr)
		{
		  found = 1;
		  break;
		}
	    }
	}

      if (ret <= 0)
	ret = 1;
    }

  if (!found)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "No call found", -3);

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #15
0
/** 
 * Print the chosen symbol table 
 * @param file
 * @param sect
 * @param tab
 * @param num
 * @param regx
 * @param get_symname
 * @return
 */
int		ds(elfshobj_t	*file,
		   elfshsect_t	*sect,
		   u_int        num,
		   regex_t	*regx,
		   char		*(*get_symname)(elfshobj_t *f, elfsh_Sym *s))
{
  elfsh_Sym	*table;
  char		*name;
  char		*type;
  char		*bind;
  u_int		typenum;
  u_int		bindnum;
  u_int		foff;
  u_int		index;
  char		*sect_name;
  char		buff[512];
  char		off[50];
  char		type_unk[ERESI_MEANING + 1];
  char		bind_unk[ERESI_MEANING + 1];

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  /* Sort the table if necessary */
  if (world.state.sort != NULL)
    switch (*world.state.sort)
      {
      case ELFSH_SORT_BY_ADDR:
	table = sect->altdata;
	break;
      case ELFSH_SORT_BY_SIZE:
	table = sect->terdata;
	break;
      default:
	PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
			  "Unknown sort mode", -1);
      }

  /* Avoid reading inexistant memory in the process for .symtab */
  else
    table = (elfsh_Sym *) (sect->shdr->sh_addr ? elfsh_readmem(sect) : sect->data);

  /* Browse symtab */
  for (index = 0; index < num; index++)
    {

      /* Retreive names */
      typenum = elfsh_get_symbol_type(table + index);
      bindnum = elfsh_get_symbol_bind(table + index);
      type = (char *) (typenum > ELFSH_SYMTYPE_MAX ? 
		       revm_build_unknown(type_unk, "type", typenum) : 
		       elfsh_sym_type[typenum].desc);
      bind = (char *) (bindnum >= ELFSH_SYMBIND_MAX ?
		       revm_build_unknown(bind_unk, "type", bindnum) : 
		       elfsh_sym_bind[bindnum].desc);
      name = get_symname(world.curjob->curfile, table + index);
      sect_name = NULL;
      sect = elfsh_get_parent_section(world.curjob->curfile, 
				      table[index].st_value, 
				      NULL);
      if (sect == NULL && table[index].st_shndx)
	sect = elfsh_get_section_by_index(world.curjob->curfile, 
					  table[index].st_shndx,
					  NULL, NULL);
      if (sect != NULL)
	sect_name = elfsh_get_section_name(world.curjob->curfile, sect);

      /* Fixup names */
      if (name == NULL || *name == 0)
	name = ELFSH_NULL_STRING;
      if (type == NULL || *type == 0)
	type = ELFSH_NULL_STRING;
      if (bind == NULL || *bind == 0)
	bind = ELFSH_NULL_STRING;
      if (sect_name == NULL)
	sect_name = ELFSH_NULL_STRING;
      foff = (!table[index].st_value ? 0 : 
	      elfsh_get_foffset_from_vaddr(world.curjob->curfile, 
					   table[index].st_value));
					
      if (sect && sect->shdr->sh_addr != table[index].st_value)
	snprintf(off, sizeof(off), " + %s", 
		 revm_colornumber("%u", (u_int) (table[index].st_value - sect->shdr->sh_addr)));
      else
	*off = '\0';



      /* Different output depending on the quiet flag */
      if (!world.state.revm_quiet)
	{
	  snprintf(buff, sizeof(buff), 
		   " %s %s %s %s %s%s "
		   "%s%s %s%s %s%s => %s%s\n",
		   revm_colornumber("[%03u]", index), 
		   revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base), 
		   revm_colortypestr_fmt("%-8s", type), 
		   revm_colorstr_fmt("%-40s", name),
		   revm_colorfieldstr("size:"),
		   revm_colornumber("%010u", elfsh_get_symbol_size(table + index)), 				  
		   revm_colorfieldstr("foffset:"),
		   revm_colornumber("%06u", foff),
		   revm_colorfieldstr("scope:"),
		   revm_colortypestr_fmt("%-6s", bind), 
		   revm_colorfieldstr("sctndx:"),
		   revm_colornumber("%02u", elfsh_get_symbol_link(table + index)),
		   revm_colorstr(sect_name), off);
	}

      else
	{
	  snprintf(buff, sizeof(buff), 
		   " %s %s %s %s %s%s %s%s %s%-6s\n",
		   revm_colornumber("[%03u]", index), 
		   revm_coloraddress(XFMT, (eresi_Addr) elfsh_get_symbol_value(table + index) + file->rhdr.base),
		   revm_colortypestr_fmt("%-8s", type), revm_colorstr_fmt("%-15s", name), 
		   revm_colorfieldstr("sz:"),
		   revm_colornumber("%06u", elfsh_get_symbol_size(table + index)),
		   revm_colorfieldstr("foff:"),
		   revm_colornumber("%06u", foff),
		   revm_colorfieldstr("scop:"),
		   revm_colortypestr_fmt("%-6s", bind));
	}
      
      if (regx == NULL || 
	  (regx != NULL && regexec(regx, buff, 0, 0, 0) == 0))
	{
	  /* If the user ask quit, we just break */
	  if (revm_output(buff) == -1)
	    break;
	}

      revm_endline();
    }

  revm_endline();
  revm_output("\n");
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #16
0
/**
 * @brief Link function layer
 * @param ctxt mjollnir context structure
 * @param str source address
 * @param dst destination address
 * @param ret return address
 */
int                     mjr_link_func_call(mjrcontext_t *ctxt,
                                           eresi_Addr src,
                                           eresi_Addr dst,
                                           eresi_Addr ret)
{
  container_t           *fun;
  char                  *tmpstr;
  eresi_Addr            tmpaddr;
  elfshsect_t           *dstsect;
  u_char                scope;
  u_char		isnew;

#if __DEBUG_FLOW__
  mjrfunc_t             *tmpfunc;
  mjrfunc_t             *tmpfunc2;
  //char                  *md5;
#endif

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

#if __DEBUG_LINKS__
  fprintf(D_DESC, "[D] %s: src:"XFMT" dst:"XFMT" ret:"XFMT"\n",
          __FUNCTION__, src, dst, ret);
#endif

  /* Check if we are not pointing into BSS */
  dstsect = elfsh_get_parent_section(ctxt->obj, dst, NULL);
  if (!dstsect || !dstsect->data)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
  scope = (!dstsect || !strcmp(dstsect->name, ELFSH_SECTION_NAME_PLT) ?
           MJR_LINK_SCOPE_GLOBAL : MJR_LINK_SCOPE_LOCAL);

  /* Link/Prepare function layer. We use an intermediate variable, else
     the compiler optimize too hard and that make segfault (bug in gcc ?) */
  tmpaddr = dst;
  fun = mjr_function_get_by_vaddr(ctxt, tmpaddr);
  if (!fun)
    {
      tmpstr = _vaddr2str(tmpaddr);
      fun = mjr_create_function_container(ctxt, tmpaddr, 0,
                                          tmpstr, NULL, NULL);
      mjr_function_register(ctxt, tmpaddr, fun);
      mjr_function_symbol(ctxt, fun);
      isnew = 1;
    }
  else
    isnew = 0;

  /* Add links between functions */
  if (ctxt->curfunc)
    {
#if __DEBUG_FLOW__
      tmpfunc = (mjrfunc_t *) ctxt->curfunc->data;
      tmpfunc2 = (mjrfunc_t *) fun->data;
      fprintf(stderr, " [*] Linking function " XFMT " to func " XFMT "\n",
              tmpfunc->vaddr, tmpfunc2->vaddr);
#endif
      mjr_container_add_link(ctxt, fun, ctxt->curfunc->id,
                             MJR_LINK_FUNC_RET, scope, CONTAINER_LINK_IN);
      mjr_container_add_link(ctxt, ctxt->curfunc, fun->id,
                             MJR_LINK_FUNC_CALL, scope, CONTAINER_LINK_OUT);
    }

  /* Fingerprint function */
  /*
  ** XXX: this segfaults on 64bits architecture - MAX_FUNC_LEN should
  ** not be used. Instead, we should fingerprint all functions with
  ** their infered size at the moment of saving debug sections.
  **
  md5 = mjr_fingerprint_function(ctxt, tmpaddr, MJR_FPRINT_TYPE_MD5);
  tmpfunc = (mjrfunc_t *) fun->data;
  if (md5)
    memcpy(tmpfunc->md5, md5, sizeof(tmpfunc->md5));
  */

#if __DEBUG_FLOW__
  tmpfunc = fun->data;
#endif

  if (scope == MJR_LINK_SCOPE_LOCAL && isnew)
    {
      elist_push(ctxt->func_stack, fun);
      ctxt->curfunc = fun;
#if __DEBUG_FLOW__
      fprintf(stderr, " [*] New CURFUNC @ %s \n", tmpfunc->name);
    }
  else if (!isnew)
    fprintf(stderr, " ******** ALREADY SEEN FUNCTION : NOT CHANGING CURFUNC @ %s \n", tmpfunc->name);
  else
    fprintf(stderr, " ******** GLOBAL FUNCTION CALL : NOT CHANGING CURFUNC @ %s \n", tmpfunc->name);
#else
    }
Example #17
0
/**
 * The Real routine that handles each thread-specific breakpoint state machine.
 * 
 * breakpoint case:
 * 
 * 0-1: restore old instr, enable step, set bp addr in ->past, reset pc to orig bp addr
 * 1-2: do nothing (just executed instr)
 * 2-3: reinstall, resetstep, thread_contall, curthread->was_step = 0, 
 *     stoppedthread->count = NONE; e2dbgworld.curbp = NULL; stoppedthread = RUNNING
 *
 * stepping case:
 * 
 * 0-1: print current instr; reinstall
 *      stoppedthread->state = BREAKING; thread_contall; 
 *      was_step = 0; count = NONE; curbp = NULL; stoppedthread->state = RUNNING
 */
void			e2dbg_breakpoint_process()
{
  char			buf[32];
  elfshbp_t		*bp;
  int			prot;
  char			*name;
  elfsh_SAddr		off;
  int			ret;
  asm_instr		ptr;
  char			*s;
  eresi_Addr		*pc; 
  eresi_Addr		savedpc;
  u_int			bpsz;
  elfshsect_t		*sect;
  elfshobj_t		*parent;
  elfsh_Sym		*sym;

#if __DEBUG_BP__
  fprintf(stderr, " [D] Entering breakpoint handler\n");
#endif

  /* Set all registers as variables and get PC */
  e2dbg_user_hooks_install();
  e2dbg_getregs(); 
  pc = e2dbg_getpc();

  parent = e2dbg_get_parent_object((eresi_Addr) *pc);
  bpsz = elfsh_get_breaksize(parent);

  /* Print variables and registers on breakpoints */
  //if (!world.state.revm_quiet)
  //cmd_vlist();

  /* Try to find the breakpoint at current instruction pointer */
#if __DEBUG_BP__
  fprintf(stderr, " [D] At PC = %08X : Trying to find breakpoint at addr %08X (bpsize = %u)\n", 
	  *pc, *pc - bpsz, bpsz);
#endif

  snprintf(buf, sizeof(buf), XFMT, *pc - bpsz);
  bp = hash_get(&e2dbgworld.bp, buf);

#if __DEBUG_BP__
  if (bp)
    fprintf(stderr, " [D] Saved instruction BYTE = %02X and PC-BPSZ BYTE = %02X \n",
	    bp->savedinstr[0], *((u_char *) *pc - bpsz));
  else
    fprintf(stderr, " [D] No BP found at %08X ! \n", *pc);
#endif

  /* Case of processing breakpoint, or if we are single-stepping */
  if (!bp || (bp->savedinstr[0] == *((u_char *) *pc - bpsz)))
    {

      /* We are single-stepping, display the instruction at $pc */
      if (e2dbgworld.stoppedthread->step)
	{

#if __DEBUG_BP__
	  fprintf(stderr, " [D] Single-stepping -IS- enabled \n");
#endif

	  ret = asm_read_instr(&ptr, (u_char *) *pc, 16, world.curjob->proc);
	  if (!ret)
	    ret++;
	  sect   = elfsh_get_parent_section(parent, (eresi_Addr) *pc, NULL);
	  name   = revm_resolve(parent, (eresi_Addr) *pc, &off);
	  off = 0;
	  sym    = elfsh_get_metasym_by_value(parent, (eresi_Addr) *pc, 
					      &off, ELFSH_LOWSYM);

#if __DEBUG_BP__
	  fprintf(stderr, 
		  " [D] Found parent = %08X (%s) in step (name = %s, parentsect = %s) off = %u\n", 
		  (eresi_Addr) parent, parent->name, name, sect->name, off);
#endif

	  revm_instr_display(-1, *pc, 0, 20, name, off, (char *) *pc);
	  e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr);
	  if (!e2dbgworld.stoppedthread->trace)
	    e2dbg_entry(NULL);
	  else
	    e2dbg_watch();

	  e2dbg_breakpoint_reinstall();
	  return;
	}

#if __DEBUG_BP__
      fprintf(stderr, " [D] Single-stepping is -NOT- enabled \n");
#endif

      /* Here starts the real stuff 
      **
      ** count == E2DBG_BREAK_EXEC     -> execute restored instruction
      ** count == E2DBG_BREAK_FINISHED -> restore breakpoint
      ** count >  E2DBG_BREAK_MAX      -> e2dbg is getting debugged by a third party debugger
      */
      e2dbgworld.stoppedthread->count++;	
      
#if __DEBUG_BP__
      fprintf(stderr, " [C] Count %u -> %u for thread ID %u \n", 
	     e2dbgworld.stoppedthread->count - 1, 
	     e2dbgworld.stoppedthread->count, 
	     ((unsigned int) e2dbgworld.stoppedthread->tid));
#endif
      
      /* execute the previously restored instruction */
      if (e2dbgworld.stoppedthread->count == E2DBG_BREAK_EXEC)
	{
#if __DEBUG_BP__
	  printf(" [D] At PC = 0x%X : Debuggee executed restored instruction \n", *pc);
#endif
	  return;
	}
      
      /* Suggested by andrewg, useful when debugging valgrind */
      if (e2dbgworld.stoppedthread->count > E2DBG_BREAK_MAX)
	{
	  printf(".::- E2DBG WARNING -::.\n"
		 "Breakpoint triggered at location " AFMT " which we don't know about.\n\n"
		 "This may be an anti-debug trick or the program may be inside another\n"
		 "debugger. Exiting (DEBUG: count = " UFMT ", step is off)\n\n",
		 *pc - bpsz, e2dbgworld.stoppedthread->count);
	  return;
	}

      e2dbg_breakpoint_reinstall();
      
      /* remove trace flag */	  
#if __DEBUG_BP__
      fprintf(stderr, " [D] At PC = " AFMT " Resetting STEP mode\n", *pc);
#endif
      e2dbg_resetstep();
      return;
    }

  /* Case of newly hit breakpoint */
  else
    {
      name = revm_resolve(parent, (eresi_Addr) *pc - bpsz, &off);
      s    = (e2dbg_is_watchpoint(bp) ? "Watch" : "Break");

#if __DEBUG_BP__
      fprintf(stderr, " [C] Count set to 1 (HIT) for thread ID %u \n", 
		(unsigned int) e2dbgworld.stoppedthread->tid);
#endif      
      
      if (off)
	printf(" [*] %spoint found at " XFMT " <%s + " DFMT "> in thread %u \n\n", 
	       s, *pc - bpsz, name, off, (unsigned int) e2dbgworld.stoppedthread->tid);
      else 
	printf(" [*] %spoint found at " XFMT " <%s> in thread %u \n\n",   
	       s, *pc - bpsz, name, (unsigned int) e2dbgworld.stoppedthread->tid);

      revm_doswitch(parent->id);
      mjr_set_current_context(&world.mjr_session, parent->name);
      
      *pc -= bpsz;
      prot = elfsh_munprotect(bp->obj, *pc,  bpsz);
      memcpy((u_char *) *pc, bp->savedinstr, bpsz);
      elfsh_mprotect(bp->obj, *pc, bpsz, prot);

      e2dbg_setstep();

#if __DEBUG_BP__
      fprintf(stderr, " [D] Setting Step mode \n");
#endif

      e2dbgworld.stoppedthread->past  = *pc;
      e2dbgworld.stoppedthread->count = E2DBG_BREAK_HIT;
      e2dbgworld.curbp                = bp;
      bp->tid                         = (uint32_t) e2dbgworld.stoppedthread->tid;

#if __DEBUG_BP__
      fprintf(stderr, " [D] Reset break \n");
#endif

      if (bp->cmdnbr)
	e2dbg_display(bp->cmd, bp->cmdnbr);
      else
	e2dbg_display(e2dbgworld.displaycmd, e2dbgworld.displaynbr);

#if __DEBUG_BP__
      fprintf(stderr, " [D] After BP display \n");
#endif

#if __DEBUG_BP__
      fprintf(stderr, " [D] PC before entry is addr 0x%X \n", *pc);
#endif
      
      savedpc = *pc;
      e2dbg_entry(NULL);
      *pc = savedpc;

#if __DEBUG_BP__
      fprintf(stderr, " [D] At PC = 0x%X : returned from BP handler with step enabled\n",
	      *pc);
#endif
    }
}
Example #18
0
/**
 * Get function addr list from call search basic
 * @param file target file
 * @param addr address list
 */
int			elfsh_addr_get_func_list(elfshobj_t *file, eresi_Addr **addr)
{
  int 			ret;
  int			index;
  asm_instr		instr;
  elfsh_SAddr		foffset;
  elfsh_Word		len;
  char			*base;
  asm_processor		proc;
  eresi_Addr		base_vaddr, caddr;
  u_char		found = 0;
  elfshsect_t		*text;
  eresi_Addr		*vaddr;
  const int		astep = 20;
  u_int			apos = 0;
  btree_t		*broot = NULL;
  u_int			diff;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

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

  /* Search entrypoint section, our address must be in this section */
  text = elfsh_get_parent_section(file, elfsh_get_entrypoint(file->hdr), &foffset);

  if (!text)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "Cannot find parent section from entry point", -1);
  
  if (!elfsh_get_anonymous_section(file, text))
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		 "Unable to get an anonymous section", -1);
  
  base = elfsh_readmem(text);
  len = text->shdr->sh_size;

  /* Get the virtual address */
  base_vaddr = (elfsh_is_runtime_mode() && !elfsh_section_is_runtime(text) ?
		file->rhdr.base + elfsh_get_section_addr(text->shdr) :
		elfsh_get_section_addr(text->shdr));

  /* Setup asm_processor structure */
  if (etrace_setup_proc(file, &proc) < 0)
        PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__,
		 "Failed during proc structure setup", -1);

  XALLOC(__FILE__, __FUNCTION__, __LINE__, vaddr, sizeof(eresi_Addr)*astep, -1);
  
  /* Despite the fact that we choose the right architecture to init asm,
     Our approach is totally architecture independant as we search using
     global type ASM_TYPE_CALLPROC and we know that op[0].imm will contain a
     relative value. */
  for (index = 0; index < len; index += ret)
    {
      /* Read an instruction */
      if ((ret = asm_read_instr(&instr, (u_char *) (base + index), len -  index, &proc)))
	{
	  /* Global assembler filter */
	  if ((instr.type & ASM_TYPE_CALLPROC)
	      && instr.op[0].imm != 0)
	    {
	      caddr = base_vaddr + index + instr.op[0].imm + instr.len;

	      /* Found a call check its local */
	      if (INTERVAL(base_vaddr, caddr, base_vaddr + len))
		{
		  found = 1;

		  diff = (u_int) caddr;

		  /* Avoid double entrie */
		  if (btree_get_elem(broot, diff) != NULL)
		    goto next;

		  btree_insert(&broot, diff, (void *)0x1);

		  /* Next will be the last of the current list
		     then realloc */
		  if ((apos+1) % astep == 0)
		    {
		      XREALLOC(__FILE__, __FUNCTION__, __LINE__, vaddr, vaddr,
			       sizeof(eresi_Addr)*(apos+1+astep), -1);

		      /* Blank new elements */
		      memset(&vaddr[apos], 0x00, astep*sizeof(eresi_Addr));
		    }

		  vaddr[apos++] = caddr;
		}
	    }
	}

    next:

      if (ret <= 0)
	ret = 1;
    }

  /* If nothing found we free allocated buffer and
     return an error */
  if (!found)
    {
      XFREE(__FILE__, __FUNCTION__, __LINE__, vaddr);
      PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		   "No call internal found", -3);
    }
  
  btree_free(broot, 0);

  *addr = vaddr;
  
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);
}
Example #19
0
/* Find the correct location for a breakpoint. Avoid putting breakpoints 
   on plt entries when possible */
eresi_Addr	e2dbg_breakpoint_find_addr(char *str)
{
  elfsh_Sym	*sym;
  elfsh_Sym	*bsym;
  elfshsect_t	*sect;
  elfshobj_t	*parent;
  char		**keys;
  int		keynbr;
  int		index;
  eresi_Addr	addr;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);
  sym = bsym = NULL;

  /* Sometimes we fix symbols on the disk : we avoid mprotect */
  /* Only return success early if not a plt symbol */
  keys = NULL;
  parent = world.curjob->curfile;
  sym = elfsh_get_metasym_by_name(parent, str);
  if (!sym || !sym->st_value)
    {
      elfsh_toggle_mode();
      sym = elfsh_get_metasym_by_name(parent, str);
      elfsh_toggle_mode();
    }
  
  if (sym && parent->hdr->e_type == ET_DYN)
    sym->st_value += parent->rhdr.base;

  if (sym && sym->st_value)
    {
      sect = elfsh_get_parent_section(parent, sym->st_value, NULL);
      if (!elfsh_is_plt(parent, sect))
	goto end;
    }

  /* Try to look in other objects */
  keys = hash_get_keys(&world.curjob->loaded, &keynbr);
  
  for (index = 0; index < keynbr; index++)
    {
      if (strstr(keys[index], E2DBG_ARGV0))
	continue;

      parent = hash_get(&world.curjob->loaded, keys[index]);
      bsym = elfsh_get_metasym_by_name(parent, str);
      if (!bsym || !bsym->st_value)
	{
	  elfsh_toggle_mode();
	  bsym = elfsh_get_metasym_by_name(parent, str);
	  elfsh_toggle_mode();
	  if (bsym && bsym->st_value)
	    {
	      sect = elfsh_get_parent_section(parent, bsym->st_value, NULL);
	      if (!elfsh_is_plt(parent, sect))
		{
		  sym = bsym;
		  if (strstr(parent->name, "libc.so"))
		    goto end;
		}
	      if (!sym)
		sym = bsym;
	    }
	}
      else
	{
	  sect = elfsh_get_parent_section(parent, bsym->st_value, NULL);
	  if (!elfsh_is_plt(parent, sect))
	    {
	      sym = bsym;
	      if (strstr(parent->name, "libc.so"))
		goto end;
	    }
	  if (!sym)
	    sym = bsym;
	}

#if __DEBUG_BP__
      printf("BPSym after %-30s = " XFMT "\n", parent->name, (eresi_Addr) sym);
#endif

    }

  /* Return error or success, dont forget to free the keys */
 end:
  if (keys)
    hash_free_keys(keys);

  if (!sym || !sym->st_value)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		 "No symbol by that name in the current file", 0);
  addr = sym->st_value;
  if (elfsh_get_objtype(parent->hdr) == ET_DYN)
    {
#if __DEBUG_BP__
      printf(" [*] Adding base addr " XFMT " of ET_DYN %s\n", 
	     parent->rhdr.base, parent->name);
#endif
      addr += parent->rhdr.base;
    }
  
#if __DEBUG_BP__
  printf(" [*] Will set breakpoint on " XFMT " (parent = %s) \n", 
	 addr, parent->name);
#endif

  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, addr);
}