前言
让我们从遥控器与目标设备之间的通信开始我们的分析,这部分从安全角度来看非常有趣。
首先,我们需要尝试了解所使用的频率。为了避免干扰,不同国家和地区对无线电频率的传输都有相应的法规规定。只有在特定的频率上才允许无许可证传输。最常见的无许可证传输频率包括:
• 2.4 GHz(ZigBee、蓝牙和蓝牙低功耗、Wi-Fi等)
• 433 MHz(主要在欧洲、亚洲、非洲和大洋洲使用)
• 868 MHz(主要在欧洲使用)
• 315 MHz(主要在美国和亚洲使用)
• 915 MHz(主要在美国和大洋洲使用)
• 426 MHz(主要在亚洲使用)
通常,无线设备会使用一个专门的芯片,该芯片针对特定频率和协议(或有限数量的频率和协议)进行设计,并负责所有信号解释、解调和传输工作。对于这类分析,我们将使用所谓的软件定义无线电(SDR)硬件设备。SDR设备被设计为可以在不同的频率上工作,并且可以接收原始的无线电波。SDR设备将所有的原始信息传送到电脑上,然后通过软件完成其他步骤,从而实现了完全控制。
市场上有许多种SDR组件,价格和功能各不相同。影响价格的主要因素包括:
• 频率范围
• 传输模式(半双工、全双工等)
• 分辨率(模数转换器和数模转换器)
• 灵敏度
其中一款最著名的SDR设备是由Great Scott Gadgets生产的HackRF One。原装HackRF One的价格约为300欧元,但由于它是开源硬件,市面上也有许多价格约为100欧元的中国克隆版。HackRF One支持半双工操作,可以在1 MHz至6 GHz的范围内工作,分辨率是8位。虽然它的灵敏度不是同类设备中最好的,但对于我们的需求来说已经足够。Great Scott Gadgets还生产了两款专为特定频率范围设计的伸缩天线。ANT500适用于75 MHz至1 GHz的频率范围,而ANT700则适用于300 MHz至1100 MHz的频率范围。如果你知道你要工作的频率,那么选择适合该频率的专用天线会比伸缩式天线提供更好的效果。
使用SDR设备的第一步是要找出传感器和遥控器工作的频率。有许多工具可用于此目的。HackRF One套件中的一个名为hackrf_sweep的工具能够以不到一秒的时间扫描整个0至6 GHz的范围。但目前我们并不需要如此宽广的范围,我们将使用一个名为gqrx的图形化工具。
程序很简单:我们先将gqrx工具设置为接近可能的频率之一,启动工具后按下遥控器上的按钮。如果工具显示了一条波形,那么我们就找到了正确的频率(请注意:在同一频率或附近频率可能会有其他设备在传输信号,尤其是在Wi-Fi使用的频率上)。如果没有显示波形,我们则将工具配置为下一个常见频率列表中的频率,然后重复上述程序。
对于我们的报警器而言,正确频率为433 MHz(确切地说是433.92 MHz,图片中最接近的是434 MHz),如黄色波形所示:
既然我们已经检测到了频率,就可以开始分析信号了。为此我们将使用一款出色的工具——Universal Radio Hacker。这款工具提供了完整的无线协议调查和逆向工程套件,并且兼容多种SDR设备,包括HackRF One。
启动工具后,我们可以使用“文件”菜单中的“记录信号”功能来录制信号。设置好SDR设备和正确的频率(433.92 MHz)后,点击“开始”按钮即可开始录制。
我们的遥控器上有四个按钮。目前我们只录制前两个按钮,“锁定”和“解锁”。我们会从报警器未设防的状态开始,先按“锁定”按钮,再按“解锁”按钮。我们将重复这个过程三次(总共六个信号),以便了解在与智能报警器的不同交互过程中信号是否会有所变化。右窗格中的“记录信号”工具会显示录制下来的波形:
我们可以保存信号并关闭“记录信号”弹出窗口。信号将会自动加载到Universal Radio Hacker主工具中。
在开始分析之前,需要了解一些关于二进制数据如何变成模拟波,反之亦然的基础知识。通常,二进制数据首先会被编码算法转换,每个比特会被转换成一组比特,目的是为了弥补小的传输和定时误差。之后,这种编码后的输入被调制,目的是从数字信息创建出模拟信号。我们感兴趣的逆向过程称为解调,其工作原理正好相反:首先我们需要解调信号,然后对其进行解码。
详细解释调制是什么超出了本文的主题,但幸运的是,Universal Radio Hacker实现了调制参数的自动检测,不过最好还是检查一下结果是否正确,因为这一阶段的错误会完全破坏后续步骤的分析。
让我们看看Universal Radio Hacker自动执行的解调,在“解释”标签页中:
在图片的左侧我们可以看到工具检测到的调制类型和参数。根据工具的分析,信号使用了ASK(振幅移键)调制。在图片的右上方我们有一个信号的可视化表示,在右下方则是一个二进制表示。值得注意的是,当前阶段的二进制表示还不是我们感兴趣的信息,因为我们还需要处理编码(稍后我们会详细讨论)。目前,可以把它看作是模拟信号的一个数字转换,其中‘1’代表‘高电平’,而‘0’代表‘低电平’。
图片中有六个区块,这是因为我们分别按下了“锁定”和“解锁”按钮各三次。让我们聚焦于第一个区块:
这个区块由若干子区块组成,可能是因为当我们按下按钮时,遥控器会多次发送信号直到按钮被释放。让我们进一步观察其中一个子区块:
我们可以看到,信号中有些部分带有波形,而有些部分没有波形。让我们再进一步放大,观察带有波形的一个单一区块:
波形在整个信号中的频率、幅度和相位似乎都保持一致,并且看起来我们只是有带波形的信号部分与无波形的信号部分交替出现。Universal Radio Hacker 工具识别这种调制为 ASK(振幅移键),它的判断是正确的。更准确地说,这里使用的调制方式是OOK(开关键控),它是 ASK 的一种变体。
调制算法将输入的二进制字符串转换为方波,进而将其转化为模拟信号。不同的调制算法使用模拟波的不同参数来编码二进制的‘1’和‘0’,包括幅度、频率和相位。ASK 使用幅度进行编码,如下图所示(来源:RF Wireless World):
如图所示,输出的模拟波对于‘1’具有更高的幅度,而对于‘0’则较低。我们信号中使用的 ASK 变体是 OOK。
在 OOK 中只有‘1’对应有模拟波,而‘0’则没有波形。
其他常用的调制方式还包括 FSK(频移键控)和 PSK(相移键控),它们分别基于频率变化和相位变化,如下图所示:
回到我们的信号,我们可以通过更改“Signal View”下拉菜单中的选项来查看信号的解调形式:
现在,让我们看一下右下角的部分,这部分包含了解析出的二进制值(记住,我们需要理解所应用的编码算法才能从比特流中提取信息):
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101 [Pause: 25264 samples]
[... (21 equals entries removed)]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101 [Pause: 25279 samples]
11101000111010001000111011101000111011101000100011101110111010001110100010001000100010001000111 [Pause: 1765504 samples]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001 [Pause: 25290 samples]
[... (18 equals entries removed)]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001 [Pause: 25296 samples]
111010001110100010001110111010001110111010001000111011101110100011101000100010001000100011101 [Pause: 1799065 samples]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101 [Pause: 25293 samples]
[... (23 equals entries removed)]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101 [Pause: 25317 samples]
11101000111010001000111011101000111011101000100011101110111010001110100010001000100010001000111 [Pause: 1480403 samples]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001 [Pause: 25267 samples]
[... (16 equals entries removed)]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001 [Pause: 25288 samples]
111010001110100010001110111010001110111010001000111011101110100011101000100010001000100011101 [Pause: 1389952 samples]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101 [Pause: 25283 samples]
[... (25 equals entries removed)]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101 [Pause: 25282 samples]
11101000111010001000111011101000111011101000100011101110111010001110100010001000100010001000111 [Pause: 1551435 samples]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001 [Pause: 25271 samples]
[... (18 equals entries removed)]
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001 [Pause: 25310 samples]
111010001110100010001110111010001110111010001000111011101110100011101000100010001000100011101 [Pause: 5141308 samples]
在分析这些数据之前,我们可以从观察中得出很多信息:
• 存在一种重复的行为模式:我们看到根据按钮按下时间发送的信息多次出现,随后是一行较少位数的数据,接着是另一组信息的多次发送,如此循环六次。
• 那些位数较少的条目似乎异常(因为它们之间的位数不同),并且总是以数字1结束。这些异常条目总是在每个序列的末尾出现,因此我们可以假设用户在序列中间释放了按钮,或者工具在处理尾部零时出现了错误(工具无法确定每行的位数,并且使用OOK调制时,零与信号缺失并无区别)。
• 如果假定位数较少的序列存在错误,那么在同一组中的所有其他序列都是相同的。而且第1、3、5组和第2、4、6组之间也是相同的(分别对应“锁定”和“解锁”按钮)。
• 除了异常序列外,每行由97位组成。
从这些观察中我们可以推断出这是一个简单的协议,在每次按下按钮时总是发送相同的信息,但这个问题我们稍后再详细讨论。
现在让我们来处理编码问题。大多数算法会将一位信息编码为多位,以使生成的信号更加抗传输和定时错误。Universal Radio Hacker提供了一个工具来处理编码,在“分析”标签页中:
默认情况下,该工具选择了“非归零(NRZ)”解码算法,这是一种简单的编码算法,当解调值为高时编码为‘1’,否则为‘0’,即一个解调值对应一个解码值(我们得到的位串与“解释”标签页中看到的一样)。这种编码算法很少被使用,因为它没有控制机制,也无法区分零和“信号缺失”。之所以作为默认选项是因为它不对前一个工具提供的值进行任何转换,可以适用于任何输入。
为了理解实际使用的编码算法,让我们来看看经过解调但尚未应用任何解码算法的“锁定”按钮和“解锁”按钮的单次传输位串:
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000100011101
1110100011101000100011101110100011101110100010001110111011101000111010001000100010001000111010001
如前所述,我们有97位长度。这个数字很奇怪。可能正确的应该是96位(2的倍数),并且可能存在一个前导或尾随位,可能是某种前导或尾随序列的一部分。
接下来,许多433 MHz遥控器发送的是24位信息。如果是这样,我们可能有一个编码算法,将1位信息编码为4个解调位(总共96位)。所以,让我们尝试将“锁定”和“解锁”的位串分成4位一组:
1110 1000 1110 1000 1000 1110 1110 1000 1110 1110 1000 1000 1110 1110 1110 1000 1110 1000 1000 1000 1000 1000 1000 1110 1
1110 1000 1110 1000 1000 1110 1110 1000 1110 1110 1000 1000 1110 1110 1110 1000 1110 1000 1000 1000 1000 1000 1110 1000 1
我们可以看到两种情况:
所有的4位块要么是1110,要么是1000(不考虑最后一个‘1’位)
用“锁定”和“解锁”命令发送的两个位串非常相似(只有最后8位,加上尾随的1共9位,有所不同)
经过对常见编码算法的研究,我们找到了正确的编码算法:EV1527,一种主要用于简单遥控器的协议。我在实现此协议的芯片的数据表中找到了关于此编码协议的良好描述:
该协议定义如下:
• ‘1’定义为三个“高”信号后跟一个“低”信号,而‘0’定义为一个“高”信号后跟三个“低”信号。
• 有一个前导序列定义为一个“高”信号后跟31个“低”信号。
• 数据帧由前导序列后跟着20位代码(遥控器的标识符)和4位(用于遥控器的按钮)组成。
该协议还解释了第97位的异常‘1’位:它是下一个序列前导序列的一部分(一个“高”信号后跟31个“低”信号),被工具误检测为上一个序列的一部分:
既然我们已经找到了编码算法,我们可以快速地使用Universal Radio Hacker来实现它,该软件提供了一个工具来实现自定义解码算法(“解码”下拉菜单中的“...”项允许使用方便的图形界面创建编码算法)。
首先,我们简单地切掉最后一个位(位置97的位)。它是下一个序列前导序列的一部分,并不包含任何信息(工具底部的“测试”部分对于查看我们的转换应用于位串非常有用):
然后我们添加一个“替换”条目,其中两行用于将‘1110’替换为‘1’,将‘1000’替换为‘0’:
我们可以使用“保存为”按钮保存我们的编码,并将其应用于我们的测试数据。“标记协议差异”复选框非常有助于快速检测信号间的差异:
最后,我们可以使用Universal Radio Hacker的标签功能来给数据的不同部分着色,只需选择前20列(遥控器的代码),右键点击数据并选择“创建标签”。然后我们可以对最后4列(按钮部分)重复同样的过程。标签不仅用于查看目的,而且在稍后使用Universal Radio Hacker的“模糊测试”工具时也将是必要的。结果如下:
解码后的“锁定”和“解锁”按钮的值为:
10100110110011101000 0001 (lock)10100110110011101000 0010 (unlock)
现在,让我们讨论一下我们正在分析的协议所面临的安全问题,然后我们将尝试使用HackRF One进行一些主动攻击:
• 窃听、伪造和重放攻击:发送的信息总是相同的,并且没有设备的身份验证或识别。攻击者可以记录信号并重放以解锁智能报警系统。
• 干扰:可以在业主按下按钮激活报警器时干扰“锁定”信号,从而使房屋处于未受保护状态。
• 按钮位的暴力破解:发送的信息由20位遥控器标识和4位按钮信息(16种组合)组成。攻击者可以记录任何按钮的信号,并执行暴力破解攻击以找出其他按钮的代码,这仅需几秒钟即可完成。此外,遥控器虽然只有4个按钮,但我们有16种潜在组合;也许我们可以找到一些隐藏的命令。
干扰攻击主要可以采取两种形式:噪声干扰或重放干扰。噪声干扰是一种简单的攻击。如果你有足够的功率并在目标频率上发射,你可以覆盖接收端的信号。HackRF One可以通过PortaPack Mayhem固件中的工具在任意频率上进行干扰,PortaPack是HackRF的一个附加组件,带有显示屏和电池,允许在没有笔记本电脑的情况下执行一些任务。重放干扰重复有效的信号(或对其进行修改),破坏或更改接收端接收到的信号。这种攻击比前面提到的那种更复杂,但通常也更难被检测到。高级报警系统可能会实施某种干扰检测和防护措施,比如在检测到干扰攻击时立即发出警告,或使用多个频率来增加成功干扰的难度。显然,我们的廉价报警系统并没有这样的防护措施,但即便如此,无线报警系统的干扰防护也并不容易实现。
重放攻击可以使用Universal Radio Hacker工具来执行。我们可以采用两种方式来进行重放:简单地重复记录的信号,或者根据我们的分析数据生成新信号,这允许我们任意修改发送的信息。要重复记录的信号只需要使用“解释”标签页中的“重放信号”功能(左侧的“播放”按钮)。要根据我们的分析数据生成新信号,则可以使用“生成器”工具。
如果我们尝试使用我们的自定义解码器获得的数据生成信号,它可能不会工作,因为Universal Radio Hacker会反转我们的协议中的替换操作,但不会添加由我们的解码器的“切割前/后”规则移除的那个‘1’位。但是那个‘1’位是必需的,因为它就是下一个信号的前导序列的一部分。要解决这个问题,我们可以简单地移除解码器中的“切割前/后”规则,只保留替换规则:
当移除该规则后,每一行的末尾会出现一个新的“0”。这是正确的,因为我们正在处理OOK调制。实际上,Universal Radio Hacker基于长时间的“低”序列将我们的信号分成了不同的行,但在OOK调制中,“低”既可以表示信号缺失也可以表示“零”。因此,Universal Radio Hacker会在最后一个‘1’之前的零序列停止。但是在OOK中,尾部的‘1’和尾部的‘1’后跟三个零是没有区别的,所以在定义了编码算法之后,工具很可能认为后续前导序列的三个“低”是零,并解码‘1000’为‘0’。
这个末尾的 '0' 将会被 Universal Radio Hacker 中的生成器工具编码为 '1000',但这对我们来说不是问题,因为它结合在下一序列之前的暂停,将会形成下一个前导码(1 后跟着 31 个 0)。
结果如下(我为最后一个位添加了一个名为“next_preamble”的标签):
我们现在可以切换到“生成器”工具,并将文件名拖放到右侧表格中:
在这里,如果我们想要的话,可以随意编辑我们的数据,一旦准备就绪,就可以通过点击“发送数据”按钮来发送。就这样,我们复制了“锁定”和“解锁”按钮的功能。
最后,我们来谈谈按钮位的暴力破解。在“生成器”工具的“模糊测试”子标签页中正是为此目的设计的。要使用模糊测试功能,需要先在分析标签页中设置好标签。首先最好清空表格中的所有条目,只留下一条(否则它会把记录的信号与模糊测试信号拼接起来)。
然后点击表格中留下的唯一条目,其标签将出现在左侧,然后可以通过右键点击想要模糊测试的标签(例如这里的“Buttons”)并选择“编辑模糊测试标签”来进行配置。
在这里我们可以配置所需的模糊测试参数,然后点击“添加到模糊测试值”按钮(默认情况下,它会对标签中的所有位组合进行模糊测试)。然后最好是点击表格右侧的“重复”按钮,为每个值制作至少几个副本(单次传输的信息往往不可靠,最好多次重复每次传输)。
配置完成后,可以关闭这个弹出窗口。在使用模糊测试工具生成信号之前,最好更改一下生成器工具的一个配置。默认情况下,模糊测试工具会在每个生成的信号之间插入暂停(无传输),时间为1百万个样本的总和。这个间隔远大于遥控器发出的信号之间的距离,导致生成的信号可能不被接收器识别。我将该值改为了接近原始记录轨道的值(我的是26K)。这个值可以在“编辑”->“选项”->“生成”中更改。原始记录轨道中信号之间的样本数估计值可以通过在“解释”工具中选择原始暂停并查看波形下方的样本数来获取:
完成这些配置后,可以启用想要模糊测试的标签(本例中是“Buttons”),点击“模糊测试”,并通过“发送数据”按钮发送攻击。
在我们的报警系统上,模糊测试非常顺利,找到了所有四个按钮的信号。遗憾的是,除了遥控器上配置的四个命令之外,并没有额外的命令。:)
我们分析的信号非常简单,但Universal Radio Hacker也能处理更为复杂的信号,比如具有多种状态和挑战响应机制的协议。在这种情况下,“模拟器”工具非常有用,允许对信号进行复杂的操纵。
至于传感器(运动传感器和门传感器)与目标设备之间的通信,其工作方式完全相同。它们有不同的代码(前20位)和在最后4位中的‘0110’。接收器会检查代码和按钮位串,丢弃含有不正确信息的信号。举个例子,这是运动传感器在经过与遥控器相同的逆向工程过程后记录下来的信号:
针对遥控器的简单协议以及传感器使用的相同协议暴露出了另一个问题。传感器仅在发生事件时(门打开或运动传感器前方有物体移动)才会传输信号。因此,如果攻击者切断电源、破坏或摧毁传感器,智能家居中枢将无法察觉这一点并触发警报。