Triage de firmware e fluxo de engenharia reversa

TL;DR


1. Tipos de arquivos de firmware: o que você pode receber

Formatos comuns

Uma realidade central

Um binário bruto não informa:

Você precisa inferir isso pelo contexto.


2. Checklist de triagem (faça sempre)

Passo 1: Identifique o tipo de arquivo

1
file firmware.bin

Se for ELF, você está em situação muito mais fácil.

Passo 2: Entropia/estrutura rápida

1
2
hexdump -C firmware.bin | head
strings -a firmware.bin | head

Procure por:

Passo 3: Procure assinaturas

Mesmo sem ferramentas especializadas, você pode buscar padrões:

1
grep -aobU $'\x7fELF' firmware.bin | head

Isso indica se há um ELF embutido dentro de um blob maior.

Passo 4: Se for ELF: extraia estrutura imediatamente

1
2
3
4
readelf -h firmware.elf
readelf -S firmware.elf
readelf -l firmware.elf
readelf -s firmware.elf | head

Perguntas-chave:


3. Se você tem um .bin: como recuperar um endereço de carga provável

Estratégia A: A partir do mapa de memória da plataforma

Se você conhece o mapa de memória do alvo (por exemplo, QEMU virt), muitas vezes conhece endereços típicos de RAM/flash.

Estratégia B: Vetores de reset / padrões de boot

Em algumas arquiteturas, o vetor de reset tem uma estrutura reconhecível. No RISC-V, o boot geralmente começa com um prólogo pequeno e um salto; os padrões são menos padronizados do que tabelas de vetor do ARM, mas você ainda pode procurar:

Estratégia C: Endereços absolutos no código

Se o firmware inclui endereços absolutos (registradores MMIO, ranges de RAM), esses endereços podem revelar a plataforma.


4. Um “primeiro disassembly” prático (sem se comprometer cedo demais)

Mesmo sem uma ferramenta GUI, você pode fazer um disassembly sanity se souber a arquitetura.

Exemplo: disassemble um binário bruto como RV32

Se você tem GNU binutils com suporte a RISC-V:

1
riscv64-unknown-elf-objdump -D -b binary -m riscv:rv32 firmware.bin | less

Se a saída for majoritariamente lixo/ilegais, suas suposições podem estar erradas:


5. Carving: extraindo sub-imagens de um blob

Se você encontrar um ELF embutido no offset O, extraia:

1
2
dd if=firmware.bin of=extracted.elf bs=1 skip=$O
file extracted.elf

Se for um ELF real, você pode usar todos os métodos do Capítulo 2.

Se você encontrar uma assinatura de filesystem ou compressão, pode precisar de ferramentas especializadas (comuns em firmware), mas o fluxo continua:


6. Transforme achados em um mapa (habilidade subestimada)

Crie uma anotação simples como:

1
2
3
4
5
6
7
8
9
Firmware X
- tamanho: ...
- tipo: ...
- possível arch: rv32im
- strings: ...
- endereço de carga suspeito: ...
- entry point suspeito: ...
- constantes notáveis: ...
- próxima ação: (emular / disassemble / encontrar logs de UART / procurar formato de update)

Isso torna seu trabalho reproduzível e mais fácil de compartilhar.


7. Laboratório minimalista de “estilo firmware” (usando seu próprio sample)

  1. Pegue build/ld_demo.elf (do Capítulo 7) e converta para .bin.
  2. Finja que você não sabe o que é.
  3. Use apenas file, hexdump, strings e objdump -b binary para identificar.
  4. Escreva seu melhor palpite sobre:
    • arquitetura,
    • endereço de carga,
    • o que o código faz.

Depois, compare com a verdade usando readelf no ELF original.


Exercícios

  1. Embuta um ELF em um blob maior (ex.: concatenando com padding) e pratique carving com grep -aob e dd.
  2. Crie um binário bruto com um endereço base conhecido (ex.: seu linker origin) e veja como o disassembly muda se você assumir um base errado.
  3. Escolha 5 strings de uma imagem de firmware e escreva hipóteses sobre a que subsistemas elas se relacionam.

Como testar suas respostas


Resumo

Você aprendeu um fluxo de triagem de firmware repetível: identificar → extrair → validar → mapear → escolher o próximo passo de análise.

A seguir: análise dinâmica com tracing no QEMU, quando isso se aplica a IoT/firmware, quais são as limitações e como fazer experimentos reprodutíveis e seguros.