@@ -69,9 +69,11 @@ def has_handshake(self):
6969 # Check if ANY validator detects a handshake
7070 # Tshark is strict (requires all 4 messages), but cowpatty/aircrack
7171 # can work with just messages 2&3, which is sufficient for cracking
72+ # hcxpcapngtool is best for hcxdumptool captures (pcapng format)
7273 return (len (self .tshark_handshakes ()) > 0 or
7374 len (self .cowpatty_handshakes ()) > 0 or
74- len (self .aircrack_handshakes ()) > 0 )
75+ len (self .aircrack_handshakes ()) > 0 or
76+ len (self .hcxpcapngtool_handshakes ()) > 0 )
7577
7678 def tshark_handshakes (self ):
7779 """Returns list[tuple] of BSSID & ESSID pairs (ESSIDs are always `None`)."""
@@ -83,15 +85,23 @@ def cowpatty_handshakes(self):
8385 if not Process .exists ('cowpatty' ):
8486 return []
8587
86- # Needs to check if cowpatty is updated and have the -2 parameter
87- cowpattycheck = Process ('cowpatty' , devnull = False )
88-
89- command = [
90- 'cowpatty' ,
91- '-2' if 'frames 1 and 2 or 2 and 3 for key attack' in cowpattycheck .stdout () else '' ,
92- '-r' , self .capfile ,
93- '-c' # Check for handshake
94- ]
88+ # Check if cowpatty supports the -2 parameter (frames 1&2 or 2&3)
89+ # Run cowpatty with -h to get help output instead of running without args
90+ try :
91+ cowpattycheck = Process (['cowpatty' , '-h' ], devnull = False )
92+ supports_dash_2 = 'frames 1 and 2 or 2 and 3 for key attack' in cowpattycheck .stdout ()
93+ except Exception :
94+ # If help check fails, assume -2 is not supported
95+ supports_dash_2 = False
96+
97+ # Build command - only include -2 if supported
98+ command = ['cowpatty' ]
99+ if supports_dash_2 :
100+ command .append ('-2' )
101+ command .extend ([
102+ '-r' , self .capfile ,
103+ '-c' # Check for handshake
104+ ])
95105
96106 proc = Process (command , devnull = False )
97107 return next (
@@ -122,6 +132,65 @@ def aircrack_handshakes(self):
122132 else :
123133 return []
124134
135+ def hcxpcapngtool_handshakes (self ):
136+ """
137+ Returns tuple (BSSID,None) if hcxpcapngtool can extract valid handshake data.
138+ This is especially useful for pcapng files captured by hcxdumptool.
139+ Only runs on .pcapng files as hcxpcapngtool is optimized for that format.
140+ """
141+ if not Process .exists ('hcxpcapngtool' ):
142+ return []
143+
144+ # Only use hcxpcapngtool for pcapng files (hcxdumptool format)
145+ # For older .cap files, use aircrack/cowpatty/tshark instead
146+ if not self .capfile .lower ().endswith ('.pcapng' ):
147+ return []
148+
149+ import tempfile
150+
151+ # Create a temporary hash file to test if hcxpcapngtool can extract data
152+ try :
153+ with tempfile .NamedTemporaryFile (mode = 'w' , suffix = '.22000' , delete = False ) as tmp :
154+ hash_file = tmp .name
155+
156+ command = [
157+ 'hcxpcapngtool' ,
158+ '-o' , hash_file ,
159+ self .capfile
160+ ]
161+
162+ proc = Process (command , devnull = False )
163+
164+ # Check if hash file was created and has content
165+ if os .path .exists (hash_file ) and os .path .getsize (hash_file ) > 0 :
166+ # Successfully extracted handshake data
167+ result = [(self .bssid , None )] if self .bssid else [(None , self .essid )]
168+
169+ # Clean up temp file
170+ try :
171+ os .remove (hash_file )
172+ except OSError :
173+ pass
174+
175+ return result
176+ else :
177+ # No valid handshake data found
178+ try :
179+ if os .path .exists (hash_file ):
180+ os .remove (hash_file )
181+ except OSError :
182+ pass
183+ return []
184+
185+ except Exception :
186+ # If anything goes wrong, clean up and return empty
187+ try :
188+ if hash_file and os .path .exists (hash_file ):
189+ os .remove (hash_file )
190+ except (OSError , NameError ):
191+ pass
192+ return []
193+
125194 def analyze (self ):
126195 """Prints analysis of handshake capfile"""
127196 self .divine_bssid_and_essid ()
@@ -133,6 +202,9 @@ def analyze(self):
133202 Handshake .print_pairs (self .cowpatty_handshakes (), 'cowpatty' )
134203
135204 Handshake .print_pairs (self .aircrack_handshakes (), 'aircrack' )
205+
206+ if Process .exists ('hcxpcapngtool' ):
207+ Handshake .print_pairs (self .hcxpcapngtool_handshakes (), 'hcxpcapng' )
136208
137209 def strip (self , outfile = None ):
138210 # XXX: This method might break aircrack-ng, use at own risk.
0 commit comments