int main(int argc, char **argv) { elfshobj_t *host; elfshobj_t *rel; elfshsect_t *txtsect; elfsh_Sym *puts_troj; elfsh_Sym *hook_func; int idx; u_long addr; /* Map host file and relocatable file */ rel = elfsh_map_obj(RELOC_FILE); if (NULL == rel) goto err; host = elfsh_map_obj(TROJANED_FILE); if (NULL == host) goto err; /* Inject etrel */ idx = elfsh_inject_etrel(host, rel); if (idx < 0) goto err; /* Get injected's section info */ txtsect = elfsh_get_section_by_name(host, RELOC_FILE".text", NULL, NULL, NULL); if (txtsect == NULL) goto err; puts_troj = elfsh_get_symbol_by_name(host, "puts_troj"); idx = elfsh_hijack_function_by_name(host, ELFSH_HIJACK_TYPE_PLT, "puts", puts_troj->st_value, NULL); if (idx < 0) goto err; hook_func = elfsh_get_symbol_by_name(host, "hook_func"); idx = elfsh_hijack_function_by_name(host, ELFSH_HIJACK_TYPE_FLOW, "legit_func", hook_func->st_value, NULL); if (idx < 0) goto err; /* Save it */ idx = elfsh_save_obj(host, OUTPUT_FILE); if (idx < 0) goto err; puts("[*] ET_REL injected"); return (0); err: elfsh_error(); return (-1); }
/** * 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); }
eresi_Addr dl_auxv_offset(char *lib){ elfshobj_t *f; f = elfutils_read_elf_file(lib); if (NULL == f){ return -1; } elfsh_Sym *s; s = elfsh_get_symbol_by_name(f, "_dl_auxv"); return s->st_value; }
/** * Remove a symbol * This function is not e2dbg safe * @param symtab * @param name * @return */ int elfsh_remove_symbol(elfshsect_t *symtab, char *name) { elfsh_Sym *ret; elfsh_Sym *tab; elfsh_Sym *enew; u_int off; u_int movedsz; hash_t *uptable = NULL; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sanity checks */ if (symtab == NULL || name == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Invalid parameters", -1); ret = elfsh_get_symbol_by_name(symtab->parent, name); if (ret == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unknown symbol", -1); /* Do it */ tab = symtab->data; off = (u_long) ret - (u_long) tab; movedsz = symtab->shdr->sh_size - off - sizeof(elfsh_Sym); if (movedsz) memcpy((char *) symtab->data + off, (char *) symtab->data + off + sizeof(elfsh_Sym), movedsz); symtab->shdr->sh_size -= sizeof(elfsh_Sym); symtab->curend -= sizeof(elfsh_Sym); XALLOC(__FILE__, __FUNCTION__, __LINE__,enew, symtab->shdr->sh_size, -1); memcpy(enew, tab, symtab->shdr->sh_size); XFREE(__FILE__, __FUNCTION__, __LINE__,tab); symtab->data = enew; /* We just cant remove the string because of ELF string table format */ elfsh_sync_sorted_symtab(symtab); /* Update hashtable */ switch(symtab->shdr->sh_type) { case SHT_SYMTAB: uptable = &symtab->parent->symhash; break; case SHT_DYNSYM: uptable = &symtab->parent->dynsymhash; break; } if (uptable && uptable->ent) hash_del(uptable, name); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 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__); }
/** * Load linkmap * @param name * @return */ int e2dbg_linkmap_load(char *name) { static int done = 0; elfshsect_t *got; eresi_Addr *linkmap_entry; void *data; #if defined(sun) Link_map *actual; #else elfshlinkmap_t *actual; #endif char *gotname; char *ename; elfsh_Ehdr *hdr; u_int elftypenum; elfsh_Sym *endsym; char buff[64]; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); if (done) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg] Starting Loading LINKMAP !! \n"); #endif e2dbg_user_hooks_install(); revm_config(E2DBG_CONFIG); /* Load debugged file */ if (name) { /* No need to fill ET_EXEC base addr */ if (!revm_is_loaded(name) && revm_file_load(name, 0, NULL) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot load file", -1); #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] file %s loaded\n", name); #endif world.curjob->curfile->linkmap = E2DBG_DYNAMIC_LINKMAP; world.curjob->curfile->iotype = ELFSH_IOTYPE_EMBEDDED; world.curjob->curfile->running = 0; } #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] Before switch\n"); #endif /* Switch to obj 1 */ if (revm_doswitch(1) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot switch on object 1", -1); #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] After switch \n"); #endif /* Base address for PIE binaries have to be imported */ if (world.curjob->curfile->hdr->e_type == ET_DYN && !world.curjob->curfile->rhdr.base) { #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] Inside ET_DYN condition\n"); #endif endsym = elfsh_get_symbol_by_name(world.curjob->curfile, "_end"); fprintf(stderr, "endsym = " AFMT " \n", (eresi_Addr) endsym); sleep(1); #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] Filling PIE base" " (_end ondisk = " AFMT " / _end in memory = " AFMT ") ! \n", endsym->st_value, e2dbgworld.syms.piebase); #endif world.curjob->curfile->rhdr.base = e2dbgworld.syms.piebase - endsym->st_value; } /* Get ALTGOT or GOT if we used LD_PRELOAD */ if (!e2dbgworld.preloaded) { gotname = ELFSH_SECTION_NAME_ALTGOT; got = elfsh_get_section_by_name(world.curjob->curfile, gotname, NULL, NULL, NULL); } else got = elfsh_get_gotsct(world.curjob->curfile); #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] %s section at " XFMT "\n", got->name, got->shdr->sh_addr); fprintf(stderr, "[e2dbg_linkmap_load] BASE = %08x\n", world.curjob->curfile->rhdr.base); #endif /* Fix first file linkmap entry */ if (world.curjob->curfile->linkmap == E2DBG_DYNAMIC_LINKMAP) { /* Fix first file linkmap entry */ hdr = elfsh_get_hdr(world.curjob->curfile); if (!hdr) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cannot get ELF header", -1); elftypenum = elfsh_get_objtype(hdr); //fprintf(stderr, "[e2dbg_linkmap_load] after ELF header \n"); /* Get ALTGOT entry */ data = elfsh_readmem(got); //fprintf(stderr, "[e2dbg_linkmap_load] after get_raw (data = %08X) \n", data); linkmap_entry = elfsh_get_got_entry_by_index(data, 1); //fprintf(stderr, "[e2dbg_linkmap_load] after entry_by_index (linkmap_entry = %08x)\n", // linkmap_entry); #if defined(__FreeBSD__) || defined(__NetBSD__) world.curjob->curfile->linkmap = (elfshlinkmap_t *) &((Obj_Entry *) elfsh_get_got_val(linkmap_entry))->linkmap; #elif defined(sun) world.curjob->curfile->linkmap = e2dbgworld.syms.map; #else world.curjob->curfile->linkmap = (elfshlinkmap_t *) elfsh_get_got_val(linkmap_entry); #endif } #if __DEBUG_LINKMAP__ else fprintf(stderr, "[e2dbg_linkmap_load] Linkmap was -NOT- dynamic\n"); fprintf(stderr, "[e2dbg_linkmap_load] LINKMAP Found at " XFMT "\n", world.curjob->curfile->linkmap); #endif revm_doswitch(1); /* now load all linkmap's files */ for (actual = elfsh_linkmap_get_lprev(world.curjob->curfile->linkmap); actual != NULL; actual = elfsh_linkmap_get_lprev(actual)) { #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] Running on LINKMAP PREV " XFMT "\n", actual); #endif ename = elfsh_linkmap_get_lname(actual); if (ename && *ename && !revm_is_loaded(ename)) { if (revm_file_load(ename, elfsh_linkmap_get_laddr(actual), world.curjob->curfile->linkmap) < 0) e2dbg_output(" [EE] Loading failed"); world.curjob->curfile->iotype = ELFSH_IOTYPE_EMBEDDED; } } #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] Running on LINKMAP NEXT\n"); #endif for (actual = elfsh_linkmap_get_lnext(world.curjob->curfile->linkmap); actual != NULL; actual = elfsh_linkmap_get_lnext(actual)) { ename = elfsh_linkmap_get_lname(actual); #if __DEBUG_LINKMAP__ fprintf(stderr, "[e2dbg_linkmap_load] Running on LINKMAP NEXT " XFMT " (%s baseaddr %08X) \n", actual, ename, actual->laddr); #endif if (ename && *ename && !revm_is_loaded(ename)) { if (revm_file_load(ename, elfsh_linkmap_get_laddr(actual), world.curjob->curfile->linkmap) < 0) e2dbg_output(" [EE] Loading failed"); world.curjob->curfile->iotype = ELFSH_IOTYPE_EMBEDDED; } } /* Everything was OK */ e2dbg_output("\n"); //elfsh_set_runtime_mode(); revm_doswitch(1); snprintf(buff, sizeof(buff), " [*] Target PID = %u \n", getpid()); e2dbg_output(buff); done = 1; PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * Insert a symbol in the given symbol table * This function is not e2dbg safe * @param sect * @param sym * @param name * @return */ int elfsh_insert_symbol(elfshsect_t *sect, elfsh_Sym *sym, char *name) { elfsh_Sym *orig; int index; int mode; hash_t *uptable; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); //fprintf(stderr, "Adding symbol %s \n", name); /* Sanity checks */ if (sect == NULL || sect->shdr == NULL || (sect->shdr->sh_type != SHT_SYMTAB && sect->shdr->sh_type != SHT_DYNSYM)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Input section is not SYMTAB", -1); if (name == NULL) name = ELFSH_NULL_STRING; /* Check if symbol already exists */ orig = elfsh_get_symbol_by_name(sect->parent, name); if (orig != NULL && sym->st_value == orig->st_value) PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, (((char *) orig - (char *) sect->data) / ELFSH_SYMTAB_ENTRY_SIZE)); /* Shift some special symbols */ //if (sect->shdr->sh_type == SHT_DYNSYM) //fprintf(stderr, "Shifting usual symbols\n"); mode = elfsh_get_mode(); elfsh_set_static_mode(); elfsh_shift_usualsyms(sect, sym); elfsh_set_mode(mode); //fprintf(stderr, "Shifted usual symbols\n"); /* Insert symbol name in .shstrtab */ index = elfsh_insert_in_strtab(sect->parent, name); if (index < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to insert in SHSTRTAB", -1); #if __DEBUG_RELADD__ fprintf(stderr, "[DEBUG_RELADD] Injected symbol %-20s [" AFMT "] \n", name, (eresi_Addr) sym->st_value); #endif /* Insert symbol in .symtab */ sym->st_name = index; index = elfsh_append_data_to_section(sect, sym, sizeof(elfsh_Sym)); /* Update hashtable */ switch(sect->shdr->sh_type) { case SHT_SYMTAB: uptable = §->parent->symhash; break; case SHT_DYNSYM: uptable = §->parent->dynsymhash; break; default: uptable = NULL; break; } if (uptable && uptable->ent) hash_add(uptable, strdup(name), (void *) index); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, sym->st_name); }