From 080e674aa6044b60b04d74c51566d03c37fce86d Mon Sep 17 00:00:00 2001 From: derv82 Date: Tue, 27 Feb 2018 04:09:46 -0500 Subject: [PATCH] Remove dependency on Wash; detect WPS via Tshark. Should resolve #62 --- README.md | 2 +- TODO.md | 16 +++++ py/Airodump.py | 16 ++--- py/AttackWEP.py | 2 +- py/AttackWPA.py | 2 +- py/Bully.py | 2 +- py/Client.py | 13 ++-- py/Reaver.py | 4 +- py/Tshark.py | 83 ++++++++++++++++++++++++ py/Wash.py | 56 ---------------- py/tests/files/contains_wps_network.cap | Bin 0 -> 10536 bytes 11 files changed, 122 insertions(+), 74 deletions(-) create mode 100644 py/Tshark.py delete mode 100644 py/Wash.py create mode 100644 py/tests/files/contains_wps_network.cap diff --git a/README.md b/README.md index ddb273e..5a07a66 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Support ------- Wifite2 is designed entirely for the latest version of Kali Rolling release (tested on Kali 2016.2, updated May 2017). -This means only the latest versions of these programs are supported: Aircrack-ng suite, wash, reaver, tshark, cowpatty. +This means only the latest versions of these programs are supported: Aircrack-ng suite, reaver, tshark, cowpatty. Other pen-testing distributions (such as BackBox) have outdated versions of these suites; these distributions are not supported. diff --git a/TODO.md b/TODO.md index d4f828a..884d901 100644 --- a/TODO.md +++ b/TODO.md @@ -57,6 +57,22 @@ TSHARK * DIY: Extract Beacon frames from the .cap file with WPS flags... * `tshark -r f.cap -R "wps.primary_device_type.category == 6" -n -2` +We can extract WPS networks' BSSID and WPS lock status: + +```bash +% tshark -r withwps-01.cap -n -Y "wps.wifi_protected_setup_state && wlan.da == ff:ff:ff:ff:ff:ff" -T fields -e wlan.ta -e wps.ap_setup_locked -E separator=, +# Output: +88:ad:43:d2:77:c8, +18:d6:c7:6d:6b:18, +f4:f2:6d:9e:34:25, +fc:51:a4:1e:11:67, +98:e7:f4:90:f1:12,0x00000001 +10:13:31:30:35:2c, +60:a4:4c:6a:46:b0, +c0:7c:d1:6f:a2:c8, +f8:cf:c5:fb:a3:e2, +``` + ------------------------------------------------------ ### Backwards Compatibility diff --git a/py/Airodump.py b/py/Airodump.py index c8814e7..6de6f54 100644 --- a/py/Airodump.py +++ b/py/Airodump.py @@ -5,7 +5,7 @@ from Process import Process from Configuration import Configuration from Target import Target from Client import Client -from Wash import Wash +from Tshark import Tshark import os, time @@ -14,7 +14,7 @@ class Airodump(object): def __init__(self, interface=None, channel=None, encryption=None,\ wps=False, target_bssid=None, output_file_prefix='airodump',\ - ivs_only=False, skip_wash=False): + ivs_only=False, skip_wps=False): ''' Sets up airodump arguments, doesn't start process yet ''' @@ -40,7 +40,7 @@ class Airodump(object): self.target_bssid = target_bssid self.output_file_prefix = output_file_prefix self.ivs_only = ivs_only - self.skip_wash = skip_wash + self.skip_wps = skip_wps # For tracking decloaked APs (previously were hidden) self.decloaking = False @@ -139,13 +139,13 @@ class Airodump(object): targets = Airodump.get_targets_from_csv(csv_filename) # Check targets for WPS - if not self.skip_wash: + if not self.skip_wps: capfile = csv_filename[:-3] + 'cap' - Wash.check_for_wps_and_update_targets(capfile, targets) + Tshark.check_for_wps_and_update_targets(capfile, targets) if apply_filter: # Filter targets based on encryption & WPS capability - targets = Airodump.filter_targets(targets, skip_wash=self.skip_wash) + targets = Airodump.filter_targets(targets, skip_wps=self.skip_wps) # Sort by power targets.sort(key=lambda x: x.power, reverse=True) @@ -218,7 +218,7 @@ class Airodump(object): return targets @staticmethod - def filter_targets(targets, skip_wash=False): + def filter_targets(targets, skip_wps=False): ''' Filters targets based on Configuration ''' result = [] # Filter based on Encryption @@ -229,7 +229,7 @@ class Airodump(object): result.append(target) elif 'WPS' in Configuration.encryption_filter and target.wps: result.append(target) - elif skip_wash: + elif skip_wps: result.append(target) # Filter based on BSSID/ESSID diff --git a/py/AttackWEP.py b/py/AttackWEP.py index c3bc48f..d6d77af 100644 --- a/py/AttackWEP.py +++ b/py/AttackWEP.py @@ -44,7 +44,7 @@ class AttackWEP(Attack): with Airodump(channel=self.target.channel, target_bssid=self.target.bssid, ivs_only=True, # Only capture IVs packets - skip_wash=True, # Don't check for WPS-compatibility + skip_wps=True, # Don't check for WPS-compatibility output_file_prefix='wep') as airodump: Color.clear_line() diff --git a/py/AttackWPA.py b/py/AttackWPA.py index 114b64d..9da7350 100644 --- a/py/AttackWPA.py +++ b/py/AttackWPA.py @@ -37,7 +37,7 @@ class AttackWPA(Attack): # First, start Airodump process with Airodump(channel=self.target.channel, target_bssid=self.target.bssid, - skip_wash=True, + skip_wps=True, output_file_prefix='wpa') as airodump: Color.clear_entire_line() diff --git a/py/Bully.py b/py/Bully.py index c860b7e..8940174 100644 --- a/py/Bully.py +++ b/py/Bully.py @@ -50,7 +50,7 @@ class Bully(Attack): def run(self): with Airodump(channel=self.target.channel, target_bssid=self.target.bssid, - skip_wash=True, + skip_wps=True, output_file_prefix='wps_pin') as airodump: # Wait for target Color.clear_entire_line() diff --git a/py/Client.py b/py/Client.py index 51a6918..2ae4b5c 100644 --- a/py/Client.py +++ b/py/Client.py @@ -21,10 +21,15 @@ class Client(object): 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() + try: + self.station = fields[0].strip() + self.power = int(fields[3].strip()) + self.packets = int(fields[4].strip()) + self.bssid = fields[5].strip() + except ValueError, e: + print "\nValueError ({})".format(e) + print "\twhile parsing {}".format(fields) + raise e def __str__(self): diff --git a/py/Reaver.py b/py/Reaver.py index f73f560..329647c 100644 --- a/py/Reaver.py +++ b/py/Reaver.py @@ -73,7 +73,7 @@ class Reaver(Attack): with Airodump(channel=self.target.channel, target_bssid=self.target.bssid, - skip_wash=True, + skip_wps=True, output_file_prefix='pixie') as airodump: Color.clear_line() @@ -210,7 +210,7 @@ class Reaver(Attack): with Airodump(channel=self.target.channel, target_bssid=self.target.bssid, - skip_wash=True, + skip_wps=True, output_file_prefix='wps') as airodump: Color.clear_line() diff --git a/py/Tshark.py b/py/Tshark.py new file mode 100644 index 0000000..9713f04 --- /dev/null +++ b/py/Tshark.py @@ -0,0 +1,83 @@ +#!/usr/bin/python2.7 +# -*- coding: utf-8 -*- + +from Process import Process +import re + +class Tshark(object): + ''' Wrapper for Tshark program. ''' + + def __init__(self): + pass + + @staticmethod + def check_for_wps_and_update_targets(capfile, targets): + ''' + Given a cap file and list of targets, use TShark to + find which BSSIDs in the cap file use WPS. + Then update the 'wps' flag for those BSSIDs in the targets. + + Args: + capfile - .cap file from airodump containing packets + targets - list of Targets from scan, to be updated + ''' + # Tshark is required to detect WPS networks + if not Process.exists('tshark'): + return + + command = [ + 'tshark', + '-r', capfile, # Path to cap file + '-n', # Don't resolve addresses + # Filter WPS broadcast packets + '-Y', 'wps.wifi_protected_setup_state && wlan.da == ff:ff:ff:ff:ff:ff', + '-T', 'fields', # Only output certain fields + '-e', 'wlan.ta', # BSSID + '-e', 'wps.ap_setup_locked', # Locked status + '-E', 'separator=,' # CSV + ] + p = Process(command) + + + try: + p.wait() + lines = p.stdout() + except: + # Failure is acceptable + return + + bssids = set() + for line in lines.split('\n'): + if ',' not in line: + continue + bssid, locked = line.split(',') + # TODO: Ignore if WPS is locked? + bssids.add(bssid.upper()) + + for t in targets: + t.wps = t.bssid.upper() in bssids + + +if __name__ == '__main__': + test_file = './tests/files/contains_wps_network.cap' + + target_bssid = 'A4:2B:8C:16:6B:3A' + from Target import Target + fields = [ + 'A4:2B:8C:16:6B:3A', # BSSID + '2015-05-27 19:28:44', '2015-05-27 19:28:46', # Dates + '11', # Channel + '54', # throughput + 'WPA2', 'CCMP TKIP', 'PSK', # AUTH + '-58', '2', '0', '0.0.0.0', '9', # ??? + 'Test Router Please Ignore', # SSID + ] + t = Target(fields) + targets = [t] + + # Should update 'wps' field of a target + Tshark.check_for_wps_and_update_targets(test_file, targets) + + print 'Target(BSSID={}).wps = {} (Expected: True)'.format(targets[0].bssid, targets[0].wps) + assert targets[0].wps == True + diff --git a/py/Wash.py b/py/Wash.py deleted file mode 100644 index 6256d71..0000000 --- a/py/Wash.py +++ /dev/null @@ -1,56 +0,0 @@ -#!/usr/bin/python2.7 -# -*- coding: utf-8 -*- - -from Process import Process -import re - -class Wash(object): - ''' Wrapper for Wash program. ''' - BSSID_REGEX = re.compile("([A-F0-9\:]{17})", re.IGNORECASE) - - def __init__(self): - pass - - @staticmethod - def check_for_wps_and_update_targets(capfile, targets): - ''' - Given a cap file and list of targets, use Wash to - find which BSSIDs in the cap file use WPS. - Then update the 'wps' flag for those BSSIDs in the targets. - - Args: - capfile - .cap file from airodump containing packets - targets - list of Targets from scan, to be updated - ''' - # Wash/Walsh is required to detect WPS - wash_name = 'wash' - if not Process.exists(wash_name): - wash_name = 'walsh' - if not Process.exists(wash_name): - # Wash isn't found, drop out - return - - command = [ - 'wash', - '-f', capfile # Path to cap file - ] - p = Process(command) - - p.wait() - if p.poll() != 0: - return - - bssids = [bssid.upper() for bssid in Wash.BSSID_REGEX.findall(p.stdout())] - for t in targets: - t.wps = t.bssid.upper() in bssids - - -if __name__ == '__main__': - from Target import Target - # Test target within range - fields = 'A4:2B:8C:16:6B:3A,2015-05-27 19:28:44,2015-05-27 19:28:46,11,54,WPA2,CCMP TKIP,PSK,-58,2,0,0.0.0.0,9,Test Router Please Ignore,'.split(',') - t = Target(fields) - targets = [t] - Wash.check_for_wps_and_update_targets('./tests/files/handshake_exists.cap', targets) - print targets[0].bssid, 'WPS =', targets[0].wps - diff --git a/py/tests/files/contains_wps_network.cap b/py/tests/files/contains_wps_network.cap new file mode 100644 index 0000000000000000000000000000000000000000..b6001fa39ce1998a01394398ac077f9fc9df151c GIT binary patch literal 10536 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