Skip to content

ELF

Executable and Linkable Format (ELF)

Types of Files:
- Executable Files
- Shared library files
- Object files

Linux Kernel Image

Convert vmlinux/vmlinuz/bzImage/zImage kernel image to ELF
Multi Part Series on ELF files

ELF Header

Read Header Information:

>>> readelf -W -h `which cat`
ELF Header:
  Magic:   7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00
  Class:                             ELF64
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           Advanced Micro Devices X86-64
  Version:                           0x1
  Entry point address:               0x2c00
  Start of program headers:          64 (bytes into file)
  Start of section headers:          37384 (bytes into file)
  Flags:                             0x0
  Size of this header:               64 (bytes)
  Size of program headers:           56 (bytes)
  Number of program headers:         11
  Size of section headers:           64 (bytes)
  Number of section headers:         27
  Section header string table index: 26

ELF Header:
1. Magic Number
- 7F 45 4C 46
2. Class
- 00: Invalid
- 01: 32bit Object
- 02: 64bit Object
3. Data Encoding
- 00: Invalid
- 01: Least Significant Byte First (LSB)
- 02: Most Significant Byte First (MSB)
3. Version
- 01: Version of ELF 1.0
4. OS ABI
- 00: None/System V (Most common)
- 01: HP-UX
- 02: NetBSD
- 03: Linux
5. ABI Version
- 00: Not used
6. Padding
- 00 00 00 00 00 00 00
7. Type
- 00 00: No File Type
- 00 01: Relocatable file type (Object Files .o files)
- 00 02: Executable file (Non ASLR executables)
- 00 03: Shared object file (Shared Libraries and ASLR Executables)
- 00 04: Core file (Core Dumps)
8. Machine Type
- 00 03: x86
- 00 08: MIPS
- 00 28: ARM
- 00 3E: amd64
- 00 B7: ARMv8
- 00 F3: RISC-V
9. ELF Version
- 00 00 00 01: Always set to ELF version 1.0
10. Entry point
- Entry point of the application
11. Program headers offset
- The start of the Program Headers at offset from binging of the file
12. Section headers offset
- The start of the Section Headers at offset from binging of the file
13. Flags
- OS and Archetecture Dependent
14. ELF Header Size
- Size of the Header Size (Kind of useless)
15. Size of each Program Header
- All program segments are the same size
16. The Number of Program Headers
17. Size of each Section Header
- All sections are the same size
18. The Number of Section Headers
19. Section table index
- Used to resolve the names of the sections in the file

Segments

Also known as program headers
relevant at Runtime

Segment Header:
1. Type of Segment
- 00 00: Null (Can be used to disable a segment)
- 00 01: Loaded into memory
- 00 02: Dynamic linked libraries
- 00 03: Interpreted (only ASLR has this segment)
- 00 04: Note (Hold debugger information)
- 00 05: HLIB (Not used)
- 00 06: Physical Address (Location where this will be loaded into memory)
- 00 07: Thread Local Storage (Thread Local Varbales)
2. Offset
- Where in the elf file this segment starts
3. Virtual Address
- Where in Virtual memory this will be located
4. Physical Address
- Where in Physical memory this will be located. Only when this is the only option
5. File Size
- How big the segment is
6. Size of the segment in memory
- If it is larger than the file size the rest is set to 00 values
7. Flags
- Permissions of the segments RWX
8. Align
- Align bytes to either 4 bytes or 8 bytes

List Segments in a File:

>>> readelf -W -l `which cat`

Elf file type is DYN (Shared object file)
Entry point 0x2c00
There are 11 program headers, starting at offset 64

Program Headers:
  Type           Offset   VirtAddr           PhysAddr           FileSiz  MemSiz   Flg Align
  PHDR           0x000040 0x0000000000000040 0x0000000000000040 0x000268 0x000268 R   0x8
  INTERP         0x0002a8 0x00000000000002a8 0x00000000000002a8 0x00001c 0x00001c R   0x1
      [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2]
  LOAD           0x000000 0x0000000000000000 0x0000000000000000 0x001520 0x001520 R   0x1000
  LOAD           0x002000 0x0000000000002000 0x0000000000002000 0x003f91 0x003f91 R E 0x1000
  LOAD           0x006000 0x0000000000006000 0x0000000000006000 0x0021b0 0x0021b0 R   0x1000
  LOAD           0x008a90 0x0000000000009a90 0x0000000000009a90 0x000630 0x0007c8 RW  0x1000
  DYNAMIC        0x008c38 0x0000000000009c38 0x0000000000009c38 0x0001f0 0x0001f0 RW  0x8
  NOTE           0x0002c4 0x00000000000002c4 0x00000000000002c4 0x000044 0x000044 R   0x4
  GNU_EH_FRAME   0x007210 0x0000000000007210 0x0000000000007210 0x0002b4 0x0002b4 R   0x4
  GNU_STACK      0x000000 0x0000000000000000 0x0000000000000000 0x000000 0x000000 RW  0x10
  GNU_RELRO      0x008a90 0x0000000000009a90 0x0000000000009a90 0x000570 0x000570 R   0x1

 Section to Segment mapping:
  Segment Sections...
   00
   01     .interp
   02     .interp .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt
   03     .init .plt .text .fini
   04     .rodata .eh_frame_hdr .eh_frame
   05     .init_array .fini_array .data.rel.ro .dynamic .got .data .bss
   06     .dynamic
   07     .note.gnu.build-id .note.ABI-tag
   08     .eh_frame_hdr
   09
   10     .init_array .fini_array .data.rel.ro .dynamic .got

