Cabeçalhos das Seções
Após o cabeçalho opcional, encontramos os cabeçalhos das seções (estas serão explicadas no próximo capítulo). Neste cabeçalho há um array de estruturas como a seguir:
Cada estrutura define uma seção no executável e a quantidade de estrutura (quantidade de elementos neste array) é igual ao número de seções no executável, definido no campo NumberOfSections do cabeçalho COFF. Vamos aos campos importantes:
Name
Este campo define o nome da seção. Como é um array de 8 elementos do tipo uint8_t, este nome está limitado à 8 caracteres. A string .text por exemplo ocupa apenas 5 bytes, então os outros 3 devem estar zerados. Há suporte à UTF-8 para estes nomes.
VirtualSize
O tamanho em bytes da seção depois de ser mapeada (carregada) em memória pelo loader. Se este valor for maior que o valor do campo SizeOfRawData, os bytes restantes são preenchidos com zeros.
VirtualAddress
O endereço relativo à base da imagem (campo ImageBase do cabeçalho Opcional) quando a seção é carregada em memória. Por exemplo, se para uma seção este valor é 0x1000 e o valor de ImageBase é 0x400000, quando carregada em memória esta seção estará no endereço 0x401000. Para chegar nesta conclusão basta somar os dois valores.
SizeOfRawData
Tamanho em bytes da seção no arquivo PE, ou seja, antes de ser mapeada em memória. Alguns autores também usam a expressão "tamanho em disco" ou simplesmente "tamanho da seção".
PointerToRawData
O offset em disco da seção no arquivo. É correto dizer que aponta para o primeiro byte da seção. Por exemplo, se para dada seção este valor é 0x400 e o valor do campo SizeOfRawData é 0x1800, para ver somente seu conteúdo em hexadecimal com o hexdump poderíamos fazer:
Characteristics
Este é um campo que define algumas flags para a seção, além das permissões em memória que ela deve ter quando for mapeada pelo loader. Ele possui 32-bits, onde alguns significam conforme a tabela a seguir:
Bit | Nome da flag | Descrição |
---|---|---|
5 | IMAGE_SCN_CNT_CODE | A seção contém código executável |
6 | IMAGE_SCN_CNT_INITIALIZED_DATA | A seção contém dados inicializados |
7 | IMAGE_SCN_CNT_UNINITIALIZED_ DATA | A seção contém dados não inicializados |
29 | IMAGE_SCN_MEM_EXECUTE | Terá permissão de execução |
30 | IMAGE_SCN_MEM_READ | Terá permissão de leitura |
31 | IMAGE_SCN_MEM_WRITE | Terá permissão de escrita |
As flags que contém o texto "MEM" no nome dizem respeito às permissões que a seção terá quando mapeada em memória. De acordo com elas o SO vai setar as permissões nas páginas de memória nas quais a seção é carregada.
É importante notar que campos como o Characteristics são o que chamamos de máscaras de bits. Por exemplo, a tabela anterior diz que se o bit 30 deste campo está setado (seu valor é 1), então esta seção terá permissão de leitura quando em memória. O valor de campo Characteristics seria então 01000000000000000000000000000000 em binário, mas você provavelmente vai encontrar este valor representado em hexadecimal (0x40000000) nos analisadores de executáveis que for utilizar. Aliás, agora é uma boa hora para abrir o DIE e analisar alguns arquivos executáveis, colocando em prática tudo o que foi visto até aqui.
Last updated