7.3 侦查

在蓝牙攻击的侦查(reconnaissance)阶段,我们可以借助“目视检查”(visual inspection)和“组合发现”(hybrid discovery),通过“主动式发现”(active discovery)和“被动式发现”(passive discovery)方式,在附近区域,检查并确定“要攻击的”蓝牙设备。这里的“发现”进程就是确定存在的蓝牙设备,以及寻找到每个设备的48位“蓝牙设备地址”。

一旦你发现了一个蓝牙设备,就可以开始枚举这个设备上所使用的服务,确认可能的攻击目标。还可以采集远端设备的特征值(fingerprint),使用蓝牙嗅探工具(sniffing tool)捕获“微微网”中的数据,进而获得访问机会。下面,我们就详细讲解这些步骤。

7.3.1 主动式设备扫描

“蓝牙侦查”扫描的第一步只是简单地查询功率覆盖范围内各设备的信息。在蓝牙规范中,这个被称为“询呼扫描”(inquiry scanning),其过程是设备在一系列频率上都主动发送查询扫描信息,然后监听有没有回应信息。如果在上面这个功率覆盖范围内,有蓝牙设备处在“可发现的”模式,它会对“询呼扫描”信息进行“询呼应答”(inquiry response),在“询呼应答”中,包含它的“蓝牙设备地址”、时钟信息(也称为“设备时钟”,或简写成CLK)、设备种类信息。设备种类信息包括电话号码、可佩带设备、玩具、计算机等。

在不同的平台上有很多种主动式“设备发现”的工具,其中有简单的命令行工具,也有复杂的图形界面工具。下面我们会讲解不同平台上的一些工具,以便了解在不同的平台上有哪些工具可供选择。

在Windows上使用BluetoothView进行设备发现

BluetoothView是一款Windows操作系统下,免费的闭源代码(closed-source)的主动式“发现扫描”工具,程序由NirSoft公司才华横溢的Nir Sofer编写,软件的下载地址是:http://www.nirsoft.net/utils/bluetooth_viewer.html 。BluetoothView软件提供一个简单的界面,可以自动检测可用的蓝牙适配器,并扫描处于“可发现的”模式的蓝牙设备,扫描结果是以表格显示的,如图7-4所示。

图7-4 蓝牙设备扫描结果

BluetoothView软件在查询到蓝牙设备后,会确定设备的“友好名称”(device-friendly name)和“蓝牙设备地址”,以及设备的“类型”(device type)和“发现时间戳”信息,如第一次看到的时间和最后一次看到的时间。双击一个已被发现的蓝牙节点,BluetoothView程序将显示该节点的详细信息,如图7-5所示。一个简单的HTML报告也会同时生成,单击“查看(View)→HTML报告-所有的项(HTML Report-All Items)”菜单项,程序会弹出该节点属性对话框,其显示效果如图7-6所示。

图7-5 HTML报告-所有的项属性对话框

图7-6 BluetoothView软件的HTML扫描结果报告

虽然BluetoothView软件只是一款简单且方便的软件工具,但该工具既不能显示目标蓝牙设备上“发现服务”(discoverable service)的列表,也不能显示设备的信号强度。所以要想获得蓝牙设备上更多的详细内容,我们还需要转向其他平台上的工具试试看。

Android上的蓝牙发现工具

在Windows操作系统上,使用BluetoothView工具进行蓝牙扫描是件简单而方便的事,因为你可以在外置蓝牙USB加密狗上,方便地通过不同的天线选择而获得不同的信号增益。然而,如前所述,在Windows中,针对蓝牙发现方面的“应用程序接口”(Application Programming Interface,API)没有提供读取发现的设备“信号强度”(signal strength)信息的调用函数。而对于“信号强度”的信息,又是我们在追踪对方时测算相对距离和估计对方节点位置的重要依据。

为了获得蓝牙设备的“信号强度”信息,以及与其他蓝牙节点的详细信息,在“谷歌玩家市场”(Google Play marketplace)上,有一款可用的Android工具可以做到这一点。这个工具不需要“访问Android平台”的权限,也就是说,在Android平台上,要正常使用这个软件,既不需要“root权限”,也不需要以root用户登录。程序只需要有访问蓝牙设备“扫描”(scanning)和“访问”(access)的标准权限即可。从开发的角度来看,就是需要“android.permission.BLUETOOTH”权限和“android.permission.BLUETOOTH_ADMIN”权限。虽然目前该工具不支持外置式蓝牙适配器,但是就目前所提供的功能来说,Android系统上的这些工具已经获得了Windows操作系统所不具备的优势。

“Bluetooth Finder”是一款由JoséLuis Costumero设计的,用于蓝牙发现的简单扫描工具,可以通过“谷歌玩家市场”下载。在启动该应用程序之后,单击“当前未扫描状态”(Scanning Off)按钮,“Bluetooth Finder”就开始扫描,此时“当前未扫描状态”按钮也自动变成了“当前正在扫描状态”(Scanning On)按钮。在扫描过程中,将搜索附近蓝牙设备,并将发现的蓝牙设备的一些参数显示出来,主要有“蓝牙设备地址”、友好名称、频繁更新的信号强度信息(单位是dBm),某次扫描的实例如图7-7所示。图中的信号强度值越高,表明被扫描的那个蓝牙设备离我们越接近,反之,则表示离我们越远。由于该值是负值,所以体现在数字上,信号强度越高,值越大,越接近于数字0,在图上表现出来的就是那个“进度条”中填充的部分越多。

图7-7 “蓝牙寻找器”扫描结果

“Bluetooth Finder”的优势很明显,特别是通过信号强度,可以大致估算对方蓝牙设备和自己的设备之间的距离,但是该软件并没有提供这样一种接口,即将单个蓝牙设备的扫描结果集中汇总,然后通过对该蓝牙设备的综合实时信息,对其实施跟踪或追踪。不过,通过上面的分析可以看出,一个变通的办法就是只要我们一直朝着“信号强度”增大的方向走,最终总能找到一个“可发现的”蓝牙设备。不幸的是,这款“Bluetooth Finder”软件,并不试图枚举发现蓝牙设备上的所有服务。

