用于DIY疗法的逆向工程胰岛素泵大约三年前,我听说有一个网站因与我的亲密关系而给予奖励:使用胰岛素泵进行反向工程通信。 我已经帮我的女儿创建了一个名为
Loop的
系统 ,并使用了Medtronic泵进行反向工程通信(大多数主要Medtronic通信协议由Ben West使用Carelink USB解码,我发现了无线电频率并做了一些额外的工作)协议)。 但是,在进行体操运动时,需要关闭Medtronic泵几个小时。 这种Omnipod泵的无内胎设计对我来说似乎很有趣,并且我拥有所有可以使用的工具。
Omnipod系统由一个称为模块(pod)的小型一次性泵和一个控制单元(PDM)组成。
由于PDM通过无线电与模块通信,并且该模块没有内置接口,因此这意味着它是完全由无线电控制的。 仅使用
RileyLink或其修改版本,就有可能与Loop完全集成。
詹姆斯·婚礼(James Wedding)给予了奖励,这引起了很多关注,然后是对工作有所帮助的合适的人。
软件无线电
SDR是一个
了不起的工具 。 他使广播的隐藏世界变得可见。 有多种类型的消息不断在播放,这些工具使您可以浏览,查看消息以及进行一些工作后-解码在那里看到的小闪烁。 如果您要查找来自特定设备的消息,则需要知道从哪个区域开始搜索。 这是FCC公共文件派上用场的地方。
PDM的FCC文档
RBV-019表示该设备在433 MHz频段中传输。 将SDR软件配置为侦听433 MHz范围后,从PDM发出状态时,将显示以下信号:

我最终发现,这两条亮线表示一种称为
频移键控或FSK的调制类型。 这意味着信号频率根据发送的信息而变化。 位1以较高的频率(较高的线)发送,位0以较低的频率(较低的线)发送。 使用
inspectrum工具
,我们可以分析数据以更清楚地识别1和0。这是第一个消息的放大图:

我编写了一个python脚本来提取这些位,以便我们可以将它们视为整个包。

事实证明,这种重复模式是
前言的一部分。 为了节省能量,接收器通常会进入睡眠模式并定期唤醒以检查信号。 发送器发送前同步码的时间足够长,以使接收器可以在较短的监听周期之一内捕获它。 当接收器听到前同步信号时,它会醒来直到出现真实数据。
您需要先经过另一层,然后才能获得实际的批处理数据。 您无法通过无线电以与原始位完全相同的方式发送数据,因为接收器会使用转换来及时等待下一个位。 如果您有一长串零或一,那么接收器可能不同步。 因此,无线电通信通常使用编码来验证是否有足够的过渡。 Omnipod通信使用所谓的
曼彻斯特编码 。 每一位编码为两位。 1编码为10,0编码为01。
所有这些花了很长时间才弄清楚,并且
在我们尝试重复原始位时
,Slack的openomni频道上有很多理论。
Mark Brighton ,
Dan Caron和
@larsonlr在使用
RFCat和
Ti Stick捕获数据包方面取得了一些成功。
Evarist Kurgio最终编写了一个名为
rtlomni的工具,他使用rtl-sdr USB接收器来监听数据包并对其进行解码,事实证明,这比基于TI Stick的方法非常方便且可靠。
包解码
收到了实际的信息后,我们开始研究包装的结构。 根据不同模块和不同团队之间的变化,我们构建了一个结构,如下所示:

CRC8
无线电距离理想的传输媒介还很远。 有许多不同的干扰源使接收器在发送0时听到1,反之亦然。 重要的是要知道何时发生,因此大多数协议都使用校验和,通常称为CRC。 接收器在接收到数据时计算CRC,数据包的最后一个字节包括发送器计算出的CRC。 如果它们不匹配,则接收器将丢弃该数据包并等待重传。
Omnipod协议使用标准的8位CRC。 当我们找到他时,我们决定我们非常接近理解消息。 我们知道多少...
消息,CRC16
一些消息太大而无法放入一个包中,因此它们被拆分为多个包。 我们开始整理消息格式,并在每条消息的末尾注意到另一组位,它们看起来像是16位CRC。 但这很奇怪:16位中的5位从未设置。 我们尝试了
许多不同的方法来弄清楚如何对其进行编码,但是没有任何效果。
这是第一个大问题:我们可以继续处理消息中的其他位,但是了解发送的内容将无济于事,并且我们将无法自己生成新的数据包,因此进度变慢了。
几个月过去了几乎无济于事。 最后,在2016年冬天,一个昵称为
@lorelai的小组成员报告说,她已成功将固件从更大的ARM芯片复制到PDM,并开始了繁琐的反汇编过程:接受CPU指令并将其转换为具有语义变量和函数名的人类可读代码。 她在发现用于传输数据的各种方法方面做得非常出色。
我查看了一个未命名的例程,发现它看起来像是从表中计算CRC的标准实现。 该表具有标准16位CRC的值。 我在表上编写了自己的实现,并且像常规的CRC一样对其进行了测试。 然后,我仔细查看了函数的编写方式。 普通的CRC实现如下所示:
while (len--) { crc = (crc << 8) ^ crctable[((crc >> 8) ^ *c++)]; }
它们的实现如下所示:
while (len--) { crc = (crc >> 8) ^ crctable[((crc >> 8) ^ *c++)]; }
注意区别吗? 原本应该是按位左移的算子被编码为右移。 这是一个错误; 没有理由削弱您自己的CRC算法,因为这使识别损坏的消息变得困难。
我们又恢复了运作! 然后,他们恢复了解码消息的工作,记录了来自PDM的会话,以传输大剂量[药物],临时基础[临时基础速度决定了胰岛素输送的增加或减少-大约为0。 车道],中止备案等。
一次性编号
在消息的开头,所有胰岛素交付团队都有一个4字节的数据,看起来像某种加密形式。 同样,我们尝试了许多不同的方法来在发送它的消息的上下文中解释和分析它,但它不是CRC(有时即使在不同的消息中,我们也看到相同的4个字节)。 有时我们看到图片重复出现。 它看起来可能是防止数据复制的协议的一部分。 在其他协议中,类似的函数称为
nonce 。
我们考虑的选项之一是记录用于回放给定命令的消息库。 即使每个模块的地址不同,现在我们也知道如何生成CRC,以便我们可以使用命令的上一个副本,将新地址放在消息上并重新计算CRC。 只有这种随机数才使我们无法使用此策略。 无论使用什么命令,模块都只接受序列中的下一个随机数,并且我们不知道如何生成下一个随机数。
但是! 毕竟,我们有反编译的PDM固件,我们可以看看那里! 因此,我们研究了PDM固件,跟踪了代码中消息的生成,并找到了这四个字节应位于的位置。 但是,我们只发现了四个
INS.
字符,而不是计算某些加密随机数的方法
INS.
。 什么废话?!?! 好吧,这个消息区域需要在稍后的管道中进行更新。
PDM上还有另一个靠近无线电的芯片。 它与模块中使用的芯片相同,标识符为SC9S08ER48,该标识符未在Internet上记录。 它可能是为Insulet订购的。 也许我们可以从该芯片上删除固件。 不幸的是,该芯片被阻塞,无法复制固件。

