|
| 1 | +# ELF HEADER |
| 2 | +The elf file header is always present at the offset 0 of the executable (Remember FILE OFFSETS from the [Introduction]?). Let's have a look at the ELF header. |
| 3 | + |
| 4 | + |
| 5 | + |
| 6 | + |
| 7 | +## ANALYSIS |
| 8 | +The files `hello_32` and `hello_64` are the 32-bit and 64-bit compiled versions of the file [hello.c].<br> |
| 9 | +Lets have a look at the ELF header of the 32-bit compiled binary. I have cross compiled the source code for a 32 bit platform. Try viewing the file with cat. |
| 10 | + |
| 11 | +```shell |
| 12 | +ELF��4,4 (44�4� TT�T����� |
| 13 | + |
| 14 | + � |
| 15 | + � |
| 16 | + ����hh�h�DDP�td�����DDQ�tdR�td |
| 17 | + |
| 18 | + � |
| 19 | + ���/lib/ld-linux.so.2GNUGNU�z�8��u�6�0P#g�G� �K��6 |
| 20 | + ��libc.so.6_IO_stdi,��__libc_start_mainGLIBC_2.0__gmon_start__ii |
| 21 | + �S�����k��������t�&�[��5����% |
| 22 | + �h������%��f�1�^�����PTR�#����p���P�����PQV����P�������$�f�f�f�f����f�f�f�f�f�f�f��$�f�f�f�f�f�f���=�t$���tU����h��Ѓ��É���'�Í�&��'��-����������t ���tU����Ph��҃��Ít&�Í��=�uU����l������Ív�Í�&��'U��]��U��� |
| 23 | +... |
| 24 | +problably some more crap |
| 25 | +``` |
| 26 | +We see here, no meaningful data can be scraped out from this output. Therefore, we ought to use a tool to analyse the information provided by the binary, here comes readelf in action.<br> |
| 27 | +
|
| 28 | +### READELF |
| 29 | +This tool scraps the ELF binary to extract and display some meaningful information from it. The '-h' flag is used to display ELF header of file `hello_64`. |
| 30 | +
|
| 31 | +```shell |
| 32 | +critical@d3ad:~/COURSE_DISECTING_BINARIES/ELF/ELF_HEADER$ readelf -h hello_64 |
| 33 | +ELF Header: |
| 34 | + Magic: 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |
| 35 | + Class: ELF64 |
| 36 | + Data: 2's complement, little endian |
| 37 | + Version: 1 (current) |
| 38 | + OS/ABI: UNIX - System V |
| 39 | + ABI Version: 0 |
| 40 | + Type: EXEC (Executable file) |
| 41 | + Machine: Advanced Micro Devices X86-64 |
| 42 | + Version: 0x1 |
| 43 | + Entry point address: 0x4003b0 |
| 44 | + Start of program headers: 64 (bytes into file) |
| 45 | + Start of section headers: 6256 (bytes into file) |
| 46 | + Flags: 0x0 |
| 47 | + Size of this header: 64 (bytes) |
| 48 | + Size of program headers: 56 (bytes) |
| 49 | + Number of program headers: 9 |
| 50 | + Size of section headers: 64 (bytes) |
| 51 | + Number of section headers: 27 |
| 52 | + Section header string table index: 26 |
| 53 | +
|
| 54 | +``` |
| 55 | +
|
| 56 | +ELF header is actually a structure - `Elf64_Ehdr` defined in file - `/usr/include/elf.h`. |
| 57 | +
|
| 58 | +```shell |
| 59 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -B16 " Elf64_Ehdr;" |
| 60 | +typedef struct |
| 61 | +{ |
| 62 | + unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */ |
| 63 | + Elf64_Half e_type; /* Object file type */ |
| 64 | + Elf64_Half e_machine; /* Architecture */ |
| 65 | + Elf64_Word e_version; /* Object file version */ |
| 66 | + Elf64_Addr e_entry; /* Entry point virtual address */ |
| 67 | + Elf64_Off e_phoff; /* Program header table file offset */ |
| 68 | + Elf64_Off e_shoff; /* Section header table file offset */ |
| 69 | + Elf64_Word e_flags; /* Processor-specific flags */ |
| 70 | + Elf64_Half e_ehsize; /* ELF header size in bytes */ |
| 71 | + Elf64_Half e_phentsize; /* Program header table entry size */ |
| 72 | + Elf64_Half e_phnum; /* Program header table entry count */ |
| 73 | + Elf64_Half e_shentsize; /* Section header table entry size */ |
| 74 | + Elf64_Half e_shnum; /* Section header table entry count */ |
| 75 | + Elf64_Half e_shstrndx; /* Section header string table index */ |
| 76 | +} Elf64_Ehdr; |
| 77 | +``` |
| 78 | +
|
| 79 | +
|
| 80 | +
|
| 81 | +### ANALYSING EACH FIELD OF ELF HEADER |
| 82 | +
|
| 83 | +#### Magic |
| 84 | + Displays 16 hexadecimal bytes in a row. Here the first 4 bytes (7f 45 4c 46) are called magic numbers. Here first byte is fixed (0x7f). These bytes are used to identify an ELF format. Have a look at the ASCII representation of the hex values (type `man ASCII` to open up ASCII table) and see the values of bytes after 0x7f, i.e. 0x45 0x4c 0x46 are 'E', 'L', 'F' respectively. |
| 85 | +
|
| 86 | +
|
| 87 | +| BYTES | Description | |
| 88 | +|:----------:|:---------------| |
| 89 | +| 7f | It is a Fixed byte | |
| 90 | +| 45 4c 46 | ELF signature. Look at the ASCII table (with command <br> `man ASCII`), the values corresponding to them are<br> 'E', 'L', 'F'. This indicates that it is an ELF executable. |
| 91 | +| 02 | It is the class described bellow. (ELF64) | |
| 92 | +| 01 | It is the Data field described bellow (2's complement,<br>little endian) |
| 93 | +| 01 | Version field bellow (Version Number 1)| |
| 94 | +| 00 | OS/ABI field bellow (UNIX - System V) | |
| 95 | +| 00 00 00 00 00 00 00 00 | Padded bytes for allignment, currently unused, kept<br> for future use. |
| 96 | + |
| 97 | +The file `/usr/include/elf.h` includes the MACROS which define values for each byte. |
| 98 | +```shell |
| 99 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A2 "EI_MAG" |
| 100 | + |
| 101 | +107:#define EI_MAG0 0 /* File identification byte 0 index */ |
| 102 | +108-#define ELFMAG0 0x7f /* Magic number byte 0 */ |
| 103 | +109- |
| 104 | +110:#define EI_MAG1 1 /* File identification byte 1 index */ |
| 105 | +111-#define ELFMAG1 'E' /* Magic number byte 1 */ |
| 106 | +112- |
| 107 | +113:#define EI_MAG2 2 /* File identification byte 2 index */ |
| 108 | +114-#define ELFMAG2 'L' /* Magic number byte 2 */ |
| 109 | +115- |
| 110 | +116:#define EI_MAG3 3 /* File identification byte 3 index */ |
| 111 | +117-#define ELFMAG3 'F' /* Magic number byte 3 */ |
| 112 | +118- |
| 113 | +``` |
| 114 | + |
| 115 | +Verify the magic field by hd (hexdump) tool. |
| 116 | +```shell |
| 117 | +critical@d3ad:~/COURSE_DISECTING_BINARIES/ELF/ELF_HEADER$ hd -n 16 hello_64 |
| 118 | +00000000 7f 45 4c 46 02 01 01 00 00 00 00 00 00 00 00 00 |.ELF............| |
| 119 | +00000010 |
| 120 | +``` |
| 121 | + |
| 122 | + |
| 123 | +#### Class |
| 124 | + The value 0x01, Specifies that it is a 64-bit binary, i.e. it contains 64-bit objects. It is the 5th byte in the 'Magic' field. |
| 125 | + |
| 126 | +| Value | Description | |
| 127 | +| :---: | :---------: | |
| 128 | +| 1 | 32-bit objects| |
| 129 | +| 2 | 64-bit ojects | |
| 130 | + |
| 131 | +```shell |
| 132 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A5 "EI_CLASS" |
| 133 | +123:#define EI_CLASS 4 /* File class byte index */ |
| 134 | +124-#define ELFCLASSNONE 0 /* Invalid class */ |
| 135 | +125-#define ELFCLASS32 1 /* 32-bit objects */ |
| 136 | +126-#define ELFCLASS64 2 /* 64-bit objects */ |
| 137 | +127-#define ELFCLASSNUM 3 |
| 138 | +128- |
| 139 | +``` |
| 140 | + |
| 141 | + |
| 142 | +#### Data |
| 143 | +This field describes the data encoding (little-endian in this case). You can have a look at the `/usr/include/elf.h` to know what each value means. |
| 144 | + |
| 145 | +| Value | Description | |
| 146 | +| :---: | :---------: | |
| 147 | +| 1 | 2's complement, little endian | |
| 148 | +| 2 | 2's complement, big endian | |
| 149 | + |
| 150 | +```shell |
| 151 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A5 "EI_DATA" |
| 152 | +129:#define EI_DATA 5 /* Data encoding byte index */ |
| 153 | +130-#define ELFDATANONE 0 /* Invalid data encoding */ |
| 154 | +131-#define ELFDATA2LSB 1 /* 2's complement, little endian */ |
| 155 | +132-#define ELFDATA2MSB 2 /* 2's complement, big endian */ |
| 156 | +133-#define ELFDATANUM 3 |
| 157 | +134- |
| 158 | +``` |
| 159 | + |
| 160 | +#### Version |
| 161 | +ELF header version number. |
| 162 | + |
| 163 | + |
| 164 | +```shell |
| 165 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A2 "EI_VERSION" |
| 166 | +135:#define EI_VERSION 6 /* File version byte index */ |
| 167 | +136- /* Value must be EV_CURRENT */ |
| 168 | +137- |
| 169 | +``` |
| 170 | + |
| 171 | +#### OS/ABI |
| 172 | +These are the values for target OS ABI (**A**pplication **B**inary **I**nterface). |
| 173 | +```shell |
| 174 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A19 "EI_OSABI" |
| 175 | +138:#define EI_OSABI 7 /* OS ABI identification */ |
| 176 | +139-#define ELFOSABI_NONE 0 /* UNIX System V ABI */ |
| 177 | +140-#define ELFOSABI_SYSV 0 /* Alias. */ |
| 178 | +141-#define ELFOSABI_HPUX 1 /* HP-UX */ |
| 179 | +142-#define ELFOSABI_NETBSD 2 /* NetBSD. */ |
| 180 | +143-#define ELFOSABI_GNU 3 /* Object uses GNU ELF extensions. */ |
| 181 | +144-#define ELFOSABI_LINUX ELFOSABI_GNU /* Compatibility alias. */ |
| 182 | +145-#define ELFOSABI_SOLARIS 6 /* Sun Solaris. */ |
| 183 | +146-#define ELFOSABI_AIX 7 /* IBM AIX. */ |
| 184 | +147-#define ELFOSABI_IRIX 8 /* SGI Irix. */ |
| 185 | +148-#define ELFOSABI_FREEBSD 9 /* FreeBSD. */ |
| 186 | +149-#define ELFOSABI_TRU64 10 /* Compaq TRU64 UNIX. */ |
| 187 | +150-#define ELFOSABI_MODESTO 11 /* Novell Modesto. */ |
| 188 | +151-#define ELFOSABI_OPENBSD 12 /* OpenBSD. */ |
| 189 | +152-#define ELFOSABI_ARM_AEABI 64 /* ARM EABI */ |
| 190 | +153-#define ELFOSABI_ARM 97 /* ARM */ |
| 191 | +154-#define ELFOSABI_STANDALONE 255 /* Standalone (embedded) application */ |
| 192 | +155- |
| 193 | +156-#define EI_ABIVERSION 8 /* ABI version */ |
| 194 | +157- |
| 195 | +``` |
| 196 | + |
| 197 | +#### TYPE |
| 198 | +Identifies the object file type. |
| 199 | + |
| 200 | +```shell |
| 201 | +critical@d3ad:~/COURSE_DISECTING_BINARIES/Introduction$ cat /usr/include/elf.h | grep -n -A9 "ET_NONE" |
| 202 | +162:#define ET_NONE 0 /* No file type */ |
| 203 | +163-#define ET_REL 1 /* Relocatable file */ |
| 204 | +164-#define ET_EXEC 2 /* Executable file */ |
| 205 | +165-#define ET_DYN 3 /* Shared object file */ |
| 206 | +166-#define ET_CORE 4 /* Core file */ |
| 207 | +167-#define ET_NUM 5 /* Number of defined types */ |
| 208 | +168-#define ET_LOOS 0xfe00 /* OS-specific range start */ |
| 209 | +169-#define ET_HIOS 0xfeff /* OS-specific range end */ |
| 210 | +170-#define ET_LOPROC 0xff00 /* Processor-specific range start */ |
| 211 | +171-#define ET_HIPROC 0xffff /* Processor-specific range end */ |
| 212 | +``` |
| 213 | + |
| 214 | +#### MACHINE |
| 215 | +It is the machine specification required to properly run this ELF. |
| 216 | +```shell |
| 217 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A190 "EM_NONE" |
| 218 | +175:#define EM_NONE 0 /* No machine */ |
| 219 | +176-#define EM_M32 1 /* AT&T WE 32100 */ |
| 220 | +177-#define EM_SPARC 2 /* SUN SPARC */ |
| 221 | +178-#define EM_386 3 /* Intel 80386 */ |
| 222 | +179-#define EM_68K 4 /* Motorola m68k family */ |
| 223 | +180-#define EM_88K 5 /* Motorola m88k family */ |
| 224 | +181-#define EM_IAMCU 6 /* Intel MCU */ |
| 225 | +182-#define EM_860 7 /* Intel 80860 */ |
| 226 | +183-#define EM_MIPS 8 /* MIPS R3000 big-endian */ |
| 227 | +184-#define EM_S370 9 /* IBM System/370 */ |
| 228 | +185-#define EM_MIPS_RS3_LE 10 /* MIPS R3000 little-endian */ |
| 229 | +.... |
| 230 | +And tons of other machine types (nearly 200) |
| 231 | +``` |
| 232 | + |
| 233 | +#### VERSION |
| 234 | +Specifies the version of the file. (not the ELF header's) |
| 235 | +
|
| 236 | +```shell |
| 237 | +critical@d3ad:~$ cat /usr/include/elf.h | grep -n -A4 "EV_NONE" |
| 238 | +378:#define EV_NONE 0 /* Invalid ELF version */ |
| 239 | +379-#define EV_CURRENT 1 /* Current version */ |
| 240 | +380-#define EV_NUM 2 |
| 241 | +381- |
| 242 | +``` |
| 243 | +
|
| 244 | +#### ENTRY POINT ADDRESS |
| 245 | +This specifies the address where the execution of the program starts (.text section)(explained later in the course). If you have ever programmed in C language, it is usually the address of the `main()` function and usually address of `_start` (in assembly programming). |
| 246 | +
|
| 247 | +#### START OF PROGRAM HEADERS |
| 248 | +It is the offset to the **P**rogram **H**eader **T**able (**PHT**) (explained later in the course), from the very first byte in the file (0x7f present at offset 0). |
| 249 | +
|
| 250 | +#### START OF SECTION HEADERS |
| 251 | +It is the offset to the **S**ection **H**eader **T**able (**SHT**) (explained later in the course), from the very first byte in the file (0x7f present at offset 0). |
| 252 | +
|
| 253 | +#### FLAGS |
| 254 | +`EFLAGS` register is set to this value when the program is loaded into memory. |
| 255 | +
|
| 256 | +#### SIZE OF THIS HEADER |
| 257 | +Displays the size of this 'ELF Header' |
| 258 | +
|
| 259 | +#### SIZE OF PROGRAM HEADERS |
| 260 | +Displays size of each segment in bytes. |
| 261 | +
|
| 262 | +#### NUMBER OF PROGRAM HEADERS |
| 263 | +Displays the number of Program Headers (Segments) in the file. |
| 264 | +
|
| 265 | +#### SIZES OF SECTION HEADERS |
| 266 | +Displays size of each section header. |
| 267 | +
|
| 268 | +#### NUMBER OF SECTION HEADERS |
| 269 | +Specifies the number of section headers (starting from the NULL entry). |
| 270 | +
|
| 271 | +#### SECTION HEADER STRING TABLE INDEX |
| 272 | +The value is 26. It means the section at index number 26 (in Section Header Table), stores all the section names (which are NULL terminated strings). |
| 273 | +
|
| 274 | +
|
| 275 | +```shell |
| 276 | +critical@d3ad:~/COURSE_DISECTING_BINARIES/ELF/ELF_HEADER$ readelf -p 26 hello_64 |
| 277 | +
|
| 278 | +String dump of section '.shstrtab': |
| 279 | + [ 1] .symtab |
| 280 | + [ 9] .strtab |
| 281 | + [ 11] .shstrtab |
| 282 | + [ 1b] .interp |
| 283 | + [ 23] .note.ABI-tag |
| 284 | + [ 31] .note.gnu.build-id |
| 285 | + [ 44] .gnu.hash |
| 286 | + [ 4e] .dynsym |
| 287 | + [ 56] .dynstr |
| 288 | + [ 5e] .gnu.version |
| 289 | + [ 6b] .gnu.version_r |
| 290 | + [ 7a] .rela.dyn |
| 291 | + [ 84] .init |
| 292 | + [ 8a] .text |
| 293 | + [ 90] .fini |
| 294 | + [ 96] .rodata |
| 295 | + [ 9e] .eh_frame_hdr |
| 296 | + [ ac] .eh_frame |
| 297 | + [ b6] .init_array |
| 298 | + [ c2] .fini_array |
| 299 | + [ ce] .dynamic |
| 300 | + [ d7] .got |
| 301 | + [ dc] .got.plt |
| 302 | + [ e5] .data |
| 303 | + [ eb] .bss |
| 304 | + [ f0] .comment |
| 305 | +
|
| 306 | +
|
| 307 | +``` |
| 308 | +
|
| 309 | +
|
| 310 | +
|
| 311 | +## NOTE |
| 312 | + You can't mug up these things. All this will start making sense after getting some hands on disecting and understanding the ELF binaries. We'll now start with the SHT and the PHT. This was designed to give you an entry point in disection of binaries and so that later on after you complete the course it could prove out to be a good review material :) |
| 313 | +
|
| 314 | +
|
| 315 | +<br> |
| 316 | +
|
| 317 | +**[PREV - ELF]** <br> |
| 318 | +**[NEXT - SECTION HEADER TABLE]** |
| 319 | +
|
| 320 | +[Introduction]: ./../../Introduction/Introduction.md |
| 321 | +[hello.c]: ./hello.c |
| 322 | +[PREV - ELF]: ./../ELF.md |
| 323 | +[NEXT - SECTION HEADER TABLE]: ./../SECTION_HEADER_TABLE/SHT.md |
0 commit comments