dimanche 23 août 2015

Dump de mémoire flash SPI avec Rasbperry Pi

Le protocole SPI

Le protocole SPI (Serial Peripheral Interface) est un protocole série synchrone largement utilisé dans les systèmes embarqués par les SoC (System on Chip) pour communiquer avec les composants de mémoire non-volatile externes. Ces architectures sont courantes dans les systèmes embarqués des Box Internet (modem router), Set-Top-Box, Smart TV, Media center, NAS, Femtocells ou encore les Box domotiques. Le protocole SPI est un protocole série synchrone qui suit un modèle Maître/Esclave.

Le protocole SPI offre ainsi une communication entre un maître et un ou plusieurs esclaves. Le maître impose la fréquence d’horloge pour synchroniser les échanges et il sélectionne l’esclave avec lequel il souhaite communiquer. Les données sont mises sur la ligne de bus adéquate MISO ou MOSI. La ligne MOSI (Master Out Slave In) permet d’envoyer des données depuis le maître vers l’esclave. La ligne MISO (Master In Slave Out) est en haute-impédance jusqu’au moment où l’esclave est sélectionné et où il doit envoyer ses données.
Schéma protocole Serial Peripheral Interface (SPI)
Serial Peripheral Interface
Lorsque l’on dispose de plusieurs esclaves, ils peuvent être connectés ensemble sur le bus en daisy-chain. Le maître sélectionne l'esclave avec lequel il souhaite communiquer parmi ses multiples sorties Slave Select (SS0, SS1, etc.). Le signal d'horloge (SCLK) est généré par le maître, ce signal sert à cadencer les échanges. Enfin, la broche de la masse ou ground en anglais (GND) est raccordé à une masse commune entre les composants.

Dans le monde de l'embarqué, un reverser ou pentesteur cherchera à dumper la mémoire flash contenant le firmware (bootloader, OS et applications) pour le reverser et aussi extraire les données intéressantes (configuration et autres données sensibles telles que des clefs cryptographiques et mot de passe). 

Il faut donc disposer d'un micro-contrôleur disposant d'un maître SPI que l'on peut configurer et programmer. Le moyen économique pour piloter un échange SPI est d'utiliser un "Bus pirate" de Dangerous Prototype ou une carte Raspberry Pi (RPi). L'article détaille une mise en oeuvre à base de RPi. La Raspberry Pi est construite à partir d'un SoC Broadcom ARM, elle est largement répandue et bénéficie une grande communauté active sur Internet.
Carte Raspberry Pi (RPi)
Carte Raspberry Pi

Déterminer la version matérielle de la RPi

Le postulat est que vous disposiez déjà d'une carte RPi avec la distribution Rapsbian dérivée de Debian.

Les informations du CPU, contenues dans le pseudo file system /proc, donne la version matérielle avec la commande :
pi@rpi ~/spi $ cat /proc/cpuinfo
processor    : 0
model name   : ARMv6-compatible processor rev 7 (v6l)
BogoMIPS     : 2.00
Features     : half thumb fastmult vfp edsp java tls
CPU implementer: 0x41
CPU architecture: 7
CPU variant  : 0x0
CPU part     : 0xb76
CPU revision : 7
Hardware     : BCM2708
Revision     : 000e
Serial       : 000000000b1f65aa

Le champ Revision donne le code de révision du matériel de votre RPi. Le tableau ci-dessous permet d'identifier le modèle de votre carte. Dans notre cas il s'agit du Model B Revision 2.0.

Tableau des versions matérielles de carte Raspberrry Pi (RPi)

La première étape est de réaliser une mise à jour de la distribution Raspbian.
pi@rpi ~ $ sudo apt-get update
pi@rpi ~ $ sudo apt-get upgrade

Dans le fichier de blacklist des modules noyau, décommentez le module SPI spi-bcm2708 afin qu'il soit chargé, puis redémarrez la carte.
pi@rpi ~ $ cat /etc/modprobe.d/raspi-blacklist.conf
# blacklist spi and i2c by default (many users don't need them)
# blacklist spi-bcm2708
blacklist i2c-bcm2708
pi@rpi ~ $ reboot

