diff --git a/py/AttackWPA.py b/py/AttackWPA.py index 00f19cf..6cdf7b1 100644 --- a/py/AttackWPA.py +++ b/py/AttackWPA.py @@ -29,7 +29,8 @@ class AttackWPA(Attack): output_file_prefix='wpa') as airodump: Color.clear_line() - Color.p('\r{+} {O}waiting{W} for target to appear...') + Color.p('\r{+} {C}WPA-handshake attack{W}: ') + Color.p('{O}waiting{W} for target to appear...') airodump_target = self.wait_for_target(airodump) # Get client station MAC addresses @@ -45,8 +46,9 @@ class AttackWPA(Attack): while True: if not deauth_proc or deauth_proc.poll() != None: # Clear line only if we're not deauthing right now - Color.p('\r%s\r' % (' ' * 70)) - Color.p('\r{+} waiting for {C}handshake{W}...') + Color.p('\r%s\r' % (' ' * 90)) + Color.p('\r{+} {C}WPA-handshake attack{W}: ') + Color.p('waiting for {C}handshake{W}...') time.sleep(1) @@ -81,8 +83,7 @@ class AttackWPA(Attack): for client in airodump_target.clients: if client.station not in clients: Color.pl('\r{+} discovered {G}client{W}:' + - ' {C}%s{W}' % client.station) - Color.p(' ' * len(' [+] waiting for handshake... ')) + ' {C}%s{W}%s' % (client.station, ' ' * 10)) clients.append(client.station) # Send deauth to a client or broadcast @@ -182,7 +183,7 @@ class AttackWPA(Attack): Color.p('{+} saving copy of {C}handshake{W} to {C}%s{W} ' % cap_filename) copy(handshake.capfile, cap_filename) - Color.pl(' {G}saved{W}') + Color.pl('{G}saved{W}') # Update handshake to use the stored handshake file for future operations handshake.capfile = cap_filename diff --git a/py/AttackWPS.py b/py/AttackWPS.py index c69eb9c..a747a92 100644 --- a/py/AttackWPS.py +++ b/py/AttackWPS.py @@ -74,7 +74,7 @@ class AttackWPS(Attack): while True: time.sleep(1) Color.clear_line() - Color.p('\r{+} {C}WPS pixiedust attack{W}: ') + Color.p('\r{+} {C}WPS pixie-dust attack{W} ') stdout_write.flush() @@ -96,51 +96,69 @@ class AttackWPS(Attack): if pin and psk and ssid: # We cracked it. bssid = self.target.bssid - Color.pl('{G}success{W}\n') + Color.pl('\n\n{+} {G}successfully cracked WPS PIN and PSK{W}\n') self.crack_result = CrackResultWPS(bssid, ssid, pin, psk) self.crack_result.dump() - self.success = True + return True else: # Failed to crack, reaver proces ended. Color.pl('{R}failed: {O}WPS pin not found{W}') - self.success = False - break + return False # Status updates, depending on last line of stdout if 'Waiting for beacon from' in stdout_last_line: - step = '(step 1/8) initialized, waiting for beacon to associate' + step = '({C}step 1/8{W}) waiting for beacon' elif 'Associated with' in stdout_last_line: - step = '(step 2/8) associated, waiting to start session' + step = '({C}step 2/8{W}) waiting to start session' elif 'Starting Cracking Session.' in stdout_last_line: - step = '(step 3/8) started session, waiting to try pin' + step = '({C}step 3/8{W}) waiting to try pin' elif 'Trying pin' in stdout_last_line: - step = '(step 4/8) trying pin' + step = '({C}step 4/8{W}) trying pin' elif 'Sending EAPOL START request' in stdout_last_line: - step = '(step 5/8) sending eapol start request' + step = '({C}step 5/8{W}) sending eapol start request' elif 'Sending identity response' in stdout_last_line: - step = '(step 6/8) sending identity response' + step = '({C}step 6/8{W}) sending identity response' elif 'Sending M2 message' in stdout_last_line: - step = '(step 7/8) sending m2 message (may take a while)' + step = '({C}step 7/8{W}) sending m2 message (may take a while)' elif 'Detected AP rate limiting,' in stdout_last_line: - step = '(step 0/8) waiting for AP rate limit' + if Configuration.wps_skip_rate_limit: + Color.pl('{R}failed: {O}hit WPS rate-limit{W}') + # TODO: Argument for --ignore-rate-limit + ''' + Color.pl('{!} {O}use {R}--ignore-rate-limit{O} to ignore' + + ' this kind of failure in the future') + ''' + break + step = '({C}step -/8{W}) waiting for AP rate limit' if 'WPS pin not found' in stdout: - # Attack failed; PIN not found. Color.pl('{R}failed: {O}WPS pin not found{W}') - reaver.interrupt() - return False + break + # TODO: Timeout check + if reaver.running_time() > Configuration.wps_timeout: + Color.pl('{R}failed: {O}timeout after %d seconds{W}' % Configuration.wps_timeout) + break + + # Reaver Failure/Timeout check fail_count = stdout.count('WPS transaction failed') + if fail_count > Configuration.wps_fail_threshold: + Color.pl('{R}failed: {O}too many failures (%d){W}' % fail_count) + break timeout_count = stdout.count('Receive timeout occurred') + if timeout_count > Configuration.wps_timeout_threshold: + Color.pl('{R}failed: {O}too many timeouts (%d){W}' % timeout_count) + break # Display status of Pixie-Dust attack Color.p('{W}%s{W}' % step) continue + # Attack failed, already printed reason why reaver.interrupt() stdout_write.close() - return self.success + return False @staticmethod diff --git a/py/Configuration.py b/py/Configuration.py index c214b4f..cac9093 100644 --- a/py/Configuration.py +++ b/py/Configuration.py @@ -82,8 +82,9 @@ class Configuration(object): Configuration.pixie_only = False # ONLY use Pixie-Dust attack on WPS Configuration.wps_timeout = 600 # Seconds to wait before failing Configuration.wps_max_retries = 20 # Retries before failing - Configuration.fail_threshold = 30 # Max number of failures - Configuration.timeout_threshold = 30 # Max number of timeouts + Configuration.wps_fail_threshold = 30 # Max number of failures + Configuration.wps_timeout_threshold = 30 # Max number of timeouts + Configuration.wps_skip_rate_limit = True # Skip rate-limited WPS APs # Overwrite config values with arguments (if defined) Configuration.load_from_arguments() @@ -96,14 +97,17 @@ class Configuration(object): ''' Sets configuration values based on Argument.args object ''' if args.channel: Configuration.target_channel = args.channel if args.interface: Configuration.interface = args.interface + if args.wep_filter: Configuration.wep_filter = args.wep_filter + if args.require_fakeauth: Configuration.require_fakeauth = False + if args.wpa_filter: Configuration.wpa_filter = args.wpa_filter + if args.wordlist: Configuration.wordlist = args.wordlist + if args.wps_filter: Configuration.wps_filter = args.wps_filter if args.no_reaver: Configuration.no_reaver = args.no_reaver if args.reaver_only: Configuration.reaver_only = args.reaver_only if args.pixie_only: Configuration.pixie_only = args.pixie_only - if args.wordlist: Configuration.wordlist = args.wordlist - if args.require_fakeauth: Configuration.require_fakeauth = False # Adjust encryption filter if Configuration.wep_filter or \ @@ -111,7 +115,6 @@ class Configuration(object): Configuration.wps_filter: # Reset filter Configuration.encryption_filter = [] - if Configuration.wep_filter: Configuration.encryption_filter.append('WEP') if Configuration.wpa_filter: Configuration.encryption_filter.append('WPA') if Configuration.wps_filter: Configuration.encryption_filter.append('WPS')