Skip to content

Commit a157132

Browse files
committed
2.1.9: --pmkid option, cleaned up --cracked, other bug fixes.
PMKID: * `--pmkid` option only attacks WPA networks with PMKID capture + crack * Decreased PMKID capture time from 60 seconds to 15 seconds. * Ignores PMKID attack if `--wps-only` is set. WPS: * Ctrl+C while waiting for `bully` to fetch PSK = remembers PIN, PSK is unknown. Misc: * `--cracked` prints results on single lines (much easier to read) * Fixed typo when required dependencies are not found (closes #127)
1 parent ebb7cac commit a157132

File tree

14 files changed

+139
-30
lines changed

14 files changed

+139
-30
lines changed

wifite/args.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,12 @@ def _add_wpa_args(self, wpa):
280280
help=self._verbose('Time to wait before failing WPA attack (default: {G}%d sec{W})' % self.config.wpa_attack_timeout))
281281
wpa.add_argument('-wpat', help=argparse.SUPPRESS, action='store', dest='wpa_attack_timeout', type=int)
282282

283+
wpa.add_argument('--pmkid',
284+
'-pmkid',
285+
action='store_true',
286+
dest='use_pmkid_only',
287+
help=Color.s('ONLY use PMKID capture on WPA endpoints (default: {G}off{W})'))
288+
283289
wpa.add_argument('--new-hs',
284290
action='store_true',
285291
dest='ignore_old_handshakes',

wifite/attack/all.py

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,8 @@ def attack_single(cls, target, targets_remaining):
6767
Color.pl('{!} {R}Error: {O}unable to attack: encryption not WEP or WPA')
6868
return
6969

70-
for attack in attacks:
70+
while len(attacks) > 0:
71+
attack = attacks.pop(0)
7172
try:
7273
result = attack.run()
7374
if result:
@@ -77,7 +78,7 @@ def attack_single(cls, target, targets_remaining):
7778
continue
7879
except KeyboardInterrupt:
7980
Color.pl('\n{!} {O}interrupted{W}\n')
80-
if not cls.user_wants_to_continue(targets_remaining, 1):
81+
if not cls.user_wants_to_continue(targets_remaining, len(attacks)):
8182
return False # Stop attacking other targets
8283

8384
if attack.success:

wifite/attack/pmkid.py

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,12 @@ def run(self):
6262
Returns:
6363
True if handshake is captured. False otherwise.
6464
'''
65+
# Skip if user only wants to run PixieDust attack
66+
if Configuration.wps_only and self.target.wps:
67+
Color.pl('\r{!} {O}Skipping PMKID attack on {R}%s{O} because {R}--wps-only{O} is set{W}' % self.target.essid)
68+
self.success = False
69+
return False
70+
6571
from ..util.process import Process
6672
# Check that we have all hashcat programs
6773
dependencies = [
@@ -103,7 +109,7 @@ def capture_pmkid(self):
103109
The PMKID hash (str) if found, otherwise None.
104110
'''
105111
self.keep_capturing = True
106-
self.timer = Timer(60)
112+
self.timer = Timer(15)
107113

108114
# Start hcxdumptool
109115
t = Thread(target=self.dumptool_thread)
@@ -159,10 +165,11 @@ def crack_pmkid_file(self, pmkid_file):
159165

160166
if key is None:
161167
# Failed to crack.
162-
Color.clear_entire_line()
163-
Color.pattack('PMKID', self.target, '{R}CRACK',
164-
'{R}Failed{O}: passphrase not found in dictionary.\n')
165-
Color.pl('')
168+
if Configuration.wordlist is not None:
169+
Color.clear_entire_line()
170+
Color.pattack('PMKID', self.target, '{R}CRACK',
171+
'{R}Failed {O}Passphrase not found in dictionary.\n')
172+
Color.pl('')
166173
return False
167174
else:
168175
# Successfully cracked.

wifite/attack/wpa.py

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,12 @@ def __init__(self, target):
2626
def run(self):
2727
'''Initiates full WPA handshake capture attack.'''
2828

29+
if Configuration.use_pmkid_only:
30+
self.success = False
31+
return False
2932
# Skip if user only wants to run PixieDust attack
3033
if Configuration.wps_only and self.target.wps:
31-
Color.pl('\r{!} {O}--wps-only{R} set, ignoring WPA-handshake attack on {O}%s{W}' % self.target.essid)
34+
Color.pl('\r{!} {O}Skipping WPA-Handshake attack on {R}%s{O} because {R}--wps-only{O} is set{W}' % self.target.essid)
3235
self.success = False
3336
return self.success
3437

@@ -110,7 +113,12 @@ def capture_handshake(self):
110113
handshake = Handshake(temp_file, bssid=bssid, essid=essid)
111114
if handshake.has_handshake():
112115
# We got a handshake
113-
Color.pl('\n\n{+} {G}successfully captured handshake{W}')
116+
Color.clear_entire_line()
117+
Color.pattack('WPA',
118+
airodump_target,
119+
'Handshake capture',
120+
'{G}Captured handshake{W}')
121+
Color.pl('')
114122
break
115123

116124
# There is no handshake

wifite/attack/wps.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,14 @@ def run(self):
1515
''' Run all WPS-related attacks '''
1616

1717
# Drop out if user specified to not use Reaver/Bully
18+
if Configuration.use_pmkid_only:
19+
self.success = False
20+
return False
21+
1822
if Configuration.no_wps:
1923
Color.pl('\r{!} {O}--no-wps{R} set, ignoring WPS attack on {O}%s{W}' % self.target.essid)
2024
self.success = False
21-
return self.success
25+
return False
2226

2327
if Configuration.use_bully:
2428
return self.run_bully()

wifite/config.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@
88

99
class Configuration(object):
1010
''' Stores configuration variables and functions for Wifite. '''
11-
version = '2.1.8'
11+
version = '2.1.9'
1212

1313
initialized = False # Flag indicating config has been initialized
1414
temp_dir = None # Temporary directory
@@ -79,6 +79,7 @@ def initialize(cls, load_interface=True):
7979
cls.wpa_handshake_dir = 'hs' # Dir to store handshakes
8080
cls.wpa_strip_handshake = False # Strip non-handshake packets
8181
cls.ignore_old_handshakes = False # Always fetch a new handshake
82+
cls.use_pmkid_only = False # Only use PMKID Capture+Crack attack
8283

8384
# Default dictionary for cracking
8485
cls.wordlist = None
@@ -227,6 +228,9 @@ def load_from_arguments(cls):
227228
if args.ignore_old_handshakes:
228229
cls.ignore_old_handshakes = True
229230
Color.pl('{+} {C}option:{W} will {O}ignore{W} existing handshakes (force capture)')
231+
if args.use_pmkid_only:
232+
cls.use_pmkid_only = True
233+
Color.pl('{+} {C}option:{W} will ONLY use {C}PMKID{W} attack on WPA networks')
230234
if args.wpa_handshake_dir:
231235
cls.wpa_handshake_dir = args.wpa_handshake_dir
232236
Color.pl('{+} {C}option:{W} will store handshakes to {G}%s{W}' % args.wpa_handshake_dir)

wifite/model/pmkid_result.py

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,13 @@ def dump(self):
3030
else:
3131
Color.pl('{!} %s {O}key unknown{W}' % ''.rjust(19))
3232

33+
def print_single_line(self, longest_essid):
34+
self.print_single_line_prefix(longest_essid)
35+
Color.p('{G}%s{W}' % 'PMKID'.ljust(5))
36+
Color.p(' ')
37+
Color.p('Key: {G}%s{W}' % self.key)
38+
Color.pl('')
39+
3340
def to_dict(self):
3441
return {
3542
'type' : self.result_type,

wifite/model/result.py

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -15,13 +15,27 @@ class CrackResult(object):
1515

1616
def __init__(self):
1717
self.date = int(time.time())
18+
self.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.date))
1819

