/** * like revm_lookup_addr - Get address value * @param file host file * @param param name to search * @return addresse found or 0 */ eresi_Addr edfmt_lookup_addr(elfshobj_t *file, char *param) { elfsh_Sym *sym; char eol; int ret; eresi_Addr val; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Lookup .symtab */ sym = elfsh_get_symbol_by_name(file, param); if (sym != NULL && sym->st_value > 0) { PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, sym->st_value); } /* Lookup .dynsym */ sym = elfsh_get_dynsymbol_by_name(file, param); if (sym != NULL && sym->st_value > 0) { PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, sym->st_value); } /* Lookup hexadecimal numeric value */ ret = sscanf(param, XFMT "%c", &val, &eol); if (ret == 1) { PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, val); } /* No match -- returns ERR */ PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to lookup address object", (eresi_Addr) 0); }
/** * Shift usual symbols (mandatory on solaris) * @param sect * @param sym */ void elfsh_shift_usualsyms(elfshsect_t *sect, elfsh_Sym *sym) { elfsh_Sym *end; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); //fprintf(stderr, "Calling shift usual syms ! \n"); /* Change _end in the symbol table */ end = elfsh_get_symbol_by_name(sect->parent, "_end"); if (end != NULL && sym->st_value + sym->st_size > end->st_value) { //printf("Shift _end! \n"); end->st_value = sym->st_value + sym->st_size; } /* Change _end if necessary (solaris) */ end = elfsh_get_dynsymbol_by_name(sect->parent, "_end"); if (end != NULL && sym->st_value + sym->st_size > end->st_value) { //printf("Shift _end! \n"); end->st_value = sym->st_value + sym->st_size; } /* Change _END_ if necessary (solaris) */ end = elfsh_get_dynsymbol_by_name(sect->parent, "_END_"); if (end != NULL && sym->st_value + sym->st_size > end->st_value) { //printf("Shift _END_! \n"); end->st_value = sym->st_value + sym->st_size; } /* Change _edata if necessary (solaris) */ if (elfsh_get_ostype(sect->parent) == ELFSH_OS_SOLARIS) { end = elfsh_get_dynsymbol_by_name(sect->parent, "_edata"); if (end != NULL && sym->st_value + sym->st_size > end->st_value) { //printf("Shift _edata! \n"); end->st_value = sym->st_value + sym->st_size; } } PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); }
/** * @brief Patch the first PLT entry (a special case which must handled by this function). * @param enew * @param off * @param symtab Section descriptor for the symbol table. * @param file Host file. * @param extplt Section descriptor for the previously injected .elfsh.extplt * @param plt Section descriptor for the .plt section. * @param diff * @return Success (0) or Error (-1). */ int elfsh_altplt_firstent(elfshsect_t *enew, u_int *off, elfshsect_t *symtab, elfshobj_t *file, elfshsect_t *extplt, elfshsect_t *plt, uint32_t diff) { u_int entsz; elfsh_Sym newsym; elfsh_Sym *sym; eresi_Addr addr; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Insert plt+0 symbol */ entsz = elfsh_get_pltentsz(file); newsym = elfsh_create_symbol(enew->shdr->sh_addr, entsz, STT_FUNC, 0, 0, 0); if (elfsh_insert_symbol(symtab, &newsym, "old_dlresolve") < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to insert old_dlresolve symbol", -1); *off = *off - entsz + elfsh_get_first_pltentsz(file); /* On MIPS we have to callback __libc_start_main and not .plt+0 */ if (FILE_IS_MIPS(plt->parent)) { sym = elfsh_get_dynsymbol_by_name(file, "__libc_start_main"); if (!sym) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot find __libc_start_main", -1); #if __DEBUG_COPYPLT__ printf("[DEBUG_COPYPLT] Found __libc_start_main MIPS at addr " XFMT "\n", sym->st_value); #endif addr = sym->st_value; } else addr = plt->shdr->sh_addr; /* Call the libelfsh hook ALTPLT */ if (elfsh_altplt(file, &newsym, addr) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "ALTPLT failed", -1); /* On IA32, reencode the PLT and EXTPLT entries to use the ALTGOT */ /* The hook does nothing on other archs for now */ if (FILE_IS_IA32(file)) if (elfsh_encodeplt1(file, plt, extplt, diff) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Reencoding of (EXT)PLT+0 failed", -1); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * @brief Change the DT_PLTGOT entry in the .dynamic section to change * the relocation base address. * @param file The host file. * @param altgot Section descriptor for the .elfsh.altgot section. * @param got Section descriptor for the .got section. * @param plt Section descriptor for the .plt section. * @param altplt Section descriptor for the .elfsh.altplt section. * @return Success (0) or Error (-1). */ int elfsh_redirect_pltgot(elfshobj_t *file, elfshsect_t *altgot, elfshsect_t *got, elfshsect_t *plt, elfshsect_t *altplt) { elfsh_Sym *sym; elfsh_Dyn *dyn; elfshsect_t *relplt; char *name; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Get the DT_PLTGOT entry in .dynamic */ dyn = elfsh_get_dynamic_entry_by_type(file, DT_PLTGOT); if (!dyn) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot find DT_PLTGOT", -1); /* Get the PLT related relocation table */ name = IS_REL(plt) ? ELFSH_SECTION_NAME_RELPLT : ELFSH_SECTION_NAME_RELAPLT; relplt = elfsh_get_section_by_name(plt->parent, name, 0, 0, 0); if (!relplt) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot find RELPLT section by name", -1); /* On MIPS we change it from .got to .alt.got : ALTGOT technique */ if (FILE_IS_MIPS(file) || FILE_IS_IA32(file)) { elfsh_set_dynentry_val(dyn, altgot->shdr->sh_addr); if (FILE_IS_MIPS(file)) { elfsh_set_gpvalue(file, altgot->shdr->sh_addr + 0x8000 - 0x10); sym = elfsh_get_dynsymbol_by_name(file, "_gp_disp"); if (sym == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Could not find _gp_disp ", -1); sym->st_value = altgot->shdr->sh_addr + 0x8000 - 0x10; elfsh_shift_mips_relocs(file, altgot->shdr->sh_addr - got->shdr->sh_addr); } else elfsh_shift_ia32_relocs(file, altgot->shdr->sh_addr - got->shdr->sh_addr, relplt, ELFSH_NOLIMIT); } /* On SPARC we change it from .plt to .alt.plt : ALTPLT technique */ else if (FILE_IS_SPARC(file)) { elfsh_set_dynentry_val(dyn, altplt->shdr->sh_addr); elfsh_shift_sparc_relocs(file, altplt->shdr->sh_addr - plt->shdr->sh_addr, relplt); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }