14
janv.
'19

Livre: Habemus Piratam, de Pierre Raufast

Publié le 14 janvier 2019

Chose n'est pas coutume, je vais parler d'un livre sur ce blog. Non pas que j'aie peur de ne publier que peu de billets sur cette année 2019 ou pris une résolution qui ne tiendront que quelques mois, mais parce que je suis tombé dessus quelque peu par hasard et que je l'ai apprécié. Ce livre, c'est Habemus Piratam de Pierre Raufast. C'est aussi le livre coup de coeur du CLUSIF.


Couverture de Habemus Piratam, crédit motspourmots.fr

C'est l'histoire d'un pirate

Comme le titre laisse supposer, il s'agit d'un roman traitant de religion chrétienne et de piratage, parodiant le célèbre Habemus Papam annonçant l'élection d'un Pape par un conclave. L'histoire de l'abbé Francis, néophyte en informatique, qui reçoit la confession d'un mystérieux pirate dans son église de la vallée de Chantebrie, entre diverses grenouilles de bénitier et autres pénitents. Ce mystérieux pirate raconte ses différents méfaits, avec moults détails, relatant l'usage de drones ou encore des plus viles techniques de piratage telles que de l'ingénierie sociale ou l'installation de logiciels malveillants. Pendant que d'autres crimes et délits se déroulent en parallèle dans le village, démontrant parfois l'utilité des objets connectés dans le contexte de certaines investigations, pour ne citer que cet exemple.

L'auteur fait dans ce roman un étalage de différentes attaques informatiques, du point de vue de ce mystérieux pirate, détaillant la réflexion derrières celles-ci et leur mise en oeuvre; tout en restant abordable et compréhensible pour quiconque n'étant pas expert dans le domaine. C'est un livre divertissant (je l'ai lu d'une traite !), techniquement correct (aucune attaque réellement impossible ou purement inspirée du cinéma) et qui peut amener une réflexion quant à notre usage des technologies, en particulier ces satanés mouchards d'objets connectés.

Un livre accessible aux frileux des technologies

Pierre Raufast dépeint dans ce roman le quotidien d'un abbé découvrant le piratage au travers des confessions d'un mystérieux pirate, sans pour autant connaître les bases de la sécurité informatique ou la cyberdélinquance. L'auteur en profite pour introduire toutes les notions nécessaires à la bonne compréhension des attaques, méthodes, outils mais aussi la manière de penser de ce pirate, tout en restant compréhensible pour tout un chacun. En somme, ce livre éclaire le lecteur sur les attaques actuelles ou qui peuvent se produire, tout en abordant les risques et les enjeux: données, argent virtuel, réputation, tout y passe. Faites-le lire à vos proches, et ils vous assailleront de questions: "est-ce que c'est possible de faire cela ?", "tu crois que je devrais arrêter de poster toutes mes photos sur Facebook ?", "tu connais un objet connecté qui ne t'espionne pas ?".

Habemus Piratam a le mérite de sensibiliser tout en distrayant, voire même d'éveiller la curiosité du lecteur. Les références aux outils ou techniques sont présentes et justes (on y parle de netcat, de keyloggers et autres pare-feus), les scénarios d'attaques possibles voire réalistes -- en particulier ceux impliquant les réseaux sociaux, et cela a même de quoi intimider le lecteur à certains moments du livre. Il ne serait pas étonnant que cet ouvrage amène un certain nombre de ses lecteurs à effectuer, à l'instar de l'abbé Francis, des recherches sur Internet à propos de ces outils, et découvrir des articles ou tutoriels d'utilisation de ceux-ci.

De Hervé à Damien, en passant par Cédric ou encore L'ANSSI

Une des particularités de ce livre, c'est qu'il fait référence à des personnes, personnages et évènements français connus de la sécurité informatique. Ainsi, il est fait mention d'un certain Damien rencontré lors de la nuit du hack, et de son fameux protocole (non, il ne s'agit pas de moi mais plutôt d'un autre Damien ayant un protocole d'alerte), ou encore de Cédric qui "[propose] illico de rédiger un article dans sa revue". D'autres noms ponctuent les différentes histoires, comme par exemple Ryu ou Zelda, ou encore un programme nommé "Babar" avec pour signature "Titi" (toute ressemblance avec un programme existant est purement fortuite).

La culture pop et geek s'est ainsi invitée dans le roman, par petites touches et références savamment dosées et distillées au fil de la progression de l'histoire, arrachant un sourire au lecteur par sa subtilité ou l'absurdité dans laquelle elle survient. Que cela fasse référence à des jeux vidéos, des logiciels malveillants ou encore des pseudonymes de pirates célèbres, les lecteurs avertis y trouveront aussi leur compte.

Habemus Piratam est un roman rafraîchissant, traitant de techniques et d'outils de piratage, le tout servi par une histoire prenante et des personnages attachants. C'est un livre qui se lit avec plaisir, que l'on soit expert en sécurité informatique ou ignorant, et qui peut amener à une réflexion sur notre vie numérique et ses enjeux.



