Estas estruturas estão presentes nos arquivos ELF.
Vamos ver o cabeçalho ELF:
#define EI_NIDENT (16)
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf32_Half e_type; /* Object file type */
Elf32_Half e_machine; /* Architecture */
Elf32_Word e_version; /* Object file version */
Elf32_Addr e_entry; /* Entry point virtual address */
Elf32_Off e_phoff; /* Program header table file offset */
Elf32_Off e_shoff; /* Section header table file offset */
Elf32_Word e_flags; /* Processor-specific flags */
Elf32_Half e_ehsize; /* ELF header size in bytes */
Elf32_Half e_phentsize; /* Program header table entry size */
Elf32_Half e_phnum; /* Program header table entry count */
Elf32_Half e_shentsize; /* Section header table entry size */
Elf32_Half e_shnum; /* Section header table entry count */
Elf32_Half e_shstrndx; /* Section header string table index */
} Elf32_Ehdr;
typedef struct
{
unsigned char e_ident[EI_NIDENT]; /* Magic number and other info */
Elf64_Half e_type; /* Object file type */
Elf64_Half e_machine; /* Architecture */
Elf64_Word e_version; /* Object file version */
Elf64_Addr e_entry; /* Entry point virtual address */
Elf64_Off e_phoff; /* Program header table file offset */
Elf64_Off e_shoff; /* Section header table file offset */
Elf64_Word e_flags; /* Processor-specific flags */
Elf64_Half e_ehsize; /* ELF header size in bytes */
Elf64_Half e_phentsize; /* Program header table entry size */
Elf64_Half e_phnum; /* Program header table entry count */
Elf64_Half e_shentsize; /* Section header table entry size */
Elf64_Half e_shnum; /* Section header table entry count */
Elf64_Half e_shstrndx; /* Section header string table index */
} Elf64_Ehdr;
O cabeçalho ELF está no início de todos os arquivos ELF .
O que isso realmente significa é que os primeiros 16 bytes de arquivos ELF são os campos e_ident
no cabeçalho ELF:
-
o primeiro byte é 0x7f;
-
o segundo é
'E'
; -
o terceiro é
'L'
; -
o quarto é
'F'
; -
o quinto é a classe;
-
o sexto é a codificação de dados;
-
o sétimo é a versão do arquivo;
-
o oito é o OS ABI;
-
etc.
Após o campo e_ident
, os próximos 2 bytes são e_type
.
Se você for head /bin/bash
, poderá ver o ELF
no início.
Agora, se você pegar um hexdump do começo de um arquivo ELF:
$ xxd /bin/bash | head 00000000: 7f45 4c46 0201 0100 0000 0000 0000 0000 .ELF............ 00000010: 0200 3e00 0100 0000 7005 4200 0000 0000 ..>.....p.B..... 00000020: 4000 0000 0000 0000 c0cd 0f00 0000 0000 @............... 00000030: 0000 0000 4000 3800 0900 4000 1d00 1c00 [email protected]...@..... 00000040: 0600 0000 0500 0000 4000 0000 0000 0000 ........@....... 00000050: 4000 4000 0000 0000 4000 4000 0000 0000 @.@.....@.@..... 00000060: f801 0000 0000 0000 f801 0000 0000 0000 ................ 00000070: 0800 0000 0000 0000 0300 0000 0400 0000 ................ 00000080: 3802 0000 0000 0000 3802 4000 0000 0000 8.......8.@..... 00000090: 3802 4000 0000 0000 1c00 0000 0000 0000 8.@.............
A primeira linha deste hexdump são os primeiros 16 bytes ( e_ident
):
-
o primeiro byte é de fato
0x7f
; -
, em seguida, vem
"ELF"
; -
depois disso vem a classe
0x02
paraELFCLASS64
(ELF64); -
, a codificação,
0x01
paraELFDATA2LSB
; -
etc.
Os dois primeiros bytes da segunda linha são e_type
. Eles são codificados em LSB (por causa de ELFDATA2LSB
), portanto, o valor é realmente 0x0002
, o que significa ET_EXEC
(esse é um arquivo executável).
Os próximos dois bytes são a arquitetura ( e_machine
): 0x003e
para EM_X86_64
porque esse é um arquivo executável x86_64
.
Você deve ser capaz de decodificar manualmente todos os campos do cabeçalho ELF e deve encontrar os mesmos valores fornecidos por readelf
. A partir disso, você pode localizar outras estruturas ELF no arquivo, como ElfXX_Shdr
ou ElfXX_Phdr
, e decodificá-las com base em sua definição (e você deve encontrar as mesmas infromações que as fornecidas por readelf
).