Master the fundamental concepts of binary formats through this focused micro-challenge.
After the ELF header comes the section header table, which describes all sections in the file. Sections are the building blocks for linking: .text holds code, .data holds initialized globals, .bss reserves space for zero-initialized data.
Each Elf64_Shdr entry contains:
sh_name: Offset into .shstrtab for the section namesh_type: Section type (PROGBITS, SYMTAB, STRTAB, NOBITS, etc.)sh_flags: Writable, allocatable, executablesh_offset: File offset to section datash_size: Size in bytesCommon flags you will encounter:
SHF_WRITE (0x1): Writable at runtimeSHF_ALLOC (0x2): Loaded into memorySHF_EXECINSTR (0x4): Contains executable instructionsFor example, .text typically has SHF_ALLOC | SHF_EXECINSTR, while .data has SHF_WRITE | SHF_ALLOC.
You will walk the section header table and list every section with its name, type, flags, offset, and size. This is exactly what readelf -S prints, and reverse engineers scan section flags first when triaging an unfamiliar binary.
The section count lives in e_shnum, and each entry is e_shentsize bytes wide. You iterate from e_shoff to e_shoff + e_shnum * e_shentsize, resolving each name through .shstrtab. Linkers merge sections with compatible flags during linking, and loaders map only sections with SHF_ALLOC set into the process address space at runtime.
Implement an ELF section header lister in C.
Requirements:
Test:
Three hints are available for this task, revealed one at a time inside the code workspace so you can struggle productively before seeing them.
All starter code and reference implementations are available for your local setup.
View on Github