
Dans cette session d'atelier, nous extrairons le firmware d'une borne de recharge pour véhicule électrique, nous l'analyserons en profondeur, puis nous l'émulerons afin de pouvoir interagir avec les services en temps réel.
Rejoignez-nous pour cette démonstration pratique d'Unblob, l'extracteur de firmware flexible. Au cours de cet atelier, nous extrairons le firmware d'un chargeur de VE, nous l'explorerons en profondeur, puis nous l'émulerons afin d'interagir avec les services en temps réel. Unblob fonctionne à la fois sur les versions matérielles et téléchargeables du firmware, ce qui nous offre un environnement riche en cibles. Aucune expérience préalable n'est requise, cette session convient à tous les niveaux de compétence et nous nous réjouissons de vous y voir.
Notre cible est un contrôleur de borne de recharge pour véhicules électriques de Phoenix Contact. Vous pouvez en savoir plus à son sujet ici.
CHARX control modular, contrôleur de charge CA, avec système Linux embarqué, IEC 61851-1, mode de fonctionnement : autonome, client, serveur,
Interfaces :
- Ethernet (2x)
- Communication cellulaire (4G/2G)
- Bus système modulaire CHARX control
- MICRO-USB type C
Protocoles de communication :
- OCPP 1.6J
- Modbus/TCP
- MQTT
Périphériques connectables :
- Compteur d'énergie
- RFID
- Détection de courant résiduel DC
- Montage sur rail DIN
Quelques outils sont nécessaires pour cet atelier. Vous pouvez les installer en
exécutant le script install-prerequisites comme ceci :```sh
./install-prerequisites
## Obtention du firmware
Le firmware peut être obtenu depuis le site web du fournisseur. Un script nommé
`download-firmware` dans ce dépôt vous permet de récupérer le firmware
sans avoir besoin d'ouvrir un navigateur.
Notre attention se porte aujourd'hui sur le firmware fourni par le fournisseur, car il contient tout
ce dont nous avons besoin. Mais un flux de travail similaire peut être appliqué à un vidage mémoire extrait d'un
appareil réel. Ce qui est intéressant ici, c'est que nous pouvons extraire, explorer et
émuler sans même avoir besoin d'un appareil réel.
## Extraction avec Unblob
Commençons par vérifier que toutes les dépendances sont disponibles:```
unblob --show-external-dependencies
The following executables found installed, which are needed by unblob:
7z ✓
debugfs ✓
jefferson ✓
lz4 ✓
lziprecover ✓
lzop ✓
sasquatch ✓
sasquatch-v4be ✓
simg2img ✓
ubireader_extract_files ✓
ubireader_extract_images ✓
unar ✓
zstd ✓
Maintenant, nous pouvons extraire le firmware avec unblob :``` unblob CHARXSEC3XXXSoftwareBundleV190.raucb
L'extraction prend environ 3 minutes sur un ordinateur portable correct. Vous devriez voir une barre de progression avancer :

Une fois l'extraction terminée, un répertoire nommé
`CHARXSEC3XXXSoftwareBundleV190.raucb_extract` devrait être visible. Vous pouvez vous y rendre
et lister son contenu.
### Chunks, chunks inconnus
Unblob fonctionne en identifiant des chunks de données dans les fichiers. Si un chunk est un
flux compressé, il est décompressé. S'il s'agit d'un système de fichiers ou d'une archive, il
est extrait. Si l'extraction ou la décompression a réussi, le chunk
qui a été extrait sur le disque est supprimé pour récupérer de l'espace.
Ici, un chunk SquashFS version 4 little-endian a été isolé sur le disque, extrait,
puis supprimé. Les fichiers (et donc les répertoires d'extraction) sont nommés selon la
nomenclature `{start_offset}-{end_offset}.{type}`.
On peut voir qu'un chunk "unknown" de 11 Ko apparaît après le système de fichiers squashfs.```
./0-132173824.squashfs_v4_le_extract
./132173824-132184833.unknown
Vous pouvez exécuter binwalk dessus pour voir ce qu'il contient :```
binwalk 132173824-132184833.unknown
0 0x0 Object signature in DER format (PKCS header length: 4, sequence length: 10997 58 0x3A Certificate in DER format (x509 v3), header length: 4, sequence length: 4372 4434 0x1152 Certificate in DER format (x509 v3), header length: 4, sequence length: 4387
Vous pouvez vérifier les certificats avec openssl :```
dd if=132173824-132184833.unknown bs=1 skip=58 | openssl x509 -in /dev/stdin -inform der -noout -text
dd if=132173824-132184833.unknown bs=1 skip=4434 | openssl x509 -in /dev/stdin -inform der -noout -text
Cela signifie que les firmwares sont probablement signés avec la clé privée du fournisseur, afin que les appareils puissent vérifier l'authenticité des firmwares.
C'est l'un des avantages d'unblob : transformer les inconnues inconnues en inconnues connues qui peuvent être investiguées.
Regardons le contenu de notre système de fichiers squashfs :``` ls -al 0-132173824.squashfs_v4_le_extract total 460532 drwxrwxr-x 4 kali kali 4096 dec 5 09:51 . drwxrwxr-x 3 kali kali 4096 dec 5 09:51 .. -rw-rw-r-- 1 kali kali 20971520 sep 8 09:59 bootimg.vfat drwxrwxr-x 3 kali kali 4096 dec 5 09:51 bootimg.vfat_extract -rwxrwxr-x 1 kali kali 2654 sep 19 2022 hook -rw-rw-r-- 1 kali kali 442 sep 8 09:59 manifest.raucm -rw-rw-r-- 1 kali kali 450584576 sep 8 09:59 root.ext4 drwxrwxr-x 22 kali kali 4096 sep 8 09:57 root.ext4_extract
Nous pouvons voir un manifeste en clair, un script shell, un MBR et un système de fichiers EXT4:```
find -maxdepth 1 -type f -exec file {} \;
./manifest.raucm: ASCII text
./hook: a /usr/bin/env sh script, ASCII text executable
./bootimg.vfat: DOS/MBR boot sector, code offset 0x3c+2, OEM-ID "mkfs.fat", sectors/cluster 4, reserved sectors 4, root entries 512, sectors 40960 (volumes <=32 MB), Media descriptor 0xf8, sectors/FAT 40, sectors/track 63, heads 255, hidden sectors 163158016, reserved 0x1, serial number 0xd09aad9c, label: "KERNEL ", FAT (16 bit)
./root.ext4: Linux rev 1.0 ext4 filesystem data, UUID=8ed19606-02c4-42e7-9cfb-1a2839f93ec4 (extents) (large files) (huge files)
bootimg.vfat et root.ext4 ont tous deux été traités et extraits par unblob. La
partition VFAT contient tout ce qui est lié au boot et au système d’exploitation (noyau Linux, DTB,
TEE) :```
oftree: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756
tee.bin: data
zImage: Linux kernel ARM boot executable zImage (little-endian)
zImage-imx6ul-ksp0632.dtb: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756
Vous verrez qu'unblob est un peu gourmand et extraira un fichier ELF et une archive CPIO du noyau Linux (`zImage`), qui correspondent au noyau minimal et au ramdisk.
Le système de fichiers EXT4 contient le système de fichiers racine monté par le noyau Linux au démarrage :```
ls -alh root.ext4_extract
total 88K
drwxrwxr-x 22 kali kali 4,0K sep 8 09:57 .
drwxrwxr-x 4 kali kali 4,0K dec 5 09:51 ..
drwxrwxr-x 2 kali kali 4,0K dec 5 09:51 bin
drwxrwxr-x 3 kali kali 4,0K dec 5 09:51 boot
drwxrwxr-x 16 kali kali 4,0K sep 8 09:56 data
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 dev
drwxrwxr-x 53 kali kali 4,0K dec 5 09:51 etc
drwxrwxr-x 18 kali kali 4,0K sep 8 09:56 home
drwxrwxr-x 2 kali kali 4,0K jul 18 03:13 identity
drwxrwxr-x 9 kali kali 4,0K dec 5 09:51 lib
drwxrwxr-x 2 kali kali 4,0K jul 18 03:14 log
drwxrwxr-x 2 kali kali 4,0K sep 8 09:57 lost+found
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 media
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 mnt
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 proc
drwxrwxr-x 2 kali kali 4,0K sep 8 09:57 run
drwxrwxr-x 2 kali kali 4,0K dec 5 09:51 sbin
drwxrwxr-x 2 kali kali 4,0K jul 18 03:14 sdcard
drwxrwxr-x 2 kali kali 4,0K jul 18 00:09 sys
drwxrwxrwx 2 kali kali 4,0K jul 18 00:09 tmp
drwxrwxr-x 11 kali kali 4,0K sep 8 09:56 usr
drwxrwxr-x 11 kali kali 4,0K dec 5 09:51 var
Faisons un peu d'exploration en utilisant un ensemble différent d'options d'unblob :```
unblob -e /tmp/out -f -k -d 3 --report /tmp/report.json
--log /tmp/unblob.log CHARXSEC3XXXSoftwareBundleV190.raucb
Ici nous continuons à extraire (`-e`) vers `/tmp/out` mais nous forçons (`-f`) l'écrasement
tout en conservant (`-k`) les morceaux découpés mais en limitant la profondeur de récursion (`-d`) à
3. Nous écrivons un rapport détaillé (`--report`) vers `/tmp/report.json` et un fichier journal
(`--log`) vers `/tmp/unblob.log`.
Jetez un œil au fichier journal, vous verrez le fonctionnement interne d'unblob.
Le fichier de rapport contient des informations détaillées sur les fichiers analysés (taille, type
de fichier, chemin, magic, type MIME, hachages MD5/SHA1/SHA256), les morceaux (taille, décalages,
distribution d'entropie) et les tâches (extraction, décompression, découpage). Il est
possible de générer de belles visualisations à partir de ces fichiers de rapport avec un peu
de Python.
Vous pouvez les créer vous-même avec le script python `diagram.py` disponible dans
ce dépôt :```
python3 diagram.py /tmp/report.json sunburst
python3 diagram.py /tmp/report.json treemap
Ces commandes ouvriront le navigateur sur une page contenant une visualisation basée sur plotly, comme celles ci-dessous :


Maintenant que nous avons une meilleure idée de ce qu'il y a à l'intérieur, il est temps de lister ce dont nous avons besoin pour mener à bien l'émulation de l'appareil.
Idéalement, nous devons rassembler ces éléments d'information :
Pour obtenir plus de détails sur la plateforme, le CPU et l'architecture, nous pouvons examiner les device tree blobs intégrés dans le firmware.
Dans la partition VFAT, nous avons ces DTB :``` oftree: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756 zImage-imx6ul-ksp0632.dtb: Device Tree Blob version 17, size=27469, boot CPU=0, string block size=1657, DT structure block size=25756
Ces fichiers sont une représentation binaire des arbres de périphériques. Nous pouvons récupérer leur source en texte clair à l'aide de `device-tree-compiler` :```
dtc -I dtb -o zImage-imx6ul-ksp0632.dts zImage-imx6ul-ksp0632.dtb
dtc -I dtb -o oftree.dts oftree
Jetez un œil au DTS et vous trouverez rapidement des détails intéressants comme le modèle :``` /dts-v1/;
/ { #address-cells = <0x01>; #size-cells = <0x01>; model = "Phytec phyBOARD-Segin i.MX6 UltraLite"; <----- right here compatible = "phytec,imx6ul-pbacd-10\0phytec,imx6ul-pcl063\0fsl,imx6ul";
Le CPU :```
cpus {
#address-cells = <0x01>;
#size-cells = <0x00>;
cpu@0 {
compatible = "arm,cortex-a7"; <---- here
device_type = "cpu";
reg = <0x00>;
clock-latency = <0xee6c>;
operating-points = <0xa9ec0 0x137478 0x80e80 0x11edd8 0x60ae0 0xfa3e8 0x30570 0xe7ef0>;
fsl,soc-operating-points = <0xa9ec0 0x137478 0x80e80 0x11edd8 0x60ae0 0x11edd8 0x30570 0x11edd8>;
clocks = <0x01 0x5d 0x01 0x1a 0x01 0x26 0x01 0xdb 0x01 0x38 0x01 0x39 0x01 0x19>;
clock-names = "arm\0pll2_bus\0pll2_pfd2_396m\0secondary_sel\0step\0pll1_sw\0pll1_sys";
arm-supply = <0x02>;
soc-supply = <0x03>;
dc-supply = <0x04>;
};
};
Ou même des périphériques :``` --snip-- ethernet@2188000 { compatible = "fsl,imx6ul-fec\0fsl,imx6q-fec"; reg = <0x2188000 0x4000>; interrupts = <0x00 0x76 0x04 0x00 0x77 0x04>; clocks = <0x01 0x90 0x01 0x91 0x01 0x30 0x01 0x2c 0x01 0x2c>; clock-names = "ipg\0ahb\0ptp\0enet_clk_ref\0enet_out"; fsl,num-tx-queues = <0x01>; fsl,num-rx-queues = <0x01>; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <0x23>; phy-mode = "rmii"; phy-handle = <0x24>;
mdio {
#address-cells = <0x01>;
#size-cells = <0x00>;
ethernet-phy@1 {
reg = <0x01>;
interrupt-parent = <0x0b>;
interrupts = <0x02 0x08>;
micrel,led-mode = <0x01>;
clocks = <0x01 0x2c>;
clock-names = "rmii-ref";
status = "okay";
linux,phandle = <0x24>;
phandle = <0x24>;
};
ethernet-phy@2 {
reg = <0x03>;
micrel,led-mode = <0x01>;
clocks = <0x01 0x2d>;
clock-names = "rmii-ref";
status = "okay";
linux,phandle = <0x13>;
phandle = <0x13>;
};
};
};
--snip-- flexcan@2090000 { compatible = "fsl,imx6ul-flexcan\0fsl,imx6q-flexcan"; reg = <0x2090000 0x4000>; interrupts = <0x00 0x6e 0x04>; clocks = <0x01 0x94 0x01 0x95>; clock-names = "ipg\0per"; status = "okay"; pinctrl-names = "default"; pinctrl-0 = <0x0f>; xceiver-supply = <0x10>; };
flexcan@2094000 { compatible = "fsl,imx6ul-flexcan\0fsl,imx6q-flexcan"; reg = <0x2094000 0x4000>; interrupts = <0x00 0x6f 0x04>; clocks = <0x01 0x96 0x01 0x97>; clock-names = "ipg\0per"; status = "disabled"; };
### Informations sur la version du noyau Linux
Nous pouvons identifier la version du noyau Linux en effectuant un grep dans la partition VFAT qui contient le noyau compressé :```
grep 'Linux version' . -ra
./zImage_extract/7296-6371487.lzo_extract/7296-6371487:
Linux version 5.15.195 (oe-user@oe-host) (gcc version 8.3.0 (GCC)) #1 SMP PREEMPT
./zImage_extract/7296-6371487.lzo_extract/7296-6371487:
Linux version %s (%s)Bluetooth subsystem version %u.%uHCI socket registration failed
Une autre façon consiste à examiner les modules du noyau dans le système de fichiers racine EXT4 :```
modinfo ./CHARXSEC3XXXSoftwareBundleV190.raucb_extract/0-138014720.squashfs_v4_le_extract/root.ext4_extract/lib/modules/5.15.195/kernel/net/bluetooth/bnep/bnep.ko.xz
filename: ./CHARXSEC3XXXSoftwareBundleV190.raucb_extract/0-138014720.squashfs_v4_le_extract/root.ext4_extract/lib/modules/5.15.195/kernel/net/bluetooth/bnep/bnep.ko.xz
alias: bt-proto-4
license: GPL
version: 1.3
description: Bluetooth BNEP ver 1.3
author: Marcel Holtmann [email protected]
srcversion: 86266D360814678CE0C94E9
depends:
intree: Y
name: bnep
vermagic: 5.15.195 preempt mod_unload modversions ARMv7 thumb2 p2v8
parm: compress_src:Compress sources headers (bool)
parm: compress_dst:Compress destination headers (bool)
## Émulation
Il se peut que nous ayons déjà un noyau compilé dans le paquet du firmware, mais ce
noyau est compilé spécifiquement pour une machine particulière (la Phytec
phyBOARD-Segin i.MX6 UltraLite).
Pour utiliser ce noyau correctement, il faudrait pouvoir l'exécuter sur une
émulation de la machine exacte pour laquelle il a été compilé. Cela demande beaucoup de temps
s'il n'est pas déjà répertorié dans la liste des machines QEMU. Remarque : une carte d'évaluation
est disponible dans QEMU (`mcimx6ul-evk - Freescale i.MX6UL Evaluation Kit
(Cortex-A7)`) mais ne correspond pas exactement.
À la place, en théorie, nous pouvons choisir une machine QEMU et utiliser diverses métadonnées que
nous trouvons dans l'image du firmware pour configurer et construire un noyau pour cette machine,
qui serait également capable d'exécuter tout ce qui se trouve dans notre système de fichiers, aussi proche que possible de
l'original.
À partir de là, nous avons quelques options :
- *émulation de l'espace utilisateur*: Nous pourrions démarrer dans notre propre ramfs/rootfs personnalisé, puis
charger le rootfs du firmware cible et faire un chroot dedans pour l'émuler.
- *émulation complète du système*: Nous pourrions essayer de démarrer directement le rootfs du firmware cible
(en le passant directement à la machine QEMU).
L'émulation de l'espace utilisateur est généralement limitante, mais c'est un excellent moyen d'étudier, de déboguer,
et d'exploiter des binaires spécifiques. Nous vous recommandons vivement de jeter un œil à
[EMUX](https://github.com/therealsaumil/emux) de Saumil Shah pour tous vos
besoins en émulation d'espace utilisateur.
Quoi qu'il en soit, nous avons toujours besoin d'un noyau qui démarre dans une machine QEMU,
qui corresponde le plus possible à ce que le firmware cible attend.
### Machines QEMU
Il n'y a que quelques candidats pour des machines à usage général offrant
de la flexibilité. Après pas mal d'expérimentations, `virt`
(https://qemu.readthedocs.io/en/latest/system/arm/virt.html) semble avoir un
bon rapport flexibilité/puissance pour nos objectifs.
Lors de la construction du noyau pour une machine QEMU donnée, il est probablement préférable pour nous de
nous assurer de pouvoir utiliser le dispositif virtio général fourni avec QEMU. Dans la
configuration, cela peut correspondre à un ou plusieurs des éléments suivants :```
CONFIG_VIRTIO=y
CONFIG_SCSI_VIRTIO=y
CONFIG_VIRTIO_PCI=y
CONFIG_VIRTIO_BLK=y
Et bien plus encore ! Cette liste est incomplète.
Il est avantageux d’utiliser un noyau dont la chaîne vermagic est identique (ou au moins très similaire). Toutes sortes de composants d’un système peuvent vérifier la vermagic du noyau et échouer si elle est différente de celle attendue. C’est surtout le cas des modules du noyau : un noyau refusera généralement de charger un module dont la vermagic ne correspond pas à la sienne. Bien que nous puissions patcher le noyau pour ignorer cela au niveau du noyau, il faut encore que la partie initiale « kernel release » de la chaîne corresponde à celle des modules du noyau, car elle sert de chemin de recherche pour modules.dep.
Dans le firmware Phoenix Contact, la vermagic est 5.15.195 preempt mod_unload modversions ARMv7 thumb2 p2v8.
La chaîne vermagic est au format du type (d’après include/linux/vermagic.h):```c
#define VERMAGIC_STRING
UTS_RELEASE " "
MODULE_VERMAGIC_SMP MODULE_VERMAGIC_PREEMPT
MODULE_VERMAGIC_MODULE_UNLOAD MODULE_VERMAGIC_MODVERSIONS
MODULE_ARCH_VERMAGIC
- Version du noyau = la version du noyau + la chaîne `CONFIG_LOCALVERSION`.
- SMP = `CONFIG_SMP`
- PREEMPT = `CONFIG_PREEMPT`
- mod_unload = `CONFIG_MODULE_UNLOAD`
- modversions = `CONFIG_MODVERSIONS`
- ARMv7 thumb2 p2v8 = `MODULE_ARCH_VERMAGIC` (lié à l'architecture pour laquelle le noyau est compilé, donc lié à l'option compilateur/architecture passée.)
Une fois que nous avons extrait le code source du noyau, nous pouvons le patcher pour qu'il ne soit pas aussi brutal dans la comparaison des chaînes vermagic. Dans kernel/module.c, nous pouvons simplement commenter le return -ENOEXEC :```diff
} else if (!same_magic(modmagic, vermagic, info->index.vers)) {
pr_err("%s: version magic '%s' should be '%s'\n", info->name, modmagic, vermagic);
- return -ENOEXEC;
+ // return -ENOEXEC;
}
if (!get_modinfo(info, "intree")) {
Ce n’est peut-être pas utile à long terme, mais c’est bon pour tester, tant qu’il existe de légères différences entre le vermagic de notre noyau et le vermagic du module. Les modules (pour la plupart) se chargeront quand même.
REMARQUE : nous fournissons ici un noyau déjà compilé qui correspond aux exigences cibles, vous n’avez donc pas besoin d’en compiler un vous-même. Il a été construit avec un script interne qui :
multi_v7_defconfig pour définir la configuration initialekernel/module.cVIRTIO et des sous-systèmes spécifiques comme
USB ou CANBUSPassons en revue les différents paramètres de notre commande qemu-system-arm. Nous fournissons le noyau de cette façon :```sh
qemu-system-arm -M virt,highmem=off
-m ${AVAILABLE_MEM_GB}G -smp ${CPU_CORES} -cpu cortex-a15
-kernel zImage
L'image du système de fichiers EXT4 est attachée comme un disque SCSI:```sh
-device virtio-scsi-device \
-device scsi-hd,drive=SystemDisk \
-drive file=${FIRMWARE_IMAGE},format=raw,if=none,id=SystemDisk
Nous définissons une sortie console appropriée de cette manière :```sh
-append "${BOOT_PARAMS}"
-no-reboot
-nographic
-serial mon:stdio \
Les `BOOT_PARAMS` sont définis dans `config.ini` et correspondent à la
commande bootcmd réelle du noyau, avec deux petites adaptations (chemin de la console et chemin du rootfs).
### Réseau
Maintenant que nous avons un système émulé fonctionnel, il est temps de configurer le réseau. La cible dispose des éléments suivants :
- deux interfaces Ethernet (`eth0` et `eth1`)
- une interface CANbus (`can0`)
- une interface USB pouvant faire office d'Ethernet sur USB (`usb0`)
- un modem cellulaire Qualcomm High Sierra (`ppp0`)
Émuler le modem cellulaire et les interfaces USB est pénible avec QEMU, et pas vraiment
nécessaire pour le fonctionnement de l'appareil puisque ces interfaces sont "optionnelles". L'interface
CAN est là pour permettre au contrôleur de parler à d'autres contrôleurs ou
à des bornes de recharge. L'interface `eth0` fournit la connectivité amont en
demandant un bail DHCP par défaut, tandis que `eth1` est réglée sur 192.168.4.1 et est
là si vous voulez chaîner plusieurs contrôleurs.
Les interfaces Ethernet sont configurées comme interfaces TAP et connectées comme ceci :```
-netdev tap,id=tap0net,ifname=${ETH_1},script=no,downscript=no \
-device virtio-net-device,netdev=tap0net,mac=${ETH_1_MAC} \
-netdev tap,id=tap1net,ifname=${ETH_0},script=no,downscript=no \
-device virtio-net-device,netdev=tap1net,mac=${ETH_0_MAC} \
L'interface CANBUS est simplement une interface PCI, connectée comme ceci :```
-object can-bus,id=canbus0
-device kvaser_pci,canbus=canbus0
-object can-host-socketcan,id=canhost0,if=can0,canbus=canbus0 \
Le schéma ci-dessous montre à quoi ressemble la configuration du réseau :

Si vous souhaitez essayer la communication inter-contrôleurs en les chaînant en guirlande comme
recommandé par Phoenix Contact, vous pourriez utiliser quelque chose comme ceci :

## Prêt ? À vos marques. Lancement !
Maintenant que tout est en place, il est temps de démarrer !
D'abord, vous devez configurer toutes les interfaces réseau comme ceci :```
sudo ./ifup.sh
Assurez-vous que votre interface amont est correctement définie dans config.ini :```
OUT_IF="eth0"
Vous pouvez ensuite lancer l'émulateur :```
sudo ./launch.sh
Vous verrez les adresses obtenues dans les journaux:``` Dec 5 10:07:46 ev3000 daemon.info avahi-daemon[1047]: Registering new address record for 192.168.4.1 on eth1.IPv4. Dec 5 10:07:46 ev3000 daemon.info avahi-daemon[1047]: Registering new address record for 192.168.88.181 on eth0.IPv4.
### Accès via SSH
Vous pouvez ensuite vous connecter en SSH à l'appareil émulé en utilisant l'utilisateur `user-app`:```sh
ssh [email protected]
Le mot de passe est "user". Vous serez obligé de le changer lors de la première connexion :```sh ssh [email protected] The authenticity of host '192.168.88.181 (192.168.88.181)' can't be established. ED25519 key fingerprint is SHA256:qMupzEehNFpx6eaGZ4d3AY5Jlms3Pmxh3/yg9OGA28o. This key is not known by any other names Are you sure you want to continue connecting (yes/no/[fingerprint])? yes Warning: Permanently added '192.168.88.181' (ED25519) to the list of known hosts. [email protected]'s password: WARNING: Your password has expired. You must change your password now and login again! Changing password for user-app Old password: Enter the new password (minimum of 5 characters) Please use a combination of upper and lower case letters and numbers. New password: Re-enter new password: passwd: password changed. Connection to 192.168.88.181 closed.
### Interface Web
Vous pouvez accéder à l'interface web à l'adresse http://192.168.4.1. Un message d'erreur
peut s'afficher pendant le démarrage de l'appareil. Une fois que tout est opérationnel, vous
devriez voir ceci :

Vous pouvez vous connecter avec les comptes suivants :
| nom d'utilisateur | mot de passe |
|----------|----------|
| manufacturer | manufacturer |
| operator | operator |
### Trafic CAN
Lorsque tout est opérationnel, vous pouvez capturer le trafic CAN émis par le
contrôleur :```
candump -i can0
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
can0 701 [1] 00000101
REMARQUE : il semble que la version 8.x de QEMU rencontre des difficultés pour attacher le contrôleur CAN pour une raison quelconque.