Habemus Piratam, Pierre Raufast, Alma Editeur, 2018.

27
déc.
'18

European Cybersecurity Challenge 2018

Publié le 27 décembre 2018

En octobre dernier se déroulait à Londres le challenge européen de cybersécurité, réunissant 17 pays de l'Union Européenne pour un CTF assez particulier. Chaque pays est représenté par une équipe de 10 participants et un ou plusieurs entraîneurs (sans compter les membres organisateurs de chaque pays), ce qui représentait ainsi plus de 200 personnes réunies pour cette compétition. J'ai ainsi eu le privilège d'être un des entraîneurs de l'équipe représentant la France lors de ce CTF, avec Heurs et Ack. Petit retour sur cette compétition hors-norme, et débriefing à froid.

Ce billet se veut être un compte-rendu de l'évènement tel que je l'ai vécu, et n'est en aucun cas un résumé de ce qu'est l'ECSC. Je vous invite à écouter l'épisode de NoLimitSecu dédié à cet évènement, auquel j'ai participé avec Maki, Anne-Charlotte et Ack, si vous souhaitez avoir plus de détails.

"Hey virtu, ça te dirait d'être coach de l'équipe de France de CTF?"

C'est un peu en ces termes que majinbooœ, président de l'association HZV, m'a apostrophé. En effet, suite au round de qualification qu'avait organisé l'ANSSI durant la Nuit du Hack 2018 (RIP), HZV devait participer à l'organisation de l'entraînement de l'équipe sélectionnée, à raison de la mise à disposition de 2 entraîneurs. Après quelques discussions, il fut décidé que Heurs et moi-même soyons désignés comme entraîneurs, aux côtés de personnes de l'ANSSI. L'aventure était lancée.

Il s'agissait de la première participation de la France à cette compétition, et cela signifiait plusieurs choses. La première, c'est que nous n'avions absolument aucune idée du type et du niveau de compétition de l'ECSC: aucun write-up n'a été publié, assez peu de retours techniques sur le contenu des épreuves ou le type de CTF. Le seul moyen de le savoir était de participer. La seconde, c'est que l'on allait être attendus par les autres équipes, et potentiellement ciblés en tant que bleus (dans tous les sens du terme). La dernière et non des moindres, c'est qu'une pression était présente de par l'envergure de l'évènement, que j'ai d'abord pris relativement à la légère.

De mon côté, j'ai participé mais aussi organisé plusieurs CTFs (dont certains de type attaque/défense, don't blame me) depuis plusieurs années, bien que cela fait désormais un certain temps que ma participation se limite à une modeste contribution dans une équipe qui n'a vocation qu'à s'amuser et non terminer dans le peloton de tête. Et encore, quand je trouve le temps de résoudre des épreuves et que celles-ci ne nécessitent pas trop de temps. Le fait d'avoir des minis-moi n'aide pas, j'en ai bien peur. Toujours est-il que je ne m'estime pas être un pourfendeur de CTF, et j'ai eu un peu de mal intérieurement à penser que je pourrais vraiment aider l'équipe à progresser.

Rendez-vous fut ainsi pris pour septembre afin d'organiser la session d'entraînement de l'équipe de France.

Premier contact avec l'équipe

Début septembre, l'ANSSI avait organisé une session de deux jours pour que l'équipe et les entraîneurs puissent faire connaissance, et débutent comme il se doit une période d'entraînement. Je ne m'étais pas trop renseigné sur les heureux sélectionnés, et je decouvris le jour J les personnes composant cette équipe. Il y avait là 13 jeunes gens, membres de différentes équipes de CTFs françaises (Inshallhack, Aperi'kube, Hexpresso entre autres), des habitués des CTFs et de p0wnage en série, dont un millenial. Je crois que c'est à ce moment que j'ai pris conscience du temps qui a passé, et que je me suis senti vieux.

Ces deux jours ont été très instructifs et m'ont permis de faire connaissance avec l'équipe, de voir les points forts et faibles de chacun, avec toujours ce sentiment de ne pas parler le "djeun's" actuel. Une sensation de parent, pour être totalement honnête. Ce moment où tu te sens en décalage, un peu comme un père relou qui essaie de se la péter auprès de tes potes. Pour ne rien arranger, ma vie professionnelle m'a obligé à m'absenter à plusieurs moments tandis que l'équipe, composée majoritairement de pentesteurs juniors ou apprenti pentesteurs, profitait pleinement des réjouissances CTFesques prévues durant cette période. Néanmoins, un passage au bar a permis de faire plus ample connaissance autour de quelques bières, d'un diabolo menthe et de mojitos. On ne le dira jamais assez, mais rien ne vaut quelques boissons et des anecdotes de CTF ou de pentest pour souder une équipe de CTF !

Le reste de l'entraînement s'est déroulé en ligne et à distance, Ack, Heurs et moi-même distillant nos conseils et challenges maison afin de préparer au mieux l'équipe. Cette période nous a permis aussi de mieux comprendre leur fonctionnement, et de voir dans quelle mesure ces membres d'équipes habituellement concurrentes pouvaient s'entendre pour établir une organisation nouvelle et résoudre efficacement des challenges.

Départ et arrivée à Londres

Le voyage pour Londres s'est déroulé sans trop de problèmes (si ce n'est un bagage abandonné en gare du Nord), et nous arrivâmes à Londres à l'heure prévue. Le temps de prendre le Tube pour nous rendre aux Tobacco Docks, l'endroit où se déroule la compétition, et nous pûmes tester notre installation en conditions réelles. Vous vous souvenez, je mentionnais un peu plus tôt notre méconnaissance de ce challenge ? Eh bien ça n'a pas loupé: nous n'avions pas prévu de switch ni de point d'accès (faute de temps) et nous nous sommes retrouvés avec des services hébergés sur des Raspberry Pi connectés au réseau WiFi. Sans pouvoir nous connecter à ces derniers, le WiFi en place faisant de la ségrégation de clients. Merci CISCO. A côté de nous, les Allemands ont monté un joli point d'accès en mode bridge et ont câblé tous leurs laptops à ce dernier, avec bien sûr quelques Raspberry Pi pour les services de collaboration. Pourquoi n'y avions nous pas pensé...

