Bombas de insulina, microchips invioláveis ​​e rádio definido por software

Bomba de insulina de engenharia reversa para terapia de bricolage

Há cerca de três anos, ouvi falar de um site que oferecia uma recompensa por estar muito próximo do meu coração: comunicações de engenharia reversa com uma bomba de insulina. Eu já ajudei a criar um sistema para minha filha chamado Loop , com uma bomba Medtronic, para a qual eu faço engenharia reversa das comunicações (a maioria dos principais protocolos de comunicação da Medtronic foi decodificada por Ben West usando o dispositivo USB Carelink, descobri as frequências de rádio e fiz alguns trabalhos extras em protocolo). Mas a bomba Medtronic precisou ser desligada durante a ginástica por várias horas. O design tubeless desta bomba Omnipod me parecia interessante, e eu tinha todas as ferramentas para trabalhar.

O sistema Omnipod consiste em uma pequena bomba de uso único denominada módulo (pod) e unidade de controle (PDM).



Como o PDM se comunica com o módulo por rádio e o módulo não possui uma interface integrada, isso significa que é totalmente controlado por rádio. Existe a possibilidade de integração total com o Loop, usando apenas o RileyLink ou sua versão modificada.

James Wedding designou uma recompensa, que atraiu muita atenção e, depois, as pessoas certas que ajudaram no trabalho.

Rádio definido por software


SDR é uma ferramenta fantástica . Ele torna visível o mundo oculto do rádio. Há uma variedade de tipos de mensagens que são transmitidas constantemente no ar, e essas ferramentas permitem que você bisbilhote, visualize mensagens e, após algum trabalho - decodifique os pequenos flashes que você vê lá. Se você estiver procurando mensagens de um dispositivo específico, precisará saber em qual área iniciar a pesquisa. É aqui que os documentos públicos da FCC são úteis.

A documentação da FCC para PDM, RBV-019 , diz que o dispositivo transmite na faixa de 433 MHz. Depois de configurar o software SDR para escutar na faixa de 433 MHz, os seguintes sinais aparecem ao emitir o status do PDM:



Como eu finalmente descobri, essas duas linhas brilhantes indicam um certo tipo de modulação chamada de comutação de frequência , ou FSK. Isso significa que a frequência do sinal varia dependendo da informação transmitida. O bit 1 é enviado como uma frequência mais alta (linha superior) e 0 é enviado com uma frequência um pouco mais baixa (linha inferior). Usando a ferramenta inspectrum, podemos analisar os dados para reconhecer mais claramente 1 e 0. Aqui está uma visão bastante ampliada da primeira mensagem:



Eu escrevi um script python para extrair esses bits para que possamos vê-los como pacotes inteiros.



Acontece que esse padrão repetitivo faz parte do preâmbulo . Para economizar energia, os receptores geralmente entram no modo de suspensão e acordam periodicamente para verificar o sinal. O transmissor envia o preâmbulo por tempo suficiente para que o receptor o pegue durante um dos curtos períodos de escuta. Quando o receptor ouve o preâmbulo, ele acorda até que dados reais apareçam.

Você precisa passar por outra camada antes de obter os dados reais do lote. Você não pode enviar seus dados pelo rádio da mesma maneira que os bits originais, porque o receptor usa transições para sincronizar a tempo de aguardar o próximo bit. Se você tiver um conjunto longo de zeros ou uns, o receptor poderá ficar fora de sincronia. Portanto, as comunicações de rádio geralmente usam codificação para verificar se há transições suficientes. As comunicações Omnipod usam a chamada codificação Manchester . Cada bit é codificado em dois bits. 1 é codificado como 10 e 0 é codificado como 01.

Demorou muito tempo para descobrir, e havia muitas teorias no canal openomni no Slack enquanto tentávamos repetir os bits originais. Mark Brighton , Dan Caron e @larsonlr obtiveram algum sucesso usando o RFCat e o Ti Stick para capturar pacotes. Evarist Kurgio finalmente escreveu uma ferramenta chamada rtlomni , ele usa o receptor USB rtl-sdr para ouvir pacotes e decodificá-los, o que acabou sendo muito conveniente e mais confiável do que os métodos baseados no TI Stick.

Decodificação de pacotes


Tendo recebido os bits reais, começamos a estudar a estrutura do pacote. Com base em quais bits foram alterados entre diferentes módulos e equipes diferentes, criamos uma estrutura parecida com esta:



CRC8


