Merge branch 'kimocoder-master'

This commit is contained in:
derv82
2018-02-27 20:39:00 -05:00
4 changed files with 93 additions and 27 deletions

View File

@@ -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')

View File

@@ -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):
''' '''

View File

@@ -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)

View File

@@ -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()