diff --git a/py/Handshake.py b/py/Handshake.py index 00a7a80..6b18f27 100644 --- a/py/Handshake.py +++ b/py/Handshake.py @@ -273,22 +273,22 @@ class Handshake(object): return [] def analyze(self): - hs.divine_bssid_and_essid() + self.divine_bssid_and_essid() - pairs = hs.tshark_handshakes() - Handshake.print_pairs(pairs, 'tshark') + pairs = self.tshark_handshakes() + Handshake.print_pairs(pairs, self.capfile, 'tshark') - pairs = hs.pyrit_handshakes() - Handshake.print_pairs(pairs, 'pyrit') + pairs = self.pyrit_handshakes() + Handshake.print_pairs(pairs, self.capfile, 'pyrit') - pairs = hs.cowpatty_handshakes() - Handshake.print_pairs(pairs, 'cowpatty') + pairs = self.cowpatty_handshakes() + Handshake.print_pairs(pairs, self.capfile, 'cowpatty') - pairs = hs.aircrack_handshakes() - Handshake.print_pairs(pairs, 'aircrack') + pairs = self.aircrack_handshakes() + Handshake.print_pairs(pairs, self.capfile, 'aircrack') @staticmethod - def print_pairs(pairs, tool=None): + def print_pairs(pairs, capfile, tool=None): ''' Prints out BSSID and/or ESSID given a list of tuples (bssid,essid) ''' @@ -298,19 +298,19 @@ class Handshake(object): if len(pairs) == 0: Color.pl("{!} %s%s {R}does not{O} contain a handshake{W}" - % (tool_str,hs.capfile)) + % (tool_str, capfile)) return for (bssid, essid) in pairs: if bssid and essid: Color.pl("{+} %s%s {G}contains a handshake{W} for {G}%s{W} ({G}%s{W})" - % (tool_str, hs.capfile, bssid, essid)) + % (tool_str, capfile, bssid, essid)) elif bssid: Color.pl("{+} %s%s {G}contains a handshake{W} for {G}%s{W}" - % (tool_str, hs.capfile, bssid)) + % (tool_str, capfile, bssid)) elif essid: Color.pl("{+} %s%s {G}contains a handshake{W} for ({G}%s{W})" - % (tool_str, hs.capfile, essid)) + % (tool_str, capfile, essid)) diff --git a/py/tests/__init__.py b/py/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/py/tests/files/airmon.output b/py/tests/files/airmon.output new file mode 100644 index 0000000..350b1b5 --- /dev/null +++ b/py/tests/files/airmon.output @@ -0,0 +1,8 @@ +No interfering processes found +PHY Interface Driver Chipset + +phy2 wlan0 rtl8187 Realtek Semiconductor Corp. RTL8187 + (mac80211 monitor mode vif enabled for [phy2]wlan0 on [phy2]wlan0mon) + (mac80211 station mode vif disabled for [phy2]wlan0) + + diff --git a/py/tests/files/airodump.csv b/py/tests/files/airodump.csv new file mode 100644 index 0000000..08f2654 --- /dev/null +++ b/py/tests/files/airodump.csv @@ -0,0 +1,42 @@ + +BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key +78:24:AF:D5:29:98, 2015-05-30 11:28:44, 2015-05-30 11:28:44, 6, -1, WPA, , , -73, 0, 1, 0. 0. 0. 0, 0, , +00:13:10:33:A6:56, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA, TKIP,PSK, -71, 7, 0, 0. 0. 0. 0, 11, orangefloss, +D8:50:E6:D7:22:95, 2015-05-30 11:28:43, 2015-05-30 11:28:43, -1, -1, , , , -70, 0, 0, 0. 0. 0. 0, 0, , +F0:99:BF:0A:B5:B0, 2015-05-30 11:28:45, 2015-05-30 11:28:48, 6, 54, WPA2, CCMP,PSK, -70, 3, 0, 0. 0. 0. 0, 22, Ingham's Wi-Fi Network, +60:02:92:BC:08:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2 WPA, CCMP TKIP,PSK, -68, 17, 0, 0. 0. 0. 0, 13, HOME-89B5-2.4, +00:25:BC:8B:24:95, 2015-05-30 11:28:44, 2015-05-30 11:28:44, 6, 54, WPA2 WPA, CCMP TKIP,PSK, -68, 1, 0, 0. 0. 0. 0, 8, atlantis, +60:02:92:BC:08:02, 2015-05-30 11:28:44, 2015-05-30 11:28:49, 6, 54, OPN, , , -68, 5, 0, 0. 0. 0. 0, 11, xfinitywifi, +00:23:69:BA:6D:F0, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2 WPA, CCMP TKIP,PSK, -67, 21, 0, 0. 0. 0. 0, 15, Pine Lake Girl2, +46:32:C8:5C:0E:3D, 2015-05-30 11:28:44, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -67, 6, 0, 0. 0. 0. 0, 12, \x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00, +44:32:C8:5C:0E:3C, 2015-05-30 11:28:44, 2015-05-30 11:28:48, 6, 54, WPA2 WPA, CCMP TKIP,PSK, -67, 5, 3, 0. 0. 0. 0, 9, HOME-0E3C, +60:02:92:BC:08:01, 2015-05-30 11:28:44, 2015-05-30 11:28:49, 6, 54, WPA2 WPA, CCMP TKIP,PSK, -69, 14, 0, 0. 0. 0. 0, 0, , +CC:A4:62:E8:E5:F0, 2015-05-30 11:28:44, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP TKIP,PSK, -67, 8, 0, 0. 0. 0. 0, 9, HOME-E5F2, +C2:A4:62:E8:E5:F0, 2015-05-30 11:28:44, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -65, 13, 0, 0. 0. 0. 0, 0, , +C6:A4:62:E8:E5:F0, 2015-05-30 11:28:45, 2015-05-30 11:28:50, 6, 54, OPN, , , -65, 14, 0, 0. 0. 0. 0, 11, xfinitywifi, +F0:99:BF:05:20:64, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -62, 30, 0, 0. 0. 0. 0, 4, JJML, +F2:64:20:05:BF:90, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -62, 23, 0, 0. 0. 0. 0, 9, JJMLGuest, +90:84:0D:DA:A8:87, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -62, 33, 5, 0. 0. 0. 0, 10, Rolston123, +10:0D:7F:8C:C1:FB, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -62, 12, 0, 0. 0. 0. 0, 12, The Internet, +00:00:00:00:00:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WEP, WEP, , -57, 138, 0, 0. 0. 0. 0, 0, , +00:1D:D5:9B:11:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP TKIP,PSK, -52, 32, 6, 0. 0. 0. 0, 9, HOME-1102, +00:24:7B:AB:5C:EE, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2 WPA, CCMP TKIP,PSK, -55, 16, 25, 0. 0. 0. 0, 11, myqwest0445, +02:1D:D5:9B:11:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -53, 41, 0, 0. 0. 0. 0, 0, , +06:1D:D5:9B:11:00, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, OPN, , , -53, 56, 0, 0. 0. 0. 0, 11, xfinitywifi, +00:F7:6F:CD:B2:2A, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -48, 44, 0, 0. 0. 0. 0, 13, im human 2015, +30:85:A9:39:D2:18, 2015-05-30 11:28:43, 2015-05-30 11:28:50, 6, 54, WPA2, CCMP,PSK, -21, 44, 4, 0. 0. 0. 0, 32, Uncle Router's Gigabit LAN Party, +00:0E:58:FA:7C:61, 2015-05-30 11:28:44, 2015-05-30 11:28:49, 6, -1, WPA, , , -1, 0, 57, 0. 0. 0. 0, 0, , +00:0E:58:F8:0B:B5, 2015-05-30 11:28:44, 2015-05-30 11:28:48, 6, -1, WPA, , , -1, 0, 59, 0. 0. 0. 0, 0, , +28:01:00:00:D0:00, 2015-05-30 11:28:44, 2015-05-30 11:28:44, 6, -1, , , , -1, 0, 0, 0. 0. 0. 0, 0, , +00:0E:58:E9:36:B3, 2015-05-30 11:28:44, 2015-05-30 11:28:48, 6, -1, WPA, , , -1, 0, 2, 0. 0. 0. 0, 0, , +05:00:40:00:BB:7C, 2015-05-30 11:28:50, 2015-05-30 11:28:50, -1, -1, , , , -1, 0, 0, 0. 0. 0. 0, 0, , + +Station MAC, First time seen, Last time seen, Power, # packets, BSSID, Probed ESSIDs +3A:01:44:32:C8:5C, 2015-05-30 11:28:44, 2015-05-30 11:28:44, -69, 3, 28:01:00:00:D0:00, +54:35:30:23:62:8E, 2015-05-30 11:28:43, 2015-05-30 11:28:50, -64, 7, 00:1D:D5:9B:11:00,HOME-1102 +10:40:F3:93:13:FA, 2015-05-30 11:28:44, 2015-05-30 11:28:48, -52, 4, 00:F7:6F:CD:B2:2A, +00:0E:58:FA:7C:61, 2015-05-30 11:28:45, 2015-05-30 11:28:50, -50, 6, 00:0E:58:E9:36:B3,Sonos_ynFI1HY4cF3gqPuljCuicmFZ66 +00:0E:58:E9:36:B3, 2015-05-30 11:28:43, 2015-05-30 11:28:49, -51, 124, 00:0E:58:FA:7C:61,Sonos_ynFI1HY4cF3gqPuljCuicmFZ66 +00:0E:58:F8:0B:B5, 2015-05-30 11:28:44, 2015-05-30 11:28:50, -48, 9, 00:0E:58:E9:36:B3,Sonos_ynFI1HY4cF3gqPuljCuicmFZ66 +5C:93:A2:0D:3D:63, 2015-05-30 11:28:44, 2015-05-30 11:28:50, -1, 22, 00:24:7B:AB:5C:EE, + diff --git a/py/tests/files/handshake_exists.cap b/py/tests/files/handshake_exists.cap new file mode 100644 index 0000000..4e89e8a Binary files /dev/null and b/py/tests/files/handshake_exists.cap differ diff --git a/py/tests/files/handshake_exists.cap.stripped.tshark b/py/tests/files/handshake_exists.cap.stripped.tshark new file mode 100644 index 0000000..ad67421 Binary files /dev/null and b/py/tests/files/handshake_exists.cap.stripped.tshark differ diff --git a/py/tests/files/handshake_not_exists.cap b/py/tests/files/handshake_not_exists.cap new file mode 100644 index 0000000..bf88b2b Binary files /dev/null and b/py/tests/files/handshake_not_exists.cap differ diff --git a/py/tests/test_Handshake.py b/py/tests/test_Handshake.py new file mode 100644 index 0000000..1c994f1 --- /dev/null +++ b/py/tests/test_Handshake.py @@ -0,0 +1,48 @@ +#!/usr/bin/python + +from Handshake import Handshake + +import unittest + +class TestHandshake(unittest.TestCase): + ''' Test suite for Target parsing an generation ''' + + 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) + + def testAnalyze(self): + hs_file = self.getFile('handshake_exists.cap') + hs = Handshake(hs_file, bssid='30:85:a9:39:d2:18') + try: + hs.analyze() + except Exception, e: + fail() + + def testHandshakeTshark(self): + hs_file = self.getFile('handshake_exists.cap') + hs = Handshake(hs_file, bssid='30:85:a9:39:d2:18') + assert(len(hs.tshark_handshakes()) > 0) + + def testHandshakePyrit(self): + hs_file = self.getFile('handshake_exists.cap') + hs = Handshake(hs_file, bssid='30:85:a9:39:d2:18') + assert(len(hs.pyrit_handshakes()) > 0) + + def testHandshakeCowpatty(self): + hs_file = self.getFile('handshake_exists.cap') + hs = Handshake(hs_file, bssid='30:85:a9:39:d2:18') + hs.divine_bssid_and_essid() + assert(len(hs.cowpatty_handshakes()) > 0) + + def testHandshakeAircrack(self): + hs_file = self.getFile('handshake_exists.cap') + hs = Handshake(hs_file, bssid='30:85:a9:39:d2:18') + assert(len(hs.aircrack_handshakes()) > 0) + + +if __name__ == '__main__': + unittest.main() diff --git a/py/tests/test_Target.py b/py/tests/test_Target.py new file mode 100644 index 0000000..6936ceb --- /dev/null +++ b/py/tests/test_Target.py @@ -0,0 +1,53 @@ +#!/usr/bin/python + +from Airodump import Airodump + +import unittest + +class TestTarget(unittest.TestCase): + ''' Test suite for Target parsing an generation ''' + + airodump_csv = 'airodump.csv' + + def getTargets(self, filename): + ''' Helper method to parse targets from filename ''' + import os, inspect + this_file = os.path.abspath(inspect.getsourcefile(TestTarget.getTargets)) + this_dir = os.path.dirname(this_file) + csv_file = os.path.join(this_dir, 'files', filename) + # Load targets from CSV file + return Airodump.get_targets_from_csv(csv_file) + + def testTargetParsing(self): + ''' Asserts target parsing finds targets ''' + targets = self.getTargets(TestTarget.airodump_csv) + assert(len(targets) > 0) + + def testTargetClients(self): + ''' Asserts target parsing captures clients properly ''' + targets = self.getTargets(TestTarget.airodump_csv) + for t in targets: + if t.bssid == '00:1D:D5:9B:11:00': + assert(len(t.clients) > 0) + + def testTargetFilter(self): + ''' Asserts target filtering works ''' + targets = self.getTargets(TestTarget.airodump_csv) + + opnTargets = Airodump.filter_targets(targets, opn=True, wpa=False, wep=False) + for t in opnTargets: + if 'OPN' not in t.encryption: + fail() + + wpaTargets = Airodump.filter_targets(targets, opn=False, wpa=True, wep=False) + for t in wpaTargets: + if 'WPA' not in t.encryption: + fail() + + wepTargets = Airodump.filter_targets(targets, opn=False, wpa=False, wep=True) + for t in wepTargets: + if 'WEP' not in t.encryption: + fail() + +if __name__ == '__main__': + unittest.main()