-
Notifications
You must be signed in to change notification settings - Fork 1.4k
/
Copy pathconfig.py
executable file
·546 lines (449 loc) · 21.7 KB
/
config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import os
import re
from .util.color import Color
from .tools.macchanger import Macchanger
class Configuration(object):
''' Stores configuration variables and functions for Wifite. '''
version = '2.2.5'
initialized = False # Flag indicating config has been initialized
temp_dir = None # Temporary directory
interface = None
verbose = 0
@classmethod
def initialize(cls, load_interface=True):
'''
Sets up default initial configuration values.
Also sets config values based on command-line arguments.
'''
# TODO: categorize configuration into separate classes (under config/*.py)
# E.g. Configuration.wps.enabled, Configuration.wps.timeout, etc
# Only initialize this class once
if cls.initialized:
return
cls.initialized = True
cls.verbose = 0 # Verbosity of output. Higher number means more debug info about running processes.
cls.print_stack_traces = True
cls.kill_conflicting_processes = False
cls.scan_time = 0 # Time to wait before attacking all targets
cls.tx_power = 0 # Wifi transmit power (0 is default)
cls.interface = None
cls.target_channel = None # User-defined channel to scan
cls.target_essid = None # User-defined AP name
cls.target_bssid = None # User-defined AP BSSID
cls.ignore_essids = None # ESSIDs to ignore
cls.clients_only = False # Only show targets that have associated clients
cls.five_ghz = False # Scan 5Ghz channels
cls.show_bssids = False # Show BSSIDs in targets list
cls.show_manufacturers = False # Show manufacturers in targets list
cls.target_manufacturer = False # User-defined AP manufacturer
cls.random_mac = False # Should generate a random Mac address at startup.
cls.no_deauth = False # Deauth hidden networks & WPA handshake targets
cls.num_deauths = 1 # Number of deauth packets to send to each target.
cls.encryption_filter = ['WEP', 'WPA', 'WPS']
# EvilTwin variables
cls.use_eviltwin = False
cls.eviltwin_port = 80
cls.eviltwin_deauth_iface = None
cls.eviltwin_fakeap_iface = None
# WEP variables
cls.wep_filter = False # Only attack WEP networks
cls.wep_pps = 600 # Packets per second
cls.wep_timeout = 600 # Seconds to wait before failing
cls.wep_crack_at_ivs = 10000 # Minimum IVs to start cracking
cls.require_fakeauth = False
cls.wep_restart_stale_ivs = 11 # Seconds to wait before restarting
# Aireplay if IVs don't increaes.
# '0' means never restart.
cls.wep_restart_aircrack = 30 # Seconds to give aircrack to crack
# before restarting the process.
cls.wep_crack_at_ivs = 10000 # Number of IVS to start cracking
cls.wep_keep_ivs = False # Retain .ivs files across multiple attacks.
# WPA variables
cls.wpa_filter = False # Only attack WPA networks
cls.wpa_deauth_timeout = 15 # Wait time between deauths
cls.wpa_attack_timeout = 500 # Wait time before failing
cls.wpa_handshake_dir = 'hs' # Dir to store handshakes
cls.wpa_strip_handshake = False # Strip non-handshake packets
cls.ignore_old_handshakes = False # Always fetch a new handshake
# PMKID variables
cls.use_pmkid_only = False # Only use PMKID Capture+Crack attack
cls.pmkid_timeout = 30 # Time to wait for PMKID capture
cls.dont_use_pmkid = False # Don't use PMKID attack
# Default dictionary for cracking
cls.cracked_file = 'cracked.txt'
cls.wordlist = None
wordlists = [
'./wordlist-top4800-probable.txt', # Local file (ran from cloned repo)
'/usr/share/dict/wordlist-top4800-probable.txt', # setup.py with prefix=/usr
'/usr/local/share/dict/wordlist-top4800-probable.txt', # setup.py with prefix=/usr/local
# Other passwords found on Kali
'/usr/share/wfuzz/wordlist/fuzzdb/wordlists-user-passwd/passwds/phpbb.txt',
'/usr/share/fuzzdb/wordlists-user-passwd/passwds/phpbb.txt',
'/usr/share/wordlists/fern-wifi/common.txt'
]
for wlist in wordlists:
if os.path.exists(wlist):
cls.wordlist = wlist
break
manufacturers = './ieee-oui.txt'
if os.path.exists(manufacturers):
with open(manufacturers, "r") as f:
# Parse txt format into dict
lines = f.read().splitlines()
k = lambda line: line.split()[0]
v = lambda line: ' '.join(line.split()[1:3]).rstrip('.')
cls.manufacturers = {k(line):v(line) for line in lines}
# WPS variables
cls.wps_filter = False # Only attack WPS networks
cls.no_wps = False # Do not use WPS attacks (Pixie-Dust & PIN attacks)
cls.wps_only = False # ONLY use WPS attacks on non-WEP networks
cls.use_bully = False # Use bully instead of reaver
cls.wps_pixie = True
cls.wps_pin = True
cls.wps_ignore_lock = False # Skip WPS PIN attack if AP is locked.
cls.wps_pixie_timeout = 300 # Seconds to wait for PIN before WPS Pixie attack fails
cls.wps_fail_threshold = 100 # Max number of failures
cls.wps_timeout_threshold = 100 # Max number of timeouts
# Commands
cls.show_cracked = False
cls.check_handshake = None
cls.crack_handshake = False
# Overwrite config values with arguments (if defined)
cls.load_from_arguments()
if load_interface:
cls.get_monitor_mode_interface()
@classmethod
def get_monitor_mode_interface(cls):
if cls.interface is None:
# Interface wasn't defined, select it!
from .tools.airmon import Airmon
cls.interface = Airmon.ask()
if cls.random_mac:
Macchanger.random()
@classmethod
def load_from_arguments(cls):
''' Sets configuration values based on Argument.args object '''
from .args import Arguments
args = Arguments(cls).args
cls.parse_settings_args(args)
cls.parse_wep_args(args)
cls.parse_wpa_args(args)
cls.parse_wps_args(args)
cls.parse_pmkid_args(args)
cls.parse_encryption()
# EvilTwin
'''
if args.use_eviltwin:
cls.use_eviltwin = True
Color.pl('{+} {C}option:{W} using {G}eviltwin attacks{W} against all targets')
'''
cls.parse_wep_attacks()
cls.validate()
# Commands
if args.cracked: cls.show_cracked = True
if args.check_handshake: cls.check_handshake = args.check_handshake
if args.crack_handshake: cls.crack_handshake = True
@classmethod
def validate(cls):
if cls.use_pmkid_only and cls.wps_only:
Color.pl('{!} {R}Bad Configuration:{O} --pmkid and --wps-only are not compatible')
raise RuntimeError('Unable to attack networks: --pmkid and --wps-only are not compatible together')
if cls.use_pmkid_only and cls.dont_use_pmkid:
Color.pl('{!} {R}Bad Configuration:{O} --pmkid and --no-pmkid are not compatible')
raise RuntimeError('Unable to attack networks: --pmkid and --no-pmkid are not compatible together')
@classmethod
def parse_settings_args(cls, args):
'''Parses basic settings/configurations from arguments.'''
if args.random_mac:
cls.random_mac = True
Color.pl('{+} {C}option:{W} using {G}random mac address{W} ' +
'when scanning & attacking')
if args.channel:
chn_arg_re = re.compile("^[0-9]+((,[0-9]+)|(-[0-9]+,[0-9]+))*(-[0-9]+)?$")
if not chn_arg_re.match(args.channel):
raise ValueError("Invalid channel! The format must be 1,3-6,9")
cls.target_channel = args.channel
Color.pl('{+} {C}option:{W} scanning for targets on channel ' +
'{G}%s{W}' % args.channel)
if args.interface:
cls.interface = args.interface
Color.pl('{+} {C}option:{W} using wireless interface ' +
'{G}%s{W}' % args.interface)
if args.target_bssid:
cls.target_bssid = args.target_bssid
Color.pl('{+} {C}option:{W} targeting BSSID ' +
'{G}%s{W}' % args.target_bssid)
if args.target_manufacturer:
cls.target_manufacturer = args.target_manufacturer
Color.pl('{+} {C}option:{W} targeting manufacturer ' +
'{G}%s{W}' % args.target_manufacturer)
if args.five_ghz == True:
cls.five_ghz = True
Color.pl('{+} {C}option:{W} including {G}5Ghz networks{W} in scans')
if args.show_bssids == True:
cls.show_bssids = True
Color.pl('{+} {C}option:{W} showing {G}bssids{W} of targets during scan')
if args.show_manufacturers == True:
cls.show_manufacturers = True
Color.pl('{+} {C}option:{W} showing {G}manufacturers{W} of targets during scan')
if args.no_deauth == True:
cls.no_deauth = True
Color.pl('{+} {C}option:{W} will {R}not{W} {O}deauth{W} clients ' +
'during scans or captures')
if args.num_deauths and args.num_deauths > 0:
cls.num_deauths = args.num_deauths
Color.pl('{+} {C}option:{W} send {G}%d{W} deauth packets when deauthing' % (
cls.num_deauths))
if args.target_essid:
cls.target_essid = args.target_essid
Color.pl('{+} {C}option:{W} targeting ESSID {G}%s{W}' % args.target_essid)
if args.ignore_essids is not None:
cls.ignore_essids = args.ignore_essids
Color.pl('{+} {C}option: {O}ignoring ESSID(s): {R}%s{W}' %
', '.join(args.ignore_essids))
if args.clients_only == True:
cls.clients_only = True
Color.pl('{+} {C}option:{W} {O}ignoring targets that do not have ' +
'associated clients')
if args.scan_time:
cls.scan_time = args.scan_time
Color.pl('{+} {C}option:{W} ({G}pillage{W}) attack all targets ' +
'after {G}%d{W}s' % args.scan_time)
if args.verbose:
cls.verbose = args.verbose
Color.pl('{+} {C}option:{W} verbosity level {G}%d{W}' % args.verbose)
if args.kill_conflicting_processes:
cls.kill_conflicting_processes = True
Color.pl('{+} {C}option:{W} kill conflicting processes {G}enabled{W}')
@classmethod
def parse_wep_args(cls, args):
'''Parses WEP-specific arguments'''
if args.wep_filter:
cls.wep_filter = args.wep_filter
if args.wep_pps:
cls.wep_pps = args.wep_pps
Color.pl('{+} {C}option:{W} using {G}%d{W} packets/sec on WEP attacks' % (
args.wep_pps))
if args.wep_timeout:
cls.wep_timeout = args.wep_timeout
Color.pl('{+} {C}option:{W} WEP attack timeout set to ' +
'{G}%d seconds{W}' % args.wep_timeout)
if args.require_fakeauth:
cls.require_fakeauth = True
Color.pl('{+} {C}option:{W} fake-authentication is ' +
'{G}required{W} for WEP attacks')
if args.wep_crack_at_ivs:
cls.wep_crack_at_ivs = args.wep_crack_at_ivs
Color.pl('{+} {C}option:{W} will start cracking WEP keys at ' +
'{G}%d IVs{W}' % args.wep_crack_at_ivs)
if args.wep_restart_stale_ivs:
cls.wep_restart_stale_ivs = args.wep_restart_stale_ivs
Color.pl('{+} {C}option:{W} will restart aireplay after ' +
'{G}%d seconds{W} of no new IVs' % args.wep_restart_stale_ivs)
if args.wep_restart_aircrack:
cls.wep_restart_aircrack = args.wep_restart_aircrack
Color.pl('{+} {C}option:{W} will restart aircrack every ' +
'{G}%d seconds{W}' % args.wep_restart_aircrack)
if args.wep_keep_ivs:
cls.wep_keep_ivs = args.wep_keep_ivs
Color.pl('{+} {C}option:{W} keep .ivs files across multiple WEP attacks')
@classmethod
def parse_wpa_args(cls, args):
'''Parses WPA-specific arguments'''
if args.wpa_filter:
cls.wpa_filter = args.wpa_filter
if args.wordlist:
if not os.path.exists(args.wordlist):
cls.wordlist = None
Color.pl('{+} {C}option:{O} wordlist {R}%s{O} was not found, wifite will NOT attempt to crack handshakes' % args.wordlist)
elif os.path.isfile(args.wordlist):
cls.wordlist = args.wordlist
Color.pl('{+} {C}option:{W} using wordlist {G}%s{W} to crack WPA handshakes' % args.wordlist)
elif os.path.isdir(args.wordlist):
cls.wordlist = None
Color.pl('{+} {C}option:{O} wordlist {R}%s{O} is a directory, not a file. Wifite will NOT attempt to crack handshakes' % args.wordlist)
if args.wpa_deauth_timeout:
cls.wpa_deauth_timeout = args.wpa_deauth_timeout
Color.pl('{+} {C}option:{W} will deauth WPA clients every ' +
'{G}%d seconds{W}' % args.wpa_deauth_timeout)
if args.wpa_attack_timeout:
cls.wpa_attack_timeout = args.wpa_attack_timeout
Color.pl('{+} {C}option:{W} will stop WPA handshake capture after ' +
'{G}%d seconds{W}' % args.wpa_attack_timeout)
if args.ignore_old_handshakes:
cls.ignore_old_handshakes = True
Color.pl('{+} {C}option:{W} will {O}ignore{W} existing handshakes ' +
'(force capture)')
if args.wpa_handshake_dir:
cls.wpa_handshake_dir = args.wpa_handshake_dir
Color.pl('{+} {C}option:{W} will store handshakes to ' +
'{G}%s{W}' % args.wpa_handshake_dir)
if args.wpa_strip_handshake:
cls.wpa_strip_handshake = True
Color.pl('{+} {C}option:{W} will {G}strip{W} non-handshake packets')
@classmethod
def parse_wps_args(cls, args):
'''Parses WPS-specific arguments'''
if args.wps_filter:
cls.wps_filter = args.wps_filter
if args.wps_only:
cls.wps_only = True
cls.wps_filter = True # Also only show WPS networks
Color.pl('{+} {C}option:{W} will *only* attack WPS networks with ' +
'{G}WPS attacks{W} (avoids handshake and PMKID)')
if args.no_wps:
# No WPS attacks at all
cls.no_wps = args.no_wps
cls.wps_pixie = False
cls.wps_pin = False
Color.pl('{+} {C}option:{W} will {O}never{W} use {C}WPS attacks{W} ' +
'(Pixie-Dust/PIN) on targets')
elif args.wps_pixie:
# WPS Pixie-Dust only
cls.wps_pixie = True
cls.wps_pin = False
Color.pl('{+} {C}option:{W} will {G}only{W} use {C}WPS Pixie-Dust ' +
'attack{W} (no {O}PIN{W}) on targets')
elif args.wps_no_pixie:
# WPS PIN only
cls.wps_pixie = False
cls.wps_pin = True
Color.pl('{+} {C}option:{W} will {G}only{W} use {C}WPS PIN attack{W} ' +
'(no {O}Pixie-Dust{W}) on targets')
if args.use_bully:
from .tools.bully import Bully
if not Bully.exists():
Color.pl('{!} {R}Bully not found. Defaulting to {O}reaver{W}')
cls.use_bully = False
else:
cls.use_bully = args.use_bully
Color.pl('{+} {C}option:{W} use {C}bully{W} instead of {C}reaver{W} ' +
'for WPS Attacks')
if args.wps_pixie_timeout:
cls.wps_pixie_timeout = args.wps_pixie_timeout
Color.pl('{+} {C}option:{W} WPS pixie-dust attack will fail after ' +
'{O}%d seconds{W}' % args.wps_pixie_timeout)
if args.wps_fail_threshold:
cls.wps_fail_threshold = args.wps_fail_threshold
Color.pl('{+} {C}option:{W} will stop WPS attack after ' +
'{O}%d failures{W}' % args.wps_fail_threshold)
if args.wps_timeout_threshold:
cls.wps_timeout_threshold = args.wps_timeout_threshold
Color.pl('{+} {C}option:{W} will stop WPS attack after ' +
'{O}%d timeouts{W}' % args.wps_timeout_threshold)
if args.wps_ignore_lock:
cls.wps_ignore_lock = True
Color.pl('{+} {C}option:{W} will {O}ignore{W} WPS lock-outs')
@classmethod
def parse_pmkid_args(cls, args):
if args.use_pmkid_only:
cls.use_pmkid_only = True
Color.pl('{+} {C}option:{W} will ONLY use {C}PMKID{W} attack on WPA networks')
if args.pmkid_timeout:
cls.pmkid_timeout = args.pmkid_timeout
Color.pl('{+} {C}option:{W} will wait {G}%d seconds{W} during {C}PMKID{W} capture' % args.pmkid_timeout)
if args.dont_use_pmkid:
cls.dont_use_pmkid = True
Color.pl('{+} {C}option:{W} will NOT use {C}PMKID{W} attack on WPA networks')
@classmethod
def parse_encryption(cls):
'''Adjusts encryption filter (WEP and/or WPA and/or WPS)'''
cls.encryption_filter = []
if cls.wep_filter: cls.encryption_filter.append('WEP')
if cls.wpa_filter: cls.encryption_filter.append('WPA')
if cls.wps_filter: cls.encryption_filter.append('WPS')
if len(cls.encryption_filter) == 3:
Color.pl('{+} {C}option:{W} targeting {G}all encrypted networks{W}')
elif len(cls.encryption_filter) == 0:
# Default to scan all types
cls.encryption_filter = ['WEP', 'WPA', 'WPS']
else:
Color.pl('{+} {C}option:{W} ' +
'targeting {G}%s-encrypted{W} networks'
% '/'.join(cls.encryption_filter))
@classmethod
def parse_wep_attacks(cls):
'''Parses and sets WEP-specific args (-chopchop, -fragment, etc)'''
cls.wep_attacks = []
from sys import argv
seen = set()
for arg in argv:
if arg in seen: continue
seen.add(arg)
if arg == '-arpreplay': cls.wep_attacks.append('replay')
if arg == '-fragment': cls.wep_attacks.append('fragment')
if arg == '-chopchop': cls.wep_attacks.append('chopchop')
if arg == '-caffelatte': cls.wep_attacks.append('caffelatte')
if arg == '-p0841': cls.wep_attacks.append('p0841')
if arg == '-hirte': cls.wep_attacks.append('hirte')
if len(cls.wep_attacks) == 0:
# Use all attacks
cls.wep_attacks = ['replay',
'fragment',
'chopchop',
'caffelatte',
'p0841',
'hirte'
]
elif len(cls.wep_attacks) > 0:
Color.pl('{+} {C}option:{W} using {G}%s{W} WEP attacks'
% '{W}, {G}'.join(cls.wep_attacks))
@classmethod
def temp(cls, subfile=''):
''' Creates and/or returns the temporary directory '''
if cls.temp_dir is None:
cls.temp_dir = cls.create_temp()
return cls.temp_dir + subfile
@staticmethod
def create_temp():
''' Creates and returns a temporary directory '''
from tempfile import mkdtemp
tmp = mkdtemp(prefix='wifite')
if not tmp.endswith(os.sep):
tmp += os.sep
return tmp
@classmethod
def delete_temp(cls):
''' Remove temp files and folder '''
if cls.temp_dir is None: return
if os.path.exists(cls.temp_dir):
for f in os.listdir(cls.temp_dir):
os.remove(cls.temp_dir + f)
os.rmdir(cls.temp_dir)
@classmethod
def exit_gracefully(cls, code=0):
''' Deletes temp and exist with the given code '''
cls.delete_temp()
Macchanger.reset_if_changed()
from .tools.airmon import Airmon
if cls.interface is not None and Airmon.base_interface is not None:
Color.pl('{!} {O}Note:{W} Leaving interface in Monitor Mode!')
Color.pl('{!} To disable Monitor Mode when finished: ' +
'{C}airmon-ng stop %s{W}' % cls.interface)
# Stop monitor mode
#Airmon.stop(cls.interface)
# Bring original interface back up
#Airmon.put_interface_up(Airmon.base_interface)
if Airmon.killed_network_manager:
Color.pl('{!} You can restart NetworkManager when finished ({C}service network-manager start{W})')
#Airmon.start_network_manager()
exit(code)
@classmethod
def dump(cls):
''' (Colorful) string representation of the configuration '''
from .util.color import Color
max_len = 20
for key in cls.__dict__.keys():
max_len = max(max_len, len(key))
result = Color.s('{W}%s Value{W}\n' % 'cls Key'.ljust(max_len))
result += Color.s('{W}%s------------------{W}\n' % ('-' * max_len))
for (key,val) in sorted(cls.__dict__.items()):
if key.startswith('__') or type(val) in [classmethod, staticmethod] or val is None:
continue
result += Color.s('{G}%s {W} {C}%s{W}\n' % (key.ljust(max_len),val))
return result
if __name__ == '__main__':
Configuration.initialize(False)
print(Configuration.dump())