ELF32: stack canary

This commit is contained in:
2025-09-05 15:57:26 +02:00
parent bd007c9a69
commit ae889caae4
4 changed files with 107 additions and 24 deletions

BIN
a.out

Binary file not shown.

BIN
helpelf

Binary file not shown.

129
main.c
View File

@@ -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,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; 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[])

View File

@@ -6,7 +6,7 @@ install:
test:
make
gcc -m32 main.c
gcc -m32 -fstack-protector main.c
./helpelf a.out
clean: