From a08dbf99c5d6b34f500fb76670eeeaa235c0fa39 Mon Sep 17 00:00:00 2001 From: derv82 Date: Sun, 14 May 2017 23:07:34 -0400 Subject: [PATCH] --crack option provides commands to crack a handshake Requested in #15 --- Wifite.py | 4 +- py/Arguments.py | 5 ++- py/Configuration.py | 4 +- py/CrackHandshake.py | 90 ++++++++++++++++++++++++++++++++++++++++++++ py/CrackResult.py | 7 ++++ 5 files changed, 107 insertions(+), 3 deletions(-) create mode 100644 py/CrackHandshake.py diff --git a/Wifite.py b/Wifite.py index 42a5879..065f72e 100755 --- a/Wifite.py +++ b/Wifite.py @@ -9,6 +9,7 @@ from py.AttackWPA import AttackWPA from py.AttackWPS import AttackWPS from py.CrackResult import CrackResult from py.Handshake import Handshake +from py.CrackHandshake import CrackHandshake from json import loads import os @@ -30,6 +31,8 @@ class Wifite(object): elif Configuration.check_handshake: self.check_handshake(Configuration.check_handshake) + elif Configuration.crack_handshake: + CrackHandshake() else: Configuration.get_interface() self.run() @@ -70,7 +73,6 @@ class Wifite(object): hs.analyze() Color.pl('') - def run(self): ''' Main program. diff --git a/py/Arguments.py b/py/Arguments.py index cb4deae..7aaa55a 100644 --- a/py/Arguments.py +++ b/py/Arguments.py @@ -276,7 +276,10 @@ class Arguments(object): dest='check_handshake', help=Color.s('Check a .cap file (or all hs/*.cap files) for WPA handshakes')) commands.add_argument('-check', help=argparse.SUPPRESS, action='store', nargs='?', const='', dest='check_handshake') - + commands.add_argument('--crack', + action='store_true', + dest='crack_handshake', + help=Color.s('Show commands to crack a captured handshake')) return parser.parse_args() if __name__ == '__main__': diff --git a/py/Configuration.py b/py/Configuration.py index c6b6125..e09dbb1 100644 --- a/py/Configuration.py +++ b/py/Configuration.py @@ -86,6 +86,7 @@ class Configuration(object): # Commands Configuration.show_cracked = False Configuration.check_handshake = None + Configuration.crack_handshake = False # Overwrite config values with arguments (if defined) Configuration.load_from_arguments() @@ -251,8 +252,9 @@ class Configuration(object): % '{W}, {G}'.join(Configuration.wep_attacks)) # Commands - if args.cracked: Configuration.show_cracked = True + if args.cracked: Configuration.show_cracked = True if args.check_handshake: Configuration.check_handshake = args.check_handshake + if args.crack_handshake: Configuration.crack_handshake = True @staticmethod diff --git a/py/CrackHandshake.py b/py/CrackHandshake.py new file mode 100644 index 0000000..b17332c --- /dev/null +++ b/py/CrackHandshake.py @@ -0,0 +1,90 @@ +#!/usr/bin/python2.7 +# -*- coding: utf-8 -*- + +from Process import Process +from Color import Color +from Configuration import Configuration +from CrackResult import CrackResult +from datetime import datetime + +import os + +class CrackHandshake(object): + def __init__(self): + self.wordlist = Configuration.wordlist or "path_to_wordlist_here" + + handshake = self.choose_handshake() + self.crack_handshake(handshake) + + def crack_handshake(self, handshake): + cap_file = os.path.realpath(handshake["handshake_file"]) + Color.pl("{+} Different ways to crack {C}%s{W}:" % cap_file) + self.print_aircrack(cap_file) + self.print_pyrit(cap_file) + self.print_john(cap_file) + self.print_oclhashcat(cap_file) + Color.pl("") + # TODO: cowpatty, oclhashcat + + def print_aircrack(self, cap_file): + if not Process.exists("aircrack-ng"): return + Color.pl("\n {O}# AIRCRACK: CPU-based cracking. Slow.") + Color.pl(" {G}aircrack-ng {W}-a 2 -w {C}%s %s{W}" % (self.wordlist, cap_file)) + + def print_pyrit(self, cap_file): + if not Process.exists("pyrit"): return + Color.pl("\n {O}# PYRIT: GPU-based cracking. Fast.") + Color.pl(" {G}pyrit {W}-i {C}%s {W}-r {C}%s {W}attack_passthrough{W}" % (self.wordlist, cap_file)) + + def print_john(self, cap_file): + if not Process.exists("pyrit"): return + Color.pl("\n {O}# JOHN: CPU or GPU-based cracking. Fast.") + Color.pl(" {O}# Use --format=wpapsk-cuda (or wpapsk-opengl) to enable GPU acceleration") + Color.pl(" {O}# See http://openwall.info/wiki/john/WPA-PSK for more info on this process") + Color.pl(" {G}aircrack-ng {W}-J hccap {C}%s{W}" % cap_file) + Color.pl(" {G}hccap2john {W}hccap.hccap > hccap.john{W}") + Color.pl(" {G}john {W}--wordlist {C}\"%s\" {W}--format=wpapsk {C}\"hccap.john\"{W}" % (self.wordlist)) + + def print_oclhashcat(self, cap_file): + if not Process.exists("hashcat"): return + Color.pl("\n {O}# OCLHASHCAT: GPU-based cracking. Fast.") + # TODO: Generate hccapx automatically + hccapx_file = "generated.hccapx" #cap_file + Color.pl(" {O}# Visit https://hashcat.net/cap2hccapx to generate a .hccapx file{W}") + Color.pl(" {G}hashcat {W}-m 2500 {C}%s %s{W}" % (self.wordlist, hccapx_file)) + + def choose_handshake(self): + Color.pl("\n{+} Listing captured handshakes...\n") + handshakes = CrackResult.load_all() + handshakes = [hs for hs in handshakes if "handshake_file" in hs and os.path.exists(hs["handshake_file"])] + if len(handshakes) == 0: + raise Exception("No handshakes found in %s" % os.path.realpath(CrackResult.cracked_file)) + + # Handshakes Header + max_essid_len = max([len(hs["essid"]) for hs in handshakes]) + Color.p(" NUM") + Color.p(" " + "ESSID".ljust(max_essid_len)) + Color.p(" " + "BSSID".ljust(17)) + Color.p(" DATE CAPTURED\n") + Color.p(" ---") + Color.p(" " + ("-" * max_essid_len)) + Color.p(" " + ("-" * 17)) + Color.p(" " + ("-" * 19) + "\n") + # Print all handshakes + for index, hs in enumerate(handshakes): + bssid = hs["bssid"] + essid = hs["essid"] + date = datetime.strftime(datetime.fromtimestamp(hs["date"]), "%Y-%m-%dT%H:%M:%S") + Color.p(" {G}%s{W}" % str(index + 1).rjust(3)) + Color.p(" {C}%s{W}" % essid.ljust(max_essid_len)) + Color.p(" {C}%s{W}" % bssid) + Color.p(" {C}%s{W}\n" % date) + # Get number from user + hs_index = raw_input(Color.s("\n{+} Select handshake num to crack ({G}1-%d{W}): " % len(handshakes))) + if not hs_index.isdigit(): + raise Exception("Invalid input: %s" % hs_index) + hs_index = int(hs_index) + if hs_index < 1 or hs_index > len(handshakes): + raise Exception("Handshake num must be between 1 and %d" % len(handshakes)) + + return handshakes[hs_index - 1] diff --git a/py/CrackResult.py b/py/CrackResult.py index 2e1f135..5a80d6d 100644 --- a/py/CrackResult.py +++ b/py/CrackResult.py @@ -41,6 +41,13 @@ class CrackResult(object): Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})' % (name, len(json))) + @classmethod + def load_all(cls): + if not os.path.exists(cls.cracked_file): return [] + with open(cls.cracked_file, "r") as json_file: + json = loads(json_file.read()) + return json + @staticmethod def load(json): ''' Returns an instance of the appropriate object given a json instance '''