计算信号发送者和接收者之间的距离

“信号强度”的信息单位是dBm,通过“信号强度”的数值,可以大约估算出蓝牙信号的“发送者”(transmitter)和蓝牙信号的“接收者”(receiver)之间的距离。假设蓝牙信号的“发送者”是一个“第2级”设备(Class 2 device),其发射功率是2.5 mW,那么你可以参考“接收信号强度指示”(Received Signal Strength Indication,RSSI)所给出的参数,其中:距离为1米时,信号强度为-55 dBm,波段为大约2.4 GHz时的“传播常量”(propagation constant)值为3,其计算发送距离中,单位为英尺 [1] (feet),也就是公式中的“d”,其公式如下。

d=10(-55-rssi)/(10×3) ×3.2808

使用编程语言Python [2] ,我们可以很容易地计算出距离。只要在蓝牙扫描过程中,将看到的“信号强度”值代替上面式子中的参数rssi即可。“传播常量”可以在2和4之间进行调整,以便适应不同的射频环境。增加“传播常量”的值意味着蓝牙信号在传播中,遇到障碍物后射频信号衰减得很多;减少“传播常量”的值意味着蓝牙信号在传播中,遇到障碍物很少,因而射频信号衰减得很少。

这种技术不需要考虑许多射频传播的因素,而只是作为一个估算值。如果你需要估算一个“第1级”发射功率的前提下,“发送者”和“接收者”之间的距离,那么“发送者”测试“信号强度”时,在距离为1米的地方,可以使用平均的“接收信号强度指示”标准作为公式中参数rssi的值。

作为“Bluetooth Finder”工具的替代品,btCrawler在“谷歌玩家市场”上的售价是0.99美元,主要用于标识周边蓝牙设备的应用,可以扫描到的值主要是“设备类型”、商备开发商(这个值主要是从“蓝牙设备地址”中分析“组织唯一标示符”的值,然后再进行匹配分析)、以及“接收信号强度指示”信息,一次实战扫描结果如图7-8所示。

在btCrawler软件中,选择一个发现了的节点后,还有一个显示的选项,可以列举出这个蓝牙设备上发布的服务,这个功能显然是“Bluetooth Finder”软件所不具备的。对于一个在Mac OS X 10.9.1“冲浪湾” [3] 版上,“服务发现”输出界面的显示如图7-9所示。

在扫描蓝牙设备的过程中,btCrawler在本地数据库中保存了扫描的结果。这个数据库中的数据可以导出为csv格式的文件到系统的SD卡上。在Android设备上,没有物理SD卡插槽,这时可以将文件导出到安卓的“虚拟SD卡”(virtual Secure Digital Memory card)。要完成这个操作,只要选择程序的“菜单(Menu)→数据库导出(Export Database)”菜单命令即可。由于csv格式是以逗号隔开的纯文本格式,所以文件格式非常小,并且可以在任何文本编辑器中查看和修改。

无论是“Bluetooth Finder”,还是btCrawler,都是“蓝牙发现”类工具中很有用的应用程序,这对一般用户来说,应该是够用了。但这两个程序在发现设备后,所显示的设备信号中都缺乏一些细节描述,对于黑客来说,似乎还缺少一些信息。要想获得蓝牙设备上,有关蓝牙发现和服务列举方面更详细的信息,你就需要使用Linux操作系统上基于命令行的工具了。

图7-8 btCrawler蓝牙节点的“服务发现”实例

图7-9 btCrawler“服务发现”的运行实例

Linux上使用hcitool进行设备发现

Linux的标准命令hcitool可以用来进行“蓝牙发现”和基本的“服务枚举”。与前面各工具相比,该命令具有一定的智能化,即当在扫描的时候,hcitool程序会缓存所有已扫描好的蓝牙设备的相关信息,这意味着,如果有某个蓝牙设备离开了自己信号覆盖的有效范围后,程序仍然能够潜在地告诉你。当然,如果你对这个功能没有兴趣,你只想关注当前自己信号覆盖以内的蓝牙节点,也就是说强制hcitool程序不要对结果进行缓存,那么可以通过“--flush”参数进行指定。另外,默认情况下,hcitool程序只会显示扫描到蓝牙设备的“蓝牙设备地址”和“设备名称”两项信息,如果你想获得更详细的信息,可以通过加上“--all”参数来实现。

提示

如果不以root用户权限运行hcitool程序进行扫描,那么扫描结果中,对于扫描到的蓝牙设备信息,在明显的时候,只显示有限的信息。

对于每一个蓝牙设备,在接到查询命令时,都会做出回复,而hcitool程序正是从这些回复中提取设备的信息。这些信息可以包含“蓝牙设备地址”、设备名称和设备类型、无线生产商(radio manufacturer)、“连接管理器协议”的版本号,以及详细的枚举信息。

注意

对于黑客来说,“连接管理器协议”版本号非常重要,因为通过版本号,黑客可以知道这个版本的蓝牙设备支持哪种安全特性(言下之意,还存在哪些漏洞)。在上方的示例中,“连接管理器协议”的版本号是2.1。在蓝牙规范中,在2.1版本之前都没有“安全简化配对”机制,而在2.1版本时,引入了这个机制,所以这暗示了我们,这个版本是支持“安全简化配对”机制的,支持这一版本之前的各破解工具,现在不一定能继续使用。

Linux上使用BTScanner进行设备发现

虽然使用hcitool命令行工具进行快速的蓝牙设备扫描是很方便的,但是这个命令没有持续扫描的能力,这个命令只在发现有蓝牙设备在自己功率覆盖范围之内时更新一下显示结果。要解决这个不足,让对于这种类型的扫描一直处于持续进行中的显示状态,那么Linux上的BTScanner工具则是一个更好的选择,这个工具在持续扫描蓝牙设备的同时,提供一种简单的、基于文本的接口,将每个发现的蓝牙设备,都以一行内容的效果显示出来。虽然只用一行信息显示,但并不意味着这个工具显示的内容少,可以这么说,除了配对(pairing)信息之外,BTScanner工具会尝试收集尽可能多的信息。如果用户选择显示某个指定的蓝牙设备时,这个工具会提供一个与这个蓝牙设备相关的详细信息视图。

