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.
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 |
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.
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 là.
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 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.Ball Grid Array |
Broches apparentes SOIC |
- 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.
- 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 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.
Sérigraphie de la mémoire flash Spansion |
Sonde connectée sur la mémoire flash sur le PCB |
Broches GPIO sur la RPi |
Capture d'échange SPI sur la mémoire avec un analyseur logique |
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
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
J'ai hate de lire l'article sur le reverse de firmware. Je pense que vous utilisez binwalk pour le reverse ?
RépondreSupprimerBinwalk 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