/** * 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); }
/** * Relocate the just injected section * @param enew * @param reltab * @param stage * @return */ static int elfsh_relocate_etrel_section(elfshsect_t *enew, elfshsect_t *reltab, u_char stage) { elfsh_Rel *cur; volatile u_int index; elfsh_Sym *sym; volatile u_int size; eresi_Addr *dword; eresi_Addr addr; char *name; char tmpname[BUFSIZ]; elfshsect_t *sect; u_int entsz; elfshsect_t *plt; void *data; elfsh_Half symtype; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* ET_REL object is not mapped we use unconditionaly the ondisk relocation tables for such operation */ data = reltab->data; #if __DEBUG_RELADD__ fprintf(stderr, "[DEBUG_RELADD] Using reloc table from %s [%s] data at %p \n", reltab->parent->name, reltab->name, data); #endif /* Loop on the relocation table entries */ size = (reltab->shdr->sh_type == SHT_RELA ? sizeof(elfsh_Rela) : sizeof(elfsh_Rel)); size = reltab->shdr->sh_size / size; plt = elfsh_get_plt(enew->parent, NULL); if (NULL == plt && elfsh_dynamic_file(enew->parent)) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to get plt", -1); entsz = elfsh_get_pltentsz(enew->parent); if (entsz < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to get pltentsz", -1); for (index = 0; index < size; index++) { #if __DEBUG_RELADD__ fprintf(stderr, "[DEBUG_RELADD] relocation loop stage %u for section %s index %u \n", stage, enew->name, index); #endif /* We try a enew relocation now that the ET_REL dependence is mapped */ retry: /* Get symbol value in ET_REL */ cur = (reltab->shdr->sh_type == SHT_RELA ? (void *) (((elfsh_Rela *) data) + index) : (void *) (((elfsh_Rel *) data) + index)); sym = elfsh_get_symbol_from_reloc(reltab->parent, cur); name = elfsh_get_symname_from_reloc(reltab->parent, cur); if (sym == NULL || name == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to find symbol in ET_REL", -1); /* Grab a pointer on the dword that need to be relocated */ dword = (eresi_Addr *) ((char *) elfsh_readmem(enew) + cur->r_offset); /* ** If symbol type is NOTYPE, we use ET_EXEC symtab, else if ** symbol link is COMMON, we use ET_REL symbol inserted in ET_EXEC ** during BSS sizescan in bss.c:elfsh_find_bsslen() */ symtype = elfsh_get_symbol_type(sym); if (elfsh_get_symbol_bind(sym) != STB_LOCAL && /* patch BEOS */ (symtype == STT_NOTYPE || elfsh_get_symbol_link(sym) == SHN_COMMON)) { if (stage == ELFSH_RELOC_STAGE2 && !strstr(name, "old_")) continue; /* If the symbol is not found and we are still in the first stage relocation, just pass it */ sym = elfsh_get_metasym_by_name(enew->parent, name); if (!sym) { switch (elfsh_find_relocsym(enew, reltab, &sym, name, stage, symtype)) { case 2: #if __DEBUG_STATIC__ fprintf(stderr, "[DEBUG_STATIC] RETRY\n"); #endif goto retry; break; case 0: continue; case 1: break; case -1: default: PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to satisfy symbol in ET_REL", -1); } } addr = sym->st_value; #if __DEBUG_RELADD__ fprintf(stderr, "[DEBUG_RELADD] Relocate using existing symbol %-20s " AFMT "]\n", name, (eresi_Addr) addr); #endif } /* Compute addr giving the injected section's vaddr in ET_EXEC */ else { /* All the following relocs are computed in stage 1 */ if (stage == ELFSH_RELOC_STAGE2) continue; /* Find target section in ET_REL */ sect = elfsh_get_section_by_index(reltab->parent, sym->st_shndx, NULL, NULL); if (sect == NULL) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cant find extracted section in ET_REL", -1); #if __DEBUG_RELADD__ fprintf(stderr, "[DEBUG_RELADD] Found -%s- section (idx = %u), now looking at " "injected base address\n", sect->name, sect->index); #endif /* Find corresponding inserted section in ET_EXEC */ snprintf(tmpname, sizeof(tmpname), "%s%s", reltab->parent->name, sect->name); sect = elfsh_get_section_by_name(enew->parent, tmpname, NULL, NULL, NULL); if (sect == NULL) { #if __DEBUG_RELADD__ elfsh_print_sectlist(reltab->parent, "HEH"); fprintf(stderr, "[DEBUG_RELADD] Did not found %s section (sym = %s) \n", tmpname, name); #endif PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Cant find inserted section in ET_EXEC", -1); } /* Compute pointer value */ addr = sect->shdr->sh_addr; addr += ((elfsh_get_symbol_type(sym) == STT_SECTION && !FILE_IS_SPARC(sect->parent) && !FILE_IS_ALPHA64(sect->parent) && !FILE_IS_MIPS(sect->parent)) ? *dword : sym->st_value); #if __DEBUG_RELADD__ fprintf(stderr, "[DEBUG_RELADD] Relocate using section %-20s base [-> " AFMT "] \n", sect->name, (eresi_Addr) addr); #endif } /* Perform relocation */ if (elfsh_relocate_entry(enew, cur, dword, addr, reltab) < 0) PROFILER_ERR(__FILE__, __FUNCTION__, __LINE__, "Unable to relocate entry", -1); } PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 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); }