# COFF

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:

```c
typedef struct {
    uint16_t Machine;
    uint16_t NumberOfSections;
    uint32_t TimeDateStamp;
    uint32_t PointerToSymbolTable;
    uint32_t NumberOfSymbols;
    uint16_t SizeOfOptionalHeader;
    uint16_t Characteristics;
} IMAGE_FILE_HEADER, IMAGE_COFF_HEADER;
```

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 incluem 0x8664 para executáveis x86-64 de 64-bits, 0x14c para executáveis x86 de 32-bits e 0xaa64 para executáveis ARM de 64-bits. A tabela completa está disponível na documentação oficial do formato.

## 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 dizer que este campo não é utilizado pelo *loader* de arquivos PE no Windows e seu valor pode ser alterado pelo compilador ou 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                            |
| --- | ---------------------------------- | -------------------------------------- |
| 1   | IMAGE\_FILE\_EXECUTABLE\_IMAGE     | Obrigatório para arquivos executáveis  |
| 5   | IMAGE\_FILE\_LARGE\_ADDRESS\_AWARE | Pode endereçar mais de 2 GB de memória |
| 8   | IMAGE\_FILE\_32BIT\_MACHINE        | O arquivo é de 32-bits                 |
| 13  | IMAGE\_FILE\_DLL                   | O arquivo é uma DLL                    |

Vamos analisar novamente o executável da calculadora. Considere que:

* Logo após a assinatura PE na posição 0x100, temos o primeiro campo do cabeçalho COFF que é o **Machine**. Ele é um campo de 2 *bytes* conforme já dito, então os *bytes* 0x64 e 0x86 definem seu valor. Considerando o *endianness*, chegamos ao valor 0x8664, que define que este executável foi criado para rodar em computadores com processadores de arquitetura x86-64.
* Em seguida, na posição 0x106, temos o **NumberOfSections** que é 7.
* Depois vem o campo **TimeDateStamp** com o número inteiro de 32 *bits* (4 *bytes*) sem sinal 0xee8136fb que é 4001445627 em decimal.
* Pulamos então 8 *bytes* referentes aos campos **PointerToSymbolTable** e **NumberOfSymbols** (normalmente zerados mesmo), encontrando a *word* **SizeOfOptionalHeader** em 0x114 cujo valor é 0xf0.
* A próxima *word* é o valor do campo **Characteristics**, que neste arquivo é 0x22. Convertendo para binário temos o valor 00100010. Contando-se a partir de zero e da direita para a esquerda, identificamos que os *bits* 1 e 5 estão ligados, significando que o executável pode endereçar mais de 2 GB de memória, o que é comum em executáveis de 64-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

Abra o **Developer Command Prompt for VS 2022** (ele é instalado junto ao Visual Studio Community) e exiba o COFF/File Header do binário da calculadora do Windows:

```
dumpbin /nologo /headers c:\windows\system32\calc.exe
```

Você deve ver uma saída parecida com essa:

```
Dump of file c:\windows\system32\calc.exe

PE signature found

File Type: EXECUTABLE IMAGE

FILE HEADER VALUES
            8664 machine (x64)
               7 number of sections
        EE8136FB time date stamp
               0 file pointer to symbol table
               0 number of symbols
              F0 size of optional header
              22 characteristics
                   Executable
                   Application can handle large (>2GB) addresses
--suprimido--
```

O que o **dumpbin** e outros analisadores de PE fazem é interpretar toda a estrutura do arquivo com base na documentação do formato PE e produzir uma saída mais legível.

Com o **Detect It Easy**, também é possível ver os cabeçalhos de um PE. Para ver o cabeçalho COFF, abra o executável no DIE e marque a caixa de seleção **Advanced**. Clique no botão **PE** e no menu à esquerda escolha **IMAGE\_FILE\_HEADER**. Você deve ver uma janela como esta:

![Cabeçalho COFF exibido pelo DIE](/files/HztpcQT5UWVg00Sc7r9D)

Aproveite e navegue pelo programa para descobrir mais detalhes sobre o arquivo antes de irmos para o Cabeçalho Opcional.


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://mentebinaria.gitbook.io/engenharia-reversa/05-o-formato-pe/cabecalhos/coff.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
