Je me suis récemment attaqué à la rétro-ingénierie du Ninja Badge de la DEFCON 18, et il se trouve que ce badge communique avec d'autres badges similaires via la couche MAC du protocole ZigBee (IEEE 802.15.4). Disposant d'un HackRF One, j'ai réussi à décoder les messages envoyés à l'aide de Gnuradio Companion, mais il m'était très difficile de coder un outil permettant de faire de l'envoi et de la réception en simultané, le HackRF One n'étant pas full-duplex. Il m'a donc fallu trouver un plan B.
Quand il s'agit de recevoir et de transmettre des paquets ZigBee, le framework Killerbee sauve pas mal la vie. Ce framework écrit en Python s'interface avec des équipements adaptés, et est en mesure de sniffer et injecter des paquets ZigBee. Enfin, quand on l'utilise avec des équipements qui le permettent. En effet, le seul device abordable qui était compatible avec ce framework est le RZ Raven d'ATMEL, dont la production a été arrêtée et qui est actuellement introuvable. Les équipements restants sont plus coûteux, comme l'ApiMote d'Attify (150$), le TelosB Mote, ou encore des cartes Silicon Labs compatibles (~300€). Par ailleurs, il existe bien un second équipement pas cher, une clé USB à base de TI CC2531, mais cette dernière ne supporte que le sniffing, ce qui ne me suffisait pas.
J'ai donc commandé une de ces clés USB à base de TI CC2531, et j'ai réussi à capturer des paquets ZigBee et à débuter l'analyse du protocole de communication du badge. Cependant, impossible d'envoyer de manière fiable des paquets, et donc d'interagir avec ce dernier. Je commençais sérieusement à douter du framework, et songeais à trouver une solution alternative. Il était clair à ce moment que personne n'avait implémenté le support de l'injection de paquet pour cette clé USB, malgré plusieurs demandes faites via des issues sur leur repository Github. La réponse apportée ? "Do it yourself", si je résume le propos. Eh bien faisons ça alors.
Ayant déjà développé sur des puces gérant des communications radio dans le cadre de mes recherches sur le protocole Bluetooth Low Energy, développer un firmware spécifique pour la puce TI CC2531 ne me faisait pas tellement peur. Par contre, si je pouvais éviter d'y passer trois semaines, ça m'arrangerait passablement. J'ai donc commencé à scruter le web à la recherche de kits de développement permettant de développer pour cette puce, avec potentiellement le support de la couche radio déjà disponible. Je suis assez rapidement tombé sur le code de Contiki, un micro-système d'exploitation qui supporte notamment la puce en question. Et pour lequel la couche radio est déjà implémentée, yippie !
Je me suis donc lancé dans le développement de ce firmware, en ajoutant une couche de communication par port série (exposé via la connectique USB) afin de piloter la puce à partir d'un ordinateur qui communique avec le code gérant la radio. La structure de Contiki, qui propose un semblant de processus, permet d'implémenter cela de manière très simple. Le premier test a pu être rapidement effectué, et s'est montré très concluant: j'arrivais à sniffer et transmettre des paquets ZigBee, autrement dit j'avais une bonne base de travail. J'ai bouclé le développement du firmware en moins d'une semaine, et mis le code à disposition (ainsi qu'une release pré-compilée) sur mon repository Github associé.
Développer un firmware c'est bien, mais faire en sorte que Killerbee puisse communiquer avec est encore mieux. En parallèle, j'ai donc implémenté un driver spécifique dans le framework Killerbee, capable de communiquer avec le firmware en question et qui supporte ainsi le sniffing et l'injection de paquets. Ce développement a été effectué sur la branche py3 du projet, qui n'est pas encore la version 3.0 officielle de Killerbee mais qui devrait l'être une fois que le portage sur Python 3.0 sera terminé, grâce à la réactivité de RiverLoopSec qui a poussé des modifications en attente quand je les ai sollicité sur Twitter (encore merci à eux !).
Ce driver est ainsi capable de sniffer des paquets ZigBee, avec pour seule limitation que ces paquets doivent avoir un FCS (une somme de contrôle) valide (il est possible d'ajouter le support des paquets invalides, mais je ne l'ai pas encore fait). Il est par ailleurs capable d'envoyer des paquets, là encore sans possibilité de contrôler le FCS. Mais c'est bien suffisant pour ce que j'ai à faire sur ce matériel. Il a d'ailleurs fallu trouver un petit nom à ce firmware, et celui proposé par tartofraise lors d'un live Twitch a été retenu: Bumblebee.
Le code du driver est intégré dans mon fork de Killerbee, disponible en suivant ce lien.
Le code source et une version pré-compilée du firmware ont été rendus publics sur mon dépôt Github associé, qui détaille par ailleurs plusieurs méthodes permettant d'installer ce dernier sur une clé TI CC2531. Basiquement, il vous faudra un programmateur CC-Debugger, ou un Raspberry Pi voire un Arduino. Une fois le firmware installé sur la clé, cette dernière est prête à l'emploi.
Sur l'ordinateur, installer killerbee à l'aide de l'outillage Python:
$ git clone --branch py3 https://github.com/virtualabs/killerbee.git
$ cd killerbee
$ python3 setup.py sdist
$ sudo pip3 install dist/killerbee-2.7.1.tgz
Killerbee est installé et prêt à l'emploi, y compris le support de Bumblebee. Vous pouvez désormais utiliser tous les outils classiques de Killerbee avec cette clé USB !
Si vous trouvez des bugs, ou souhaitez des améliorations, n'hésitez pas à soumettre des issues ou des feature requests, et pourquoi pas des pull requests !
Je ne pensais pas écrire ce bout de texte maintenant, mais il semblerait qu'il en ait été décidé autrement. Un coup de fil d'un ami proche, passé un samedi midi ensoleillé, et que j'ai loupé car occupé à préparer le repas avec ma petite famille. J'ai répondu par SMS un "Tu voulais ?", histoire de voir si ça pouvait se régler simplement en quelques messages échangés. "Rappelle, important". Ce que je fis, donc. Pour apprendre que David M a.k.a dvrasp, un ami de longue date, s'est éteint la veille sans crier gare. Après Paolo, Peter, Simon, la communauté HZV perd un de ses plus anciens membres. Et nous, eh bien, on en a gros.
Ma première rencontre avec David s'est passé sur IRC, le Discord des vieux. A l'époque, j'étais étudiant et m'amusais à creuser le format de fichier des programmes exécutables de Windows, et je l'ai contacté pour savoir s'il y avait moyen de publier un article dans feu The Hackademy Magazine, dont il était rédacteur en chef. Il a trouvé l'idée sympa, et c'est ainsi que mon premier article est paru, en 2005. Ma première rencontre IRL avec David s'est déroulée quelques mois plus tard, quand nous discutions avec la société d'édition pour laquelle il travaillait d'un projet de magazine que nous souhaitions lancer, XeLoRy et moi-même. Ce premier vrai contact m'a marqué: j'ai découvert une personne qui semblait très réfléchie, ouverte et amicale. Nous avons assez peu échangé ce jour là, en vérité. Ce fut pour moi l'occasion de mettre un visage sur un pseudonyme, ce qui n'était pas rien. Nous avons continué à échanger par la suite, des articles, des idées, du code. Jusqu'à ce qu'il me fasse suivre une offre d'emploi.
A ce moment là, ma situation personnelle était assez précaire: j'étais étudiant, en couple, avec un loyer et une voiture, mais de maigres revenus. J'avais pris la décision de chercher du travail afin de pouvoir être serein et démarrer dans la vie active, et nous en avions discuté. David et moi étions d'accord sur le fait que pigiste n'était pas une situation d'avenir, surtout avec les retards de paiement de la société d'édition. Quand quelqu'un l'a contacté pour savoir s'il pouvait passer une annonce pour une offre d'emploi particulière, il y a jeté un oeil et a directement pensé à moi. Il s'agissait d'un poste d'ingénieur de développement C/C++ pour lequel des connaissances en reverse engineering étaient souhaitées. J'ai lu en diagonale l'offre, et me suis arrêté sur "Vous êtes diplômé(e) d'une école d'ingénieur ou équivalent universitaire (Bac + 5)". Je lui ai répondu que je n'avais pas ce niveau, et donc que je ne correspondais pas au profil. Il a insisté. Durant un mois, presque. Jusqu'à ce que je me décide à envoyer une lettre de motivation et un CV. Deux semaines plus tard, après un entretien téléphonique et un rendez-vous à Paris, j'étais embauché. "Je te l'avais dit que ton profil ferait l'affaire !", m'a-t-il répondu lorsque je lui annonçait la nouvelle. C'est grâce à David que j'ai eu mon premier job. Pas moins que ça.
Nous nous croisions régulièrement durant les meetings HZV organisés à Sysdream, l'occasion de discuter autour d'une bière ou quinze, mais aussi lors des Nuits du Hack que nous organisions plus ou moins de façon anticipée. Je me rappelle en particulier de la Nuit du Hack 2007, lorsque nous rentrions chacun chez nous via le premier RER du matin (ou presque). David était en face de moi, sa sacoche sur les genoux. Il l'ouvre, regarde dedans, et sort un "Ohhh meeerde ! Je crois que j'ai oublié mon laptop !" ... avant de se raviser et de sortir un ordinateur portable qui prenait toute la place dans la sacoche. Ainsi qu'un petit livre intitulé "Memoirs of a virus programmer", qu'il me présente comme étant un excellent ouvrage que je devrais lire, et me le donne ensuite. Nous nous quitterons quelques stations plus loin, nous donnant rendez-vous à un prochain meeting HZV ou à la prochaine Nuit du Hack, ou encore sur IRC. J'avalais le livre dans la semaine et effectivement, ce fut une lecture très intéressante. Quelques années plus tard, c'est à 4 heures du matin que l'on s'est retrouvé pour rédiger les slides de la présentation que je donnais le jour même lors d'une Nuit du Hack. L'occasion de bien rigoler et de fignoler le support d'un talk en y intégrant des références subtiles (ou pas), tout en l'ayant lui comme public fictif, challengeant mes arguments et posant des questions afin d'améliorer ma préparation.
J'ai ce souvenir de David, quelqu'un de sincère et généreux, intelligent et perspicace, avec qui j'ai eu de nombreuses discussions éclairées ou éclairantes. Je garde ces quelques anecdotes de lui et bien d'autres (mais impossible de toutes les narrer dans un billet de blog), ces moments simples où l'on se marrait, sa bienveillance. Repose en paix, l'ami.
Je suppose que vous n'êtes pas passé à côté de la nouvelle, mais en ce moment c'est confinement. Je me retrouve donc à la maison avec mes deux minis-moi (un de 6 ans, l'autre de 7) que je dois occuper tant bien que mal. Une fois passé le stock de jeux de sociétés dont nous disposons, pourtant bien fourni, je me suis rapidement retrouvé sans munition.
Et c'est là que j'ai aperçu une de mes boîtes de Unlock, un escape game à base de cartes qui nous a fait passer de bonnes soirées, et je me suis dit: "Et pourquoi ne pas inventer un escape game pour enfants en CP/CE1 ?".
J'ai de suite pensé à utiliser un cadenas pour l'épreuve finale, et en particulier mon cryptex de chez Ugears que j'ai eu à Noël il y a deux ans. Oui mais il y a un hic: je ne me souviens absolument plus du code de ce dernier ! Le code de ce cryptex est défini lors du montage, et est donc fixe. La première étape a donc été de retrouver ce code à 3 chiffres, sans faire de recherche exhaustive car bien trop longue (il faut placer les anneaux de manière à ce qu'ils soient parfaitement alignés sur la combinaison pour que le cryptex s'ouvre) ! J'ai donc opté pour une méthode plus rapide, assez similaire aux techniques employées sur certains cadenas à bagues: le décodage.
Le principe du cryptex est simple: chaque anneau possède une encoche en face du chiffre qui lui est associé dans la combinaison, ce qui n'autorise la partie mobile (l'anse) à ne bouger que lorsque les encoches des anneaux sont alignées avec la barre de verrouillage, autrement dit lorsque la bonne combinaison est choisie. L'objectif quand on cherche à décoder la combinaison est donc de retrouver la position de ces encoches à l'aide d'un outil nommé "décodeur".
J'ai utilisé une canette vide pour en récupérer la tôle, puis découpé cette dernière de façon à avoir une fine languette de métal. En plaçant cette dernière entre deux anneaux (ou rotors), et en faisant tourner ces derniers, la languette est "attrapée" par l'encoche et entraînée dans la rotation de l'anneau, dévoilant ainsi un chiffre de la combinaison. J'ai ainsi pu retrouver les trois chiffres composant cette combinaison, et ouvrir le cryptex (ouf !).
Je pensais que cela allait être une tâche facile de créer cet escape game, mais non. La particularité des escape games basé sur des cartes, comme Unlock, c'est que la plupart des actions nécessitent de faire des combinaisons. Unlock utilise par ailleurs une application pour Android et iOS afin de proposer des casse-têtes, des puzzles, et même de la réalité augmentée. En ce qui me concerne, je n'avais pas le temps de développer une application aussi complexe, cela va de soi. Il faut donc anticiper un tantinet les numéros que l'on va attribuer aux cartes, afin d'éviter les erreurs et de permettre l'utilisation de valeurs crédibles en fonction des éléments à trouver.
Je me suis donc lancé en début d'après-midi, en partant de recherches sur Google Images pour trouver mes images de base (il ne vous aura pas échappé que je ne suis point graphiste, et heureusement) et Inkscape pour la conception des cartes. Il m'a fallu un peu plus d'une heure pour pondre une histoire et une ébauche de résolution, créer les différentes cartes et intégrer le tout.
J'ai ensuite imprimé l'ensemble des cartes, les ai découpées et assemblées. Je les ai ensuite essayées en y jouant avec mes minis-moi, qui se sont bien pris au jeu !
Cette phase de test a été l'occasion de trouver des erreurs, de penser à des améliorations, en bref de le rendre un poil meilleur ! Car bon, il ne faut pas l'oublier: il s'agit d'un petit escape game conçu en moins de 2 heures avec les moyens du bord.
J'ai aussi publié sur Twitter et Instagram une photo de ce jeu, et plusieurs personnes ont manifesté leur intérêt. Du côté de la famille et des amis, où on avait fait passer quelques photos, c'était la même chose. L'idée a donc germé de le diffuser. Et pour le diffuser, il faut l'améliorer et le rendre utilisable par d'autres (aïe).
La première modification apportée a été de changer le nom. En effet, le nom d'origine était "Le trésor d'Ecco Vid", mais la blagounette n'a pas été directement comprise par les enfants. Dommage. Sur conseil de mon épouse, j'ai changé le nom de Ecco Vid en Ecco Rona, qui sonne mieux et annonce de suite la couleur :). J'ai aussi procédé à plusieurs bugfix suite à la session de test (quelques erreurs sur des numéros, un numéro caché trop visible, etc.), et ai ajouté toute une section concernant les règles (encore trop sommaires à mon goût), l'assemblage et la personnalisation.
Après ces quelques heures supplémentaires à fignoler les cartes et les énigmes, j'ai tout poussé sur Github (fichiers de conception SVG, polices de caractères utilisées et PDF final), et vous pouvez donc vous en resservir. Vous pouvez imprimer le jeu à partir du fichier PDF ou bien le modifier comme il vous chante ce dernier, pour l'adapter à votre situation (cadenas différent, énigmes plus corsées, à vous d'improviser !).
Le tout est diffusé sous licence Creative Commons CC-BY-NC-SA, donc faites vous plaisir !