Accueil > hack, Linux > Linux is everywhere_PQI AIRCard, partie IV: Flash it !!!

Linux is everywhere_PQI AIRCard, partie IV: Flash it !!!

the_flash Ah, cela faisait bien longtemps que bidouiller de l’embarqué ne m’avait pas autant amener de plaisir.

De nos jours les plateformes ouvertes (cartes ACME , cartes FriendlyArm et bien d’autres…) sont beaucoup plus courantes qu’avant et c’est très bien. Pour autant, pénétrer dans le firmware d’un matériel à priori fermé (et faisant preuve manifeste de GPL violation) cela donne un charme supplémentaire.
Dans les chapitres I, II et III des trois posts précédents, nous avons planté le décor avec la découverte du firmware puis la mise en place d’une liaison série avec le matériel. La porte ouverte à des modifications plus profondes. Alors prêt à flasher votre pqi Air Card, suivez le guide.

A – Etude de la séquence de boot

L’accès à la console série (cf chapitre III) a le gros avantage de pouvoir nous laisser accéder au bootloader de la carte. Lors de la séquence de démarrage, il vous suffira de taper frénétiquement sur une touche, n’importe laquelle pour interrompre la séquence et d’arriver sur une invite de commande. La fenêtre de tir est de 3 secondes après démarrage du bootloader de Keyasic. Celui-ci (KA Boot 04240806 pour son petit nom) réside dans la ROM du SOC. Il fonctionne comme un stage 1 et son rôle est entre-autre d’appeler program.bin (genre stage 2) qui comme nous l’avons vu (cf chapitre I) , est basé sur U-Boot. C’est plutôt une bonne nouvelle pour nos expérimentations. En effet, les chances de « breaker » la carte sont réduites puisque dans son extrême bonté (^w incompétence ?) le constructeur a mis à notre disposition le fameux program.bin (uboot donc) dans son firmware update. Si les choses se passaient mal, on aurait toujours la possibilité de reflasher la carte avec le uboot d’origine en suivant la procédure standard de flashage. Bref cela s’annonce bien.

Une fois arrivé sur l’invite de console de U-Boot, un printenv plantera le décor. Voilà ce que l’on obtient:

KA Boot 04240806
div=9f00
�scu: 11c33303,00000000,00040404,00009f00,1
Status 20200804
Hit to stop : 0  –> interruption de la séquence de boot par appui répété sur une touche<–
KA2000#printenv
bootargs=root=/dev/ram0 rw console=ttyS0,38400n8 mem=30M
bootcmd=run set_bootargs; run bootf
baudrate=38400
console_args=console=ttyS0,38400n8
root_args=root=/dev/ram0 rw
initrd=0x800000,4M
misc_args=mem=30M
set_bootargs=setenv bootargs ${console_args} ${root_args} ${misc_args}
boot_sd=run set_bootargs; mmc init; fatload mmc 1 208000 image2632; fatload mmc 1 600000 initramfs.gz; go 208000
bootcmd=run set_bootargs; run bootf
stdin=serial
stdout=serial
stderr=serial
bootf=mmc init; go 208000
bootdelay=2
ver=U-Boot 2010.06-rc1 (Aug 13 2011 – 00:08:49) on KeyAsic KA2000

Héhéhé, pas mal d’info déjà dans cette commande. Notamment les variables d’environnement bootcmd, bootf et boot_sd.
Les deux premières (bootcmd et bootf) correspondent en fait au démarrage normal de la carte. Par contre boot_sd, semble être un reliquat (encore un !!) de tests de productions et permettrait de booter grâce à la carte SD.

On peut essayer de booter normalement avec un simple go 208000 (0x208000 étant l’adresse en RAM du kernel). Cela marche parfaitement voilà ce que l’on obtient:

KA2000#go 208000
go 208000
(192-96-1)
console [ttyS0] enabled
NET: Registered protocol family 16
cfg80211: Calling CRDA to update world regulatory domain
NET: Registered protocol family 2
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
(….) suite du démarrage de linux
———————————————————-
Production mode-VER. 147_DEC202012_M -Date 20/12/2012
————————————————————
sleep disable
Please press Enter to activate this console.

Bon jusqu’à là tout va bien. Essayons maintenant de booter mais en chargeant nous même en mémoire le noyau et l’ initramfs issus du firmware update. J’ai nommé Image3 pour le kernel et initramfs3.gz pour le RFS. Pour cela, sur le PC hôte, on monte la SD-Card et on copie dessus les deux fichiers en question (pratique ce SOC spécialisé tout de même !!on peut tout faire à la volée sans avoir à enlever la mini-SD de son slot😉 ).

lemoi@T60:~/temp/pqiAIRCard$ mount /media/disk
lemoi@T60:~/temp/pqiAIRCard$ cp initramfs3.gz /media/disk/
lemoi@T60:~/temp/pqiAIRCard$ cp Image3 /media/disk/
lemoi@T60:~/temp/pqiAIRCard$ sync
lemoi@T60:~/temp/pqiAIRCard$ ls -al /media/disk/

drwxr-xr-x 5 lemoi root 8192 14 mars 14:35 .
drwxr-xr-x 5 root root 4096 14 mars 14:34 ..
drwxr-xr-x 4 lemoi root 8192 1 janv. 1980 DCIM
-rwxr-xr-x 1 lemoi root 2664833 14 déc. 07:40 Image3
-rwxr-xr-x 1 lemoi root 2564665 14 mars 14:35 initramfs3.gz
drwxr-xr-x 2 lemoi root 8192 1 janv. 2012 MISC
lemoi@T60:~/temp/pqiAIRCard$umount /media/disk/