O rádio está longe de ser um meio de transmissão ideal. Existem muitas fontes diferentes de interferência que fazem o receptor ouvir 1 quando 0 é enviado e vice-versa. É importante saber quando isso aconteceu; portanto, a maioria dos protocolos usa uma soma de verificação, geralmente chamada de CRC. O receptor calcula o CRC à medida que os dados são recebidos e o último byte do pacote inclui o CRC calculado pelo transmissor. Se não corresponderem, o receptor descarta o pacote e aguarda a retransmissão.

O protocolo Omnipod usou o CRC padrão de 8 bits. Quando o encontramos, decidimos que estávamos muito perto de entender as mensagens. Quão pouco sabíamos ...

Mensagens, CRC16


Algumas mensagens são grandes demais para caber em um pacote e, portanto, são divididas em vários pacotes. Começamos a juntar o formato da mensagem e notamos outro conjunto de bits no final de cada mensagem, que parecia um CRC de 16 bits. Mas era estranho: 5 dos 16 bits nunca foram configurados. Tentamos muitos métodos diferentes para descobrir como isso é codificado, mas nada funcionou.

Este foi o primeiro grande problema: poderíamos continuar trabalhando em outros bits nas mensagens, mas não ajudará muito a entender o que está sendo enviado e não seremos capazes de gerar novos pacotes por conta própria; portanto, o progresso diminuiu.

Vários meses se passaram quase sem sucesso. Finalmente, no inverno de 2016, um membro do grupo sob o apelido @lorelai relatou que havia copiado com êxito o firmware de um chip ARM maior para o PDM e iniciou o tedioso processo de desmontagem: aceitando instruções da CPU e transformando-as em código legível por humanos com variáveis ​​semânticas e nomes de funções. Ela fez um trabalho incrível ao descobrir os vários métodos usados ​​para transmitir dados.

Eu olhei para uma das rotinas sem título e notei que parecia uma implementação padrão do cálculo de CRC a partir de uma tabela. E a tabela tinha valores para o CRC padrão de 16 bits. Eu escrevi minha própria implementação em tabelas e foi testada como um CRC regular. Então, observei cuidadosamente como a função foi escrita. Uma implementação normal de CRC se parece com isso:

while (len--) { crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)]; } 

A implementação deles ficou assim:

 while (len--) { crc = (crc >> 8) ^ crctable[((crc >> 8) ^ *c++)]; } 

Percebe a diferença? O que era para ser um operador de turno esquerdo bit a bit foi codificado como um turno direito. Isso é um erro; Não há motivo para prejudicar seu próprio algoritmo CRC, pois isso dificulta a identificação de mensagens corrompidas.

Estamos de volta em operação! E eles retomaram o trabalho de decodificação de mensagens, gravando sessões do PDM para entrega de bolus [drogas], bases temporárias [Taxa Basal Temporária determina um aumento ou diminuição na entrega de insulina - aprox. pista], suspensão de arquivamento etc.

Número de uso único


Todas as equipes de entrega de insulina tinham dados de 4 bytes no início da mensagem, que pareciam alguma forma de criptografia. Novamente, tentamos várias maneiras diferentes de interpretar e analisá-lo no contexto das mensagens em que foi enviado, mas não era o CRC (às vezes vimos os mesmos 4 bytes, mesmo em mensagens diferentes). E às vezes vimos a imagem se repetir. Parecia, talvez, como parte de um protocolo para impedir a reprodução de dados. Em outros protocolos, uma função semelhante é chamada nonce .

Uma das opções que consideramos foi gravar uma base de mensagens para reproduzir determinados comandos. Mesmo que o endereço de cada módulo fosse diferente, agora sabíamos como gerar um CRC, para que pudéssemos pegar a cópia anterior do comando, colocar o novo endereço na mensagem e recontar o CRC. Somente esse nonce nos impediu de usar essa estratégia. Independentemente do comando, o módulo aceitou apenas o próximo nonce na sequência e não sabíamos como gerar o próximo nonce.

Mas! Afinal, temos um firmware PDM descompilado, podemos apenas olhar lá! Então, estudamos o firmware do PDM, rastreamos a geração de mensagens no código e descobrimos onde esses quatro bytes deveriam estar. Mas, em vez de um método que calcula algum nonce criptográfico, encontramos apenas quatro caracteres INS. . Que bobagem?!?! Bem, de alguma forma, essa área de mensagens precisa ser atualizada posteriormente no pipeline.

Havia outro chip no PDM, mais próximo do rádio. Era o mesmo chip usado nos módulos, com o identificador SC9S08ER48, que não estava documentado na Internet. Provavelmente foi feito sob encomenda para o Insulet. Talvez possamos remover o firmware deste chip. Infelizmente, o chip foi bloqueado, o que impediu a cópia do firmware.