L'équipe de France de CTF teste l'installation

Une fois les préparatifs effectués, direction l'hôtel pour poser les valises et rejoindre l'ensemble des participants et des organisateurs pour un repas de bienvenue. L'hôtel est superbe, juste en face du Tower Bridge et à deux pas de la Tour de Londres. Dommage que le temps soit si pluvieux. Nous nous retrouvons donc au repas, autour d'une tablée "France", tout au fond de la salle (en bons élèves que nous sommes). Et c'est à ce moment là que survint le premier moment awkward: les vidéos de présentation des équipes. L'organisation côté France a été informée du fait qu'il faille réaliser une vidéo de présentation de l'équipe, introduisant les participants et les entraîneurs, mais elle pensait à l'origine que ce n'était pas important. Devinez quoi ? Cela le fut. Car oui, la vidéo de présentation de chaque équipe fut projetée, et nous nous sommes rendus compte à quel point certaines d'entre elles avaient été imaginatives. Sans parler du budget ou de la réalisation elle-même. Je pense qu'il fut assez clair que notre participation était la première, mais elle a tout de même reçu un bon accueil. C'est juste que l'on a passé les jours suivants à essayer d'expliquer le pourquoi des avatars présents sur notre vidéo.

Les avatars de l'équipe de France (une partie du moins)

Une fois le repas terminé, j'organisais une petite session de rappel sur les attaques et exploitations hardware, car ce fut un des thèmes annoncés par les organisateurs de la compétition. L'organisation n'a eu de cesse de dire que tout ce dont on aurait besoin serait mis à disposition, j'en profitais pour faire un dernier point avec l'équipe sur les outils et logiciels requis. Puis ce fut l'heure d'aller dormir en vue de la compétition du lendemain.

Deux jours de compétition