Une fois cela fait, on s’assure que U-Boot peut voir les deux fichiers en question à la racine de la SD-Card. Sur le terminal :

KA2000#mmc init
Status 20200804
RCA0 68, RCA1 b3
….
KA2000#fatls mmc 0:1
dcim/
misc/
2564665 initramfs3.gz
2664833 image32 file(s), 2 dir(s)

Bon on va pouvoir maintenant les charger en mémoire. Pour les adresses, on va s’inspirer de la variable d’environnement boot_sd en mettant donc le noyau à 0x208000 et l’initramfs à 0x600000. On essaiera ensuite de booter.

KA2000#mmc init
KA2000#fatload mmc 1 208000 image3  –> vous pouvez remarquer ici que c’est insensible à la casse
..reading image3
……………………………………………………………………………………………………………………………………………………….
2664833 bytes read
KA2000#fatload mmc 1 600000 initramfs3.gz
..reading initramfs3.gz
……………………………………………………………………………………………………………………………………………………….
2564665 bytes read
KA2000#go 208000
go 208000
(192-96-1)
console [ttyS0] enabled
NET: Registered protocol family 16
cfg80211: Calling CRDA to update world regulatory domain
NET: Registered protocol family 2
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
ttyS0 at MMIO 0xa0004000 (irq = 1) is a KA2000
msgmni has been set to 58
loop: module loaded
TCP cubic registered
NET: Registered protocol family 17
lib80211: common routines for IEEE802.11 drivers
Kernel panic – not syncing: No init found. Try passing init= option to kernel.
<–gros FAIL, le noyau boot mais veut pas monter l’image–>

Bon visiblement, le noyau démarre sans problème mais l’initramfs ne veut pas se monter.
Note:
Normalement aveb U-Boot, on ne démarre pas un noyau et un initramfs comme cela. En effet, il existe un utilitaire livré avec U-Boot pour faire des images de démarrage comprenant un entête, un code d’amorçage, le noyau linux et l’initramfs. Il s’agit de mkimage et il est empaqueté pour Debian(paquet uboot-mkimage). Je vous renvoie aux pages de documentions pour connaitre son fonctionnement. Néanmois, ici,  mkimage ne nous sera d’aucune utilité car le bootloader semble avoir été un peu modifié dans son fonctionnement d’origine. 

Dans les variables d’environnement (cf, le printenv du début)  on trouve aussi la variable: initrd=0x800000,4M. Après avoir redémarrer la carte, on peut essayer de dumper la mémoire pour voir si on trouve bien des traces de l’initramfs à l’adresse 0x800000. Sur la console on dumpe les 16 premiers mots à l’adressse 0x800000:

KA2000#md.w 800000 10
00800000: 0000 0000 0000 0000 0000 0000 0000 0000 …………….
00800010: 0000 0000 0000 0000 0000 0000 0000 0000 …………….

Des 0x0000, c’est pas ça, on ne trouvera rien à cette adresse.
Il est peut-être possible que l’initrd soit spécifié en dur dans Image3. Essayons de trouver des traces d’informations dans le binaire:

lemoi@T60:~/temp/pqiAIRCard$ strings Image3 | grep initrd
root=/dev/ram0 rw console=ttyS0,38400n8 mem=32M initrd=0x500000,3M
(…)

Tiens, tiens intéressant !! 0x500000. Essayons sur la carte de dumper la mémoire à cette adresse pour voir:

KA2000#md.w 500000 10
00500000: 414b 5a47 2700 3122 8b1f 0008 a193 50d2                KAGZ.' »1…….P
00500010: 0300 5bdc 747f 5554 bf7e 326f c309 e830                 …[.tTU~.o2..0.

Bingo !! c’est bien ça. On retrouve là l’en-tête « KAGZ… » particulière de l’initramfs (cf chapitre I). Maintenant qu’on connait l’adresse exacte on peut essayer à nouveau de booter manuellement. Sur la console:

KA2000# mmc init
Status 20200804
RCA0 68, RCA1 b3
….reading program.bin
KA2000#fatload mmc 1 500000 initramfs3.gz
..reading initramfs3.gz
……………………………………………………………………………………………………………………………………………………….
2564665 bytes read
KA2000#go 208000
(192-96-1)
console [ttyS0] enabled
NET: Registered protocol family 16
cfg80211: Calling CRDA to update world regulatory domain
NET: Registered protocol family 2
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
(….) suite du démarrage de linux
(…)
———————————————————-
Production mode-VER. 147_DEC202012_M -Date 20/12/2012
————————————————————
Please press Enter to activate this console.

Super !!! on peut donc charger à la volée des images intramfs et tenter le démarrage sans avoir à flasher la carte. C’est pratique pour les tests et cela ira ainsi beaucoup plus vite. En parlant de vitesse, il pourra être un peu fastidieux à terme d’utiliser les commandes mmc init, fatload etc … mentionnées plus haut. On va donc déjà commencer à modifier notre environnement de travail en définissant notre propre script de test dans U-Boot. Sur la console:

KA2000# setenv test   ‘set_bootargs; mmc init; fatload mmc 1 500000 initramfs3.gz; go 208000’
KA2000# saveenv test

Avec saveenv, la variable test sera stocké durablement et il suffira de faire un run test pour booter directement sur les images initramfs3.gz placées à la racine de la SD-Card. L’environnement de développement s’en trouve facilité.
Note:
dans le script de test, il n’est pas fait mention du chargement du noyau à l’adresse 0x208000, celui-ci s’y trouvant déjà grâce à l’intervention de program.bin. Les principales altérations du firmware se feront sur le root file système et non sur le noyau.
.
B – On s’amuse un peu ?

J’avais déjà identifié dans le chapitre I, le constructeur du SOC: KeyAsic. En fait , ce sont eux les véritables concepteurs du système. La société pqi intervient ici comme une sorte d’intégrateur pour le produit final et cela explique pas mal de chose (nous en reparlerons plus tard).

Il existe un produit concurrent à la pqi AirCard, c’est la Flucard . En cherchant sur le net, j’ai trouvé un blog en Japonais (merci GoogleTranslate) qui en parle.  Le Blogger, s’intéresse lui aussi à l’analyse du firmware Flucard qui présente des similarités vraiment troublantes avec celui de pqi (même en-tête de initramfs.gz  notamment). En lisant son blog, j’étais quand même bien content de voir que ses investigations en restaient au stade d’une simple connexion telnet donc j’ai largement de l’avance sur le hack de la carte (France 1 – Japan 0  ).

En analysant les scripts cgi  perl du firmware, j’ai même trouvé des commentaires en rapport avec la Fluecard !!). Bref, fluecard est lui-aussi un intégrateur de ces SOCS. Peut être même que Fluecard et Pqi ont un rapport commercial ? Qu’importe.

