COFF
Common Object File Format Specification
Imediatamente após a assinatura PE temos o cabeçalho COFF (Common Object File Format Specification) às vezes chamado simplesmente de Cabeçalho do Arquivo (File Header ) ou mesmo Cabeçalho do Arquivo PE (PE File Header). Trata-se de um cabeçalho especificado antes mesmo do formato PE para o sistema operacional VAX/VMS (depois chamado de OpenVMS) da DEC (empresa comprada pela Compaq, que por sua vez, foi comprada pela HP) na década de 70. A razão pela qual a Microsoft teria aproveitado o formato COFF é que boa parte dos engenheiros do time que desenvolveu o Windows NT trabalhavam para a DEC antes.
O cabeçalho COFF possui apenas 20 bytes e é representado pela seguinte estrutura:
Vamos à definição dos campos importantes para nós:
Machine
Campo de 2 bytes que define a arquitetura da máquina para qual o programa foi construído. Valores comuns são 0x14c (Intel i386 ou compatíveis) e 0x8664 (AMD64 ou compatíveis). A tabela completa está disponível na documentação oficial.
NumberOfSections
Também de 2 bytes, o valor deste campo é o número de seções que o arquivo PE em questão possui. As seções serão estudadas mais a frente.
TimeDateStamp
Este é um número de 32 bits que define o número de segundos desde à meia-noite do dia 1 de Janeiro de 1970, conhecido também por Epoch time. Com este valor é possível saber quando o arquivo foi criado.
Vale lembrar que este campo não é utilizado pelo loader de arquivos PE no Windows e seu valor pode ser alterado após a compilação, logo, não é 100% confiável, ou seja, você não pode garantir que um binário PE foi compilado na data e hora informadas pelo valor neste campo.
SizeOfOptionalHeader
Contém o tamanho do próximo cabeçalho, conhecido como Cabeçalho Opcional, que estudaremos muito em breve.
Characteristics
Campo que define alguns atributos do arquivo. Este campo é uma máscara de bits, ou seja, cada bit desses 2 bytes diz respeito à uma característica específica do binário. Não cabe aqui explicar todos os possíveis valores, mas os mais comuns são:
Bit | Nome | Comentários |
---|---|---|
2 | IMAGE_FILE_EXECUTABLE_IMAGE | Obrigatório para arquivos executáveis |
9 | IMAGE_FILE_32BIT_MACHINE | Arquivo de 32-bits |
14 | IMAGE_FILE_DLL | O arquivo é uma DLL |
Analise novamente o (dump hexadecimal do executável da calculadora)[dos.md#exercicios] considere que:
Logo após a assinatura PE na posição 0xd8 temos o primeiro campo do cabeçalho COFF que é o Machine. Ele é um campo de 2 bytes conforme já dito, então os bytes 0x4c e 0x01 definem seu valor. Considerando o endianness, chegamos ao valor 0x14c, que define que este executável foi criado para máquinas Intel i386 ou compatíveis.
Em seguida, na posição 0xde, temos o NumberOfSections que é 4.
Depois vem o campo TimeDateStamp com o número inteiro de 32 bits (4 bytes) sem sinal 0x4ce7979d que é 1290246045 em decimal. Podemos usar o comando date do Linux para converter para data e hora atuais:
Pulamos então 8 bytes referentes aos campos PointerToSymbolTable e NumberOfSymbols (normalmente zerados mesmo), encontrando o valor da word SizeOfOptionalHeader em 0xec de valor 0xe0.
A próxima word é o valor do campo Characteristics, que neste arquivo é 0x102. Convertendo para binário temos o valor 100000010 (bits 2 e 9 setados) significando que o arquivo é um executável de 32-bits.
Em algumas referências o leitor encontrará o cabeçalho COFF como parte do cabeçalho NT (IMAGE_NT_HEADER), onde o primeiro campo é chamado de Signature Bytes, que é onde fica a assinatura PE para binários PE, mas também pode conter os bytes equivalentes das strings NE, LE ou MZ (executáveis puros de MS-DOS). Na verdade o COFF é uma especificação completa para arquivos do tipo "código-objeto", mas não exploraremos seu uso além do formato PE neste livro.
Exercício
Baixe e descompate o arquivo CRACKME.ZIP em https://www.mentebinaria.com.br/files/file/19-crackme-do-cruehead/. Usando o comando dumpbin através do Visual Studio Developer Command Prompt (instalado com o Visual Studio Community), exiba o COFF/File Header do binário CRACKME.EXE. Você deve ver algo assim:
Com o DIE, é preciso carregar o CRACKME.EXE nele, marcar a caixa de seleção Advanced, clicar no botão PE (Alt+P), na aba NT Headers e por fim, na aba File Header. Você deve ver uma janela como a abaixo:
Os botões com "..." localizados ao lado direito de vários valores de campos provêem informações adicionais sobre tais valores. Não deixe de experimentar.
Last updated