Skip to content

Commit 5f718aa

Browse files
committed
PMKID: fixed the pmkid re-use issue
1 parent e6a0084 commit 5f718aa

1 file changed

Lines changed: 59 additions & 18 deletions

File tree

wifite/attack/pmkid.py

Lines changed: 59 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import os
1313
import time
1414
import re
15+
import glob
1516
from shutil import copy
1617

1718

@@ -28,31 +29,67 @@ def __init__(self, target):
2829
@staticmethod
2930
def get_existing_pmkid_file(bssid):
3031
"""
31-
Load PMKID Hash from a previously-captured hash in ./hs/
32-
Returns:
33-
The hashcat hash (hash*bssid*station*essid) if found.
34-
None if not found.
32+
Returns existing PMKID hash file for the given BSSID.
33+
Returns None if no PMKID hash file exists for the given BSSID.
3534
"""
3635
if not os.path.exists(Configuration.wpa_handshake_dir):
3736
return None
3837

3938
bssid = bssid.lower().replace(':', '')
4039

41-
file_re = re.compile(r'.*pmkid_.*\.22000')
42-
for filename in os.listdir(Configuration.wpa_handshake_dir):
43-
pmkid_filename = os.path.join(Configuration.wpa_handshake_dir, filename)
40+
if Configuration.verbose > 1:
41+
Color.pl('{+} {D}Looking for existing PMKID for BSSID: {C}%s{W}' % bssid)
42+
43+
# Use glob pattern for better file matching
44+
pmkid_pattern = os.path.join(Configuration.wpa_handshake_dir, 'pmkid_*.22000')
45+
for pmkid_filename in glob.glob(pmkid_pattern):
4446
if not os.path.isfile(pmkid_filename):
4547
continue
46-
if not re.match(file_re, pmkid_filename):
48+
49+
try:
50+
with open(pmkid_filename, 'r') as pmkid_handle:
51+
pmkid_hash = pmkid_handle.read().strip()
52+
53+
if Configuration.verbose > 2:
54+
Color.pl('{+} {D}Checking file {C}%s{W}: {C}%s{W}' % (os.path.basename(pmkid_filename), pmkid_hash[:50] + '...'))
55+
56+
# Validate hash format before parsing
57+
if not pmkid_hash or not pmkid_hash.startswith('WPA*'):
58+
if Configuration.verbose > 2:
59+
Color.pl('{+} {D}SKIP: Invalid hash format in {C}%s{W}' % os.path.basename(pmkid_filename))
60+
continue
61+
62+
# Split hash and validate sufficient fields
63+
hash_fields = pmkid_hash.split('*')
64+
if len(hash_fields) < 4:
65+
if Configuration.verbose > 2:
66+
Color.pl('{+} {D}SKIP: Insufficient fields in {C}%s{W} (got %d, need 4+)' % (os.path.basename(pmkid_filename), len(hash_fields)))
67+
continue
68+
69+
# Extract BSSID from correct field (index 3, not 1)
70+
existing_bssid = hash_fields[3].lower().replace(':', '')
71+
72+
# Validate extracted BSSID format
73+
if len(existing_bssid) != 12 or not all(c in '0123456789abcdef' for c in existing_bssid):
74+
if Configuration.verbose > 2:
75+
Color.pl('{+} {D}SKIP: Invalid BSSID format in {C}%s{W}: {C}%s{W}' % (os.path.basename(pmkid_filename), existing_bssid))
76+
continue
77+
78+
if Configuration.verbose > 2:
79+
Color.pl('{+} {D}Extracted BSSID: {C}%s{W} vs target: {C}%s{W}' % (existing_bssid, bssid))
80+
81+
if existing_bssid == bssid:
82+
if Configuration.verbose > 1:
83+
Color.pl('{+} {G}Found matching PMKID file: {C}%s{W}' % os.path.basename(pmkid_filename))
84+
return pmkid_filename
85+
86+
except (IOError, OSError) as e:
87+
if Configuration.verbose > 2:
88+
Color.pl('{+} {R}ERROR reading {C}%s{W}: %s' % (os.path.basename(pmkid_filename), str(e)))
4789
continue
4890

49-
with open(pmkid_filename, 'r') as pmkid_handle:
50-
pmkid_hash = pmkid_handle.read().strip()
51-
if pmkid_hash.count('*') < 3:
52-
continue
53-
existing_bssid = pmkid_hash.split('*')[1].lower().replace(':', '')
54-
if existing_bssid == bssid:
55-
return pmkid_filename
91+
if Configuration.verbose > 1:
92+
Color.pl('{+} {D}No existing PMKID found for BSSID: {C}%s{W}' % bssid)
5693
return None
5794

5895
def run_hashcat(self):
@@ -83,11 +120,15 @@ def run_hashcat(self):
83120
pmkid_file = None
84121

85122
if not Configuration.ignore_old_handshakes:
86-
# Load exisitng PMKID hash from filesystem
87-
pmkid_file = self.get_existing_pmkid_file(self.target.bssid)
123+
# Load existing PMKID hash from filesystem
124+
if Configuration.verbose > 1:
125+
Color.pl('{+} {D}Checking for existing PMKID for BSSID: {C}%s{W}' % self.target.bssid)
126+
pmkid_file = AttackPMKID.get_existing_pmkid_file(self.target.bssid)
88127
if pmkid_file is not None:
89128
Color.pattack('PMKID', self.target, 'CAPTURE',
90-
'Loaded {C}existing{W} PMKID hash: {C}%s{W}\n' % pmkid_file)
129+
'Using {C}existing{W} PMKID hash: {C}%s{W}' % os.path.basename(pmkid_file))
130+
elif Configuration.verbose > 1:
131+
Color.pl('{+} {D}No existing PMKID found, will capture new one{W}')
91132

92133
if pmkid_file is None:
93134
# Capture hash from live target.

0 commit comments

Comments
 (0)