西湖论剑IOT蓝牙

前言

转载文章,记录学习

来源

https://xuanxuanblingbling.github.io/wireless/ble/2021/06/26/ble/

蓝牙协议

协议简介

新老并存是蓝牙协议栈复杂的主要原因,协议分层如图:

[image](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/protocal.png)

想了解最全面的蓝牙协议栈设计,可以去 蓝牙官网 找,目前最新的白皮书是:Bluetooth Core Specification v5.3

协议实现

谈协议分层总是很简单,因为上面这种图片随处可见,但其本质的内容是一个抽象的设计方案,而不是具体的实现方案(软件代码,硬件电路)。对于黑客来说,我们不仅仅关注抽象的协议设计上有没有问题,更关注的是协议的实现,因为设计一般都是经过世界上顶尖的大脑们反复推敲出来的,而实现可能就是某个开发者半夜一边吃外卖一边写出来的。协议设计的问题可能在白皮书中隐约看到,但实现的漏洞你是不可能从白皮书中看出来的,比如:

这些漏洞他们的本体在:

所以我们要了解的是,整个蓝牙的通信过程中,其数据处理的每一个过程究竟在哪?换种说法就是:每层的协议到底是软件实现还是硬件实现?如果是软件实现,那是什么层次的软件(应用代码、内核代码、还是芯片固件等等)?也就是具体协议的落地层次,可以参考:

主要就是三种架构方案,后两者的最大区别是:蓝牙app的业务代码与蓝牙协议栈是否运行在同一个处理器上。当然这也就会造成两者蓝牙模组/SoC的开发厂商提供的SDK的本质不同,单芯片的SDK主要完成编译烧录运行,而双芯片主要完成通信过程。

[image](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/realization.png)

PC和手机一般用蓝牙的都是host+controller双芯片标准架构,其通信的HCI协议也是蓝牙官方规定好的。通过分析linux的蓝牙驱动,以及相关芯片的datasheet,都能看出来这些芯片不参与任何上层协议的实现工作:

而嵌入式设备上的使用的蓝牙,可能会采用单芯片整体方案或者自定义双芯片架构,也就是那些蓝牙模组/SoC。模组,模块,SoC其实这些概念用起来比较混淆:

可见网上卖的大部分模组,模块,使用起来都应该属于自定义双芯片架构,因为你看上面的开发,配置一下串口然后就能直接使用GATT协议进行工作了,可见模组中已经实现了比较完整的蓝牙协议栈了。单芯片整体方案最常见的例子就是ESP32,我们的业务代码和蓝牙协议栈代码都运行在一个处理器上:

ESP32拆解图 可见:ESP32中就封装了一个ESP的SoC和flash

[image](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/esp32.png)

其蓝牙协议栈的实现在:https://github.com/espressif/esp-idf/tree/master/components/bt,即我们开发的业务代码最终会和这个蓝牙协议栈一起编译,打包,然后烧录进esp32的flash中,由esp32的xtensa处理器来执行。

攻击技能

这里只讨论从空口对另一台蓝牙设备的攻击,不讨论本地对自身的蓝牙驱动或者蓝牙芯片的攻击。

