From 1078a4d5de031eeef030a69a8a06bd5a0be1938b Mon Sep 17 00:00:00 2001 From: derv82 Date: Thu, 4 Jun 2015 00:52:36 -0700 Subject: [PATCH] Crack results can be saved or loaded. Although they're not saved or loaded at this time. :( Also, BANNER! --- Wifite.py | 24 +++++++- py/Airodump.py | 16 ++++- py/Arguments.py | 4 +- py/Attack.py | 2 +- py/AttackWPA.py | 4 +- py/Configuration.py | 2 +- py/CrackResult.py | 85 ++++++++++++++++++++++++++ py/CrackResultWEP.py | 19 +++++- py/{WPAResult.py => CrackResultWPA.py} | 25 +++++++- py/CrackResultWPS.py | 27 +++++--- py/Scanner.py | 32 ++++++++++ py/Target.py | 2 +- py/Wash.py | 4 +- 13 files changed, 223 insertions(+), 23 deletions(-) create mode 100644 py/CrackResult.py rename py/{WPAResult.py => CrackResultWPA.py} (54%) diff --git a/Wifite.py b/Wifite.py index e200048..3fbf252 100755 --- a/Wifite.py +++ b/Wifite.py @@ -18,7 +18,12 @@ class Wifite(object): 2) Attacks each target ''' s = Scanner() - targets = s.select_targets() + if s.target: + # We found the target we want + targets = [s.target] + else: + targets = s.select_targets() + for t in targets: Color.pl('{+} starting attacks against {C}%s{W} ({C}%s{W})' % (t.bssid, t.essid)) @@ -47,10 +52,27 @@ class Wifite(object): # TODO: Save attack.crack_result pass + def print_banner(self): + """ Displays ASCII art of the highest caliber. """ + Color.pl("") + Color.pl("{G} .;' `;, ") + Color.pl("{G} .;' ,;' `;, `;, " + + "{W}WiFite v%.2f" % Configuration.version) + Color.pl("{G}.;' ,;' ,;' `;, `;, `;, ") + Color.pl("{G}:: :: : {GR}( ){G} : :: :: " + + "{W}automated wireless auditor") + Color.pl("{G}':. ':. ':. {GR}/_\\{G} ,:' ,:' ,:' ") + Color.pl("{G} ':. ':. {GR}/___\\{G} ,:' ,:' " + + "{W}designed for Linux") + Color.pl("{G} ':. {GR}/_____\\{G} ,:' ") + Color.pl("{G} {GR}/ \\{G} ") + Color.pl("{W}") + if __name__ == '__main__': w = Wifite() try: + w.print_banner() w.run() except Exception, e: Color.pl('\n{!} {R}Error:{O} %s{W}' % str(e)) diff --git a/py/Airodump.py b/py/Airodump.py index 7f9c18c..7cece41 100644 --- a/py/Airodump.py +++ b/py/Airodump.py @@ -192,8 +192,9 @@ class Airodump(object): @staticmethod def filter_targets(targets): - ''' Filters targets based on encryption defined in Configuration ''' + ''' Filters targets based on Configuration ''' result = [] + # Filter based on Encryption for target in targets: if 'WEP' in Configuration.encryption_filter and \ 'WEP' in target.encryption: @@ -204,6 +205,19 @@ class Airodump(object): elif 'WPS' in Configuration.encryption_filter and \ target.wps: result.append(target) + + # Filter based on BSSID/ESSID + bssid = Configuration.target_bssid + essid = Configuration.target_essid + i = 0 + while i < len(result): + if bssid and result[i].bssid.lower() != bssid.lower(): + result.pop(i) + continue + if essid and result[i].essid.lower() != essid.lower(): + result.pop(i) + continue + i += 1 return result diff --git a/py/Arguments.py b/py/Arguments.py index bd5d4fb..c77bfb0 100644 --- a/py/Arguments.py +++ b/py/Arguments.py @@ -12,7 +12,9 @@ class Arguments(object): description = 'Wrapper script around aircrack-ng and reaver' description += ' https://github.com/derv82/wifite2' - parser = argparse.ArgumentParser(description=description) + parser = argparse.ArgumentParser( + description=description, + usage=argparse.SUPPRESS) # Global variables glob = parser.add_argument_group('SETTINGS') diff --git a/py/Attack.py b/py/Attack.py index 29e89f6..e0497c7 100644 --- a/py/Attack.py +++ b/py/Attack.py @@ -7,7 +7,7 @@ class Attack(object): Contains functionality common to all attacks ''' - target_wait = 10 + target_wait = 20 def __init__(self, target): self.target = target diff --git a/py/AttackWPA.py b/py/AttackWPA.py index bede736..ef8f002 100644 --- a/py/AttackWPA.py +++ b/py/AttackWPA.py @@ -6,7 +6,7 @@ from Color import Color from Configuration import Configuration from Handshake import Handshake from Process import Process -from WPAResult import WPAResult +from CrackResultWPA import CrackResultWPA import time import os @@ -165,7 +165,7 @@ class AttackWPA(Attack): ' {O}%s did not contain password{W}' % wordlist.split(os.sep)[-1]) - self.crack_result = WPAResult(bssid, essid, handshake.capfile, key) + self.crack_result = CrackResultWPA(bssid, essid, handshake.capfile, key) self.crack_result.dump() self.success = True return self.success diff --git a/py/Configuration.py b/py/Configuration.py index db8dbca..e33205f 100644 --- a/py/Configuration.py +++ b/py/Configuration.py @@ -7,6 +7,7 @@ class Configuration(object): initialized = False # Flag indicating config has been initialized temp_dir = None # Temporary directory + version = 2.00 @staticmethod def initialize(): @@ -20,7 +21,6 @@ class Configuration(object): return Configuration.initialized = True - Configuration.version = 2.00 # Program version Configuration.tx_power = 0 # Wifi transmit power (0 is default) Configuration.interface = None Configuration.target_channel = None # User-defined channel to scan diff --git a/py/CrackResult.py b/py/CrackResult.py new file mode 100644 index 0000000..76f590c --- /dev/null +++ b/py/CrackResult.py @@ -0,0 +1,85 @@ +#!/usr/bin/python + +from Color import Color + +import os +import time +from json import loads, dumps + +class CrackResult(object): + ''' Abstract class containing results from a crack session ''' + + # File to save cracks to, in PWD + cracked_file = "cracked.txt" + + def __init__(self): + self.date = int(time.time()) + + def dump(self): + raise Exception("Unimplemented method: dump()") + + def to_dict(self): + raise Exception("Unimplemented method: to_dict()") + + def save(self): + ''' Adds this crack result to the cracked file and saves it. ''' + name = CrackResult.cracked_file + json = [] + if os.path.exists(name): + f = open(name, 'r') + text = f.read() + f.close() + try: + json = loads(text) + except Exception, e: + Color.pl('{!} error while loading %s: %s' % (name, str(e))) + json.append(self.to_dict()) + f = open(name, 'w') + f.write(dumps(json, indent=2)) + f.close() + Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})' + % (name, len(json))) + + @staticmethod + def load(json): + ''' Returns an instance of the appropriate object given a json instance ''' + if json['type'] == 'WPA': + from CrackResultWPA import CrackResultWPA + result = CrackResultWPA(json['bssid'], + json['essid'], + json['handshake_file'], + json['key']) + elif json['type'] == 'WEP': + from CrackResultWEP import CrackResultWEP + result = CrackResultWEP(json['bssid'], + json['essid'], + json['hex_key'], + json['ascii_key']) + + elif json['type'] == 'WPS': + from CrackResultWPS import CrackResultWPS + result = CrackResultWPS(json['bssid'], + json['essid'], + json['pin'], + json['psk']) + result.date = json['date'] + return result + +if __name__ == '__main__': + # Deserialize WPA object + Color.pl('\nCracked WPA:') + json = loads('{"bssid": "AA:BB:CC:DD:EE:FF", "essid": "Test Router", "key": "Key", "date": 1433402428, "handshake_file": "hs/capfile.cap", "type": "WPA"}') + obj = CrackResult.load(json) + obj.dump() + + # Deserialize WEP object + Color.pl('\nCracked WEP:') + json = loads('{"bssid": "AA:BB:CC:DD:EE:FF", "hex_key": "00:01:02:03:04", "ascii_key": "abcde", "essid": "Test Router", "date": 1433402915, "type": "WEP"}') + obj = CrackResult.load(json) + obj.dump() + + # Deserialize WPS object + Color.pl('\nCracked WPS:') + json = loads('{"psk": "the psk", "bssid": "AA:BB:CC:DD:EE:FF", "pin": "01234567", "essid": "Test Router", "date": 1433403278, "type": "WPS"}') + obj = CrackResult.load(json) + obj.dump() diff --git a/py/CrackResultWEP.py b/py/CrackResultWEP.py index 6511ead..361efd9 100644 --- a/py/CrackResultWEP.py +++ b/py/CrackResultWEP.py @@ -1,27 +1,40 @@ #!/usr/bin/python from Color import Color +from CrackResult import CrackResult import time -class CrackResultWEP(object): +class CrackResultWEP(CrackResult): def __init__(self, bssid, essid, hex_key, ascii_key): + self.result_type = 'WEP' self.bssid = bssid self.essid = essid self.hex_key = hex_key self.ascii_key = ascii_key - self.time = time.time() + super(CrackResultWEP, self).__init__() def dump(self): if self.essid: Color.pl('{+} ESSID: {C}%s{W}' % self.essid) Color.pl('{+} BSSID: {C}%s{W}' % self.bssid) - Color.pl('{+} Encryption: {C}WEP{W}') + Color.pl('{+} Encryption: {C}%s{W}' % self.result_type) Color.pl('{+} Hex Key: {G}%s{W}' % self.hex_key) if self.ascii_key: Color.pl('{+} Ascii Key: {G}%s{W}' % self.ascii_key) + + def to_dict(self): + return { + 'type' : self.result_type, + 'date' : self.date, + 'essid' : self.essid, + 'bssid' : self.bssid, + 'hex_key' : self.hex_key, + 'ascii_key' : self.ascii_key + } if __name__ == '__main__': crw = CrackResultWEP('AA:BB:CC:DD:EE:FF', 'Test Router', '00:01:02:03:04', 'abcde') crw.dump() + crw.save() diff --git a/py/WPAResult.py b/py/CrackResultWPA.py similarity index 54% rename from py/WPAResult.py rename to py/CrackResultWPA.py index 82d164c..551e2a6 100644 --- a/py/WPAResult.py +++ b/py/CrackResultWPA.py @@ -1,13 +1,16 @@ #!/usr/bin/python from Color import Color +from CrackResult import CrackResult -class WPAResult(object): +class CrackResultWPA(CrackResult): def __init__(self, bssid, essid, handshake_file, key): + self.result_type = 'WPA' self.bssid = bssid self.essid = essid self.handshake_file = handshake_file self.key = key + super(CrackResultWPA, self).__init__() def dump(self): if self.essid: @@ -16,6 +19,8 @@ class WPAResult(object): if self.bssid: Color.pl('{+} %s: {C}%s{W}' % ('Access Point BSSID'.rjust(19), self.bssid)) + Color.pl('{+} %s: {C}%s{W}' % + ('Encryption'.rjust(19), self.result_type)) if self.handshake_file: Color.pl('{+} %s: {C}%s{W}' % ('Handshake File'.rjust(19), self.handshake_file)) @@ -23,10 +28,24 @@ class WPAResult(object): Color.pl('{+} %s: {G}%s{W}' % ('PSK (password)'.rjust(19), self.key)) else: Color.pl('{!} %s {O}key unknown{W}' % ''.rjust(19)) + + def to_dict(self): + return { + 'type' : self.result_type, + 'date' : self.date, + 'essid' : self.essid, + 'bssid' : self.bssid, + 'key' : self.key, + 'handshake_file' : self.handshake_file + } if __name__ == '__main__': - w = WPAResult('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', 'abcd1234') + w = CrackResultWPA('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', 'abcd1234') w.dump() + + w = CrackResultWPA('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', 'Key') print '\n' - w = WPAResult('AA:BB:CC:DD:EE:FF', 'Test Router', 'hs/capfile.cap', None) w.dump() + w.save() + print w.__dict__['bssid'] + diff --git a/py/CrackResultWPS.py b/py/CrackResultWPS.py index e2f1269..736dd16 100644 --- a/py/CrackResultWPS.py +++ b/py/CrackResultWPS.py @@ -1,26 +1,39 @@ #!/usr/bin/python from Color import Color +from CrackResult import CrackResult import time -class CrackResultWPS(object): +class CrackResultWPS(CrackResult): def __init__(self, bssid, essid, pin, psk): + self.result_type = 'WPS' self.bssid = bssid self.essid = essid self.pin = pin self.psk = psk - self.time = time.time() + super(CrackResultWPS, self).__init__() def dump(self): if self.essid: - Color.pl('{+} ESSID: {C}%s{W}' % self.essid) - Color.pl('{+} BSSID: {C}%s{W}' % self.bssid) - Color.pl('{+} Encryption: {C}WPA{W} ({C}WPS{W})') - Color.pl('{+} WPS PIN: {G}%s{W}' % self.pin) - Color.pl('{+} PSK/Password: {G}%s{W}' % self.psk) + Color.pl('{+} %s: {C}%s{W}' % ( 'ESSID'.rjust(12), self.essid)) + Color.pl('{+} %s: {C}%s{W}' % ( 'BSSID'.rjust(12), self.bssid)) + Color.pl('{+} %s: {C}WPA{W} ({C}WPS{W})' % 'Encryption'.rjust(12)) + Color.pl('{+} %s: {G}%s{W}' % ( 'WPS PIN'.rjust(12), self.pin)) + Color.pl('{+} %s: {G}%s{W}' % ('PSK/Password'.rjust(12), self.psk)) + + def to_dict(self): + return { + 'type' : self.result_type, + 'date' : self.date, + 'essid' : self.essid, + 'bssid' : self.bssid, + 'pin' : self.pin, + 'psk' : self.psk + } if __name__ == '__main__': crw = CrackResultWPS('AA:BB:CC:DD:EE:FF', 'Test Router', '01234567', 'the psk') crw.dump() + crw.save() diff --git a/py/Scanner.py b/py/Scanner.py index caf3aa9..16e1fec 100644 --- a/py/Scanner.py +++ b/py/Scanner.py @@ -20,6 +20,7 @@ class Scanner(object): ''' self.previous_target_count = 0 self.targets = [] + self.target = None # Specific target (based on ESSID/BSSID) # Loads airodump with interface/channel/etc from Configuration with Airodump() as airodump: @@ -35,6 +36,11 @@ class Scanner(object): % ' '.join(airodump.pid.command)) self.targets = airodump.get_targets() + + if self.found_target(): + # We found the target we want + return + self.print_targets() target_count = len(self.targets) @@ -50,6 +56,32 @@ class Scanner(object): except KeyboardInterrupt: pass + def found_target(self): + ''' + Check if we discovered the target AP + Returns: the Target if found, + Otherwise None. + ''' + bssid = Configuration.target_bssid + essid = Configuration.target_essid + + if bssid == None and essid == None: + return False + + for target in self.targets: + if bssid and bssid.lower() == target.bssid.lower(): + self.target = target + break + if essid and essid.lower() == target.essid.lower(): + self.target = target + break + + if self.target: + Color.pl('\n{+} {C}found target{G} %s {W}({G}%s{W})' + % (self.target.bssid, self.target.essid)) + return True + + return False def print_targets(self): ''' diff --git a/py/Target.py b/py/Target.py index 2a91181..357130d 100644 --- a/py/Target.py +++ b/py/Target.py @@ -126,7 +126,7 @@ class Target(object): if __name__ == '__main__': - 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(',') + 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) t.clients.append("asdf") t.clients.append("asdf") diff --git a/py/Wash.py b/py/Wash.py index ef20fe4..a01818e 100644 --- a/py/Wash.py +++ b/py/Wash.py @@ -52,9 +52,9 @@ class Wash(object): if __name__ == '__main__': from Target import Target # Test target within range - fields = 'CC:A4:62:E8:E5:F0, 2015-05-27 19:28:44, 2015-05-27 19:28:46, 6, 54, WPA2, CCMP TKIP,PSK, -58, 2, 0, 0. 0. 0. 0, 9, HOME-E5F2, '.split(',') + 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('/tmp/airodump-01.cap', targets) + Wash.check_for_wps_and_update_targets('./tests/files/handshake_exists.cap', targets) print targets[0].bssid, 'WPS =', targets[0].wps