Twenty Year Anniversary

Coloured ELF File Dissector

Coloured ELF File Dissector
Posted Apr 1, 2014
Authored by nitr0us

This code dissects the internal data structures in ELF files. It supports x86 and x86_64 archs and runs under Linux.

tags | tool, x86
systems | linux, unix
MD5 | 4a02b3a93a1b5bbbc55d24c00624140e

Coloured ELF File Dissector

Change Mirror Download
/*
* dissector.c - Coloured ELF files dissector
* By Alejandro Hernandez <nitr0us>
*
* Supported archs: x86 / x86_64
*
* No security in mind (No boundary checkings)
* If a malformed ELF is supplied, it'll definitely segfault
*
* $gcc dissector.c -o dissector -Wall
*
* Mexico
*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <getopt.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <elf.h>

//#ifdef COLOURS
#define RED "\033[31m"
#define WHITE "\033[01m"
#define YELLOW "\033[33m"
#define RESET "\033[00m"
//#else
//#define RED ""
//#define WHITE ""
//#define YELLOW "\033[33m"
//#define RESET ""
//#endif

/*** 32 - 64 BITS COMPAT ***/
#if defined(__i386__) // x86
#define Elf_Half Elf32_Half
#define Elf_Word Elf32_Word
#define Elf_Sword Elf32_Sword
#define Elf_Xword Elf32_Xword
#define Elf_Sxword Elf32_Sxword
#define Elf_Addr Elf32_Addr
#define Elf_Off Elf32_Off
#define Elf_Section Elf32_Section
#define Elf_Ehdr Elf32_Ehdr
#define Elf_Shdr Elf32_Shdr
#define Elf_Sym Elf32_Sym
#define Elf_Rel Elf32_Rel
#define Elf_Rela Elf32_Rela
#define Elf_Phdr Elf32_Phdr
#define Elf_Dyn Elf32_Dyn
#define Elf_Nhdr Elf32_Nhdr

#define ELF_ST_TYPE ELF32_ST_TYPE
#define ELF_ST_BIND ELF32_ST_BIND
#define ELF_ST_VISIBILITY ELF32_ST_VISIBILITY

#define ELF_R_TYPE ELF32_R_TYPE
#define ELF_R_SYM ELF32_R_SYM

#define DEC "%d"
#define HEX "%.8x"

#define SPACE ""

#elif defined(__x86_64__) // x86_64
#define Elf_Half Elf64_Half
#define Elf_Word Elf64_Word
#define Elf_Sword Elf64_Sword
#define Elf_Xword Elf64_Xword
#define Elf_Sxword Elf64_Sxword
#define Elf_Addr Elf64_Addr
#define Elf_Off Elf64_Off
#define Elf_Section Elf64_Section
#define Elf_Ehdr Elf64_Ehdr
#define Elf_Shdr Elf64_Shdr
#define Elf_Sym Elf64_Sym
#define Elf_Rel Elf64_Rel
#define Elf_Rela Elf64_Rela
#define Elf_Phdr Elf64_Phdr
#define Elf_Dyn Elf64_Dyn
#define Elf_Nhdr Elf64_Nhdr

#define ELF_ST_TYPE ELF64_ST_TYPE
#define ELF_ST_BIND ELF64_ST_BIND
#define ELF_ST_VISIBILITY ELF64_ST_VISIBILITY

#define ELF_R_TYPE ELF64_R_TYPE
#define ELF_R_SYM ELF64_R_SYM

#define DEC "%ld"
#define HEX "%.16lx"

#define SPACE " " // Used to align the view when printing 64 or 32 bit variables
#else
#error "Unsupported arch"
#endif
/*** 32 - 64 BITS COMPAT ***/


/* 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 NOTES (1 << 6)
#define ALL (HEADER + SECTION + PROGRAM + SYMBOL + DYNAMIC + RELOC + NOTES)

/* PROTOTYPES */
void usage(const char *);
void banner();
int elf_identification(int);
void elf_header(Elf_Ehdr);
void sht(char *);
void pht(char *);
void symbols(char *);
void dynamic(char *);
void relocations(char *);
void notes(char *);

