BLE模块Hacking

这本来应该是一个不可公开的project。不过感觉花了许多精力在上面最后却没有重用所以还是想至少把解决问题的过程写出来共享一下比较好。

简单来说就是当时在学校研究室的聚会里接了一个外包的活:某个产品采用了一个CC2541的BLE模块,因为某些原因想要获取该设备上温度传感器的值,不管是通过破解BLE协议也好,重新写个固件也罢。需要和app进行通讯。给的资料说是国内有在卖公版的蓝牙模块,然而实际测试却发现厂家用了自己的固件。所以得想办法hack掉这个芯片获取里面的值或者说破解掉这个芯片。

知道了芯片型号之后首先就是datasheet了,TI的官网上就能找到该芯片的详细信息,然而正如上面所说,毕竟不是公版固件所以实际查看发现芯片到模块的阵脚与datasheet上标记的略有不同,该是UART的地方走了GPIO接了传感器,而且还是需要数模转换的🤔。所以似乎官方datasheet的作用并不是很大。

后来考虑先从app下手,就从产品生产商拿到了专用app,然后尝试用Hopper Disassembler和radare2进行反编译。为此还专门找了台破解了的iOS设备将下载下来的app进行移除加密,然后扔到Hopper Disassembler和radare2里进行分析,最后虽然找到不少String,也找到了BLE相关的代码,但是毕竟都是汇编,然后Hopper Disassembler的可视化也是非常的难用,而且考虑到这个app很有可能用的是swift而Hopper Disassembler的可视化显示的是Objective-C,就更难分析了。最后折腾了近一个月愣是没得出来任何结果。

不过好在之前甲方有app以及一部分的破解数据,主要是该设备有定时关机的功能,所以他们当时也是用wireshark截取蓝牙通讯的数据包拿到16进制的控制数据。然后他们有用flutter写了一个小的demo,实测确实是可以用的。

于是我也照抄用Swift写了一个iOS版的app,主要还是为了测试如何和该设备进行通讯。毕竟iOS的话我自己比较熟,查资料也方便得多。

首先分析甲方写的demo手机app,发送给设备的数据格式为:

135d146035dcd508a902
70140d3c2faca5f33a603e42de2a9c9c9c9c57e7
86b5149c9cb39c44e0
……

而从设备传回给app的数据格式大约为:

d35d7649d09c9c9c68dd
d35df549d09c9c9c6812
d35db549d09c9c9cea64
d35d8149d09c9c9c68fc
d35d8549d09c9c9cea85
d35dc449d09c9c9ceacf
d35d2949d09c9c9cea35
d35ded49d09c9c9c6832
d35db649d09c9c9c6815
d35d9c49d09c9c9ceafe
d35d5949d09c9c9ce287
d35de149d09c9c9c8651
d35d2549d09c9c9c86bf
d35d4449d09c9c9ce226
d35d0949d09c9c9c8636

……

由此可见传给设备的数据虽然差别挺大,但是回传的数据格式几乎都是统一的。能够看出来的也就是前面4位d35d以及中间的9c会相同,而最后4位几乎都是不同的。可以断定数据只是被编码成16进制了但是并没有加密,所以只需要观察变化的数据即可。

而且这次主要是为了要从设备上获取温度传感器的信息,相当于是只读,所以就不需要太考虑app发送数据给设备的事情。不过测试发现,设备并不会一直将状态信息自动回传给app,而是需要app先发送一个指令才会回传状态信息。

该设备有温度,RGB灯光,电量检测以及设备模式切换控制这几项功能。所以上面回传的状态信息应该也至少包含这4个数据。使用控制变量法,保持一个传感器不变的情况下去修改设置,然后保持相同设置的前提下不断获取数据,检查哪段数据有变化则得出以下的结论:

d35d xx(temp) xx(r=52,g=76,b=49,y=22,off=59) xx(battery,0d=100%?) 9c xx(Auto/Manual 9c=Manual) 9c xx xx(verify?)

所以如果要知道温度的话,首先得先制作出一个稳定温度的环境,然后将传感器放入该环境进行测量,由于已知温度的情况下再进行升温或者降温操作的话,频繁获取数据后则就可以知道几乎每一个温度点所对应的16进制数据了。

要说控制温度的话,相比起找个有误差的温度计,直接找个冰+水反而简单,毕竟初中物理冰+水=0度。所以只要知道0度的值了,之后传感器拿出来同时不断收集数据,就可以知道0度到室温变化所得到的值,而从冰水中拿出来放入冰箱冷冻库的话则就可以得知零下温度的值。

而测试出来的0度所对应的16进制正好是9c,也就是返回数据中作为分隔符的部分。然后接着测试出来1度是b6,2度是ed等等。。。

而测试到后来发现,虽然无法直接将温度传感器泡入开水,但是当我尝试将设备的供电降下来,从100%电量降到50%甚至30%之后,得到的16进制数据开始和温度传感器的16进制数据对上了,也就是说温度的数据编码方式和电量的是一模一样的,所以温度+电量全部测试完后,则就得到一个完整的10进制数据和16进制编码的对照表。

虽然最后仍然没能破解数据最后4位应该是验证数据的编码,不过至少目标拿到温度传感器数据的目的是达到了。

以上的研究大约花了4个月,当然不是连续的而是在学校有空余的时候进行的研究。虽然最后总结出来看上去流程非常简单,但是光是想到这个控制变量测试方法就花了很久时间,更不说之前反编译app以及写这个测试专用app的时间。

虽然最后该项目被冷藏起来了,不过以上测试代码已公开至Github,欢迎参观

————————————————————

后记:感谢xiao99xiao提供的youtube视频,BLE的数据包截取可以通过Android自带的Bluetooth HCI snoop功能就可以记录app和设备之间的通讯。之后将这个log导入wireshark进行分析就可以得知传输的具体内容。这个也是当年甲方获取设备和app之间通讯的方法。

因为当年写的这个BLE demo程序,后来毕业课题的时候需要做一个remote app来做demo,最后也是靠当时写的代码重复使用写了个简单的BLE remote controller操作NUC上跑的软件。毕竟并不是所有和iOS交互的东西都需要上MFi,MFi也不便宜。如果只是想简单的和iOS交互,甚至只是想弄个串口传输数据的话,BLE确实完全能满足需求。

发表评论

您的电子邮箱地址不会被公开。

*

:b1 :b2 :b3 :b4 :b5 :b6 more »

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据