From 20ea673a3d16bc6fe4834f83f6d74a44363566db Mon Sep 17 00:00:00 2001 From: derv82 Date: Fri, 6 Apr 2018 18:44:46 -0400 Subject: [PATCH] 2.1.2: Quiet decloak. Support ESSIDs with commas and trailing spaces Decloaked ESSIDs will have a "*" next to their name. For #78 While testing, I found that Wifite did not parse Airodump's CSV correctly. Specifically, ESSIDs with commas or trailing spaces. Fixed in this commit. Also fixed hidden ESSID detection introduced by the new CSV parsing logic. --- tests/files/airodump-weird-ssids.csv | 13 +++++++ tests/test_Airodump.py | 52 ++++++++++++++++++++++++++++ wifite/config.py | 2 +- wifite/model/target.py | 14 ++++++-- wifite/tools/airodump.py | 12 ++++--- wifite/util/scanner.py | 9 +++-- 6 files changed, 89 insertions(+), 13 deletions(-) create mode 100644 tests/files/airodump-weird-ssids.csv create mode 100644 tests/test_Airodump.py diff --git a/tests/files/airodump-weird-ssids.csv b/tests/files/airodump-weird-ssids.csv new file mode 100644 index 0000000..ac57f39 --- /dev/null +++ b/tests/files/airodump-weird-ssids.csv @@ -0,0 +1,13 @@ + +BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key +AA:BB:CC:DD:EE:FF, 2018-04-06 18:21:23, 2018-04-06 18:21:24, 10, 54, WPA2, CCMP,PSK, -34, 5, 0, 0. 0. 0. 0, 24, Comma\, no trailing space, +AA:BB:CC:DD:EE:FF, 2018-04-06 18:19:17, 2018-04-06 18:19:19, 10, 54, WPA2, CCMP,PSK, -35, 18, 0, 0. 0. 0. 0, 20, \"Quoted ESSID\, Comma\, no trailing spaces. \", +AA:BB:CC:DD:EE:FF, 2018-04-06 18:35:29, 2018-04-06 18:35:30, 10, 54, WPA2, CCMP,PSK, -31, 12, 0, 0. 0. 0. 0, 22, "Comma\, Trailing space ", +AA:BB:CC:DD:EE:FF, 2018-04-06 18:22:45, 2018-04-06 18:22:46, 10, 54, WPA2, CCMP,PSK, -29, 15, 0, 0. 0. 0. 0, 30, "\"quote\" comma\, trailing space ", +AA:BB:CC:DD:EE:FF, 2018-04-06 18:50:11, 2018-04-06 18:50:17, 10, 54, WPA2, CCMP,PSK, -20, 43, 0, 0. 0. 0. 0, 19, \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00, + + + + +Station MAC, First time seen, Last time seen, Power, # packets, BSSID, Probed ESSIDs + diff --git a/tests/test_Airodump.py b/tests/test_Airodump.py new file mode 100644 index 0000000..5d085b6 --- /dev/null +++ b/tests/test_Airodump.py @@ -0,0 +1,52 @@ +#!/usr/bin/python2.7 +# -*- coding: utf-8 -*- + +import sys +sys.path.insert(0, '..') + +from wifite.tools.airodump import Airodump + +import unittest + +class TestAirodump(unittest.TestCase): + ''' Test suite for Wifite's interaction with the Airodump tool ''' + + + def test_airodump_weird_characters(self): + csv_filename = self.getFile('airodump-weird-ssids.csv') + targets = Airodump.get_targets_from_csv(csv_filename) + + target = targets[0] + expected = 'Comma, no trailing space' + assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid) + + target = targets[1] + expected = '"Quoted ESSID, Comma, no trailing spaces. "' + assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid) + + target = targets[2] + expected = 'Comma, Trailing space ' + assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid) + + target = targets[3] + expected = '"quote" comma, trailing space ' + assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid) + + # Hidden access point + target = targets[4] + assert target.essid_known == False, 'ESSID full of null characters should not be known' + expected = None + assert target.essid == expected, 'Expected ESSID (%s) but got (%s)' % (expected, target.essid) + assert target.essid_len == 19, 'ESSID length shold be 19, but got %s' % target.essid_len + + + def getFile(self, filename): + ''' Helper method to parse targets from filename ''' + import os, inspect + this_file = os.path.abspath(inspect.getsourcefile(self.getFile)) + this_dir = os.path.dirname(this_file) + return os.path.join(this_dir, 'files', filename) + + +if __name__ == '__main__': + unittest.main() diff --git a/wifite/config.py b/wifite/config.py index 225a36e..d434de1 100755 --- a/wifite/config.py +++ b/wifite/config.py @@ -12,7 +12,7 @@ class Configuration(object): initialized = False # Flag indicating config has been initialized temp_dir = None # Temporary directory - version = '2.1.1' + version = '2.1.2' @staticmethod def initialize(load_interface=True): diff --git a/wifite/model/target.py b/wifite/model/target.py index 3d79c87..e7648d7 100755 --- a/wifite/model/target.py +++ b/wifite/model/target.py @@ -52,14 +52,18 @@ class Target(object): self.essid_known = True self.essid_len = int(fields[12].strip()) - self.essid = fields[13].strip() - if self.essid == '\\x00' * self.essid_len or self.essid.strip() == '': + self.essid = fields[13] + if self.essid == '\\x00' * self.essid_len or \ + self.essid == 'x00' * self.essid_len or \ + self.essid.strip() == '': # Don't display "\x00..." for hidden ESSIDs self.essid = None # '(%s)' % self.bssid self.essid_known = False self.wps = None + self.decloaked = False # If ESSID was hidden but we decloaked it. + self.clients = [] self.validate() @@ -84,7 +88,7 @@ class Target(object): Specifically formatted for the "scanning" table view. ''' - max_essid_len = 25 + max_essid_len = 24 essid = self.essid if self.essid_known else "(%s)" % self.bssid # Trim ESSID (router name) if needed if len(essid) > max_essid_len: @@ -99,6 +103,10 @@ class Target(object): # Unknown ESSID essid = Color.s("{O}%s" % essid) + # Add a "*" if we decloaked the ESSID + decloaked_char = '*' if self.decloaked else ' ' + essid += Color.s("{P}%s" % decloaked_char) + if show_bssid: bssid = Color.s('{O}%s ' % self.bssid) else: diff --git a/wifite/tools/airodump.py b/wifite/tools/airodump.py index 91786c0..ccfa72d 100755 --- a/wifite/tools/airodump.py +++ b/wifite/tools/airodump.py @@ -45,7 +45,7 @@ class Airodump(object): # For tracking decloaked APs (previously were hidden) self.decloaking = False - self.decloaked_targets = [] + self.decloaked_bssids = set() self.decloaked_times = {} # Map of BSSID(str) -> epoch(int) of last deauth @@ -161,7 +161,8 @@ class Airodump(object): if old_target.bssid != new_target.bssid: continue if new_target.essid_known and not old_target.essid_known: # We decloaked a target! - self.decloaked_targets.append(new_target) + new_target.decloaked = True + self.decloaked_bssids.add(new_target.bssid) if self.pid.poll() is not None: raise Exception('Airodump has stopped') @@ -185,7 +186,11 @@ class Airodump(object): if type(line) is bytes: line = line.decode('utf-8') line = line.replace('\0', '') lines.append(line) - csv_reader = csv.reader(lines, delimiter=',') + csv_reader = csv.reader(lines, + delimiter=',', + quoting=csv.QUOTE_ALL, + skipinitialspace=True, + escapechar='\\') hit_clients = False for row in csv_reader: @@ -317,4 +322,3 @@ if __name__ == '__main__': Color.pl(' {G}%s %s' % (str(idx).rjust(3), target.to_str())) Configuration.delete_temp() - diff --git a/wifite/util/scanner.py b/wifite/util/scanner.py index 8162c71..ae45049 100755 --- a/wifite/util/scanner.py +++ b/wifite/util/scanner.py @@ -48,6 +48,10 @@ class Scanner(object): # We found the target we want return + for target in self.targets: + if target.bssid in airodump.decloaked_bssids: + target.decloaked = True + self.print_targets() target_count = len(self.targets) @@ -61,11 +65,6 @@ class Scanner(object): outline += " {G}%d{W} target(s)," % target_count outline += " {G}%d{W} client(s)." % client_count outline += " {O}Ctrl+C{W} when ready " - decloaked = airodump.decloaked_targets - if len(decloaked) > 0: - outline += "(decloaked" - outline += " {C}%d{W} ESSIDs:" % len(decloaked) - outline += " {G}%s{W}) " % ", ".join([x.essid for x in decloaked]) Color.clear_entire_line() Color.p(outline)