Sections

Relevant at Linktime

Common Sections:
- .text: code.
- .data: initialized data.
- .rodata: initialized read-only data.
- .bss: uninitialized data.
- .plt: PLT (Procedure Linkage Table) (IAT equivalent).
- .got: GOT entries dedicated to dynamically linked global variables.
- .got.plt: GOT entries dedicated to dynamically linked functions.
- .symtab: global symbol table.
- .dynamic: Holds all needed information for dynamic linking.
- .dynsym: symbol tables dedicated to dynamically linked symbols.
- .strtab: string table of .symtab section.
- .dynstr: string table of .dynsym section.
- .interp: RTLD embedded string.
- .rel.dyn: global variable relocation table.
- .rel.plt: function relocation table.
- shstrtab: Table for the names of each of the sections

Section Header:
1. Section Name
- Offset into the string table
2. Type
- 00 00: Null (Ignored)
- 00 01: Process Bits
- 00 02: Symbol table (List of symbol table structures)
- 00 03: String Table (List of null terminated strings)
- 00 04: Relocation
- 00 05: Hash table
- 00 06: Dynamic linking
- 00 07: Note (Debugging info)
- 00 08: No Bits (uninitialized variables)
- 00 09: Relocation
- 00 0A: SH Library
- 00 0B: Dynmaic Symbols (List of symbol table structures)
3. Flags
- 01: Writable
- 02: Allocate
- 04: Executable Instructions
4. Where Address will appear in memory
5. Offset of location in the elf file
6. How large the Size is in the elf file
7. Linked to another section
8. Info
9. Address Align
10. Entry Size
- size for data in an array in the section

List Sections in a File:

>>> readelf -l -S `which cat`
There are 27 section headers, starting at offset 0x9208:

Section Headers:
  [Nr] Name               Type            Address          Off    Size   ES Flg Lk Inf Al
  [ 0]                    NULL            0000000000000000 000000 000000 00      0   0  0
  [ 1] .interp            PROGBITS        00000000000002a8 0002a8 00001c 00   A  0   0  1
  [ 2] .note.gnu.build-id NOTE            00000000000002c4 0002c4 000024 00   A  0   0  4
  [ 3] .note.ABI-tag      NOTE            00000000000002e8 0002e8 000020 00   A  0   0  4
  [ 4] .gnu.hash          GNU_HASH        0000000000000308 000308 000060 00   A  5   0  8
  [ 5] .dynsym            DYNSYM          0000000000000368 000368 0005e8 18   A  6   1  8
  [ 6] .dynstr            STRTAB          0000000000000950 000950 0002c9 00   A  0   0  1
  [ 7] .gnu.version       VERSYM          0000000000000c1a 000c1a 00007e 02   A  5   0  2
  [ 8] .gnu.version_r     VERNEED         0000000000000c98 000c98 000060 00   A  6   1  8
  [ 9] .rela.dyn          RELA            0000000000000cf8 000cf8 000810 18   A  5   0  8
  [10] .rela.plt          RELA            0000000000001508 001508 000018 18  AI  5  22  8
  [11] .init              PROGBITS        0000000000002000 002000 00001b 00  AX  0   0  4
  [12] .plt               PROGBITS        0000000000002020 002020 000020 10  AX  0   0 16
  [13] .text              PROGBITS        0000000000002040 002040 003f42 00  AX  0   0 16
  [14] .fini              PROGBITS        0000000000005f84 005f84 00000d 00  AX  0   0  4
  [15] .rodata            PROGBITS        0000000000006000 006000 00120e 00   A  0   0 32
  [16] .eh_frame_hdr      PROGBITS        0000000000007210 007210 0002b4 00   A  0   0  4
  [17] .eh_frame          PROGBITS        00000000000074c8 0074c8 000ce8 00   A  0   0  8
  [18] .init_array        INIT_ARRAY      0000000000009a90 008a90 000008 08  WA  0   0  8
  [19] .fini_array        FINI_ARRAY      0000000000009a98 008a98 000008 08  WA  0   0  8
  [20] .data.rel.ro       PROGBITS        0000000000009aa0 008aa0 000198 00  WA  0   0 32
  [21] .dynamic           DYNAMIC         0000000000009c38 008c38 0001f0 10  WA  6   0  8
  [22] .got               PROGBITS        0000000000009e28 008e28 0001d0 08  WA  0   0  8
  [23] .data              PROGBITS        000000000000a000 009000 0000c0 00  WA  0   0 32
  [24] .bss               NOBITS          000000000000a0c0 0090c0 000198 00  WA  0   0 32
  [25] .comment           PROGBITS        0000000000000000 0090c0 00004c 01  MS  0   0  1
  [26] .shstrtab          STRTAB          0000000000000000 00910c 0000f7 00      0   0  1
Key to Flags:
  W (write), A (alloc), X (execute), M (merge), S (strings), I (info),
  L (link order), O (extra OS processing required), G (group), T (TLS),
  C (compressed), x (unknown), o (OS specific), E (exclude),
  l (large), p (processor specific)