int numeric = 0;
int shstrtab_offset = 0;

int main(int argc, char **argv)
{
int fd, opt, mode = 0;
char *elfptr;
struct stat statinfo;
Elf_Ehdr header;
Elf_Shdr shstrtab_section;

if(argc < 3)
usage(argv[0]);

while((opt = getopt(argc, argv, "naHSPsDRhN")) != 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 'N':
mode |= NOTES;
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);

header = *(Elf_Ehdr *) elfptr;
shstrtab_section = *(Elf_Shdr *) (elfptr + header.e_shoff + header.e_shstrndx * sizeof(Elf_Shdr));
if(shstrtab_section.sh_size > 0)
shstrtab_offset = shstrtab_section.sh_offset;

if(mode & HEADER){
printf("\n%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);
}

if(mode & NOTES){
printf("\n%sNOTES:%s\n", RED, RESET);
notes(elfptr);
}

munmap(elfptr, statinfo.st_size);
return 0;
}

void usage(const char *self)
{
banner();

fprintf(stderr, "Usage: %s [-n] <options> <elf_file>\n", self);
fprintf(stderr, "\tOptions:\n");
fprintf(stderr, "\t-n\tPrint everything in numeric values\n");
fprintf(stderr, "\t-a\tAll(-HSPsdr)\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-N\tNotes\n");
fprintf(stderr, "\t-h\tThis help\n");
exit(0);
}

void banner()
{
printf("%s######################################################%s\n", RED, RESET);
printf("%s##%s%s ELF ( x86 / x86_64 ) Dissector %s%s##%s\n", RED, RESET, YELLOW, RESET, RED, RESET);
printf("%s##%s%s by nitr0us %s%s##%s\n", RED, RESET, YELLOW, RESET, RED, RESET);
printf("%s######################################################%s\n\n", RED, RESET);
}

int elf_identification(int fd)
{
Elf_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(Elf_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%.2x", 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%.2x", 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%.2x", 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%.2x", 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%.2x", 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;
case EM_X86_64:
printf("EM_X86_649");
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"HEX, WHITE, RESET, hdr.e_entry);
printf("\n%se_phoff:%s\t\t0x"HEX"\t("DEC")", WHITE, RESET, hdr.e_phoff, hdr.e_phoff);
printf("\n%se_shoff:%s\t\t0x"HEX"\t("DEC")", WHITE, RESET, hdr.e_shoff, hdr.e_shoff);
printf("\n%se_flags:%s\t\t0x%x\t(%d)", WHITE, RESET, hdr.e_flags, hdr.e_flags);
printf("\n%se_ehsize:%s\t\t0x%x\t(%d)", WHITE, RESET, hdr.e_ehsize, hdr.e_ehsize);
printf("\n%se_phentsize:%s\t\t0x%x\t(%d)", WHITE, RESET, hdr.e_phentsize, hdr.e_phentsize);
printf("\n%se_phnum:%s\t\t0x%x\t(%d)", WHITE, RESET, hdr.e_phnum, hdr.e_phnum);
printf("\n%se_shentsize:%s\t\t0x%x\t(%d)", WHITE, RESET, hdr.e_shentsize, hdr.e_shentsize);
printf("\n%se_shnum:%s\t\t0x%x\t(%d)", WHITE, RESET, hdr.e_shnum, hdr.e_shnum);
printf("\n%se_shstrndx:%s\t\t0x%x\t(%d)\n", WHITE, RESET, hdr.e_shstrndx, hdr.e_shstrndx);
}

void sht(char *mem)
{
int k;
Elf_Ehdr hdr = *(Elf_Ehdr *) mem;
Elf_Shdr *sections = (Elf_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%-18.8x ", sections->sh_name);
else{
if(shstrtab_offset == 0)
printf("0x%-15.8x ", sections->sh_name);
else
printf("%-20s ", mem + shstrtab_offset + sections->sh_name);
}

if(numeric)
printf("0x%-12.8x ", sections->sh_type);
else
switch(sections->sh_type){
case SHT_NULL:
printf("%-14s ", "SHT_NULL");
break;
case SHT_PROGBITS:
printf("%-14s ", "SHT_PROGBITS");
break;
case SHT_SYMTAB:
printf("%-14s ", "SHT_SYMTAB");
break;
case SHT_STRTAB:
printf("%-14s ", "SHT_STRTAB");
break;
case SHT_RELA:
printf("%-14s ", "SHT_RELA");
break;
case SHT_HASH:
printf("%-14s ", "SHT_HASH");
break;
case SHT_DYNAMIC:
printf("%-14s ", "SHT_DYNAMIC");
break;
case SHT_NOTE:
printf("%-14s ", "SHT_NOTE");
break;
case SHT_GNU_HASH:
printf("%-14s ", "SHT_GNU_HASH");
break;
case SHT_NOBITS:
printf("%-14s ", "SHT_NOBITS");
break;
case SHT_REL:
printf("%-14s ", "SHT_REL");
break;
case SHT_SHLIB:
printf("%-14s ", "SHT_SHLIB");
break;
case SHT_DYNSYM:
printf("%-14s ", "SHT_DYNSYM");
break;
case SHT_INIT_ARRAY:
printf("%-14s ", "SHT_INIT_ARRAY");
break;
case SHT_FINI_ARRAY:
printf("%-14s ", "SHT_FINI_ARRAY");
break;
case SHT_GNU_verdef:
printf("%-14s ", "SHT_VERDEF");
break;
case SHT_GNU_verneed:
printf("%-14s ", "SHT_VERNEED");
break;
case SHT_GNU_versym:
printf("%-14s ", "SHT_VERSYM");
break;
default:
printf("%s0x%-12.8x%s ", RED, sections->sh_type, RESET);
}

if(numeric)
printf(" 0x%.8x ", (unsigned int) sections->sh_flags);
else
printf(" %c %c %c ", /* Needs to be improved. Seen more flags than only those three */
(sections->sh_type & SHF_WRITE) ? 'W' : ' ',
(sections->sh_type & SHF_ALLOC) ? 'A' : ' ',
(sections->sh_type & SHF_EXECINSTR) ? 'X' : ' ');

printf("0x%.8x ", (unsigned int) sections->sh_addr);
printf("0x%.7x ", (unsigned int) sections->sh_offset);
printf("0x%.6x ", (unsigned int) sections->sh_size);
printf("0x%.2x ", sections->sh_link);
printf("0x%.4x ", sections->sh_info);
printf("0x%.8x ", (unsigned int) sections->sh_addralign);
printf("0x%.4x\n", (unsigned int) sections->sh_entsize);
}
}

void pht(char *mem)
{
int k;
Elf_Ehdr hdr = *(Elf_Ehdr *) mem;
Elf_Phdr *phdrs = (Elf_Phdr *) (mem + hdr.e_phoff);

printf("%s[NR] p_type p_offset p_vaddr"SPACE" p_paddr"SPACE" 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_TLS:
printf("%-17s", "PT_TLS");
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;
case PT_GNU_RELRO:
printf("%-17s", "PT_GNU_RELRO");
break;
default:
printf("%s0x%-14.8x%s ", RED, phdrs->p_type, RESET);
}

printf("0x%.8x ", (unsigned int) phdrs->p_offset);
printf("0x"HEX" ", phdrs->p_vaddr);
printf("0x"HEX" ", phdrs->p_paddr);
printf("0x%.8x ", (unsigned int) phdrs->p_filesz);
printf("0x%.8x ", (unsigned int) 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%.8x\n", (unsigned int) 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;
Elf_Ehdr hdr = *(Elf_Ehdr *) mem;
Elf_Shdr *shdr = (Elf_Shdr *) (mem + hdr.e_shoff), *shdr_table, stringtable;
Elf_Sym *sym;

shdr_table = shdr;

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 %s"DEC"%s entries:\n", YELLOW, mem + shstrtab_offset + shdr->sh_name, RESET, YELLOW, shdr->sh_size / shdr->sh_entsize, RESET);

sym = (Elf_Sym *) (mem + shdr->sh_offset);
stringtable = *(Elf_Shdr *) (mem + hdr.e_shoff + (shdr->sh_link * sizeof(Elf_Shdr)));
strtab_off = stringtable.sh_offset;

printf("%s[ NR ] st_value"SPACE" 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"HEX" ", sym->st_value);
printf("0x%.5x ", (unsigned int) sym->st_size);

if(numeric)
printf(" 0x%.2x ", sym->st_info);
else
switch(ELF_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(ELF_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(ELF_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_shndx);
}

if(numeric)
printf("0x%.4x\n", sym->st_name);
else{
if(ELF_ST_TYPE(sym->st_info) == STT_SECTION)
printf("%s\n", mem + shstrtab_offset + shdr_table[sym->st_shndx].sh_name);
else
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;
Elf_Ehdr hdr = *(Elf_Ehdr *) mem;
Elf_Shdr *shdr = (Elf_Shdr *) (mem + hdr.e_shoff), stringtable;
Elf_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 %s"DEC"%s entries:\n", YELLOW, mem + shstrtab_offset + shdr->sh_name, RESET, YELLOW, shdr->sh_size / shdr->sh_entsize, RESET);

dyn = (Elf_Dyn *) (mem + shdr->sh_offset);
stringtable = *(Elf_Shdr *) (mem + hdr.e_shoff + (shdr->sh_link * sizeof(Elf_Shdr)));
strtab_offset = stringtable.sh_offset;

printf("%s[ NR ] d_tag"SPACE" TYPE NAME/VALUE%s\n", WHITE, RESET);

for(l = 0; l < shdr->sh_size / shdr->sh_entsize; l++, dyn++){
printf("[%4d] ", l);

printf("0x"HEX" ", dyn->d_tag);

if(numeric)
printf("0x%.8x ", (unsigned int) 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_GNU_HASH:
printf("%-20s ", "DT_GNU_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, (unsigned int) 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_STRTAB:
case DT_SYMTAB:
case DT_INIT:
case DT_FINI:
case DT_INIT_ARRAY:
case DT_FINI_ARRAY:
case DT_REL:
case DT_JMPREL:
case DT_VERSYM:
case DT_VERNEED:
case DT_GNU_HASH:
printf("0x"HEX"\n", dyn->d_un.d_ptr);
break;
case DT_PLTRELSZ:
case DT_STRSZ:
case DT_SYMENT:
case DT_RELSZ:
case DT_RELENT:
case DT_INIT_ARRAYSZ:
case DT_FINI_ARRAYSZ:
printf(HEX" bytes\n", dyn->d_un.d_val);
break;
case DT_PLTREL:
printf("%s\n", (dyn->d_un.d_val == DT_REL) ? "DT_REL" : "DT_RELA");
break;
case DT_VERNEEDNUM:
case DT_DEBUG:
printf("0x"HEX"\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;
Elf_Ehdr hdr = *(Elf_Ehdr *) mem;
Elf_Shdr *shdr = (Elf_Shdr *) (mem + hdr.e_shoff), *shdr_table, symtab_section, stringtable;
Elf_Sym *sym;
Elf_Rel *rel;
Elf_Rela *rela;

shdr_table = shdr;

for(k = 0; k < hdr.e_shnum; k++, shdr++){
if(shdr->sh_type != SHT_REL && shdr->sh_type != SHT_RELA)
continue;

flag = 1;

printf("Found Relocation Section [%s%s%s] with %s"DEC" %s%s entries:\n", YELLOW, mem + shstrtab_offset + shdr->sh_name, RESET, YELLOW, shdr->sh_size / shdr->sh_entsize, shdr->sh_type == SHT_REL ? "SHT_REL" : "SHT_RELA", RESET);

if(shdr->sh_type == SHT_REL)
rel = (Elf_Rel *) (mem + shdr->sh_offset);
else
rela = (Elf_Rela *) (mem + shdr->sh_offset);

symtab_section = shdr_table[shdr->sh_link];
stringtable = *(Elf_Shdr *) (mem + hdr.e_shoff + (symtab_section.sh_link * sizeof(Elf_Shdr)));
symstrtab_offset = stringtable.sh_offset;
sym = (Elf_Sym *) (mem + symtab_section.sh_offset);

printf("%s[ NR ] r_offset"SPACE" r_info TYPE SYM[ndx] SYMBOL NAME + r_addend%s\n", WHITE, RESET);

for(l = 0; l < shdr->sh_size / shdr->sh_entsize; l++){
printf("[%4d] ", l);

printf("0x"HEX" ", shdr->sh_type == SHT_REL ? rel->r_offset : rela->r_offset);
printf("0x%.8x ", shdr->sh_type == SHT_REL ? (unsigned int) rel->r_info : (unsigned int) rela->r_info);

if(numeric)
printf("0x%.8x ", shdr->sh_type == SHT_REL ? (unsigned int) rel->r_info : (unsigned int) rela->r_info);
else
switch(ELF_R_TYPE(shdr->sh_type == SHT_REL ? rel->r_info : rela->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, shdr->sh_type == SHT_REL ? (unsigned int) rel->r_info : (unsigned int) rela->r_info, RESET);
}

symndx = ELF_R_SYM(shdr->sh_type == SHT_REL ? rel->r_info : rela->r_info);
printf(" %.4d ", symndx);

if(ELF_ST_TYPE(sym[symndx].st_info) == STT_SECTION)
printf("%s", mem + shstrtab_offset + shdr_table[sym[symndx].st_shndx].sh_name);
else
printf("%s", mem + symstrtab_offset + sym[symndx].st_name);

if(shdr->sh_type == SHT_REL){
putchar('\n');
rel++;
} else {
printf(" + 0x%x\n", (unsigned int) rela->r_addend);
rela++;
}
}

putchar('\n');
}

if(!flag)
printf("[%sNO RELOCATIONS FOUND%s]\n", WHITE, RESET);
}

/*
* It doesn't loop through the notes.
* It just parses the 1st entry found in every SHT_NOTE section found.
*/
void notes(char *mem)
{
int k, l, flag = 0, *abi;
Elf_Ehdr hdr = *(Elf_Ehdr *) mem;
Elf_Shdr *shdr = (Elf_Shdr *) (mem + hdr.e_shoff);
Elf_Nhdr *note;
char *note_name;

for(k = 0; k < hdr.e_shnum; k++, shdr++){
if(shdr->sh_type != SHT_NOTE)
continue;

flag = 1;

printf("Found Note Section [%s%s%s] with %s"DEC"%s bytes:\n", YELLOW, mem + shstrtab_offset + shdr->sh_name, RESET, YELLOW, shdr->sh_size, RESET);

note = (Elf_Nhdr *) (mem + shdr->sh_offset);

printf("%s[ NR ] n_namesz n_descsz n_type%s\n", WHITE, RESET);

printf("[%4d] ", 0);

printf("0x%.8x ", note->n_namesz);
printf("0x%.8x ", note->n_descsz);

if(numeric)
printf("0x%.8x\n", note->n_type);

switch(note->n_type){
case NT_GNU_ABI_TAG:
note_name = (char *) (void *) note + sizeof(*note);
printf("%s", numeric ? "" : strcmp(note_name, ELF_NOTE_GNU) == 0 ? "NT_GNU_ABI_TAG\n" : "NT_VERSION\n");

printf("\tName:\t%s\n", note_name);

if(strcmp(note_name, ELF_NOTE_GNU))
break;

abi = (int *) ((void *) note + sizeof(*note) + note->n_namesz);

putchar('\t');

if(numeric){
printf("OS:\t0x%.8x\n", *(abi++));
printf("\tABI:\tMajor: 0x%.8x ", *(abi++));
printf("Minor: 0x%.8x ", *(abi++));
printf("Subminor: 0x%.8x\n", *(abi));
} else {
switch(*abi){
case ELF_NOTE_OS_LINUX:
printf("OS:\tELF_NOTE_OS_LINUX\n");
break;
case ELF_NOTE_OS_GNU:
printf("OS:\tELF_NOTE_OS_GNU\n");
break;
case ELF_NOTE_OS_SOLARIS2:
printf("OS:\tELF_NOTE_OS_SOLARIS2\n");
break;
case ELF_NOTE_OS_FREEBSD:
printf("OS:\tELF_NOTE_OS_FREEBSD\n");
break;
default:
printf("OS:\t%s0x%.8x%s\n", RED, *abi, RESET);
}

printf("\tABI:\t%d.", *(++abi));
printf("%d.", *(++abi));
printf("%d\n",*(++abi));
}
break;
case NT_GNU_HWCAP:
printf("%s", numeric ? "" : "NT_GNU_HWCAP\n");
break;
case NT_GNU_BUILD_ID:
printf("%s", numeric ? "" : "NT_GNU_BUILD_ID\n");
printf("\tName:\t%s\n", (char *) ((void *) note + sizeof(*note)));

printf("\tBuildID: ");

char *desc = (char *) (void *) note + sizeof(*note) + note->n_namesz;

for(l = 0; l < note->n_descsz; l++)
printf("%.2x", (*(desc++) & 0xff));

putchar('\n');

break;
case NT_GNU_GOLD_VERSION:
printf("%s", numeric ? "" : "NT_GNU_GOLD_VERSION\n");
break;
default:
printf("%s0x%.8x%s\n", RED, note->n_type, RESET);
}

putchar('\n');
}

if(!flag)
printf("[%sNO NOTES FOUND%s]\n", WHITE, RESET);
}

Comments

RSS Feed Subscribe to this comment feed

No comments yet, be the first!

Login or Register to post a comment

File Archive:

November 2018

  • Su
  • Mo
  • Tu
  • We
  • Th
  • Fr
  • Sa
  • 1
    Nov 1st
    10 Files
  • 2
    Nov 2nd
    15 Files
  • 3
    Nov 3rd
    2 Files
  • 4
    Nov 4th
    2 Files
  • 5
    Nov 5th
    32 Files
  • 6
    Nov 6th
    27 Files
  • 7
    Nov 7th
    8 Files
  • 8
    Nov 8th
    9 Files
  • 9
    Nov 9th
    17 Files
  • 10
    Nov 10th
    2 Files
  • 11
    Nov 11th
    2 Files
  • 12
    Nov 12th
    33 Files
  • 13
    Nov 13th
    29 Files
  • 14
    Nov 14th
    23 Files
  • 15
    Nov 15th
    45 Files
  • 16
    Nov 16th
    11 Files
  • 17
    Nov 17th
    0 Files
  • 18
    Nov 18th
    0 Files
  • 19
    Nov 19th
    0 Files
  • 20
    Nov 20th
    0 Files
  • 21
    Nov 21st
    0 Files
  • 22
    Nov 22nd
    0 Files
  • 23
    Nov 23rd
    0 Files
  • 24
    Nov 24th
    0 Files
  • 25
    Nov 25th
    0 Files
  • 26
    Nov 26th
    0 Files
  • 27
    Nov 27th
    0 Files
  • 28
    Nov 28th
    0 Files
  • 29
    Nov 29th
    0 Files
  • 30
    Nov 30th
    0 Files

Top Authors In Last 30 Days

File Tags

Systems

packet storm

© 2018 Packet Storm. All rights reserved.

Services
Security Services
Hosting By
Rokasec
close