BTScanner软件的下载地址是http://www.pentest.co.uk ,同样也可以使用apt-get命令通过Unbuntu安装包管理系统,或者是Synaptic安装包管理器来安装它,安装的步骤和方法同Linux下其他同类安装包的安装过程类似。

要使用BTScanner程序,首先打开一个Linux上的终端(terminal)窗口,然后以root权限运行命令btscaner,所以其命令的格式为“sudo btscanner”。运行后的BTScanner程序会开启一个浅灰色的背景,并在屏幕底部的“状态栏”(status window)中显示“热键”(hotkey)列表。用户可以通过这些“热键”来控制BTScanner开始扫描、停止扫描、将当前的结果保存到日志文件中,或是针对某个蓝牙设备开始某种攻击。表7-2列举了可用的“热键”以及该按键所对应的作用。

表7-2 BTScanner软件的热键选项

要开始扫描周边的蓝牙设备,按下“i”键。BTScanner程序在“状态栏”上显示“开始询呼扫描”的状态行,然后在主窗口中显示被发现的蓝牙设备信息,这些信息包括某个蓝牙设备被发现时的“时间戳”(timestamp),设备的“蓝牙设备地址”,蓝牙设备的“系统时钟信息”,“设备类型”,“友好名称”等信息,如图7-10所示。

图7-10 扫描发现的蓝牙设备信息

提示

如果你的扫描设备上存在不止一个蓝牙接口的话,BTScanner程序会同时使用所有的蓝牙接口,一起进行扫描。这项特性使得BTScanner工具在发现和枚举设备的速度上快于那些只能使用单个蓝牙接口的工具。

BTScanner中存在的bug

bug像瘟疫一样遍布在许多新的程序中,许多黑客工具也都难于幸免,BTScanner程序也不例外。现在的BTScanner程序,其原作者已经多年没有对它进行维护升级了,这导致程序中存在的bug至今仍然存在着。

消失的设备  在BTScanner程序的显示中,设备列表中正在显示的蓝牙设备,会突然莫名其妙地消失。在遇到这种问题时,要想找回消失的蓝牙设备,一个变通方案是:如果设备从显示列表中突然消失,则按小写字母键“o”打开“选择一种排序方法”(Enter A Sort Method)对话框,然后随便按什么排序,以便改变当前的显示顺序,然后再按小写字母键“f”和“回车”键回到上一级显示中,这时消失的设备就会因为重新排序而出现。

无法启动BTScanner程序  在“终端”窗口中,运行BTScanner程序需要终端窗口至少有80个字符的显示宽度 [4] 。如果你尝试在小于这个宽度的终端窗口中打开BTScanner程序运行的话,你会看见“状态栏”显示“已完成读取OUI数据库”(Finished reading the OUI database)的状态信息提示,然会返回到Shell外壳命令行提示状态。所以,在开启BTScanner程序之前,首先确认你的终端窗口至少有80个字符的宽度(最好有24个字符的高度)或者更大。

调整尺寸时会崩溃  如果你在BTScanner程序运行的时候,尝试调整“终端”显示窗口的大小,那么BTScanner程序就会崩溃,并提示“分段的‘段地址’访问错误”(Segmentation fault)。避免这种情况,需要在开启BTScanner之前,先确认你要使用的窗口大小是否合适,如果不合适,马上调整,直到“终端”窗口的尺寸合适了,再运行程序,否则,在退出BTScanner程序之前,不要尝试调整“终端”窗口的大小。

BTScanner程序最大的特征之一,是程序为每个被发现的蓝牙设备所生成的日志信息。当你运行BTScanner程序时,它会在用户的主目录下创建一个名为bts的目录。在这个目录中,BTScanner程序会根据设备的“蓝牙设备地址”,为每一个被发现的节点再各自创建一个目录,不过,因为冒号不适合做文件名和目录名,所以BTScanner程序会把“蓝牙设备地址”中冒号分隔符替换为下划线分隔符(比如00_02_EE_6E_72_D3)。

提示

BTScanner程序创建的所有目录和日志数据都只有root用户才能够访问,所以如果在使用cd命令转换到bts目录时遇到了“禁止访问”(Permission denied)的提示信息,则需要运行“sudo su”命令切换到root权限才行。

在每个设备目录中,BTScanner程序都会创建两个文件:“时间戳文件”(timestamps file)和“信息文件”(info file)。“时间戳文件”中包括BTScanner每次收到蓝牙设备回应的时间。在跟踪移动蓝牙设备的时候这个记录会非常有用,可以根据时间来判断,在某一段时间里,这个蓝牙设备是否在或者不在自己的功率覆盖范围之内。

“信息文件”包括详细的设备信息,包括“蓝牙设备地址”、“设备制造商名称”、“蓝牙设备地址”所关联的“供应商名称”、“组织唯一标示符”编码,“MAC地址前缀”,以及一份详细的设备所有服务列表。

除了BTScanner程序存在一些bug(详见前面“BTScanner中存在的bug”的内容)之外,BTScanner程序的日志存储和分析功能对于确认“可发现的”蓝牙设备是非常有用的。遗憾的是,BTScanner程序的作者不再进行升级开发这个程序了,因此本程序,将来恐怕也难看到任何bug的解决方案了。

iPhone平台上的发现工具怎么样

还有一些工具可以用来进行蓝牙设备的扫描工作,但在实战中我们不推荐使用,因为这些工具通常易用性很差,进行扫描的操作十分复杂,或者程序缺少扫描工作所需要的必要功能,也没有什么特色。举例来说,“越狱版”(jailbroken)的iPhone可以使用Cydia程序来安装SweetTooth蓝牙扫描程序。在我们编写本书的时候,SweetTooth也还只能显示“可发现的”蓝牙设备的设备名称,还不能读取到“蓝牙设备地址”、“设备类型”和其他相关信息。

另外,比较悲剧的是,Apple公司限制开发者使用“本地iPhone蓝牙功能”(native iPhone Bluetooth functionality)来进行蓝牙设备的扫描操作,因此iPhone用户除了上述软件,并且是在越狱设备上可以使用外,其他就再没有可用的“蓝牙发现”工具了。

