Exemple #1
0
/**
 * Perform a raw write on the object cache data 
 * @param file
 * @param foffset
 * @param src_buff
 * @param len
 * @return
 */
int		elfsh_raw_write(elfshobj_t	*file, 
				u_int		foffset, 
				void		*src_buff, 
				int		len)
{
  elfshsect_t	*sect;
  int		sect_off;
  void		*dst;
  int		prot;

  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);

  sect = elfsh_get_parent_section_by_foffset(file, foffset, NULL);
  if (sect == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid virtual address", -1);

  sect_off = foffset - sect->shdr->sh_offset;
  if (sect_off + len > sect->shdr->sh_size)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Section too short", -1);

  dst = elfsh_get_anonymous_section(file, sect);
  if (dst == NULL)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);

  if (elfsh_is_runtime_mode())
    {
      prot = elfsh_munprotect(file, (eresi_Addr) dst + sect_off, len);
      memcpy(dst + sect_off, src_buff, len);
      elfsh_mprotect(file, (eresi_Addr) dst + sect_off, len, prot);
    }
  else
    memcpy(dst + sect_off, src_buff, len);

  
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (len));
}
Exemple #2
0
/**
 * Perform a raw read on the object cache data 
 * @param file
 * @param foffset
 * @param dest_buff
 * @param len
 * @return
 */
int		elfsh_raw_read(elfshobj_t *file, u_int foffset, void *dest_buff, int len)
{
  volatile elfshsect_t	*sect;
  volatile void	*src;
  volatile int	sect_off;
  
  PROFILER_IN(__FILE__, __FUNCTION__, __LINE__);
  sect = elfsh_get_parent_section_by_foffset(file, foffset, NULL);
  if (sect == NULL)
    PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, 
		      "Invalid virtual address", -1);

  sect_off = foffset - sect->shdr->sh_offset;
  if (sect_off + len > sect->shdr->sh_size)
    len -= (sect_off + len - sect->shdr->sh_size);
  
  src = elfsh_get_anonymous_section(file, sect);
  if (src == NULL)
    PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0);

  memcpy(dest_buff, src + sect_off, len);
  PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (len));
}
/**
 * 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);
}
/**
 * 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);
}
Exemple #5
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);
}
Exemple #6
0
/**
 * 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);
}