En tant qu'entraîneurs, Ack et moi-même avions seulement le droit de discuter avec le capitaine de l'équipe, Maki, pour faire le point et les guider en fonction des tâches à réaliser. Pour le reste, nous étions relégués dans une salle annexe, sans vue directe sur le score ni sur l'équipe. Nous n'avions évidemment pas accès à la plateforme du CTF, et donc aucun moyen de surveiller l'évolution du classement et du score des différentes équipes en direct. Cela fut résolu assez rapidement à l'aide d'un peu de scripting Python, le score fourni par le site web de l'évènement étant synchronisé sur les scores actuels des équipes. Nous ne disposions pas des informations concernant la validation des challenges ni l'historique, mais c'était déjà mieux que rien. Nous disposions par ailleurs de Red Bull à volonté (ce qui n'était définitivement pas une bonne chose), d'un accès Internet, de prises de courant et d'une salle (trop) chauffée agrémentée de (quelques) confortables fauteuils et canapés. Le minimum vital pour survivre.

La première journée s'est clôturée avec un score honorable pour notre équipe, et une troisième position plutôt encourageante. Il y a eu beaucoup de mouvement durant la dernière heure, plusieurs équipes ayant validé de nombreuses épreuves avant la clôture de la journée. Car oui, chaque journée avait son lot d'épreuves uniques, le CTF ne se déroulant pas la nuit. Après un repas bien mérité, ce fut l'heure d'aller se reposer afin de se préparer pour la seconde journée de compétition.

Cette seconde journée fut rude pour l'équipe et nous-même entraîneurs, pour plusieurs raisons. La première raison est que le matériel mis à disposition pour un challenge hardware basique était limité à un seul adaptateur FTDI. L'équipe a galéré sur ce qui se présentait comme une épreuve facile, et nous avons perdu du temps précieux à casser un identifiant et un mot de passe par défaut relativement bidons. L'équipe italienne quant à elle disposait d'un programmateur adéquat (dixit leur entraîneur), et a pu extraire le firmware et chercher les chaînes de caractères. 5 minutes montre en main. C'est à ce moment là que je m'en suis voulu d'avoir fait confiance aux organisateurs, sur le fait que "tout le nécessaire serait fourni". En ce qui concerne les épreuves hardware, il valait mieux venir équipé. On saura pour la prochaine fois. La seconde raison est propre à la plateforme de CTF, avec le souci bien connu du format de flag. Il se trouve que certaines (beaucoup ?) d'épreuves ne suivaient aucune règle quant à la structure des flags. Cela pouvait être un simple texte, ou bien une list d'adresses IP séparées par des virgules par exemple. Un autre flag devait être soumis sous forme de date/heure, mais le format donné en exemple (01/01/1970) ne permettait pas de déduire s'il s'agissait d'un format MM/DD/YYYY ou DD/MM/YYYY. Bref, il fallut se débrouiller et s'en remettre au guessing et à un poil de bruteforce pour se tirer de ces situations.

Il restait toutefois une épreuve particulière à passer: le bandstand. Aucune information n'a fuité sur cette épreuve (ou plutôt cette série d'épreuves), et nous stressions un peu à l'idée de devoir l'affronter. Une fois une partie des membres de l'équipe entrés, nous (entraîneurs) n'avions aucune information et l'impossibilité de communiquer avec eux. Cette épreuve était cruciale car elle permettait de remporter un nombre non-négligeable de points, dont nous avions besoin pour remonter dans le classement. Le stress était palpable, en particulier le mien qui a été augmenté par un certain nombre de Red Bulls que j'avais consommé durant les heures précédentes. En guise d'épreuve, il s'agissait d'un escape game cyberpunk plutôt cool d'après l'équipe, qui l'a terminé haut la main en battant le record de temps et du nombre d'épreuves terminées ! Nous nous sommes alors senti soulagés, et l'équipe a pris les devants de la compétition en remontant à la première place. Je dois dire que ce fut un soulagement, avec l'angoisse juste après de savoir si l'équipe allait réussir à maintenir cette position.

Plusieurs fois les allemands et les anglais ont chamboulé le classement de tête, mais notre équipe arrivait fièrement à contrecarrer cela et revenir en tête, le tout se jouant à quelques milliers de points (ce qui était peu vu les scores atteints à ce moment de la compétition). Pour au final se faire coiffer au poteau par l'équipe allemande, qui a validé à quelques minutes de la fin une épreuve lui donnant la victoire. Le match fut au final très serré, et la tension lors de la dernière demi-heure atroce, les deux équipes étant relativement proche au classement mais aussi physiquement: les allemands occupaient la tablée d'à côté. Cloture du score, pas d'annonce des résultats. Angoisse. Heureusement, le site de l'évènement affichait les derniers scores (vous vous souvenez, la synchronisation ;) et nous avons pu avoir le classement final: la France en seconde position. L'équipe était déçue de s'être fait déchoir de la première place à si peu de temps de la fin de la compétition, mais nous en avons profité pour débriefer avec les allemands et faire plus ample connaissance.

L'après-compétition