Ce qui m’intéresse dans un premier temps c’est de vérifier si on peut faire tourner un initramfs différent de celui d’origine sur la pqiAircard. On va donc mélanger les genres: un noyau pqi et un RFS flucard !! Outre le fait d’être amusant, on pourra aussi vérifier si oui on non le root file system est protégé par une signature cryptographique quelconque.

Le firmware de Flucard propose deux noyaux: image, image3 ; et deux RFS: intramfs.gz et initramfs3.gz. Prenons au hasard le initramfs3.gz de Flucard et plaçons le sur la SD-Card avant de booter dessus grâce à run test. Sur la console:

KA2000#run test
Status 20200804
RCA0 68, RCA1 b3
….reading program.bin
…..reading initramfs3.gz
……………………………………………………………………………………………………………………………………………………….
2619629 bytes read
KA200# go 208000
(192-96-1)
console [ttyS0] enabled
NET: Registered protocol family 16
cfg80211: Calling CRDA to update world regulatory domain
NET: Registered protocol family 2
TCP: Hash tables configured (established 1024 bind 1024)
TCP reno registered
ttyS0 at MMIO 0xa0004000 (irq = 1) is a KA2000
msgmni has been set to 58
loop: module loaded
TCP cubic registered
NET: Registered protocol family 17
lib80211: common routines for IEEE802.11 drivers
starting pid 27, tty ‘/dev/console’: ‘/etc/init.d/rcS’
(0>0)switch_modules
init bomb irq
Bypass Flag En=0
req irq 40 (1010000)
req irq 43 (40)
req irq 41 (43)
ka_sdhc_drv_init
0328a Hello console …
bw = 2
mmc0: new SDHC card at address b368
mmcblk0: mmc0:b368 CAR 14.9 GiB
mmcblk0:bootsec @ 20
p1 p2
FAT sec 20 sz 2800 #2 rtdir 5020 csz 10
Can not read config.trek
cp: can’t stat ‘/mnt/mtd/tem.txt’: No such file or directory
start httpd
this is power up app
flu app, call interval 0       <– héhé, c’est marrant la fluapp
flu_app: can’t stat ‘/mnt/mtd/config/config.JPG’: No such file or directory
flu_app: can’t stat ‘/mnt/mtd/config/upload.JPG’: No such file or directory
flu_app: can’t stat ‘/mnt/mtd/config/receiver_control.JPG’: No such file or directory
flu_app: can’t stat ‘/mnt/mtd/config/sender_control.JPG’: No such file or directory
<–oui c’est sûr on a pas mis les fichiers de conf !! –>
umount
FAT sec 20 sz 2800 #2 rtdir 5020 csz 10
disable motion irq
cannot open /dev/gpio_i2c to access motion sensor iic
flu_app: can’t stat ‘/mnt/mtd/config/config.JPG’: No such file or directory
flu_app: can’t stat ‘/mnt/mtd/config/upload.JPG’: No such file or directory
flu_app: can’t stat ‘/mnt/mtd/config/receiver_control.JPG’: No such file or directory
flu_app: can’t stat ‘/mnt/mtd/config/sender_control.JPG’: No such file or directory
umount
FAT sec 20 sz 2800 #2 rtdir 5020 csz 10
uAp start
sdio wakeup
mlan: module license ‘Marvell Proprietary’ taints kernel.
mmc1: new SDIO card at address 0001
Disabling lock debugging due to kernel taint
Can not read config.trek
Can not read config.trek
name = Auto Start Wifi value = uap
Segmentation fault
rcS donePleasepress Enter to activate this console. <— Applaudissez maintenant
# ls /mnt/sd/DCIM/    
123_TREK 199_WIFI  <–le firmware a créé un répertoire 123_TREK dans DCIM

Mise à part quelques plaintes bien normales (notamment les absences de fichier de conf stockés dans la partition jjfs2) on voit que ca marche plutôt pas mal non ? Et la bonne nouvelle dans tout ça c’est que visiblement Pqi n’a pas protégé l’intégrité de leur initramfs puisque un autre RFS peut y tourner dessus.

Tant qu’on y est, continuons dans l’espièglerie et faisons booter un noyau Flucard sur l’initrd de la pqi. On copie le image3 de flucard sur la SD-Card,  on le charge en mémoire et on boote. Sur la console:

KA2000#run set_bootargs
KA2000#mmc init
Status 20200804
RCA0 68, RCA1 b3
….reading program.bin
KA2000#fatload mmc 1 208000 image3
..reading image3
……………………………………………………………………………………………………………………………………………………….
2853952 bytes read
KA2000#go 208000
starting pid 27, tty ‘/dev/console’: ‘/etc/init.d/rcS’
KeyASIC WifiSD console …
Sun Jan 1 00:00:00 UTC 2012
wsd to sd
wsd to sd
cp softmac to lib/
set pid 53
this is kcard startup app
kcard app, call interval 10
KCARD_DISABLE_POWER_MGMT
Finding: »Auto WiFi Mode »: Got: « Enable »
default wifi on
start boa
rcS done
..setup AP mode start
[01/Jan/2012:00:00:02 +0000] buzzer
boa: server version Boa/0.94.14rc21
[01/Jan/2012:00:00:02 +0000] boa: server built Dec 19 2012 at 17:13:38.
[01/Jan/2012:00:00:02 +0000] boa: starting server pid=72, port 80
ifconfig: SIOCGIFFLAGS: No such device <– petit problème avec le driver Wifi
lo no wireless extensions.ifconfig: SIOCGIFFLAGS: No such device
———————————————————-
Production mode-VER. 147_DEC202012_M -Date 20/12/2012
————————————————————
sleep disablePlease press Enter to activate this console.

Donc mise à part le problème de driver pour le wifi on a un système pleinement fonctionnel. En injectant le module wifi de la Flucard (dans RFS/lib/ar6000.ko) on devrait peut-être même retrouver un système complet.
Bon c’est bien rigolo tout ça et c’est vraiment de bonne augure. On va donc pouvoir commencer à charger nos propres initramfs modifiées.
.
C – firmware personnalisé:

La modification de l’initramfs originale suivra cette logique:
– suppression de l’entête du fichier original
– désarchivage de l’archive gunzip et cpio
– modification du système racine
– Réarchivage gz + cpio
– Reconstruction de l’en-tête
Pour la supression de l’en-tête, nous avons vu qu’il fallait enlever ses 8 premiers octets. La commande suivante sera beaucoup plus rapide que le dd vu au chapitre I:

lemoi@T60:/tmp$ tail -c+9 initramfs3.gz > RFS.cpio.gz
<–Beaucoup plus rapide que dd if=initramfs3.gz of=RFS.cpio.gz bs=1 skip=8 –>
<–On désarchive le gz en maintenant le fichier original–>
lemoi@T60:/tmp$ gunzip -c RFS.cpio.gz > RFS_orig.cpio
<–On examine l’archive obtenue: –>
lemoi@T60:/tmp$ file RFS_orig.cpio
RFS_orig.cpio: ASCII cpio archive (SVR4 with no CRC)

Arrêtons-nous quelques instants sur le désarchivage du cpio car il faut voir quelques subtilités.
Si vous essayez de désarchiver le cpio sans privilège particulier voilà ce que vous obtenez:

lemoi@T60:/tmp$ mkdir RFS_orig
lemoi@T60:/tmp$ cd RFS_orig/
lemoi@T60:/tmp/RFS_orig$ cpio -i <../RFS_orig.cpio
cpio: dev/fb0: échec de la fonction : mknod: Opération non permise
cpio: dev/mmc1: échec de la fonction : mknod: Opération non permise
cpio: dev/ttyS: échec de la fonction : mknod: Opération non permise
cpio: dev/tty0: échec de la fonction : mknod: Opération non permise
(…) < — messages d’erreurs identiques –>
cpio: dev/mtd0: échec de la fonction : mknod: Opération non permise
cpio: dev/tty1: échec de la fonction : mknod: Opération non permise
cpio: dev/mmcblk0p2: échec de la fonction : mknod: Opération non permise
10518 blocs

Ces messages d’erreurs sont normaux car les fichiers sous le répertoire /dev sont spéciaux et résultent de la création en mode bloc ou caractère de fichiers de périphériques grâce à la commande mknod (cf man mknod). La préservation des attributs complets de ces fichiers est fondamentale pour l’obtention d’une initramfs fonctionnelle.
Une des solutions est de se logger en #root puis de désarchiver. Par contre, l’inconvénient de cette méthode est que tous les fichiers ainsi désarchivés se trouvent affublées des droits root. Aussi, pour la modification de l’image il faudra obligatoirement opérer en tant que #root. C’est une solution vraiment dangereuse et peu recommandée. En effet, imaginez un peu l’impact de la commande #rm /bin alors que on voulait faire un simple #rm ./bin. Jamais un simple « . » n’aura eu autant d’importance !!!
Pour éviter cela, il existe la commande fakeroot (cf man fakeroot) qui permet le temps d’une commande ou le temps d’un shell de duper les droits d’administrateur (mais uniquement pour les fichiers que l’on va créer). C’est très pratique et cela permet de travailler sans risque sur notre PC hôte (c’est d’ailleurs la technique utilisée pour l’empaquetage des paquets debian). Pour autant, il faudra prendre quand même quelques précautions. Examinons par exemple la manipulation suivante:

<–On lance un shell fakeroot–>
lemoi@T60:/tmp$ fakeroot
<–On crée un périphérique de type caractère comme celui contenu dans l’initramfs–>
root@T60:/tmp# mknod ttyS0 c 4
<–On vérifie–>
root@T60:/tmp# ls -al ttyS0
crw-r–r– 1 root root 4, 64 16 mars 14:54 ttyS0
<–on sort de la session fakeroot–>
root@T60:/tmp#exit
<–On vérifie:–>
lemoi@T60:/tmp$ls -al ttyS0
-rw-r–r– 1 lemoi lemoi 0 16 mars 14:54 ttyS0
<–On relance la session fakeroot–>
lemoi@T60:/tmp$fakeroot
<–On vérifie–>
root@T60:/tmp# ls -al ttyS0
-rw-r–r– 1 root root 0 16 mars 14:54 ttyS0  <–Dommage c’est devenu un fichier normal !!

