Skip to content

Commit 95fd40c

Browse files
committed
Update README.md
1 parent b719051 commit 95fd40c

7 files changed

Lines changed: 95 additions & 116 deletions

File tree

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -116,7 +116,6 @@ Second, only the latest versions of these programs are supported and must be ins
116116
* [`hostapd`](https://w1.fi/hostapd/): For creating rogue access points (v2.9+ required).
117117
* [`dnsmasq`](http://www.thekelleys.org.uk/dnsmasq/doc.html): For DHCP and DNS services (v2.80+ required).
118118
* [`wpa_supplicant`](https://w1.fi/wpa_supplicant/): For validating captured credentials (v2.9+ required).
119-
* **⚠️ LEGAL WARNING:** Evil Twin attacks require explicit written authorization. Unauthorized use is illegal and may result in criminal prosecution. See [Evil Twin Guide](docs/EVILTWIN_GUIDE.md) for complete legal requirements, usage instructions, and best practices.
120119

121120

122121

@@ -950,7 +949,7 @@ Wifite2 is actively maintained and welcomes contributions! Here's how you can he
950949
* Create tutorials and guides for specific use cases
951950
* Translate documentation to other languages
952951

953-
**Maintainer:** [@kimocoder](https://github.com/kimocoder)
952+
**Maintainer:** [@kimocoder](https://github.com/kimocoder)
954953
**Original Author:** [@derv82](https://github.com/derv82)
955954

956955
---

wifite/attack/attack_monitor.py

100644100755
Lines changed: 4 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -53,12 +53,12 @@ def __init__(self, tui_controller=None):
5353
# Attack tracking
5454
# List of recent attack events (limited to last 100)
5555
self.attack_events = []
56-
56+
5757
# Dictionary tracking networks under attack
58-
# Format: {bssid: {'essid': str, 'count': int, 'last_seen': float,
58+
# Format: {bssid: {'essid': str, 'count': int, 'last_seen': float,
5959
# 'first_seen': float, 'attack_types': {'deauth': int, 'disassoc': int}}}
6060
self.networks_under_attack = {}
61-
61+
6262
# Dictionary tracking attacker MACs
6363
# Format: {mac: {'count': int, 'targets': set(), 'first_seen': float,
6464
# 'last_seen': float, 'attack_types': {'deauth': int, 'disassoc': int}}}
@@ -165,7 +165,7 @@ def parse_frame(self, frame_data):
165165
try:
166166
# Extract frame type
167167
frame_type = frame_data.get('frame_type', '')
168-
168+
169169
# Determine attack type based on frame type
170170
# 0x0c = Deauthentication (12 decimal)
171171
# 0x0a = Disassociation (10 decimal)
@@ -422,29 +422,6 @@ def update_statistics(self):
422422
recent_events=self.attack_events
423423
)
424424

425-
def display_legal_warning(self):
426-
"""
427-
Display legal warning about wireless monitoring.
428-
429-
Warns users about legal requirements and authorization needs.
430-
"""
431-
if self.tui_view:
432-
self.tui_view.add_log('[bold red]⚠️ LEGAL WARNING ⚠️[/bold red]')
433-
self.tui_view.add_log('[yellow]Wireless monitoring requires authorization.[/yellow]')
434-
self.tui_view.add_log('[yellow]Only monitor networks you own or have permission to monitor.[/yellow]')
435-
self.tui_view.add_log('[yellow]Unauthorized monitoring may be illegal in your jurisdiction.[/yellow]')
436-
else:
437-
Color.pl('')
438-
Color.pl('{!} {R}═══════════════════════════════════════════════════════════{W}')
439-
Color.pl('{!} {R} ⚠️ LEGAL WARNING ⚠️ {W}')
440-
Color.pl('{!} {R}═══════════════════════════════════════════════════════════{W}')
441-
Color.pl('{!} {O}Wireless monitoring requires authorization.{W}')
442-
Color.pl('{!} {O}Only monitor networks you own or have explicit permission to monitor.{W}')
443-
Color.pl('{!} {O}Unauthorized monitoring may be illegal in your jurisdiction.{W}')
444-
Color.pl('{!} {O}You are responsible for compliance with all applicable laws.{W}')
445-
Color.pl('{!} {R}═══════════════════════════════════════════════════════════{W}')
446-
Color.pl('')
447-
448425
def run(self):
449426
"""
450427
Main monitoring loop.
@@ -461,9 +438,6 @@ def run(self):
461438
Returns:
462439
bool: True if monitoring completed successfully
463440
"""
464-
# Display legal warning
465-
self.display_legal_warning()
466-
467441
# Validate dependencies
468442
if not self.validate_dependencies():
469443
return False

wifite/attack/pmkid_passive.py

100644100755
Lines changed: 47 additions & 47 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,14 @@ def extract_and_save_pmkids(self):
201201
bssid = pmkid_data.get('bssid', '').upper()
202202
essid = pmkid_data.get('essid', '')
203203
pmkid_hash = pmkid_data.get('hash', '')
204-
204+
205205
# Skip if we already have this BSSID
206206
if bssid in self.captured_pmkids:
207207
continue
208-
208+
209209
# Save the PMKID hash to file
210210
pmkid_file = self.save_pmkid_hash(bssid, essid, pmkid_hash)
211-
211+
212212
if pmkid_file:
213213
# Add to captured_pmkids dictionary
214214
self.captured_pmkids[bssid] = {
@@ -218,130 +218,130 @@ def extract_and_save_pmkids(self):
218218
'captured_at': time.time()
219219
}
220220
new_pmkids += 1
221-
221+
222222
# Notify TUI if available
223223
if self.tui_view:
224224
self.tui_view.add_pmkid_captured(essid, bssid)
225-
225+
226226
# Update statistics
227227
self.statistics['networks_detected'] = len(pmkids)
228228
self.statistics['pmkids_captured'] = len(self.captured_pmkids)
229229
self.statistics['last_extraction'] = time.time()
230-
230+
231231
# Update TUI or display in classic mode
232232
if self.tui_view:
233233
# Update TUI view with new statistics
234234
self.update_tui_statistics()
235235
elif new_pmkids > 0:
236236
# Classic mode - only show if new PMKIDs captured
237237
Color.pl('{+} {G}Captured %d new PMKID(s)!{W}' % new_pmkids)
238-
238+
239239
except Exception as e:
240240
error_msg = f'Error during hash extraction: {str(e)}'
241241
if self.tui_view:
242242
self.tui_view.add_log(f'[red]✗[/red] {error_msg}')
243243
else:
244244
Color.pl('{!} {R}%s{W}' % error_msg)
245-
245+
246246
if Configuration.verbose > 0:
247247
import traceback
248248
if self.tui_view:
249249
self.tui_view.add_log(traceback.format_exc())
250250
else:
251251
Color.pl('{!} {R}%s{W}' % traceback.format_exc())
252-
252+
253253
def save_pmkid_hash(self, bssid, essid, pmkid_hash):
254254
"""
255255
Save a single PMKID hash to file.
256-
256+
257257
Generates filename with format: pmkid_{essid}_{bssid}_{timestamp}.22000
258258
Checks for existing file with same BSSID to prevent duplicates.
259259
Saves hash to Configuration.wpa_handshake_dir.
260-
260+
261261
Args:
262262
bssid (str): Target BSSID
263263
essid (str): Target ESSID
264264
pmkid_hash (str): PMKID hash in .22000 format
265-
265+
266266
Returns:
267267
str: File path of saved hash, or None if save failed
268268
"""
269269
# Create handshake directory if it doesn't exist
270270
if not os.path.exists(Configuration.wpa_handshake_dir):
271271
os.makedirs(Configuration.wpa_handshake_dir)
272-
272+
273273
# Generate filesystem-safe filename
274274
essid_safe = re.sub('[^a-zA-Z0-9]', '', essid) if essid else 'hidden'
275275
bssid_safe = bssid.replace(':', '-')
276276
timestamp = time.strftime('%Y-%m-%dT%H-%M-%S')
277-
277+
278278
filename = f'pmkid_{essid_safe}_{bssid_safe}_{timestamp}.22000'
279279
pmkid_file = os.path.join(Configuration.wpa_handshake_dir, filename)
280-
280+
281281
# Check for existing file with same BSSID to prevent duplicates
282282
# This is a simple check - more sophisticated duplicate detection
283283
# could be added by checking file contents
284284
import glob
285285
pattern = os.path.join(Configuration.wpa_handshake_dir, f'pmkid_*_{bssid_safe}_*.22000')
286286
existing_files = glob.glob(pattern)
287-
287+
288288
if existing_files:
289289
# Already have a PMKID for this BSSID
290290
if Configuration.verbose > 1:
291291
Color.pl('{+} {D}Skipping duplicate PMKID for {C}%s{W}' % bssid)
292292
return None
293-
293+
294294
try:
295295
# Save hash to file
296296
with open(pmkid_file, 'w') as f:
297297
f.write(pmkid_hash)
298298
f.write('\n')
299-
299+
300300
if self.tui_view:
301301
# TUI mode - log is added by add_pmkid_captured in extract_and_save_pmkids
302302
pass
303303
else:
304304
# Classic mode
305305
Color.pl('{+} {G}Saved PMKID:{W} {C}%s{W} ({C}%s{W})' % (essid if essid else '<hidden>', bssid))
306306
Color.pl('{+} File: {C}%s{W}' % pmkid_file)
307-
307+
308308
return pmkid_file
309-
309+
310310
except Exception as e:
311311
error_msg = f'Error saving PMKID: {str(e)}'
312312
if self.tui_view:
313313
self.tui_view.add_log(f'[red]✗[/red] {error_msg}')
314314
else:
315315
Color.pl('{!} {R}%s{W}' % error_msg)
316316
return None
317-
317+
318318
def update_tui_statistics(self):
319319
"""
320320
Update TUI view with current statistics.
321-
321+
322322
Called periodically to refresh the TUI display with latest capture data.
323323
"""
324324
if not self.tui_view:
325325
return
326-
326+
327327
# Calculate capture file size
328328
if os.path.exists(self.pcapng_file):
329329
size_bytes = os.path.getsize(self.pcapng_file)
330330
else:
331331
size_bytes = 0
332-
332+
333333
# Update TUI view
334334
self.tui_view.update_capture_status(
335335
networks_detected=self.statistics['networks_detected'],
336336
pmkids_captured=self.statistics['pmkids_captured'],
337337
capture_file_size=size_bytes,
338338
last_extraction=self.statistics.get('last_extraction')
339339
)
340-
340+
341341
def display_statistics(self):
342342
"""
343343
Display real-time capture statistics.
344-
344+
345345
Shows networks detected, PMKIDs captured, capture duration, and file size.
346346
Updates display periodically without clearing screen.
347347
Uses Color class for formatted output in classic mode.
@@ -350,14 +350,14 @@ def display_statistics(self):
350350
# Calculate duration
351351
if self.statistics['start_time']:
352352
self.statistics['duration_seconds'] = int(time.time() - self.statistics['start_time'])
353-
353+
354354
# Calculate capture file size
355355
if os.path.exists(self.pcapng_file):
356356
size_bytes = os.path.getsize(self.pcapng_file)
357357
self.statistics['capture_size_mb'] = size_bytes / (1024 * 1024)
358358
else:
359359
size_bytes = 0
360-
360+
361361
if self.tui_view:
362362
# TUI mode - update the view
363363
self.tui_view.update_capture_status(
@@ -376,7 +376,7 @@ def display_statistics(self):
376376
minutes = (duration % 3600) // 60
377377
seconds = duration % 60
378378
duration_str = f'{hours:02d}:{minutes:02d}:{seconds:02d}'
379-
379+
380380
# Display statistics
381381
Color.clear_entire_line()
382382
Color.p('\r{+} {C}Networks:{W} {G}%d{W} | {C}PMKIDs:{W} {G}%d{W} | {C}Duration:{W} {G}%s{W} | {C}Size:{W} {G}%.2f MB{W}' % (
@@ -385,69 +385,69 @@ def display_statistics(self):
385385
duration_str,
386386
self.statistics['capture_size_mb']
387387
))
388-
388+
389389
def run(self):
390390
"""
391391
Main entry point for passive PMKID attack.
392-
392+
393393
Validates dependencies before starting.
394394
Starts passive capture with HcxDumpToolPassive.
395395
Starts monitoring thread.
396396
Enters statistics display loop with keyboard interrupt handling.
397397
Handles duration timeout if configured.
398398
Calls cleanup on exit.
399399
"""
400-
400+
401401
# Validate dependencies
402402
if not self.validate_dependencies():
403403
return False
404-
404+
405405
try:
406406
# Start TUI view if available
407407
if self.tui_view:
408408
self.tui_view.start()
409-
409+
410410
# Start passive capture
411411
with self.start_passive_capture() as dumptool:
412412
self.dumptool = dumptool
413-
413+
414414
# Record start time
415415
self.statistics['start_time'] = time.time()
416-
416+
417417
# Start monitoring thread
418418
self.start_monitoring_thread()
419-
419+
420420
# Calculate end time if duration is specified
421421
end_time = None
422422
if Configuration.pmkid_passive_duration > 0:
423423
end_time = time.time() + Configuration.pmkid_passive_duration
424-
424+
425425
# Main statistics display loop
426426
try:
427427
while True:
428428
# Display statistics
429429
self.display_statistics()
430-
430+
431431
# Check if duration timeout reached
432432
if end_time and time.time() >= end_time:
433433
if self.tui_view:
434434
self.tui_view.add_log('Duration timeout reached')
435435
else:
436436
Color.pl('\n{+} {G}Duration timeout reached{W}')
437437
break
438-
438+
439439
# Sleep briefly
440440
time.sleep(1)
441-
441+
442442
except KeyboardInterrupt:
443443
if self.tui_view:
444444
self.tui_view.add_log('Interrupted by user')
445445
else:
446446
Color.pl('\n{!} {O}Interrupted by user{W}')
447-
447+
448448
# Cleanup
449449
self.cleanup()
450-
450+
451451
except Exception as e:
452452
error_msg = f'Error during passive capture: {str(e)}'
453453
if self.tui_view:
@@ -466,13 +466,13 @@ def run(self):
466466
# Stop TUI view if it was started
467467
if self.tui_view:
468468
self.tui_view.stop()
469-
469+
470470
return True
471-
471+
472472
def cleanup(self):
473473
"""
474474
Stop capture and perform final extraction.
475-
475+
476476
Stops monitoring thread gracefully.
477477
Stops hcxdumptool process (handled by context manager).
478478
Performs final hash extraction from capture file.
@@ -483,7 +483,7 @@ def cleanup(self):
483483
self.tui_view.add_log('Cleaning up...')
484484
else:
485485
Color.pl('\n{+} {C}Cleaning up...{W}')
486-
486+
487487
# Stop monitoring thread
488488
if self.monitor_thread:
489489
self.monitor_thread.stop()

0 commit comments

Comments
 (0)