1920
def dump(self):
2021
raise Exception('Unimplemented method: dump()')
2122

2223
def to_dict(self):
2324
raise Exception('Unimplemented method: to_dict()')
2425

26+
def print_single_line(self, longest_essid):
27+
raise Exception('Unimplemented method: print_single_line()')
28+
29+
def print_single_line_prefix(self, longest_essid):
30+
essid = self.essid if self.essid else 'N/A'
31+
Color.p('{W} ')
32+
Color.p('{C}%s{W}' % essid.ljust(longest_essid))
33+
Color.p(' ')
34+
Color.p('{GR}%s{W}' % self.bssid.ljust(17))
35+
Color.p(' ')
36+
Color.p('{D}%s{W}' % self.readable_date.ljust(19))
37+
Color.p(' ')
38+
2539
def save(self):
2640
''' Adds this crack result to the cracked file and saves it. '''
2741
name = CrackResult.cracked_file
@@ -52,12 +66,32 @@ def display(cls):
5266

5367
if len(cracked_targets) == 0:
5468
Color.pl('{!} {R}no results found in {O}%s{W}' % name)
55-
else:
56-
Color.pl('{+} displaying {G}%d {C}cracked target(s){W}\n' % len(cracked_targets))
57-
for item in cracked_targets:
58-
cr = cls.load(item)
59-
cr.dump()
60-
Color.pl('')
69+
return
70+
71+
Color.pl('\n{+} Displaying {G}%d{W} cracked target(s) from {C}%s{W}\n' % (
72+
len(cracked_targets), name))
73+
74+
results = sorted([cls.load(item) for item in cracked_targets], key=lambda x: x.date, reverse=True)
75+
longest_essid = max([len(result.essid or 'ESSID') for result in results])
76+
77+
# Header
78+
Color.p('{D} ')
79+
Color.p('ESSID'.ljust(longest_essid))
80+
Color.p(' ')
81+
Color.p('BSSID'.ljust(17))
82+
Color.p(' ')
83+
Color.p('DATE'.ljust(19))
84+
Color.p(' ')
85+
Color.p('TYPE'.ljust(5))
86+
Color.p(' ')
87+
Color.p('KEY')
88+
Color.pl('{D}')
89+
Color.p(' ' + '-' * (longest_essid + 17 + 19 + 5 + 11 + 12))
90+
Color.pl('{W}')
91+
# Results
92+
for result in results:
93+
result.print_single_line(longest_essid)
94+
Color.pl('')
6195