Il ressort de ce qui précède la chose suivante:
L’extraction de l’archive cpio devra se faire préférablement grâce à un shell obtenu grâce à fakeroot. Les modifications du système de fichier initramfs puis son réarchivage devront obligatoirement se faire sous le même shell sous peine de perdre les attributs particuliers des fichiers de périphériques contenus dans /dev. Sans cette précaution, l‘initramfs obtenu ne vous permettrait pas de booter.

Sinon pas de problème particulier pour reconstruire l’archive si ce n’est que cpio devra utiliser en sortie l’option -H newc  (cf man cpio) pour le nouveau format portable SVR4 ( voir un peu plus haut la sortie de la commande file RFS_orig.cpio)

La reconstruction de l’en-tête du fichier initramfs3.gz devra contenir « KAGZ« + 4 octets représentant la taille de l’archive compressée initramfs (RFS.cpio.gz pour garder la dénomination de ce qui précède). La subtilité est la façon dont sont stockés ces 4 octets. Exemple:

lemoi@T60:/tmp$ hexdump initramfs3.gz | more
0000000 414b 5a47 2700 3122 8b1f 0008 a193 50d2
(…)
lemoi@T60:/tmp$ls -l RFS.cpio.gz
-rw-r–r– 1 lemoi lemoi 2564657 16 mars 10:21 RFS.cpio.gz
<– on convertit 2564657 en hexa –>
lemoi@T60:/tmp$ python
Python 2.6.6 (r266:84292, Dec 27 2010, 00:02:40)
>>>hex(2564657)
‘0x00272231’
^D

Si vous essayez de rentrer la valeur 0x00272231 avec un programme dans un fichier, voila comme elle apparaîtra stockée sur le fichier du PC hôte: 0x22310027 (ahh les joies de l’endianess !!!). Aussi je m’en sors avec un petit code C que je vous propose ci-dessous et qui utilise la fonction htonl (man 3 htonl) prédestinée à la programmation réseau (où dès lors qu’on parle avec des sockets, il faut se mettre en verlan). Le programme prends en premier paramètre la taille de l’archive (en décimal) et en deuxième paramètre le nom du fichier en-tête à créer:

#include <stdio.h>
#include <stdlib.h>
#include <arpa/inet.h>
int main (int argc, char *argv[]){
long hexval;
long swap_hexval;
char * hexend;
char *header="KAGZ";
FILE * fd;
if((fd=fopen(argv[2], "wb")) == NULL) {
printf("Cannot open file.\n");
exit(1);
}
hexval = strtol(argv[1], &hexend , 10);
swap_hexval=htonl(hexval);
fprintf(fd,"%s",header);
fwrite( &swap_hexval,sizeof(swap_hexval),1,fd);
fclose(fd);
return 0;
}

J’ai confectionné des scripts pour automatiser le désarchivage et le réarchivage des images initramfs (le réarchivage utilise donc le programme C mentionné ci-dessus). Je vous propose leur téléchargement ici. Le script rfsarchive.sh vérifiera aussi que l’archive produite ne dépasse pas la taille de 3 Mo (nous verrons plus tard pourquoi).
Vous devrez au préalable compiler le programme C (qui se trouve aussi dans l’archive) pour leur fonctionnement (avec un gcc headermake.c -o headermake) puis placer ce programme dans votre répertoire de travail.
Afin de ne pas risquer d’écraser les différents répertoires de vos tests, les scripts vous proposeront un nom aléatoire pour vos sytème de fichiers racines et/ou vos archives compressées finales. Enfin, vu les explications précédentes, les scripts devront être exécuter sous un shell fakeroot.
Fort de ces petits ajustements, essayons donc de construire une nouvelle image de système de fichier. Nous utiliserons les scripts mentionnés afin de montrer leur fonctionnement.

Pour notre première modification, nous allons tenter la chose suivante:
Je vais partitionner la SD-Card afin de faire apparaître deux partitions (je ne détaille pas cette étape). Ensuite nous allons créer un deuxième répertoire de montage dans le système de fichier racine puis modifier le fichier /etc/fsatb afin que cette deuxème partition se monte facilement. On travaillera donc sur le initramfs3.gz d’origine livré par Pqi.

lemoi@T60:/tmp$ fakeroot
root@T60:/tmp# rfsextract.sh initramfs3.gz
find correct header KAGZ in initramfs3.gz file, program start…
By default, RFS folder will be RFS-QtnuBCRNnh proceed ? Y [n]
10518 blocs
Job done
root@T60:/tmp# cd RFS-QtnuBCRNnh/
root@T60:/tmp/RFS-QtnuBCRNnh# ls -l ./mnt/
total 8
drwxrwxrwx 2 root root 4096 16 mars 19:27 mtd
drwxrwxrwx 2 root root 4096 16 mars 19:27 sd
root@T60:/tmp/RFS-QtnuBCRNnh# mkdir ./mnt/sd2
root@T60:/tmp/RFS-QtnuBCRNnh# cat ./etc/fstab
#/dev/root / auto defaults,errors=remount-ro 0 0
#none /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
/dev/mmcblk0p1 /mnt/sd vfat defaults 1 1
root@T60:/tmp/RFS-QtnuBCRNnh# vim ./etc/fstab  <– on édite le fichier
root@T60:/tmp/RFS-QtnuBCRNnh# cat ./etc/fstab
#/dev/root / auto defaults,errors=remount-ro 0 0
#none /proc proc defaults 0 0
none /dev/pts devpts mode=0622 0 0
/dev/mmcblk0p1 /mnt/sd vfat defaults 1 1
/dev/mmcblk0p2 /mnt/sd2 vfat defaults 1 1  <– voici la ligne rajoutée
root@T60:/tmp/RFS-QtnuBCRNnh# cd ..
root@T60:/tmp# rfsarchive.sh RFS-QtnuBCRNnh/
By default, initrfs file will be initramfs3-RFS-QtnuBCRNnh.gz proceed ? Y [n] <– je veux personnaliser le nom donc [n]
please enter initrfs file name
initramfs3_lemoi.gz
10518 blocs
root@T60:/tmp# exit
exit
<– Tiens d’ailleurs au passage : 
On a rajouté des trucs et l’image est plus petite c’est pas beau ça ?–>
lemoi@T60:/tmp$ ls -al initramfs3*
-rwxr-xr-x 1 lemoi lemoi 2564665 16 mars 19:20 initramfs3.gz
-rw-r–r– 1 lemoi lemoi 2562794 16 mars 19:29 initramfs3_lemoi.gz
<–On copie l’initramfs dans la SD-Card–>
lemoi@T60:/tmp$ cp initramfs3_lemoi.gz    /media/disk/initramfs3.gz
lemoi@T60:/tmp$ sync