l'annonce du classement final a été faite durant la soirée, dans un bar roof-top où l'ensemble des participants et des entraîneurs ont pu se remettre de leurs émotions (et les équipes enchaîner sur un concours de cul-sec avec des représentants de chaque pays, on s'amuse comme on peut). L'Allemagne a ainsi fini en première position, suivie de la France et du Royaume-Uni.

Le lendemain se déroulait la cérémonie de remise des prix, organisée sur un bateau vogant sur la Tamise, où notre équipe s'est vue remettre un trophée et un prix par participant. Nous avons aussi pris la photo de l'équipe, et avons pu profiter de cette ballade pour admirer London by night. Pour enchaîner avec le CTF de Hack.lu une fois rentré à l'hôtel. Je me suis acharné sur une épreuve de stéganographie qui s'est révélée être infaisable (comme nous l'avait indiqué un des membres de l'équipe allemande proche de FluxFingers), mais que voulez-vous, j'avais trouvé un chunk bizarre dans un fichier ZIP et était persuadé d'être sur une piste (merci à Ange Albertini pour ses infos préciseuses sur les formats de fichiers divers et variés, c'est toujours d'un grand secours).

Remise des prix (crédits: ANSSI)

Puis taxi, Eurostar, Paris, et le retour au boulot. Cette parenthèse londonienne s'est terminée aussi vite qu'elle a commencée, mais j'en garde un bon souvenir. J'ai rencontré des types futés, qui ont été capables de s'entendre et de collaborer au sein d'une équipe soudée, capables de poncer des challenges et de persévérer, de représenter la France durant cette compétition et de terminer à la seconde place du podium alors que c'était notre première participation. A ceux-là, je leur tire mon chapeau. En tant qu'entraîneur, je n'ai pas senti que ma présence sur place ait été d'une quelconque utilité quant à la résolution technique des épreuves (pour ma part j'ai souvent servi de canard lors de duck debugging), mais j'ai le sentiment d'avoir été utile quand à la préparation de l'équipe. Le rôle d'entraîneur dans le contexte de cette compétition consiste à travailler en amont, et les dés sont quasimment jetés au moment où se déroule la compétition. L'équipe fait le reste, et elle l'a très bien fait.

On remet ça en 2019 ?

29
juin
'17

L'attaque du porte-clé intercepteur

Publié le 29 juin 2017

Lors de la quinzième édition de la Nuit du Hack, qui avait lieu ce week-end au New York Hotel de Disneyland Paris, j'ai présenté un moyen simple et pas cher de concevoir un équipement permettant de réaliser des attaques sur le protocole Bluetooth Low Energy (BLE), voire de simuler le comportement de n'importe quel équipement BLE. Je n'ai pas eu le temps d'entrer dans les détails, aussi vais-je le faire dans ce billet de blog.

Recyclage de Gablys

Cela fait quelques années que je cotoie des Gablys, des porte-clés connectés en BLE à des smartphones permettant de détecter la perte de clés ou d'objets, qui peut accessoirement être utilisé comme télécommande pour déclencher des selfies ou retrouver son smartphone égaré (une fonction de localisation inversée, en quelque sorte).

Un Gablys est assez simple: l'ensemble repose sur un transceiver de Nordic Semiconductor capable de communiquer en BLE, le nRF51822. Ce transceiver intègre un CPU ARM ainsi qu'une mémoire Flash de 256Kio, et a la particularité d'être débuggable et programmable via OpenOCD. De plus, il possède de base un bouton poussoir ainsi qu'un buzzer piezzo, qui permettent une interaction utilisateur (quoique l'on peut s'en passer selon les usages).

Les avantages du nRF51822 sont multiples:

Bref, il est dès lors possible de reprogrammer un Gablys afin de lui faire faire ce que l'on veut, à l'aide d'outils standards.

Installation des logiciels nécessaires

Pour réussir à développer et tester un firmware opensource pour Gablys, j'ai commencé par télécharger la version 11.0 du SDK de Nordic Semiconductor. Pourquoi la version 11.0 me direz-vous ? Parce que c'était celle a priori employée pour développer le firmware original de la bête. Notez que la dernière version du SDK devrait tout aussi bien fonctionner, mais il faudra prendre en compte les évolutions des fonctions exposées par ce dernier.

Tout d'abord, on télécharge la version voulue du SDK (la version 12.0 par exemple sur le site de Nordic Semiconductor. On dézippe le fichier dans un dossier prévu à cet effet:

$ unzip nRF5_SDK_12.3.0_d7731ad.zip
$ mv nRF5_SDK_12.3.0_d7731ad nrf5-sdk

Il nous faut ensuite installer la toolchain ARM et en ce qui me concerne j'ai préféré installer une version à jour plutôt que celle de ma debian, en la téléchargeant directement à partir du site d'ARM. J'en ai profité pour la décompresser dans un dossier à part, nommé toolchain:

$ cd nrf5-sdk && mkdir toolchain && cd toolchain
$ wget "https://developer.arm.com/-/media/Files/downloads/gnu-rm/6_1-2017q1/gcc-arm-none-eabi-6-2017-q1-update-linux.tar.bz2?product=GNU%20ARM%20Embedded%20Toolchain,64-bit,,Linux,6-2017-q1-update"
$ tar xvjf gcc-arm-none-eabi-6-2017-q1-update-linux.tar.bz2

Une fois la toolchain ARM décompressée, il suffit de la déclarer dans le fichier components/toolchain/gcc/Makefile.posix du SDK Nordic Semiconductor:

GNU_INSTALL_ROOT := /home/virtualabs/nrf5-sdk/toolchain/gcc-arm-none-eabi-6-2017-q1-update/
GNU_VERSION := 6.3.1
GNU_PREFIX := arm-none-eabi

Enfin, il nous faut ajouter une configuration particulière pour notre Gablys dans le fichier examples/bsp/gablys.h. Pour ce faire, il suffit de copier un fichier de configuration existant:

$ cp pca20006.h gablys.h

Nous en profitons pour ajouter une ligne dans le fichier boards.h du même dossier afin de déclarer notre board:

...

#elif defined(BOARD_N5DK1)
  #include "n5_starterkit.h"
#elif defined(BOARD_GABLYS)
  #include "gablys.h"
#elif defined(BOARD_CUSTOM)
  #include "custom_board.h"
#else
#error "Board is not defined"

...

Puis de modifier la fin du fichier afin de ne pas utiliser de quartz basse-fréquence, absent sur notre Gablys:

// Low frequency clock source to be used by the SoftDevice
#define NRF_CLOCK_LFCLKSRC      *                      \
    .source        = NRF_CLOCK_LF_SRC_RC,            \
    .rc_ctiv       = 16,                                                 \
    .rc_temp_ctiv  = 2,                                               \
   .xtal_accuracy = NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM \
*

De cette manière, tous les codes exemples fonctionneront sans problème avec notre Gablys, ce dernier ne possédant pas d'oscillateur basse-fréquence. Il est alors temps de lancer notre première compilation, et voir si ces modifications portent leurs fruits.

Première compilation

Pour essayer notre configuration, nous allons tenter de compiler une application BLE sur mesure, ble_app_beacon. Pour ce faire, nous allons ajouter une configuration propre à notre Gablys, et faire en sorte de tout configurer pour que cela compile correctement.

Dans un premier temps, il nous faut créer une arborescence sur mesure:

$ cd nrf5-sdk/examples/ble_peripheral/ble_app_beacon/
$ mkdir -p gablys/s130/armgcc/
$ cp pca20006/s130/config ./gablys/s130/ -rf
$ cp pca20006/s130/armgcc ./gablys/s130/armgcc -rf

Puis nous éditons dans un premier temps le fichier Makefile situé dans le dossier gablys/s130/armgcc/, afin de déclarer notre board plutôt que celle d'origine (PCA20006). Pour ce faire, il faut changer les options de compilation -DBOARD_PCA20006 en -DBOARD_GABLYS:

# Libraries common to all targets
LIB_FILES += \

# C flags common to all targets
CFLAGS += -DSWI_DISABLE0
CFLAGS += -DSOFTDEVICE_PRESENT
CFLAGS += -DNRF51
CFLAGS += -DNRF51822
CFLAGS += -DS130
CFLAGS += -DBLE_STACK_SUPPORT_REQD
CFLAGS += -DBOARD_GABLYS
CFLAGS += -DNRF_SD_BLE_API_VERSION=2
CFLAGS += -mcpu=cortex-m0
CFLAGS += -mthumb -mabi=aapcs
CFLAGS +=  -Wall -Werror -O3 -g3
CFLAGS += -mfloat-abi=soft
# keep every function in separate section, this allows linker to discard unused ones
CFLAGS += -ffunction-sections -fdata-sections -fno-strict-aliasing
CFLAGS += -fno-builtin --short-enums

# C++ flags common to all targets
CXXFLAGS += \

# Assembler flags common to all targets
ASMFLAGS += -x assembler-with-cpp
ASMFLAGS += -DSWI_DISABLE0
ASMFLAGS += -DSOFTDEVICE_PRESENT
ASMFLAGS += -DNRF51
ASMFLAGS += -DNRF51822
ASMFLAGS += -DS130
ASMFLAGS += -DBLE_STACK_SUPPORT_REQD
ASMFLAGS += -DBOARD_GABLYS
ASMFLAGS += -DNRF_SD_BLE_API_VERSION=2

Et on lance la compilation avec make:

$ make
mkdir _build
Compiling file: nrf_log_backend_serial.c
Compiling file: nrf_log_frontend.c
Compiling file: app_button.c
Compiling file: app_error.c
Compiling file: app_error_weak.c
Compiling file: app_timer.c
Compiling file: app_util_platform.c
Compiling file: hardfault_implementation.c
Compiling file: nrf_assert.c
Compiling file: sdk_errors.c
Compiling file: boards.c
Compiling file: nrf_drv_clock.c
Compiling file: nrf_drv_common.c
Compiling file: nrf_drv_gpiote.c
Compiling file: nrf_drv_uart.c
Compiling file: bsp.c
Compiling file: bsp_nfc.c
Compiling file: main.c
Compiling file: RTT_Syscalls_GCC.c
Compiling file: SEGGER_RTT.c
Compiling file: SEGGER_RTT_printf.c
Compiling file: ble_advdata.c
Compiling file: ble_conn_params.c
Compiling file: ble_srv_common.c
Assembling file: gcc_startup_nrf51.S
Compiling file: system_nrf51.c
Compiling file: softdevice_handler.c
Linking target: _build/nrf51822_xxaa.out

   text        data     bss     dec     hex filename
  11808         136     616   12560    3110 _build/nrf51822_xxaa.out

Preparing: _build/nrf51822_xxaa.hex
Preparing: _build/nrf51822_xxaa.bin

Le code compile parfaitement, et le Makefile produit un fichier binaire ainsi qu'un fichier au format ihex, dont nous allons nous servir pour programmer le nRF51822 présent sur le Gablys.

Programmation du Gablys

Le Makefile standard est fait pour fonctionner avec l'outil nrfjprog, cependant il est possible de le faire fonctionner avec OpenOCD et un STLink v2 à la chinoise.

Première étape, installer OpenOCD. La version 0.10.0 tirée de Github fera l'affaire. Vous pouvez tout aussi bien l'installer via les paquets standards de votre distribution, cela devrait fonctionner de la même façon.

On modifie donc la fin de notre fichier Makefile pour y intégrer deux cibles: la première nommée flash permettant de flasher l'application, la seconde nommée flash_softdevice permettant de flasher le SoftDevice [1].

flash: nrf51822_xxaa
    @echo Flashing: $(OUTPUT_BINARY_DIRECTORY)/$<.hex
    openocd -f interface/stlink-v2.cfg -f target/nrf51.cfg -c init -c "reset init" -c "halt" -c "program _build/nrf51822_xxaa.hex verify" -c "reset" -c "exit"

## Flash softdevice
flash_softdevice:
    @echo Flashing SoftDevice s130 ...
    openocd -f interface/stlink-v2.cfg -f target/nrf51.cfg -c init -c "reset init" -c "halt" -c "nrf51 mass_erase" -c "program $(abspath ../../../../../../components/softdevice/s130/hex/s130_nrf51_2.0.1_softdevice.hex) verify" -c "reset" -c "exit"

Ensuite, il faut connecter correctement le STLink à notre Gablys:

Puis flasher d'abord le SoftDevice, et ensuite l'application:

$ make flash_softdevice && make flash
Flashing SoftDevice s130 ...
openocd -f interface/stlink-v2.cfg -f target/nrf51.cfg -c init -c "reset init" -c "halt" -c "nrf51 mass_erase" -c "program /home/virtualabs/nrf5-sdk/components/softdevice/s130/hex/s130_nrf51_2.0.1_softdevice.hex verify" -c "reset" -c "exit"
Open On-Chip Debugger 0.10.0+dev-00146-g1025be36 (2017-06-16-16:35)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.246408
Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000006d0 msp: 0x000007c0
Info : nRF51822-QFAA(build code: G2) 256kB Flash
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0xfffffffe msp: 0xfffffffc
** Programming Started **
auto erase enabled
Info : Padding image section 0 with 2112 bytes
Warn : using fast async flash loader. This is currently supported
Warn : only with ST-Link and CMSIS-DAP. If you have issues, add
Warn : "set WORKAREASIZE 0" before sourcing nrf51.cfg to disable it
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000001e msp: 0xfffffffc
wrote 110592 bytes from file /home/virtualabs/nrf5-sdk/components/softdevice/s130/hex/s130_nrf51_2.0.1_softdevice.hex in 4.979112s (21.691 KiB/s)
** Programming Finished **
** Verify Started **
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000002e msp: 0xfffffffc
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000002e msp: 0xfffffffc
verified 108448 bytes in 0.698049s (151.717 KiB/s)
** Verified OK **
Flashing: /nrf51822_xxaa.hex
openocd -f interface/stlink-v2.cfg -f target/nrf51.cfg -c init -c "reset init" -c "halt" -c "program _build/nrf51822_xxaa.hex verify" -c "reset" -c "exit"
Open On-Chip Debugger 0.10.0+dev-00146-g1025be36 (2017-06-16-16:35)
Licensed under GNU GPL v2
For bug reports, read
    http://openocd.org/doc/doxygen/bugs.html
Info : auto-selecting first available session transport "hla_swd". To override use 'transport select <transport>'.
Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
adapter speed: 1000 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : Unable to match requested speed 1000 kHz, using 950 kHz
Info : clock speed 950 kHz
Info : STLINK v2 JTAG v17 API v2 SWIM v4 VID 0x0483 PID 0x3748
Info : using stlink api v2
Info : Target voltage: 3.246408
Info : nrf51.cpu: hardware has 4 breakpoints, 2 watchpoints
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000006d0 msp: 0x000007c0
target halted due to debug-request, current mode: Thread
xPSR: 0xc1000000 pc: 0x000006d0 msp: 0x000007c0
** Programming Started **
auto erase enabled
Info : nRF51822-QFAA(build code: G2) 256kB Flash
Warn : using fast async flash loader. This is currently supported
Warn : only with ST-Link and CMSIS-DAP. If you have issues, add
Warn : "set WORKAREASIZE 0" before sourcing nrf51.cfg to disable it
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000001e msp: 0x000007c0
wrote 12288 bytes from file _build/nrf51822_xxaa.hex in 0.589847s (20.344 KiB/s)
** Programming Finished **
** Verify Started **
target halted due to breakpoint, current mode: Thread
xPSR: 0x61000000 pc: 0x2000002e msp: 0x000007c0
verified 11944 bytes in 0.088029s (132.503 KiB/s)
** Verified OK **

La programmation du SoftDevice et de l'application se sont bien déroulées, tout comme la vérification de la bonne écriture du code. De base, le CPU a été remis à zéro après la programmation, et si vous avez laissé votre Gablys connecté, celui-ci doit annoncer un périphérique BLE ressemblant à un beacon.

Il est temps d'aller plus loin dans le code source, afin d'implémenter quelque chose d'utile !

Firmware opensource pour Gablys

J'ai profité de l'occasion pour développer un firmware opensource pour Gablys, réimplémentant les principaux services et leurs characteristics, et se comportant presque à l'identique. Le code source de ce firmware est disponible sur Github. Ce dernier peut être compilé et flashé comme décrit précédemment.

En pratique, les services propres au Gablys sont implémentés dans le fichier gss/gss.c, dont la fonction ble_gss_init a pour rôle la création et l'initialisation de l'ensemble de ces services et des characteristics associées. A noter l'astuce avec le SDK Nordic pour déclarer un service ayant un UUID sur 128 bits:

static const ble_uuid128_t m_btn_uuid128 =
    {
       {
           0x45, 0xfa, 0x56, 0xc1, 0xfb, 0x1b, 0xc0, 0x28,
           0x96, 0xa8, 0x67, 0x18, 0x01, 0x28, 0x17, 0x4f
       }
    };

    /* ... du code ici ... */

    /* Add Gablys Button service. */
    ble_btn_uuid.uuid = GSS_BTN_SERVICE_UUID;
    err_code = sd_ble_uuid_vs_add(&m_btn_uuid128, &ble_btn_uuid.type);
    APP_ERROR_CHECK(err_code);

    err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
                            &ble_btn_uuid,
                            &p_gss->btn_service_handle);

    if (err_code != NRF_SUCCESS)
    {
        return err_code;
    }

Enfin, la stack BLE est initialisée dans le fichier main.c, grâce à la fonction ble_stack_init:

static void ble_stack_init(void)
{
    uint32_t err_code;

    nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;

    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);

    ble_enable_params_t ble_enable_params;
    err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
                                                    PERIPHERAL_LINK_COUNT,
                                                    &ble_enable_params);
    APP_ERROR_CHECK(err_code);

    //Check the ram settings against the used number of links
    CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT);

    // Enable BLE stack.
    sd_ble_enable(&ble_enable_params, &app_ram_base);
    ble_enable_params.common_enable_params.vs_uuid_count = 10;
    err_code = softdevice_enable(&ble_enable_params);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);
}