主动扫描技术的防御技术

针对蓝牙设备,主动式扫描工具要求蓝牙设备处在“可发现的”模式下才可以识别出它们,这就意味着蓝牙设备主动扫描是一种机会主义的攻击方式。原因很简单,攻击者只是识别出那些应答了“询呼请求”的那些蓝牙设备,所以攻击者也很容易地就能够确认它们,对于不做应答的蓝牙设备,攻击者也无能为力。同时,防御此类攻击的方法非常直接:不要让你的蓝牙设备处于“可发现的”模式。

这个建议听起来很容易,但是要做到,有些时候却是很困难的,这里的困难不是指设备的协议不容易通过程序实现,而是因为“牵一发而动全身”,很多蓝牙相关的通信协议本身就需要以这个功能作为前提。举例来说,在初始“配对交换”(pairing exchange)过程中,许多蓝牙设备要求另一个蓝牙设备处于“可发现的”的状态,如果对方没有处于“可发现的”状态,则无法继续,而一旦对方处于“可发现的”状态,则又为攻击者创建一个新的窗口,然后借助于网络提供的机会实施攻击。现实中,另有一些蓝牙设备也容易受到黑客的攻击,这些蓝牙设备的实现方式粗制滥造,所以在使用无线接口与其他蓝牙设备连接的时候,每次都要求用户进行发现和选择,用户只要稍不注意,就是使该蓝牙设备处于“可发现的”模式中。

前面我们列举的这些工具的共同特点是:要扫描的目标蓝牙设备必须处于“可发现的”模式下,扫描程序才能够识别和确认。同时,我们也提到,要想蓝牙设备安全,最好的措施是在“配对交换”结束后,终端用户将他们蓝牙设备调整为“非可发现的”模式,从而防止“主动式扫描”工具发现它们,这样等于又增加了一层安全。现在,我们介绍在对方蓝牙设备处于“非可发现的”模式下可以使用什么技巧来识别这些蓝牙设备。

7.3.2 被动式设备扫描

在蓝牙规范中,并不要求两个需要通信的蓝牙设备之间通过“询呼扫描”(inquiry scan)进行数据的交换。因此,如果你通过一些第三方的外部技术,获得了某个蓝牙设备的地址,比如你是通过阅读文档找到的。那么对方的蓝牙设备,区分不出你现在所发起的连接,是在获得“蓝牙设备地址”后是直接发起的,还是通过主动式的扫描后,从扫描中拿到“蓝牙设备地址”后发起的。无论是哪一种,都会涉及“蓝牙设备地址”,所以这部分的介绍,全都是被动式捕获“蓝牙设备地址”的技术。

目视检查

有时候,要确认一个蓝牙设备,简单的“目视检查”(Visual Inspection)足矣!因为前面所谓的蓝牙设备,其实并不存在这样一个叫“蓝牙”的设备,而是说某个设备具有蓝牙功能的通信接口,因此具有蓝牙接口对于许多设备来说是很值得自夸的一个功能,凡是具有此功能的产品,都会在产品上打上“蓝色的LED灯”图案,或者蓝牙的“蓝牙技术联盟”的标志。举例来说,看一下图7-11中所示的设备,这幅照片是作者在当地的超市中拍摄的,这个超市的所有收款台都配有手持的条形码扫描仪,与传统有线的条形码扫描仪相比,对于一般小件物品,二者相差不大,但对于扫描大件物品时,由于蓝牙手持的条形码扫描仪不需要连线,可以在一定范围内随便移动,不受连线的限制,因而其优势十分明显。上面的蓝牙标志清楚地标明,这个设备是使用蓝牙技术进行通信的。

注:蓝牙技术联盟的标志是: ,而蓝牙的标志是该标志左边椭圆型的蝴蝶标志。并且由于其名字的原因,蓝牙通常会使用蓝色作为其图案的主色调。——译者注

图7-11 蓝牙手持条形码扫描仪

在付款台附近进行一次非正式扫描之后,我们发现所有的蓝牙手持条形码扫描仪现在的配置都处于“非可发现的”模式中。这就意味着,如果我们想对它们实施攻击,那么前面提到的主动式扫描发现是不可行的,这该怎么办呢?仔细地观察这些扫描仪的底座,可以发现每个底座上都有一个条形码,而该条形码正是这台手持条形码扫描仪的“蓝牙设备地址”,如图7-12所示。拿到这个条码值,结合前面对“蓝牙设备地址”的介绍,我们知道这个地址的前3个字节是“00:0C:A7”,分别是“非必要地址部分”、“高位地址部分”部分,共同组成了IEEE“组织唯一标示符”的生产商编码。这个生产商编码可以通过http://standards.ieee.org/regauth/oui/oui.txt 查询所对应的生产厂家。通过查询,我们可以知道该蓝牙手持条形码扫描仪的设备生产商是“码捷(苏州)科技有限公司”(Metro(Suzhou)Technologies Co.,Ltd)。访问“码捷科技”的网站,知道这是“码捷科技”(Mecrologic)的一个子公司,并且这款蓝牙手持条形码扫描仪的型号是MS9535 VoyagerBT。从“码捷科技”公司的公司网站上,我们还可以找到有关这款扫描仪的一份PDF版本的用户指南,在上面描述了这款设备的默认“个人识别号码”信息。

图7-12 手持条形码扫描仪的条形码

把“蓝牙设备地址”信息印贴在设备外壳上是很普遍的现象。由于两个蓝牙设备之间,必须共享“蓝牙设备地址”信息才能完成“配对交换”的操作,所以要与某个蓝牙设备进行联系,必须通过某种方式输入对方的“蓝牙设备地址”信息。可以通过蓝牙设备自动完成的“询呼请求”/“询呼应答”过程,也可以通过手动输入操作,还可以通过其他第三方的一些方式来完成。对于那些结构简单的蓝牙设备,由于缺少“LCD显示屏”,并且没有什么可配置的选项,所以手动输入“蓝牙设备地址”信息的方法并不可行。虽然使用“主动式扫描发现”是可行的,但是当扫描时,同时发现多个蓝牙设备的时候,对这些设备进行区分又变成了麻烦事,因为此时虽然知道在你的功率覆盖范围内有几个蓝牙设备,也知道每一个蓝牙设备的“蓝牙设备地址”信息,但哪一个蓝牙设备对应于哪一个“蓝牙设备地址”呢?或者说,你要与哪一个蓝牙设备进行“配对”操作呢?这时,最有效的办法,就是直接将每一个蓝牙设备的“蓝牙设备地址”信息印在或写好贴在设备上。