Après le reboot, il faut charger le module si ce n'est pas déjà fait (vérifier avec la commande lsmod).
pi@rpi ~ $ sudo modprobe spi-bcm2708
pi@rpi ~ $ lsmod |grep spi
spi_bcm2708             6018  0 

Si une erreur apparaît, il faut alors mettre à jour le firmware de la carte RPi pour supporter le protocole SPI sur les GPIO. Le firmware est indépendant du système d'exploitation Raspbian et dépend du SoC.
pi@rpi ~ $ sudo wget http://goo.gl/1BOfJ -O /usr/bin/rpi-update  
pi@rpi ~ $ sudo chmod +x /usr/bin/rpi-update
pi@rpi ~ $ sudo rpi-update
*** Raspberry Pi firmware updater by Hexxeh, enhanced by AndrewS and Dom
*** Performing self-update
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  8107  100  8107    0     0  23898      0 --:--:-- --:--:-- --:--:-- 30708
 *** Relaunching after update
 *** Raspberry Pi firmware updater by Hexxeh, enhanced by AndrewS and Dom
 *** We're running for the first time
 *** Backing up files (this will take a few minutes)
 *** Backing up firmware
 *** Backing up modules 3.18.7+
 *** Downloading specific firmware revision (this will take a few minutes)
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100   168    0   168    0     0    334      0 --:--:-- --:--:-- --:--:--   443
100 44.5M  100 44.5M    0     0   714k      0  0:01:03  0:01:03 --:--:--  902k
 *** Updating firmware
 *** Updating kernel modules
 *** depmod 3.18.10-v7+
 *** depmod 3.18.10+
 *** Updating VideoCore libraries
 *** Using HardFP libraries
 *** Updating SDK
 *** Running ldconfig
 *** Storing current firmware revision
 *** Deleting downloaded files
 *** Syncing changes to disk
 *** If no errors appeared, your firmware was successfully updated to 8751db9fd7138848c29cc55ec05f95c9eea80acb
 *** A reboot is needed to activate the new firmware

Ensuite, il faut modifier la configuration dnas le fichier /boot/config.txt de la carte RPi et ajouter en fin de fichier la directive dtparam=spi=on puis redémarrer.
pi@rpi ~ $ sudo su -
root@rpi:~# echo dtparam=spi=on >> /boot/config.txt
pi@rpi ~ $ sudo reboot

Après redémarrage, il faut charger le module noyau puis vérifier que les pseudo périphériques spidev ont été créés par le module.
pi@rpi ~ $ ls -l /dev/spi*
crw-rw---T 1 root spi 153, 0 janv.  1  1970 /dev/spidev0.0
crw-rw---T 1 root spi 153, 1 janv.  1  1970 /dev/spidev0.1

Vérifier le support du protocole SPI

Pour vérifier le support du protocole SPI sur les GPIO de la carte RPi, il est nécesaire de créer une boucle sur la RPi en connectant la broche MOSI (GPIO 10) à la broche MISO (GPIO9), puis d'exécuter la commande de test spidev_test. Le code source de cette commande est .

Attention, il faut utiliser l'ancien code, sinon il faut substituer "*device = "/dev/spidev1.1"  par "/dev/spidev0.0" :
pi@rpi ~/spi $ gcc spidev_test.c -o spidev_test
pi@rpi ~/spi $ sudo ./spidev_test
spi mode: 0
bits per word: 8
max speed: 500000 Hz (500 KHz)

FF FF FF FF FF FF
40 00 00 00 00 95
FF FF FF FF FF FF
FF FF FF FF FF FF
FF FF FF FF FF FF
DE AD BE EF BA AD
F0 0D

Le mapping des broches GPIO pour une carte RPi de Revision 2 est illustré ci-dessous.
Mapping des GPIO de la carte RAspberry Pi (RPi)
Mapping GPIO RPi B rev 2

Dumper une mémoire flash

Afin de vider le contenu d'une mémoire flash série, il est nécessaire que le packaging du composant possède des broches apparentes (ex: SOIC). Un composant BGA (Ball Grid Array) ne sera pas dumpable avec des moyens artisanaux.
Contact Ball Grid Array (BGA)
Ball Grid Array

