Pompe à insuline à ingénierie inverse pour la thérapie de bricolageIl y a environ trois ans, j'ai entendu parler d'un site Web offrant une récompense pour être très proche de mon cœur: la rétro-ingénierie des communications avec une pompe à insuline. J'ai déjà aidé à créer un
système pour ma fille appelé
Loop , avec une pompe Medtronic pour laquelle je fais de l'ingénierie inverse des communications (la plupart du protocole de communication Medtronic principal a été décodé par Ben West à l'aide de Carelink USB, et j'ai découvert les fréquences radio et fait un travail supplémentaire sur protocole). Mais la pompe Medtronic a dû être arrêtée pendant la gymnastique pendant plusieurs heures. Le design tubeless de cette pompe Omnipod m'a paru intéressant, et j'avais tous les outils pour travailler.
Le système Omnipod se compose d'une petite pompe à usage unique appelée module (pod) et d'une unité de contrôle (PDM).
Étant donné que le PDM communique avec le module par radio et que le module n'a pas d'interface intégrée, cela signifie qu'il est entièrement radiocommandé. Il existe une possibilité d'intégration complète avec Loop, en utilisant uniquement
RileyLink ou sa version modifiée.
James Wedding a nommé une récompense, qui a attiré beaucoup d'attention, puis les bonnes personnes qui ont aidé dans le travail.
Radio définie par logiciel
Le SDR est un
formidable outil . Il rend visible le monde caché de la radio. Il existe une variété de types de messages qui sont constamment diffusés dans l'air, et ces outils vous permettent de fouiner, d'afficher des messages et, après un certain travail, de décoder les petits éclairs que vous voyez là-bas. Si vous recherchez des messages à partir d'un appareil spécifique, vous devez savoir dans quelle zone commencer la recherche. C'est là que les documents publics de la FCC sont utiles.
La documentation FCC pour PDM,
RBV-019 , indique que l'appareil transmet dans la bande 433 MHz. Après avoir configuré le logiciel SDR pour écouter dans la plage 433 MHz, les signaux suivants apparaissent lors de l'émission de l'état à partir de PDM:

Comme je l'ai finalement découvert, ces deux lignes lumineuses indiquent un certain type de modulation appelé
fréquence shift keying , ou FSK. Cela signifie que la fréquence du signal varie en fonction des informations transmises. Le bit 1 est envoyé comme une fréquence plus élevée (ligne supérieure) et 0 est envoyé avec une fréquence légèrement inférieure (ligne inférieure). En utilisant l'outil d'
inspection, nous pouvons analyser les données pour reconnaître plus clairement 1 et 0. Voici une vue considérablement agrandie du premier message:

J'ai écrit un script python pour extraire ces bits afin que nous puissions les regarder comme des packages entiers.

Il s'avère que ce motif répétitif fait partie du
préambule . Pour économiser de l'énergie, les récepteurs passent souvent en mode veille et se réveillent périodiquement pour vérifier le signal. L'émetteur envoie le préambule suffisamment longtemps pour que le récepteur l'attrape pendant l'une des courtes périodes d'écoute. Lorsque le récepteur entend le préambule, il se réveille jusqu'à ce que des données réelles apparaissent.
Vous devez passer par une autre couche avant d'obtenir les données réelles du lot. Vous ne pouvez pas envoyer vos données sur la radio exactement de la même manière que les bits d'origine, car le récepteur utilise des transitions pour se synchroniser dans le temps quand attendre le bit suivant. Si vous avez un long ensemble de zéros ou de uns, le récepteur peut se désynchroniser. Par conséquent, les communications radio utilisent généralement le codage pour vérifier qu'il y a suffisamment de transitions. Les communications omnipodes utilisent le soi-disant
codage Manchester . Chaque bit est codé en deux bits. 1 est codé comme 10 et 0 est codé comme 01.
Il a fallu beaucoup de temps pour le découvrir, et il y avait beaucoup de théories sur
le canal openomni à Slack alors que nous essayions de répéter les bits originaux.
Mark Brighton ,
Dan Caron et
@larsonlr ont réussi à utiliser
RFCat et
Ti Stick pour capturer des paquets.
Evarist Kurgio a finalement écrit un outil appelé
rtlomni , il utilise le récepteur USB rtl-sdr pour écouter les paquets et les décoder, ce qui s'est avéré très pratique et plus fiable que les méthodes basées sur TI Stick.
Décodage de paquets
Après avoir reçu les bits réels, nous avons commencé à étudier la structure du paquet. Sur la base des bits qui ont changé entre différents modules et différentes équipes, nous avons créé une structure qui ressemble à ceci:

CRC8
La radio est loin d'être un support de transmission idéal. Il existe de nombreuses sources d'interférences différentes qui font que le récepteur entend 1 lorsque 0 est envoyé, et vice versa. Il est important de savoir quand cela s'est produit, de sorte que la plupart des protocoles utilisent une somme de contrôle, souvent appelée CRC. Le récepteur calcule le CRC à mesure que les données sont reçues, et le dernier octet du paquet inclut le CRC calculé par l'émetteur. S'ils ne correspondent pas, le récepteur rejette le paquet et attend la retransmission.
Le protocole Omnipod utilisait le CRC 8 bits standard. Lorsque nous l'avons trouvé, nous avons décidé que nous étions très près de comprendre les messages. Comme nous en savions peu ...
Messages, CRC16
Certains messages sont trop volumineux pour tenir dans un seul package, ils sont donc divisés en plusieurs packages. Nous avons commencé à reconstituer le format du message et avons remarqué un autre ensemble de bits à la fin de chaque message, qui ressemblait à un CRC 16 bits. Mais c'était étrange: 5 bits sur 16 n'ont jamais été définis. Nous avons essayé de
nombreuses méthodes différentes pour comprendre comment cela est codé, mais rien n'a fonctionné.
C'était le premier gros problème: nous pouvions continuer à travailler sur d'autres bits dans les messages, mais cela n'aiderait pas beaucoup à comprendre ce qui est envoyé, et nous ne pourrons pas générer nous-mêmes de nouveaux paquets, donc les progrès ont ralenti.
Plusieurs mois se sont écoulés presque en vain. Enfin, à l'hiver 2016, un membre du groupe sous le surnom
@lorelai a déclaré qu'elle avait copié avec succès le micrologiciel d'une puce ARM plus grande vers PDM et commencé le processus de désassemblage fastidieux: accepter les instructions du processeur et les transformer en code lisible par l'homme avec des variables sémantiques et des noms de fonction. Elle a fait un travail incroyable en découvrant les différentes méthodes utilisées pour transmettre les données.
J'ai regardé l'une des routines sans titre et j'ai remarqué qu'elle ressemblait à une implémentation standard du calcul CRC à partir d'une table. Et la table avait des valeurs pour le CRC 16 bits standard. J'ai écrit ma propre implémentation sur des tables, et elle a été testée comme un CRC normal. Ensuite, j'ai regardé attentivement comment la fonction a été écrite. Une implémentation CRC normale ressemble à ceci:
while (len--) { crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)]; }
Leur implémentation ressemblait à ceci:
while (len--) { crc = (crc >> 8) ^ crctable[((crc >> 8) ^ *c++)]; }
Remarquez la différence? Ce qui était censé être un opérateur de décalage gauche au niveau du bit a été en quelque sorte codé comme un décalage droit. C'est une erreur; Il n'y a aucune raison de paralyser votre propre algorithme CRC, car cela rend difficile l'identification des messages corrompus.
Nous sommes de retour en opération! Et ils ont repris le travail sur le décodage des messages, les sessions d'enregistrement à partir du PDM pour l'administration de bolus [médicaments], les bases temporaires [Le débit basal temporaire détermine une augmentation ou une diminution de l'administration d'insuline - env. voie], suspension du classement, etc.
Numéro à usage unique
Toutes les équipes d'administration d'insuline avaient une donnée de 4 octets au début du message, qui ressemblait à une forme de cryptographie. Encore une fois, nous avons essayé de nombreuses façons différentes de l'interpréter et de l'analyser dans le contexte des messages dans lesquels il a été envoyé, mais ce n'était pas CRC (parfois nous avons vu les mêmes 4 octets même dans des messages différents). Et parfois, nous avons vu l'image se répéter. Elle semblait, peut-être, faire partie d'un protocole visant à empêcher la reproduction des données. Dans d'autres protocoles, une fonction similaire est appelée
nonce .
L'une des options que nous avons envisagées consistait à enregistrer une base de messages pour lire les commandes données. Même si l'adresse de chaque module était différente, nous savions maintenant comment générer un CRC, afin que nous puissions prendre la copie précédente de la commande, mettre la nouvelle adresse sur le message et recompter le CRC. Seul ce nonce nous a empêché d'utiliser cette stratégie. Quelle que soit la commande, le module n'a accepté que le nonce suivant dans la séquence, et nous ne savions pas comment générer le nonce suivant.
Mais! Après tout, nous avons un firmware PDM décompilé, nous pouvons simplement y regarder! Nous avons donc étudié le micrologiciel PDM, suivi la génération de messages dans le code et trouvé où ces quatre octets devraient être. Mais au lieu d'une méthode qui calcule un nonce cryptographique, nous venons de trouver quatre caractères
INS.
. Quelle absurdité?!?! Eh bien, cette zone de message doit être mise à jour plus tard dans le pipeline.
Il y avait une autre puce sur le PDM, plus près de la radio. C'était la même puce qui était utilisée dans les modules, avec l'identifiant SC9S08ER48, qui n'était pas documentée sur Internet. Il a probablement été fabriqué sur commande pour l'Insulet. Peut-être que nous pouvons supprimer le firmware de cette puce. Malheureusement, la puce a été bloquée, ce qui a empêché la copie du firmware.