7.3.3 组合式扫描

在确认识别某个蓝牙设备的时候,如果“主动式扫描发现”和“目视检查”都无法奏效,那么不妨试试下面几种组合发现机制。

Wi-Fi和蓝牙在地址上的“大小差一”

当一个设备制造商在生产一个需要带有多个接口的产品时,就必须为每个接口都配置一个MAC地址 [5] 。通常来讲,单个设备上的多个MAC地址之间通常都是彼此相关的。从技术的角度来看,那就是这些MAC地址之间的前5个字节都是相同,但是最后一位在数值上相差1,这个称为“大小差一”(Off-by-One) [6] 现象。比如,某个蓝牙设备有两个接口,如果设备制造商给第一个接口配置的MAC地址是00:21:5C:7E:70:C3,那么第二个接口的MAC地址通常是00:21:5C:7E:70:C4。根据这种设备制造商的习惯性行为,有些系统就可以将MAC地址相连的两个接口,识别为是一个设备上的,这种想法已经被“无线入侵检测系统”(Wireless Intrusion Detection System,WIDS)的供应商用在判断网络上的恶意AP接入点的算法上了。其原理是,在通过一个“网络地址转换”连接的网络上,如前所述,作为无线IEEE 802.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)”菜单进行查看,某个实例的效果如图7-13所示。

图7-13  Apple公司iOS手机上蓝牙设备地址和Wi-Fi的MAC地址的相关性

知道了这种产品制造商的习惯性行为以后,一旦我们确认了Wi-Fi和蓝牙二者MAC地址之间的关系,我们还可以借助这种关联互相判断二者的行为。比如,我们通过某iPhone手机在无线网络上,以客户端身份所做的操作拿到其Wi-Fi的“基本服务集标识”地址,然后将加减1以后的“逻辑‘蓝牙设备地址’”地址,在蓝牙网络中进行测试。并且,在实战中,我们也不需要把在Wi-Fi无线网络中查到的所有“基本服务集标识”地址一一地进行蓝牙的“蓝牙设备地址”测试。既然知道对方的手机是iPhone,那么它的设备“组织唯一标示符”编码应该是Apple公司。所以它的“蓝牙设备地址”的前三位,是不是也应该是Apple公司的前三位代码呢?在我们编写本书的时候,共有18997个“组织唯一标示符”编码被分配,其中Apple公司共分配到284个 [7] 。“组织唯一标示符”编码仍然是前面提到过的: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 packet summary line),在每一行中,主要显示“源地址”,但是通过“-z”参数可以实现“二次配置”,将其作为静态选项,显示成既有对前缀解析过的(prefix-resolved),也有未对前缀解析过(prefix-unresolved)的MAC地址格式,以便进行前后对照。其显示效果如下所示:

注意

在无线网络中,使用airmon-ng命令进行嗅探的时候,通常习惯于将无线网络接口在信道1中设置为“监测模式”。而无线设备在发送“探测请求”数据包的时候,是向所有信道发送,以便可以捕获到那里活动的无线设备。所以上面例子中,由于信道选择的原因,只能扫描到所选频率上存在的无线设备。

从上面的输出结果中,你可以看到两个“探测请求”数据帧。第一个“探测请求”帧来自前缀是HonHaiPr的设备,因为它不是iPhone,所以可以选择忽略 [8] 。下一个“探测请求”帧的源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命令可以获得蓝牙“友好名称”(friendly name)。其原理和方法,还是如上所述,首先从得到的Wi-Fi无线网卡的MAC地址上,将最后一个字节的值加1,然后将新的MAC地址值作为“蓝牙设备地址”。当然,为了保险,你也可以考虑将Wi-Fi无线网卡的MAC地址中最后一个字节减1,作为在加1后失败的一个后选方案,这样看上去更加周密。

提示

记住!上面无论是“加1”,还是“减1”,都是以十六进制的方式进行的。比如,下面以“加1”为例,如果某次扫描拿到的Wi-Fi无线网卡MAC地址的最后一字节是44,那么你可以在hcitool命令中,推算该蓝牙设备的MAC地址的最后一字节是45。而如果最后一个字节的值是39,那么推算出的值最后一个字节就是3A,而不是40。

Wi-Fi和蓝牙“大小差一”问题的防御措施

对于一个攻击者,要想使用“大小差一”分析方法进行“蓝牙设备地址”的发现扫描,那么对方的设备必须有多个接口,并且每个接口都可以观察得到。所以防御“大小差一”式分析的方法是:尽可能关闭那些不使用的接口,包括Wi-Fi适配器,这样即使对方知道我们的设备存在这种问题,也会因为拿不到Wi-Fi无线网卡的“基本服务集标识”地址,而无法猜测“蓝牙设备地址”,进而从环节上,减少相关地址信息的泄露。

Wi-Fi无线网卡的“基本服务集标识”地址和“蓝牙设备地址”之间的这个“大小差一”问题,对于确认一些设备是很有帮助的,但这种方法并不适用于那些只有一个蓝牙接口,或者接口的编号不连续的设备。在这种情况下,攻击者可以使用其他技术,比如通过被动式通信数据包的嗅探来监听并提取出一部分“蓝牙设备地址”。

7.3.4 被动通信数据包分析

如前所述,一个“传统蓝牙”的数据包中的包头位置,并没有包含“蓝牙设备地址”信息,这一点不像IEEE 802.11的Wi-Fi无线网络通信数据包,也不像以太网有线通信的数据包。不过,对于蓝牙通信,在蓝牙设备在加入“微微网”的时候,“从设备”采用的是一个没用的“逻辑传输地址”(Logical Transport Address,LT_ADDR)。这个地址将在之后的通信中,作为该设备之后所有通信的“逻辑源地址”(logical source address)或“逻辑目标地址”(logical destination address)。“逻辑传输地址”只使用了3位来表示“逻辑源地址”,而不像“蓝牙设备地址”有48位,在保存的时候也得全部保存。