Broches apparentes SOIC d'une puce mémoire
Broches apparentes SOIC
Pour connecter une mémoire flash série supportant le protocole SPI, il faut récupérer la datasheet auprès du fabricant pour connaître le brochage de la puce mémoire. Ensuite, deux options se présentent. La première est de déssouder la mémoire flash pour la dumper, l'autre est de positionner une sonde in-situ :
  1. Le déssoudage doit éviter d'endommager la mémoire flash. Cette méthode est invasive car le PCB sera détérioré et inutilisable à moins d'y souder un socket pour remettre en place la mémoire. Attention à la température lors du dessoudage, si celle-ci est trop élevée les pistes métalliques sur le PCB peuvent se dissocier de la carte et rompre la connectivité ! Pour travailler correctement, il faut disposer d'une station de soudage de précision, de panne de qualité et de loupe adaptée. 
  2. La sonde est plus facile à mettre en oeuvre, mais des problèmes de tension peuvent survenir sur la carte empêchant toute capture correcte d'un signal. En effet, en laissant la mémoire flash en place, le courant alimente les composants environnants qui peuvent interférer. Dans ce cas, la seule option est de déssouder le composant.

Une sonde de test à pince (clip) de 16 voies coûte environ 10 $.
Sonde de test à pince (clip probe)
Sonde clip 3M 16 voies
Le cas présenté dans cet article cible le vidage mémoire d'une mémoire flash Spansion SPI à 16 broches. Ce composant est soudé sur le PCB d'un système embarqué multimédia grand public (le modèle n'est pas révélé pour des raisons éthiques). Une photo de la puce mémoire montre la sérigraphie permettant d'identifier le modèle de composant chez le fabricant.


Composant mémoire flash Spansion
Sérigraphie de la mémoire flash Spansion
Voici à quoi ressemble la sonde in-situ connectée à la mémoire flash sur le PCB.


Sonde connecté à la puce mémoire sur le PCB
Sonde connectée sur la mémoire flash sur le PCB
Côté RPi, les GPIO sont reliés aux broches de la sonde avec des straps flexibles.
Les GPIO de la RPI connecté pour le protocole SPI
Broches GPIO sur la RPi
Un analyseur logique Logic Pro Saleae a été utilisé préalablement pour vérifier l'identification des broches de la mémoire flash.


Capture d'échange SPI avec analyseur logique Saleae
Capture d'échange SPI sur la mémoire avec un analyseur logique
Le schéma de connexion est illustré ci-dessous, les broches CE (Chip Enable) correspondent aux broches SS (Slave Select):
Schéma de raccordements RPi et mémoire flash SPI
Schéma de connexion

Flashrom

Flashrom est un logiciel Open Source sous licence GPLv2. Cet utilitaire universel sert à programmer des mémoires Flash (lecture, écriture, détection, effacement) en packaging DIP, PLCC, SOIC, TSOP ou BGA. 

Flashrom supporte les interfaces LPC, FWH et SPI. Il supporte plus de 450 familles de composants de mémoires Flash, 286 chipsets et 450 cartes mères. Malheureusement il n'est pas disponible sur le repository de Raspbian. Il faut donc le télécharger et le compiler sur la carte RPi. Plus d'information ici.


pi@rpi ~ $ mkdir flashrom; cd flashrom/
pi@rpi ~/flashrom $ git clone https://github.com/stefanct/flashrom
pi@rpi ~/flashrom $ sudo apt-get install libpci-dev  pciutils libftdi-dev zlib1g-dev
pi@rpi ~/flashrom $ make
pi@rpi ~/flashrom $ sudo make install
Replacing all version templates with 0.9.8-r1887.
Checking for a C compiler... found.
Target arch is arm
Target OS is Linux
Checking for FTDI support... found.
Checking for FT232H support in libftdi... found.
Checking if Linux SPI headers are present... yes.
Checking for utsname support... found.
mkdir -p /usr/local/sbin
mkdir -p /usr/local/share/man/man8
install -m 0755 flashrom /usr/local/sbin
install -m 0644 flashrom.8 /usr/local/share/man/man8

Flashrom ne supporte pour l'instant que des mémoires jusqu'à 16 Mo en adressage sur 24-bit .Pour des mémoires de plus grande capacité, il faut supporter un adressage 32-bits qui est actuellement non supporté par flashrom. Le passage en mode d'adressage étendu est réalisé en activant un bit dans un registre de configuration puis en utilisant soit des commandes standards, soit des commandes spécifiques, avec des situations variables selon les fabricants.

Flashrom permet de lister les puces mémoire supportées, les modèles de mémoire Spansion supportées sont listées ci-dessous :
pi@rpi ~ $ flashrom -L | grep -i spansion                         
Spansion      S25FL004A                              512  SPI     
Spansion      S25FL008A              PRE            1024  SPI     
Spansion      S25FL016A              PR             2048  SPI     
Spansion      S25FL032A/P            PREW           4096  SPI     
Spansion      S25FL064A/P            PREW           8192  SPI     
Spansion      S25FL204K                              512  SPI     
Spansion      S25FL208K                             1024  SPI     
Spansion      S25FL116K/                            2048  SPI     
Spansion      S25FL132K                             4096  SPI     
Spansion      S25FL164K              PREW           8192  SPI     
Spansion      S25FL127S-64kB         PREW          16384  SPI     
Spansion      S25FL127S-256kB                      16384  SPI     
Spansion      S25FL128P......0                     16384  SPI     
Spansion      S25FL128P......1                     16384  SPI     
Spansion      S25FL128S......0                     16384  SPI     
Spansion      S25FL128S......1                     16384  SPI     
Spansion      S25FL129P......0       PREW          16384  SPI     
Spansion      S25FL129P......1                     16384  SPI      

La datasheet du fabricant permet d'identifier le modèle de composant. Lorsque celui-ci ou un modèle approchant est supporté par flashrom, il suffit de lire la mémoire et de copier le contenu dans un fichier.

Pour réaliser cette étape, nous utilisons l’interface noyau /etc/spidev0.0 (bus 0 et Chip Select 0) pour le type de programmateur linux_spi. La commande ci-dessous effectue une lecture (-r pour read) et écrit le contenu dans le fichier flash128.rom. Elle force (-f) l'usage du profil de chip (-c)  ' S25FL128S......0' :
pi@rpi ~/spi $ flashrom -p linux_spi:dev=/dev/spidev0.0 -r flash128.rom -f -c 'S25FL128S......0'
flashrom v0.9.8-r1887 on Linux 3.18.10+ (armv6l)
flashrom is free software, get the source code at http://www.flashrom.org

Calibrating delay loop... OK.
No EEPROM/flash device found.
Force read (-f -r -c) requested, pretending the chip is there:
Assuming Spansion flash chip "S25FL128S......0" (16384 kB, SPI) on linux_spi.
Please note that forced reads most likely contain garbage.

Reading flash... done.

La taille du fichier flash128.rom est de 16 Mo, il contient le contenu de la flash.


pi@rpi ~/spi $ ls -l flash128.rom

-rw-r--r-- 1 pi pi 16777216 avril  8 12:44 flash128.rom



Conclusion

L'analyse du contenu du dump d'une mémoire flash fera l'objet d'un prochain article traitant du reverse de firmware et de la recherche de clefs cryptographiques. Cependant, jetez un œil sur la recherche de port série ici.

2 commentaires:

  1. J'ai hate de lire l'article sur le reverse de firmware. Je pense que vous utilisez binwalk pour le reverse ?

    RépondreSupprimer
    Réponses
    1. Binwalk est incontournable pour extraire les différents éléments du firmware. Il existe également Hachoir. Ensuite, des outils comme strings sont très utiles. J'utilise aussi Yara avec des règles personnelles pour rechercher des clefs asymétriques. Pour aller plus loin, j'utilise IDA Pro (j'ai une licence Windows) pour du reverse engineering pour analyser le code obfusqué ou la recherche de vulns. Sinon j'utilise aussi radare2 sous Linux. Cela requiert la connaissance des différents jeux d'instructions ASM de CPU de systèmes embarqués : MIPS, ARM, SH4, x86 (retour d'expérience perso).

      Supprimer