“传统蓝牙”规范在2.4GHz的ISM波段上定义了79个信道,每个信道有1MHz的带宽。设备在这些信道中以每秒1600次的频率进行跳转,换句话说,就是每微秒625次跳转。这项信道跳转技术被称为“跳频扩频”(Frequency HoppingSpread Spectrum,FHSS),这时的蓝牙设备中,用户最大可以达到3Mbps的通信带宽,最大约为100米的传输距离。“跳频扩频”通过在射频(RadioFrequency,RF)频谱中快速地移动,针对噪声信道为通信提供鲁棒性(robustness)。
任何通过蓝牙技术进行无线通信的设备,需要通信双方在同一时刻处于同一信道之内如下图所示。通过协调的方式进行跳频的所有设备可以相互进行通信,它们共同组成了一个蓝牙的“微微网”。“微微网”是两个或者多个蓝牙设备之间使用的基本网络模型。每个“微微网”都有一个“主设备”(master)和一个到七个“从设备”(slave)。“微微网”中的通信是严格在一个“从设备”和一个“主设备”之间进行的。“微微网”中使用的信道跳跃的顺序是伪随机性的(pseudorandom),它只能通过“主设备”的地址和时钟产生
“设备发现”技术
就像所有的无线协议一样,使用蓝牙进行通信时,也同样需要确认在功率覆盖范围内是否有可能的“接入点”(peer),这个似乎并不难,只要大家同一频率,使用相同的通信协议握手即可,而当使用“跳频扩频”技术的时候,这个问题会变得非常复杂。假定在某一段时间内,有两个蓝牙设备已经在“微微网”中开始交互操作,这当然意味着它们两个设备的跳频的序列是一致的。但是每一个设备同样是“可发现的”(discoverable),这意味着这个蓝牙设备会周期性地广播它的“蓝牙设备地址”(BluetoothDeviceAddress,BD ADDR)到其他还没有加入到这个“微微网”的蓝牙设备上,以便这些设备可以通过它的广播找到它。在这种情况下,这个蓝牙设备就必须暂时地停止它在“微微网”中的跳频动作,然后进入“监听”状态,以便监听是否有其他可能的蓝牙设备正在找自己,如果有,则对那些请求做出回应,然后回来找到原来那个跟自己在“微微网”中通信的蓝牙设备,继续之前的通信过程。这种定期检查其他设备是否在找自己的机制,称为“可发现的”。
许多蓝牙设备默认都不是“可发现的”,所以你需要专门开启这项功能,这通常需要一段时间该操作才能生效。在你打开一些以iOS作为系统内核的移动设备的蓝牙配置“设置”(Settings)页面时,系统会默认进入“可发现的”模式。如果某设备无视其他设备的“发现请求”(discoveryrequest,或者也不主动寻找其他设备的“发现请求”,那么这个设备就称为“非可发现的”(non-discoverable)设备。要与这种“非可发现的”设备进行通信,唯一的方法就是通过其他一些手段,在拿到它的“蓝牙设备地址”以后,再通过“蓝牙设备地址”进行通信
协议概述
在一个蓝牙网络中,可能使用着的协议数量足以令人咋舌。这些协议通常可以分成两类:一种是在“蓝牙控制器(Bluetooth controller)之间通信使用的,另一种是在“蓝牙主机”(Bluetooth host)之间通信时选择使用的。因为本书属于无线网络安全的主题,所以上面所说的“蓝牙主机”就是我们从笔记本电脑上运行攻击程序所攻击的对象。“蓝牙控制器”则是内置在笔记本电脑里的USB芯片组(chip),或是USB加密狗(dongle),接受“蓝牙主机”的命令,并解释执行这些命令
如图显示了蓝牙协议栈中各层(layer)的组织结构,以及在每一层中,具体实现了哪些协议。
从图中可以看到,“蓝牙控制器”负责跳频,基带封装(basebandencapsulation)并且将适当的结果返回到“蓝牙主机”。
“蓝牙主机”负责处理更高层的协议,尤其是“主机控制接口”(Host Controller Interface,HCI)连接,它是“蓝牙主机”(你的笔记本电脑)和“蓝牙控制器”(你的蓝牙适配器中的芯片组)之间的通信接口。
在和蓝牙打交道的时候,需要把这个“蓝牙主机”/“蓝牙控制器”的模型放在你的脑海中。
但作为黑客,我们最渴望的是对设备绝对的控制权,以便于可以操纵它的行为。如果将图中的“蓝牙控制器”部分从整个模型中分离出来,那就意味着对于“蓝牙控制器”控制的那部分功能,我们都只能任由摆布而无可奈何。无论我们想让“蓝牙控制器”做什么,比如“始终保持在信道6上,不要再接收后面的包”,除非将这些要求转换为一系列的“主机控制接口”请求,或者通过另一种方式实现这些功能,否则无法达到预期的目的。最终导致我们对于这个无线设备没有那么多的控制能力。
(1)射频通信协议
“射频通信协议”( Radio Frequency Communication,RFCOMM)是蓝牙设备中采用的传输协议,使用该协议的蓝牙设备,一般是那些需要稳定的基于“流”(streams-based)的传输,这点和TCP协议很相似。“射频通信协议”被广泛应用于模拟串口通信,向电话设备发送 AT命令集(又称“Hayes 命令集”),在“对象交换协议”(Object Exchange,OBEX)协议上传输文件。
(2)逻辑链路控制及适配协议·逻辑链路控制及适配协议”(Logical Link Control and Adaptation Protocol,L2CAP)是基于数据报文(datagram-based)的协议,该协议主要用于传输更高层的协议,比如“射频通信协议”和其他上层协议。一个应用层的程序员可以将“逻辑链路控制及适配协议”作为一种传输层协议使用,由于它是基于数据报文的,所以它的运行和UPD协议的运行很相似,是不可靠的连接方式,采用的是基于消息的数据传送机制。
(3)主机控制接口协议
如前面所说,蓝牙标准规定了使用“主机控制接口协议”的接口层来控制蓝牙芯片组这些芯片组就是上面提到的“蓝牙控制器”。对于开发者来说,要访问标准蓝牙硬件的协议栈,远程“友好设备”(device-friendly)名称检索,连接建立以及终止,“主机控制接口协议位于他们所能访问到的协议栈的最底层。
(4)连接管理器协议连接管理器协议”(Link Manager Protocol,LMP)位于“蓝牙控制器”协议堆栈的顶部,通过特定的硬件才能够访问它,换句话说,没有特定的硬件,这个协议是不可访问的因此“连接管理器协议”主要用于处理那些“低层次加密”(1ow-evel encryption)、信息验证(authentication)、数据配对(pairing)等操作。虽然通过控制“蓝牙主机”也可以完成这些功能,并可以明确地请求这些操作,但是“蓝牙控制器”的职责就是决定应该发送哪种类型的数据包,以及如何处理结果。
(5)基带层
和“连接管理器协议”层类似,开发者在没有特定硬件工具的前提下,是无法访问基带(baseband)层的。蓝牙的基带层主要规定了空中传输的参数(比如传输的速率),数据包最终在哪一层是形成帧,以及确定传送和接收的信道
(6)蓝牙设备地址“蓝牙设备地址”是一个48位(共6个字节)的数据,由三部分组成。
非必要地址部分“非必要地址部分”(Nonsignificant Address Part,NAP)有16 位长度位于“蓝牙设备地址”的前16位,是“组织唯一标示符”(Organizationally UniqueIdentifier,OUI)的一部分。这一部分被称为“非必要”的原因是这 16位不会在跳频和其他蓝牙派生函数中使用。(前两个字节)
高位地址部分“高位地址部分”(UpperAddressPart,UAP)有8位,是“组织唯一标示符”的后8位部分。(中间一个字节)
低位地址部分“低位地址部分”(Lower AddressPart,LAP)有 24位,用来标识一个独一无二的蓝牙设备。 (后三个字节)
不像其他的无线协议中地址是公开并广泛使用的参数,在蓝牙网络中,“蓝牙设备地址是作为一个秘密信息,不对外公开的。在以太网以及Wi-Fi无线网中,数据帧中都包含有地址,而在蓝牙通信中,“蓝牙设备地址”并会不包含在数据帧的头部进行传输,从安全的角度,这样就防止了攻击者使用侦听技术轻而易举地发现“蓝牙设备地址”的值。更为巧妙的是,恰恰是没有“蓝牙设备地址”信息,所以攻击者很难发现网络中正在使用的跳频规律从而更增加了数据通信数据包的侦听难度
加密和认证
加密和认证是直接包含在蓝牙标准规范中的,它直接在“蓝牙控制器”的芯片组中实现这对于使用者和开发者来说是一种节约成本的措施。加密和认证使用与否是可选的,协议的开发商可以既不认证,也不加密;或者二者选择其中之一;或者两者皆用。
蓝牙的认证或者使用“传统配对”(traditionalpairing)方式,或者使用在“蓝牙2.1规范(Bluetooth 2.1specification)中新设计的“安全简化配对”(SSP)方式。下面的内容中,我们将会讲解这两种认证机制。
1.传统配对
在当前大多数的蓝牙设备上,尽管“传统配对”认证的交换方式仍然在使用,但在“蓝牙 2.1规范”中,“传统配对”方式被“安全简化配对”方式所取代。在使用“传统配对”方式中,当两个设备第一次相遇的时候,它们会完成一次配对交换,在这个过程中,每个蓝牙设备都从“蓝牙设备地址”中会派生出一个“安全密钥”(securitykey)、一个“个人识别号码”personal identification number,PIN),以及一个随机数,其中的“安全密钥”又称为“连接密钥”(link key)。当交换过程结束的时候,两个设备都会将“连接密钥”信息存储在本地的
'非易失性存储器”(local nonvolatile memory)中,以便在之后的认证交换中使用,以及需要使用的时候,用来派生“加密密钥”如果一个攻击者捕获到用于派生“连接密钥”的“传统配对”方式交换过程,同时也捕获了随后的认证交换过程,那么他随后攻击所选择的“个人识别号码”是完全有可能的。通常来讲,这是通过“个人识别号码”的“暴力攻击”(brute-forcc attack)来实现的,也就是通过猜测的“个人识别号码”计算,生成一个可能使用的“连接密钥”,随后将本地计算的认证结果同合法交换过程中的结果进行比较,最终检验所猜测的“个人识别号码”是否正确详细的计算过程和攻击技术细节,我们会在后面进行讲解。
2.安全简化配对
在我们刚刚介绍的“传统配对”策略中,存在的最大问题就是这个实施被动式攻击的攻击者在捕获配对数以后,能够迅速地还原得到“个人识别号码”和存储的“连接密钥”。如果这个攻击者成功地拿到“连接密钥”,那么他就可以通过蓝牙网络解密所攻击的这一对蓝牙设备上的所有数据包交换,还能伪造合法设备参与其中。“安全简化配对”方式则会阻止这种被动式攻击的攻击者获得“连接密钥”,并且对于不同的蓝牙设备类型,提供多种认证选项。
“安全简化配对”方式通过采用“公钥密码学”(public keycryptography)的策略来改善蓝牙认证交换过程中的安全性,特别是通过“Difie-Hellman“圆曲线密钥”(Elliptic CurveDifie-Hellman,ECDH)算法实现交换机制。一次 Difie-Hellman的密钥交换允许两台对等的蓝牙设备先交换“公钥”(public key),然后从中派生出一个“共享密钥”(shared secret)这个密钥对于捕获者来说是无法再生成的。这个产生出来的密钥被称为DHKey(即DiffieHellman key)。最终“连接密钥”由DHKey派生,并在随后的认证和加密过程中使用。通过 DHKey 交换算法的使用,一个强大的“熵池”°(entropypool)可以用来派生双方设备上的“连接密钥”。这个强大的“熵池”解决了“传统配对”派生中最大的问题,那就是在“熵池”,每一个单一的资源只是一个很小的“个人识别号码”值。在介绍完了蓝牙技术的组成之后,我们就可以以攻击者的视角来讲解蓝牙了。同样我们会讲解各种攻击蓝牙技术的方法,深度挖掘支持这一全球标准的各相关技术和组件。
侦察
在蓝牙攻击的侦查(reconnaissance)阶段,我们可以借助“目视检查”(visualinspection)和“组合发现”(hybrid discovery),通过“主动式发现”(active discovery)和“被动式发现"(passive discovery)方式,在附近区域,检查并确定“要攻击的”蓝牙设备。这里的“发现”进程就是确定存在的蓝牙设备,以及寻找到每个设备的48位“蓝牙设备地址”
一旦你发现了一个蓝牙设备,就可以开始枚举这个设备上所使用的服务,确认可能的攻击目标。还可以采集远端设备的特征值(fingerprint),使用蓝牙嗅探工具(snifingtool)捕获“微微网”中的数据,进而获得访问机会。下面,我们就详细讲解这些步骤。
激活蓝牙
hciconfig
hciconfig hci1 up
以下主要是针对传统蓝牙模块
主动式扫描
Linux 上使用 hcitool 进行设备发现
Linux的标准命令hcitool可以用来进行“蓝牙发现”和基本的“服务枚举”。与前面各工具相比,该命令具有一定的智能化,即当在扫描的时候,hcitool程序会缓存所有已扫描好的蓝牙设备的相关信息,这意味着,如果有某个蓝牙设备离开了自己信号覆盖的有效范围后,程序仍然能够潜在地告诉你。当然,如果你对这个功能没有兴趣,你只想关注当前自己信号覆盖以内的蓝牙节点,也就是说强制hcitool程序不要对结果进行缓存,那么可以通过“--flush”参数进行指定。另外,默认情况下,hcitool程序只会显示扫描到蓝牙设备的“蓝牙设备地址”和“设备名称”两项信息,如果你想获得更详细的信息,可以通过加上“--all”参数来实现。
hcitool scan --all --flush(执行蓝牙设备的全面扫描,并刷新缓存)
对于每一个蓝牙设备,在接到查询命令时,都会做出回复,而hcitool程序正是从这些回复中提取设备的信息。这些信息可以包含“蓝牙设备地址”、设备名称和设备类型、无线生产商(radio manufacturer)、“连接管理器协议”的版本号,以及详细的枚举信息。
Linux 上使用 BTScanner 进行设备发现(推荐)
- h:帮助 (help)。按下此键可获取 btscanner 的帮助文档和命令列表。
- i:查询扫描 (inquiry scan)。按下此键将在附近的蓝牙设备中执行查询扫描,以获取设备的基本信息。
- b:强制扫描 (brute force scan)。按下此键将执行强制扫描,尝试获取更详细的信息,如服务和特征的列表。
- a:中止扫描 (abort scan)。按下此键将停止当前的扫描操作。
- s:保存摘要 (save summary)。按下此键将保存当前扫描结果的摘要到文件中。
- o:选择排序 (select sort)。按下此键将打开排序菜单,允许你选择按特定字段对扫描结果进行排序。
- Enter:选择 (select)。按下此键将选中当前光标所在的设备进行进一步操作。
- Q:退出 (quit)。按下此键将退出 btscanner。
虽然使用hcitool命令行工具进行快速的蓝牙设备扫描是很方便的,但是这个命令没有持续扫描的能力,这个命令只在发现有蓝牙设备在自己功率覆盖范围之内时更新一下显示结果。要解决这个不足,让对于这种类型的扫描一直处于持续进行中的显示状态,那么Linux上的BTScanner工具则是一个更好的选择,这个工具在持续扫描蓝牙设备的同时,提供一种简单的、基于文本的接口,将每个发现的蓝牙设备,都以一行内容的效果显示出来。虽然只用一行信息显示,但并不意味着这个工具显示的内容少,可以这么说,除了配对(pairing)信息之外,BTScanner 工具会尝试收集尽可能多的信息。如果用户选择显示某个指定的蓝牙设备时,这个工具会提供一个与这个蓝牙设备相关的详细信息视图。
注意:BTScanner 中存在的 bug
bug 像瘟疫一样遍布在许多新的程序中,许多黑客工具也都难于幸免,BTScanner程序也不例外。现在的 BTScanner 程序,其原作者已经多年没有对它进行维护升级了,这导致程序中存在的 bug至今仍然存在着。
消失的设备
在BTScanner程序的显示中,设备列表中正在显示的蓝牙设备,会突然莫名其妙地消失。在遇到这种问题时,要想找回消失的蓝牙设备,一个变通方案是:如果设备从显示列表中突然消失,则按小写字母键“0”打开“选择一种排序方法”(Enter ASort Mcthod)对话框,然后随便按什么排序,以便改变当前的显示顺序,然后再按小写字母键“f”和“回车”键回到上一级显示中,这时消失的设备就会因为重新排序而出现。无法启动 BTScanner程序 在“终端”窗口中,运行BTScanner程序需要终端窗口至少有80个字符的显示宽度。如果你尝试在小于这个宽度的终端窗口中打开BTScanner程序运行的话,你会看见“状态栏”显示“已完成读取 OU】数据库”(Finished reading theOUl database)的状态信息提示,然会返回到Shell 外壳命令行提示状态。所以,在开启BTScanner程序之前,首先确认你的终端窗口至少有80个字符的宽度(最好有24个字符的高度)或者更大
调整尺寸时会崩溃,如果你在BTScanner程序运行的时候,尝试调整“终端”显示窗口的大小,那么BTScanncr程序就会崩溃,并提示“分段的'段地址’访问错误”Segmentation fult)。避免这种情况,需要在开启BTScanner之前,先确认你要使用的窗口大小是否合适,如果不合适,马上调整,直到“终端”窗口的尺寸合适了,再运行程序否则,在退出BTScanner程序之前,不要尝试调整“终端”窗口的大小。
BTScanner程序创建的所有目录和日志数据都只有root用户才能够访问,所以如果在使用cd命令转换到bts目录时遇到了“禁止访问”(Permission denied)的提示信息则需要运行“sudo su”命令切换到root 权限才行
apt-get install btscanner 安装
btscanner 启动
按i开始扫描
得到结果
BTScanner程序最大的特征之一,是程序为每个被发现的蓝牙设备所生成的日志信息当你运行 BTScanner程序时,它会在用户的主目录下创建一个名为bts的目录。在这个目录中,BTScanner程序会根据设备的“蓝牙设备地址”,为每一个被发现的节点再各自创建一个目录,不过,因为冒号不适合做文件名和目录名,所以BTScanner程序会把“蓝牙设备地址”中冒号分隔符替换为下划线分隔符(比如00_02_EE_6E_72_D3)。
在每个设备目录中,BTScanner 程序都会创建两个文件:“时间戳文件”(timestamps file和“信息文件”(info file)。“时间戳文件”中包括 BTScanner 每次收到蓝牙设备回应的时间在跟踪移动蓝牙设备的时候这个记录会非常有用,可以根据时间来判断,在某一段时间里这个蓝牙设备是否在或者不在自己的功率覆盖范围之内。
“信息文件”包括详细的设备信息,包括“蓝牙设备地址”、“设备制造商名称”、“蓝牙设备地址”所关联的“供应商名称”、、“组织唯一标示符”编码,“MAC地址前缀”,以及一份详细的设备所有服务列表。
除了BTScanner程序存在一些bug(详见前面“BTScanner 中存在的 bug”的内容)之外,BTScanner 程序的日志存储和分析功能对于确认“可发现的”蓝牙设备是非常有用的。遗憾的是,BTScanner程序的作者不再进行升级开发这个程序了,因此本程序,将来恐怕也难看到任何bug的解决方案了。
被动式扫描
在蓝牙规范中,并不要求两个需要通信的蓝牙设备之间通过“询呼扫描”(inquiry scan)进行数据的交换。因此,如果你通过一些第三方的外部技术,获得了某个蓝牙设备的地址,比如你是通过阅读文档找到的。那么对方的蓝牙设备,区分不出你现在所发起的连接,是在获得“蓝牙设备地址”后是直接发起的,还是通过主动式的扫描后,从扫描中拿到“蓝牙设备地址”后发起的。无论是哪一种,都会涉及“蓝牙设备地址”,所以这部分的介绍,全都是被动式捕获“蓝牙设备地址”的技术。
目视检查
有时候,要确认一个蓝牙设备,简单的“目视检查”(VisualInspection)足矣!因为前面所谓的蓝牙设备,其实并不存在这样一个叫“蓝牙”的设备,而是说某个设备具有蓝牙功能的通信接口,因此具有蓝牙接口对于许多设备来说是很值得自夸的一个功能,凡是具有此功能的产品,都会在产品上打上“蓝色的LED灯”图案,或者蓝牙的“蓝牙技术联盟”的标志。
举例来说,一个超市的所有收款台都配有手持的条形码扫描仪,与传统有线的条形码扫描仪相比,对于一般小件物品,二者相差不大,但对于扫描大件物品时,由于蓝牙手持的条形码扫描仪不需要连线,可以在一定范围内随便移动,不受连线的限制,因而其优势十分明显。上面的蓝牙标志清楚地标明,这个设备是使用蓝牙技术进行通信的。
在付款台附近进行一次非正式扫描之后,我们发现所有的蓝牙手持条形码扫描仪现在的配置都处于“非可发现的”模式中。
这就意味着,如果我们想对它们实施攻击,那么前面提到的主动式扫描发现是不可行的,这该怎么办呢?仔细地观察这些扫描仪的底座,可以发现每个底座上都有一个条形码,而该条形码正是这台手持条形码扫描仪的“蓝牙设备地址”。
拿到这个条码值,结合前面对“蓝牙设备地址”的介绍,我们知道这个地址的前3个字节是“00:0C:A7”,分别是“非必要地址部分”、“高位地址部分”部分,共同组成了IEEE“组织唯一标示符”的生产商编码。这个生产商编码可以通过 http://standards.ieee.org/regauth/oui/oui.txt 查询所对应的生产厂家。通过查询,我们可以知道该蓝牙手持条形码扫描仪的设备生产商是“码捷(苏州)科技有限公司”(Metro(Suzhou)Technologies Co.,Ltd)。访问“码捷科技”的网站,知道这是“码捷科技”(Mecrologic)的一个子公司,并且这款蓝牙手持条形码扫描仪的型号是MS9535 VoyagerBT。从“码捷科技”公司的公司网站上,我们还可以找到有关这款扫描仪的一份PDF版本的用户指南,在上面描述了这款设备的默认“个人识别号码”信息。
把“蓝牙设备地址”信息印贴在设备外壳上是很普遍的现象。
由于两个蓝牙设备之间,必须共享“蓝牙设备地址”信息才能完成“配对交换”的操作,所以要与某个蓝牙设备进行联系,必须通过某种方式输入对方的“蓝牙设备地址”信息。可以通过蓝牙设备自动完成的“询呼请求”/“询呼应答”过程,也可以通过手动输入操作,还可以通过其他第三方的一些方式来完成。
对于那些结构简单的蓝牙设备,由于缺少“LCD显示屏”,并且没有什么可配置的选项,所以手动输入“蓝牙设备地址”信息的方法并不可行。虽然使用“主动式扫描发现”是可行的,但是当扫描时,同时发现多个蓝牙设备的时候,对这些设备进行区分又变成了麻烦事,因为此时虽然知道在你的功率覆盖范围内有几个蓝牙设备,也知道每一个蓝牙设备的“蓝牙设备地址”信息,但哪一个蓝牙设备对应于哪一个“蓝牙设备地址”呢?或者说你要与哪一个蓝牙设备进行“配对”操作呢?这时,最有效的办法,就是直接将每一个蓝牙设备的“蓝牙设备地址”信息印在或写好贴在设备上。
组合式扫描
在确认识别某个蓝牙设备的时候,如果“主动式扫描发现”和“目视检查”都无法奏效那么不妨试试下面几种组合发现机制
Wi-Fi和蓝牙在地址上的“大小差一”
当一个设备制造商在生产一个需要带有多个接口的产品时就必须为每个接口都配置一个MAC地址。通常来讲,单个设备上的多个MAC 地址之间通常都是彼此相关的。
从技术的角度来看那就是这些MAC地址之间的前5个字节都是相同,但是最后一位在数值上相差1,这个称为“大小差一”(Of-by-One)“现象。
比如,某个蓝牙设备有两个接口,如果设备制造商给第一个接口配置的MAC地址是 00:21:5C:7E:70:C3,那么第二个接口的 MAC地址通常是 00:21:5C:7E:70:C4。
根据这种设备制造商的习惯性行为,有些系统就可以将MAC地址相连的两个接口,识别为是一个设备上的,这种想法已经被“无线入侵检测系统”( Wireless Intrusion DetectionSystem,WIDS)的供应商用在判断网络上的恶意 AP 接入点的算法上了。
其原理是,在通过一个“网络地址转换”连接的网络上,如前所述,作为无线IEEE802.11访问网络中,其“基本服务集标识”其实就是AP接入点的MAC地址,而有线网络中,其“网络地址转换”的MAC地址当然还是网卡硬件的MAC地址,如果这两个地址相差1,这足以说明这两个MAC地址位于同一个设备上,那么,一个设备为何需要既通过无线上网,又通过有线上网呢?唯一的可能就是“这是一个AP接入点”,而一个单位中,有限的几个AP接入点在“无线人侵检测系统”中都登记在案,既然没有被登记,那很可能就是一个恶意的AP接入点。回到本节的主题上,同样的逻辑判断方法,我们也可以判断一个产品上的蓝牙接口,比如说某iPhone,一般同时提供了用于无线网卡的“基本服务集标识”地址和用于蓝牙的“蓝牙设备地址”地址,而这两个地址通常情况下都会相差1。
打开较早期的iPhone手机,Apple在给Wi-Fi无线网络接口分配的MAC地址和给蓝牙接口分配的MAC地址就存在“大小差一”现象,蓝牙接口分配的“蓝牙设备地址”地址比Wi-Fi无线网络接口分配的“基本服务集标识”地址大1或小1。如果你想确认一下是不是,可以通过单击iPhone 手机上的“设置(Settings)|常规(General)关于(About)”菜单进行查看
知道了这种产品制造商的习惯性行为以后,一旦我们确认了Wi-Fi和蓝牙二者MAC地址之间的关系,我们还可以借助这种关联互相判断二者的行为。比如,我们通过某iPhone手机在无线网络上,以客户端身份所做的操作拿到其Wi-Fi的“基本服务集标识”地址,然后将加减1以后的“逻辑'蓝牙设备地址’”地址,在蓝牙网络中进行测试。并且,在实战中,我们也不需要把在 Wi-Fi无线网络中查到的所有“基本服务集标识”地址一一地进行蓝牙的“蓝牙设备地址”测试。既然知道对方的手机是iPhone,那么它的设备“组织唯一标示符”编码应该是Apple 公司。所以它的“蓝牙设备地址”的前三位,是不是也应该是 Apple 公司的前三位代码呢?在我们编写本书的时候,共有18997个“组织唯一标示符”编码被分配,其中 Apple 公司共分配到 284个"。
“组织唯一标示符”编码仍然是前面提到过的:http://standards.ieee.org/regauth/oui/oui.txt。
在“监测模式”下使用Wi-Fi无线网络接口,我们可以使用 Wireshark 工具集中基于文本(text-based)的tshark程序来捕获“探测请求”(probe request)数据包。
在下面的应用中由于只是查找客户端的MAC地址,所以我们只要监听和捕获发自客户端所在系统中的数据包即可。
在下面的示例中,我们通过“-i wlan0”参数指定了无线网卡第一个接口,然后通过“-Nm”参数告诉tshark程序要对MAC地址的前缀进行解析,这样如果该设备可以在上面“组织唯一标示符”编码表中查到,则直接显示公司的名称,便于你的识别。
然后再通过“-R wlan.fc.type_subtype eq 4”参数,告诉 tshark 程序告诉“显示过滤器”(display filter)在显示的时候,只是显示“探测请求”数据包。
还要通过“wlan.sa”参数告诉 tshark 程序的是在显示的时候,只在界面上增加无线通信的源地址即可。该源地址还会作为附加的字段进行显示,这是通过“-z proto,colinfo,wlan.sa,wlan.sa”参数实现的。默认情况下,tshark程序会以行为单位显示每一个扫描到的结果,这个行称为“标准包汇总行”(standard packesummary line),在每一行中,主要显示“源地址”,但是通过“-z”参数可以实现“二次配置”,将其作为静态选项,显示成既有对前缀解析过的(prefix-resolved),也有未对前缀解析过(prefix-unresolved)的MAC地址格式,以便进行前后对照。其显示效果如下所示:
在无线网络中,使用 airmon-ng命令进行嗅探的时候,通常习惯于将无线网络接口在信道1中设置为“监测模式”。而无线设备在发送“探测请求”数据包的时候,是向所有信道发送,以便可以捕获到那里活动的无线设备。所以上面例子中,由于信道选择的原因,只能扫描到所选频率上存在的无线设备
从上面的输出结果中,你可以看到两个“探测请求”数据帧。第一个“探测请求”帧来自前缀是HonHaiPr的设备,因为它不是iPhone,所以可以选择忽略。下一个“探测请求帧的源MAC地址为“Apple 58:94:D6”,这个明确标明了就是从一个Apple 设备发送过来。除此之外,作为与前面MAC地址的前缀解析格式进行参照,在后面扩展的统计显示区域内也以全地址的格式显示了MAC地址,即E4:98:D6:58:94:D6。
如果在上面tshark的命令后面,再加上“|grep Apple”参数,那就等于是增加一个对关键字“Apple”的筛选器,这样,在输出的结果中,就只会显示带有“Apple”字样的设备了。
一旦通过 Wi-Fi无线网卡的方式获得了这个Apple手机的MAC地址,就可以通过这个无线网卡的MAC地址尝试获得蓝牙通信中的信息了,比如使用hcitool命令可以获得蓝牙“友好名称”( fiendly name)。其原理和方法,还是如上所述,首先从得到的 Wi-Fi无线网卡的MAC地址上,将最后一个字节的值加1,然后将新的MAC地址值作为“蓝牙设备地址”当然,为了保险,你也可以考虑将Wi-Fi无线网卡的 MAC地址中最后一个字节减1,作为在加1后失败的一个后选方案,这样看上去更加周密。
记住!上面无论是“加1”,还是“减1”,都是以十六进制的方式进行的。比如,下面以“加1”为例,如果某次扫描拿到的Wi-Fi无线网卡MAC地址的最后一字节是44,那么你可以在hcitool命令中,推算该蓝牙设备的MAC地址的最后一字节是 45。而如果最后一个字节的值是39,那么推算出的值最后一个字节就是3A,而不是40。
被动通信数据包分析
如前所述,一个“传统蓝牙”的数据包中的包头位置,并没有包含“蓝牙设备地址”信息,这一点不像IEEE802.11的Wi-Fi无线网络通信数据包,也不像以太网有线通信的数据包。不过,对于蓝牙通信,在蓝牙设备在加入“微微网”的时候,“从设备”采用的是一个没用的“逻辑传输地址”(Logical Transport AddresS,LT ADDR)。这个地址将在之后的通信中.作为该设备之后所有通信的“逻辑源地址”(logical source address)或“逻辑目标地址”(logicaldestination address)。“逻辑传输地址”只使用了3位来表示“逻辑源地址",而不像“蓝牙设
备地址”有48位,在保存的时候也得全部保存。这种设计非常重要,因为这意味着即使通过捕获数据包,检验MAC地址的头部信息也无法确定某个“活跃”(active)的蓝牙设备完整的“蓝牙设备地址”。不过,通过检测其他各个“活跃”蓝牙设备的MAC头部,至少离拿到完整的“蓝牙设备地址”的目标更近了一步。这一点你会在随后的内容中看到。
促使每一个数据包在蓝牙网络中传输,是由一系列“数值”(value)和“字段”(field)组成的,这些“数值”和“字段”统称为“访问码”(access code)。“访问码”由3部分组成:“前导码”(preamble),“包尾”(trailer),“同步字”(sync word)。
“同步字”是蓝牙“微微网”中发送的每个数据包的重要组成部分。每次一个“从设备或者“主设备”收到一个数据包,“同步字”都会在基带头部数据开始传输之前,帮助无线接口稳定接收数据。对于一个给定的“微微网”“同步字”也可以用来确认通信数据包的来源,因为不同的“微微网”之间,“同步字”都是唯一的。这样的好处就是在同一片物理空间中,可以有多个蓝牙网络彼此接近,或互相重迭运行,都不会在识别自己“微微网”数据包的时候导致模棱两可的结论,也不会在接到一个数据包后,不知道这个数据包是来自于哪个“微微网”
如下所示,“同步字”由3各部分组成:“BCH 纠错码”(BCHerror correcting code)、“低位地址部分”、“巴克序列”(Barker Sequence)。其中,“BCH 纠错码”用于检查和纠正接收到数据中的错误,BCH是由其发明者Bose、Ray-Chaudhuri、Hocquenghem三人的首字母组合命名的;“低位地址部分”如前面7.1.2节所述,是“蓝牙设备地址”的低 24位;“巴克序列'用于数据间的互相关联,提高数据包检查中数据正确性的概率,减少数据包看似正确、实际错误的概率)。对于想拿到“蓝牙设备地址”的黑客来说,“低位地址部分”字段无疑是最令他们感兴趣的,因为它包含了“蓝牙设备地址”中的末尾3个字节,也就是 24位。
通过将“主设备”的“低位地址部分”编码到“同步码”中,在“微微网”中的任何蓝牙设备在接收到某个数据包之后,都可以确认这个数据包是不是给自己的,这样就能够区分处于同一物理空间中的两个或者更多的“微微网”。对于黑客来说,则可以借助于从一个“活跃”的“微微网”中拿到的“同步字”,得到“主设备”的“蓝牙设备地址”的“低位地址部分”部分。而且,此时也可以判断处于“非可发现的”模式的蓝牙设备中“蓝牙设备地址”的“高位地址部分”部分。这是因为“蓝牙MAC层”(BluetoothMAC-layer)的包头包含一个称作“头部校验和纠错校验”(Header Eror Correction,HEC)和的字段,该字段的结构如下图所示。其中的“头部校验和纠错校验和”本身只是MAC层数据的一个简单的校验和,没有特殊的含义,但是,这个校验和在计算的时候,需要将“高位地址部分”作为输入,这就意味着高位地址部分”的值可以通过这个校验和获得。通过收集多个蓝牙数据包,你可以准确地判断出“高位地址部分”的值,并排除假的值。结合上面读到的“低位地址部分”值,就等于是拿到了48位“蓝牙设备地址”中的32位了。
不幸的是,标准的蓝牙接口并不提供“同步字”的内容。对于这些设备,由于设计者并不希望用户对这些底层的信息感兴趣,所以这些设备缺少捕获这类底层蓝牙数据包信息的接口。幸运的是,在一些开源硬件和软件项目中,多多少少会涉及这方面的内容,通过这些可用信息的组合,可以帮助我们间接确认这些信息
超牙(蓝牙5.0)的被动式发现 (使用ubertooth-rx工具)
使用外接蓝牙5.0,并且使用ubertooth-rx工具
示例用法:
ubertooth-rx – 扫描并嗅探所有 LAPs
ubertooth-rx -l <lap> – 计算给定 LAP 的 UAP
ubertooth-rx -l <lap> -u <uap> – 计算时钟并跟踪蓝牙Piconet
ubertooth-rx -z -t 20 – 调查模式: 在20秒内发现所有 LAPs+UAPs
主要模式:
-l <LAP> 解码 (6位十六进制) - 如果未指定,则嗅探所有 LAPs
-u <UAP> 解码 (2位十六进制) - 如果未指定,计算 UAP (需要 LAP)
-z 调查模式 - 发现并列出 piconets (自动包含 -s, 使用 ctrl-C 中断)
-i <文件名> 输入文件 - 如果未指定,使用 Ubertooth 进行实时捕获
配置:
-c <蓝牙频道> 设置固定蓝牙频道 [默认: 39]
-e 最大 AC 错误 (默认: 2, 范围: 0-4)
-t <秒数> 嗅探超时 - 0 表示无超时 [默认: 0]
输出选项:
-r<文件名> 抓取数据包到 PcapNG 文件
-q<文件名> 抓取数据包到 PCAP 文件
-d<文件名> 转储数据包到二进制文件
其他:
-V 打印版本信息
-U <0-7> 设置要使用的 Ubertooth 设备
从命令行运行ubertooth-rx工具,该工具就可以从活跃蓝牙发射节点中提取出“蓝牙设备地址”中的“低位地址部分”的值,如下所示:
ubertooth-rx
尽管这些蓝牙设备配置为“非可发现的”模式,但从上面ubertooth-rx程序的输出中,我们还是找出两个蓝牙“低位地址部分”值--A6:56:F7和CB:B8:7A。拿到了“低位地址部分”的值,我们随后就可以继续使用“超牙扫描”(ubertooth-scan),提取“高位地址部分的值。
“超牙扫描”通过超牙接口,使用ubertooth-rx工具,还原了“低位地址部分”的值。但是还得用Linux上那个名为“BlueZ”的libbluetooth库所提供的接口,加上一个传统的Linux加密狗,才能拿到已被确认了“低位地址部分”地址的蓝牙设备的“非必要地址部分”的值。在这种方式中,“超牙扫描”可以通过清除那些“格式没错,但数据有错”(false-positive)的数据包,可以加快还原“非必要地址部分”的速度。
“超牙扫描”程序默认情况下的操作,都使用第一个可用的蓝牙接口,在Linux操作系统上的接口名称是hci0。要指定不同的蓝牙接口,可以通过“-d”参数,并在参数后面跟上你要使用接口的名称,就可以改变为所指定的蓝牙接口。
在这个例子中,“超牙扫描”已经识别出两个“传统蓝牙”设备,并还原了二者的“低位地址部分”和“高位地址部分”的值。等到“蓝牙设备地址”的信息还原以后,“超牙扫描显示出“自适应跳频”(Adaptive Frequency Hopping,AFH)表,该表的作用是避免使用射频干扰(RFinterference)的信道。
有了“低位地址部分”和“高位地址部分”的值,我们就等于还原了蓝牙MAC地址 48位中的 32位,现在还缺的是“非必要地址部分”。即使没有“非必要地址部分”的值,我们仍然可以使用标准蓝牙接口,以及Linux上的Bluez工具与“非可发现的”模式的蓝牙设备进行交互操作了,通过交换操作,又可以还原出“设备名称”,以及“基本接口”信息(basic interfaceinformation)。在实践操作中,任何工具和程序都需要完整的“蓝牙设备地址”,但既然上述操作并不需要“蓝牙设备地址”值中的“非必要地址部分”部分,那么我们在上述操作中,完全可以在需要填写“非必要地址部分”的地方随便用其他的值代替。下面的例子用00:00来代替
服务的枚举
“服务发现协议”是一个由“蓝牙技术联盟”定义的一个蓝牙协议。该协议用于识别或公布某个蓝牙设备上所有可用的服务。“服务发现协议”的创建,主要是满足蓝牙网络中的一些独特需求,比如枚举出远程蓝牙设备上的服务的“功能”(function)、“类型”(class),或者其他属性,例如一些操作功能,还有一些“私人的配置”(profile)。当一个蓝牙服务的开发者在设备上实现蓝牙栈(Bluetoothstack)的时候,他必须挑选出哪些服务可以告诉远端蓝牙设备,并能够通过“服务发现协议”识别出这些服务。而从攻击者角度来说,“服务发现协议”可以允许你识别并确认远端“蓝牙主机”上可能的服务,还可以看到不同的蓝牙“私人配置”文件。而这些配置文件的内容,正是需要连接到服务上所需要的详细信息。
使用 sdptool 工具枚举蓝牙上的所有服务
前面我们已经介绍了几个“主动式发现”的工具。这些工具都可以枚举和显示最基本的“服务发现协议”记录信息。这些工具使用起来很方便,但是在以下几个方面都存在局限性。
这些工具只能用来攻击“可发现的”模式的“蓝牙主机”,对于通过其他方式识别出的“非可发现的”模式下的“蓝牙主机”,则不能显示“服务发现协议”信息。
这些工具对“服务发现协议”记录数据,通常是汇总成主要的“私人配置”格式,在内容显示上,没有连接到该“蓝牙主机”所需的必要细节。
这些工具在枚举服务时可能会忽略那些可以使用但未在目标设备上进行声明的服务而Linux上的sdptool命令则可以让你列举出目标蓝牙设备上的所有服务。这个工具没有图形化界面,并且该工具显示的结果看上去很生硬,看着吃力,但是它却是在蓝牙“服务发现”方面,可用的工具中综合指数最好的一款。在本例中,我们使用sdptool来识别一台名为“MacBook Air”的笔记本电脑,这台电脑运行在 OSX10.9.1“冲浪湾”版上,看看它的“传统蓝牙”适配器上的所有服务信息。
在这个输出中,你可以看到OSX笔记本电脑运行了五个服务:
“A2DP 音频源”服务(A2DPAudio Source)
蓝牙设备使用“高级音频分发配置文件Advanced Audio Distribution Profile,A2DP)生成“流媒体音乐”( stream music)到A2DP的接收器上(比如蓝牙耳机)。
目标设备的AVRCP控制服务(AVRCPTarget)
可以通过“音/视频远程控制协议(Audio/Visual Remote Control Protocol,AVRCP)进行远程控制的蓝牙设备。蓝牙与PDA同步服务(Bluetooth-PDA-Sync)蓝牙设备通过“蓝牙与PDA同步服务和手持设备进行数据交换。
耳机音频网关(Headset Audio Gateway)
蓝牙设备使用“耳机配置文件”(HeadsetProfile,HSP)服务作为网关,在设备和耳机之间,用于接收和发送音频。
组间 ad-hoc无线自组网络服务(Group Ad-hoc Network Service)
蓝牙设备允许远端设备在连接网络的时候,使用“蓝牙网络封装协议”(BluetoothNetworkEncapsulationProtocol, BNEP).
从sdptool命令的输出,可以看到结果中为每个服务的配置文件都提供了额外的配置信息。下面让我们更详细地阅读输出内容中的每一个项。
“服务名称”(Service Name)和“服务描述”(Service Description)字段的内容是由编写服务程序的开发人员提供的。由于开发人员的个人因素,经常会看到多个“蓝牙主机”上,相似的服务,名称却出现很多不一致的现象。无论是“服务名称”,还是“服务描述”,其实都只是一个识别标志,只要用户想要查看某个“可发现的”模式蓝牙设备的信息,那么该用户的操作系统都会通过一个“可用服务列表”(listofavailableservice)的形式把这些服务都列出来,并且大多数用户都可以直接在操作系统中看到它们。
“服务记录句柄’(Service RecHandle)表示的是“服务发现协议”服务记录的句柄(handle)。该句柄与这个服务关联,是一个32位的数字值,并且对于任何一个给定的“蓝牙主机”,该值都是唯一的,但对于不同的“蓝牙主机”,即使是相同的服务,也允许该值不同。通常情况下,每一个蓝牙在编程实现时都会使用一个特定的“服务记录句柄”记录特定的配置文件。例如Apple的OSX系统中蓝牙栈总是使用0x10006作为“A2DP音频源”服务的句柄。随后的“服务类型 ID 列表”(Service ClassIDList)字段,表示用于识别特定的蓝牙配置文件这些文件就是为这个服务的实现而定制的。在这些例子中,“音频源”的配置定制文件主要是通过将一个数字的ID值分配给该配置文件,这个值是由“蓝牙技术联盟”分配的,可以确保数字的唯一性。并且该文件主要用于向“音频接收器”(Audio Simnk)设备发送高质量的“音频流”内容
对于一些配置文件来说,“语言基本属性列表”(LanguageBase Atr List)主要显示在服务实现的过程中,用于人可阅读的语言描述字段。对于我们来说最感兴趣的是codeISO639字段,即ISO签署的639号规范,这个规范是用双字母表示某个国家或地区的语言名称。在本例中,0x656e是小写字母“en”的ASCI码值,在“ISO639”规范中代表“英语”(即English的前两个字母)。通常情况下,在一台主机上所有的服务所使用的语言都是一样,这取决于你当初安装本地操作系统的时候所选的语言类型。如果你想尝试传送一个破解用的工具包,那么你需要指定用一个和远端主机系统上语音包相同的工具包,由此可见,这个字段的信息对于你选择合适的语言包(languagepack)还是很有用的。
在前面的例子中,我们使用“sdptoolbrowse 00:00:CE:E3:96:EB”命令通过“服务发现协议”读取了某个蓝牙设备的服务列表。虽然我们使用的“蓝牙设备地址”并不完整,但通过这个“模糊查询”的方式,对方“很好地”完成了“服务发现协议”的枚举操作,最终得到了完整的可用服务列表。然而,有一些“蓝牙主机”就不会这么友好地回复我们的枚举操作了,当我们如法炮制地向这些“蓝牙主机”发出枚举命令时,它们会尝试阻止向我们回复“服务发现协议”的信息。例如,当我们用同样的命令查询一个Pebble牌蓝牙智能手表的时候,其命令如下:
sdptool browse 00:18:33:E4:F2:80
幸运的是,sdptool命令也设计了一组参数,即使目标蓝牙设备尝试隐藏可用的服务,该命令也能够拿到“服务发现协议”的服务枚举列表。其原理是,虽然该蓝牙设备不在对方要求服务枚举的时候提供服务列表,但是当对方明确提出要读取某一个指定服务的时候,这个蓝牙设备就不得不提供该服务的完整服务信息,否则,其他的蓝牙设备将无法与该蓝牙设备进行正常的通信。现在的问题是,怎么知道对方有哪些服务(因为这本来也就是我们要枚举的目的)?这就涉及一个“公共服务句柄基值”(common service-handle base value)的问题。
如前所述,蓝牙服务中,每一个服务都有一个“服务记录句柄”,所有的“服务记录句柄都是在“公共服务句柄基值”的基础上加一个数字。因此,我们可以基于这个“公共服务句柄基值”做出一个“可能存在服务”的列表值,sdptool命令会按照列表中的值,依次探测目标蓝牙设备上的服务,凡是该蓝牙设备上有的服务中,都如实回复,而该蓝牙设备上没有的服务,则不作回复,这等于间接地读到了所有的服务。要实现该命令,可以带上“records参数后,通过 sdptool命令实现。
sdptool records 00:18:33:E4:F2:80
以下主要是针对低功耗蓝牙模块 (蓝牙4.0)
“低功耗蓝牙”技术概述
“低功耗蓝牙”是蓝牙技术以另外的方式进行演化的过程中的一次颠覆性改变。早期“基本速率蓝牙”1.2设备的设计速率是1Mbps,后来“增强数据速率蓝牙”2.0设备的设计速率达到了 3Mbps。“高速蓝牙”3.0的技术进一步扩展蓝牙协议,通过在Wi-Fi上跑蓝牙,使其达到了蓝牙的高速访问。,甚至被称为“交替使用介质访问层/物理层的蓝牙”(BluetoothAlternate MAC/PHY,AMP)。蓝牙在速度上步步提升,根据这种趋势,似乎最终要与Wi-Fi一决高下了。然而,蓝牙4.0就是我们现在要介绍的“低功耗蓝牙”,其数据传输的速率,突
然“峰回路转”,又回到了 1Mbps 的原点。在摒弃传输速度不停增长的大趋势背景下,“低功耗蓝牙”开辟了在低功耗应用的新机遇。这时,这个“另外的方式”不再试图追求更快的数据传输速率,转而向使用蓝牙进行通信的软硬件开发者提供了一个新的替代品。这个替代品意义重大,同样能产生高的效益,那就是:较低的电池利用率。
“低功耗蓝牙”的设计旨在给开发者和消费者一种能力,也就是通过一个硬币大小的电池提供相当长的一段时间,在这段时间里,在保证效率的前提下,提供设备以轻量级的数据传输。因为“传统蓝牙”已经提供了功率守恒的特性,所以“低功耗蓝牙”的设计中,除了保持这一优点,还为一系列新的应用和设备创建了一种强大的使用机会,使这些应用和设备都能充分利用这一机会。
因此,在蓝牙技术重点的这一次转移过程中,“低功耗蓝牙”与以前版本的蓝牙规范有显著的不同。“低功耗蓝牙”所进行的重大变化不仅体现在底层物理层的操作特性中,而且还体现在上层设备发现和数据交换行为中。我们将在这一节中研究这些特性,在阅读对“低功耗蓝牙”的扫描技术和高层协议操作之前,先介绍“低功耗蓝牙”的工作原理。
物理层的行为
“低功耗蓝牙”仍然使用 2.4GHz频谱,通过“高斯频移键控”(Gaussian Frequency ShifKeying,GFSK)进行调制,这一点和“传统蓝牙”中的“基本速率传统蓝牙”是一样的。此外,“低功耗蓝牙”也使用“跳频扩频”技术来避免干扰。不过,与“传统蓝牙”不一样的是“低功耗蓝牙”的频率跳转非常简单,并且设备在跳频期间占用某一个信道的时间也更长了其实就是在每个信道的停留时间(dweltime)更长了。并且,从设备软硬件的实现角度来看通过“低功耗蓝牙”的跳频方式也是更简单,比如,在“低功耗蓝牙”中,系统共使用了40个信道,其中允许跳频的信道有 37个,还有3个信道专用于发送“通告数据”(advertising)。不过,对于“低功耗蓝牙”跳频行为的深入介绍将安排在下一章。
为了最大限度地节能,“低功耗蓝牙”设备的发射功率限制为10mW。这有限的发射功率使设备达到一个合理的传输距离,那就是10米左右。不过,这时的系统却可以保持在一个较低的整体功率预期之内。
操作模式和连接的建立
“低功耗蓝牙”一共可以从五种远程操作状态中,选择其中之一作为当前的操作状态
待机状态(StandbyState)在待机状态,一个设备不再接收和发送数据包,此时的功耗最小,对设备来说,也是最节能的状态,这时允许设备关掉发送和接收接口。
通告状态(AdvertisingState)一个处于通告状态下的设备将定期在其配置的“通告信道”(advertising channel),以所配置的速率值发送“信标通告”(beaconadvertisements)。该速率的变量名为“BeaconMaxInterval”,一般情况下,该值设置为1秒或2秒。处于“通告状态”的设备一般也被称为“通告者”(advertiser)。
扫描状态(Scanning State)当设备处于扫描状态时,“低功耗蓝牙”设备会监听“通告信道”中有哪些设备处于“通告状态”。处于“扫描状态”的设备一般也称为“扫描者”(scanner)。
初始化状态(Initiating State)一个设备处于“初始化状态”,那么它会监听特定设备所发的通告,一旦有设备发出通告,就会回复这个设备,并在随后建立一个连接。处于“初始化状态”的设备一般也称为“初始化者”(initiator)。
连接状态(Connection State)设备可以从“初始化状态”或“通告状态”转换到“连接状态’,完成这一操作的设备,既可以是“主设备”也可以是“从设备”,两个角色都允许。
“主设备模式”(master mode)“主设备模式”下的设备初始化一个到特定目标设备的连接,又称为“发起方模式”(initiator mode)。
“从设备模式”(slave mode)“从设备模式”下的设备接收来自“主设备”的查询连接,并将其应用于一个需要认证的阶段,以便完成连接的进程
这个专为设备操作模式而定义的结构,被灵活地借用到产品设计上,以便降低复杂性。例如,对于一个设备,如果只扫描处于“通告状态”的“低功耗蓝牙”设备是不是存在,那么这个设备就完全没有必要具备发射功能,这样做可以降低电池消耗量,最大程度减少设备成本。
要在两个“低功耗蓝牙”设备之间创建一个连接,“扫描状态”的设备会在“通告信道”里察看信标通告,然后决定要连接的目标设备。当接收设备选择好,“扫描状态”的设备就发送连接请求。在这一点上,回复的设备就会协商连接参数并同“主设备”建立一个连接在连接建立之前,这个回复的设备的身份还不是“从设备模式”
数据帧的配置
“低功耗蓝牙”使用有限的“有效载荷”(payload)的大小作为其整体节能策略的一部分,该“有效载荷”的长度为2~39字节。基本的“低功耗蓝牙”数据帧是由“前导码”(preamble)、“访问码”( access code)、“有效载荷”和“循环冗余校验”(Cyclical RedundancyCheck,CRC)校验码组成。其中的“访问码”有时称为“访问地址”(access address)。整个结构如下图所示。
“低功耗蓝牙”数据包中,“有效载荷”长度的变化取决于“访问地址”的值和接收设备的状态。例如,一个数据包如果遵循“逻辑链路控制及适配协议”,那么它的内容就是一个长度是16位的头部,后面跟着变长的“有效载荷数据”(payload data),然后是一个可选的“信息完整性检査码”(Message IntegrityCheck,MIC)。这时,这些数据头部的各个字段意义分别如下:
逻辑链路ID(Logical Link Identifier,LLID)字段“逻辑链路ID”进一步说明了这个“有效载荷”数据的作用。比如0x01表示该数据包是一个帧的延续内容,或者这是一个空的“逻辑链路控制及适配协议”数据包;0x02表示一个“逻辑链路控制及适配协议”数据包的开始;0x03表示这是一个“逻辑链路控制”数据包的内容。
下一个期望的序列号(NextExpected Sequence Number,NESN)字段“下一个期望的序列号”是用于对接收到的数据包进行确认。
序列号(SequenceNumber,SN)字段“序列号”主要用于发送数据包时,接收方确认该值是针对于“下一个期望的序列号”的下一个数据包。
更多数据(More Data,MD)字段“更多数据”主要是为了说明发送方是否还有要发送给接收者的数据。
保留字段(Reserved)未使用的位,虽然目前没有使用,但建议都填成“0”。目前接收者会忽略该位。跟在“长度”字段后面也有个“保留”字段,意义与此相同。
长度字段(Length)“长度”字段表示的是包含“信息完整性检查码”在内的“有效载荷数据”的长度,以字节为单位的。
同样,一个“通告”数据包的有效载荷使用的也是一个16位的头部,后面跟的是通告的有效载荷数据,其完整的描述如下:
类型字段(Type)有效载荷内容的类型,通过这一字段确定该数据包是一个“通告”数据包,也可以是一个扫描请求或响应,或者是一个连接请求。“类型”字段中,大部分可能的值都会保留,以供将来使用。其中的“通告”数据包包括“有向通告”( directed advertisement)、“广播通告”(broadcast advertisements)、“非连接通告(nonconnectable advertisement)或“通告征集扫描”(advertisement solicitation scan)。
发送地址字段(TXaddress)这个1位字段表示如果发送方将正在使用的生成的MAC地址用作私用,那该位就为“1”,否则如果MAC地址可以被无线接口使用则该位就为“0”
接收地址字段(RXaddress)这个1位字段意义同“发送地址”字段意义一样,但是应用于接收地址上。
有效载荷长度字段(payloadlength)这个6位字段指的是“有效载荷数据”(payloaddata)的长度(不包括头部内容的长度)。值得注意的是,尽管这个值在填写的时候最大可以填到63个字节(2-1),但实际有效的值是0~37。
保留字段(Reserved)未使用的位。在“通告信道”头部,这个位是保留的,并且建议目前都填成“0”。注意,共有两个“保留”字段,一个在“类型”字段后面,另一个在头部的最末端,二者意义相同。
这种数据帧的格式更详细地显示如下所示。
“蓝牙规范”4.0中,描述了“逻辑链路控制及适配协议”有效载荷数据的格式,包括所有定义的数据帧类型的格式。就像前面各版“蓝牙规范”一样,“逻辑链路控制及适配协议层句柄的数据被编码到顶层协议中。但与前面各版“蓝牙规范”不同的是,“低功耗蓝牙”中“逻辑链路控制及适配协议”并不提供“重传”(retransmission)、“碎片整理”(fagmentation)'数据重组”(reassembly)等功能,这样做的目的是为了在一个简单的协议栈中实现最基本的功能。“逻辑链路控制及适配协议”规范在蓝牙4.1设备中又得到了进一步扩展,新加了对带有“流量控制”(flow control)的“面向连接信道”(connection-oriented channel)的支持.
蓝牙支持协议规范
就像以前版本的蓝牙规范(如7.1.3节提到的是“传统蓝牙”的规范,这里是“低功耗蓝牙”的规范),“低功耗蓝牙”设备所提供的设备配置文件服务具有良好的结构,简化了蓝牙栈的实现。“逻辑链路控制及适配协议”的服务作为底层的基础,介于链路层规范和上层协议之间。
“属性协议”(Attribute Protocol,ATT)通过“逻辑链路控制及适配协议”的信道,用于传递少量数据。包括设备在功能形成时的数据交换。
“通用属性协议”(Generic Attribute Protocol,GATT)在“属性协议”的顶部,“通用属性协议”提供了一个用于对“属性服务器”(attributeserver)和“属性客户端”(attribute client)实现“服务发现”、读取属性、写人属性的操作。
“安全管理协议”(Security Manager Protocol,SMP)用于在一个连接的“逻辑链路控制及适配协议”信道上,交换设备之间与安全相关的数据。
“通用访问配置文件”(Generic Access Profile,GAP)代表了“低功耗蓝牙”设备的基本功能,包括完成设备发现,启动和完成连接,完成服务发现的能力。
“低功耗蓝牙”协议的功能使用了基本的数据结构定义。这种结构定义可以适应众多厂商使用蓝牙技术的要求。比如,一个供应商实现了一个“低功耗蓝牙耐体温监测系统”,那么他就可以使用“通用属性协议”的特性定义一组数据,然后发送到接收设备上,该系统可以唯一地识别出这些数据,各数据之间可以相互区分开来。这个功能已经被用于蓝牙广告产品“Apple iBeacon”中了,在该产品中,Apple公司使用了针对iBeacon的特定属性定义这个协议。这使得Apple公司可以创建一个与其他厂商的竞争或合作协议。
“低功耗蓝牙”的安全控制
作为“通用访问配置文件”的这些属性,“低功耗蓝牙”提供了新的功能,用于通过物理层的无线接口(airinterface)或者是高层的“属性协议",保护机密性和数据完整性。产品设计师可以选择实现那些安全的功能,因为这些功能最适合他们的产品需求组合:没加密没认证、有认证但没有加密、既有加密也有认证。此外,“低功耗蓝牙”实现了私有人增强功能,对黑客通过拿到的“蓝牙设备地址”破解用户本地数据的攻击,具有减轻此类攻击的能力。
1.加密和信息认证
“低功耗蓝牙”使用“高级加密标准-计数模式和密码块链消息认证码协议(AES-CounterMode Cipher Block Chaining-Message Authentication Code Protocol,AES-CCMP),采用128位密钥进行加密和完整性保护。这种加密支持力度类似于IEEE802.11规范中的WPA2,所以该认证的全称是“基于'高级加密标准-计数模式和密码块链消息认证码协议’的'Wi-F保护访问下的预共享密钥版本2’认证”,简称WPA2AES-CCMP。
使用加密“和”/“或”认证的决定,是由软硬件开发人员和“低功耗蓝牙”安全模式共同选择的。
(1)安全模式1
“低功耗蓝牙”的“安全模式1”运行在无线的物理层接口(air-interface layer),提供三选一的安全级别:
安全模式1的级别1不加密不认证。
安全模式1的级别2通过未经认证的配对后衍生出的一个密钥;在密钥衍生之后
设备就加密数据。
安全模式1的级别3 通过经验认的配对后衍生出的一个密钥:跟在加密数据的后面安全模式1所使用的加密,依靠产品设计师选择实现的级别。但是该模式并没有使用消息真实性的检查,使其很容易受到“中间人的畸形数据”(malformed data man-in-the-middle)攻击和“重播”攻击(replay attack)。
(2)安全模式 2
安全模式2运行在“属性协议”层,主要提供对上层的支持,用于一个或两个安全级别提供完整性保护上的“数据签名”(data signing)。
安全模式2的级别1通过未经认证的配对后衍生出的一个密钥;在密钥衍生之后数据包的“有效载荷数据”是加密的,并且有效地使用了一个“消息认证码"(MessageAuthentication Code, MAC)
安全模式2的级别2同“安全模式2的级别1”一样,不同的是,设备必须是通过认证的配对。
在“安全模式2”的任一级别上操作,在信息的接收方会使用一个“消息认证码”验证数据的完整性。“消息认证码”的使用减轻了“中间人的畸形数据”篡改攻击的威胁,但这并不能减轻“重播”攻击。幸运的是,蓝牙规范也要求使用重播计数器,而在“安全模式2数据帧”下,重播计数器作为“消息认证码”MAC计算的一部分,如下所示。
“签名计数器”(signature counter)字段从零开始,每发送一个数据包,“签名计数器”都会自动增加1。接收设备验证数据包中的这个签名,是用实测的有效载荷内容计算“消息认证码”,然后再用计算出来的这个“消息认证码”和观察到的“消息认证码”作比较,如果这两个值是匹配的,那么接收方检查“签名计数器”的值,来保证数据以前没有看到过,以避免“重播”式攻击。如果“签名计数器”的值大于最后观察到的“签名计数器”的值,那么这个数据包的处理和接收方就会记录观察到的“签名计数器”,以便以后验证使用。
2.私有特征
“低功耗蓝牙”规范引人很多只有这个版本才具有的“私有特征”(Privacy Feotur),这样做的目的就是为了使攻击者在一段时间内破解一个蓝牙设备变得更困难。比如,在以前的版本中,对于任意一个蓝牙设备,它在所有的连接中都会使用相同的“蓝牙设备地址”,这个地址不妨称为“静态地址”,而在“低功耗蓝牙”规范中,蓝牙设备使用一个生成的地址取代以前定义好并分配的“静态地址”,并持续一段时间。“私有特征”共支持两种生成的地址:
可以解析的“私有地址”(resolvable privacyaddress)设备可以选择生成一个“私有地址”,这个地址可以反推出“静态地址”,与该设备共享一个加密的密钥。要解析这个私有地址,允许客户端设备对每一个连接都产生一个新的“私有地址”但是在与通信的另一个蓝牙节点之间,却是通过“静态地址”维持认证关系。
不可解析的“私有地址”(non-resolvable privacy adress)不可解析的“私有地址”的使用情况是:在蓝牙设备建立连接的时候,连接的发送方并不想把“静态地址”透露给连接的接受方。因此不可解析的“私有地址”无法反推出“静态地址”
扫描和侦听
对于“低功耗蓝牙”功能的设备,你可以通过扫描和举找到这些“低能耗蓝牙”,并将其列为目标设备。目前,有许多能够发现和列举“低能量蓝牙”设备的工具还不太稳定也不太可靠,不过,随着“低功耗蓝牙”设备越来越多,这些工具可能会变得越来越稳定功能越来越丰富。
再需要那些参数,而只需要使用“lescan”参数,就可以扫描到这些低功耗的蓝牙设备。在写本书的时候,这个hcitool工具有个bug,即当你通过使用“lescan”参数使用hcitool命令时,经常会返回一个错误,不用管这些错误,再次重新运行这个命令,有时甚至需要多次重新运行这个命令,才能完成正常的低功耗设备扫描。如下面的例子所示。
hcitool lescan
与直接使用“hcitoolscan”命令不同,当带上“lescan”参数以后,那么hcitool工具就在扫描和识别蓝牙设备,并对每一个“可发现的”蓝牙设备的扫描结果重复显示好几次。如果要将 hcitool工具输出的内容重定向到文件中,并且每隔一分钟或几分钟,就中断一下扫描过程,那么就可以通过该文件查看扫描结果,不过,鉴于这个文件里有很多重复的扫描行所以可以通过排序功能,从扫描结果中对每一种结果中各取一行,最终生成一个没有重复行的扫描结果,如下所示:
在这个输出结果中可以看到有些设备的重复信息,比如说,“蓝牙设备地址”为90:59:AF:28:17:A2的设备共出现了两次,第一次显示设备名称为“活动力监控器”(ActivityMonitor),第二次显示的则是一个“(未知)设备”(unknown)。对于这样的扫描结果,你可以通过“可发现的”设备,借助于“蓝牙设备地址”进行服务枚举的扫描,以便获得更详细更准确的内容。
在hcitool工具,通过“lescan”参数的输出数据中,那个“蓝牙设备地址”为90:59:AF:28:17:A2的设备是一个“iHealth 牌活动力监控器”(iHealthActivity Monitor),主要用于记录佩戴者所走的“步数”、“卡路里的消耗值”(calories burned)、“所走的距离”( distance traveled)和“睡眠的程度”( sleep pattern)。本设备会不停地在“通告信道”中“通告”(advertise)它的“蓝牙设备地址”,即使和某一个目标设备配对成功,该操作也不会停止,这样做显然使该设备很容易被识别和扫描。
对于 Limux操作系统最新版本的Bluez 工具包中,包含了一个名为gatttool的工具软件,该软件可以列举一个“低功耗蓝牙”设备上的服务和个性化特点。这款gatttool工具可以在命令行中使用,也可以以交互的模式查询目标设备上的主要服务,其命令行的运行效果如下所示:
对于gattool程序来说,命令行版本的输出和交互式版本的输出,其结果和格式都是相同的。两者都可以显示出这个蓝牙设备上四个主要的服务。其中的服务信息,在显示的时候是以“通用唯一标识符”格式显示的。“通用唯一标识符”格式所表示的是由标准的16位“通用属性协议”服务码组成的,该服务器又是通过“蓝牙技术联盟”定义的。这16位“通用属性协议”服务码定义如下所示。这些服务码中,每一位所代表的具体意义,可以通过“蓝牙技术联盟”的“开发者门户网站”(Developer Portalsite)进行查询。“蓝牙技术联盟”开发者门户网站的网页地址是:https://developer.bluetooth.org/gatt/services/Pages/ServicesHome.aspx。
除了“主要服务”信息,还可以识别目标设备的“服务特性”信息(service characteristic)命令跟上面的命令一样,不过要获取服务特性,就不能使用“-primary”参数了,因为这个参数是读取服务信息,而要将参数换成“--characteristics”,其格式和效果如下所示:
通用唯一标识符”信息是从上面带有“--characteristics”参数的“特性扫描”返回的。显示的格式和前面“主要服务”信息格式一样,同样是以16位的值作为“服务分配码”。这个特性模式下的“服务分配码”和“服务描述”显示,为了格式的紧凑、节省显示的空间,其中“通用唯一标识符”这一列已删除掉了。
有了“主要服务”信息,你可以继续评估目标设备,通过“参数,可以拿--char-read "到与每一个“通用唯一标识符”关联的信息。其显示效果如下所示:
在这个例子中,我们从“通用唯一标识符”中“服务分配码”为0x2a00的“服务描述得知这个“服务分配码”的意义是:这是一个“设备名称”(Device Name),然后我们就可以从这个“服务分配码”中读信息了。结果读到的是一串十六进制的数字,这些十六字节的数字代表的是设备名的 ASCH码,我们可以通过 Python进行解码,可以看到解码后的内容是'Activity Monitor”。当我们评估目标设备时,我们应该测试所有返回的“通用唯一标识符”这样可以识别潜在的信息泄露威胁。对于这个iealth设备,一些“通用唯一标识符”返回基本信息,反之就返回其他的错误信息(就像目标设备所需要的认证状态可以获取一些敏感信息),如下所示:
关于“iHealth牌活动力监视器”的一个有趣的属性是,这个在特性列表中的设备使用个保留的“通用唯一标识符”(“服务分配码”为 0x2a30)。从这个“通用唯一标识符”返回的数据是一个ASCII字符串,内容是“com.jiuan.AMV10”。这个域名“jiuan.com”注册于Andon组织,这是一个专业从事共享健康信息的设备开发组织的OEM版。很显然,是该公司开发了这个“iHealth牌活动力监视器”