Une fois cela fait sur la console en accédant à U-Boot:

KA2000#run test
reading initramfs3.gz ………………………………………..
2562794 bytes read go 208000 (192-96-1)
<–déroulement normal du boot –>
———————————————————-
Production mode-VER. 147_DEC202012_M -Date 20/12/2012
————————————————————
sleep disable
Please press Enter to activate this console.
# ls /mnt/
mtd sd sd2  <– héhé, pas mal
# mount /mnt/sd2/
# df -h
Filesystem Size Used Available Use% Mounted on
/dev/mtdblock0 1.0M 196.0K 828.0K 19% /mnt/mtd
/dev/mmcblk0p1 10.0G 5.4M 10.0G 0% /mnt/sd
/dev/mmcblk0p2 4.9G 1.3G 3.6G 27% /mnt/sd2
#  <– Applaudir maintenant

.
D – Assez rigolé maintenant on flashe pour de vrai !!

Donc maintenant que nous avons notre nouveau intramfs nous allons essayer de le flasher pour qu’il réside de façon permanente dans la mémoire flash de la carte. Pour cela, et conformément au manuel Start_Guide_Firmware_Update du constructeur, nous avons besoin de placer à la racine de la permière partion de la carte les fichiers suivants:
program.bin
Image3
mtd_jffs2.bin
initramfs3.gz (le nouveau,  celui modifié on est bien d’accord …)
autoload.tbl (tiens on en a pas encore parlé de lui !!)

Puis on reboote la carte et on observe ce qui ce passe. Voilà un dump de la console:

KA Boot 04240806
div=9f00
�scu: 11c33303,00000000,00040404,00009f00,1
Status 20200804Hit to stop : 2 1 0
Status 20200804
RCA0 68, RCA1 b3
….reading program.bin
……………………………go E00000pre: 11c33303,00000000,00040404,00009f00,1 (PLL 192MHz, div=9f00)
post:11c33303,00000000,00040404,00009f00,1
Status 20200804
****** Program Mode (GEN3) ******
RCA0 68, RCA1 b3
….reading autoload.tbl
……found autoload.tbl, start program.
1024 bytes read
..00003000: 00000000 00000000 00000000 00000000 …………….
00003010: 0100414b 02350000 330b2610 00020402 KA….5..&.3….
00003020: 06080200 00003203 00000000 00103000 …..2…….0..
00003030: 00040020 00000000 00000000 00000000 ……………
reading delchain.dis
…enable delay chain
00001000: 00000000 00000000 00000000 00000000 …………….
00001010: 0100414b 02350000 330b2610 00020402 KA….5..&.3….
00001020: 06080200 00003203 00000000 00103000 …..2…….0..
00001030: 00040020 00000000 00000000 00000000 ……………
..00003000: 00000000 00000300 00000000 00000000 …………….
00003010: 0100414b 02350000 330b2610 00020402 KA….5..&.3….
00003020: 06080200 00003203 00000000 00103000 …..2…….0..
00003030: 00040020 00000000 00000000 00000000 ……………
reading image3
……reading preprog_chk.bin
…found image3, start program.
..reading image3
……………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………..
2664833 bytes read
……………………………………………………………………………………………..reading initramfs3.gz
……found initramfs3.gz, start program.
..reading initramfs3.gz
………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………………..
2562794 bytes read
……………………………………………………………………………………………..reading mtd_jffs2.bin
……found mtd_jffs2.bin, start program.
..reading mtd_jffs2.bin
……………………………………………………………………………………………………………………………………………………………………………………………………………………………………..
1048576 bytes read
……………………………….<– à partir d’ici la carte reboote toute seule –><– puis repart sur un démarrage normal donc j’abrège un peu …->
———————————————————-
Production mode-VER. 147_DEC202012_M -Date 20/12/2012
————————————————————
sleep disable
Please press Enter to activate this console
# ls /mnt/
mtd sd sd2
# mount /mnt/sd2
# df -h
Filesystem Size Used Available Use% Mounted on
/dev/mtdblock0 1.0M 196.0K 828.0K 19% /mnt/mtd
/dev/mmcblk0p1 10.0G 456.0K 10.0G 0% /mnt/sd
/dev/mmcblk0p2 4.9G 1.3G 3.6G 27% /mnt/sd2  <– applaudir maintenant
# ls /mnt/sd
DCIM MISC   <– on voit que les fichiers placés à la racine ont disparus

