到现在为止,你应该对gqrx程序中遇到的“快速傅里叶变换”(FFT)和瀑布的特点开始适应了吧。在“频域”(frequency domain)的范围内分析数据的传输,对用户来说,通常会有一个相当直观的形式化印象,这无论对于信号定位、识别、两信号间比较都是一样。然而,这也只是图表中所表达的内容中的一半内容,另一半对信号的分析,则是通过“时域”(time domain)实现的。在这一节中,我们来讨论一下数字无线通信的内部工作机制。
想象一下,在我们十岁的时候,我们需要通过我们的“树上堡垒”(tree fort)之间传送秘密的信息,两个“树上堡垒”之间有一定的距离(如图11-10所示)。所以我就抓住我妈妈的花园浇花软管,在软管的一头套上一个气球,然后你就你那边的“树上堡垒”中对着软管吹气,你所吹的气通过软管到达我这边,就把气球吹大了。
图11-10 通过“树上堡垒”通信
通过软管吹气球,我可以向你发送一个消息;如果在预定吹的时候,我没有吹,那么一个瘪的气球也同样表示我向你发送了一个消息,只是这两个消息表示的意思不一样。比如不吹气球表示“送我条金枪鱼;我的老虎饿了”;那么,吹气球则可以表示为相反的意思。当然,既然这么做可以发送多于一个消息了,所以我们很快就发明了二进制,并且通过上面的方式,约定了每五秒我们之间至少会做一个“吹”与“不吹”的动作,这里的“吹”与“不吹”的动作其实就是二进制传输中“位”(bit)的概念。
很显然,这个方法很快就遇到了一些问题。我们都有了难以说出的节奏感(sense of rhythm),因为有时我需要超过五秒或者更长的时间才能发送一个“位”。这会对接收方带来困扰,对方是发了连接的两个“0”?还是只有一个“0”?或者,在无意识中,你接收的时间起始点,正好是发送方发送过程中的某个点。这都会导致“发送方的发送没有出错,接收方的接收也没有出错,但接收方接收的信息不是发送方发送的信息”的现象。为了解决这个问题,我们发明了一种数据包结构,即在数据中增加一个“校验和”(checksum)。这样,发送方在发送前,先对要发送的数据通过一定的算法算出一个“校验和”,然后在发送的时候,除了发送数据之外,额外加上这个“校验和”。接收方将数据与“校验和”一起接收后,通过同样的方法对数据进行计算,然后将自己算出的“校验和”和接收到的“校验和”进行比较,如果二者一样,则表示数据是对的,不一样则表示或者接收到的“数据”是错的,或者接收到的“校验和”是错的,总之,接收到的数据是错的。这样,我们至少可以确保得到消息的正确性(包括正确和错误两种可能)。挺复杂的,不是吗?
如果你用过像Arduinog一样的微控制器,你会知道这是怎样的数字通信工程。上面例子中的软管代表的是信号传输线 (或电路板上的走线),吹到气球中的压力代表电压。显然,上面吹气球的这个“系统”具有一定的物理局限性,因为我们只能在一个方向上进行通信(就是吹气),除非我们再拉第二条等长的软管,在另一端套上气球由这边来吹,或者事先约定好,在软管的两端都可以套上气球,并定时切换由谁来吹。同时,如果软管的长度太长,那么要吹大一个气球,将耗费的能量太多了。
同样在上面的例子中,我们在发送1和0的过程中,随时有可能会有数据丢失现象。显然,我不能在发送0的时候,把周围所有的大气都吸净,而生成一个真空的环境。同样,我们可以像动画片“Cap’n Crunch”一样,只要吹响哨子(whistle),就可以搅动周围的空气压力以便让你的耳朵可以听到,这样做的好处是双向通信也容易了,但是代价就是附近的所有人都可以接收到我们之间通信的信息。
当然,就像我们必须与我们的父母和邻居共享相同的空间一样,在爸爸正在修剪草坪的时候跟他沟通是相当困难的。街道对面的那个恼人的孩子在偷走了我们“Cap’n Crunch”哨子,然后再与我们进行沟通的念头,不用说也是行不通的。要想让我们所做的事变得更容易,我们只有把我们的哨子换成长笛,因为长笛有许多个音洞,多种发音的音调,这样,当我们遇到一种干扰源的时候,我们可以“移动”到另一个远离干扰源的通信方式上。
这种原始的例子正在一点一点地接近无线通信工程。大致的意思就是:我一次发送一个“广场”的1,虽然简单,但是也难免出错;但是如果能在传输的过程中,发送一个需要改变的“通知”,然后临时地改变频谱却是件很容易的事。通过下面的一个例子,我们看看能不能理解“邮局代码标准化顾问组”协议的工作原理。
“邮局代码标准化顾问组”(POCSAG)协议是一个无线通信协议。这个协议的数据传送机制是,从开始时首先拿到一段文本信息,然后将这段文本信息保存在一个有几千字节容量的内存芯片中,再根据数据包的结构将数据打包,最后,将这段打好包后的信息以“位流”(stream of bit)的方式发送到空中,而无线调制模块在调制这些信息,然后将它们依次发送到空中的时候,是以一个电磁波的形式发送的(见图11-11)。
图11-11 以电磁波的形式发送信息
在这里,你可以看到一个模拟的“邮局代码标准化顾问组”协议编码在“时域”上的传输过程。上面的虚线是帮助你看清楚原始的二进制信息。在这种情况下,“邮局代码标准化顾问组”协议使用两个频率值代表数据,其中较低的频率表示0,较高的频率表示1。这种调制称为“二进制频移键控” (Binary Frequency Shift-Keying,BFSK),也可简称为FSK。利用“树上堡垒”的例子,“二进制频移键控”就像用长笛发出两种不同的音符来表示发送的信息。
回到我们的例子上,在信息结束之前,有人用一个强大的发射器开始与我们进行对话,这就形成了对我们的“干扰”。虚线表示我们的数据仍然是存在的,但由于新的信号叠加进来以后,导致我们很难看出原来的数据信号,如图11-12所示。不过,在我们放弃这些后来干扰时的数据包时,让我们来检查一直被干扰期间的“频域” 信号。
图11-12 “干扰”信号加入后的波形图
两条竖直的“铁轨”瀑布代表的是信道上的每个用户正在发送信号。两个“铁轨”的每一个轨道上,都有两个频率值,而使用这两个频率信号就可以构成上面所说的“二进制频移键控”。如果你看到这个信号的“快速傅里叶变换”图的话,那么这里的两个“铁轨”看起来,会像一对“兔子耳朵”。
比原来信号中的“1”和“0”本身大得多的是“干扰信号”(interfering signal);就是图11-12中,右边的竖亮条。如果我们让这个信号通过一个“滤波器”(filter),就可以可以把干扰过滤掉,然后留下我们想要的信号,消除不必要的“噪声” [1] (noise)。在“时域”上,这样做就可以消除“干扰信号”,最终让我们看到我们的信号。当然,无论我们怎么做,总是还会有一些“干扰信号”通过滤波器,最后仍然保存在正常信号中;只是我们希望能尽可能多地过滤掉这些“噪声”,防止读取“位”发生差错的现象发生!
到目前为止,我们已经可以方便地将无线通信信号想象成我们经常听到的声音了。但是毕竟二者还不能完全等价,简单地说,二者唯一的区别在于声波和通信用的无线电波之间的传播介质和使用的频率是不一样的。这是一种说法,其实还有的区别就是,不是所有的无线信号都有声音。著名的“木星之声”(Sounds of Jupiter),是由“旅行者一号”(Voyager I)航天器所录,其实名为“之声”,实际上所录的只是在经过这个星球的时候,这个星球表面的太阳风(solar wind)所引发的电磁波的信号值。然后有人将这些信号加速,并且将其转换到人类听觉频率的范围,然后再把转换后的信号通过扬声器播放出来,享受这种“天籁之音”的效果。而实际上,在太空中,是没有我们人类可以听得到的声音的,只有那些听不到的无线电磁波。
可是,换一种角度,我们也可以发现,有好多种无线通信方式喜欢用声音进行交流,比如“自动分组报告系统”(APRS)解调器,以及V.92协议调制解调器。这取决于你如何看待它。这些调制解调器的原始设计者意识到电话线有3~4KHz带宽,所以在设计自己的协议产生的电信号时,如果能“看”到这些信号,那会显得很直观,于是他们就把这个带宽的数据当成是声音的带宽,然后将其当作声音。在某些情况下,比如对方传的原始信号恰在声音的范围内,那么这个信号通过“声音耦合器” (acoustic coupler)后,在调制解调器上还是可以听到声音,这时,就相当于有两个持有手机在通话一样。
抛开上述个别比较钻牛角尖的事例之外,整体上,你应该对原始的无线通信理论有较好的理解。下面就将结合这一新的认识去攻击脆弱的无线设备。
攻击车库入口的电子钥匙
如果你做到了现在这一步,你可能已经发现,SDR设备的功能远远超过我们已经向你展示的上述,在生态系统领域内有限的应用。当然,“好马还要配上好鞍”,除了SDR设备本身,还要有dump1090程序和multimon-ng程序的鼎立支持。其实,“好马好鞍之外,还要有好的骑师”,那就是对于SDR设备,有什么样的工具能从“无线轮胎压力监测系统”(Wireless Tire Pressure Monitoring System,TPMS)以“拉”的方式拿到数据呢?在一次模糊测试中,又有什么应用程序允许你发送任意格式的“全球移动通信系统”(GSM)协议的数据包呢?这下麻烦了,我们大概要东拼西凑地去各处找针对具体应用的这些程序。其实则不然,想想这个设备名字中,本应属于“硬件”来做的“无线收发”,现在却改成了“软件”来负责,这其实就足以说明,即使是针对上述不同的应用,通过软件的定义,我们仍然可以通过SDR设备进行控制。
虽然我们不能在仅仅一章的内容里就教会你如何建立一个属于你自己的“全球移动通信系统”协议栈,但是,我们可以教你一些基本的构建块,就像搭积木一样,有了这些基本块,剩下的就是怎么搭了。比如,许多现代电子设备使用的“开关键控”(On-Off Keying,OOK),这显然是一个简单的,容易理解的调制方案。在这一部分中,我们将分析“无线电子钥匙”(wireless key fob)系统,并试图确定该设备是否存在容易遭受攻击的漏洞。
像所有真正的入侵一样,黑客需要一些努力、技巧、耐心和运气。这种类型的分析一直是充满着挑战性,心脏脆弱的请绕道离开!
找到一个“开关键控”的发射器应该不会太难。在你的房子周围,可能就有多个这样的设备是采用“开关键控”技术的,比如车库门遥控器、汽车的电子钥匙、气象站、门铃、智能喷水枪。我们建议先从一个廉价的无线门铃,或者简单的车库门开启装置开始,因为越便宜的无线设备,越有可能采用“开关键控”技术。
在这次攻击中,我们的目标是“精灵公司”(Genie Company)的车库门开启装置,这是作者本人所使用的。你不需要为了检验本节的内容而专门再买一个这样特定的产品,因为这里介绍的是通用的步骤,这些对付这类电子产品的技术可以直接应用于你所选的其他电子产品上,一般情况下,同样可以作为你自己攻击实验中的目标。
设备的侦听
虽然,进行“黑盒测试”(black-box testing)是完全有可能的,但那样只是对于一个初学者才采用的方式。为了减少这里攻击情节描述的复杂性,现在,我们假设你已经能对要攻击的电子设备进行物理层面上的访问,换句话说,就是你可以走的离车库电子门足够得近。那么第一个问题就是“什么是FCCID?”,“美国联邦通讯委员会”(Federal Communications Commission,FCC)是一个组织的名称,大多数的无线设备,若要在美国销售就必须符合该组织的“FCC Part 15” [2] 条例。“美国联邦通讯委员会”维护着一个兼容设备的在线数据库,提供对各种电子产品的测试“记录”(test record)、“所分配频率”(frequency allocation),“产品用户手册”(manual),甚至产品内部的照片!“美国联邦通讯委员会”会为每个设备编一个唯一的识别码,有了这个概念,那么FCCID就是“美国联邦通讯委员会设备编码”。
通常情况下,“美国联邦通讯委员会设备编码”(FCCID)会印在装置的背面,有时候该码也会直接在设备模具的外壳塑料上塑模成型,也有时候只是简单地在外壳上印上一个标签,在标签上打印或手写上这样的编码。如果你在设备上找不到编码,那就检查包装盒或说明书。找到这个“美国联邦通讯委员会设备编码”之后,你就可以通过“美国联邦通讯委员会”的网站进行查询,网址是http://transition.fcc.gov/oet/ea/fccid 。
图11-13 车库门遥控器上的FCCID
如图11-13所示,这个车库门遥控器上的“美国联邦通讯委员会设备编码”是“B8QACSCT”,乍一看,我们也看不出什么意义。要想知道每一位的明确含义,我们需要知道该编码的组成结构,这个ID值可分为两个部分,分别是“受让人代码”(grantee code)和“产品代码”(product code),其中,“受让人代码”由三或五个字符组成,剩下的那当然就是“产品代码”了。对于这个实例,“B8Q”就是“受让人代码”,而“ACSCT”就是“产品代码”。把这两个值输入到“美国联邦通讯委员会”FCC的网站后,可以查询到一组产品文档的列表,本实例中,查到了两个结果,如图11-14所示。对这些文档的内容稍稍进行一点点的信息挖掘,我们就会发现这款车库门遥控器的无线频率被分配到390MHz上,如图11-14产品列表中,最右边一列字段所示。
图11-14 实例查询结果
没有上述这些信息,我们就只能通过gqrx工具在空气中,通过暴力破解(brute-force)的方式,搜遍所有频率来找这个无线车库门遥控器的频率。这种情况也不是不可能的,每次当我们按下“搜索”按钮的时候,当然心里希望能有所斩获,只是有些时候,用些巧劲儿又是完全必要的,比如如果某次攻击中,你必须得靠暴力方式找到对方所用的频率,若你要搜索的产品属于工业(Industrial)、科学(Scientific)和医疗(Medical),三者常被合称为“ISM”,那么它们三个行业产品的无线频率,一般分别开始于315MHz、433MHz和915MHz。记住,如果采用更高的采样率,那么你将会不断地看到更多射频频率的频谱。
在本节中,我们将使用一个新的工具,名叫osmocom_fft。该程序的用户界面是一个精简版gqrx程序和SDR#程序,不过该功能注重的是实用而不是功能繁杂。我们的目标是找到要捕获无线设备的信号,所以该软件主界面图的正中间,就是频段的中心,在图中设定好中心频率以后,再选择一个合适的增益,并将这些参数保存到一个文件。
下面就可以运行RTL版的SDR设备,中心频率设定为390MHz,采样率设定为2.5“每秒百万次采样值”(MSPS)。这给了我们一个“大水桶”(wide bucket)来装所捕获到的信号,这是为了防止某些无线电子设备万一不按“美国联邦通讯委员会”规定的频率值发送数据的时候,我们也能捕获到。另外,我们也把射频增益调在某个地方的中部,对于增益这种耗大、影响极大的参数来说,仅凭预感,我们就知道电池可能很快就能耗掉一半。最后,我们知道这些无线设备信号传输持续时间将是很短的,想想按一个汽车的无线钥匙还能用多长时间呀,多数情况下比眨眼还快。为了让我们不错过对方的每一次按键,我们不妨启用“峰值保持”(Peak Hold)功能。
一旦我们按下了车库门遥控器的按钮,在软件osmocom_fft的主界面上,我们就会看到一个突发的活动,在390MHz的左边一点,如图11-15所示。太棒了!这是我们第一次尝试就抓到的第一个信号。不用说,在实战中,我们并不总是这么幸运。
图11-15 在软件osmocom_fft上看到的突发活动
虽然我们找到了要找的信号,我们还没有准备好去捕获到它。在这个例子中,我们所设的增益值太高了。所以在该频率的左边和右边,分别都出现了一些干扰导致的扭曲,解决这个问题,我们可以降低增益,直至这些扭曲消失在噪声层(noise floor)中,如果你看到“载波振荡”(carrier wandering),那就每次给予100KHz的微调,因为这种偏移不是你的接收机造成的,而是对方廉价的无线车库门遥控器造成的,可以说这也是廉价的“开关键控”类发射器的共同特点。你可能也注意到图的中心一个直流的“穗”状毛刺,这是射频测量系统中的一种常见伪影现象(artifact)。调整你的信号“偏移量”(offset),一直到直流的“穗”状毛刺不再干扰你的正常数据!
剩下要做的就是将捕获到的数据保存到一个文件中。按下右下角的“录制”(record)按钮后,应用程序就开始将射频采样的数据保存到硬盘中了。连续捕获两个或三个好的发射数据以后,就可以再次单击“录制”按钮停止当前录音。
示例中的这个车库遥控钥匙是很老的型号,所以只要简单地将上面捕获到的数据包简单地“重播”(replay)一下,就可以打开车库的大门。打开HackRF版的SDR设备,后面的处理过程非常简单,注意你在osmocom_fft软件上的设置,主要是“频率”、“增益”和“采样率”三个参数。接下来,就可以开始捕获的过程了,这里用的是HackRF版的SDR设备上自带的hackrf_transfer程序。其命令格式和运行效果如下所示:
采样的数据都被保存到一个文件中。命令中的“-a”参数、“-l”(小写L)参数和“-g”参数主要分别用于调整“幅度”,“低噪音”(low noise),和“中频增益控制”(intermediate frequency gain control)。另外,“-f”参数是以Hz为单位的采样率。如果你想知道该命令中更多有关参数的信息,可以运行“hackrf_transfer--help”。在完成采集数据的记录以后,按Ctrl+C停止捕获过程。
要重传这些信号,以发运“重播”攻击,可以运行以下命令:
在这个例子中,“-x”参数的作用是设置发射增益。这个参数具体选什么值,当然就是“仁者见仁,智者见智”的事情了,一般都是“看不同人的口味下调料”。除非你碰巧有一个频谱分析仪,可以帮你确定需要设置多少发送信号的输出功率。你可能会认为存在一个0分贝(dB)的增益值来发送原始信号,但实际中这种情况是不可能存在的,因为发送0分贝的增益就意味着你的发射器必须位于一个“极度安静”(quietest signal)的场所中。
注意
假设你站在你的车库门附近,我们发现10~20分贝的增益就可以很好地捕获信号。但如果没有发射天线连接到你的无线收发设备中,一个噪音的干扰就有可能破坏,甚至摧毁设备中的模拟电路,所以一定要确保你的天线是与你的SDR设备是硬件兼容的!这里所说的“兼容”不是尺寸上正好可以安装,而是指二者要匹配正确阻抗(impedance),阻抗组一般在50欧姆(ohms)左右,并且在操作前就将频率设好,直接设为目标的工作频率。
如果设备不工作怎么办?
设备的正常工作,通常是所有环节设置都对的结果,但导致设备不能正常工作的原因太多了,所以面对“如果设备不工作,该怎么办”这样的问题,答案就是“没有直接的答案”。这种练习就像是“撬锁”(lock-picking),谁也不能说哪种方法就是好的,哪种方法就是对的。“自己动手,丰衣足食”,通过你对SDR设备工作原理的理解,你需要自己开发出一套直观的操作流程,然后借助于你自己的流程,操控SDR设备,完成攻击,并且在某些情况下,你需要的纯粹是运气。对于创建符合你自己习惯的套路,我们可以给你一些想法,但是没有承诺。
如果你攻击一个廉价的无线门铃,或是一个旧车库的电子门,这一招应该很灵。攻击上述设备失败的主要原因,最大的可能是你的SDR设备的发射信号太弱导致的。解决方法也很简单,逐步认真地加强发射增益,并尝试重新接近这些无线设备的接收机。如果还失败,那就是你的信号仍然还是太弱,继续尝试加大到更大的接收增益,直到显示出接收的波形。
现代车库的电子门和汽车,都在安全系统上有了较大的改进,很多产品都通过“滚动码”实现。这样做的好处是,即使你偷偷录制了某个电子门或汽车的上一次通信数据包,但由于电子门或汽车在使用一段时间以后,就自动滚动到下一组值上了,所以即使你通过“重播”攻击,也许只能有效地使用一次,也许根本连一次也用不了。在录制远端通信的过程中,如果想“重播”看看效果,也要确保你的距离足够远,以便对方的电子门和汽车接收器无法“听到”你发的“重播”信号。对于现代的电子门和汽车系统,这些录制的数据通信包应该尽可能早地使用,因为先进的系统可以在某个编码使用一段时间以后,自动终止该码的使用,而更换成新的编码,这个时候,再用原来保存的旧码通过“重播”攻击方式进行攻击就没有效果了。
现在我们已经检验了捕获和“重播”功能,所使用的实例就是开启一个简单的车库电子门。下一步,让我们进入到一个更高级的攻击方式,即攻击一个“免钥匙开门”的汽车系统。
攻击“免钥匙开门”的汽车系统
在写作这一章的过程中,Johnny Cache跑过来,想看看我们能否破解他“Mini Cooper”小轿车的“免钥匙开门”的汽车系统(keyless entry system)。根据前面我们破解车库大门电子锁的那套设备和操作流程,我们使用了相同的认证手段、相同的捕获数据包方式、相同的“重播”技术,的确打开了一次它的车门。不过,当我们想第二次打开的时候,我们发现之前捕获的数据包已不再有效。难道“Mini Cooper”使用的是“滚动码”机制?或者车锁系统采用的是“质疑响应”(Challenge response)机制?我们不得不回过头来,从自身的操作流程和分析思路上找问题的原因和解决办法。既然前面我们已经将捕获到的开门无线信号的波形记录到磁盘上了,那么我们就不需要再从捕获无线信号这一步开始了。
在本节中,我们使用“‘GNU计划’中无线部分同伴”(GNU Radio Companion)设计一个信号处理算法,来还原从无线车钥匙上捕获到的数据包。我们的算法将非常接近于那个我们正在分析的无线电子车钥匙的型号,所以你需要在这些设备上改变这些步骤的时候,只需要进行微调即可,当然也不排除有大幅调整的可能。而且,这种设计方法是非线性的(nonlinear)和实验化的(experimental),所以要想在最大程度上获得成功,我们需要关注的是概念的内涵(implicit concept),理解它想表达的深层含义;而不是“邯郸学步”,只是简单地模仿前面各个明确的操作步骤(explicit step)。
“GNU计划”中无线部分的“Hello World” [3] 当我们要创建一个应用程序的时候,通常会先构建一个框架,然后借助于这个框架来验证当前的工作是不是有益的。对于现在要进行“Mini Cooper”车门只能接受一次“重播”攻击的事实,我们要建立的框架就是将一些信号加入到一个“快速傅里叶变换”数据块(FFT block)中,并且确认一下,我们确实看到了相同的发送数据包,而这个发送的数据包正是我们之前记录的。记录的步骤如下。
1)打开gnuradio-companion程序,这个程序可以让我们通过对所用数据包的选用数据块(using block)的拖放处理(drag-and-drop process)设计出我们自己的信息处理算法。
2)按下Ctrl+F组合键,查询“文件源”(File Source)数据块,然后将选中的块拖到“工作区”(workspace)上。
3)双击“文件源”(File Source)数据块,就可以打开该数据块的“属性”(properties)窗口,单击窗口中的标题为省略号“...”的按钮,就可以打开文件浏览器,并选中你所捕获的文件。
4)查询“减速”(Throttle)数据块,将该数据块放在你的“文件源”数据块的后面。单击“输入”(In)和“输出”(Out)选项卡就可以将这些信息插入到“减速”(Throttle)数据块中。这个数据块的作用是负责限制采样样品从磁盘文件中的读取速度。除非你使用的是一块硬件(例如声卡或SDR设备),否则你应该在流程图(flowgraph)中的某个地方包含这个数据块。
5)在“减速”数据块的后面放置一个基于QT的图形化频率接收器,然后连接上去。当你运行这个程序的时候,程序将会在输出显示中增加一个“快速傅里叶变换”视图。
6)确保“选项”数据块(Options block,通常在界面的左上角)是用于生成一个QT图形化界面的设置,而不是使用WX工具包(QT最终会成为gnuradio-companion程序的图形化界面)。
7)打开名为samp_rate的“变量”数据块(Variable block),将该项设置成与你文件的采样率相同的值。我们在osmocom_fft程序中使用的是1个“每秒百万次采样值”(MSPS),所以我们进入1e6(或1000000)。这个变量是全局和传播在工作区中的所有数据块。
注:以C语言为主的编程中,数字的科学计数法表示形式。1e6等价于1×106 ,即100万。——译者注
8)将上面流程保存到磁盘文件中,然后单击绿色箭头来开始执行程序。
注意
在设置的时候,要确保你的samp_rate值设置的是正确的。许多“数据块”操作都需要知道两次采样之间的这个时间段长度,比如说“滤波器”就与采样率关系很大。另外,虽然同为“数据块”的名称,但不要在上面的概念中混淆了“减速”数据块的作用,“减速”数据块只影响文件处理的速度,而不会影响到收发速度怎么处理。
注意,在图11-16只有一个峰值了,一峰值就意味着只有一个“开关键控”发射器。如果你看到两个峰值,那您的设备可能是一个“二进制频移键控”发射器。保持这种状态继续监听着!你还应该能够得到一些数据;只是我们得多做一些工作才能够关联并得到这一些值!
图11-16 我们的第一个“GNU计划”中的无线程序,包含了程序的输出
信号波形加工 在我们的例子中有一个非常干净的信号,中心频率接近于0Hz。大约40dB的信噪比(Signal-to-Noise Ratio,SNR)是一种优良的低数据率数据,很像前面提到的“开关键控”发射器。如果设备所接收到的信号中有干扰信号,或很弱的信噪比,那么你可能需要对你的信号波形进行加工。虽然你不能改变你的信号所对应“底噪”(noise floor)的振幅,但是可以去除噪声,有效地提高信噪比,这个过程可以通过以下步骤实现:
1)从前面的步骤中,使用“快速傅里叶变换”公式,写下你的信号占用频率的范围。在我们的例子中,信号之间运行在-100kHz和+100kHz之间。
2)如果你的信号是接近您的图形的中心,那么使用一个“低通滤波器”(Low Pass Filter)。并且放在“减速”数据块和“快速傅里叶变换”之间。
3)如果你的信号向一侧发生偏移,你可以使用“复用”数据块(Multiply block),配以余弦函数(cosine)调用,将其调谐到中心点上。然而,这样你可能会发现使用的“带通滤波器”(Band Pass Filter)会更容易。
4)设置你的滤波器的“截止频率”(Cutoff Frequencies)和“传输带宽”(Transition Width),并重新运行程序。在这个例子中,我们配置了“频率接收器”(frequency sink)同时接收两个流,所以我们可以比较它们的之前数据和之后数据的差异,如图11-17所示。
图11-17 配置频率接收器后接收的两个数据流
学生常常问我“什么是一个合适的滤波器”?如果我们从开始到结束,设计的是一个高性能的无线滤波器,我们可能需要使用“匹配的滤波器” (matched filter),这样可以利用一个已知的信号更可靠地检测到一个未知的信号。然而,这更多的是一种“餐巾纸的背面” [4] (back of the napkin)式的逆向工程项目,同样,现在仅仅是设计一个滤波器,通过该滤波器让你的信号在通过的时候去除掉你不要的那部分频谱。
也就是说,数字滤波器不是让信号更自由地想到哪个频段就到哪个频段,而是在传输的时候,限制在更窄的带宽范围之内。带宽越窄,你的滤波器就与CPU关系越大。选择一个比你的采样频率略少百分之十,可能会使你的模拟显得更缓慢。在这个例子中,我们将“低通滤波器”设置在任一方向上允许+/-100kHz的变化范围,这样可以将下一个100kHz内的噪声逐渐减弱。你可以在前面的图像中看到,在滤波器滤通区域之外的“底噪声”显著地下降了。
解调“开关键控”发射器 该过程的下一步,是瞥一眼正在发射的实际的数据“位”。这里,我们需要引入两个新的数据块。“复数型Mag”数据块 (Complex to Mag block)负责解调“开关键控”发射器,和“QT图形界面时间接收器”数据块的作用是及时将解调后的声波输出出来。如果你碰巧有一个“二进制频移键控”信号,那就用“正交解调器”(Quadrature Demodulator)取代“复杂型Mag”数据块。
在放置数据块的时候,需要注意“复数型Mag”数据块的选项卡的颜色将会由蓝色变成桔黄色,变化的原因是因为数据类型已从“复数”变为“浮点数”。令人遗憾的是,我们没有足够的空间来讨论复数型信号。如果你对本问题比较好奇,属于数学极客 [5] (geek)或一个数学公式受虐狂,我们高调推荐你看《复数信号处理:复数型,而不是复杂的》(Quadrature Signals:Complex,But Not Complicated)这篇文章,该文章由Rick Lyons所写,其网址是http://www.dspguru.com/dsp/tutorials/quadrature-signals 。在任何情况下,都要确保你配置“QT图形界面时间接收器”(QT GUI Time Sink)的数据类型是“从复数型到浮点型”(Complex to Float)这个选项。
“QT图形界面时间接收器”是一个复杂的数据块,有许多配置选项。图上所选择的参数值,也正好是将根据上面例子中所用的参数值。这些选项可以在运行时通过双击图上区域进行查看。
第一次时,我们按这个流程图的顺序运行程序,迎接我们的是部分数据“位”因为数值不停地变化,而从整体看上去在不停地闪来闪去。回想起来,这是有道理的,因为我们已经将“QT图形界面时间接收器”的值配置为一次显示1024个采样值。对于一个有1个“每秒百万次采样值”(MSPS)变化率的采样值,每个值只能在窗口中显示短暂的1毫秒,那数据位不闪反而不正常了。找到问题所在,解决方法也很简单,在图像中间单击菜单,我们配置数据块显示的点数为“100倍速”显示(即“100 x”)。这样,一旦有一次数据发送出现,我们就可以停止当前的显示,操作方法仍然是在图像中间单击一下菜单。然后按下鼠标左键,拖动出一个“缩放框”(zoom box),以便让系统知道我们想看的区域,然后系统就只显示这个区域内的图像内容。如果想调整图像内容的大小,可以通过右键鼠标缩小(zooms out)图像,左键鼠标放大(zooms in)图像,或者你可以使用鼠标滚动轮进行调节,其方式和其他程序通过滚动轮调整大小的方式一样,故不再赘述。
在图11-18中,你可以看到,数据流的部分是由1和0组成。每一个“位”看起来和旁边相同的值的“位”看上去都有些不同,这是系统中的噪声造成的。如果信号传输的距离远一些,那么“位”的振幅会减小。如果噪音太大,或信号的幅度太低,那么你可能会在记录某一位的时候意外地出错。
图11-18 调整后的数据流
对信息进行解码的方法之一,是把一个屏幕的窗口进行截屏,然后手工地录制每一个比特位。这也是一种“把自己搞得头晕脑涨,失去你仅有的那么一点理智”的伟大方式,这样做很容易让电脑明白和理解我们。除此之外,“时钟恢复” (clock recovery)也是一个最复杂的、令人沮丧和棘手的一件事。另外,因为我们对“逆向工程”(reverse engineering)就是一个睁眼瞎,所以想知道我们正在做的这一部分是否正确,也是件很困难的事。最重要的事情是我们可以帮助你设计自己的系统,那就是放置一个“时间接收器”(Time Sink)到流程图的每一步,这样只要你在每一步中检查时间接收器的结果,就可以确定所输出的结果是不是你所期望的值了。
首先,我们必须确定一下,数据“位”发送的速度有多快,换句话说就是“波特率” (baud rate)的值有多大。在传输开始时,首先传的是“前导码” (preamble),这样对于同步定位是有帮助的。“前导码”通常是一个值为“10101010……”的字符串,并且在通信的时候,“前导码”会重复地发送足够多次,以便帮助作为接收方的计算机“锁定”时钟。通过使用“时间接收器”,我们算出它花了大约2.1毫秒发送10个数据“位”,做一个小小的除法运算,也就是4761比特/秒,因此我们使用最接近的波特率值为4800波特 [6] ,因为对于串行端口来说,这是一个有效的波特率,在这个波特率中,我们有足够的信心可以保证数据传输的正确性 [7] 。
注:很简单,就是10/2.1×103 =4761.90。——译者注
在速率为1个“每秒百万次采样值”(MSPS)时,每个“位”将有208.3个采样 [8] 。这是一个很大数据量的样本!我们配置的“低通滤波器”将其除以20,也就是说每20个采样,只取其中1个。那么这样,每一个符号“位”就给我们留下了约10.4个样本。通过使用“Marker” [9] 标注“时间接收器”,我们可以看到实际的采样值,如图11-19所示。
图11-19 通过Marker标注“时间接收器”,看到实际的采样值
在图11-19中,你可以看到的数据代表的是“1011”(至少我们非常肯定,我们没有看到有一位少于10个采样)。每一个“位”刚刚超过10个“采样/符号”。我们的目标是将这个值再下降到每个“位”一个采样,并将其写入一个文件。我们通过设置“决策阈值”(Decision Threshold)约为0.5。这样采样在大于这个值后,就会知道哪个位代表数字1,剩下的位当然就代表数字0。
你可能会天真地认为,配置一个“低通滤波器”,然后再除了208就“足够好”了,(1个“每秒百万次采样值”除以208约为4800Hz)。但很快你会发现,不幸的是,“时钟抖动”(clock jitter)会引起数据“位”的错误。一个更好的方式来做这件事是使用“时钟恢复”数据块。你可以告诉这段代码你对每个符号会产生多少采样,这样一来,整个系统就会表现得很好,并且尽最大的努力智能地挑选每一个数据“位”。
“时钟恢复”数据块是很微妙的,它的工作就是提供一个每个符号采样四次的滤波信号。只要你试着将“时钟恢复”数据块的输出与你的“输入信号”(Input Signal)做一个对比,你就会发现有趣的现象,那就是因为采样率发生了改变,所以最后导致你需要两个独立的“时间接收器”。试着建立起这样的触发机制有助于后面数据的捕获。
因为这里的“时钟恢复”数据块输出了一个“估计位”(estimated bit),所以我们需要做出一个决定。“二进制识别器” (binary slicer)将会把正的采样值(positive sample),也就是大于0.0的采样值识别成“逻辑1”(logical 1),而把负的采样值(negative sample),识别成“逻辑0”(logical 0)。你可以指定“减速”值,以便使用“减速”数据块帮助滤波器输出这些数据“位”。
在这个系统中的一个有趣的数据块,就是“根升余弦滤波器” (Root Raised Cosine Filter)。这种特殊的滤波器只用于数字数据。配置输入采样率和预期的波特率,它就会通过删除不必要的频率,平滑地输出比特位。正确使用“根升余弦滤波器”,可以帮助我们得到一个较低的“误码率”(Bit Error Rate,BER)。
图11-20说明了一个可以可靠地工作的解决方案。应该指出的是,这种设计只适用于在“实验室环境”中可以良好地工作,因为“实验室环境”中,一切传输条件都是理想化的。而对于一个在野外的环境中进行工作的系统,设计更为复杂,并且涉及大量的参数微调,如果你把这个系统安装在你的车中,你会发现你只能对在你10英尺 [10] 范围内的汽车车门进行开锁的破解工作。
图11-20 终极“开关键控”发射器解调方案
经验丰富的信号处理专家可以在上面方案中指出一些糟糕的设计选项。比如,在流程的正中间,我们决定需要有“减速”选项的地方都放置了“减速”数据块。另外,我们任意地选择了0.5作为一个“减速”值的参数。然而对于这个“减速”值需要设置多低,我们仍然还能接收到信息?也许,额外的分析和滤波器的结构,可更好地提高对传输数据捕获的可靠性。
一旦我们有数据“位”输出,我们就需要从中找到我们所需要的信息,并且显示出来。这时,你应该多注意那些在每个传输开始的“前导码”,因为这之后的,才是发送的内容部分,为此,我们专门写了一块叫“模式输出” (Pattern Dump)的数据块,可以从网站http://github.com/tkuester/gr-reveng 中查看。你可以配置一定的模式,然后进行搜索。当这个数据块的运行中发现有合适的模式,就会打印随后的N个字节到屏幕上。或者,你也可以按位次把这些数据“位”拼凑成一个一个的字节,然后依次将它写到一个文件中,用于以后分析。
注意
网站
你可以下载上面实例中的这个输出文件,以及其他相关的“GNU计划”中的无线图形进行分析和理解。下载的网址同样是本书的配套网站,网址是http://www.hackingexposedwireless.com/files/11/8-clock_recovery-ANSWER.grc 。
下面的内容,就是通过上面的信号处理流程输出的结果中的一小段。
从整个文件的内容来看,很明显,有人使用电子钥匙首先发送了一个长的“前导码”。跟着连续发送了4次相同的信息,看上去这把电子钥匙是拿错了。如果我们的车没有接收到第一次所发的消息,那么电子钥匙还有三次开锁的机会。在文件中深度查找,我们可以找到五次相似的块信息。
我们注意到一件奇怪的事情,没有消息顺序地依次超过两个1秒的时间。有一些无线电使用“曼彻斯特编码” [11] (Manchester encoding)避免“1秒”的长串是“背靠背”(back to back)的形式。也就是说当出现一长串1或一长串0的时候,“曼彻斯特编码”可以有效地避免接收方无法通过“时间恢复”数据块进行同步的问题,这是因为“曼彻斯特编码”将要传送的数字“1”转换成了二进制的“10”,而将数字“0”转换成了二进制的“01”,所以无论传输什么样的值,中间总有一个“跳变”的过程,因而十分利于“时间恢复”的操作。
在配置“模式输出”数据块以后,就可以完成“曼彻斯特码”的解码工作,如上所述,我们可以从中恢复出可靠的比特流数据,如下所示。不过,有些与被攻击汽车门锁上,带有隐私性质的数据都已去掉。
尽管我们还没有完全做到通过逆向工程破解这把电子钥匙,但是看上去,上面的数据中,好像有两个字段正在发生变化:一个16位的字段和一个32位的字段。如果我们重复使用第一次的消息会发生什么呢?是这次能够把车门打开,还是显示代码已过期?16位字段的第二字节为什么一直以3为步长进行增量累加?为什么锁车按钮所发送的数据,每次会有如此惊奇的不同?这辆汽车能够反过来跟电子钥匙进行数据传输吗?
要回答这些问题,唯一的办法就是收集更多的数据。在你理解了车锁和电子钥匙之间通信协议的详细格式以后,你就可以进展到实时修改程序的工作了,然后就可以将这一方法扩展到其他车型的车锁和电子钥匙上。在某些时候,你甚至可能会尝试构建一个发射器,然后通过暴力的方式破解这些汽车的车锁安全系统。
[1] 在通信中,凡是不是我们原有信号产生的,都可以视为“噪声”。——译者注
[2] “FCC Part 15条例”指的是无线电频率装置或产品发出的无线电频率RF能量(9KHz至3000GHz)条例及应用原则。该条例本身又可以细分为多版,比如A版(通用细则)、B版(无意辐射电子产品或装置)、C版(适用于有意辐射电子产品或装置)。——译者注
[3] 1974年,由Brian Kernighan和Dennis M. Ritchie合著的《The C Programme Language》一书中,将第一个程序设定为打印“Hello World”这个字符串,在此之后的计算机书中,都争相效仿,将打印这个字符串的程序作为全书的第一个程序。所以计算机界,一般习惯上将“Hello World”理解为你使用某个新工具所做的第一件简单且正式的事。——译者注
[4] 源于Roam Dan在其《The Back of The Napkin: Solving Problems And Selling Ideas with Pictures》书中提出的一种解决问题的新观念,其主旨是通过笔、餐巾纸、白板等低科技含量的设备,为高科技行业、政府机构、金融行业等行业提供视觉化思考培训,解决各种商务问题。——译者注
[5] 极客,主要指对科学(本处当然是指对数学)抱有狂热爱好的某一类人,原理事事必问来源究竟,公式处处都要推证到底。——译者注
[6] 串口的波特率是可设的,但并不是说可以随意设置,而是从总共20多个固定值中进行选择。通常的选择原则是“大于你的波特率中,最小的那个”。比如本处4761,选择了4800的波特率。——译者注
[7] 这个结论十分勉强。串口通信有几个重要的参数,除了波特率之外,还有停止位、校验位和流量控制。如果该SDR设备将自己要发送的数据传送给一个串口模块,那么SDR设备发的数据是“裸数据”,停止位、校验位和流量控制则由串口模块完成,这个结论是对的;如果是SDR设备直接以串口方式向外通信,那么停止位、校验位和流量控制将占用带宽,这时4800的波特率,肯定是不够用的。——译者注
[8] 即1000000/4800=208.33。——译者注
[9] Marker值,是频谱仪中的专用术语。你可以简单地理解为一个Marker就是频谱仪屏幕上的一个点。只是该点中,x坐标是由用户指定的,而y坐标是频谱仪告诉用户的。——译者注
[10] 10英尺约合3.05米。——译者注
[11] 曼彻斯特编码,一种用于物理层的数据通信编码,每一位都会做出跳变,从低到高跳变表示“1”,从高到低跳变表示“0”。这样做的最大好处是,当连续出现0,或连续出现1的时候,接收方仍然能很好地同步。因而这种方式广泛地应用于局域网中的数据通信中。——译者注