C'est d'ailleurs dans cette fonction que l'on peut rajouter du code permettant d'usurper une adresse MAC, comme ci-dessous:

static void ble_stack_init(void)
{
    uint32_t err_code;
    ble_gap_addr_t address;

    address.addr_type = BLE_GAP_ADDR_TYPE_PUBLIC;
    address.addr[0] = 0xFE;
    address.addr[1] = 0xFE;
    address.addr[2] = 0xC0;
    address.addr[3] = 0x15;
    address.addr[4] = 0x4D;
    address.addr[5] = 0xDE;

    nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;

    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);

    ble_enable_params_t ble_enable_params;
    err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
                                                    PERIPHERAL_LINK_COUNT,
                                                    &ble_enable_params);
    APP_ERROR_CHECK(err_code);

    //Check the ram settings against the used number of links
    CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT,PERIPHERAL_LINK_COUNT);


    // Enable BLE stack.
    sd_ble_enable(&ble_enable_params, &app_ram_base);
    ble_enable_params.common_enable_params.vs_uuid_count = 10;
    err_code = softdevice_enable(&ble_enable_params);
    APP_ERROR_CHECK(err_code);

    sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &address);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);

    // Register with the SoftDevice handler module for BLE events.
    err_code = softdevice_sys_evt_handler_set(sys_evt_dispatch);
    APP_ERROR_CHECK(err_code);
}

