Manual

do

Maker

.

com

Binwalk e extração de firmwares

Binwalk e extração de firmwares

Extração de firmwares fácil - Binwalk é uma ferramenta fundamental para análise e interação e extração de firmwares, mas não é a única coisa que você utilizará na manipulação de imagens. Em um dos posts de embedded exemplifiquei a extração de dados de um arquivo CPIO. Mas existem outros formatos com outros tipos de extração para embarcados. Então, esse será um post que talvez receba algumas atualizações conforme eu for passando por essas extrações. Para não deixá-lo de fora, iniciaremos por:

CPIO

Em diversos livecds o sistema raiz é basicamente o initrd. O initrd contém toda a estrutura de um sistema raiz necessária para fazer a pré-carga do sistema levantando módulos e serviços que porventura sejam necessários. Maiores detalhes sobre o initrd podem ser vistos nos posts sobre embedded.

Então, para extrair uma raiz de um arquivo CPIO, primeiramente copie o initrd do livecd (ou o próprio de sua distro, para fazer experimentos) para um diretório, por exemplo, /tmp/initrd. Depois, faça primeiramente a descompressão; se a extensão for gz, use gzip; lz, use lzma. Porém como foi mostrado neste post sobre embedded, algumas vezes a extensão pode 'mentir' sobre o real formato do arquivo. Enfim, faça a extração.

Após a extração do arquivo, um cpio com o provável nome de 'initrd' será gerado nesse diretório. Então para fazer a extração de firmwares use:

cpio -idmuv <initrd

A raiz do sistema será extraída do CPIO para o diretório em que esse comando estiver sendo executado, portanto certifique-se de que não esteja executando-o em um nível de diretório em que possa se misturar com outros dados. A extração de firmwares deve ser feita em um diretório reservado, crie-o se ainda não o fez.

bin

Arquivos bin podem ser imagens de firmware. Para extrair o sistema nesse caso são duas etapas, porque os arquivos bin possuem um conjunto que compõe o sistema como um todo. Para exemplo da extração e da estrutura de um arquivo .bin, vamos utilizar um aplicativo recomendado pelo Alan (que palestrou sobre o Linux BIOS no FISL8) para o grande mestre Marcelo Barros. O aplicativo se chama BinWalk e pode ser instalado via apt-get em distribuições Debian like.

Utilizando o binwalk (pré- extração de firmwares)

Após instalá-lo, você poderá executá-lo sobre o arquivo binário do sistema. No exemplo estou utilizando o bin do Carambola, uma board MIPS:


binwalk arquivo.bin 
DECIMAL   	HEX       	DESCRIPTION
--------------------------------------------
0         	0x0       	uImage header,
  header size: 64 bytes, header CRC: 0x119ECEC2,
  created: Fri Jun 15 11:08:03 2012, image size:
  854075 bytes, Data Address: 0x80000000,  Entry
  Point: 0x80000000, data CRC: 0x5FD3BF10,   OS:
  Linux, CPU: MIPS, image type: OS Kernel Image,
  compression type: lzma, image name: MIPS OpenWrt
  Linux-3.3.8
64        	0x40       LZMA   compressed data,
 properties: 0x6D, dictionary size: 8388608 bytes,
 uncompressed size: 2491056 bytes
1179648   	0x120000       Squashfs filesystem,
 little endian, version 4.0, size: 541137663 bytes,
 1079 inodes, blocksize: 0 bytes, created: Tue  Apr
 28 01:20:16 1987

Como se pode ver, o sistema foi composto por 3 partes:

  • uBoot (bootloader)
  • kernel (utilizando a compressão LZMA)
  • sistema (utilizando squashfs)

Agora vem a parte divertida, que é extrair a parte do binário referente ao sistema raiz. Para isso, utilizamos o bom e velho dd. Repare que o endereço do sistema no binário está após 1179648. Daí basta iniciar o strip do binário a partir desse endereço:


dd ibs=1 skip=1179648 if=carambola.bin of=carambola.squashfs

2359300+0 records in
4608+1 records out
2359300 bytes (2.4 MB) copied, 0.63503 s, 3.7 MB/s

Utilizo linux Mint, então instalei através do apt o squashfs-tools, levantei o módulo e descomprimi assim:


apt-get install squashfs-tools
modprobe squashfs
unsquashfs carambola.squashfs

Foi criado um diretório squashfs-root contendo toda a estrutura do sistema raiz.
Se quisesse copiar o kernel, teria que limitar o dd com count para que ele não fosse até o final do arquivo. Como o sistema raiz vai até o final do binário, não foi necessário limitar o dd.

Vamos a uma breve introdução do SquashFS:

O que é SquashFS?

Quando se está criando um sistema linux pequeno para embedded, na maioria das arquiteturas preza-se pelo espaço de armazenamento. Nesse caso, quanto maior for a compressão do sistema, melhor.

O SquashFS é um arquivo de sistemas read-only que permite a você comprimir todo o sitema ou simplesmente diretórios, escrevendo os resultados para outras partições, dispositivos ou arquivos ordinários, então monta-o diretamente (se um dispositivo) ou utilizando um dispositivo de loopback (se for um arquivo). Para utilizar um dispositivo de loopback você pode simplesmente passar a opção '-o loop' na montagem do arquivo. O restante do comando é similar à montagem de um device.
Outra vantagem sobre um arquivo tar por exemplo, é a performance e velocidade de acesso, por isso seu uso é tão apreciado.

Um documento um pouco desatualizado pode ser encontrado nesse link.

jffs2