工作又变慢了……这真是一个死胡同。 我们全力以赴地投入了这个随机数,并且在其背后的数学运算中没有任何好的线索。 ER48芯片(可能是秘密的)被封锁了,很难找到任何有助于破解它的公共信息。
X光片
为了了解ER48,Slack社区的一些成员建议拍摄X光片。 确实很酷,但是不幸的是,没有打开任何新的机会。
一般射击
详细拍摄验尸和射击
Dan Caron决定求助于英国剑桥大学的研究员
Sergey Skorobogatov博士 。 Dan读到他有从锁定的芯片中提取代码的经验,并说服他看一下我们的问题。 Skorobogatov博士在使用SEM(扫描电子显微镜)进行微电路反向工程领域进行了研究。 他建议有可能,但是会很昂贵,需要昂贵的设备,并且不能保证结果。
乔·莫兰 (
Joe Moran)在我们于2016年秋天在Nightscout黑客马拉松上相遇后最近开始使用Loop,他同意为该项目提供帮助。 他与一家硅谷公司Nanolab Technologies达成协议,以开放和拍摄芯片,并还为Nanolab和Skorobogatov博士(以及他的个人模块)的工作提供了资助。
Skorobogatov博士要求Nanolab应用各种成像技术,以找出是否可以通过已知的非侵入性或半侵入性方法来破坏保护。 结果,出现了许多图像,其中有些非常漂亮。 这些是硅基质的光学显微图像。
光学显微镜下微电路的整体视图
光学显微镜下微电路的整体视图还使用扫描电子显微镜拍摄了基质的特定区域的照片。 具有不同的电压,不同的表面处理和不同的设备。
闪存的SEM图像。 不显示数据不幸的是,这些图像都没有显示闪存的实际内容。
Skorobogatov博士有最后一种方法,该方法只能在失败的情况下使用。 这是一种获得专利的方法,其使用必须获得大学的许可。 Skorobogatov博士进行了初步测试,并确认他能够读取该芯片上的数据。 但是在继续之前,有必要签署NDA,因此就谁将接收提取的固件内容进行了谈判。
最终,NDA签署了Nightscout基金会,并负责防止未经授权就披露内存提取方法和结果。
这项协议和工作的结果
是 Sergei Skorobogatov博士撰写的
一篇令人难以置信的文章 ,以及固件代码。 从第一次开始,代码中就有很多错误,但这足以开始。 在Nightscout春季Hackathon上,如果有人想拆装,Joe会找这些家伙。 没有人举起手。 将处理器指令转换为可以理解的内容是艰巨的工作,而且很少有人知道该怎么做。 我试图使用CPU文档来研究汇编程序,但是却没有取得什么成就,感到很失望。 其他人乐观地希望获得固件代码,并期望快速发展,然后意识到任务的规模和复杂性-并悄然下降。
SC908指令拆卸示例事实证明,乔在汇编程序方面也有丰富的经验,他开始执行这项艰巨的任务。 7月,Skorobogatov博士完成了第二次内存提取操作,错误少得多。 在夏天,乔·莫兰(Joe Moran)孜孜不倦地工作,以显示大量的处理器指令,并将它们逐步集成到模块伪代码的整体画面中。
最后,硬件逆向工程专家
Ken Shirriff加入了我们,他大大加快了这一过程。 乔和肯在一起在一起,最终翻译了足够的代码以找到一个编码随机数的函数。 这发生在2017年9月。
RileyLink和Loop
我们更新了openomni的Python脚本,但是现在是时候专注于RileyLink + iOS了,因此我开始研究OmniKit和RileyLink的固件更新。 我相信我们具有该协议的基础知识,其余仅是细节。 再次,完全低估了还有多少。

我必须编写一个新的固件来处理模块的调制和编码。 我还必须重写RL上的两个芯片如何相互通信才能处理零,因为在Medtronic中,零是数据包标记的特殊结尾。 必须对Loop的大部分内容进行重新设计,以支持多个泵,并重新设计接口以支持配对,停用和错误处理。 幸运的是,
Nate Racklift为Loop奠定了坚实的基础,从而使这一切成为可能。
同时,继续在理解团队形式方面进行工作。 一切
都已在
openomni Wiki上仔细记录,该协议是该协议最全面的文档。 随着时间的推移,Joe,Evarist和ElkeJäger在解码消息和更新页面方面做得非常出色。 各种Slack通道成员有助于捕获PDM数据包和模块,以帮助整体解码。
解码是一项很有趣的工作,因为每个团队的每个组成部分都解密,因此获得了很多小的胜利,我真的很喜欢处理这一部分,并逐渐将代码添加到Loop中。 在2018年4月,我在Slack上分享了自己的信息:“我按照编程的基本日程通过iPhone + RL配对了主要插管,然后生了5个单位生病。”
RL 2.0固件已于2018年7月完成,并且已经交付了新产品。 希望这些板可以与Loop和Omnipod一起使用,但是现有的915 MHz天线太糟糕了,无法在433 MHz下有效工作。
整个夏天,解码和实现都取得了显着进展,Loop正在逐渐接近性能。 乔通过给我资金来完成了一件了不起的事情,所以我辞掉了日常工作而专注于这个项目,最终我加入了出色的Tidepool团队。 当然,在DIY和医疗设备的法律法规领域,还有很多我不会讲的事件,但这是一个非常有趣的夏天!
尖叫声
当驱动程序中出现更多功能时,我将其连接到Loop,启用了按时自动配置交付的功能。 在此阶段,当一些内部模块检查发现问题并且他停止输送胰岛素时,通常会获得“浮空”模块。
但这似乎是一个可解决的问题,因为当我们手动发送命令时,我们继续在Loop和原始PDM程序包中发现小的差异,并且我假设如果将它们全部修复,“尖叫”将停止。
工作循环!
在2018年10月3日,Joe放弃使用Loop管理的模块并成为第一个Loop Omnipod用户,尽管他没有立即告诉我,因为他知道我会担心的。 当他告诉我时,我仍然很担心。 我们了解了模块的工作方式,了解了功能,并且对基本算法进行了长时间的测试,但仍然...