6296

6397
@classmethod
@@ -97,6 +131,7 @@ def load(json):
97131
json['pmkid_file'],
98132
json['key'])
99133
result.date = json['date']
134+
result.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(result.date))
100135
return result
101136

102137
if __name__ == '__main__':

wifite/model/wep_result.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,16 @@ def dump(self):
2323
Color.pl('{+} Hex Key: {G}%s{W}' % self.hex_key)
2424
if self.ascii_key:
2525
Color.pl('{+} Ascii Key: {G}%s{W}' % self.ascii_key)
26-
26+
27+
def print_single_line(self, longest_essid):
28+
self.print_single_line_prefix(longest_essid)
29+
Color.p('{G}%s{W}' % 'WEP'.ljust(5))
30+
Color.p(' ')
31+
Color.p('Hex: {G}%s{W}' % self.hex_key.replace(':', ''))
32+
if self.ascii_key:
33+
Color.p(' (ASCII: {G}%s{W})' % self.ascii_key)
34+
Color.pl('')
35+
2736
def to_dict(self):
2837
return {
2938
'type' : self.result_type,

wifite/model/wpa_result.py

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,14 @@ def dump(self):
2929
Color.pl('{+} %s: {G}%s{W}' % ('PSK (password)'.rjust(19), self.key))
3030
else:
3131
Color.pl('{!} %s {O}key unknown{W}' % ''.rjust(19))
32-
32+
33+
def print_single_line(self, longest_essid):
34+
self.print_single_line_prefix(longest_essid)
35+
Color.p('{G}%s{W}' % 'WPA'.ljust(5))
36+
Color.p(' ')
37+
Color.p('Key: {G}%s{W}' % self.key)
38+
Color.pl('')
39+
3340
def to_dict(self):
3441
return {
3542
'type' : self.result_type,

0 commit comments

Comments
 (0)