Merge branch 'kimocoder-master'
This commit is contained in:
@@ -71,6 +71,15 @@ class Arguments(object):
|
|||||||
metavar="[num]",
|
metavar="[num]",
|
||||||
default=None,
|
default=None,
|
||||||
help=Color.s('Number of deauth packets to send (default: {G}%d{W})' % Configuration.num_deauths))
|
help=Color.s('Number of deauth packets to send (default: {G}%d{W})' % Configuration.num_deauths))
|
||||||
|
glob.add_argument('-p',
|
||||||
|
action='store',
|
||||||
|
dest='scan_time',
|
||||||
|
nargs='?',
|
||||||
|
const=10,
|
||||||
|
metavar='scantime',
|
||||||
|
type=int,
|
||||||
|
help=Color.s('{G}Pillage{W}: Attack all targets after {C}scantime{W} seconds'))
|
||||||
|
glob.add_argument('--pillage', help=argparse.SUPPRESS, action='store', dest='scan_time', nargs='?', const=10, type=int)
|
||||||
|
|
||||||
# WEP
|
# WEP
|
||||||
wep = parser.add_argument_group('WEP-RELATED')
|
wep = parser.add_argument_group('WEP-RELATED')
|
||||||
|
|||||||
@@ -34,6 +34,35 @@ class AttackWPA(Attack):
|
|||||||
self.success = False
|
self.success = False
|
||||||
return self.success
|
return self.success
|
||||||
|
|
||||||
|
handshake = None
|
||||||
|
|
||||||
|
# Capture the handshake ("do it live!")
|
||||||
|
if handshake is None:
|
||||||
|
handshake = self.capture_handshake()
|
||||||
|
|
||||||
|
if handshake is None:
|
||||||
|
# Failed to capture handshake
|
||||||
|
self.success = False
|
||||||
|
return self.success
|
||||||
|
|
||||||
|
# Analyze handshake
|
||||||
|
Color.pl('\n{+} analysis of captured handshake file:')
|
||||||
|
handshake.analyze()
|
||||||
|
|
||||||
|
# Crack it
|
||||||
|
key = self.crack_handshake(handshake, Configuration.wordlist)
|
||||||
|
if key is None:
|
||||||
|
self.success = False
|
||||||
|
else:
|
||||||
|
self.crack_result = CrackResultWPA(bssid, essid, handshake.capfile, key)
|
||||||
|
self.crack_result.dump()
|
||||||
|
self.success = True
|
||||||
|
return self.success
|
||||||
|
|
||||||
|
def capture_handshake(self):
|
||||||
|
''' Returns captured or stored handshake, otherwise None '''
|
||||||
|
handshake = None
|
||||||
|
|
||||||
# First, start Airodump process
|
# First, start Airodump process
|
||||||
with Airodump(channel=self.target.channel,
|
with Airodump(channel=self.target.channel,
|
||||||
target_bssid=self.target.bssid,
|
target_bssid=self.target.bssid,
|
||||||
@@ -46,7 +75,17 @@ class AttackWPA(Attack):
|
|||||||
|
|
||||||
self.clients = []
|
self.clients = []
|
||||||
|
|
||||||
handshake = None
|
bssid = airodump_target.bssid
|
||||||
|
essid = airodump_target.essid if airodump_target.essid_known else None
|
||||||
|
|
||||||
|
# Try to load existing handshake
|
||||||
|
if Configuration.ignore_old_handshakes == False:
|
||||||
|
handshake = self.load_handshake(bssid=bssid, essid=essid)
|
||||||
|
if handshake:
|
||||||
|
Color.clear_entire_line()
|
||||||
|
Color.pl('{+} found {G}existing handshake{W} for {C}%s{W}' % handshake.essid)
|
||||||
|
Color.pl('{+} from {C}%s{W}' % handshake.capfile)
|
||||||
|
return handshake
|
||||||
|
|
||||||
timeout_timer = Timer(Configuration.wpa_attack_timeout)
|
timeout_timer = Timer(Configuration.wpa_attack_timeout)
|
||||||
deauth_timer = Timer(Configuration.wpa_deauth_timeout)
|
deauth_timer = Timer(Configuration.wpa_deauth_timeout)
|
||||||
@@ -107,28 +146,14 @@ class AttackWPA(Attack):
|
|||||||
time.sleep(step_timer.remaining())
|
time.sleep(step_timer.remaining())
|
||||||
continue # Handshake listen+deauth loop
|
continue # Handshake listen+deauth loop
|
||||||
|
|
||||||
if not handshake:
|
if handshake is None:
|
||||||
# No handshake, attack failed.
|
# No handshake, attack failed.
|
||||||
Color.pl("\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds" % (Configuration.wpa_attack_timeout))
|
Color.pl("\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds" % (Configuration.wpa_attack_timeout))
|
||||||
self.success = False
|
return handshake
|
||||||
return self.success
|
else:
|
||||||
|
|
||||||
# Save copy of handshake to ./hs/
|
# Save copy of handshake to ./hs/
|
||||||
self.save_handshake(handshake)
|
self.save_handshake(handshake)
|
||||||
|
return handshake
|
||||||
# Print analysis of handshake file
|
|
||||||
Color.pl('\n{+} analysis of captured handshake file:')
|
|
||||||
handshake.analyze()
|
|
||||||
|
|
||||||
# Try to crack handshake
|
|
||||||
key = self.crack_handshake(handshake, Configuration.wordlist)
|
|
||||||
if key is None:
|
|
||||||
self.success = False
|
|
||||||
else:
|
|
||||||
self.crack_result = CrackResultWPA(bssid, essid, handshake.capfile, key)
|
|
||||||
self.crack_result.dump()
|
|
||||||
self.success = True
|
|
||||||
return self.success
|
|
||||||
|
|
||||||
def crack_handshake(self, handshake, wordlist):
|
def crack_handshake(self, handshake, wordlist):
|
||||||
'''Tries to crack a handshake. Returns WPA key if found, otherwise None.'''
|
'''Tries to crack a handshake. Returns WPA key if found, otherwise None.'''
|
||||||
@@ -200,6 +225,24 @@ class AttackWPA(Attack):
|
|||||||
" {O}%s{R} did not contain password{W}" % wordlist.split(os.sep)[-1])
|
" {O}%s{R} did not contain password{W}" % wordlist.split(os.sep)[-1])
|
||||||
return None
|
return None
|
||||||
|
|
||||||
|
def load_handshake(self, bssid, essid):
|
||||||
|
if not os.path.exists(Configuration.wpa_handshake_dir):
|
||||||
|
return None
|
||||||
|
|
||||||
|
if essid:
|
||||||
|
essid_safe = re.escape(re.sub('[^a-zA-Z0-9]', '', essid))
|
||||||
|
else:
|
||||||
|
essid_safe = '[a-zA-Z0-9]+'
|
||||||
|
bssid_safe = re.escape(bssid.replace(':', '-'))
|
||||||
|
date = '\d{4}-\d{2}-\d{2}T\d{2}-\d{2}-\d{2}'
|
||||||
|
get_filename = re.compile('handshake_%s_%s_%s\.cap' % (essid_safe, bssid_safe, date))
|
||||||
|
|
||||||
|
for filename in os.listdir(Configuration.wpa_handshake_dir):
|
||||||
|
cap_filename = os.path.join(Configuration.wpa_handshake_dir, filename)
|
||||||
|
if os.path.isfile(cap_filename) and re.match(get_filename, filename):
|
||||||
|
return Handshake(capfile=cap_filename, bssid=bssid, essid=essid)
|
||||||
|
|
||||||
|
return None
|
||||||
|
|
||||||
def save_handshake(self, handshake):
|
def save_handshake(self, handshake):
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -28,13 +28,15 @@ class Configuration(object):
|
|||||||
|
|
||||||
Configuration.verbose = 0 # Verbosity level.
|
Configuration.verbose = 0 # Verbosity level.
|
||||||
|
|
||||||
|
Configuration.scan_time = 0 # Time to wait before attacking all targets
|
||||||
|
Configuration.all_targets = False # Run attacks against all targets automatically
|
||||||
|
|
||||||
Configuration.tx_power = 0 # Wifi transmit power (0 is default)
|
Configuration.tx_power = 0 # Wifi transmit power (0 is default)
|
||||||
Configuration.interface = None
|
Configuration.interface = None
|
||||||
Configuration.target_channel = None # User-defined channel to scan
|
Configuration.target_channel = None # User-defined channel to scan
|
||||||
Configuration.target_essid = None # User-defined AP name
|
Configuration.target_essid = None # User-defined AP name
|
||||||
Configuration.target_bssid = None # User-defined AP BSSID
|
Configuration.target_bssid = None # User-defined AP BSSID
|
||||||
Configuration.five_ghz = False # Scan 5Ghz channels
|
Configuration.five_ghz = False # Scan 5Ghz channels
|
||||||
Configuration.pillage = False # "All" mode to attack everything
|
|
||||||
Configuration.random_mac = False # Should generate a random Mac address at startup.
|
Configuration.random_mac = False # Should generate a random Mac address at startup.
|
||||||
Configuration.no_deauth = False # Deauth hidden networks & WPA handshake targets
|
Configuration.no_deauth = False # Deauth hidden networks & WPA handshake targets
|
||||||
Configuration.num_deauths = 1 # Number of deauth packets to send to each target.
|
Configuration.num_deauths = 1 # Number of deauth packets to send to each target.
|
||||||
@@ -60,6 +62,7 @@ class Configuration(object):
|
|||||||
Configuration.wpa_attack_timeout = 500 # Wait time before failing
|
Configuration.wpa_attack_timeout = 500 # Wait time before failing
|
||||||
Configuration.wpa_handshake_dir = "hs" # Dir to store handshakes
|
Configuration.wpa_handshake_dir = "hs" # Dir to store handshakes
|
||||||
Configuration.wpa_strip_handshake = False # Strip non-handshake packets
|
Configuration.wpa_strip_handshake = False # Strip non-handshake packets
|
||||||
|
Configuration.ignore_old_handshakes = False # Always fetch a new handshake
|
||||||
|
|
||||||
# Default dictionary for cracking
|
# Default dictionary for cracking
|
||||||
Configuration.wordlist = None
|
Configuration.wordlist = None
|
||||||
@@ -138,6 +141,9 @@ class Configuration(object):
|
|||||||
if args.target_essid:
|
if args.target_essid:
|
||||||
Configuration.target_essid = args.target_essid
|
Configuration.target_essid = args.target_essid
|
||||||
Color.pl('{+} {C}option:{W} targeting ESSID {G}%s{W}' % args.target_essid)
|
Color.pl('{+} {C}option:{W} targeting ESSID {G}%s{W}' % args.target_essid)
|
||||||
|
if args.scan_time:
|
||||||
|
Configuration.scan_time = args.scan_time
|
||||||
|
Color.pl('{+} {C}option:{W} ({G}pillage{W}) attack all targets after {G}%d{W}s' % args.scan_time)
|
||||||
if args.verbose:
|
if args.verbose:
|
||||||
Configuration.verbose = args.verbose
|
Configuration.verbose = args.verbose
|
||||||
Color.pl('{+} {C}option:{W} verbosity level {G}%d{W}' % args.verbose)
|
Color.pl('{+} {C}option:{W} verbosity level {G}%d{W}' % args.verbose)
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ from Color import Color
|
|||||||
from Target import Target
|
from Target import Target
|
||||||
from Configuration import Configuration
|
from Configuration import Configuration
|
||||||
|
|
||||||
from time import sleep
|
from time import sleep, time
|
||||||
|
|
||||||
class Scanner(object):
|
class Scanner(object):
|
||||||
''' Scans wifi networks & provides menu for selecting targets '''
|
''' Scans wifi networks & provides menu for selecting targets '''
|
||||||
@@ -30,8 +30,9 @@ class Scanner(object):
|
|||||||
try:
|
try:
|
||||||
with Airodump() as airodump:
|
with Airodump() as airodump:
|
||||||
# Loop until interrupted (Ctrl+C)
|
# Loop until interrupted (Ctrl+C)
|
||||||
while True:
|
scan_start_time = time()
|
||||||
|
|
||||||
|
while True:
|
||||||
if airodump.pid.poll() is not None:
|
if airodump.pid.poll() is not None:
|
||||||
# Airodump process died
|
# Airodump process died
|
||||||
self.err_msg = '\r{!} {R}Airodump exited unexpectedly (Code: %d){O} Command: {W}%s' % (airodump.pid.poll(), " ".join(airodump.pid.command))
|
self.err_msg = '\r{!} {R}Airodump exited unexpectedly (Code: %d){O} Command: {W}%s' % (airodump.pid.poll(), " ".join(airodump.pid.command))
|
||||||
@@ -66,6 +67,10 @@ class Scanner(object):
|
|||||||
outline += " {G}%s{W}) " % ", ".join([x.essid for x in decloaked])
|
outline += " {G}%s{W}) " % ", ".join([x.essid for x in decloaked])
|
||||||
Color.clear_entire_line()
|
Color.clear_entire_line()
|
||||||
Color.p(outline)
|
Color.p(outline)
|
||||||
|
|
||||||
|
if Configuration.scan_time > 0 and time() > scan_start_time + Configuration.scan_time:
|
||||||
|
return
|
||||||
|
|
||||||
sleep(1)
|
sleep(1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
@@ -83,10 +88,10 @@ class Scanner(object):
|
|||||||
return False
|
return False
|
||||||
|
|
||||||
for target in self.targets:
|
for target in self.targets:
|
||||||
if bssid and bssid.lower() == target.bssid.lower():
|
if bssid and target.bssid and bssid.lower() == target.bssid.lower():
|
||||||
self.target = target
|
self.target = target
|
||||||
break
|
break
|
||||||
if essid and essid.lower() == target.essid.lower():
|
if essid and target.essid and essid.lower() == target.essid.lower():
|
||||||
self.target = target
|
self.target = target
|
||||||
break
|
break
|
||||||
|
|
||||||
@@ -159,6 +164,9 @@ class Scanner(object):
|
|||||||
+ " You may need to wait longer,"
|
+ " You may need to wait longer,"
|
||||||
+ " or you may have issues with your wifi card")
|
+ " or you may have issues with your wifi card")
|
||||||
|
|
||||||
|
if Configuration.scan_time > 0:
|
||||||
|
return self.targets
|
||||||
|
|
||||||
self.print_targets()
|
self.print_targets()
|
||||||
Color.clear_entire_line()
|
Color.clear_entire_line()
|
||||||
|
|
||||||
@@ -171,6 +179,7 @@ class Scanner(object):
|
|||||||
input_str += ' or {G}all{W}: '
|
input_str += ' or {G}all{W}: '
|
||||||
|
|
||||||
chosen_targets = []
|
chosen_targets = []
|
||||||
|
|
||||||
for choice in raw_input(Color.s(input_str)).split(','):
|
for choice in raw_input(Color.s(input_str)).split(','):
|
||||||
if choice == 'all':
|
if choice == 'all':
|
||||||
chosen_targets = self.targets
|
chosen_targets = self.targets
|
||||||
@@ -187,7 +196,6 @@ class Scanner(object):
|
|||||||
pass
|
pass
|
||||||
return chosen_targets
|
return chosen_targets
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
# Example displays targets and selects the appropriate one
|
# Example displays targets and selects the appropriate one
|
||||||
Configuration.initialize()
|
Configuration.initialize()
|
||||||
|
|||||||
Reference in New Issue
Block a user