Esse tipo de arquivo eu não tinha a menor idéia de como extraí-lo, pesquisei um bocado. Gerei uma imagem jffs2 de 128k em um dos SDKs que utilizo (OpenWrt) para fazer essa parte do post:


export loop=$(losetup -f)
losetup $loop rootfs.jffs2
modprobe block2mtd block2mtd=$loop,131072
modprobe jffs2
modprobe mtdblock
mkdir rootfs
mount -t jffs2 -o ro /dev/mtdblock0 rootfs

Reparou em block2mtd o valor após $loop? Esse número cabalístico funcionou para mim tal como para o Marcelo e também na origem da informação em um outro link. Então, deverá funcionar para você também.
Depois bastará listar dentro rootfs para ver seus arquivos.

ROMFS

ROMFS é um econômico e pequeno sistema de arquivos read-only originado e usado em alguns projetos Linux. Ele é um sistema de arquivos baseado em blocos, disponível no kernel desde a versão 2.1.21 (Janeiro de 1997).

Diferentemente do squashfs, o romfs armazena apenas o mínimo requerido para levantar um sistema, sem considerar timestamps ou permissões. Uma boa aplicação para romfs é utilizá-lo no ramdisk inicial ou então, em um dispositivo que necessite de recursos mínimos e trabalhe em modo somente-leitura.

O Sparc-boot.org foi um projeto que utilizou romfs, porém hoje já não existe. O uClinux também fez uso do romfs para processadores Motorola m68k e ARM.
Na atualidade, sinceramente, não sei se alguém utiliza ainda esse formato, mas está disponível sua criação através de seleção no menu do BuildRoot.
Um arquivo ROMFS pode ser montado da mesma forma que um arquivo iso:


mount -o loop,ro arquivo.romfs mountpoint

Cloop

O cloop é um módulo do kernel do Linux. Ele adiciona suporte a descompressão transparente em dispositivos de bloco read-only, mas não é um arquivo de sistemas por si só. Ele foi originalmente escrito por Rusty Russell, posteriormente mantido por Klaus Knopper, o autor do Knoppix, que deu origem a centenas de live cds, entre eles, o Kurumin. A taxa de compressão do cloop é de 2.5:1, o que fazia do Knoppix um sistema de 700MB na compressão, sendo que a extração de firmwares gerava um arquivo de 1.8GB.

Para chegar ao sistema de arquivos, duas etapas são necessárias. Primeiro, instale o pacote cloop-utils, depois:


extract_compressed_fs arquivo.cloop arquivo_de_saida
mount -o loop arquivo_de_saida mountpoint

cramfs

Compressed ROM File System, ou cramfs é um sistema de arquivos read-only simplista e eficiente, utilizado principalmente em sistemas embarcados. Diferente de uma imagem convencional, um cramfs não precisa ser descomprimido para ser utilizado, por esse motivo algumas distribuições de linux utilizam (ou utilizaram) esse formato em suas imagens de instalação. O principal motivo para utilização desse formato é a economia de memória por não haver descompressão do arquivo.

Para descomprimí-lo, instale o pacote cramfsprogs e execute:


cramfsck -x dir_de_saida arquivo.cramfs

ubifs

Unsorted Block Image File System ou UBIFS. Ele é um sucessor do JFFS2 e compete ao logfs como um arquivo de sistema para usar com memória flash raw. Seu desenvolvimento começou em 2007.
Dispositivos MTD não podem ser utilizados diretamente.
Uma das maiores diferenças entre UBIFS e JFFS2 é que UBIFS suporta cache de escrita. Sua performance também é melhor do que JFFS2 para dispositivos NAND de grandes tamanhos. Ele também preserva a compressão on-the-fly do JFFS2 e é recuperável e tolerante a falhas de energia. A compressão padrão compreende zlib e LZO.

A magnífica documentação do UBIFS pode ser encontrada aqui.

Infelizmente não há ferramenta no user-space ainda para manipulação de imagens mtd e não é possível montá-la como um loop porque ela não trabalha com dispositivos de bloco.

A documentação descreve um hacking que confesso não ter funcionado no meu sistema. De qualquer modo, as ferramentas mdt-utils são necessárias, mas instalei também o mtdev-tool.


#O exemplo descreve a emulação de um dispositivo NAND assim:
modprobe nandsim first_id_byte=0x20 second_id_byte=0xaa third_id_byte=0x00 fourth_id_byte=0x15

#O dispositivo já deve estar criado em /dev. Caso não esteja:
mknod /dev/mtd0 c 90 0

# Copie o conteudo da imagem para o dispositivo mtd0:
dd if=ubi.img of=/dev/mtd0 bs=2048

#O load do ubi apontando para o dispositivo mtd criado:
modprobe ubi mtd=0

# montagem do  UBIFS
mount -t ubifs /dev/ubi0_0 /mnt/ubifs

#O sistema está disponível agora em /mnt/ubifs. Quando finalizar:
umount /mnt/ubifs
rmmod ubifs ubi nandsim

A compressão desses arquivos normalmente é feita pelo SDK utilizado para contruir o sistema, mas há casos que a compilação manual do respectivo arquivo pode ser necessária. Eu utilizo esse método algumas vezes para construir o initrd do Phantom e o fiz também para embarcar uma versão modificada do SLITaz em um dispositivo que ainda não posso citá-lo por ser um possível produto.

Então, em algum momento farei um post mostrando como reconstruir seus arquivos de sistema, é só aguardar. Curtiu esse post?

Nome do Autor

Djames Suhanko

Autor do blog "Do bit Ao Byte / Manual do Maker".

Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.