这种设计非常重要,因为这意味着即使通过捕获数据包,检验MAC地址的头部信息,也无法确定某个“活跃”(active)的蓝牙设备完整的“蓝牙设备地址”。不过,通过检测其他各个“活跃”蓝牙设备的MAC头部,至少离拿到完整的“蓝牙设备地址”的目标更近了一步。这一点你会在随后的内容中看到。

促使每一个数据包在蓝牙网络中传输,是由一系列“数值”(value)和“字段”(field)组成的,这些“数值”和“字段”统称为“访问码”(access code)。“访问码”由3部分组成:“前导码”(preamble),“包尾”(trailer),“同步字”(sync word)。

“同步字”是蓝牙“微微网”中发送的每个数据包的重要组成部分。每次一个“从设备”或者“主设备”收到一个数据包,“同步字”都会在基带头部数据开始传输之前,帮助无线接口稳定接收数据。对于一个给定的“微微网”,“同步字”也可以用来确认通信数据包的来源,因为不同的“微微网”之间,“同步字”都是唯一的。这样的好处就是在同一片物理空间中,可以有多个蓝牙网络彼此接近,或互相重迭运行,都不会在识别自己“微微网”数据包的时候导致模棱两可的结论,也不会在接到一个数据包后,不知道这个数据包是来自于哪个“微微网”。

如下所示,“同步字”由3各部分组成:“BCH纠错码”(BCH error correcting code)、“低位地址部分”、“巴克序列”(Barker Sequence)。其中,“BCH纠错码”用于检查和纠正接收到数据中的错误,BCH是由其发明者Bose、Ray-Chaudhuri、Hocquenghem三人的首字母组合命名的;“低位地址部分”如前面7.1.2节所述,是“蓝牙设备地址”的低24位;“巴克序列”用于数据间的互相关联,提高数据包检查中数据正确性的概率,减少数据包看似正确、实际错误的概率)。对于想拿到“蓝牙设备地址”的黑客来说,“低位地址部分”字段无疑是最令他们感兴趣的,因为它包含了“蓝牙设备地址”中的末尾3个字节,也就是24位。

通过将“主设备”的“低位地址部分”编码到“同步码”中,在“微微网”中的任何蓝牙设备在接收到某个数据包之后,都可以确认这个数据包是不是给自己的,这样就能够区分处于同一物理空间中的两个或者更多的“微微网”。对于黑客来说,则可以借助于从一个“活跃”的“微微网”中拿到的“同步字”,得到“主设备”的“蓝牙设备地址”的“低位地址部分”部分。

而且,此时也可以判断处于“非可发现的”模式的蓝牙设备中“蓝牙设备地址”的“高位地址部分”部分。这是因为“蓝牙MAC层”(Bluetooth MAC-layer)的包头包含一个称作“头部校验和纠错校验”(Header Error Correction,HEC)和的字段,该字段的结构如下图所示。其中的“头部校验和纠错校验和”本身只是MAC层数据的一个简单的校验和,没有特殊的含义,但是,这个校验和在计算的时候,需要将“高位地址部分”作为输入,这就意味着,“高位地址部分”的值可以通过这个校验和获得。通过收集多个蓝牙数据包,你可以准确地判断出“高位地址部分”的值,并排除假的值 [9] 。结合上面读到的“低位地址部分”值,就等于是拿到了48位“蓝牙设备地址”中的32位了。

不幸的是,标准的蓝牙接口并不提供“同步字”的内容。对于这些设备,由于设计者并不希望用户对这些底层的信息感兴趣,所以这些设备缺少捕获这类底层蓝牙数据包信息的接口。幸运的是,在一些开源硬件和软件项目中,多多少少会涉及这方面的内容,通过这些可用信息的组合,可以帮助我们间接确认这些信息。

超牙的被动式发现

“超牙项目”(Project Ubertooth)是一个开源的硬件项目,由Great Scott Gadgets团队的Michael Ossmann开发。在这个项目中,Ossmann使用一个自定义的电路板界面开发了一个接口,这个接口可以检测出“传统蓝牙”和“低能耗蓝牙”中发现“蓝牙主机”系统的底层的通信数据包,其通信链路采用的是一个USB接口。超级的硬件系统,目前处于版本为1的阶段,称为“超牙一号”(Ubertooth One)。通过这个工具,可以创建你自己的“传统蓝牙”和“低能耗蓝牙”底层的通信数据包捕获工具。目前可以通过几个在线零售商店买到,售价大约为120美元。从http://greatscottgadgets.com/ubertoothone 网址可以查到该接口的详细资料。

“超牙”系统在与“蓝牙主机”之间的通信功能是通过另一个开源的项目完成的。该项目生成的开发支持包,包括“蓝牙基带通信库”(Bluetooth Baseband Library libbtbb)、“Linux版的蓝牙库”(Linux Bluetooth library)、一个名为“BlueZ”的libbluetooth库,以及其他相关的开发资料。对于Ubuntu操作系统,安装超牙的“蓝牙主机”系统软件时所需要安装的依赖项及其安装方法如下所示。对于“蓝牙基带通信库”中当前的最新功能,可以通过最新版的软件获得,而最新版的软件,则可以通过git拿到源代码,然后进行编译连接后使用。

下一步,安装超牙软件,如上所述,这可以通过git拿到源代码,然后进行编译连接后使用。

该超牙项目还包括一个满足Linux操作系统中udev配置规则的文件,该文件允许usb组与超牙的硬件进行交互(interact)操作。这意味着你可以使用你的超牙硬件在没有root权限的前提下将udev规则文件复制的“udev配置目录”(udev configuration directory),然后在usb组中添加您的登录账户,其步骤如下所示:

完成上述操作以后,注销系统,然后重新登录,以便上面组成员的变化得到应用。

下一步,将超牙设备插入到一个可用的USB接口中。检查您的安装,要确保超牙功能状态是正常。这种检查操作可以通过超牙工具ubertooth-util程序,核查超牙固件的版本号:

在这个例子中,超牙固件的版本号是在2012年10月发布的。要能够访问超牙连接的“断开功能”(breaking feature),还需要将这个固件的版本升级到最新版。固件源程序的发布版可以从超牙的git网站上查到,但是如果要在ARM架构中使用的蓝牙接口,则还需要再重新编译一遍。编译的方法是先下载gcc编译器的ARM版本,然后通过“/opt”参数解压缩这些编译工具到你的Linux“蓝牙主机”上。其命令格式如下所示:

注意

随着时间的推移,gcc-arm-embedded项目变更后的发行版中,有个launchpad.net文件将在未来停止支持。访问https://launchpad.net/gcc-arm-embedded 可以确定自己的gcc-arm-embedded是不是最新的版本。

在gcc-arm-embedded软件安装好以后,你就可以编译最新版的超牙固件,用于蓝牙分析了。

提示

如果你对上面的编译过程不太熟悉,或者不想下载基于ARM的编译器,或者是不想自己动手编译那个最新版超牙固件的源代码,那么你也可以换一种方法,直接从超牙的网站https://github.com/greatscottgadgets/ubertooth 下载到最新版的发布版,然后将这些下载的固件文件,加载到“ubertooth-one-firmware-bin/”目录中。

当一个固件完成了编译,就可以刷新超牙设备用户的ubertooth-util目录,如下所示。

当固件刷新的进程结束运行后,删除拔出并重新插入超牙装置。现在,你再通过ubertooth-util程序看一下超牙设备的版本号是不是发生了改变。ubertooth util标识符不同版本的固件,也可以从通过git下载的gcc-arm-embedded程序的版本号上反映出固件现在使用的是哪个版本:

要测试超牙的功能,你会得到一个基本的频谱图,在频谱图中显示了2.4GHz频段的所有活跃点。该超牙设备是由Spectools项目提供支持的,程序由Mike Kershaw编写。可用的下载版本网站是https://www.kismetwireless.net/spectools 。不幸的是,Ubuntu系统上的软件包管理尚未赶上Spectools的新功能,所以在Ubuntu系统上,你需要先安装Linux上必要的依赖程序和依赖库,然后再下载和编译Spectools的源程序,如下所示:

下一步,在不带参数的情况下,运行spectool_gtk程序。然后选择已连接的超牙接口,就可以启动频谱活动的显示界面了,界面显示如图7-14所示。

图7-14 频谱活动的显示界面

当系统上的超牙配置和当前的固件版本匹配了以后,就可以捕获底层的蓝牙数据包了,这时,即使是“非可发现的”蓝牙设备,只要在自己的功率覆盖范围内,都可以进行捕获。从命令行运行ubertooth-rx工具,该工具就可以从活跃蓝牙发射节点中提取出“蓝牙设备地址”中的“低位地址部分”的值,如下所示:

尽管这些蓝牙设备配置为“非可发现的”模式,但从上面ubertooth-rx程序的输出中,我们还是找出两个蓝牙“低位地址部分”值——A6:56:F7和CB:B8:7A。拿到了“低位地址部分”的值,我们随后就可以继续使用“超牙扫描”(ubertooth-scan),提取“高位地址部分”的值。

提示

当一个蓝牙设备扫描其他处于“非可发现的”模式的蓝牙设备的时候,会将“低位地址部分”的值设置为Ox9E8B33 [10] 。这个地址是保留给“查询设备扫描”(Inquiry Device Scan)时使用的,表示的是这个地址是由发起“主动式扫描”的蓝牙设备发出的,而不是表示发起“主动扫描”的蓝牙设备的“低位地址部分”值是这个数字。

“超牙扫描”通过超牙接口,使用ubertooth-rx工具,还原了“低位地址部分”的值。但是还得用Linux上那个名为“BlueZ”的libbluetooth库所提供的接口,加上一个传统的Linux加密狗,才能拿到已被确认了“低位地址部分”地址的蓝牙设备的“非必要地址部分”的值。在这种方式中,“超牙扫描”可以通过清除那些“格式没错,但数据有错”(false-positive)的数据包,可以加快还原“非必要地址部分”的速度。

注意

“超牙扫描”程序默认情况下的操作,都使用第一个可用的蓝牙接口,在Linux操作系统上的接口名称是hci0。要指定不同的蓝牙接口,可以通过“-d”参数,并在参数后面跟上你要使用接口的名称,就可以改变为所指定的蓝牙接口。

在这个例子中,“超牙扫描”已经识别出两个“传统蓝牙”设备,并还原了二者的“低位地址部分”和“高位地址部分”的值。等到“蓝牙设备地址”的信息还原以后,“超牙扫描”显示出“自适应跳频”(Adaptive Frequency Hopping,AFH)表,该表的作用是避免使用射频干扰(RF interference)的信道。

有了“低位地址部分”和“高位地址部分”的值,我们就等于还原了蓝牙MAC地址48位中的32位,现在还缺的是“非必要地址部分”。即使没有“非必要地址部分”的值,我们仍然可以使用标准蓝牙接口,以及Linux上的BlueZ工具与“非可发现的”模式的蓝牙设备进行交互操作了,通过交换操作,又可以还原出“设备名称”,以及“基本接口”信息(basic interface information)。在实践操作中,任何工具和程序都需要完整的“蓝牙设备地址”,但既然上述操作并不需要“蓝牙设备地址”值中的“非必要地址部分”部分,那么我们在上述操作中,完全可以在需要填写“非必要地址部分”的地方随便用其他的值代替。下面的例子用00:00来代替。

被动式服务发现的防御措施

对于一个黑客来说,“被动式发现”(passive discovery)是一项神奇的技术,可以用来发现即使是处于“非可发现的”模式下的蓝牙设备,并能在“微微网”中获得“主设备”蓝牙的“蓝牙设备地址”中的一部分。使用超牙的硬件,并配以ubertooth-rx程序进行的“低位地址部分”发现,就是一个被动式操作。如果在这个分析过程中,没有新的活跃节点生成,那么,上面的超牙扫描也无法生成,对监视这个“微微网”的黑客来说,他也就得不到读“低位地址部分”值的机会了。

