Informática Numaboa - Referências
O formato PE
Sab 11 Abr 2009 11:01 |
- Detalhes
- Categoria: Formatos padrão
- Atualização: Sábado, 11 Abril 2009 23:44
- Autor: vovó Vicki
- Acessos: 14446
Cabeçalhos das seções
Cabeçalho MZ do DOS |
Fragmento (stub) do DOS |
Cabeçalho do Arquivo |
Cabeçalho Opcional Diretório de Dados |
Cabeçalhos das Seções |
Seção 1 |
Seção 2 |
... |
Seção n |
As seções são compostas por duas partes principais: primeiro, a descrição da seção (do tipo IMAGE_SECTION_HEADER) e depois os dados propriamente ditos. Desta forma, logo após os diretórios de dados, encontramos um array de cabeçalhos de seções do tipo número de seções ('NumberOfSections'), ordenado pelos RVAs das seções. Um cabeçalho de seção contém:
- Um array de Nomes das Seções
- Endereço Físico e do Tamanho Virtual
- Endereço Virtual
- Tamanho dos Dados
- Ponteiro para os Dados
- Ponteiro para Remanejamento
- Características
Nomes das Seções
O primeiro componente é um array de IMAGE_SIZEOF_SHORT_NAME de 8 bytes para guardar o nome (ASCII) da seção. Se todos os 8 bytes forem usados não existe um terminador 0 (zero) para a string! O nome é tipicamente algo como ".data" ou ".text" ou mesmo ".bss". Não há a necessidade do nome ser precedido por um ponto '.' e não existem nome predefinidos (qualquer nome é aceito).
Os nomes também não têm qualquer relação com o conteúdo da seção. Uma seção de nome ".code" pode ou não conter código executável: pode perfeitamente conter a tabela de endereços de importação, pode conter código executável E a tabela de endereços de importação e até os dados inicializados.
Para achar informações nas seções, é preciso buscá-las nos diretórios de dados do cabeçalho opcional. Não se deixe influenciar pelo nome da seção e não assuma que os dados da seção estejam logo no início da mesma.
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | ASCII |
... | |||||||||||||||||
0000 01B0 | 2E | 74 | 65 | 78 | 74 | 00 | 00 | 00 | .text... | ||||||||
0000 01C0 | 94 | 01 | 00 | 00 | 00 | 10 | 00 | 00 | 00 | 02 | 00 | 00 | 00 | 04 | 00 | 00 | ”............... |
0000 01D0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 20 | 00 | 00 | 60 | ............ ... |
0000 01E0 | 2E | 72 | 64 | 61 | 74 | 61 | 00 | 00 | C2 | 01 | 00 | 00 | 00 | 20 | 00 | 00 | .rdata..Å.... .. |
0000 01F0 | 00 | 02 | 00 | 00 | 00 | 06 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | ................ |
0000 0200 | 00 | 00 | 00 | 00 | 40 | 00 | 00 | 40 | 2E | 64 | 61 | 74 | 61 | 00 | 00 | 00 | ....@..@.data... |
0000 0210 | 24 | 00 | 00 | 00 | 00 | 30 | 00 | 00 | 00 | 02 | 00 | 00 | 00 | 08 | 00 | 00 | $....0.......... |
0000 0220 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 40 | 00 | 00 | C0 | ............@..Å |
0000 0230 | 2E | 72 | 73 | 72 | 63 | 00 | 00 | 00 | 60 | 09 | 00 | 00 | 00 | 40 | 00 | 00 | .rsrc...`....@.. |
0000 0240 | 00 | 0A | 00 | 00 | 00 | 0A | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | ................ |
0000 0250 | 00 | 00 | 00 | 00 | 40 | 00 | 00 | C0 | ....@..Å......... |
Endereço Físico e do Tamanho Virtual
O próximo membro da IMAGE_SECTION_HEADER é a união de 32 bits do Endereço Físico ('PhysicalAddress') e do Tamanho Virtual ('VirtualSize'). Num arquivo objeto, este é o endereço para o qual o conteúdo é remanejado; num executável, é o tamanho do conteúdo. Mais uma vez, este campo não é utilizado! Há linkadores que o preenchem com o tamanho, outros com o endereço e outros ainda que o preenchem com 0. Apesar disso, os executáveis não apresentam problemas.
Endereço Virtual
Logo a seguir vem o Endereço Virtual ('VirtualAddress'), um valor de 32 bits que contém o RVA para os dados da seção quando esta estiver mapeada na RAM.
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | ASCII |
... | |||||||||||||||||
0000 01B0 | 2E | 74 | 65 | 78 | 74 | 00 | 00 | 00 | .text... | ||||||||
0000 01C0 | 94 | 01 | 00 | 00 | 00 | 10 | 00 | 00 | 00 | 02 | 00 | 00 | 00 | 04 | 00 | 00 | ”............... |
0000 01D0 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 00 | 20 | 00 | 00 | 60 | ............ ... |
No nosso exemplo, o valor encontrado é 0000 1000, ou seja, o RVA será de 4096 bytes (destacado em azul).
Tamanho dos Dados
Após o endereço virtual vêm 32 bits para os Tamanho dos Dados ('SizeOfRawData'), que nada mais é do que o tamanho dos dados da seção arredondado para cima, para o próximo múltiplo de 'FileAlignment' (alinhamento de arquivo).
No nosso exemplo, o valor encontrado é 0000 0200, ou seja, o tamanho dos dados da seção é de 512 bytes (veja acima, destacado em verde).
Ponteiro para os Dados
Segue-se o Ponteiro para os Dados ('PointerToRawData'), também de 32 bits. Este ponteiro é extremamente útil porque é o offset do início do arquivo em disco até os dados da seção. Se for 0, os dados da seção não estão contidos no arquivo e serão carregados arbitrariamente no momento da carga do programa.
No exemplo, encontramos 0000 0400, destacado acima em vermelho. Observe o endereço 0400 deste arquivo armazenado em disco:
Offset | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | A | B | C | D | E | F | ASCII |
0000 0400 | 6A | 00 | E8 | 87 | 01 | 00 | 00 | A3 | 1C | 30 | 40 | 00 | E8 | 77 | 01 | 00 | j.è‡...£.0@.èw.. |
Após uma longa sucessão de zeros em endereços anteriores, em 0400 inicia-se a sucessão de dados da seção .text.
Ponteiro para Remanejamento
A seguir vem o Ponteiro para Remanejamento ('PointerToRelocations') de 32 bits e o Ponteiro para Números de Linha ('PointerToLinenumbers'), também de 32 bits, o Número de Remanejamentos ('NumberOfRelocations') de 16 bits e o Número de Números de Linha ('NumberOfLinenumbers'), também de 16 bits. Todas estas informações somente são utilizadas para arquivos objeto. Os executáveis não possuem um diretório de remanejamento base especial e a informação de número de linha, se é que está presente, geralmente está localizada num segmento especial para debugging ou em qualquer outro lugar.
No exemplo, todas estas posições estão preenchidas com zeros (observe a linha 01D0 acima).
Características
O último membro dos cabeçalhos das seções é o valor de 32 bits com as Características. São um punhado de flags que descrevem como a memória das seções deve ser tratada:
Nome | Bit | Setado (valor 1) |
IMAGE_SCN_CNT_CODE | 5 | A seção contém código executável. |
IMAGE_SCN_CNT_INITIALIZED_DATA | 6 | A seção contém dados que recebem um valor definido antes que a execução se inicie. Em outras palavras: os dados da seção são significativos. |
IMAGE_SCN_CNT_UNINITIALIZED_DATA | 7 | A seção contém dados não inicializados que terão todos os bytes zerados antes que a execução se inicie. Este, geralmente, é o BSS. |
IMAGE_SCN_LNK_INFO | 9 | A seção não contém dados de imagem e sim comentários, descrições ou outra documentação qualquer. Esta informação faz parte de arquivos objeto e pode ser a informação para o linker, como, por exemplo, as bibliotecas necessárias. |
IMAGE_SCN_LNK_REMOVE | 11 | Os dados fazem parte de uma seção de um arquivo objeto que deve ser deixado de fora quando o arquivo executável for linkado. Com frequência este bit está combinado com o bit 9. |
IMAGE_SCN_LNK_COMDAT | 12 | A seção contém o "common block data", que são funções de pacotes. |
IMAGE_SCN_MEM_FARDATA | 15 | Existe 'far data' - significado incerto. |
IMAGE_SCN_MEM_PURGEABLE | 17 | Os dados da seção podem sofrer um 'purge' - não é o mesmo que descartáveis, pois há um bit para este fim (veja abaixo). O mesmo bit, aparentemente, é usado para indicar informações de 16 bits - significado incerto. |
IMAGE_SCN_MEM_LOCKED | 18 | Significado incerto - a seção não pode ser deslocada na memória? - não há informação de remanejamento? |
IMAGE_SCN_MEM_PRELOAD | 19 | Significado incerto - a seção deve ser "paginada" antes do início da execução? |
20 a 23 | Especificam um alinhamento. Não há informações disponíveis. Existe um #define IMAGE_SCN_ALIGN_16BYTES e parecidos... | |
IMAGE_SCN_LNK_NRELOC_OVFL | 24 | A seção contém alguns remanejamentos extendidos - significado incerto. |
IMAGE_SCN_MEM_DISCARDABLE | 25 | Os dados da seção não são necessários após o início do processo. É o caso, por exemplo, das informações de remanejamento. São encontradas também para rotinas de startup de drivers e serviços que são executados apenas uma vez e para diretórios de importação. |
IMAGE_SCN_MEM_NOT_CACHED | 26 | Os dados da seção não devem ir para cache. (Será que significa desligar o cache de segundo nível?) |
IMAGE_SCN_MEM_NOT_PAGED | 27 | Os dados da seção não devem sair da página. Isto é interessante para drivers. |
IMAGE_SCN_MEM_SHARED | 28 | Os dados da seção são compartilhados entre todas as instâncias das imagens que estiverem sendo executadas. Se forem os dados inicializados de uma DLL, por exemplo, todos os conteúdos das mesmas variáveis serão os mesmos em todas as instâncias da DLL. Note que apenas a seção da primeira instância é inicializada. Seções contendo código são sempre compartilhadas copy-on-write, isto é, o compartilhamento não funciona se houver a necessidade de fazer remanejamentos. |
IMAGE_SCN_MEM_EXECUTE | 29 | O processo recebe acesso de 'execução' na memória da seção. |
IMAGE_SCN_MEM_READ | 30 | O processo recebe acesso de 'leitura' na memória da seção. |
IMAGE_SCN_MEM_WRITE | 31 | O processo recebe acesso de 'escrita' na memória da seção. |
Analisando os últimos 32 bits do cabeçalho da seção .text, destacados em magenta logo acima, obtemos o hexadecimal 6000 0020. Abrindo-o em bits para poder analisar este valor, constatamos o seguinte:
Hexa | 60 | 00 | 00 | 20 | ||||||||||||||||||||||||||||
Binário | 1 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 1 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
Bits | 31 | 30 | 29 | 28 | 27 | 26 | 25 | 24 | 23 | 22 | 21 | 20 | 19 | 18 | 17 | 16 | 15 | 14 | 13 | 12 | 11 | 10 | 9 | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
Relevante na seção .text são os seguintes bits:
- Bit 5 = 0: A seção NÃO contém código executável.
- Bit 7 = 1: A seção contém dados não inicializados.
- Bit 29 = 0: O processo NÃO recebe acesso de 'execução'.
- Bit 30 = 1: O processo recebe acesso de 'leitura'.
- Bit 31 = 1: O processo recebe acesso de 'escrita'.
:anota: Exercícios propostos
Para este módulo, tente o seguinte:
- Abra os bits de Características das seções .rdata e .data do programa exemplo. Quais as diferenças entre estas seções?
- Abra outro programa e determine as Características das suas seções.
- Determine o endereço virtual das seções do programa exemplo e verifique se aponta para o início dos dados das respectivas seções.
- Faça o mesmo com um outro executável qualquer.