/* * elf_dissector.c - ELF files dissector * * Tip: y0u will see better on an Eterm or Xterm Terminal ;)... * * If y0u want something like a rainbow jeje, compile like this =): * $gcc elf_dissector.c -o elf_dissector -DCOLOURS -Wall -O2 * * nitr0us < nitrousenador .at. gmail .dot. com > * Mexico */ #include #include #include #include #include #include #include #include #include #ifdef COLOURS #define RED "\033[31m" #define WHITE "\033[01m" #define RESET "\033[00m" #else #define RED "" #define WHITE "" #define RESET "" #endif /* MODES */ #define HEADER (1 << 0) #define SECTION (1 << 1) #define PROGRAM (1 << 2) #define SYMBOL (1 << 3) #define DYNAMIC (1 << 4) #define RELOC (1 << 5) #define ALL (HEADER + SECTION + PROGRAM + SYMBOL + DYNAMIC + RELOC) void usage(const char *); void banner(); int elf_identification(int); void elf_header(Elf32_Ehdr); void sht(char *); void pht(char *); void symbols(char *); void dynamic(char *); void relocations(char *); int numeric = 0; int shstrtab_offset = 0; int main(int argc, char **argv) { int fd, opt, mode = 0; char *elfptr; struct stat statinfo; Elf32_Ehdr header; Elf32_Shdr shstrtab_section; if(argc < 3) usage(argv[0]); while((opt = getopt(argc, argv, "naHSPsdrh")) != EOF) switch(opt){ case 'n': numeric = 1; break; case 'a': mode |= ALL; break; case 'H': mode |= HEADER; break; case 'S': mode |= SECTION; break; case 'P': mode |= PROGRAM; break; case 's': mode |= SYMBOL; break; case 'd': mode |= DYNAMIC; break; case 'r': mode |= RELOC; break; case 'h': default: usage(argv[0]); } if(argv[optind] == NULL){ fprintf(stderr, "Give me an ELF file\n"); usage(argv[0]); } if((fd = open(argv[optind], O_RDONLY)) == -1){ perror("open"); exit(-1); } if(!elf_identification(fd)){ fprintf(stderr, "This is not a supported ELF file\n"); exit(-1); } if(fstat(fd, &statinfo) == -1){ perror("stat"); close(fd); exit(-1); } if((elfptr = (char *) mmap(NULL, statinfo.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED){ perror("mmap"); close(fd); exit(-1); } close(fd); banner(); header = *(Elf32_Ehdr *) elfptr; shstrtab_section = *(Elf32_Shdr *) (elfptr + header.e_shoff + header.e_shstrndx * sizeof(Elf32_Shdr)); if(shstrtab_section.sh_size > 0) shstrtab_offset = shstrtab_section.sh_offset; if(mode & HEADER){ printf("%sELF HEADER:%s\n", RED, RESET); elf_header(header); } if(mode & SECTION){ printf("\n%sSECTION HEADER TABLE:%s\n", RED, RESET); if(header.e_shoff == 0) printf("[%sNO SECTION HEADER TABLE FOUND%s]\n", WHITE, RESET); else sht(elfptr); } if(mode & PROGRAM){ printf("\n%sPROGRAM HEADER TABLE:%s\n", RED, RESET); pht(elfptr); } if(mode & SYMBOL){ printf("\n%sSYMBOL TABLE:%s\n", RED, RESET); symbols(elfptr); } if(mode & DYNAMIC){ printf("\n%sDYNAMIC INFORMATION:%s\n", RED, RESET); dynamic(elfptr); } if(mode & RELOC){ printf("\n%sRELOCATIONS:%s\n", RED, RESET); relocations(elfptr); } munmap(elfptr, statinfo.st_size); return 0; } void usage(const char *self) { fprintf(stderr, "Usage: %s [-n] \n", self); fprintf(stderr, "\tOptions:\n"); fprintf(stderr, "\t-n\tPrint everything in numeric values\n"); fprintf(stderr, "\t-a\tAll(-HSPs)\n"); fprintf(stderr, "\t-H\tELF header\n"); fprintf(stderr, "\t-S\tSection headers\n"); fprintf(stderr, "\t-P\tProgram headers\n"); fprintf(stderr, "\t-s\tSymbol Table\n"); fprintf(stderr, "\t-d\tDynamic information\n"); fprintf(stderr, "\t-r\tRelocations\n"); fprintf(stderr, "\t-h\tThis help\n"); exit(0); } void banner() { printf("%s######################################################%s\n", RED, RESET); printf("%s##%s%s ELF Dissector %s%s##%s\n", RED, RESET, WHITE, RESET, RED, RESET); printf("%s##%s%s by nitr0us %s%s##%s\n", RED, RESET, WHITE, RESET, RED, RESET); printf("%s##%s%s nitrousenador.at.gmail.dot.com %s%s##%s\n", RED, RESET, WHITE, RESET, RED, RESET); printf("%s##%s%s %s%s##%s\n", RED, RESET, WHITE, RESET, RED, RESET); printf("%s##%s%s Mexico %s%s##%s\n", RED, RESET, WHITE, RESET, RED, RESET); printf("%s######################################################%s\n\n", RED, RESET); } int elf_identification(int fd) { Elf32_Ehdr header; if(read(fd, &header, sizeof(header)) == -1){ perror("elf_identification: read"); return 0; } /* magic number verification */ if(header.e_ident[EI_MAG0] != ELFMAG0 || header.e_ident[EI_MAG1] != ELFMAG1 || header.e_ident[EI_MAG2] != ELFMAG2 || header.e_ident[EI_MAG3] != ELFMAG3){ fprintf(stderr, "elf_identification: Invalid MAGIC Number\n"); return 0; } return 1; } void elf_header(Elf32_Ehdr hdr) { int k; printf("%se_ident:%s\t\t", WHITE, RESET); for(k = 0; k < EI_NIDENT; k++) printf("%.2x ", hdr.e_ident[k]); printf("\n%se_ident[EI_CLASS]:%s\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_ident[EI_CLASS]); else switch(hdr.e_ident[EI_CLASS]){ case ELFCLASSNONE: printf("ELFCLASSNONE"); break; case ELFCLASS32: printf("ELFCLASS32"); break; case ELFCLASS64: printf("ELFCLASS64"); break; default: printf("%sINVALID CLASS%s (0x%x)", RED, RESET, hdr.e_ident[EI_CLASS]); } printf("\n%se_ident[EI_DATA]:%s\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_ident[EI_DATA]); else switch(hdr.e_ident[EI_DATA]){ case ELFDATANONE: printf("ELFDATANONE"); break; case ELFDATA2LSB: printf("ELFDATA2LSB"); break; case ELFDATA2MSB: printf("ELFDATA2MSB"); break; default: printf("%sINVALID DATA%s (0x%x)", RED, RESET, hdr.e_ident[EI_DATA]); } printf("\n%se_ident[EI_VERSION]:%s\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_ident[EI_VERSION]); else{ if(hdr.e_ident[EI_VERSION] == EV_CURRENT) printf("EV_CURRENT"); else printf("%sINVALID VERSION%s (0x%x)", RED, RESET, hdr.e_ident[EI_VERSION]); } printf("\n%se_ident[EI_OSABI]:%s\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_ident[EI_OSABI]); else switch(hdr.e_ident[EI_OSABI]){ case ELFOSABI_SYSV: printf("ELFOSABI_SYSV"); break; case ELFOSABI_NETBSD: printf("ELFOSABI_NETBSD"); break; case ELFOSABI_OPENBSD: printf("ELFOSABI_OPENBSD"); break; case ELFOSABI_FREEBSD: printf("ELFOSABI_FREEBSD"); break; case ELFOSABI_LINUX: printf("ELFOSABI_LINUX"); break; case ELFOSABI_SOLARIS: printf("ELFOSABI_SOLARIS"); break; default: printf("%s0x%x%s", RED, hdr.e_ident[EI_OSABI], RESET); } printf("\n%se_ident[EI_ABIVERSION]:%s\t0x%x", WHITE, RESET, hdr.e_ident[EI_ABIVERSION]); printf("\n%se_type:%s\t\t\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_type); else switch(hdr.e_type){ case ET_NONE: printf("ET_NONE"); break; case ET_REL: printf("ET_REL"); break; case ET_EXEC: printf("ET_EXEC"); break; case ET_DYN: printf("ET_DYN"); break; case ET_CORE: printf("ET_CORE"); break; default: printf("%s0x%x%s", RED, hdr.e_type, RESET); } printf("\n%se_machine:%s\t\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_machine); else switch(hdr.e_machine){ case EM_NONE: printf("EM_NONE"); break; case EM_SPARC: printf("EM_SPARC"); break; case EM_386: printf("EM_386"); break; case EM_MIPS: printf("EM_MIPS"); break; case EM_PARISC: printf("EM_PARISC"); break; case EM_PPC: printf("EM_PPC"); break; case EM_SPARCV9: printf("EM_SPARCV9"); break; default: printf("%s0x%x%s", RED, hdr.e_machine, RESET); } printf("\n%se_version:%s\t\t", WHITE, RESET); if(numeric) printf("0x%x", hdr.e_version); else switch(hdr.e_version){ case EV_NONE: printf("EV_NONE"); break; case EV_CURRENT: printf("EV_CURRENT"); break; default: printf("%s0x%x%s", RED, hdr.e_version, RESET); } printf("\n%se_entry:%s\t\t0x%.8x", WHITE, RESET, hdr.e_entry); printf("\n%se_phoff:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_phoff, hdr.e_phoff); printf("\n%se_shoff:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_shoff, hdr.e_shoff); printf("\n%se_ehsize:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_ehsize, hdr.e_ehsize); printf("\n%se_phentsize:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_phentsize, hdr.e_phentsize); printf("\n%se_phnum:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_phnum, hdr.e_phnum); printf("\n%se_shentsize:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_shentsize, hdr.e_shentsize); printf("\n%se_shnum:%s\t\t0x%.8x\t(%d)", WHITE, RESET, hdr.e_shnum, hdr.e_shnum); printf("\n%se_shstrndx:%s\t\t0x%.8x\t(%d)\n", WHITE, RESET, hdr.e_shstrndx, hdr.e_shstrndx); } void sht(char *mem) { int k; Elf32_Ehdr hdr = *(Elf32_Ehdr *) mem; Elf32_Shdr *sections = (Elf32_Shdr *) (mem + hdr.e_shoff); printf("%s[NR] sh_name sh_type sh_flags sh_addr sh_offset sh_size sh_link sh_info sh_addralign sh_entsize%s\n", WHITE, RESET); for(k = 0; k < hdr.e_shnum; k++, sections++){ printf("[%2d] ", k); if(numeric) printf("0x%-15.8x ", sections->sh_name); else{ if(shstrtab_offset == 0) printf("0x%-15.8x ", sections->sh_name); else printf("%-17s ", mem + shstrtab_offset + sections->sh_name); } if(numeric) printf("0x%-11.8x ", sections->sh_type); else switch(sections->sh_type){ case SHT_NULL: printf("%-13s ", "SHT_NULL"); break; case SHT_PROGBITS: printf("%-13s ", "SHT_PROGBITS"); break; case SHT_SYMTAB: printf("%-13s ", "SHT_SYMTAB"); break; case SHT_STRTAB: printf("%-13s ", "SHT_STRTAB"); break; case SHT_RELA: printf("%-13s ", "SHT_RELA"); break; case SHT_HASH: printf("%-13s ", "SHT_HASH"); break; case SHT_DYNAMIC: printf("%-13s ", "SHT_DYNAMIC"); break; case SHT_NOTE: printf("%-13s ", "SHT_NOTE"); break; case SHT_NOBITS: printf("%-13s ", "SHT_NOBITS"); break; case SHT_REL: printf("%-13s ", "SHT_REL"); break; case SHT_SHLIB: printf("%-13s ", "SHT_SHLIB"); break; case SHT_DYNSYM: printf("%-13s ", "SHT_DYNSYM"); break; case SHT_INIT_ARRAY: printf("%-13s ", "SHT_INIT_ARRAY"); break; case SHT_FINI_ARRAY: printf("%-13s ", "SHT_ARRAY"); break; case SHT_GNU_verdef: printf("%-13s ", "SHT_VERDEF"); break; case SHT_GNU_verneed: printf("%-13s ", "SHT_VERNEED"); break; case SHT_GNU_versym: printf("%-13s ", "SHT_VERSYM"); break; default: printf("%s0x%-11.8x%s ", RED, sections->sh_type, RESET); } if(numeric) printf(" 0x%.4x ", sections->sh_flags); else printf(" %c %c %c ", (sections->sh_type & SHF_WRITE) ? 'W' : ' ', (sections->sh_type & SHF_ALLOC) ? 'A' : ' ', (sections->sh_type & SHF_EXECINSTR) ? 'X' : ' '); printf("0x%.8x ", sections->sh_addr); printf("0x%.7x ", sections->sh_offset); printf("0x%.6x ", sections->sh_size); printf(" 0x%.2x ", sections->sh_link); printf("0x%.4x ", sections->sh_info); printf(" 0x%.2x ", sections->sh_addralign); printf(" 0x%.2x\n", sections->sh_entsize); } } void pht(char *mem) { int k; Elf32_Ehdr hdr = *(Elf32_Ehdr *) mem; Elf32_Phdr *phdrs = (Elf32_Phdr *) (mem + hdr.e_phoff); printf("%s[NR] p_type p_offset p_vaddr p_paddr p_filesz p_memsz p_flags p_align%s\n", WHITE, RESET); for(k = 0; k < hdr.e_phnum; k++, phdrs++){ printf("[%2d] ", k); if(numeric) printf("0x%-14.8x ", phdrs->p_type); else switch(phdrs->p_type){ case PT_NULL: printf("%-17s", "PT_NULL"); break; case PT_LOAD: printf("%-17s", "PT_LOAD"); break; case PT_DYNAMIC: printf("%-17s", "PT_DYNAMIC"); break; case PT_INTERP: printf("%-17s", "PT_INTERP"); break; case PT_NOTE: printf("%-17s", "PT_NOTE"); break; case PT_SHLIB: printf("%-17s", "PT_SHLIB"); break; case PT_PHDR: printf("%-17s", "PT_PHDR"); break; case PT_GNU_EH_FRAME: printf("%-17s", "PT_GNU_EH_FRAME"); break; case PT_GNU_STACK: printf("%-17s", "PT_GNU_STACK"); break; default: printf("%s0x%-14.8x%s ", RED, phdrs->p_type, RESET); } printf("0x%.8x ", phdrs->p_offset); printf("0x%.8x ", phdrs->p_vaddr); printf("0x%.8x ", phdrs->p_paddr); printf("0x%.8x ", phdrs->p_filesz); printf("0x%.8x ", phdrs->p_memsz); if(numeric) printf("0x%.4x ", phdrs->p_flags); else printf(" %c %c %c ", (phdrs->p_type & PF_X) ? 'X' : ' ', (phdrs->p_type & PF_W) ? 'W' : ' ', (phdrs->p_type & PF_R) ? 'R' : ' '); printf("0x%.4x\n", phdrs->p_align); if(phdrs->p_type == PT_INTERP) printf("[Interpreter: %s%s%s]\n", WHITE, mem + phdrs->p_offset, RESET); } } void symbols(char *mem) { int k, l, flag = 0, strtab_off; Elf32_Ehdr hdr = *(Elf32_Ehdr *) mem; Elf32_Shdr *shdr = (Elf32_Shdr *) (mem + hdr.e_shoff), stringtable; Elf32_Sym *sym; for(k = 0; k < hdr.e_shnum; k++, shdr++){ if(shdr->sh_type != SHT_SYMTAB && shdr->sh_type != SHT_DYNSYM) continue; flag = 1; printf("Found symbol table [%s%s%s] with %d entries:\n", WHITE, mem + shstrtab_offset + shdr->sh_name, RESET, shdr->sh_size / shdr->sh_entsize); sym = (Elf32_Sym *) (mem + shdr->sh_offset); stringtable = *(Elf32_Shdr *) (mem + hdr.e_shoff + (shdr->sh_link * sizeof(Elf32_Shdr))); strtab_off = stringtable.sh_offset; printf("%s[ NR ] st_value st_size TYPE BINDING VISIBILITY st_shndx st_name%s\n", WHITE, RESET); for(l = 0; l < shdr->sh_size / shdr->sh_entsize; l++, sym++){ printf("[%4d] ", l); printf("0x%.8x ", sym->st_value); printf("0x%.5x ", sym->st_size); if(numeric) printf(" 0x%.2x ", sym->st_info); else switch(ELF32_ST_TYPE(sym->st_info)){ case STT_NOTYPE: printf("%-12s ", "STT_NOTYPE"); break; case STT_OBJECT: printf("%-12s ", "STT_OBJECT"); break; case STT_FUNC: printf("%-12s ", "STT_FUNC"); break; case STT_SECTION: printf("%-12s ", "STT_SECTION"); break; case STT_FILE: printf("%-12s ", "STT_FILE"); break; case STT_COMMON: printf("%-12s ", "STT_COMMON"); break; case STT_TLS: printf("%-12s ", "STT_TLS"); break; case STT_NUM: printf("%-12s ", "STT_NUM"); break; default: printf(" %s0x%.2x%s ", RED, sym->st_info, RESET); } if(numeric) printf(" 0x%.2x ", sym->st_info); else switch(ELF32_ST_BIND(sym->st_info)){ case STB_LOCAL: printf("%-11s ", "STB_LOCAL"); break; case STB_GLOBAL: printf("%-11s ", "STB_GLOBAL"); break; case STB_WEAK: printf("%-11s ", "STB_WEAK"); break; case STB_NUM: printf("%-11s ", "STB_NUM"); break; default: printf(" %s0x%.2x%s ", RED, sym->st_info, RESET); } if(numeric) printf(" 0x%.2x ", sym->st_other); else switch(ELF32_ST_VISIBILITY(sym->st_other)){ case STV_DEFAULT: printf("%-14s ", "STV_DEFAULT"); break; case STV_INTERNAL: printf("%-14s ", "STV_INTERNAL"); break; case STV_HIDDEN: printf("%-14s ", "STV_HIDDEN"); break; case STV_PROTECTED: printf("%-14s ", "STV_PROTECTED"); break; default: printf(" %s0x%.2x%s ", RED, sym->st_other, RESET); } if(numeric) printf(" 0x%.4x ", sym->st_shndx); else switch(sym->st_shndx){ case SHN_UNDEF: printf("%-11s ", "SHN_UNDEF"); break; case SHN_ABS: printf("%-11s ", "SHN_ABS"); break; case SHN_COMMON: printf("%-11s ", "SHN_COMMON"); break; default: printf(" 0x%.2x ", sym->st_other); } printf("%s\n", mem + strtab_off + sym->st_name); } putchar('\n'); } if(!flag) printf("[%sNO SYMBOL TABLE FOUND%s]\n", WHITE, RESET); } void dynamic(char *mem) { int k, l, flag = 0, strtab_offset; Elf32_Ehdr hdr = *(Elf32_Ehdr *) mem; Elf32_Shdr *shdr = (Elf32_Shdr *) (mem + hdr.e_shoff), stringtable; Elf32_Dyn *dyn; for(k = 0; k < hdr.e_shnum; k++, shdr++){ if(shdr->sh_type != SHT_DYNAMIC) continue; flag = 1; printf("Found Dynamic Section [%s%s%s] with %d entries:\n", WHITE, mem + shstrtab_offset + shdr->sh_name, RESET, shdr->sh_size / shdr->sh_entsize); dyn = (Elf32_Dyn *) (mem + shdr->sh_offset); stringtable = *(Elf32_Shdr *) (mem + hdr.e_shoff + (shdr->sh_link * sizeof(Elf32_Shdr))); strtab_offset = stringtable.sh_offset; printf("%s[ NR ] d_tag TYPE NAME/VALUE%s\n", WHITE, RESET); for(l = 0; l < shdr->sh_size / shdr->sh_entsize; l++, dyn++){ printf("[%4d] ", l); printf("0x%.8x ", dyn->d_tag); if(numeric) printf("0x%.8x ", dyn->d_tag); else switch(dyn->d_tag){ case DT_NULL: printf("%-20s ", "DT_NULL"); break; case DT_NEEDED: printf("%-20s ", "DT_NEEDED"); break; case DT_PLTRELSZ: printf("%-20s ", "DT_PLTRELSZ"); break; case DT_PLTGOT: printf("%-20s ", "DT_PLTGOT"); break; case DT_HASH: printf("%-20s ", "DT_HASH"); break; case DT_STRTAB: printf("%-20s ", "DT_STRTAB"); break; case DT_SYMTAB: printf("%-20s ", "DT_SYMTAB"); break; case DT_STRSZ: printf("%-20s ", "DT_STRSZ"); break; case DT_SYMENT: printf("%-20s ", "DT_SYMENT"); break; case DT_INIT: printf("%-20s ", "DT_INIT"); break; case DT_FINI: printf("%-20s ", "DT_FINI"); break; case DT_SONAME: printf("%-20s ", "DT_SONAME"); break; case DT_RPATH: printf("%-20s ", "DT_RPATH"); break; case DT_SYMBOLIC: printf("%-20s ", "DT_SYMBOLIC"); break; case DT_REL: printf("%-20s ", "DT_REL"); break; case DT_RELSZ: printf("%-20s ", "DT_RELSZ"); break; case DT_RELENT: printf("%-20s ", "DT_RELENT"); break; case DT_PLTREL: printf("%-20s ", "DT_PLTREL"); break; case DT_DEBUG: printf("%-20s ", "DT_DEBUG"); break; case DT_TEXTREL: printf("%-20s ", "DT_TEXTREL"); break; case DT_JMPREL: printf("%-20s ", "DT_JMPREL"); break; case DT_BIND_NOW: printf("%-20s ", "DT_BIND_NOW"); break; case DT_INIT_ARRAY: printf("%-20s ", "DT_INIT_ARRAY"); break; case DT_FINI_ARRAY: printf("%-20s ", "DT_FINI_ARRAY"); break; case DT_INIT_ARRAYSZ: printf("%-20s ", "DT_INIT_ARRAYSZ"); break; case DT_FINI_ARRAYSZ: printf("%-20s ", "DT_FINI_ARRAYSZ"); break; case DT_VERSYM: printf("%-20s ", "DT_VERSYM"); break; case DT_RELCOUNT: printf("%-20s ", "DT_RELCOUNT"); break; case DT_VERDEF: printf("%-20s ", "DT_VERDEF"); break; case DT_VERDEFNUM: printf("%-20s ", "DT_VERDEFNUM"); break; case DT_VERNEED: printf("%-20s ", "DT_VERNEED"); break; case DT_VERNEEDNUM: printf("%-20s ", "DT_VERNEEDNUM"); break; default: printf("%s0x%.8x%s ", RED, dyn->d_tag, RESET); } switch(dyn->d_tag){ case DT_NEEDED: case DT_SONAME: case DT_RPATH: printf("%s\n", mem + strtab_offset + dyn->d_un.d_val); break; case DT_PLTGOT: case DT_HASH: case DT_INIT: case DT_FINI: case DT_REL: case DT_JMPREL: case DT_VERSYM: case DT_VERNEED: printf("0x%.8x\n", dyn->d_un.d_ptr); break; case DT_PLTRELSZ: case DT_STRSZ: case DT_SYMENT: case DT_RELSZ: case DT_RELENT: printf("%d bytes\n", dyn->d_un.d_val); break; default: putchar('\n'); } if(dyn->d_tag == DT_NULL) /* End of _DYNAMIC[] */ break; } } if(!flag) printf("[%sNO DYNAMIC SECTION FOUND%s]\n", WHITE, RESET); } void relocations(char *mem) { int k, l, symndx = 0, flag = 0, symstrtab_offset; Elf32_Ehdr hdr = *(Elf32_Ehdr *) mem; Elf32_Shdr *shdr = (Elf32_Shdr *) (mem + hdr.e_shoff), *shdr_table, symtab_section, stringtable; Elf32_Rel *rel; Elf32_Sym *sym; shdr_table = shdr; for(k = 0; k < hdr.e_shnum; k++, shdr++){ if(shdr->sh_type != SHT_REL) continue; flag = 1; printf("Found Relocation Section [%s%s%s] with %d entries:\n", WHITE, mem + shstrtab_offset + shdr->sh_name, RESET, shdr->sh_size / shdr->sh_entsize); symtab_section = shdr_table[shdr->sh_link]; stringtable = *(Elf32_Shdr *) (mem + hdr.e_shoff + (symtab_section.sh_link * sizeof(Elf32_Shdr))); symstrtab_offset = stringtable.sh_offset; rel = (Elf32_Rel *) (mem + shdr->sh_offset); sym = (Elf32_Sym *) (mem + symtab_section.sh_offset); printf("%s[ NR ] r_offset r_info TYPE SYM[ndx] SYMBOL NAME%s\n", WHITE, RESET); for(l = 0; l < shdr->sh_size / shdr->sh_entsize; l++, rel++){ printf("[%4d] ", l); printf("0x%.8x ", rel->r_offset); printf("0x%.8x ", rel->r_info); if(numeric) printf("0x%.8x ", rel->r_info); else switch(ELF32_R_TYPE(rel->r_info)){ case R_386_NONE: printf("%-14s ", "R_386_NONE"); break; case R_386_32: printf("%-14s ", "R_386_32"); break; case R_386_PC32: printf("%-14s ", "R_386_PC32"); break; case R_386_GOT32: printf("%-14s ", "R_386_GOT32"); break; case R_386_PLT32: printf("%-14s ", "R_386_PLT32"); break; case R_386_COPY: printf("%-14s ", "R_386_COPY"); break; case R_386_GLOB_DAT: printf("%-14s ", "R_386_GLOB_DAT"); break; case R_386_JMP_SLOT: printf("%-14s ", "R_386_JMP_SLOT"); break; case R_386_RELATIVE: printf("%-14s ", "R_386_RELATIVE"); break; case R_386_GOTOFF: printf("%-14s ", "R_386_GOTOFF"); break; case R_386_GOTPC: printf("%-14s ", "R_386_GOTPC"); break; default: printf("%s0x%.8x%s ", RED, rel->r_info, RESET); } symndx = ELF32_R_SYM(rel->r_info); printf(" %.4d ", symndx); if(ELF32_ST_TYPE(sym[symndx].st_info) == STT_SECTION) printf("%s\n", mem + shstrtab_offset + shdr_table[sym[symndx].st_shndx].sh_name); else printf("%s\n", mem + symstrtab_offset + sym[symndx].st_name); } putchar('\n'); } if(!flag) printf("[%sNO RELOCATIONS FOUND%s]\n", WHITE, RESET); }