1212import os
1313import time
1414import re
15+ import glob
1516from 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