协议-低功耗蓝牙协议(BLE)
蓝牙
蓝牙是一种近距离无线通信技术,运行在2.4GHz免费频段,目前已大量应用于各种移动终端,物联网,健康医疗,智能家居等行业。
低功耗蓝牙协议是由蓝牙技术联盟(Bluetooth SIG)在2010年发布的蓝牙4.0,并不是蓝牙3.0的升级,而是全新的技术架构。
蓝牙4.0版本分为两种模式,单模蓝牙和双模蓝牙。
双模蓝牙,支持低功耗蓝牙的同时还兼容经典蓝牙,经典蓝牙的特点是大数据高速率,例如音频、视频等数据传输,常见的蓝牙音箱就是双模蓝牙,他需要大量的音频数据传输。
单模蓝牙,即低功耗蓝牙模式,是蓝牙4.0中的重点技术,低功耗,快连接,长距离。像各种手环,蓝牙温度计等都属于单模蓝牙。
低功耗蓝牙
目前低功耗蓝牙在移动终端,智能家居,互联设备等市场都有广泛应用。
其优点:
- 低功耗,使用纽扣电池就可以运行数月至数年。
- 快连接,毫秒级的连接速度,传统蓝牙甚至长达数分钟。
- 远距离,长达数百米的通信距离,而传统蓝牙通常10米左右。
蓝牙联盟为低功耗蓝牙定义了一些标准数据规范(profile),只要遵守该规范,任意厂家的蓝牙设备,均可以相互连接与通信,例如无线蓝牙键盘鼠标,无论是安卓或是iOS还是Windows,均是即插即用,这便是“标准”的力量。
低功耗蓝牙支持的标准Profile有:
- HID,用于无线鼠标,键盘或其他遥控设备。
- BatteryServices,电池状态服务,用于告知电池电量状态。
- HRP,心率计Profile,用于心率采集。等等。
低功耗蓝牙还可以自定义Profile,伴随着智能手机的发展和普及,低功耗蓝牙的这个特性得到了发扬光大,同时也拓宽了低功耗蓝牙的应用领域。例如,可以自定义一个开关量的Profile,数据01表示开灯,数据00表示关灯,然后手机发送数据01和00就可以控制灯的亮和灭。
类似的应用案例有很多,下面总结应用特点:
- 支持自定义Profile,可以收发任意格式的数据,如01和00。
- 支持自定义设备,支持任意设备的连接和通信,例如智能蓝牙插座等。
工作流程
以下将低功耗蓝牙统称为BLE,低功耗蓝牙设备称为BLE设备。
角色
BLE设备角色主要分为两种角色,主机(Master)
和从机(Peripheral)
,当主机和从机建立连接之后才能相互收发数据。
- 主机,主机可以发起对从机的扫描连接。例如手机,通常作为BLE的主机设备。
- 从机,从机只能广播并等待主机的连接。例如智能手环,是作为BLE的从机设备。
另外还有观察者(Observer)
和广播者(Broadcaster)
,这两种角色不常使用,但也十分有用,例如苹果的iBeacon,就是使用广播者角色来做,只需要广播特定内容即可。
iBeacon,苹果公司开发的一种通过低功耗蓝牙技术进行一个十分精确的微定位技术;
- 观察者,观察者角色监听空中的广播事件,和主机唯一的区别是不能发起连接,只能持续扫描从机。
- 广播者,广播者可以持续广播信息,和从机的唯一区别是不能被主机连接,只能广播数据
蓝牙协议栈没有限制设备的角色范围,同一个BLE设备,可以作为主机,也可以作为从机,我们称之为主从一体,主从一体的好处是,每个BLE设备都是对等的,可以发起连接,也可以被别人连接,更加实用。
广播
一个智能手环,在绑定之前,需要让手机发现自己才能去进行绑定操作。
这个让手机发现自己的操作就叫做广播。
即从机每经过一个时间间隔发送一次广播数据包
,这个时间间隔称为广播间隔
,这个广播动作叫做广播事件
,只有当从机处于广播状态时,主机才能发现该从机。
BLE设备拥有40个信道,从0到39,其中37,38,39就是BLE的广播信道。
在每个广播事件中,广播包会分别在37,38和39三个信道上依次广播。
广播时间间隔的范围是从20ms到10.24s,广播间隔影响建立连接的时间。广播间隔越大,连接的时间越长。
广播数据包最多能携带31个字节的数据,一般包含可读的设备名称,设备是否可连接等信息。
当主机收到从机广播的数据包后,它可以再发送获取更多数据包的请求,这个时候从机将广播扫描回应
数据包,扫描回应数据包和广播包一样,可以携带31个字节的数据,如果长度不足,会补0,这部分数据无意义。
提示:蓝牙4.x,广播有效载荷最多是31个字节。而在蓝牙5.0中,通过添加额外的广播信道和新的广播PDU,将有效载荷增加到了255个字节
在安卓手机中可以使用BLE调试助手来查看广播包。
广播包一般格式为 0x长度类型数据长度类型数据…
0x02011A05030F1892FD11094544494649455220545753312050726F
这是我附近某个耳机的广播信息。
分析:
- 0x02/01/1A05,长度2/类型/对应长度的值。
- 0x03/0F/1892FD,长度3/类型/对应长度的值。
- 0x11/09/4544494649455220545753312050726F,长度16/类型/对应的值。
前两段数据并不能看出什么信息,第三段数据可以转为ascii看一下。
即蓝牙耳机名字。
扫描
扫描是主机监听从机广播数据包和发送扫描请求的过程,主机通过扫描,可以获取到从机的广播包以及扫描回应数据包,主机可以对已扫描到的从机设备发起连接请求,从而连接从机设备并通信。
扫描动作有两个比较重要的时间参数:扫描窗口
和扫描间隔
,如果扫描窗口等于扫描间隔,那么主机将一直处于扫描状态之中,持续监听从机广播包。
- 被动扫描,主机监听广播信道的数据,当接收到广播包时,协议栈将向上层(也就是应用层,用户可编程)传递广播包。
- 主动扫描,主动扫描除了完成被动扫描的动作外,还会向从机发送一个扫描请求,从机收到该请求时,会再次发送一个称作
扫描回应
的广播包。
连接
除了扫描, 设备也可以主动发起连接, 发起状态的设备和扫描状态的设备区别在于:当它监听到一个可连接的广播, 发起设备就会发送一个连接请求, 而扫描设备会发送一个扫描请求。连接请求包括一套为从设备准备的连接参数, 安排连接期间发生的通道和时间。如果广播设备接收了连接, 两个设备会进入连接状态, 发起方会称为 Master(主机),而广播方会称为 Slave(从机)。
所有的通信都发生在两个设备的连接事件期间, 连接事件周期的发生, 按照连接参数指定的间隔联系, 每个事件发生在某个数据通道(0~36), 调频增量参数决定了下次连接时间发生的通道, 在每个连接时间期间, Master 先发送, Slave 会在 150us 之后做出回应, 即使一个连接事件发生( 或两者), 双方都没有数据发送(例外情况是从设备潜伏使能), 这允许两个设备都承认对方仍然存在并保持活跃的连接。
主机和从机都可以主动断开连接。一边发起断开, 另一边必须在断开连接之前回应这个断开请求。
通信
BLE 通信的两个基本概念。
- GAP 通用访问配置文件(Generic Access Profile)
- GATT 通用属性配置文件(Generic Attribute Protocol)
GAP完成了上面广播,连接的操作。
GATT则定义了两个 BLE 设备连接后如何使用服务和属性两个概念进行数据交换。
GATT 的两个主要概念:
- 服务(Services)
- 特征(Characteristics)
Profile
包含一个或者多个服务
,每个服务
又包含一个或者多个特征
。主机可以发现和获取从机的服务
和特征
,然后与之通信。特征
是主从通信的最小单元。
每个服务和特征都有自己的唯一标识UUID
,标准UUID为128位,蓝牙协议栈中一般采用16位,也就是两个字节的UUID格式。
每个特征都有自己的属性,属性的取值有:可读 Read
,可写 Write
以及 通知 Notify
。
这样,两个BLE设备就有以下的数据交互方式。
- 主机可主动向从机Write写入或Read读取数据。
- 从机可主动向主机Notify通知数据。
测试
这里使用了两台手机来模拟两个BLE设备
从机:
主机连接从机:
上面链接后可以看到整个profile,下面每个UUID对应一个服务,不同服务之间有不同的特征。在UUID为 0xFFF0的服务中,有三个特征,0xFFF1,0xFFF2,0xFFF3。
可以看到FFF1的属性为read/notify,可读,通知。FFF2的属性为Write,可写。
从机页面中,从机通过0xfff1发送数据。0xfff2接收数据。
0xfff1
从机发送数据:
主机实时接收:
0xfff2
主机发送数据:
从机实时接收:
嗅探
可以理解为利用窃听装置来获取双方通信内容。
ble设备功能设计中,一定会少不了私有的Service或Characteristic,就要通过app逆向或嗅探蓝牙通信来分析了。
蓝牙嗅探最好的神器是Ubertooth One,精致的硬件+配套的软件变成了物联网黑客强大的帮手。
这玩意挺贵的,贵不是他的缺点,是我的缺点。
所以我们使用暂时使用廉价的替代方案,BLE USB Dongle。之后有设备后会配套更新相应文章。
这玩意只支持ble
这里使用的是一块nRF52832 Dongle,某宝可以直接买到烧录好的板子,具体烧录过程就不赘述。
具体可看官方文档:https://www.nordicsemi.com/Products
配置wireshark
购买板子后找客服要来物料包,其中包含相关插件。
打开 wireshark → 帮助 → 关于 wireshark → 文件夹 → 双击打开 Extcap 路径(全 局路径和个人路径二选其一)如下图所示:
将 extcap 文件夹的四个文件复制到 wireshark 的 extcap 路径下, 以全局路径为例,如图所示:
双击 wireshark 个人配置的路径,如图:
在弹出的文件夹中打开 profiles 文件夹
将解压压缩包的 Profile_nRF_Sniffer_xx_xx 文件夹拷贝到 profiles 文件夹中,如图:
使用
软件配置成功后,将设备 插入 USB 口连接至 PC 端,打开 Wireshark,选 择 nRF sniffer COMx,具体串口号根据实际选择。
在工具栏中选择 → 视图 → 接口工具栏 → nRF sniffer,会出现如下界面(默认抓取 所有 BLE 广播信号):
选择任一 BLE 从机上电进行广播。
抓取指定 MAC 地址设备的数据包。
可通过 APP 查看设备 MAC 地址,如下图所示:
如下图红色方框中所示,点击 devices 过滤下拉框选择对应 MAC 地址的 device,选择 固定设备后则只会抓取和该设备有关的数据包。
Wireshark 选择该 MAC 地址设备后,该设备的广播包、scan request packet 和 scan response packet 都会被捕获到。
![image-20230111102119282](/Users/pipi/Library/Application Support/typora-user-images/image-20230111102119282.png)
该设备与任意 master 通信的数据包都可以被抓取,包括连接过程和连接之后的数据 包。双击任意一个 packet 可查看具体内容,例如该设备广播包抓取内容如下:
Hello World
其实是对一个简单的蓝牙氛围灯的嗅探与攻击,其功能比较简单且无数据加密。
app长这样
分析
使用wireshark来嗅探相关信息。
使用手机app连接灯。
有很多Empty PDU空包,使用 !(btle.data_header.llid == 0x1) 来过滤
开关
从手机发送打开命令
其对0x000e特征发送了bc01010155
关闭命令
对0x000e特征发送了bc01010055
通过对比,第5位的01/00控制灯的打开和关闭。
改变速度
该灯可以调节灯块闪烁速度。从0-100
修改为0
修改为100
对比第四位从00-64转换为10进制,即0-100
所以通过修改该参数可控制速度。
bc0801 00 55
改变灵敏度
与速度类似
修改为0
修改为100
特征与速度类似
改变模式
第一个模式
最后一个模式
所以模式从01-99共153个。
bc060200 01 55
改变颜色
通过对多个颜色的分析,数据格式应该为bc04060 11c 0 196 000055,其中11c控制亮度,196控制颜色。
通过上面的分析,发现都是通过0x000e来进行操作。
攻击
这里利用linux蓝牙栈(blueZ)来操作。
sudo apt-get install bluez
安装完成后会有hcitool和gatttool两个工具,分别进行扫描和连接以及数据的读写。
硬件使用一个蓝牙4.0的免驱适配器。
如果你的电脑虚拟机无法获取到主机网卡,可以在vm设置中取消与linux共享蓝牙设备,再接入外接适配器。
hciconfig
用于配置蓝牙设备。我们可以运行这个命令来列出连接到我们计算机的 BLE 适配器以及它们的基本信息。
hciconfig hciX up 启用名为 hciX 的蓝牙设备
hciconfig hciX down 停用名为 hciX 的蓝牙设备
如果之后扫描和连接过程中出现什么问题,可以通过这两条命令来重启蓝牙设备尝试解决。
hcitool
hcitool 用于配置蓝牙连接,并向蓝牙设备发送一些特殊命令。
hcitool -i hciX 使用 hciX 接口,如果不指定,默认使用第一个可用接口。
hcitool scan 扫描处于发现模式的传统蓝牙设备。
hcitool lescan 扫描 BLE 设备。
Gattool
gatttool -I 以交互模式启动 gatttool。
gatttool -t random -b [adr] -I 使用随机 LE 地址在交互模式下启动 gattool。连接到地址为 adr 的远程蓝牙设备。
primary 检查已连接 BLE 设备的可用服务。
characteristic 检查已连接 BLE 设备的可用属性,以便从中读取数据。
char-desc 特征描述符的发现。检查 n 个 handle。
char-read-hnd 使用 handle 读取属性 。
char-write-req 向 handle 写入值。
通过扫描获取的灯泡mac地址ff:22:09:30:00:18
使用gatttool
连接
有时候连接成功了但是会报错,需要再连接下。
使用primary
查看服务
使用Characteristics
查看特征
在找到服务和特征后,需要知道读/写数据的 handle。这可以使用char-desc
命令得到。
在找到 handle 后,使用命令char-read-hnd <handle>
从 handle 中读取数据。
也可以使用char-read-uuid <uuid>
来读取。
从前面嗅探中可知,该灯是通过0x000e来写入数据。
可以命令char-write-req <handle> <value>
向 handle 中写入值。
关机:
如果char-write-req
报错,可以使用char-write-cmd
替换。
不过注意cmd是没有返回内容的,只能从设备反应来查看是否执行成功。
以上就是入门BLE协议的相关知识,关与协议的工具,有个比较强的大的框架mirage,不过相关文章很少,需要自行研究。
之后也会尝试更多相关设备的研究。