.elf formata inspeção interna

2

Eu estava lendo a especificação de formato ELF, onde foi dito tudo isso com cabeçalhos de elfos, cabeçalho de programa, seções, segmentos e etc. Tudo isso é referenciado como estruturas com todos os tipos de campos e valores.

Então, a questão é, onde tudo isso vai? Quero dizer, posso assisti-los como structs, não como saída de readelf util?

Existe algum arquivo intermediário, onde todos esses elf-magic existem, mesclados no código-fonte? Ou são apenas internos do compilador, e em estruturas de especificação são mencionados apenas para humanos?)

Parece "galinha e ovo pergunta" para mim (falando sobre código compilado em termos de código).

    
por Constantine 24.08.2016 / 17:37

1 resposta

1

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 para ELFCLASS64 (ELF64);

  • , a codificação, 0x01 para ELFDATA2LSB ;

  • 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 ).

    
por 27.08.2016 / 00:01