O trabalho desacelerou novamente ... era como um verdadeiro beco sem saída. Colocamos todos os nossos esforços mentais nesse sentido, e não tínhamos bons conhecimentos em matemática por trás disso. E o chip ER48, que (possivelmente) guardava segredos, foi bloqueado e é difícil encontrar informações públicas que ajudem a decifrá-lo.

Raios X


Tentando entender o ER48, alguns membros da comunidade Slack sugeriram fazer raios-x. Foi muito legal, mas, infelizmente, não abriu novas oportunidades.


Tiro geral


Tiro detalhado

Autópsia e tiro


Dan Caron decidiu recorrer ao pesquisador, Dr. Sergey Skorobogatov, da Universidade de Cambridge, no Reino Unido. Dan leu que tem experiência na extração de código de chips bloqueados e o convenceu a dar uma olhada no nosso problema. O Dr. Skorobogatov conduziu pesquisas no campo do uso do MEV (microscópio eletrônico de varredura) para engenharia reversa de microcircuitos. Ele sugeriu que é possível, mas será caro, exige equipamentos caros e não garante um resultado. Joe Moran , que recentemente começou a usar o Loop depois de nos conhecermos no hackathon Nightscout no outono de 2016, concordou em ajudar no projeto. Ele concordou com uma empresa do Vale do Silício, a Nanolab Technologies, para abrir e fotografar os chips, e também financiou gentilmente o trabalho de Nanolab e Dr. Skorobogatov (além de seus módulos pessoais).

O Dr. Skorobogatov pediu à Nanolab para aplicar várias técnicas de imagem para descobrir se é possível quebrar a proteção com métodos não invasivos ou semi-invasivos conhecidos. Como resultado, muitas imagens apareceram, algumas delas muito bonitas. Estas são imagens microscópicas ópticas de uma matriz de silício.


Visão geral do microcircuito sob um microscópio óptico


Visão geral do microcircuito sob um microscópio óptico

Também foram tiradas fotos de áreas específicas da matriz usando um microscópio eletrônico de varredura. Com tensões diferentes, preparação de superfície diferente e equipamentos diferentes.


Imagem SEM de células flash. Não mostra dados

Infelizmente, nenhuma dessas imagens mostrou o conteúdo real da memória flash.

Dr. Skorobogatov teve um último método, que pode ser usado apenas em caso de falha. Esse era um método patenteado, cuja utilização precisava obter a permissão da universidade. Dr. Skorobogatov fez o teste inicial e confirmou que ele era capaz de ler os dados neste chip. Porém, antes de continuar, era necessário assinar o NDA e, portanto, foram realizadas negociações sobre quem receberia o conteúdo do firmware extraído.

Por fim, a NDA assinou a fundação Nightscout e assumiu a responsabilidade de impedir a divulgação não autorizada de métodos e resultados de extração de memória.

O resultado deste acordo e trabalho foi um artigo incrível escrito pelo Dr. Sergei Skorobogatov, bem como o código do firmware. Desde a primeira vez, houve alguns erros no código, mas isso foi suficiente para começar. No Hackathon Nightscout Spring, Joe virou-se para os caras, se alguém gostaria de desmontar. Ninguém levantou as mãos. Transformar as instruções do processador em algo compreensível é um trabalho minucioso, e poucas pessoas sabem como fazê-lo. Tentei me aprofundar no assembler usando a documentação da CPU, mas consegui muito pouco e fiquei decepcionado. Outros pediram otimista o código do firmware com expectativas de progresso rápido, depois perceberam a escala e a complexidade da tarefa - e caíram silenciosamente.


Exemplo de desmontagem de instruções SC908

Acontece que Joe também tinha uma vasta experiência trabalhando com montador, e ele começou a realizar essa tarefa difícil. Em julho, o Dr. Skorobogatov concluiu uma segunda operação de extração de memória com muito menos erros. Durante o verão, Joe Moran trabalhou incansavelmente para exibir um grande número de instruções do processador e gradualmente integrá-las à imagem geral do pseudocódigo do módulo.

No final, Ken Shirriff , especialista em engenharia reversa de hardware, juntou-se a nós e acelerou bastante o processo. Juntos, Joe e Ken acabaram traduzindo código suficiente para encontrar uma função que codifica nonce. Isso aconteceu em setembro de 2017.



RileyLink and Loop


Atualizamos os scripts Python do openomni, mas agora é hora de focar no RileyLink + iOS, então comecei a trabalhar no OmniKit e nas atualizações de firmware do RileyLink. Eu acreditava que tínhamos o básico do protocolo, e o resto eram apenas detalhes. Mais uma vez, subestimando completamente o quanto ainda está por vir.