Voilà tout c’est bien passé🙂
La porte est donc ouverte aux firmwares personnalisés. Une petite chose encore non résolue. C’est la fonction du fichier autoboot.tbl et des octets qui le peuple. C’est surtout dans un intérêt didactique car nous l’avons vu, nous pouvons faire désormais un peu ce que nous voulons de la carte. Surtout qu’il n’est pas forcément utile d’optimiser la place allouée au système de fichier vu que nous disposons des énormes ressources de la carte SD .

Donc pour ceux intéressés par l’énigme, voilà quelques pistes à creuser:

L’étude des strings de program.bin montre une différence entre les zones d’écriture en mémoire ram et flash entre ce qui est écrit en dur dans le programme et ce qui passe lors du flashage. C’est je pense en rapport avec le programme delchain.dis que l’on voit appraître dans le log ci-dessus. De plus, delchain.dis semble en rapport avec autload.tbl.
Une manière de procéder serait d’utiliser la commande sf read de U-Boot puis de dumper la Ram avec des memory dump (md). Enfin, les logs de la console couplés avec quelques commandes awk permettraient de reconstruire le programme delchain.dis  afin d’essayer de voir comment il fonctionne.
note:
Sur cette version U-Boot modifiée, il ne semble pas y avoir de moyen d’écrire les dumps mémoires directement sur la SD-Card. 
.
E- Des programmeurs Yaourt

Nous avons bien avancé dans l’étude de la carte. C’est sûr, le travail nous a été facilité par le manque de protections de la part du concepteur. Listons ici les différents éléments ayant permis les découvertes et essayons de voir les mesures possibles qui auraient pu être prises

1> Le firmware update fait clairement apparaître les éléments d’un système linux embarqué (image, initramfs3, mtd.jffs2 ect…). N’était-il pas possible au moins de changer les noms,  voir de regrouper les données au sein d’un unique fichier un peu plus opaque?

2> Les outils utiles à la phase de conception (Serveur Telnet, Serveur Ftp) restent toujours actifs dans la version production. N’était-il pas possible de les désactiver dans les scripts d’ Init ? (ça prends 3 secondes de commenter la ligne)

3> La console Série est clairement identifiée dans la sérigraphie du CI. Pas possible d’effacer ?

4> Le kernel crache vers ttyS0. Pas compliquer d’éviter ça

5> Pas de signature crypto de l’initramfs …

Bref, et j’en passe. Mais attention, ne vous méprenez pas. Je suis au contraire très content que cela soit finalement aussi simple. Je veux juste amener un point de réflexion qui me semble important d’être souligné.

Comme expliqué précédemment, les véritables concepteurs du système ce sont en fait les fabricants du SOC: Keyasic. Quand on a la capacité technique de produire un SOC on peut sans problème sécuriser les points évoqués ci-dessus. Oui mais voilà; est-il vraiment dans l’intérêt de Keyasic de le faire ? je ne pense pas non. Il ont tout intérêt à laisser leur matériel le plus ouvert possible (objectif: diffuser le matériel).
Derrière tout ça arrive des intégrateurs comme Pqi ou Flucard. Eux, ce sont ce que j’appelle des Yaourthières qui nous font du beau code yaourth. Un peu de de Bash quand ils sont obligés,  un peu de cgi Perl mais encore c’est parce que PhP ça marchait pas sur la carte. Et puis c’est tout. Le bas niveau, le kernel, les modules, le boot, le système de fichier c’est pas eux. Ils ne maîtrisent pas, c’est tout.
Et c’est très bien tout ça; continuez,  continuez braves gens… L’avenir s’annonce radieux.  Belle revanche pour nous, aficionado de la première heure non ?

