diff --git a/a.out b/a.out index 5e9a6d4..33fe0fc 100755 Binary files a/a.out and b/a.out differ diff --git a/helpelf b/helpelf index 6a1f727..62041bf 100755 Binary files a/helpelf and b/helpelf differ diff --git a/main.c b/main.c index aacd17f..430fe32 100644 --- a/main.c +++ b/main.c @@ -33,11 +33,17 @@ #include #include +// Data structures as per ELF specification: +// https://refspecs.linuxfoundation.org/elf/elf.pdf +// Only what we need (no elf.h) + #define MAX_FILENAME 256 #define EI_NIDENT 16 #define MAX_HEADER_LEN 2048 #define PF_X 1 #define PT_GNU_STACK 0x6474e551 +#define SHT_DYNSYM 11 +#define SHT_SYMTAB 2 #define Elf32_Half uint16_t #define Elf32_Word uint32_t @@ -52,6 +58,7 @@ bool verbose = false; bool pie = false; bool nx = false; +bool canary = false; struct Elf32_Ehdr { @@ -83,6 +90,30 @@ struct Elf32_Phdr Elf32_Word p_align; }; +struct Elf32_Shdr +{ + Elf32_Word sh_name; + Elf32_Word sh_type; + Elf32_Word sh_flags; + Elf32_Addr sh_addr; + Elf32_Off sh_offset; + Elf32_Word sh_size; + Elf32_Word sh_link; + Elf32_Word sh_info; + Elf32_Word sh_addralign; + Elf32_Word sh_entsize; +}; + +struct Elf32_Sym +{ + Elf32_Word st_name; + Elf32_Addr st_value; + Elf32_Word st_size; + unsigned char st_info; + unsigned char st_other; + Elf32_Half st_shndx; +}; + struct Elf64_Ehdr { unsigned char e_ident[EI_NIDENT]; @@ -155,29 +186,35 @@ void display_elf32(struct Elf32_Ehdr* header) printf("32-bit ELF "); display_elf_common(header->e_ident); - switch (header->e_type) + if (verbose) { - case 0x00: - printf("(no file type),"); - break; - case 0x01: - printf("(relocatable file),"); - break; - case 0x02: - printf("(executable file),"); - break; - case 0x03: // (ET_DYN, prob means PIE) - printf("(shared object file),"); - pie = true; - break; - case 0x04: - printf("(core file),"); - break; - default: - printf("(unknown),"); - break; + switch (header->e_type) + { + case 0x00: + printf("(no file type),"); + break; + case 0x01: + printf("(relocatable file),"); + break; + case 0x02: + printf("(executable file),"); + break; + case 0x03: // (ET_DYN, prob means PIE) + printf("(shared object file),"); + pie = true; + break; + case 0x04: + printf("(core file),"); + break; + default: + printf("(unknown),"); + break; + } + printf(" "); + } else if (header->e_type == 0x03) + { + pie = true; } - printf(" "); switch (header->e_machine) { @@ -231,13 +268,13 @@ void display_elf32(struct Elf32_Ehdr* header) void check_sec32(struct Elf32_Ehdr* header, FILE* fp) { - fseek(fp, header->e_phoff, SEEK_SET); /* * Browse thru program header table (e_phnum items) from e_phoff (program header offset) * if its stack and has executable bit then we know NX isnt there */ - for (size_t i=0; i < header->e_phnum; i++) + fseek(fp, header->e_phoff, SEEK_SET); + for (size_t i=0; ie_phnum; i++) { struct Elf32_Phdr p_header; fread (&p_header, 1, sizeof(struct Elf32_Phdr), fp); @@ -253,6 +290,51 @@ void check_sec32(struct Elf32_Ehdr* header, FILE* fp) } } } + + /* + * Same for section header table (e_shnum items) from e_shoff (section header offset) + * find sections .dynsym or .symtab: + * and look for __stack_chk_fail (call for stack smashing) + */ + fseek(fp, header->e_shoff, SEEK_SET); + + // Read section headers + struct Elf32_Shdr *s_headers = malloc(header->e_shnum * sizeof(struct Elf32_Shdr)); + fread(s_headers, sizeof(struct Elf32_Shdr), header->e_shnum, fp); + + // Find section name string table (at e_shstrndx) and read it + struct Elf32_Shdr s_header_str = s_headers[header->e_shstrndx]; + char* s_header_strtab = malloc(s_header_str.sh_size); + fseek(fp, s_header_str.sh_offset, SEEK_SET); + fread(s_header_strtab, 1, s_header_str.sh_size, fp); + + for (size_t i=0; ie_shnum; i++) + { + if (s_headers[i].sh_type == SHT_DYNSYM || s_headers[i].sh_type == SHT_SYMTAB) + { + // load symbol table + unsigned int nsyms = s_headers[i].sh_size / s_headers[i].sh_entsize; + struct Elf32_Sym *syms = malloc(s_headers[i].sh_size); + fseek(fp, s_headers[i].sh_offset, SEEK_SET); + fread(syms, s_headers[i].sh_size, 1, fp); + + // load string table + struct Elf32_Shdr str_header = s_headers[s_headers[i].sh_link]; + char* strtab = malloc(str_header.sh_size); + fseek(fp, str_header.sh_offset, SEEK_SET); + fread(strtab, 1, str_header.sh_size, fp); + + // iterate through symbols, check for __stack_chk_fail + for (size_t j=0; j