ChameleonUltra, un nouvel outil pour vos expérimentations RFID/NFC

Spécialité(s)


Résumé

Si vous êtes curieux et amateur de technologies RFID/NFC, vous connaissez sans doute le classique lecteur USB ACR122U, le plus compétent/stable SCL3711 et l'incontournable (et coûteux) Proxmark 3 RDV4. Un petit nouveau a fait son apparition dernièrement et le qualificatif de « petit » n'est pas ici utilisé à la légère : le ChameleonUltra. Petite prise en main et essai de ce qui sera, à terme, un véritable bijou indispensable dans votre boîte à outils...


Body

Qualifier le ChameleonUltra n'est pas chose facile, car il reprend certaines fonctionnalités du Proxmark 3, peut fonctionner comme un lecteur RFID/NFC 125 kHz (LF pour Low Frequency) et 13,56 MHz (HF pour High Frequency), mais aussi, et surtout, dispose de fonctions d'émulation/simulation de tags plus performantes que celles proposées par un Proxmark 3 (en termes de vitesse et de réactivité). De plus, le ChameleonUltra est minuscule (2,4 cm par 4 cm et 8 mm d'épaisseur) et peut fonctionner de façon autonome (accu LiPo) ou connecté à un PC/Mac via une liaison USB à connecteur USB-C et interface CDC-ACM (Communication Device Class - Abstract Control Model). Certes, un Proxmark 3 RDV4 équipé d'un module BlueShark Standalone fera de même, mais on ne parle pas du tout de la même échelle ici, ni en taille (cf. photos) ni en autonomie (~45 min pour le BlueShark contre plus de 6 mois pour le ChameleonUltra).

Ce périphérique, au prix non négligeable de quelque 130 € (chez les Lyonnais de Lab401 par exemple, distributeur officiel pour l'Europe), peut donc être à la fois un lecteur RFID/NFC, un tag (8 emplacements d'émulation disponibles, déclinés en HF et LF, donc 16 tags en tout) et un outil de pentest pour éprouver la sécurité de tags comme les traditionnels MIFARE Classic ou des dispositifs de contrôle d'accès utilisant cette même technologie. Je parle ici de MIFARE Classic, car, et c'est très important si vous comptez éviter toute déception ou frustration après la réception de votre ChameleonUltra, c'est le seul type de tag HF qui est actuellement supporté par le firmware du matériel. Le ChameleonUltra a un énorme potentiel, mais pour l'instant, c'est surtout du potentiel. Il est en effet capable matériellement, par exemple, d'émuler des NTAG21x, des MIFARE Ultralight (+ Ultralight C), des MIFARE DESFire (+ EV1, EV2) et MIFARE Plus, mais l'applicatif en firmware n'implémente pour le moment pas ces fonctions. Il en va de même pour la lecture des DESFire et MIFARE Plus, ou encore, côté LF, de la simulation des T5577, HID Prox, ioProx ou encore des EM4305 pour n'en citer que quelques-uns. Une page spécifique du dépôt GitHub [1], docs/technical_whitepaper.md, liste en détail l'état des fonctionnalités effectivement supportées à la date où sont couchées ces lignes, mais dans l’ensemble, ceci se limite à du MIFARE Classic (HF) et du EM410x (LF). Il s'agit donc d'un potentiel extraordinaire outil en devenir...

Préciser cet état de fait me paraît important, car les caractéristiques listées sur les pages des sites commercialisant le matériel restent relativement vagues sinon trompeuses, en précisant des choses comme « Cartes supportées [...] HID Prox / Indala / PAC/Stanley », ce qui est, au mieux, inexact au sens strict du terme. Pour quelque 150 € d'investissement potentiel, ceci mérite pourtant d'être clairement annoncé. Soit dit en passant, la mention des attaques « Emboîté » (nested), « Emboîté dur » (HardNested) et « Côté obscur » (DarkSide) sur MIFARE Classic, sur la même page, est si comique qu'on se demande si ce n'est pas fait exprès.

CU livraison-s

Lorsque vous commandez un ChameleonUltra (officiel), il n'arrive pas seul. Vous recevez également un câble USB (un peu court), une gaine de protection en silicone, un mini-tournevis Torx pour démonter le produit avec deux vis supplémentaires, et un anneau en céramique pour faire de votre ChameleonUltra un porte-clés. Le tout dans une jolie boîte.

1. Mais qu'est-ce qu'un ChameleonUltra ?

Le ChameleonUltra est construit autour d'un microcontrôleur nRF52840 de chez Nordic Semiconductor, intégrant un cœur ARM Cortex-M4, 1 Mio de flash, 256 Kio de RAM et différents périphériques, dont un contrôleur Bluetooth Low Energy (BLE), une interface USB 2.0 et un support NFC-A initialement présent pour offrir une capacité d'émulation afin de simplifier l'appairage Bluetooth. De base, le nRF52840 est donc limité côté NFC puisqu’incapable de lire ou d’écrire des tags ISO/IEC 14443 A (généralement raccourcis en « HF 14a » ou « 14a »). De ce fait, les développeurs, constatant que les capacités d'émulation NFC du microcontrôleur Nordic affichaient des performances très intéressantes et qu'il était même possible d'émuler du MIFARE Classic (qui n'est pas à strictement parler du NFC), décidèrent de compléter le circuit avec une puce MFRC522 de NXP. Celle-ci offrant un frontend compatible MIFARE, NTAG et 14a en général, le duo nRF52840+MFRC522 fait du ChameleonUltra un simulateur, un lecteur et un outil de test générique RFID/NFC. La modulation basse fréquence (LF) est prise en charge directement par la partie analogique du nRF52840 avec l'assistance de quelques circuits analogiques (opamp, filtres, détection d'enveloppe, pilotage de l'antenne, etc.). À cela s'ajoutent enfin huit LED RGB et deux boutons formant l'interface utilisateur en mode autonome afin de pouvoir sélectionner le tag à émuler et/ou copier l'UID d'un tag physique pour l'émuler ensuite (les emplacements « peuplés » LF sont bleus, HF en vert et HF+LF en rouge). Le choix de l'action liée à l'utilisation des boutons, que ce soit par appui bref ou long, est configurable via l'un des outils supportant le matériel (ligne de commande, application GUI en Flutter ou application module iOS/Android). Une LED blanche est également présente et sert à signaler la présence d'un champ électromagnétique (non configurable, apparemment).

Vous l'avez compris, le ChameleonUltra est excessivement compact. Il se compose de deux PCB prenant en sandwich l'accu LiPo avec l'une des deux faces donnant accès aux boutons et l'autre, noyée dans la résine, montrant les puces et les LED. Sur la tranche se trouve un connecteur USB-C et de l'autre côté, une encoche permettant d'attacher un anneau pour en faire un porte-clés, un lanyard, etc. En commandant la version officielle, vous recevrez également un câble USB-C/USB-A (transformable en USB-C/USB-C), une attache porte-clés, une gaine de protection en silicone et un mini-tournevis pour éventuellement démonter le produit (et remplacer l'accu).

Notez que les distributeurs officiels (Lab401, Hackerwarehouse, RRG sur AliExpress, Sneaktechnology) sont naturellement l'option à préférer pour un achat, mais le projet étant open source, des ChameleonUltra sont également apparus rapidement chez des vendeurs (autre que RRG) sur AliExpress, avec des niveaux de qualité très variables et des prix sensiblement plus bas (~120 €). Personnellement, je n'opterais pas pour une telle alternative, non seulement parce qu'il est préférable de supporter le projet, mais également en raison de l'incertitude concernant ce qui sera effectivement réceptionné. Certaines photos d'annonces montrent clairement un matériel différent, plus épais et donc des économies évidentes faites sur les composants, comme c'était déjà le cas pour les Proxmark 3. D'autres vous préviennent que des clones existent, mais sont facilement identifiables en raison de leur libellé « Chamele0nUltra », alors que le leur est, bien entendu, le « vrai » ChameleonUltra (sic). Enfin, certaines annonces proposent des ChameleonUltra à un prix défiant toute concurrence (~65 €) alors qu'il s'agit en réalité de devkit, une déclinaison du matériel en un seul PCB, beaucoup moins compact (5,3 cm par 8,5 cm), qui offre les mêmes fonctionnalités, mais est destiné au développement et à la mise au point (connecteur SWD, Serial Wire Debug) du firmware.

CU euro-s

Le ChameleonUltra est véritablement un concentré de technologies RFID/NFC réduit au maximum de compacité. L'objectif est simple : rendre l'outil le plus discret possible, sinon invisible dans le creux d'une main.

2. Installation, compilation et prise en main

Le ChameleonUltra, en émulateur de tag, est autonome, mais sa configuration nécessite, bien entendu, l'utilisation d'un outil spécifique. Vous pouvez parfaitement vous en sortir avec Chameleon Ultra GUI [2] [3] [4] ou encore MTools Lite [5] pour le fonctionnement en tant que lecteur RFID/NFC, mais l'approche du magazine est généralement plus « spartiate », avec une préférence vers la ligne de commande. Plutôt que de reposer sur un binaire ou une application clé en main, nous allons donc nous baser sur les sources officielles pour tout reconstruire. Ceci vous permettra également d'être systématiquement à jour tout en vous permettant, par la suite, de contribuer au projet plus rapidement.

Commençons donc par récupérer les sources via GitHub et lançons immédiatement la construction des quelques binaires nécessaires pour les attaques sur les MIFARE Classic :

$ git clone https://github.com/RfidResearchGroup/ChameleonUltra.git
$ cd ChameleonUltra
$ cd software/src
$ mkdir build
$ cd build
 
$ cmake ../
-- The C compiler identification is GNU 12.2.0
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Check for working C compiler: /usr/bin/cc - skipped
-- Detecting C compile features
-- Detecting C compile features - done
-- Configuring done
-- Generating done
-- Build files have been written to: /home/denis/ChameleonUltra/software/src/build
 
$ make
[ 2%] Building C object CMakeFiles/nested.dir/crapto1.c.o
[ 5%] Building C object CMakeFiles/nested.dir/crypto1.c.o
[ 8%] Building C object CMakeFiles/nested.dir/bucketsort.c.o
[...]
[ 94%] Building C object CMakeFiles/mfkey64.dir/parity.c.o
[ 97%] Building C object CMakeFiles/mfkey64.dir/mfkey64.c.o
[100%] Linking C executable /home/denis/ChameleonUltra/software/bin/mfkey64
[100%] Built target mfkey64
 
$ cd ../..
$ ls bin/
darkside mfkey32 mfkey32v2 mfkey64 nested

Ces cinq binaires que nous obtenons dans software/bin sont destinés à être exécuté localement, ce sont des programmes pour l'hôte et non pour l'ARM du ChameleonUltra. En effet, le matériel n'est pas capable de « craquer » lui-même les clés de certains tags MIFARE, mais repose sur la puissance de calcul de la machine hôte.

Pour piloter notre ChameleonUltra, nous devons utiliser le client écrit en Python se trouvant dans software/script sous la forme du fichier chameleon_cli_main.py. Bien entendu, Debian (et ses dérivés) étant Debian, ce script nécessite un module dans une version qui n'est pas disponible sous la forme de paquet (voir requirements.txt dans le même répertoire). Pour ne pas saccager notre environnement de travail, nous utilisons le mécanisme d'environnement virtuel de Python, via le module venv :

$ python3 -m venv /kkpart/ChameleonUltra

Ceci aura pour effet d'installer un interpréteur Python spécifique, local, et non géré par le système de gestion de paquets, dans /kkpart, qui est un répertoire que vous aurez créé arbitrairement pour l'occasion à l'emplacement qui vous chante. Ceci fait, nous pouvons utiliser pip3, se trouvant là en compagnie d'un lien symbolique distinct vers l'interpréteur Python, pour installer les modules nécessaires :

$ /kkpart/ChameleonUltra/bin/pip3 install -r requirements.txt
Collecting pyserial==3.5
  Using cached pyserial-3.5-py2.py3-none-any.whl (90 kB)
Collecting colorama==0.4.6
  Using cached colorama-0.4.6-py2.py3-none-any.whl (25 kB)
Collecting prompt-toolkit==3.0.39
  Using cached prompt_toolkit-3.0.39-py3-none-any.whl (385 kB)
Collecting wcwidth
  Using cached wcwidth-0.2.6-py2.py3-none-any.whl (29 kB)
Installing collected packages: wcwidth, pyserial, prompt-toolkit, colorama
Successfully installed colorama-0.4.6
prompt-toolkit-3.0.39 pyserial-3.5 wcwidth-0.2.6

On me souffle dans l'oreillette que ma façon d'utiliser venv est « bizarre ». Étant ce qu'on peut appeler un hérétique aux yeux des dévots de la secte des adorateurs du grand serpent, je prends ça comme un compliment. Ce que vous êtes censé faire, proprement, est en fait :

$ source /kkpart/bin/activate
<Vous êtes dans l'environnement comme
l'indique le prompt modifié>
 
$ pip3 install -r requirements.txt
 
$ python chameleon_cli_main.py
[...]
 
$ deactivate

Nous pouvons enfin exécuter le script, via l'interpréteur de l'environnement fraîchement créé :

$ /kkpart/ChameleonUltra/bin/python chameleon_cli_main.py
██████╗██╗ ██╗ █████╗ ██╗   ██╗███████╗██╗     ███████╗ █████╗ ██╗ ██╗
██╔════╝██║ ██║██╔══██╗███╗ ███║██╔════╝██║     ██╔════╝██╔══██╗███╗ ██║
██║     ███████║███████║████████║█████╗ ██║     █████╗ ██║ ██║████╗██║
██║     ██╔══██║██╔══██║██╔██╔██║██╔══╝ ██║     ██╔══╝ ██║ ██║██╔████║
╚██████╗██║ ██║██║ ██║██║╚═╝██║███████╗███████╗███████╗╚█████╔╝██║╚███║
╚═════╝╚═╝ ╚═╝╚═╝ ╚═╝╚═╝   ╚═╝╚══════╝╚══════╝╚══════╝ ╚════╝ ╚═╝ ╚══╝
[Offline] chameleon -->

Au lancement, le client n'est pas connecté au ChameleonUltra que vous aurez préalablement branché en USB. Il faut pour cela utiliser la commande hw (comme hardware) et connect :

[Offline] chameleon --> hw connect
{ Chameleon connected }
[USB] chameleon -->

Si les permissions sont correctement configurées (c'est un port série CDC ACM qui apparaît à la connexion), le client détecte automatiquement le périphérique et vous pouvez alors interagir avec ce dernier, pour demander son identifiant, par exemple :

[USB] chameleon --> hw chipid get
- Device chip ID: 09312bf290b41fa0

Mais si nous demandons d'autres informations, comme la version du firmware (version) ou les informations sur les emplacements, ou slots, d'émulation (hw slot list), nous rencontrons un problème :

[USB] chameleon --> hw version
CLI exception: Traceback (most recent call last):
  File "/home/denis/ChameleonUltra/software/script/chameleon_cli_main.py",
line 175, in startCLI
    unit.on_exec(args_parse_result)
  File "/home/denis/ChameleonUltra/software/script/chameleon_cli_unit.py",
line 295, in on_exec
    git_version = self.cmd.get_git_version()
                  ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/denis/ChameleonUltra/software/script/chameleon_cmd.py",
line 309, in get_git_version
    resp = self.device.send_cmd_sync(DATA_CMD_GET_GIT_VERSION, 0x00)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/denis/ChameleonUltra/software/script/chameleon_com.py",
line 344, in send_cmd_sync
    raise CMDInvalidException(f"Device unsupported cmd: {cmd}")
chameleon_com.CMDInvalidException: Device unsupported cmd: 1017
 
[USB] chameleon --> hw slot list

Le code du projet évolue rapidement et notre matériel à peine réceptionné dispose d'un firmware trop ancien pour le client obtenu via GitHub. Au moment des tests, aucun firmware à jour facilement installable n'était disponible (là encore, tout a évolué depuis) et j'ai été agréablement obligé de tout simplement construire un nouveau firmware et de le flasher dans le périphérique. Vous pouvez vous passer de ce genre de tracasserie à présent, mais être en mesure de le faire, rapidement, vous permettra de rester dans la course et de toujours utiliser la dernière version après un simple git pull dans le répertoire constituant votre repo local. C'est la même logique qui s'applique avec un Proxmark 3 et c'est très bien ainsi.

Pour flasher le firmware, rien de plus simple, il suffit de passer le ChameleonUltra en mode DFU (Device Firmware Upgrade) pour que le nRF52840 démarre sur son bootloader et nous permette d'utiliser un outil spécifique Nordic (et à priori propriétaire) pour mettre à jour l'application en mémoire flash. Cet outil, appelé nRF Util est disponible sur le site du constructeur [6] en version Windows, macOS et GNU/Linux. Pour ce système, c'est directement un binaire ELF x86-64 qui est téléchargé et devra donc être rendu exécutable (chmod +x) et placé dans le $PATH (~/bin/ chez moi). Vous devrez également ajuster les règles udev pour permettre un accès au périphérique USB redémarré en mode DFU. Un fichier /etc/udev/rules.d/nrf.rules contenant ce qui suit fera très bien l'affaire :

SUBSYSTEMS=="usb", ATTRS{idVendor}=="1915", MODE="0666", GROUP="plugdev"

Le reste sera pris en charge par un script flash-dfu-app.sh présent dans le répertoire firmware/, qui s'occupera du passage en mode DFU et du flashage. Mais :

$ firmware/flash-dfu-app.sh
Flashing ultra
DFU package for ultra not found, aborting.
Build firmware using CURRENT_DEVICE_TYPE=ultra firmware/build.sh

Bien sûr, encore faut-il avoir quelque chose à flasher, ce qui n'est pas le cas par défaut. Nous devons donc créer l'archive ZIP normalement présente dans le sous-répertoire firmware/objects/ et, implicitement donc, compiler le firmware.

Là, les choses se compliquent (et deviennent un peu étranges aussi), car nous avons besoin d'outils supplémentaires, encore une fois disponibles sur le site de Nordic [7]. Ces nRF Command Line Tools pourront être installés sous la forme d'un paquet Debian décliné en version X86-64, i386, ARM 32 bits et ARM 64 bits, directement téléchargeable une fois la bonne plateforme sélectionnée (des RPM sont également présents). Le paquet pourra ensuite être installé via la commande :

$ sudo dpkg -i nrf-command-line-tools_10.23.0_amd64.deb

Ce n'est pas tout, pour développer (et donc compiler) pour le microcontrôleur nRF, nous avons besoin d'un SDK et c'est là que tout ceci prend une tournure vraiment peu conventionnelle. Installer le SDK se fera via la commande nrfutil, celle-là même que vous avez téléchargée sous forme de binaire précédemment, avec :

$ nrfutil install device nrf5sdk-tools

Il n'est pas nécessaire d'être root pour cette opération. Fort heureusement d'ailleurs, car sinon il n'y aurait tout simplement pas d'article. Il est parfaitement hors de question que j'exécute un binaire inconnu avec cette identité, même dans un environnement isolé. On pourra ensuite vérifier la présence du SDK avec :

$ nrfutil list
Command        Version Description
device         1.2.2    Work with Nordic Semiconductor devices
nrf5sdk-tools  1.0.1    nRF5 SDK tools that were available in nRF Util 6
   dfu                  
   keys                 
   pkg                  
   settings             
   zigbee               
Found 2 installed command(s)

Je ne vous cache pas que tout ceci ne me plaît aucunement et que la faute n'en incombe ni aux créateurs du ChameleonUltra, ni aux développeurs contribuant au projet. Nordic, si vous lisez ceci, faites les choses proprement et de façon cohérente, s'il vous plaît : packagez tous vos outils, pas la moitié d'entre eux, et pour l'amour du ciel, arrêtez de vous éloigner de l'écosystème open source (cf. [8] et le fichier LICENSE présent dans ce dépôt archivé).

CU leds-s

Le fonctionnement autonome est grandement facilité par l'interface utilisateur consistant en deux boutons (à l'arrière) et une tripotée de LED RGB en façade. 8 pour la sélection de l'emplacement mémoire du tag à émuler/simuler, un témoin de charge (« CHG ») et un notificateur de présence de champ électromagnétique (en bas).

Nous y sommes presque, mais nous devons surmonter un nouveau problème. Le processeur au cœur du nRF52840 est un ARM Cortex-M4, nous avons donc besoin d'une chaîne de compilation pour cette cible. Si vous développez pour Raspberry Pico, par exemple, vous avez très certainement déjà ce genre de chose à portée de main (paquet gcc-arm-none-eabi et ses dépendances) sous la forme d'un GCC 12.2.rel1-1 (avec Debian 12). Malheureusement, voici ce que vous obtiendrez en tenant de l'utiliser :

Compiling file: oberon_backend_eddsa.c
Compiling file: oberon_backend_hash.c
Compiling file: oberon_backend_hmac.c
Linking target: ../objects/bootloader.out
/usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/bin/ld:
../objects/bootloader.out section `.svc_data' will not fit in region `FLASH'
/usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/bin/ld:
region FLASH overflowed with .data and user data
/usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/bin/ld:
section .mbr_params_page VMA [000fe000,000fefff]
overlaps section .svc_data VMA [000fdff8,000fe003]
/usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/bin/ld:
section .nrf_balloc VMA [000fe004,000fe02b]
overlaps section .mbr_params_page VMA [000fe000,000fefff]
/usr/lib/gcc/arm-none-eabi/12.2.1/../../../arm-none-eabi/bin/ld:
region `FLASH' overflowed by 132 bytes
collect2: error: ld returned 1 exit status

L'éditeur de liens nous explique gentiment (ou pas) que le binaire est trop gros pour la flash et que certaines sections débordent sur d'autres. Mais, d'autre part, la documentation du ChameleonUltra [9] précise que les chaînes de compilation testées et validées par le projet sont gcc-arm-none-eabi-10.3-2021.10 et /arm-gnu-toolchain-12.2.rel1-XXX-arm-none-eabi. La version « 12.2.rel1 » de Debian devrait, en principe, fonctionner, mais le Dockerfile inclus avec les sources (firmware/Dockerfile) télécharge en réalité une chaîne de compilation mise à disposition par Keil et non un GCC ARM « générique » (NDLR : la chaîne AArch32 bare-metal target en version 12.3rel1 disponible via [10] fonctionne également).

Si nous téléchargeons cette chaîne de compilation depuis https://armkeil.blob.core.windows.net, nous obtenons une archive arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi.tar.xz qu'il nous suffit de décompresser quelque part dans notre système. Il n'est pas même nécessaire de modifier notre PATH puisque le Makefile du projet référence directement l'emplacement utilisé (dans firmware/nrf52_sdk/components/toolchain/gcc/Makefile.posix) :

GNU_INSTALL_ROOT ?= /usr/bin/
GNU_VERSION ?= 9.3.1
GNU_PREFIX ?= arm-none-eabi

Il nous suffit donc d'exporter deux variables d'environnement et de lancer la construction avec :

export GNU_INSTALL_ROOT=/chemin/arm-gnu-toolchain-12.2.rel1-x86_64-arm-none-eabi/bin/
 
$ CURRENT_DEVICE_TYPE=ultra firmware/build.sh
Building firmware for ultra (hw_version=0)
+ cd bootloader
+ make -j
Chameleon Ultra <Bootloader>: zZZZZZ.
cd ../objects && mkdir bootloader
Compiling file: main.c
Compiling file: dfu_public_key.c
Compiling file: hw_connect.c
Compiling file: libc_nano_stubs.c
Compiling file: nrfx_clock.c
[...]
Bootloader DFU Settings:
* File:                     settings.hex
* Family:                   NRF52840
* Start Address:            0x000FF000
* CRC:                      0x66C6F3B3
* Settings Version:         0x00000002 (2)
* App Version:              0x00000001 (1)
* Bootloader Version:       0x00000001 (1)
* Bank Layout:              0x00000000
* Current Bank:             0x00000000
* Application Size:         0x0003370C (210700 bytes)
* Application CRC:          0x4D41F056
* Bank0 Bank Code:          0x00000001
* Softdevice Size:          0x00025634 (153140 bytes)
* Boot Validation CRC:      0x0E8DFCD9
* SD Boot Validation Type:  0x00000001 (1)
* App Boot Validation Type: 0x00000001 (1)
[...]
+ zip -j ultra-binaries.zip
    /tmp/cu_binaries_QB5YhzaUq4/application.hex
    /tmp/cu_binaries_QB5YhzaUq4/bootloader.hex
    /tmp/cu_binaries_QB5YhzaUq4/fullimage.hex
    /tmp/cu_binaries_QB5YhzaUq4/softdevice.hex
  adding: application.hex (deflated 62%)
  adding: bootloader.hex (deflated 59%)
  adding: fullimage.hex (deflated 61%)
  adding: softdevice.hex (deflated 59%)
+ rm -rf /tmp/cu_binaries_QB5YhzaUq4

Le script firmware/build.sh fait tout le travail à notre place et nous obtenons effectivement l'archive tant désirée dans ./firmware/objects/ultra-binaries.zip. Nous pouvons alors retenter la mise à jour du firmware avec le script shell :

$ firmware/flash-dfu-app.sh
Flashing ultra
[00:00:09] ###### 100% [2/2 C2737630B3E6] Programmed

Victoire ! De retour dans le client chameleon_cli_main.py, tout est maintenant fonctionnel :

[Offline] chameleon --> hw connect
{ Chameleon connected }
 
[USB] chameleon --> hw version
- Version: v1.0 (dev-197-gd928ab2)
 
[USB] chameleon --> hw slot list
- Slot 1 data (active):
   HF: Empty - Mifare Classic 1k
   LF: Empty - EM410X
- Slot 2 data:
   HF: Empty - Mifare Classic 1k
   LF: Empty - Unknown
- Slot 3 data:
   HF: Empty - Unknown
   LF: Empty - EM410X
- Slot 4 data (disabled):
   HF: Empty - Unknown
   LF: Empty - Unknown
- Slot 5 data (disabled):
   HF: Empty - Unknown
   LF: Empty - Unknown
- Slot 6 data (disabled):
   HF: Empty - Unknown
   LF: Empty - Unknown
- Slot 7 data (disabled):
   HF: Empty - Unknown
   LF: Empty - Unknown
- Slot 8 data (disabled):
   HF: Empty - Unknown
   LF: Empty - Unknown
- Mifare Classic emulator settings:
   Detection (mfkey32) mode: disabled
   Gen1A magic mode: disabled
   Gen2 magic mode: disabled
   Use anti-collision data from block 0: disabled
   Write mode: Normal

3. Utilisons (un peu) notre ChameleonUltra

À présent que nous avons un client qui fonctionne, nous pouvons faire un petit tour du propriétaire. Trois « activités » peuvent être envisagées ici : lire des tags, attaquer des tags (MIFARE) et émuler des tags. Je ne vais pas tout couvrir ici, loin de là, étant donné que la plupart des utilisateurs préféreront sans doute l'outil GUI plus intuitif. Je me contenterai donc d'un simple exemple pour présenter la philosophie du client officiel, en configurant une émulation de tag de A à Z.

Commençons par lister ce qui existe avec hw slot list. Je vous fais grâce de la sortie qui est identique à la précédente (insérée là pour l'effet dramatique), après la mise à jour du firmware. Nous décidons d'utiliser l'emplacement 6 pour émuler un tag MIFARE Classic 1K (S50) dont nous possédons l'image sous la forme d'un fichier de 1024 octets nommé « lav.bin ».

CU proxmark-s

Le « concurrent » du ChameleonUltra peut être vu comme étant le Proxmark 3 RDV4 (alias PM3) équipé d'un module BlueShark Standalone, mais en réalité, les objectifs poursuivis par ces deux matériels sont sensiblement différents. Le ChameleonUltra est clairement orienté vers l'émulation alors qu'un Proxmark 3 est dédié à l'analyse. Les deux cependant partagent nombre de fonctionnalités (lecture, écriture, émulation, attaques, etc.), mais le PM3 est capable de sniffer les communications et gère également les tags ISO-14443 type B (14b), ISO-15693, Felica, etc.

Nous commençons donc par rendre cet emplacement enable. J'utilise ici le terme anglais, car il y a une distinction à faire entre « activé » au sens enabled qui veut dire « disponible pour utilisation » et « actif » au sens active qui signifie que c'est l'emplacement actuellement utilisé pour faire une simulation. Nous faisons donc :

[USB] chameleon --> hw slot enable -s 6 -e 1
- Set slot 6 enable success.

-s désigne l'emplacement (attention, la liste commence à 1 et non à 0) et -e permet de choisir enable (1) ou disable (2). Notez que le client dispose d'une complétion automatique et d'une option -h permettant d'obtenir de l'aide pour toutes les commandes. Nous devons ensuite préciser le type de tag à émuler en utilisant la correspondance suivante (à cette date) :

  • 1 : EM410X ;
  • 2 : Mifare Mini ;
  • 3 : Mifare Classic 1k ;
  • 4 : Mifare Classic 2k ;
  • 5 : Mifare Classic 4k ;
  • 6 : NTAG 213 ;
  • 7 : NTAG 215 ;
  • 8 : NTAG 216.

Nous avons une image de MIFARE Classic 1K et nous utilisons donc la commande :

[USB] chameleon --> hw slot type -s 6 -t 3
- Set slot tag type success.

Tant que nous y sommes, et pour nous faciliter la vie par la suite lorsque nous aurons oublié ce que nous avons stocké dans le ChameleonUltra, nous pouvons donner un nom (ou nickname) à l'emplacement avec :

[USB] chameleon --> hw slot nick set -s 6 -st 2 -n mflav1k
- Set tag nick name for slot 6 success.

-s désigne le numéro de l'emplacement comme précédemment, -st (sense type) précise la technologie LF (1) ou HF (2) et enfin, -n permet de spécifier le nom choisi. Tout étant en place, nous n'avons plus qu'à mettre à jour la flash avec :

[USB] chameleon --> hw slot update
- Update config and data from device memory to flash success.

Et éventuellement vérifier avec un petit hw slot list :

[...]
- Slot 6 data (active):
   HF: mflav1k - Mifare Classic 1k
   LF: Empty - Unknown
[...]

Nous pouvons ensuite rendre actif cet emplacement avec :

[USB] chameleon --> hw slot change -s 6
- Set slot 6 activated success.

Ceci a le même effet que d'utiliser les boutons pour choisir un emplacement (et les boutons sont utilisables en même temps que le client). Il ne nous reste plus qu'à charger les données en mémoire et finaliser la configuration. Pour cela, nous utilisons une commande hf mf et non hw slot. Une commande permet de charger des données « brutes » en mémoire :

[USB] chameleon --> hf mf eload -f /chemin/lav.bin -t bin
.....................................................
...........
- Load success

-f précise le chemin vers le fichier (~/ ne fonctionne pas pour désigner votre $HOME) et -t le type de fichier, qui peut être binaire (bin) ou texte/hexadécimal (hex). Le type peut être omis si l'extension du fichier est respectivement .bin ou .eml (les formats supportés par le client Proxmark 3). Mais ce n'est pas tout. En effet, pour que l'émulation fonctionne, nous devons préciser des éléments de configuration que sont l'UID du tag et les paramètres d'anticollision (SAK et ATQA). Dans le cas d'un MIFARE Classic avec une UID de 4 octets, ces informations sont présentes dans l'image puisqu'il s'agit des quatre premiers octets pour l'UID, suivi de l'octet de vérification (inutile ici, car calculé), puis l'octet de SAK (Select AcKnowledge) à 0x08 (parfois 0x88 en réalité avec certains tags) et les deux octets de ATQA (Answer To reQuest type A) respectivement à 0x04 et 0x00. Nous définissons cela avec :

[USB] chameleon --> hf mf sim --sak 08 --atqa 0400 --uid 12B178C5
- Set anti-collision resources success

Nous vérifions avec :

[USB] chameleon --> hf mf info
- UID Size: 4
- UID Hex : 12B178C5
- SAK Hex : 08
- ATQA Hex : 0400

Et nous n'oublions pas de mettre à jour la flash :

[USB] chameleon --> hw slot update
- Update config and data from device memory to flash success.

Il ne nous reste plus qu'à quitter le client Python et déconnecter le ChameleonUltra pour lire le tag émulé en emplacement 6 avec un lecteur et/ou une application Android, par exemple. Dans mon expérimentation, le dispositif utilisant le tag d'où provient l'image n'a pas remarqué de différence, pas plus que l'app NFC Taginfo de Reasearch Lab Hagenberg, NFC Tools de Wakdev ou encore le très connu MIFARE Classic Tool (MCT) de Gerhard Klostermeier. Mais l'application TagInfo de NXP signale « Unknown Mifare class IC, possibly cloned » ce qui est intéressant (et pas uniquement parce que les dev de l'application n'ont pas lu le mémo précisant que c'est « MIFARE » et non « Mifare »).

Voici pour cette rapide démonstration qui, je vous assure, est plus facile à lire qu'elle a été à produire. La prise en main du ChameleonUltra est, pour l'instant, un peu déroutante. J'avoue que la logique de l'outil CLI en Python et la syntaxe des commandes me paraît très perturbante (non, ce n'est pas parce que je n'aime pas Python). Les numéros d'emplacement débutent à 1, certaines commandes prennent en argument un numéro d'emplacement, d'autres agissent sur l'emplacement actif, les informations sur l'émulateur MIFARE apparaissent avec hw slot list mais sont configurés par hf mf settings... C'est troublant, mais gageons que ceci comme le reste du projet se résoudra avec le temps. Et puis il y a toujours la possibilité de développer votre propre outil, dans le langage que vous préférez, pour avoir quelque chose qui vous est parfaitement adapté (et peut-être davantage dans un « esprit Unix »).

CU resine-s 0

La face avant du ChameleonUltra expose les composants utilisés, ce qui est du plus bel effet. Mais ceci est purement cosmétique, car même si cela protège effectivement le circuit, il devient impossible d'intervenir matériellement sur le produit. Si vous souhaitez un matériel équivalent, offrant ce genre de facilité, c'est vers le ChamleonUltra Dev Kit qu'il faudra vous orienter.

Un dernier mot cependant sur l'intérêt d'utiliser un ChameleonUltra pour une émulation de tag et non une autre solution comme une Ultimate Magic Card ou un porte-clés multi-RFID (comme [11] ou [12]). En réalité, ces deux pseudoéquivalents sont parfaits en comparaison, car le ChameleonUltra combine précisément les avantages des deux. Le porte-clés multi-RFID permet de combiner plusieurs tags (3 à 10) en un seul objet, tout en offrant la possibilité de modifier l'UID (selon modèle). L'Ultimate Magic Card (alias Gen4 GTU) n'est qu'un unique tag, mais qui peut être un MIFARE Classic, un MIFARE Ultralight EV1 ou un NTAG21x selon la configuration, tout en offrant des fonctionnalités « spéciales » comme le shadow mode. Disposer d'un ChameleonUltra, à terme, reviendra à avoir un jeu de 8 Ultimate Magic Cards qui, de plus, émule aussi les tags LF et fait office de lecteur USB. Sachant qu'à ~25 € la Magic Card (dans le meilleur des cas et en cherchant bien, tout en jonglant avec la quantité et le port pseudoaléatoire sur AliExpress), on arrive déjà à 200 €, on comprend mieux pourquoi le ChameleonUltra est à ce point intéressant et n'a pas fini de faire parler de lui.

À propos de fonctionnalités spéciales, l'émulateur de MIFARE Classic est configurable et vous permet d'activer différents modes de fonctionnement. Attention cependant, cette configuration n'est pas globale à tous les emplacements concernés (tous les HF pour le moment), même si elle semble ne pas changer entre les emplacements avec un hw slot list. En réalité, il s'agit d'un bug du script Python (signalé à l'instant par votre humble serviteur), car cette information dépend de l'emplacement actif. Si vous changez d'emplacement avec hw change -s 6 par exemple (ou les boutons du ChameleonUltra), ce sera la configuration de l'émulateur pour l'emplacement 6 qui sera affichée partout. Nul doute que ceci sera potentiellement corrigé au moment de la publication de l'article, mais cela démontre à quel point toute aide est utile au projet et qu'elle est facile à apporter (même si on n’aime pas Python).

Quoi qu'il en soit, voici ce qui s'affiche et ce qu'il faut savoir :

- Mifare Classic emulator settings:
   Detection (mfkey32) mode: disabled
   Gen1A magic mode: disabled
   Gen2 magic mode: disabled
   Use anti-collision data from block 0: disabled
   Write mode: Normal

Commençons par le plus évident, étant donné que nous venons de configurer les informations d'anticollision précédemment. Il est possible de directement déduire ces informations du bloc 0 de l'image en flash. Pour activer cette fonction, il suffit d'utiliser hf mf settings --coll 1 pour les tags avec des UID de 4 octets (par opposition à des tags avec des UID de 7 octets). Gen1A et Gen2 font référence aux technologies utilisées par les Magic Cards, permettant de changer leur UID (ce qui est impossible avec un tag « normal »). Un tag « magique » Gen1A permet cette modification en utilisant un enchaînement de commandes spéciales, alors qu'un tag Gen2 autorise, tout simplement, l'écriture du bloc 0 comme n'importe quel autre bloc (on parle aussi de tags CUID pour Changeable UID). Configurer un fonctionnement Gen1A et/ou Gen2 se fait respectivement avec hf mf settings --gen1a 1 et hf mf settings --gen2 1.

« Detection » référence une technique d'attaque consistant à solliciter non pas un tag, mais un lecteur et en collectant des nonces, des valeurs arbitraires générées pseudoaléatoirement, qui peuvent ensuite être utilisées pour déduire les clés (voir [13] à la partie « MFKEY32v2 walkthrough »). Pour activer la collecte de nonces, on utilisera hf detection enable -e 1. Notez que les clés calculées/déduites ne sont que celles utilisées par le lecteur, pas toutes celles potentiellement configurées dans un tag normalement utilisé avec ce dernier.

Et enfin, la cerise sur le gâteau, nous avons le mode d'écriture qui peut être :

  • Normal (hf mf settings --write 0), ce qui est écrit par le lecteur est effectivement enregistré ;
  • Denied (hf mf settings --write 1) qui refuse toute opération d'écriture (techniquement, le tag émulé est en lecture seule et répond des NACK) ;
  • Deceive (hf mf settings --write 2) pour accuser réception (ACK) de l'opération d'écriture, mais ne pas l'appliquer réellement ;
  • et Shadow (hf mf settings --write 3) pour que le tags émulé procède « virtuellement » aux écritures et permette une relecture, mais « en RAM ». Si le tag quitte le champ électromagnétique, sa mémoire revient à son état initial.

CU bulles-s 0

La résine qui couvre le circuit assure une protection pour un usage courant (même si rayable facilement) et on distingue des bulles d'air emprisonnées à certains endroits. Je ne peux m'empêcher de me questionner sur la façon dont va effectivement vieillir cette finition et s'il n'y a pas un risque, à long terme, pour l'intégrité du produit lui-même (jaunissement, décollage, fissure des soudures dues à une rétractation de la résine, etc.).

Conclusion

Avant toute chose et même si je peux paraître très critique dans mes propos en début d'article, il est important de bien comprendre que le code, à la fois pour le firmware et le client Python, est en permanente évolution. Des ajouts et corrections sont faits régulièrement et à l'heure où cet article est fini d'être rédigé, une partie de ces évolutions peut être disruptive si, comme moi, vous vous lancez dans un développement lié au protocole utilisé par le ChameleonUltra. Ceci pour vous dire clairement que l'achat de ce matériel est un investissement qui va se bonifier dans le temps et à terme valoir son pesant d'or. Pour preuve, je remarque à cet instant précis que Sébastien Dudek, dont le nom ne vous est pas inconnu si vous êtes également lecteur de Misc, vient tout juste d'annoncer sur Twitter (ou « X », ou je ne sais quel nouveau nom inventé par le troll en chef de cette plateforme) qu'il travaille sur l'implémentation de l'émulation MIFARE Ultralight.

Oui, pour le moment le nombre de types de tags émulés et/ou lus/écrits est limité. Oui, le fait que le client Python compte les emplacements à partir de 1 est totalement traumatisant (*tousse* Lua *tousse*) et le jeu de commandes un peu désordonné. Et, oui, une application GUI en Flutter implique de nombreuses dépendances à installer (faites un simple ldd sur chameleonultragui et vous comprendrez). Mais tout ceci sera finalement très secondaire lorsque le ChameleonUltra deviendra pleinement opérationnel et pourra, dans une certaine mesure, remplacer totalement une collection d'Ultimate Magic Cards, et en même temps faire office de lecteur RFID/NFC proche de ce qu'offre un Proxmark 3 RDV4 (sans pour autant le remplacer vraiment).

C'est un sujet qu'on pourrait presque qualifier de « en friche » (NDLR : de moins en moins au fil du temps, cf. [9]), et la raison pour laquelle je n'ai pas creusé et décrit ici tout ce que fait déjà le ChameleonUltra (attaques, collecte de nonces, lecture, etc.). Finalement, deux options s'offrent à vous : vous jeter dans le bain immédiatement pour vivre/suivre l'aventure, ou tout simplement attendre que le support logiciel se bonifie sans votre aide et ne céder à la tentation que plus tard. Personnellement, mon choix était fait dès que le produit est devenu (à nouveau) disponible chez un distributeur officiel, mais ça, c'est peut-être juste moi...

En guise de mots de la fin, je préciserai que la communauté est très active, massive et accueillante, et se retrouve sur le serveur Discord « RFID Hacking » de Iceman [14], en plus de l'écosystème existant via GitHub. Saluons également le fabricant du ChameleonUltra (et du Proxmark 3 RDV4), RRG (RFID Research Group), qui a initialement développé le matériel, le firmware et l'outil CLI, puis les a remis aux mains de la communauté (prenez-en de la graine, Nordic). Et pour finir, un grand merci à Philippe pour ses conseils avisés et commentaires.

Références

[1] https://github.com/RfidResearchGroup/ChameleonUltra

[2] https://github.com/GameTec-live/ChameleonUltraGUI

[3] https://play.google.com/store/apps/details?id=io.chameleon.ultra

[4] https://apps.apple.com/app/chameleon-ultra-gui/id6462919364

[5] https://play.google.com/store/apps/details?id=com.mtoolstec.mtoolsLite

[6] https://www.nordicsemi.com/Products/Development-tools/nrf-util

[7] https://www.nordicsemi.com/Products/Development-tools/nrf-command-line-tools/download

[8] https://github.com/NordicSemiconductor/pc-nrfutil

[9] https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/docs/development.md

[10] https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads

[11] https://lab401.com/fr/products/multi-rfid-keyfob

[12] https://fr.aliexpress.com/item/1005002324917760.html

[13] https://github.com/RfidResearchGroup/ChameleonUltra/blob/main/docs/cli.md

[14] https://t.ly/d4_C



Article rédigé par

Par le(s) même(s) auteur(s)

Raspberry Pi Pico 2 : double double cœur ARM et RISC-V

Magazine
Marque
Hackable
Numéro
59
Mois de parution
mars 2025
Spécialité(s)
Résumé

Cela fait quelque temps déjà qu'une nouvelle Pico est arrivée chez les revendeurs et fait doucement son bonhomme de chemin. Celle-ci intègre un nouveau microcontrôleur très particulier qui, en plus de fournir davantage de ressources que son prédécesseur, à une double nature : ARM Cortex-M33 et RISC-V Hazard3. Le fait d'utiliser l'une ou l'autre architecture est laissé au choix du développeur et nous allons bien entendu explorer les deux options. Pour accompagner cette évolution, le SDK lui aussi change en passant de la version 1.5.1 à 2.0.0, puis dernièrement, à 2.1.0. Faisons donc un petit tour de ce que tout cela implique...

Vous reprendrez bien un peu d'assembleur avec votre fugu ?

Magazine
Marque
GNU/Linux Magazine
Numéro
274
Mois de parution
mars 2025
Spécialité(s)
Résumé

Dans un précédent article [1], nous avons fait connaissance avec la possibilité (semi-sérieuse) de développer nos outils en ligne de commande en assembleur, pour le plaisir (et par masochisme). Ce qui va suivre n'est pas réellement une suite, mais plus exactement une exploration autour du sujet, accompagnée de quelques explications autour de la notion de Position Independent Code ou PIC.

NouveauLes derniers articles Premiums

Nouveau Les derniers articles Premium

Bun.js : l’alternative à Node.js pour un développement plus rapide

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Dans l’univers du développement backend, Node.js domine depuis plus de dix ans. Mais un nouveau concurrent fait de plus en plus parler de lui, il s’agit de Bun.js. Ce runtime se distingue par ses performances améliorées, sa grande simplicité et une expérience développeur repensée. Peut-il rivaliser avec Node.js et changer les standards du développement JavaScript ?

PostgreSQL au centre de votre SI avec PostgREST

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Dans un système d’information, il devient de plus en plus important d’avoir la possibilité d’échanger des données entre applications. Ce passage au stade de l’interopérabilité est généralement confié à des services web autorisant la mise en œuvre d’un couplage faible entre composants. C’est justement ce que permet de faire PostgREST pour les bases de données PostgreSQL.

La place de l’Intelligence Artificielle dans les entreprises

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

L’intelligence artificielle est en train de redéfinir le paysage professionnel. De l’automatisation des tâches répétitives à la cybersécurité, en passant par l’analyse des données, l’IA s’immisce dans tous les aspects de l’entreprise moderne. Toutefois, cette révolution technologique soulève des questions éthiques et sociétales, notamment sur l’avenir des emplois. Cet article se penche sur l’évolution de l’IA, ses applications variées, et les enjeux qu’elle engendre dans le monde du travail.

Petit guide d’outils open source pour le télétravail

Magazine
Marque
Contenu Premium
Spécialité(s)
Résumé

Ah le Covid ! Si en cette période de nombreux cas resurgissent, ce n’est rien comparé aux vagues que nous avons connues en 2020 et 2021. Ce fléau a contraint une large partie de la population à faire ce que tout le monde connaît sous le nom de télétravail. Nous avons dû changer nos habitudes et avons dû apprendre à utiliser de nombreux outils collaboratifs, de visioconférence, etc., dont tout le monde n’était pas habitué. Dans cet article, nous passons en revue quelques outils open source utiles pour le travail à la maison. En effet, pour les adeptes du costume en haut et du pyjama en bas, la communauté open source s’est démenée pour proposer des alternatives aux outils propriétaires et payants.

Les listes de lecture

7 article(s) - ajoutée le 01/07/2020
La SDR permet désormais de toucher du doigt un domaine qui était jusqu'alors inaccessible : la réception et l'interprétation de signaux venus de l'espace. Découvrez ici différentes techniques utilisables, de la plus simple à la plus avancée...
8 article(s) - ajoutée le 01/07/2020
Au-delà de l'aspect nostalgique, le rétrocomputing est l'opportunité unique de renouer avec les concepts de base dans leur plus simple expression. Vous trouverez ici quelques-unes des technologies qui ont fait de l'informatique ce qu'elle est aujourd'hui.
9 article(s) - ajoutée le 01/07/2020
S'initier à la SDR est une activité financièrement très accessible, mais devant l'offre matérielle il est parfois difficile de faire ses premiers pas. Découvrez ici les options à votre disposition et les bases pour aborder cette thématique sereinement.
Voir les 34 listes de lecture

Abonnez-vous maintenant

et profitez de tous les contenus en illimité

Je découvre les offres

Déjà abonné ? Connectez-vous