Fundamentos de Engenharia Reversa
Apoie este trabalho
  • 🙌Apresentação
  • 👀Antes de Começar
  • 🥇Introdução
  • 🔢Números
    • Sistemas de Numeração
    • O Byte
    • Números Negativos
    • Cálculos com Binários
  • 🧵Cadeias de Texto
    • ASCII
    • Unicode
    • C Strings
  • 🗂️Arquivos
    • Formatos
  • 💼O formato PE
    • Cabeçalhos
      • MS-DOS
      • COFF
      • Opcional
      • Diretórios de Dados
      • Cabeçalhos das Seções
    • Seções
    • Import Table
    • Endereçamento
  • 🚗Execução de Programas
    • Executáveis
    • Bibliotecas
    • Processos
  • 🖼️Windows API
    • Caixas de Mensagens
    • Manipulação de Arquivos
    • Acesso ao Registro
  • ⚙️Assembly
    • Registradores
    • Instruções Básicas
    • Funções e Pilha
  • 🐞Depuração
    • O Debugger
    • Disassembly
    • Breakpoints
    • Manipulação do Fluxo
    • Patches
  • Apêndices
    • Tabela ASCII
    • Tabela ISO-8859-1/Latin-1
    • Exemplos de Código em Assembly
    • Funções da API do Windows
    • Ferramentas
    • Referências
  • Sobre o livro
    • 📝Registro de alterações
Powered by GitBook
On this page
  • Offset
  • Conteúdo
  • Representação Textual
  • Exemplo do Formato GIF

Was this helpful?

Edit on GitHub
Export as PDF
  1. Arquivos

Formatos

PreviousArquivosNextO formato PE

Last updated 5 days ago

Was this helpful?

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:

O HxD é um editor hexadecimal. Para entender 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 engenheiria 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 chamda 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, com o GNU/Linux, não consideram a extensão de 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.

🗂️
Conteúdo de um arquivo GIF visualizado em hexadecimal