对于协议的抽象设计和实现方法有了清晰的认知之后,就是什么东西实现在哪?怎么实现的? 我们从开发者的视角切换成攻击者。我们不仅会对漏洞的发现,原理更加明晰,而且还能更清楚的知道,我们如何发动一次攻击:即在什么协议层次?怎么发送攻击流量?怎么完成这个层次的流量抓取? 此时我们需要回答一个问题:

  • 问:基本所有的手机或电脑本身都是支持蓝牙的,那为什么还要其他的外置硬件才能进行某些场景下的安全研究呢?
  • 答:研究一个通信的过程,黑客主要有五个动作:收、发、抓、断、改。本机的硬件可能不支持某些动作,比如发畸形链路层报文:[CC2541 SweynTooth BLE漏洞实测](http://iotbzw.com/2020/05/17/CC2541 SweynTooth BLE漏洞实测/)、抓空中其他设备的通信报文等等。

对于空中信号,完成基于中间人的断、改,一般通过拉长双方距离,然后采用中继设备来实现中间人,比如NFCGate。不过除了在通信的物理链路上做手脚,还可以在通信过程的软件实现处完成中间人,就像可以使用frida来hook掉android侧的app进而完成对蓝牙数据的修改一样,只要在关注的目标层次之前,篡改其未来要处理的数据即可。对于蓝牙的中间人我还没有调研过,这里还是主要说,收、发、抓这三个动作。

层次抓包

其实在通信过程的任何阶段,都可以想办法捕获通信内容,所说的常规方法只不过因为是现成的方案。

蓝牙抓包一般来说有如下几种办法:

方法 抓包位置 所需硬件 特点 方法说明
Ubertooth 空口 Ubertooth BLE/BR, open source 使用Ubertooth监听蓝牙通信
nRF52832 空口 nRF52832 only BLE nRF52832 Sniffer 抓包使用体验
cc2540 空口 cc2540 only BLE CC2540 USB Dongle 蓝牙抓包分析仪使用教程
hollong 空口 hollong only BLE Hollong 蓝牙4.0/4.1/4.2 BLE协议监控分析仪 文档
HCI接口 本机 本机蓝牙 only local 使用Ubuntu虚拟机抓Bluetooth报文
HCIlog 本机 本机蓝牙 only local Android Bluetooth HCI log 详解

抓包位置不同,捕获的数据包层次就不同,看起来的样子也不同,主要是两种,空口和HCI:

但是以上两个都不够直观,我们使用接下来的例题自己抓两个包:

可以清楚的对比两种报文的差异了,其实大差不差:

[image](https://xuanxuanblingbling.github.io/assets/pic/bluetooth/snifer_hci.png)

HCI和空口是蓝牙协议栈的不同层次,协议对两个层次的数据组织并不是简单的封装。这个差异最开始很让我困惑,因为我们太熟悉以太网的报文了,以至于理所应当的认为:数据在通信的每一个层次的流动就是简单做一些数据的包裹,即添加或删除一些头之类的操作。但其实数据在他的整个生命周期的过程,除了基本的包裹操作,还可以有非常多的变换,比如加密解密,编码解码等。这里的本质原因是:每个层次所考虑的问题不仅仅是对下层负责,可能还要在本层完成一些事情。

高级收发

攻击行为本质就是恶意数据的收发,任何包含发送数据的攻击都必然要有攻击的信道。

如果只是BLE应用层(ATT流量)的简单读写交互的话,nRF connect 这个手机软件就足够了,但当我们需要:

  • 攻击经典蓝牙
  • 在ATT层有复杂的交互
  • 攻击其他非ATT的底层协议

这时 nRF connect 就有些力不从心了,于是我们需要更高级的收发包方法,让我们能构造更丰富的恶意报文,所以我们需要尽量彻底的控制蓝牙设备,让其为我们工作。刚才我们说过,目前的手机以及PC都采用的是host+controller双芯片标准架构,所以由于硬件的限制,一般来说,我们只能构造链路层以上的报文。对于链路层和物理层的攻击,则需要更加可控的蓝牙设备,比如ESP32,[Nordic52840](http://iotbzw.com/2020/05/17/CC2541 SweynTooth BLE漏洞实测/),甚至是自己构建的SDR。这里我们只关注PC和手机平台作为攻击机:

攻击机 蓝牙设备 协议栈 原生API 顶层工具
linux PC PC蓝牙controller bluez D-Bus APIC socket API bluez toolsScapypybluezbluepypygattbluescan
android 手机蓝牙controller Fluoride java API nRF connect
iPhone 手机蓝牙controller 私有 Objective-C API nRF connect

bluez API 说明:Linux Bluetooth API Function Locations

在以上原生API的帮助下,我们在空口收发包的最低层次能到L2CAP。值得注意的是,HCI层协议是主机和控制器的交互界面,其自身的生命周期只存在于二者交互的过程中,而不存在于纯空口过程中。所以对于从空口上完成的HCI层攻击,还是发送其他层协议的报文,从而触发对端的HCI过程,进而发生攻击。

不过原生API的使用不够便捷与轻量,而linux的蓝牙攻击工具是生态最成熟的,基本都是python的库,只有bluez自带的用户态二进制工具除外。所以linux的PC是我们理想的攻击平台,但由于我们大都是使用linux虚拟机,其使用蓝牙设备的方式是和宿主机共享,在这种情况下可能会出现各种各样的问题,所以一般建议linux虚拟机独占一个蓝牙外设。比如我媳妇的惠普windows本中的linux虚拟机就可以使用共享本机的蓝牙设备正常攻击,而我的 MacBook Pro 上,虽然可以使用hciconfig看到蓝牙设备,但之后无法正常进行攻击,这里使用bluepy中的blescan进行测试。

所以当你尝试共享蓝牙设备给linux虚拟机不好使的情况下,才可能需要单独购买一个蓝牙USB外设。bluescan的官方文档中建议Ostran 奥视通 USB 蓝牙适配器 OST-105 CSR 8150 v4.0或者UD100 G03,我之前一直很奇怪为啥非得这俩蓝牙外设,他们多啥?这玩意淘宝一搜不一大堆么?后来仔细看看才发现,原来网上卖的蓝牙USB外设大部分没有linux的驱动,都是windows独占。另外这些蓝牙USB外设的信号也没有手机或者PC上自带的蓝牙芯片稳定,经常需要插拔,重新连接到虚拟机等重置操作。外设配置好后,就可以关注怎么控制外设收发包了,即linux上的蓝牙顶层工具,这些工具是各有特色:

工具 形态 底层 接口最低控制层次 特点
bluez tools 命令行 bluez HCI(BR/BLE) 基础:主要用于配置检查,能完成一些基本的正常业务数据包
Scapy python bluez HCI(BR/BLE) 收发:使用复杂,可在python层面直接控制HCI,组织数据包灵活
pybluez python bluez L2CAP(BR/BLE) 收发:成熟的python蓝牙库,对L2CAP、RFCOMM层的接口友好
bluepy python bluez GATT (BLE) 收发:GATT相关处理较多,扫描脚本blescan命令行直接可用
pygatt python gatttool GATT (BLE) 收发:将gatttool(bluez tools)封装成python接口
bluescan python bluepy , pybluez HCI(BR/BLE) 扫描:安恒海特实验室 Sourcell Xu 开发,安全向,主要用于扫描,Python 3.9以上适配

工具使用示例文章:

有了这些工具,学会了怎么使用这些工具配置,发包,扫描,就可以完成下面的题目了。