Une fois compilé et flashé, le nouvel équipement est visible avec l'adresse MAC DE:4D:15:C0:FE:FE, comme le montre l'exemple ci-dessous (testé avec l'exemple beacon et non le firmware opensource):

Vous vous imaginez bien à ce stade de la lecture qu'il n'est pas très difficile de recréer n'importe quel équipement Bluetooth Low Energy à partir de ce petit porte-clé, et qu'avec un peu d'imagination et de temps on pourrait mettre à mal la sécurité de quelques équipements, voire réaliser des attaques très ciblées sur des périphériques communiquant en BLE.

Ok, et quoi d'autre ?

Nous avons démontré qu'il était possible d'utiliser un Gablys comme plateforme de développement peu onéreuse, à l'aide de logiciels libres et d'équipement à bas coût (STLink v2 notamment), et de profiter des avantages de ce dernier: il est petit, peu gourmand en énergie, programmable à volonté et alimenté par une pile bouton !

Il est dès lors possible de le mettre dans une poche et de simuler un équipement existant jusqu'à utiliser la même adresse Bluetooth (MAC), disons par exemple un cadenas connecté, et d'amener une application sur smartphone à transmettre à ce faux cadenas un code confidentiel (cette dernière faisant confiance à l'adresse Bluetooth du cadenas), comme je l'ai démontré l'année dernière lors de la Nuit du Hack.

J'ai placé le SDK modifié avec les examples cités dans cet article sur un repository spécifique, si certains d'entre vous veulent tester sans tout modifier à la main.

[1] Pour plus d'information sur les SoftDevice de NordicSemiconductor, consulter la page dédiée sur le site du fondeur



Les contenus disponibles sur ce blog sont publiés sous licence Creative Commons BY-NC-SA.
Vous pouvez réutiliser tout ou partie de ces contenus à condition de citer l'auteur et l'origine, vous ne pouvez en faire une utilisation commerciale, et enfin vous devez partager tout travail ou œuvre dérivée sous les mêmes conditions — c'est-à-dire avec la même licence d'utilisation Creative Commons.