|
| 1 | ++++ |
| 2 | +title = "Understanding ELFs, part 2" |
| 3 | +date = 2025-01-29 |
| 4 | +authors = ["InnocentZero"] |
| 5 | ++++ |
| 6 | + |
| 7 | +## Segments |
| 8 | + |
| 9 | +Sections gather all the information needed to link a given executable. Segments, on the other |
| 10 | +hand, contain information needed to load the program into memory. Segments can be imagined as |
| 11 | +a tool to make linux loader's life easier, as they group sections by attributes into single |
| 12 | +segments in order to make the loading process more efficient. Otherwise the loader would load |
| 13 | +each individual section into memory independently. |
| 14 | + |
| 15 | +Similar to sections, Segments, also called _Program Headers_, also have a **Program Header Table** |
| 16 | +that lists all the segments. This table is read by the loader and helps map the ELF into memory. |
| 17 | +These can be seen via `readelf -l executable`. |
| 18 | + |
| 19 | +``` |
| 20 | +Elf file type is DYN (Position-Independent Executable file) |
| 21 | +Entry point 0x1040 |
| 22 | +There are 13 program headers, starting at offset 64 |
| 23 | +
|
| 24 | +Program Headers: |
| 25 | + Type Offset VirtAddr PhysAddr |
| 26 | + FileSiz MemSiz Flags Align |
| 27 | + PHDR 0x0000000000000040 0x0000000000000040 0x0000000000000040 |
| 28 | + 0x00000000000002d8 0x00000000000002d8 R 0x8 |
| 29 | + INTERP 0x0000000000000318 0x0000000000000318 0x0000000000000318 |
| 30 | + 0x000000000000001c 0x000000000000001c R 0x1 |
| 31 | + [Requesting program interpreter: /lib64/ld-linux-x86-64.so.2] |
| 32 | + LOAD 0x0000000000000000 0x0000000000000000 0x0000000000000000 |
| 33 | + 0x0000000000000630 0x0000000000000630 R 0x1000 |
| 34 | + LOAD 0x0000000000001000 0x0000000000001000 0x0000000000001000 |
| 35 | + 0x0000000000000191 0x0000000000000191 R E 0x1000 |
| 36 | + LOAD 0x0000000000002000 0x0000000000002000 0x0000000000002000 |
| 37 | + 0x00000000000000bc 0x00000000000000bc R 0x1000 |
| 38 | + LOAD 0x0000000000002dd0 0x0000000000003dd0 0x0000000000003dd0 |
| 39 | + 0x0000000000000248 0x0000000000000250 RW 0x1000 |
| 40 | + DYNAMIC 0x0000000000002de0 0x0000000000003de0 0x0000000000003de0 |
| 41 | + 0x00000000000001e0 0x00000000000001e0 RW 0x8 |
| 42 | + NOTE 0x0000000000000338 0x0000000000000338 0x0000000000000338 |
| 43 | + 0x0000000000000040 0x0000000000000040 R 0x8 |
| 44 | + NOTE 0x0000000000000378 0x0000000000000378 0x0000000000000378 |
| 45 | + 0x0000000000000044 0x0000000000000044 R 0x4 |
| 46 | + GNU_PROPERTY 0x0000000000000338 0x0000000000000338 0x0000000000000338 |
| 47 | + 0x0000000000000040 0x0000000000000040 R 0x8 |
| 48 | + GNU_EH_FRAME 0x0000000000002018 0x0000000000002018 0x0000000000002018 |
| 49 | + 0x0000000000000024 0x0000000000000024 R 0x4 |
| 50 | + GNU_STACK 0x0000000000000000 0x0000000000000000 0x0000000000000000 |
| 51 | + 0x0000000000000000 0x0000000000000000 RW 0x10 |
| 52 | + GNU_RELRO 0x0000000000002dd0 0x0000000000003dd0 0x0000000000003dd0 |
| 53 | + 0x0000000000000230 0x0000000000000230 R 0x1 |
| 54 | +
|
| 55 | + Section to Segment mapping: |
| 56 | + Segment Sections... |
| 57 | + 00 |
| 58 | + 01 .interp |
| 59 | + 02 .interp .note.gnu.property .note.gnu.build-id .note.ABI-tag .gnu.hash .dynsym .dynstr .gnu.version .gnu.version_r .rela.dyn .rela.plt |
| 60 | + 03 .init .plt .text .fini |
| 61 | + 04 .rodata .eh_frame_hdr .eh_frame |
| 62 | + 05 .init_array .fini_array .dynamic .got .got.plt .data .bss |
| 63 | + 06 .dynamic |
| 64 | + 07 .note.gnu.property |
| 65 | + 08 .note.gnu.build-id .note.ABI-tag |
| 66 | + 09 .note.gnu.property |
| 67 | + 10 .eh_frame_hdr |
| 68 | + 11 |
| 69 | + 12 .init_array .fini_array .dynamic .got |
| 70 | +``` |
| 71 | + |
| 72 | +## Types of Segments |
| 73 | + |
| 74 | +There are many types of segments. The most common and important ones are: |
| 75 | + |
| 76 | +- `PT_PHDR`: Contains the program header. |
| 77 | +- `PT_LOAD`: Actually loaded in the memory. Every other section is mapped to this. |
| 78 | +- `PT_INTERP`: Holds the `.interp` section responsible for providing the interpreter. |
| 79 | +- `PT_NULL`: First entry of the table, unassigned. |
| 80 | +- `PT_DYNAMIC`: Holds the `.dynamic` section. |
| 81 | + |
| 82 | + |
| 83 | +An interesting thing to note here is the `GNU_STACK` segment in the output. It has a peculiar |
| 84 | +size of 0. This implies that the stack size is decided by the kernel. Its size is always |
| 85 | +ignored and it is just there for permission management. |
| 86 | + |
| 87 | +Another thing to be mentioned is `GNU_EH_FRAME` that specifies the frame unwinding information. |
| 88 | +Usually the same as `.eh_frame_hdr` section. |
0 commit comments