Le travail a de nouveau ralenti ... c'était comme une vraie impasse. Nous avons mis tous nos efforts mentaux dans ce nonce, et nous n'avions pas de bonnes pistes en mathématiques derrière cela. Et la puce ER48, qui (probablement) gardait des secrets, a été bloquée, et il est difficile de trouver des informations publiques qui pourraient l'aider à se fissurer.
Rayons X
En essayant de comprendre ER48, certains membres de la communauté Slack ont suggéré de prendre des radiographies. C'était vraiment cool, mais malheureusement, cela n'a pas ouvert de nouvelles opportunités.
Plan général
Plan détailléAutopsie et prise de vue
Dan Caron a décidé de se tourner vers un chercheur, le
Dr Sergey Skorobogatov de l'Université de Cambridge au Royaume-Uni. Dan a lu qu'il avait de l'expérience dans l'extraction de code à partir de puces verrouillées et l'a convaincu de jeter un œil à notre problème. Le Dr Skorobogatov a mené des recherches dans le domaine de l'utilisation du SEM (microscope électronique à balayage) pour l'ingénierie inverse des microcircuits. Il a suggéré que c'est possible, mais que cela coûtera cher, nécessitera un équipement coûteux et ne garantit pas un résultat.
Joe Moran , qui a récemment commencé à utiliser Loop après notre rencontre au hackathon Nightscout à l'automne 2016, a accepté d'aider avec le projet. Il a convenu avec une entreprise de la Silicon Valley, Nanolab Technologies, d'ouvrir et de photographier les puces, et a également aimablement financé le travail de Nanolab et du Dr Skorobogatov (ainsi que ses modules personnels).
Le Dr Skorobogatov a demandé à Nanolab d'appliquer diverses techniques d'imagerie pour savoir s'il est possible de casser la protection avec des méthodes connues non invasives ou semi-invasives. En conséquence, de nombreuses images sont apparues, dont certaines très belles. Ce sont des images microscopiques optiques d'une matrice de silicium.
Vue générale du microcircuit sous microscope optique
Vue générale du microcircuit sous microscope optiqueDes photos ont également été prises de zones spécifiques de la matrice à l'aide d'un microscope électronique à balayage. Avec différentes tensions, différentes préparations de surface et différents équipements.
Image SEM des cellules flash. N'affiche pas de donnéesMalheureusement, aucune de ces images n'a montré le contenu réel de la mémoire flash.
Le Dr Skorobogatov avait une dernière méthode, qui ne peut être utilisée qu'en cas d'échec. Il s'agissait d'une méthode brevetée, dont l'utilisation devait obtenir l'autorisation de l'université. Le Dr Skorobogatov a effectué le test initial et a confirmé qu'il était capable de lire les données sur cette puce. Mais avant de continuer, il était nécessaire de signer le NDA, et donc des négociations ont eu lieu sur qui recevrait le contenu du firmware extrait.
En fin de compte, la NDA a signé la fondation Nightscout et a pris la responsabilité d'empêcher la divulgation non autorisée des méthodes et des résultats d'extraction de mémoire.
Le résultat de cet accord et de ce travail a été
un article incroyable écrit par le Dr Sergei Skorobogatov, ainsi que le code du firmware. Dès la première fois, il y avait pas mal d'erreurs dans le code, mais c'était suffisant pour commencer. Au Nightscout Spring Hackathon, Joe s'est tourné vers les gars si quelqu'un voulait faire le démontage. Personne n'a levé la main. Transformer les instructions du processeur en quelque chose de compréhensible est un travail minutieux, et très peu de gens savent comment le faire. J'ai essayé de me plonger dans l'assembleur en utilisant la documentation du CPU, mais j'ai réalisé très peu et j'ai été déçu. D'autres ont demandé avec optimisme le code du firmware avec des attentes de progrès rapides, puis ont réalisé l'ampleur et la complexité de la tâche - et sont tombés tranquillement.
Exemple de démontage des instructions SC908Il s'avère que Joe avait également une vaste expérience de travail avec l'assembleur, et il a commencé à effectuer cette tâche difficile. En juillet, le Dr Skorobogatov a terminé une deuxième opération d'extraction de mémoire avec beaucoup moins d'erreurs. Pendant l'été, Joe Moran a travaillé sans relâche pour afficher un grand nombre d'instructions de processeur et les intégrer progressivement dans l'image globale du pseudocode du module.
Finalement,
Ken Shirriff , un expert en rétroconception matérielle, nous a rejoint et il a considérablement accéléré le processus. Ensemble, Joe et Ken ont fini par traduire suffisamment de code pour trouver une fonction qui code nonce. Cela s'est produit en septembre 2017.
RileyLink et Loop
Nous avons mis à jour les scripts Python d'Openomni, mais maintenant il est temps de se concentrer sur RileyLink + iOS, j'ai donc commencé à travailler sur OmniKit et les mises à jour du firmware pour RileyLink. Je croyais que nous avions les bases du protocole, et le reste n'était que des détails. Encore une fois, sous-estimer complètement ce qui reste à venir.