一个月后,在2018年11月的Nightscout黑客马拉松上,又有几名冒险家决定自己尝试一下,并且还成为一个小型封闭测试小组的一部分,该小组将在代码发布之前增长到30多人。
不幸的是,我们仍然遇到模块“尖叫”,通常在整整三天的使用完成之前就发生了,我们仔细比较了Loop命令和PDM示例。 在此过程中,Elke特别有用:他编写了一个脚本,用于自动检查原始版本的命令。 我开始担心模块的间歇性运行是由于每五分钟对通信的电池需求增加而引起的。
在超级胶上钻过后面板塑料的模块中调压器的分接头因此,我开始使用Arduino测量模块的电源电压,写入数据并将其保存在本地数据库中以进行可视化。 我比较了PDM和Loop。
模块电源电压的长期变化不幸的是,这也证明是死胡同。 使用PDM并注入大量胰岛素,我可以使模块的电压低于Loop模块整个寿命期间的电压,并且不能使模块“尖叫”。 似乎压力不是问题,还必须有其他事情。
带有955 MHz(左)和433 MHz线圈天线(右)的RileyLinks在某个时候,我注意到,如果与模块的消息交换失败,该模块有时会继续尝试通过一次又一次地重新发送数据包来结束交换。 测试人员的日志也显示出许多故障,因此我开始尝试使用天线。 这两个问题都应与沟通质量有关。 我计划尝试使用不同的天线,并在Internet上的不同位置订购它们,但直到成为优先事项时,我才有时间对其进行测试。
我有几个433 MHz柔性天线,可以连接到RL外壳的内部。 在某些情况下,它们通常表现出更好的性能,而在另一些情况下则不然。 太不可靠了。 当我上线时,它在非常惊人的范围内始终如一地表现出良好的性能。 是时候为RileyLink提出新案例了。
有了新的天线并进行了一些优化,减少了消息传递,同时仍然每5分钟进行一次调整,尖叫声变得非常罕见。 大概可以与PDM模块的常规使用相媲美。 在过去的7,500个小时的实时测试中,94%的模块完好无损。
测试和文件
测试小组慢慢成长:新用户不断加入系统,他们以崭新的外观可以评估哪些零件令人困惑。 这些测试人员使用了许多浮华的模块,为提高Omnipod的Loop性能做出了巨大贡献。 基本上,他们发送了问题报告和工作日志。
这些报告具有消息日志,可以使用Elke制造的工具进行分析。 它可以让我们了解是否收到任何失真的命令,还可以让您收集有关Loop与模块交互的某些部分的统计信息。
Marion Barker加入了测试小组,并添加了特殊的报告和有关测试进度的其他统计信息-我们能够使用她的成功模块统计信息来应对失败情况,以期获得高水平的进度。
最后,
Katie DiSimone加入了测试小组。 她使用有关在多个设备上使用Loop的文档开始了
loopdocs.org的重大重组。 与Omnipod一起使用的Loop版本的等待令人难以置信,如果没有好的文档,很显然我们将被同样的问题所淹没。
新循环功能
与Omnipod集成需要重新考虑一些界面元素并添加新控件。 该模块不会报告电池电量,如果发生这种情况,用户可以用很少的电量做些小事,因此显示电池电量小部件没有意义。 另外,在泵上没有用户界面的情况下,用户应该能够快速取消推注。 储罐图标描绘了Medtronic储罐,因此我们想对其进行改造。 感谢
Paul Forgione开发了该模块的徽标,该徽标现在显示了水箱的高度。

致谢
感谢所有帮助我们走了很长一段路的人,以便我们实现了很久以前设定的目标。 我知道我没有提及所有涉及的事件,也不是所有事件。 一篇文章不可能做到这一点,而且我只有个人经验。 很难想象要花多少时间。 如果将它们全部加在一起,我相信这是一个令人震惊的数字。 更不用说创建Omnipod本身的工作了,在我看来,这使所有这些努力蒙上了阴影。 所以谢谢大家。 此外,这些时间中的许多时间本来会与家人在一起。 由于花了很多时间,我非常感谢我的妻子和孩子们的理解,我也要感谢他们。
注意事项
我应该提到
Joachim Ornstedt ,他是openomni解码的贡献者之一,并且可能是第一次与omnipod集成。 他制造了一种设备,该设备使用光学字符识别(OCR)从PDM中提取数据,并通过另一个微控制器将数字按钮连接到物理PDM。 这种方法很难扩展,但是非常聪明,它绕开了我们在基于RE的解决方案中必须解决的许多问题。 我真的很佩服他如何处理该问题,并在使设备与Loop配合工作的过程中花费了很少的时间来完成工作。