/** * Debug : print the section list * @param obj * @param label * @return */ int elfsh_print_sectlist(elfshobj_t *obj, char *label) { elfshsect_t *actual; u_int index; u_char *data; char *sctname; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); printf(" [SCTLIST][%s]\n", label); for (index = 0, actual = obj->sectlist; actual != NULL; index++, actual = actual->next) { sctname = elfsh_get_section_name(obj, actual); if (sctname == NULL) sctname = "UNK"; data = elfsh_readmem(actual); if (data == (u_char *)NULL) data = (u_char *)"\xFF\xFF\xFF"; printf(" [%03u:%03u] %-15s HDRNAM: %-15s BYTES[%02X %02X %02X] P(%8p) " "A(%8p) N(%8p) SCTIDX(%03u) HDRFOFF:%010u SZ:%010u VADDR:%08X \n", index, actual->index, (actual->name != NULL ? actual->name : "UNK"), sctname, (u_int) data[0], (u_int) data[1], (u_int) data[2], actual->prev, actual, actual->next, actual->index, (u_int) actual->shdr->sh_offset, (u_int) actual->shdr->sh_size, (u_int) actual->shdr->sh_addr); } puts(" [EOL]\n"); fflush(stdout); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * @brief Display relocation entries */ int cmd_rel() { elfshsect_t *sect; elfsh_Rel *rel; regex_t *tmp; char *type; char *typeshort; char *name; u_int index; u_int index2; u_int typenum; char buff[256]; u_int size; revmconst_t *types; char addstr[32]; char logbuf[BUFSIZ]; void *data; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); /* Sanity checks */ sect = elfsh_get_reloc(world.curjob->curfile, 0, &size); if (sect == NULL) RET(-1); /* Choose between global or local regx */ FIRSTREGX(tmp); snprintf(logbuf, BUFSIZ - 1, " [RELOCATION TABLES]\n [Object %s]\n\n", world.curjob->curfile->name); revm_output(logbuf); /* We need to iterate as much as there is .rel* sections */ for (index2 = 0; sect; index2++) { snprintf(logbuf, BUFSIZ - 1, " {Section %s} \n", elfsh_get_section_name(world.curjob->curfile, sect)); revm_output(logbuf); /* Iterate on the .rel entries array for each .rel section */ data = elfsh_readmem(sect); for (index = 0; index < size; index++) { /* Get the current relocation entry */ if (sect->shdr->sh_type == SHT_RELA) { rel = (void *) ((elfsh_Rela *) data + index); snprintf(addstr, sizeof(addstr), "add[%s]", revm_colornumber("%08u", (unsigned int) ((elfsh_Rela *) rel)->r_addend)); } else { rel = (elfsh_Rel *) data + index; addstr[0] = 0x00; } /* Get linked symbol name */ name = elfsh_get_symname_from_reloc(world.curjob->curfile, rel); typenum = elfsh_get_reltype(rel); types = revm_getrelascii(world.curjob->curfile); type = (char *) (typenum > ELFSH_RELOC_MAX(world.curjob->curfile) ? NULL : types[typenum].desc); typeshort = (char *) (typenum > ELFSH_RELOC_MAX(world.curjob->curfile) ? NULL : types[typenum].name); /* Output is different depending on the quiet flag */ if (!world.state.revm_quiet) snprintf(buff, sizeof(buff), " [%s] %s %s %s%s%s : %s %s => %s\n", revm_colornumber("%03u", index), revm_colortypestr_fmt("%-15s", typeshort), revm_coloraddress(XFMT, elfsh_get_reloffset(rel)), revm_colorfieldstr("sym["), revm_colornumber("%03u", elfsh_get_relsym(rel)), revm_colorfieldstr("]"), (name != NULL ? revm_colorstr_fmt("%-30s", name) : revm_colorwarn_fmt("%-30s", "<?>")), addstr, revm_colortypestr(type)); else snprintf(buff, sizeof(buff), " [%s] %s %s %s%s%s : %s %s\n", revm_colornumber("%03u", index), revm_colortypestr_fmt("%-15s", typeshort), revm_coloraddress(XFMT, elfsh_get_reloffset(rel)), revm_colorfieldstr("sym["), revm_colornumber("%03u", elfsh_get_relsym(rel)), revm_colorfieldstr("]"), (name != NULL ? revm_colorstr_fmt("%-22s", name) : revm_colorwarn_fmt("%-22s", "<?>")), addstr); /* Print it if it matchs the regex */ if (NULL == tmp || (tmp != NULL && name != NULL && 0 == regexec(tmp, buff, 0, 0, 0))) switch (revm_output(buff)) { case -1: revm_endline(); revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); case -2: revm_endline(); goto next; } revm_endline(); } next: sect = elfsh_get_reloc(world.curjob->curfile, index2 + 1, &size); revm_output("\n"); } revm_output("\n"); PROFILER_ROUT(__FILE__, __FUNCTION__, __LINE__, 0); }
/** * @brief Display a PHT * @param phdr * @param num * @param base */ void revm_pht_print(elfsh_Phdr *phdr, uint16_t num, eresi_Addr base) { elfsh_Shdr *shdr; int shtnum; int index; int index2; char *type; u_int typenum; elfshsect_t *list; regex_t *tmp; char buff[512]; char warnmsg[256]; char logbuf[BUFSIZ]; int check; eresi_Addr addr; eresi_Addr addr_end; PROFILER_IN(__FILE__, __FUNCTION__, __LINE__); FIRSTREGX(tmp); /* Primary view (2 modes, depending on the quiet flag) */ for (index = 0; index < num; index++) { typenum = elfsh_get_segment_type(phdr + index); type = (char *) (typenum >= ELFSH_SEGTYPE_MAX ? revm_display_pdesc(typenum) : elfsh_seg_type[typenum].desc); addr = phdr[index].p_vaddr; addr_end = phdr[index].p_vaddr + phdr[index].p_memsz; if (elfsh_is_runtime_mode()) { addr_end += base; addr += base; } /* We check if we have a correct alignment */ check = (addr - phdr[index].p_offset) & (phdr[index].p_align - 1); if (check != 0) snprintf(warnmsg, 255, "Wrong alignment (%d)", check); if (!world.state.revm_quiet) snprintf(buff, sizeof(buff), " %s %s -> %s %c%c%c %s%s%s " "%s%s%s %s%s%s %s%s%s => %s %s\n", revm_colornumber("[%02u]", index), revm_coloraddress(XFMT, addr), revm_coloraddress(XFMT, addr_end), (elfsh_segment_is_readable(&phdr[index]) ? 'r' : '-'), (elfsh_segment_is_writable(&phdr[index]) ? 'w' : '-'), (elfsh_segment_is_executable(&phdr[index]) ? 'x' : '-'), revm_colorfieldstr("memsz("), revm_colornumber(UFMT, phdr[index].p_memsz), revm_colorfieldstr(")"), revm_colorfieldstr("foffset("), revm_colornumber(UFMT, phdr[index].p_offset), revm_colorfieldstr(")"), revm_colorfieldstr("filesz("), revm_colornumber(UFMT, phdr[index].p_filesz), revm_colorfieldstr(")"), revm_colorfieldstr("align("), revm_colornumber(UFMT, phdr[index].p_align), revm_colorfieldstr(")"), revm_colortypestr(type), check != 0 ? revm_colorwarn(warnmsg) : "" ); else snprintf(buff, sizeof(buff), " %s %s -> %s %c%c%c %s%s%s " "%s%s%s %s%s%s\n", revm_colornumber("[%02u]", index), revm_coloraddress(XFMT, addr), revm_coloraddress(XFMT, addr_end), (elfsh_segment_is_readable(&phdr[index]) ? 'r' : '-'), (elfsh_segment_is_writable(&phdr[index]) ? 'w' : '-'), (elfsh_segment_is_executable(&phdr[index]) ? 'x' : '-'), revm_colorfieldstr("memsz("), revm_colornumber(UFMT, phdr[index].p_memsz), revm_colorfieldstr(")"), revm_colorfieldstr("foffset("), revm_colornumber(UFMT, phdr[index].p_offset), revm_colorfieldstr(")"), revm_colorfieldstr("filesz("), revm_colornumber(UFMT, phdr[index].p_filesz), revm_colorfieldstr(")")); if (!tmp || (tmp && !regexec(tmp, buff, 0, 0, 0))) revm_output(buff); revm_endline(); } snprintf(logbuf, BUFSIZ - 1, "\n [SHT correlation]" "\n [Object %s]\n\n", world.curjob->curfile->name); revm_output(logbuf); /* Retreive the sht */ if ((shdr = elfsh_get_sht(world.curjob->curfile, &shtnum)) == 0) PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); snprintf(logbuf, BUFSIZ - 1, " [*] SHT %s \n", (world.curjob->curfile->shtrb ? "has been rebuilt \n" : "is not stripped \n")); revm_output(logbuf); /* Alternate View */ for (index = 0; index < num; index++, index2 = 0) { typenum = elfsh_get_segment_type(phdr + index); type = (char *) (typenum >= ELFSH_SEGTYPE_MAX ? revm_display_pname(typenum) : elfsh_seg_type[typenum].name); snprintf(logbuf, BUFSIZ - 1, " %s %s \t", revm_colornumber("[%02u]", index), revm_colortypestr_fmt("%-10s", type)); revm_output(logbuf); revm_endline(); /* In SHT */ for (index2 = 0, list = world.curjob->curfile->sectlist; list; list = list->next) if (elfsh_segment_is_parent(list, phdr + index)) { index2++; snprintf(logbuf, BUFSIZ - 1, "%s%s ", (list->shdr->sh_offset + list->shdr->sh_size > phdr[index].p_offset + phdr[index].p_filesz ? "|" : ""), revm_colorstr(elfsh_get_section_name(world.curjob->curfile, list))); revm_output(logbuf); revm_endline(); } /* In RSHT */ for (index2 = 0, list = world.curjob->curfile->rsectlist; list; list = list->next) if (elfsh_segment_is_parent(list, phdr + index)) { index2++; snprintf(logbuf, BUFSIZ - 1, "%s%s ", (list->shdr->sh_addr + list->shdr->sh_size > phdr[index].p_vaddr + phdr[index].p_memsz ? "|" : ""), revm_colorstr(elfsh_get_section_name(world.curjob->curfile, list))); revm_output(logbuf); revm_endline(); } revm_output("\n"); } PROFILER_OUT(__FILE__, __FUNCTION__, __LINE__); }
/** * 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); }
/** * 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); }
/** * 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); }