Eu tive que escrever um novo firmware que lida com modulação e codificação do módulo. Eu também tive que reescrever como dois chips no RL se comunicam para processar zeros, uma vez que na Medtronic os zeros eram o final especial do marcador de pacotes. Grande parte do Loop teve que ser redesenhada para oferecer suporte a várias bombas, bem como novas interfaces para oferecer suporte a emparelhamento, desativação e tratamento de erros. Felizmente, Nate Racklift lançou uma base sólida na Loop para tornar tudo isso possível.

Enquanto isso, continuava o trabalho de compreensão do formato das equipes. Tudo foi cuidadosamente documentado no wiki openomni , a documentação mais abrangente do protocolo. Joe, Evarist e Elke Jäger fizeram um ótimo trabalho ao longo do tempo decodificando mensagens e atualizando páginas. Vários membros do canal Slack contribuíram para a captura de pacotes PDM e do módulo para ajudar nos esforços gerais de decodificação.

A decodificação foi um trabalho divertido, com muitas pequenas vitórias, pois cada componente de cada equipe descriptografa, e eu realmente gostei de trabalhar nessa parte, adicionando gradualmente o código ao Loop. Em abril de 2018, compartilhei no Slack que fiz “canulação primária emparelhada via iPhone + RL de acordo com o cronograma basal programado e depois cinco unidades adoeceram”.

O firmware RL 2.0 foi concluído em julho de 2018, e novas entregas já foram acompanhadas. Esperava-se que essas placas pudessem ser usadas com Loop e Omnipod, mas a antena de 915 MHz existente era muito ruim para funcionar efetivamente a 433 MHz.

A decodificação e a implementação progrediram significativamente durante o verão, e o Loop está gradualmente se aproximando do desempenho. Joe fez a coisa incrível ao me dar financiamento, então deixei meu emprego e me concentrei nesse projeto e, eventualmente, entrei para a maravilhosa equipe de Tidepool. Obviamente, no campo da bricolage e da regulamentação legislativa de equipamentos médicos, houve mais eventos que não abordarei, mas foi um verão muito interessante!

Screamers


Quando mais funções apareceram no driver, eu o conectei ao Loop, ativando a capacidade de configurar automaticamente a entrega no prazo. Nesse estágio, os módulos "chamativos" eram frequentemente obtidos quando algumas das verificações internas do módulo encontravam um problema e ele parou de fornecer insulina.

Mas isso parecia ser um problema solucionável, pois continuamos a encontrar pequenas discrepâncias nos pacotes Loop e no PDM original ao enviar comandos manualmente, e presumi que, se corrigirmos todos eles, os "gritos" serão interrompidos.

Loop de trabalho!


Em 3 de outubro de 2018, Joe vestiu o módulo gerenciado Loop e se tornou o primeiro usuário do Loop Omnipod, embora não tenha me contado imediatamente porque sabia que eu ficaria preocupado. Quando ele me disse, eu ainda estava preocupada. Vimos como o módulo funcionava e entendíamos a funcionalidade, e o algoritmo básico foi testado por um longo tempo, mas ainda assim ...



Um mês depois, no hackathon Nightscout em novembro de 2018, vários outros aventureiros decidiram tentar por si mesmos e também se tornaram parte de um pequeno grupo fechado de testes que crescerá para mais de 30 pessoas antes da publicação do código.

Infelizmente, ainda encontramos "gritos" de módulo, ocorrendo frequentemente antes da conclusão dos três dias completos de uso, e comparamos cuidadosamente os comandos de loop com as amostras do PDM. Nesse processo, Elke foi especialmente útil: ele escreveu um script para verificar automaticamente comandos com versões originais. Comecei a me preocupar que a operação intermitente dos módulos fosse causada pelo aumento dos requisitos de bateria para comunicações a cada cinco minutos.


Torneiras do regulador de tensão no módulo, perfuradas através do plástico do painel traseiro, na supercola

Portanto, comecei a medir a tensão de alimentação do módulo usando o Arduino, gravar dados e salvá-los em um banco de dados local para visualização. Eu comparei PDM e Loop.


Alteração de longo prazo na tensão de alimentação do módulo

Infelizmente, isso também acabou sendo um beco sem saída; usando o PDM e injetando uma grande quantidade de insulina, eu poderia levar o módulo a uma voltagem mais baixa do que durante toda a vida útil do módulo Loop, e não conseguia fazer o módulo "gritar". Parecia que o estresse não era um problema, devia haver algo mais.