相比之下,在还原“高位地址部分”的过程中,由于“超牙扫描”并不需要使用黑客所猜测的候选“高位地址部分”进行主动式扫描,所以检测一个攻击者所使用的技术是可能的。然而,在蓝牙的安全领域,监控蓝牙活动和检测蓝牙攻击的商业工具实在太少,以至于这种可能变成了极不可能。

一种针对“被动式发现”的防御方法,就是在“同步字”(sync word)的字段中,避免使用敏感的“蓝牙设备地址”。我们可以设计一个蓝牙组件,该组件可以防止蓝牙“匿名”(anonymity)模式下,“唯一可识别”(uniquely identifiable)的蓝牙数据的泄露。该组件中,蓝牙网络也将每次使用一个由“微微网”中蓝牙“主设备”生成的不同的“蓝牙设备地址”。不过,在蓝牙设备会话期间,由于攻击者会在蓝牙网络中进行嗅探,所以限制了“低位地址部分”值的可用性,而且,这个看似不错的方法有两个明显的局限性:

·并不能完全解决威胁  因为攻击者从主动的会话中拿到当前的“低位地址部分”,最终,负责通信的“微微网”一旦形成,攻击者仍然可以使用这些信息来攻击“微微网”。当网络再次形成的时候,虽然使用了另一个由“主设备”生成的“蓝牙设备地址”,但是攻击者也可以简单地再次重复“低位地址部分”的嗅探操作,很快他就会生成新的“低位地址部分”信息。

·并不能广泛部署  蓝牙的“匿名”模式还没有在蓝牙设备中被广泛的采用。目前大多数蓝牙设备还不能对用户提供这样一个配置选项。

到目前为止,我们通过各种工具来检验各种发现蓝牙设备的技术。这些工具中,“主动式扫描”的工具有Windows系统上的BluetoothView、Android系统上的“Bluetooth Finder”,“被动式扫描”的工具有ubertooth-rx,将“主动式扫描”和“被动式扫描”合二为一的“组合式扫描”的工具有ubertooth-scan。另外我们也发现,即使没有“蓝牙设备地址”中的“非必要地址部分”,我们也可以使用已还原的“高位地址部分”和“低位地址部分”,通过查询的方式扫描蓝牙设备,以实现比较隐蔽的攻击机会。

[1] 注:1英尺等于0.3048米。——编辑注

[2] Python是一种面向对象的解释型计算机程序设计语言,其语法简洁、清晰,具有丰富和强大的类库。它常被昵称为胶水语言,能够把用其他语言制作的各种模块(尤其是C/C++)很轻松地联结在一起。——译者注

[3] 苹果计算机操作系统OS X的子版本号中,10.9以前的版本都以大型猫科动物命名,如10.0为猎豹(Cheetah),10.1为美洲狮(Puma),10.2为美洲虎(Jaguar),10.3为黑豹(Panther),10.4为老虎(Tiger),10.5为豹子(Leopard),10.6为雪豹(Snow Leopard),10.7为狮子(Lion),10.8为美洲狮(Mountain Lion),不过,10.9以后,则改为旅游地的名称,如10.9为加州北部的“冲浪湾”(Mavericks),10.10为加州北部的某国家公园的名字(Yosemite)。——译者注

[4] 计算机在显示的时候,一直有两种显示模式,一种叫文本模式,另一种是图形模式。图形模式好理解,就是整个屏幕由m×n个像素点组成,各点两两之间没有任何关联,每个像素点可以根据自己的需要显示任意RGB颜色。文本模式,则是将屏幕分成p×q的几个块,各块两两之间大小和形状都完全一样,又可以分为m×n的小区,每个小区只能显示一个ASCII字符,文中所说的宽度指的是这里的p,高度指的是这里的q。由于两种模式各有利弊,并且都有很大的应用市场,所以即使是现在广泛存在的图形操作系统(很显然用的是图形模式)中,也会仿真出文本模式。比如Windows下的“命令提示符”;Linux下的“终端”,都是仿真出来文本模式。——译者注

[5] 在通信的概念上,有线网卡的地址即“介质访问控制”(Media Access Control,MAC)地址;无线网卡的地址称为“基本服务集标识”地址,蓝牙的地址称为“蓝牙设备地址”地址。三者各有区别,但本质相同,所以本书的英文版在很多地方混用了三个概念,在介绍相关性的时候,有时会统一称为MAC地址。——译者注

[6] “大小差一”(Off-by-One)最早出现在编程领域,并且虽然名为“差一”,实际特指“大一”。在编程中,如果定义一个长度为100数组,很多编程语言习惯将序号定义为0~99,但生活中的习惯认为是1~100,而在使用第100位的时候,本应使用99,如果写成100,就产生了“大小差一”的错误,更重要的是,编译器并不能识别出这类错误,最终导致在可执行文件中存在因这种错误而导致的bug。本处引用,其实只是借用值大小上相差1这个现象,并不存在bug的问题。——译者注

[7] 顺便提一下,在本书原书第二版的时候,共有12 756个“组织唯一标示符”编码被分配,其中Apple公司共分配到17个。并且此处的“编写本书的时候”也是指原版,而不是本翻译版。——译者注

[8] 自己不生产硬件的手机品牌(包括各大名牌手机),无疑手机的配件都是全球采购的,所以无线网卡的MAC地址和蓝牙MAC地址很难保证存在上述“大小差一”的现象。——译者注

[9] “校验和”的算法,通常都是多对一的函数。因此不能反向推算,或者说如果非要进行反向推算的话,会同时得到多个可能的值,并且其中只有一个是正确的。如果能捕获到多个数据包,就意味着拿到同一个值的多个校验和,或者将一次反推的多个值代入到后面的校验和运算,然后比较运算结果;或者是将每次反推的多组多个值进行比对,找出相同的那个值,最终都能确定出原始的“高位地址部分”。——译者注

[10] 该值前面的“0x”表示这是由十六进制表示的数据,该值称为“通用查询访问码”(General Inquire Access Code,GIAC),值固定为:0x9E8B33。——译者注