J'ai dû écrire un nouveau firmware qui gère la modulation et le codage du module. J'ai également dû réécrire comment deux puces sur RL se parlent pour traiter les zéros, car dans Medtronic, les zéros étaient la fin spéciale du marqueur de paquet. Une grande partie de Loop a dû être repensée pour prendre en charge plusieurs pompes, ainsi que de nouvelles interfaces pour prendre en charge l'appariement, la désactivation et la gestion des erreurs. Heureusement,
Nate Racklift a posé des bases solides chez Loop pour rendre tout cela possible.
Pendant ce temps, le travail s'est poursuivi pour comprendre le format des équipes. Tout a été soigneusement documenté sur le
wiki openomni , la documentation la plus complète du protocole. Joe, Evarist et
Elke Jäger ont fait un excellent travail au fil du temps dans le décodage des messages et la mise à jour des pages. Divers membres du canal Slack ont contribué à la capture des paquets PDM et du module pour aider les efforts de décodage globaux.
Le décodage était un travail amusant, avec beaucoup de petites victoires, car chaque composant de chaque équipe décrypte, et j'ai vraiment aimé travailler sur cette partie, en ajoutant progressivement du code à Loop. En avril 2018, j'ai partagé à Slack que j'avais fait «une canulation primaire couplée via iPhone + RL selon le programme basal programmé, puis 5 unités sont tombées malades».
Le micrologiciel RL 2.0 a été achevé en juillet 2018 et de nouvelles livraisons l'ont déjà accompagné. On espérait que ces cartes pourraient être utilisées avec Loop et Omnipod, mais l'antenne existante à 915 MHz était trop mauvaise pour fonctionner efficacement à 433 MHz.
Le décodage et la mise en œuvre ont considérablement progressé au cours de l'été et Loop se rapproche progressivement des performances. Joe a fait la chose incroyable en me donnant du financement, alors j'ai quitté mon travail de jour et me concentrer sur ce projet, et j'ai finalement rejoint la merveilleuse équipe de Tidepool. Bien sûr, dans le domaine du bricolage et de la réglementation législative des équipements médicaux, il y a eu plus d'événements que je ne couvrirai pas, mais ce fut un été très intéressant!
Screamers
Lorsque plus de fonctions sont apparues dans le pilote, je l'ai connecté à Loop, activant la possibilité de configurer automatiquement la livraison à l'heure. À ce stade, des modules «flashy» ont souvent été obtenus lorsque certaines vérifications internes des modules ont révélé un problème et il a cessé de délivrer de l'insuline.
Mais cela semblait être un problème résolu, car nous avons continué à trouver de petites différences dans les packages de boucle et le PDM d'origine lors de l'envoi manuel des commandes, et j'ai supposé que si nous les corrigions tous, les «cris» cesseraient.
Boucle de travail!
Le 3 octobre 2018, Joe a enfilé le module géré Loop et est devenu le premier utilisateur Loop Omnipod, bien qu'il ne me l'ait pas dit tout de suite parce qu'il savait que je serais inquiet. Quand il me l'a dit, j'étais toujours inquiet. Nous avons vu comment le module fonctionnait, et compris la fonctionnalité, et l'algorithme de base a été testé pendant longtemps, mais quand même ...

