Binwalk e extração de firmwares | Do bit Ao Byte
Linux Binwalk e extração de firmwares 27 de junho de 201210 de maio de 2016
initrd.linux bios.raiz
Binwalk é apenas uma das ferramentas
Binwalk é uma ferramenta fundamental para análise e interação, 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:
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 extraí-lo 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.
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, que por sua vez me passou a dica através desse post. O aplicativo se chama BinWalk e o Marcelo fez um pacote (disponibilizado no link dele) e também o disponibilizo aqui.
Utilizando o binwalk
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
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.864 0x40 LZMA compressed data, properties: 0x6D, dictionary size: 8388608 bytes, uncompressed size: 2491056 bytes1179648 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
dd ibs=1 skip=1179648 if=carambola.bin of=carambola.squashfs 2359300+0 records in4608+1 records out2359300 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:
unsquashfs carambola.squashfs
apt-get install squashfs-toolsmodprobe squashfsunsquashfs 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.
Esse tipo de arquivo eu não tinha a menor idéia de como extraí-lo, daí esse link do post do Marcelo. 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.jffs2modprobe block2mtd block2mtd=$loop,131072modprobe jffs2modprobe mtdblockmkdir rootfsmount -t jffs2 -o ro /dev/mtdblock0 rootfs Reparou em block2mtd o valor após $loop? Esse número cabalistico 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 é 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
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 sua extração 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
extract_compressed_fs arquivo.cloop arquivo_de_saidamount -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
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:
#O dispositivo já deve estar criado em /dev. Caso não esteja:
# Copie o conteudo da imagem para o dispositivo mtd0:
#O load do ubi apontando para o dispositivo mtd criado:
# montagem do UBIFS
#O sistema está disponível agora em /mnt/ubifs. Quando finalizar:
#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 UBIFSmount -t ubifs /dev/ubi0_0 /mnt/ubifs #O sistema está disponível agora em /mnt/ubifs. Quando finalizar:umount /mnt/ubifsrmmod 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? Compartilhe através das redes sociais disponibilizadas abaixo! ;-)
Comments comments ← Eletrônica digital com Arduino – Sensor de linha para open/close
Eletrônica digital com Arduino – EtherShield V1.1 na IDE 1.0.1 →
Um comentário em "Binwalk e extração de firmwares"	Pingback: Extração de imagens de sistema | Linux Ajuda Deixe uma resposta Cancelar respostaVocê precisa fazer o login para publicar um comentário.	Receber aviso por email