Pour ma part je vous donne rendez-vous bientôt. On continuera à habiller la pqi Air Card avec son nouvel habit de printemps. Ca parlera de cross compilation (entre autre …)

  1. mars 18, 2013 à 3:10

    Pendant ce temps là au Japon:
    French people are quite deep analysis on the PQI Air Card
    I mess around from the stage of boot »
    @osakanataro

  2. mars 20, 2013 à 8:24

    Vraiment intéressant, j’apprends pleins de trucs!
    Un autre firmware sur le même SOC : http://fr.transcend-info.com/support/dlcenter/Driver/WiFiSD_v1.6.zip

  3. avril 4, 2013 à 11:09

    Salut,
    Très intéressant tout ça…
    J’ai commencé une étude similaire sur la carte SDHC transcend dont parle glandais.
    Je pense que tous ces articles vont me permettre de hacker convenablement ma carte.
    http://colas.sebastien.free.fr/index.php/category/transcend-sdhc-wifi/
    La carte de transcend est un peu mieux sécurisée, pas de ftp, pas de telnet.

  4. avril 20, 2013 à 5:33

    Transcend a publié les sources de sa carte on dirait, bon point non?

  5. Kazu
    mai 20, 2013 à 10:24

    Dear all,
    I am visit from Japan. Thank you very for your good report. I hope your deeply hack on the AirCard.
    I was contact to PQI Japan sales office last week. PQI they are use GPL. Therefore, PQI have to open source code.
    If they open the source code, i can send to you.
    I already install Busybox in MMC of Aircard and used it.
    I am sorry can not speak and read french.
    Best regards.

  6. août 8, 2013 à 9:06

    Malheureusement, j’ai perdu mon premier commentaire suite à une mauvaise connection à WordPress. Je vais donc être plus concis: j’ai acquis récemment une de ces cartes, après avoir lu qu’elle faisait tourner Linux.
    J’en suis très satisfait, mais il me manque une fonction comme celle de mon smartphone, c’est à dire quelque chose qui redimensionne et envoie les photos directement sur google plus quand je suis à proximité de mon réseau wifi.
    À la vue de vos découvertes, pensez vous qu’il serait possible de faire tourner en tâche de fond un script qui redimensionne ( avec ImageMagick, mais comment l’installer ? Sur ARM ?) et envoie sur Google + ( avec GoogleCl, même problématique que plus haut ? Plus comment s’authentifier ? Navigateur en mode texte, Lynks ? ) les nouvelles photos au moment où la carte se connecterait au réseau de la maison ?
    Si vous pouviez perdre un instant pour y penser, je vous en serais fort reconnaissant !
    Louis

    • août 9, 2013 à 2:01

      Bonjour,
      la carte SD permet nombre de bidouilles car on n’est pas limité en terme de place (contrairement à un système embarqué tradionnel).
      Seul le CPU est un peu limite pour faire tourner du imagemagick à mon avis mais bon à essayer…
      Sinon pas de difficulté majeure pour imagemagick pour ARM il suffit de cross compiler (en static par contre).
      Google permet via Googlecl d’accéder à certaines API dont celle pour les images.
      https://developers.google.com/gdata/docs/directory?hl=fr&csw=1
      Ces API sont portés dans différent langages dont Python. Il faudrait donc pour cela faire tourner python sur la carte.
      Pas de difficulté pour cela. Cross compilation (idem en static) ou bien utiliser directement un binaire précompilé pour ARM.
      En prendre un déjà tout fait pour android par exemple (méthode sale mais rapide).
      Sinon peut être un peu dommage d’embarquer toute cette usine à gaz dans la carte.
      J’ai pour ma part fait des firmwares perso bien pratiques avec du rsync embarqué sur la carte.
      Vu que de toute façon il vous faut la proximité de votre réseau pour que cela fonctionne autant minimiser le temps
      de transfert entre la carte et le réseau puis utiliser ensuite la puissance d’une machine (routeur perso, serveur, PC qui reste souvent allumé etc …) pour faire les tâches de plus haut niveau que vous décrivez.
      Cdt

  7. Marco77
    août 12, 2013 à 7:52

    Salut à tous,
    J’arrive en provenance d’un lien en commentaire sur un article faisant la une de HD, qui parle d’une carte wifi transcend sur laquelle le soft embarqué contient des failles à foison dans le userland (directory traversal, remote execution etc.).
    J’ai suivi avec grand intérêt cette série de billets, d’ailleurs plutôt portée sur la partie boot d’un firmware custom.

    Cela dit, tout ce que vous publiez n’est guère rassurant, comme de savoir que ce mini système est un point d’accès ouvert où n’importe quel péquin peut venir choper vos données (photos) et en plus, un tas de ports est gentiment ouvert au niveau réseau !? Un simple telnet donnant semble-t-il un shell root ???
    A se demander si c’est de l’incompétence ou de la malveillance…

  8. août 20, 2013 à 5:10

    Bonjour,
    Je me permet de citer et de traduire certaines parties de ton travail sur https://forum.openwrt.org/viewtopic.php?id=45820
    Merci de me le signaler si ce n’est pas convenable.

  9. août 2, 2014 à 3:35

    Automatica is a USB memory stick with built in WiFi. You can plug it into your car audio USB to play the audio files using the car music controls. Whenever Automatica is able to connect to the Internet, your content is updated from the cloud and kept on the USB flash memory. You can always play your sync’d content from the flash drive, even when you have no internet connection.

    Is there someone out there that hack the Transcend to make it work like the Automatica? That is, connect to the cloud on boot and sync the Transcend files that are stored on the cloud? (Dropbox or similar?)

    Most recent cars have USB audio ports, some have SD audio ports, or maybe a Transcend SD could be used with a SD to USB device.

    Here’s a picture and description of the Automatica
    https://automaticaweb.com/

    A discussion about what I’d like to do
    https://forum.openwrt.org/viewtopic.php?pid=232898#p232898

    Activating the semi built-in telnet and ftp deamons on a Transcend WiFi SD card
    http://www.ad001.de/transcend-wifi-ftpd.html

    Original Hack Blog
    http://haxit.blogspot.com/2013/08/hacking-transcend-wifi-sd-cards.html

    Can anyone take on the project to make a transend automatically sync (download) from a cloud folder?

    chuck(at)etusa.com

  10. décembre 28, 2014 à 11:50

    Très intéressante cette série d’article. J’ai quelques questions sur le fonctionnement en tant que SD Card classique :
    – est-ce le noyau linux qui gère ça ? une puce dédiée (comme sur la carte Transcend) ?
    – peut-on écrire sur la micro SD sans risque de corruption ? Sur la carte Transcend, la lecture fonctionne mais pas l’écriture.

    Mon but serait le suivant : la carte SD récupère diverses notifications depuis le réseau, génère une image (ou télécharge directement l’image, c’est pareil), la dépose dans l’espace de stockage visible depuis l’extérieur, éventuellement en démontant / remontant cet espace (comme si on débranchait / rebranchait la carte SD) avant de rajouter l’image. Ainsi je pourrais recycler un vieux cadre photo pour afficher mes notifications.

  1. No trackbacks yet.

Laisser un commentaire

Entrez vos coordonnées ci-dessous ou cliquez sur une icône pour vous connecter:

Logo WordPress.com

Vous commentez à l'aide de votre compte WordPress.com. Déconnexion / Changer )

Image Twitter

Vous commentez à l'aide de votre compte Twitter. Déconnexion / Changer )

Photo Facebook

Vous commentez à l'aide de votre compte Facebook. Déconnexion / Changer )

Photo Google+

Vous commentez à l'aide de votre compte Google+. Déconnexion / Changer )

Connexion à %s

%d blogueurs aiment cette page :