Un mois plus tard, lors du hackathon de Nightscout en novembre 2018, plusieurs autres aventuriers ont décidé de l'essayer par eux-mêmes et ont également fait partie d'un petit groupe de test fermé qui comptera plus de 30 personnes avant la publication du code.
Malheureusement, nous avons encore rencontré des «cris» de module, survenant souvent avant la fin des trois jours complets d'utilisation, et nous avons soigneusement comparé les commandes de boucle avec des échantillons PDM. Dans ce processus, Elke a été particulièrement utile: il a écrit un script pour vérifier automatiquement les commandes avec les versions originales. J'ai commencé à m'inquiéter du fait que le fonctionnement intermittent des modules était dû à l'augmentation des besoins en batterie pour les communications toutes les cinq minutes.
Prises du régulateur de tension dans le module, percées à travers le plastique du panneau arrière, sur supergluePar conséquent, j'ai commencé à mesurer la tension d'alimentation du module à l'aide d'Arduino, à écrire des données et à les enregistrer dans une base de données locale pour la visualisation. J'ai comparé PDM et Loop.
Changement à long terme de la tension d'alimentation du moduleMalheureusement, cela s'est également avéré être une impasse; en utilisant PDM et en injectant une grande quantité d'insuline, j'ai pu amener le module à une tension plus basse que pendant toute la durée de vie du module Loop, et je n'ai pas pu faire «hurler» le module. Il semblait que le stress n'était pas un problème, il devait y avoir autre chose.
RileyLinks avec antennes à bobine 955 MHz (gauche) et 433 MHz (droite)À un moment donné, j'ai remarqué que si l'échange de messages avec le module échouait, le module continuait parfois à essayer de mettre fin à l'échange en renvoyant des paquets encore et encore. Les journaux des testeurs ont également montré beaucoup de problèmes, j'ai donc commencé à expérimenter avec des antennes. Les deux problèmes doivent être liés à la qualité de la communication. J'ai prévu d'essayer différentes antennes et de les commander à différents endroits sur Internet, mais je n'ai pas eu le temps de les tester jusqu'à ce que cela devienne une priorité.
J'avais plusieurs antennes flexibles de 433 MHz qui peuvent être fixées à l'intérieur du boîtier RL. Ils montrent souvent de meilleures performances dans certains scénarios, mais pas dans d'autres; trop peu fiable. Quand je suis arrivé à la bobine, il a montré de bonnes performances très régulièrement et sur des gammes très étonnantes. Il est temps de faire une nouvelle affaire pour RileyLink.
Avec une nouvelle antenne et quelques optimisations qui ont réduit la messagerie tout en faisant des ajustements toutes les 5 minutes, les cris sont devenus très rares. Probablement comparable à l'utilisation habituelle des modules avec PDM. Au cours des 7 500 dernières heures de tests en temps réel, 94% des modules ont été exécutés sans échec.
Test et documentation
Le groupe de test a lentement grandi: de nouveaux utilisateurs ont constamment rejoint le système, qui, avec un nouveau look, pouvaient évaluer quelles parties semblaient déroutantes. Ces testeurs ont supporté de nombreux modules flashy et ont grandement contribué à améliorer les performances de Loop avec Omnipod. Fondamentalement, ils ont envoyé des rapports de problèmes et des journaux de travail.
Ces rapports contiennent un journal de messages qui peut être analysé à l'aide d'un outil créé par Elke. Cela donne une idée si nous obtenons des commandes déformées et vous permet également de collecter des statistiques sur certaines parties de l'interaction de Loop avec les modules.
Marion Barker a rejoint le groupe de test et ajouté des rapports spéciaux et des statistiques supplémentaires sur la progression des tests - et nous avons pu utiliser ses statistiques des modules réussis contre les échecs afin d'avoir une idée de haut niveau des progrès.
Finalement,
Katie DiSimone a rejoint le groupe de test. Elle a commencé une restructuration majeure de
loopdocs.org avec de la documentation sur l'utilisation de Loop avec plusieurs appareils. L'attente pour la version de Loop qui fonctionnait avec Omnipod était incroyablement longue, et sans une bonne documentation, il était clair que nous serions submergés par les mêmes questions.
Nouvelles fonctionnalités de boucle
L'intégration avec Omnipod a nécessité une refonte de certains des éléments de l'interface et l'ajout de nouveaux contrôles. Le module ne signale pas la batterie et l'utilisateur peut faire peu avec une faible charge si cela se produit, donc l'affichage du widget de niveau de batterie n'a pas de sens. De plus, sans interface utilisateur sur la pompe, l'utilisateur devrait pouvoir annuler rapidement le bolus. L'icône du réservoir représentait le réservoir Medtronic, nous voulions donc le refaire. Merci à
Paul Forgione d' avoir développé le logo du module, qui indique désormais le niveau du réservoir.

