ELF32: stack canary
This commit is contained in:
87
main.c
87
main.c
@@ -33,11 +33,17 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
|
||||
// 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,6 +186,8 @@ void display_elf32(struct Elf32_Ehdr* header)
|
||||
printf("32-bit ELF ");
|
||||
display_elf_common(header->e_ident);
|
||||
|
||||
if (verbose)
|
||||
{
|
||||
switch (header->e_type)
|
||||
{
|
||||
case 0x00:
|
||||
@@ -178,6 +211,10 @@ void display_elf32(struct Elf32_Ehdr* header)
|
||||
break;
|
||||
}
|
||||
printf(" ");
|
||||
} else if (header->e_type == 0x03)
|
||||
{
|
||||
pie = true;
|
||||
}
|
||||
|
||||
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; i<header->e_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; i<header->e_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<nsyms; j++)
|
||||
{
|
||||
const char* name = strtab + syms[j].st_name;
|
||||
if (strcmp(name, "__stack_chk_fail") == 0)
|
||||
{
|
||||
canary = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void display_elf64(struct Elf64_Ehdr* header)
|
||||
@@ -274,6 +356,7 @@ void display_sec_common()
|
||||
{
|
||||
printf(" %s, ", nx ? "\x1b[32mNX enabled\x1b[0m" : "\x1b[31mNX disabled\x1b[0m");
|
||||
printf("%s, ", pie ? "\x1b[32mPIE enabled\x1b[0m" : "\x1b[31mPIE disabled\x1b[0m");
|
||||
printf("%s\n", canary ? "\x1b[32mStack canary enabled\x1b[0m" : "\x1b[31mStack canary disabled\x1b[0m");
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
|
||||
Reference in New Issue
Block a user