Setting up Client, Target, and Airodump wrappers
Fixed bugs in Process and other related classes.
This commit is contained in:
152
py/Airodump.py
Normal file
152
py/Airodump.py
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
from Process import Process
|
||||||
|
from Configuration import Configuration
|
||||||
|
from Target import Target
|
||||||
|
from Client import Client
|
||||||
|
|
||||||
|
import os
|
||||||
|
|
||||||
|
class Airodump(object):
|
||||||
|
''' Wrapper around airodump-ng program '''
|
||||||
|
|
||||||
|
def __init__(self, interface, channel=None, encryption=None, wps=False):
|
||||||
|
''' Constructor, sets things up '''
|
||||||
|
self.targets = []
|
||||||
|
self.interface = interface
|
||||||
|
self.channel = channel
|
||||||
|
self.encryption = encryption
|
||||||
|
self.wps = wps
|
||||||
|
|
||||||
|
def __enter__(self):
|
||||||
|
'''
|
||||||
|
Setting things up for this context.
|
||||||
|
Called at start of 'with Airodump(...) as x:'
|
||||||
|
'''
|
||||||
|
self.delete_airodump_temp_files()
|
||||||
|
|
||||||
|
self.csv_file_prefix = Configuration.temp() + "airodump";
|
||||||
|
|
||||||
|
# Build the command
|
||||||
|
command = [
|
||||||
|
'airodump-ng',
|
||||||
|
self.interface,
|
||||||
|
'-a', # Only show associated clients
|
||||||
|
'-w', self.csv_file_prefix # Output file prefix
|
||||||
|
]
|
||||||
|
if self.channel:
|
||||||
|
command.extend(['-c', str(self.channel)])
|
||||||
|
if self.encryption:
|
||||||
|
command.extend(['--enc', self.encryption])
|
||||||
|
if self.wps:
|
||||||
|
command.extend(['--wps'])
|
||||||
|
|
||||||
|
# Start the process
|
||||||
|
self.pid = Process(command, devnull=True)
|
||||||
|
return self
|
||||||
|
|
||||||
|
|
||||||
|
def __exit__(self, type, value, traceback):
|
||||||
|
'''
|
||||||
|
Tearing things down since the context is being exited.
|
||||||
|
Called after 'with Airodump(...)' goes out of scope.
|
||||||
|
'''
|
||||||
|
# Kill the process
|
||||||
|
self.pid.interrupt()
|
||||||
|
self.pid.kill()
|
||||||
|
# Delete temp files
|
||||||
|
self.delete_airodump_temp_files()
|
||||||
|
|
||||||
|
def delete_airodump_temp_files(self):
|
||||||
|
''' Deletes airodump* files in the temp directory '''
|
||||||
|
for fil in os.listdir(Configuration.temp()):
|
||||||
|
if fil.startswith('airodump'):
|
||||||
|
os.remove(Configuration.temp() + fil)
|
||||||
|
|
||||||
|
def get_targets(self, wpa_wep_only=True):
|
||||||
|
''' 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('airodump') and fil.endswith('csv'):
|
||||||
|
# Found the file
|
||||||
|
csv_filename = Configuration.temp() + fil
|
||||||
|
break
|
||||||
|
if csv_filename == None or not os.path.exists(csv_filename):
|
||||||
|
# No file found
|
||||||
|
return self.targets
|
||||||
|
|
||||||
|
targets = []
|
||||||
|
|
||||||
|
# Parse the .CSV file
|
||||||
|
import csv
|
||||||
|
with open(csv_filename, 'rb') as csvopen:
|
||||||
|
csv_reader = csv.reader(csvopen, delimiter=',')
|
||||||
|
for row in csv_reader:
|
||||||
|
# Each "row" is a list of fields for a target/client
|
||||||
|
|
||||||
|
if len(row) == 0: continue
|
||||||
|
|
||||||
|
if row[0].strip() == 'BSSID':
|
||||||
|
# This is the "header" for the list of Targets
|
||||||
|
hit_clients = False
|
||||||
|
continue
|
||||||
|
|
||||||
|
elif row[0].strip() == 'Station MAC':
|
||||||
|
# This is the "header" for the list of Clients
|
||||||
|
hit_clients = True
|
||||||
|
continue
|
||||||
|
|
||||||
|
if hit_clients:
|
||||||
|
# The current row corresponds to a "Client" (computer)
|
||||||
|
client = Client(row)
|
||||||
|
|
||||||
|
if 'not associated' in client.bssid:
|
||||||
|
# Ignore unassociated clients
|
||||||
|
continue
|
||||||
|
|
||||||
|
# Add this client to the appropriate Target
|
||||||
|
for t in targets:
|
||||||
|
if t.bssid == client.bssid:
|
||||||
|
t.clients.append(client)
|
||||||
|
break
|
||||||
|
|
||||||
|
else:
|
||||||
|
# The current row corresponds to a "Target" (router)
|
||||||
|
target = Target(row)
|
||||||
|
|
||||||
|
if target.essid_len == 0:
|
||||||
|
# Ignore empty/blank ESSIDs
|
||||||
|
continue
|
||||||
|
|
||||||
|
if wpa_wep_only and 'WPA' not in target.encryption and 'WEP' not in target.encryption:
|
||||||
|
# Ignore non-WPA and non-WEP encrypted networks
|
||||||
|
continue
|
||||||
|
|
||||||
|
if self.encryption and self.encryption not in target.encryption:
|
||||||
|
# We're looking for a specific type of encryption
|
||||||
|
continue
|
||||||
|
|
||||||
|
targets.append(target)
|
||||||
|
|
||||||
|
# Sort by power
|
||||||
|
targets.sort(key=lambda x: x.power, reverse=True)
|
||||||
|
|
||||||
|
self.targets = targets
|
||||||
|
|
||||||
|
return self.targets
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
''' Example usage. wlan0mon should be in Monitor Mode '''
|
||||||
|
with Airodump('wlan0mon', channel=6) as airodump:
|
||||||
|
from time import sleep
|
||||||
|
|
||||||
|
sleep(7)
|
||||||
|
|
||||||
|
targets = airodump.get_targets()
|
||||||
|
for t in targets:
|
||||||
|
print 'Target>', t
|
||||||
|
|
||||||
|
Configuration.delete_temp()
|
||||||
|
|
||||||
@@ -1,19 +0,0 @@
|
|||||||
#!/usr/bin/python
|
|
||||||
|
|
||||||
class CapFile(object):
|
|
||||||
"""
|
|
||||||
Holds data about an access point's .cap file,
|
|
||||||
including filename, AP's ESSID & BSSID.
|
|
||||||
"""
|
|
||||||
def __init__(self, filename, ssid, bssid):
|
|
||||||
self.filename = filename
|
|
||||||
self.ssid = ssid
|
|
||||||
self.bssid = bssid
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return self.filename
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
|
||||||
c = CapFile("cap-01.cap", "My Router", "AA:BB:CC:DD:EE:FF")
|
|
||||||
print c
|
|
||||||
|
|
||||||
46
py/Client.py
46
py/Client.py
@@ -1,11 +1,41 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
class Client:
|
class Client(object):
|
||||||
"""
|
'''
|
||||||
Holds data for a Client (device connected to Access Point/Router)
|
Holds details for a "Client" - a wireless device (e.g. computer)
|
||||||
"""
|
that is associated with an Access Point (e.g. router)
|
||||||
|
'''
|
||||||
|
|
||||||
def __init__(self, bssid, station, power):
|
def __init__(self, fields):
|
||||||
self.bssid = bssid
|
'''
|
||||||
self.station = station
|
Initializes & stores client info based on fields.
|
||||||
self.power = power
|
Args:
|
||||||
|
Fields - List of strings
|
||||||
|
INDEX KEY
|
||||||
|
0 Station MAC (client's MAC address)
|
||||||
|
1 First time seen,
|
||||||
|
2 Last time seen,
|
||||||
|
3 Power,
|
||||||
|
4 # packets,
|
||||||
|
5 BSSID, (Access Point's MAC address)
|
||||||
|
6 Probed ESSIDs
|
||||||
|
'''
|
||||||
|
self.station = fields[0].strip()
|
||||||
|
self.power = int(fields[3].strip())
|
||||||
|
self.packets = int(fields[4].strip())
|
||||||
|
self.bssid = fields[5].strip()
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
''' String representation of a Client '''
|
||||||
|
result = ''
|
||||||
|
for (key,value) in self.__dict__.iteritems():
|
||||||
|
result += key + ': ' + str(value)
|
||||||
|
result += ','
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fields = '54:35:30:23:62:8E, 2015-05-27 19:43:47, 2015-05-27 19:43:47, -67, 2, (not associated) ,HOME-1102'.split(',')
|
||||||
|
c = Client(fields)
|
||||||
|
print c
|
||||||
|
|||||||
@@ -5,9 +5,10 @@ import os
|
|||||||
class Configuration(object):
|
class Configuration(object):
|
||||||
''' Stores configuration variables for Wifite. '''
|
''' Stores configuration variables for Wifite. '''
|
||||||
|
|
||||||
|
temp_dir = None
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self):
|
||||||
''' Sets up default initial configuration values '''
|
''' Sets up default initial configuration values '''
|
||||||
self.temp_dir = None # Temporary directory
|
|
||||||
|
|
||||||
self.version = 2.00 # Program version
|
self.version = 2.00 # Program version
|
||||||
self.tx_power = 0 # Wifi transmit power (0 is default)
|
self.tx_power = 0 # Wifi transmit power (0 is default)
|
||||||
@@ -64,13 +65,15 @@ class Configuration(object):
|
|||||||
if args.wordlist: self.wordlist = args.wordlist
|
if args.wordlist: self.wordlist = args.wordlist
|
||||||
|
|
||||||
|
|
||||||
def temp(self):
|
@staticmethod
|
||||||
|
def temp():
|
||||||
''' Creates and/or returns the temporary directory '''
|
''' Creates and/or returns the temporary directory '''
|
||||||
if self.temp_dir == None:
|
if Configuration.temp_dir == None:
|
||||||
self.temp_dir = self.create_temp()
|
Configuration.temp_dir = Configuration.create_temp()
|
||||||
return self.temp_dir
|
return Configuration.temp_dir
|
||||||
|
|
||||||
def create_temp(self):
|
@staticmethod
|
||||||
|
def create_temp():
|
||||||
''' Creates and returns a temporary directory '''
|
''' Creates and returns a temporary directory '''
|
||||||
from tempfile import mkdtemp
|
from tempfile import mkdtemp
|
||||||
tmp = mkdtemp(prefix='wifite')
|
tmp = mkdtemp(prefix='wifite')
|
||||||
@@ -78,13 +81,14 @@ class Configuration(object):
|
|||||||
tmp += os.sep
|
tmp += os.sep
|
||||||
return tmp
|
return tmp
|
||||||
|
|
||||||
def delete_temp(self):
|
@staticmethod
|
||||||
|
def delete_temp():
|
||||||
''' Remove temp files and folder '''
|
''' Remove temp files and folder '''
|
||||||
if self.temp_dir == None: return
|
if Configuration.temp_dir == None: return
|
||||||
if os.path.exists(self.temp_dir):
|
if os.path.exists(Configuration.temp_dir):
|
||||||
for f in os.listdir(self.temp_dir):
|
for f in os.listdir(Configuration.temp_dir):
|
||||||
os.remove(self.temp_dir + f)
|
os.remove(Configuration.temp_dir + f)
|
||||||
os.rmdir(self.temp_dir)
|
os.rmdir(Configuration.temp_dir)
|
||||||
|
|
||||||
|
|
||||||
def exit_gracefully(self, code=0):
|
def exit_gracefully(self, code=0):
|
||||||
|
|||||||
@@ -34,15 +34,20 @@ class Process(object):
|
|||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def __init__(self, command):
|
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
|
||||||
self.pid = Popen(command, stdout=PIPE, stderr=PIPE)
|
if devnull:
|
||||||
|
sout = Process.devnull()
|
||||||
|
serr = Process.devnull()
|
||||||
|
else:
|
||||||
|
sout = PIPE
|
||||||
|
serr = PIPE
|
||||||
|
self.pid = Popen(command, stdout=sout, stderr=serr)
|
||||||
|
|
||||||
def stdout(self):
|
def stdout(self):
|
||||||
''' Waits for process to finish, returns stdout output '''
|
''' Waits for process to finish, returns stdout output '''
|
||||||
|
|||||||
76
py/Target.py
Normal file
76
py/Target.py
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
#!/usr/bin/python
|
||||||
|
|
||||||
|
class Target(object):
|
||||||
|
'''
|
||||||
|
Holds details for a "Target" aka Access Point (e.g. router).
|
||||||
|
'''
|
||||||
|
|
||||||
|
def __init__(self, fields):
|
||||||
|
'''
|
||||||
|
Initializes & stores target info based on fields.
|
||||||
|
Args:
|
||||||
|
Fields - List of strings
|
||||||
|
INDEX KEY EXAMPLE
|
||||||
|
0 BSSID (00:1D:D5:9B:11:00)
|
||||||
|
1 First time seen (2015-05-27 19:28:43)
|
||||||
|
2 Last time seen (2015-05-27 19:28:46)
|
||||||
|
3 channel (6)
|
||||||
|
4 Speed (54)
|
||||||
|
5 Privacy (WPA2)
|
||||||
|
6 Cipher (CCMP TKIP)
|
||||||
|
7 Authentication (PSK)
|
||||||
|
8 Power (-62)
|
||||||
|
9 beacons (2)
|
||||||
|
10 # IV (0)
|
||||||
|
11 LAN IP (0. 0. 0. 0)
|
||||||
|
12 ID-length (9)
|
||||||
|
13 ESSID (HOME-ABCD)
|
||||||
|
14 Key ()
|
||||||
|
'''
|
||||||
|
self.bssid = fields[0].strip()
|
||||||
|
self.channel = fields[3].strip()
|
||||||
|
|
||||||
|
self.encryption = fields[5].strip()
|
||||||
|
if 'WPA' in self.encryption:
|
||||||
|
self.encryption = 'WPA'
|
||||||
|
elif 'WEP' in self.encryption:
|
||||||
|
self.encryption = 'WEP'
|
||||||
|
if len(self.encryption) > 4:
|
||||||
|
self.encryption = self.encryption[0:4].strip()
|
||||||
|
|
||||||
|
self.power = int(fields[8].strip())
|
||||||
|
if self.power < 0:
|
||||||
|
self.power += 100
|
||||||
|
|
||||||
|
self.beacons = int(fields[9].strip())
|
||||||
|
self.ivs = int(fields[10].strip())
|
||||||
|
|
||||||
|
self.essid_len = int(fields[12].strip())
|
||||||
|
self.essid = fields[13].strip()
|
||||||
|
if self.essid == '\\x00' * self.essid_len:
|
||||||
|
# Don't display "\x00..." for hidden ESSIDs
|
||||||
|
self.essid = '(hidden, length: %s)' % self.essid_len
|
||||||
|
|
||||||
|
self.clients = []
|
||||||
|
|
||||||
|
|
||||||
|
def __str__(self):
|
||||||
|
''' String representation of this Target '''
|
||||||
|
result = ''
|
||||||
|
for (key,value) in self.__dict__.iteritems():
|
||||||
|
if key == 'clients': continue
|
||||||
|
result += key + ': ' + str(value)
|
||||||
|
result += ', '
|
||||||
|
for client in self.clients:
|
||||||
|
result += 'client: %s' % client.station
|
||||||
|
result += ','
|
||||||
|
if result.endswith(', '):
|
||||||
|
result = result[:-2]
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
fields = '00:AC:E0:71:74:E0, 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-74E2, '.split(',')
|
||||||
|
t = Target(fields)
|
||||||
|
print t
|
||||||
|
|
||||||
Reference in New Issue
Block a user