Remerciements
Merci à toutes les personnes qui nous ont aidés à aller si loin afin que nous réalisions l'objectif que nous nous étions fixé il y a longtemps. Je sais que je n'ai pas mentionné tous les événements et pas tous les événements. Ce n'est pas possible dans un article, et je n'ai qu'une expérience personnelle. Il est difficile d'imaginer combien d'heures cela a pris. Si vous les ajoutez tous ensemble, je suis sûr que c'est un chiffre choquant. Sans parler du travail de création de l'Omnipod lui-même, qui, il me semble, éclipse tous ces efforts. Merci à tous. De plus, bon nombre de ces heures auraient autrement été consacrées à des familles. J'apprécie vraiment la compréhension de ma femme et de mes enfants en raison du temps que j'y ai consacré, et je tiens également à les remercier.
Remarques
Je dois mentionner
Joachim Ornstedt comme l'un des contributeurs au décodage openomni, ainsi que le créateur de probablement la première intégration avec l'omnipode. Il a construit un appareil qui utilisait la reconnaissance optique de caractères (OCR) pour extraire les données du PDM et a connecté les touches numériques au PDM physique via un autre microcontrôleur. Cette approche est difficile à mettre à l'échelle, mais elle est très intelligente et contourne bon nombre des problèmes que nous avons dû résoudre avec une solution basée sur les ER. J'admire vraiment la façon dont il a résolu le problème et mis en place un travail pendant une infime fraction du temps qu'il a fallu pour que l'appareil fonctionne avec Loop.