# Formatos

Os arquivos de texto, independentemente da codificação (ASCII, ISO-8859-1, UTF-8, etc) são tipos de arquivos bem simples. Começaremos agora a avaliar tipos de arquivos mais complexos. Acontece que para um programa **salvar** ou **abrir** um determinado tipo de arquivo, é essencial que este conheça seu **formato**. Tomemos por exemplo o formato GIF. Para inspecionar seu conteúdo, utilizaremos, no Windows, um editor hexadecimal gráfico chamado HxD.

Analise o seguinte arquivo GIF aberto no HxD:

![Conteúdo de um arquivo GIF visualizado em hexadecimal](/files/tm1NUJnBeQcamahT0PVf)

O HxD é um editor hexadecimal. Para entender como estes editores funcionam, vamos começar pelas colunas onde os *bytes* estão organizados.

## **Offset**

Também chamado de **offset no arquivo** ou **offset em disco**, esta coluna exibe a **posição** do conteúdo no arquivo, em *bytes*. Na imagem, o primeiro *byte* (no *offset* 0) é o 0x47. O segundo é o 0x49 e assim por diante. Já o byte no *offset* 0x10 é o 0x06.

Identifique na imagem as afirmações a seguir:

* O *byte* no *offset* 0x53 é o 0xc8.
* O *byte* no *offset* 0x7c é 0xc0.
* O *byte* no *offset* 0x90 é 0x6c.

## **Conteúdo**

A próxima coluna exibe os *bytes* em si. Sem segredos. Por serem editores hexadecimais, programas como o HxD exibem o conteúdo do arquivo em bytes hexadecimais separados por espaços, mas é importante lembrar que o conteúdo de um arquivo é uma sequência de bits em disco ou em outro dispositivo de armazenamento que, quando aberto num editor, tem seu conteúdo copiado para a memória. A maneira como estes bytes serão visualizados fica a cargo do programa que o abre. Por exemplo, se o editor exibisse os bytes em decimal, os primeiros dois bytes (0x47 e 0x49) seriam 71 e 73. Se fosse em binário, seria 1000111 e 1001001.

A esta altura você já deve ter percebido que um número pode ser expresso de várias maneiras, no entanto, o sistema hexadecimal é bem otimizado para fins de engenharia reversa.

## **Representação Textual**

Na terceira coluna o HxD nos apresenta a representação textual em ASCII de cada *byte* exibido na segunda coluna, ou seja, se o *byte* em questão estiver dentro da faixa de caracteres ASCII imprimíveis (de 0x20 à 0x7e), sua representação é exibida. Para valores fora desta faixa, o HxD imprime um ponto.

Há dezenas de outros editores hexadecimais disponíveis, inclusive alguns visualizadores de linha de comando. Vale consultar o apêndice Ferramentas e testar alguns. Se você tiver curiosidade de saber como funciona um visualizador hexadecimal, recomendo olhar o código do **hdump**, disponível em <https://github.com/merces/hdump>, um visualizador de linha de comando que implementei em C para funcionar em Windows, Linux e macOS.

## **Exemplo do Formato GIF**

De volta ao formato, é importante ressaltar que tanto quem programa o software que salva um determinado tipo de arquivo quanto quem programa o software que visualiza tal formato precisa conhecê-lo bem. Vejamos então como o formato GIF é definido.

Em geral, os formatos são definidos por campos (faixas de *bytes*) de tamanho fixo ou variável, que podem assumir determinados valores. Para entendê-los, precisamos da documentação deste formato (no caso, do GIF) que está disponível livremente na internet. Conforme sua especificação, o formato GIF segue, dentre outras, as seguintes regras:

| Byte offset (posição no arquivo) | Tamanho do campo em bytes | Valor em hexadecimal | Descrição         |
| -------------------------------- | ------------------------- | -------------------- | ----------------- |
| 0                                | 6                         | 47 49 46 38 39 61    | Cabeçalho         |
| 6                                | 2                         | \<variável>          | Largura em pixels |
| 8                                | 2                         | \<variável>          | Altura em pixels  |

Seguindo esta tabela fornecida por quem desenhou o formato GIF e olhando o conteúdo do arquivo de exemplo na imagem anterior, podemos verificar que o primeiro campo, de 6 *bytes*, casa exatamente com o que está definido no padrão. Os *bytes* são a sequência 0x47, 0x49, 0x46, 0x38, 0x39 e 0x61 que representam a sequência em ASCII GIF89a. É bem comum ao definir formatos de arquivo que o primeiro campo, normalmente chamado de cabeçalho (*header*) ou número mágico (*magic number*), admita como valor uma representação ASCII que dê alguma indicação de que tipo de arquivo se trata. Por exemplo, os tipos de arquivo ZIP possuem o *magic number* equivalente ao texto **PK**. Já o tipo de arquivo RAR começa com os *bytes* equivalentes ao texto **Rar!**. Não é uma regra, mas é comum.

> No exemplo do formato GIF o tamanho do primeiro campo é de 6 *bytes,* mas outros formatos podem utilizar *magic numbers* de diferentes tamanhos. Não há regra específica.

Logo após o primeiro campo, temos o segundo campo, que define a largura em *pixels* da imagem GIF segundo sua documentação. Este campo possui 2 *bytes* e, na imagem de exemplo, são os *bytes* 0x30 e 0x00. Aqui cabe voltar num conceito importante que é o **endianness**. Acontece que na arquitetura Intel os *bytes* de um número inteiro são armazenados de trás para frente (ordem essa chamada de ***little-endian***). Sendo assim, a leitura correta da largura em *pixels* deste GIF é 0x0030, ou simplesmente 0x30 (já que zero à esquerda não conta), que é 48 em decimal.

O próximo campo, também de 2 *bytes*, nos diz a altura em *pixels* da imagem GIF e também possui o valor 0x30 (já lendo os *bytes* de trás para frente conforme explicado). É correto dizer então que esta é uma imagem de 48 x 48 *pixels*.

É por isso que alguns sistemas operacionais, como o GNU/Linux, não consideram a extensão de um arquivo como sendo algo importante para definir seu tipo. Na verdade, o conteúdo do arquivo o define.

Não seguiremos com toda a interpretação do formato GIF pois isto foge do nosso escopo, mas vamos seguir a mesma lógica para entender o formato de arquivos executáveis do sistema Windows, objeto de estudo do próximo capítulo.


---

# 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/04-arquivos/formatos.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.