RileyLinks com antenas de bobina de 955 MHz (esquerda) e 433 MHz (direita)

Em algum momento, notei que, se a troca de mensagens com o módulo falhou, o módulo algumas vezes continuava tentando finalizar a troca reenviando pacotes repetidamente. Os registros dos testadores também mostraram muitas falhas, então comecei a experimentar antenas. Ambos os problemas devem estar relacionados à qualidade da comunicação. Planejei experimentar antenas diferentes e as encomendei em lugares diferentes na Internet, mas não tive tempo para testá-las até que isso se tornasse uma prioridade.

Eu tinha várias antenas flexíveis de 433 MHz que podem ser conectadas à parte interna do gabinete da RL. Eles geralmente mostram melhor desempenho em alguns cenários, mas não em outros; muito pouco confiável. Quando cheguei ao rolo, ele mostrou um bom desempenho de forma muito consistente e em intervalos muito surpreendentes. Hora de apresentar um novo argumento para o RileyLink.

Com uma nova antena e algumas otimizações que reduziam as mensagens e ainda faziam ajustes a cada 5 minutos, os gritos se tornaram muito raros. Provavelmente comparável ao uso usual de módulos com PDM. Nas últimas 7.500 horas de testes em tempo real, 94% dos módulos foram concluídos sem falhas.

Teste e documentação


O grupo de testes cresceu lentamente: novos usuários constantemente aderiam ao sistema, que com uma nova aparência podiam avaliar quais partes pareciam confusas. Esses testadores suportaram muitos módulos chamativos e deram uma contribuição muito grande para melhorar o desempenho do Loop com o Omnipod. Basicamente, eles enviaram relatórios de problemas e logs de trabalho.

Esses relatórios têm um log de mensagens que podem ser analisadas usando uma ferramenta feita pela Elke. Ele dá uma idéia se tivermos algum comando distorcido e também permite que você colete estatísticas sobre certas partes da interação do Loop com os módulos.

Marion Barker se juntou ao grupo de testes e adicionou relatórios especiais e estatísticas adicionais sobre o progresso dos testes - e pudemos usar suas estatísticas de módulos bem-sucedidos contra falhas para ter uma ideia de alto nível do progresso.

No final, Katie DiSimone se juntou ao grupo de testes. Ela iniciou uma grande reestruturação do loopdocs.org com documentação sobre o uso do Loop com vários dispositivos. A espera pela versão do Loop que funcionou com o Omnipod foi incrivelmente alta e, sem uma boa documentação, ficou claro que ficaríamos sobrecarregados com as mesmas perguntas.

Novos recursos de loop


A integração com o Omnipod exigiu uma revisão de alguns dos elementos da interface e a adição de novos controles. O módulo não informa a bateria e o usuário pode fazer pouco com uma carga baixa, se isso acontecer, portanto, exibir o widget de nível da bateria não faz sentido. Além disso, sem uma interface de usuário na bomba, o usuário deve poder cancelar rapidamente o bolus. O ícone do tanque mostrava o tanque da Medtronic, então queríamos refazê-lo. Agradecemos a Paul Forgione por desenvolver o logotipo do módulo, que agora mostra o nível do tanque.



Agradecimentos


Obrigado a todas as pessoas que nos ajudaram a percorrer esse longo caminho para que possamos realizar a meta que estabelecemos há muito tempo. Eu sei que não mencionei todos os envolvidos e nem todos os eventos. Isso não é possível em um artigo, e eu tenho apenas experiência pessoal. É difícil imaginar quantas horas foram necessárias. Se você adicioná-los todos juntos, tenho certeza de que é uma figura chocante. Sem mencionar o trabalho de criação do próprio Omnipod, que, ao que me parece, ofusca todos esses esforços. Então, obrigado a todos. Além disso, muitas dessas horas seriam gastas com as famílias. Realmente aprecio a compreensão de minha esposa e filhos por causa do tempo que dediquei a isso e quero agradecer a eles também.

Anotações


Devo mencionar Joachim Ornstedt como um dos colaboradores da decodificação openomni, bem como o criador da provavelmente primeira integração com o omnipod. Ele construiu um dispositivo que usava reconhecimento óptico de caracteres (OCR) para extrair dados do PDM e conectou os botões numéricos ao PDM físico através de outro microcontrolador. É difícil escalar essa abordagem, mas é muito inteligente e ignora muitos dos problemas que tivemos para lidar com uma solução baseada em ER. Eu realmente admiro como ele lidou com o problema e configurou o trabalho por uma pequena fração do tempo necessário para que o dispositivo funcionasse com o Loop.

Source: https://habr.com/ru/post/pt450962/


All Articles