From 992a84fd3b679bd65bfd303f5d8d1f7dc832e792 Mon Sep 17 00:00:00 2001 From: derv82 Date: Wed, 28 Feb 2018 03:04:59 -0500 Subject: [PATCH] Improved `--crack` option. * Detect handshakes instead of relying on cracked.txt * cracked.txt doesn't store non-cracked handshakes! * Sort handshakes by capture date * Use cap2hccapx.bin found in /usr/lib/hashcat-utils * Link to tool if it's not found. * Include BSSID in --crack commands if relevant --- py/CrackHandshake.py | 107 ++++++++++++++++++++++++++++++------------- 1 file changed, 74 insertions(+), 33 deletions(-) diff --git a/py/CrackHandshake.py b/py/CrackHandshake.py index 19dcae7..c8eb261 100644 --- a/py/CrackHandshake.py +++ b/py/CrackHandshake.py @@ -17,56 +17,97 @@ class CrackHandshake(object): 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) + cap_file = handshake["handshake_file"] + bssid = handshake["bssid"] + Color.pl("\n Below are commands to crack the handshake {C}%s{W}:" % cap_file) + self.print_aircrack(cap_file, bssid) + self.print_pyrit(cap_file, bssid) 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_aircrack(self, cap_file, bssid): + Color.pl("") + if not Process.exists("aircrack-ng"): + Color.pl(" {R}aircrack-ng not found."); + Color.pl(" {O}More info on installing {R}Aircrack{O} here: {C}https://www.aircrack-ng.org/downloads.html{W}"); + return + Color.pl(" {O}# AIRCRACK: CPU-based cracking. Slow.") + Color.pl(" {G}aircrack-ng {W}-a {C}2 {W}-b {C}%s {W}-w {C}%s %s{W}" % (bssid, 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_pyrit(self, cap_file, bssid): + Color.pl("") + if not Process.exists("pyrit"): + Color.pl(" {R}pyrit not found."); + Color.pl(" {O}More info on installing {R}Pyrit{O} here: {C}https://github.com/JPaulMora/Pyrit{W}"); + return + Color.pl(" {O}# PYRIT: GPU-based cracking. Fast.") + Color.pl(" {G}pyrit {W}-b {C}%s {W}-i {C}%s {W}-r {C}%s {W}attack_passthrough{W}" % (bssid, 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("") + if not Process.exists("john"): + Color.pl(" {R}john not found."); + Color.pl(" {O}More info on installing {R}John The Ripper{O} here: {C}http://www.openwall.com/john/{W}"); + return + Color.pl(" {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}hccap2john {C}hccap.hccap {W}> {C}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.") - hccapx_file = "generated.hccapx" - if Process.exists("cap2hccapx"): - Color.pl(" {G}cap2hccapx {C}%s %s{W}" % (cap_file, hccapx_file)) + Color.pl("") + if not Process.exists("hashcat"): + Color.pl(" {R}hashcat {O}not found."); + Color.pl(" {O}More info on installing {R}hashcat{O} here: {C}https://hashcat.net/hashcat/"); + return + Color.pl(" {O}# HASHCAT: GPU-based cracking. Fast.") + Color.pl(" {O}# See {C}https://hashcat.net/wiki/doku.php?id=cracking_wpawpa2 {O}for more info") + + hccapx_file = "/tmp/generated.hccapx" + cap2hccapx = "/usr/lib/hashcat-utils/cap2hccapx.bin" + if os.path.exists(cap2hccapx): + Color.pl(" {G}%s {W}%s {C}%s{W}" % (cap2hccapx, cap_file, hccapx_file)) else: - Color.pl(" {O}# Visit https://hashcat.net/cap2hccapx to generate a .hccapx file{W}") - Color.pl(" {O}# Browse -> %s -> Convert" % cap_file) + Color.pl(" {O}# Install hashcat-utils: {C}https://hashcat.net/wiki/doku.php?id=hashcat_utils") + Color.pl(" {C}cap2hccapx.bin {W}%s {C}%s{W}" % (cap_file, hccapx_file)) + Color.pl(" {O}# OR visit https://hashcat.net/cap2hccapx to generate a .hccapx file{W}") + Color.pl(" {O}# Then click BROWSE -> %s -> CONVERT and save to %s" % (cap_file, hccapx_file)) + Color.pl(" {G}hashcat {W}-m 2500 {C}%s %s{W}" % (hccapx_file, self.wordlist)) 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"])] + hs_dir = Configuration.wpa_handshake_dir + Color.pl("{+} Listing captured handshakes from {C}%s{W}\n" % os.path.realpath(hs_dir)) + handshakes = [] + for hs_file in os.listdir(hs_dir): + if not hs_file.endswith('.cap') or hs_file.count("_") != 3: + continue + + name, essid, bssid, date = hs_file.split("_") + + if name != 'handshake': + continue + + handshakes.append({ + 'essid': essid, + 'bssid': bssid.replace('-', ':'), + 'date': date.replace('.cap', '').replace('T', ' '), + 'handshake_file': os.path.realpath(os.path.join(hs_dir, hs_file)) + }) + + handshakes.sort(key=lambda x: x['date'], reverse=True) + if len(handshakes) == 0: - raise Exception("No handshakes found in %s" % os.path.realpath(CrackResult.cracked_file)) + raise Exception("No handshakes found in %s" % os.path.realpath(hs_dir)) # Handshakes Header - max_essid_len = max([len(hs["essid"]) for hs in handshakes]) + max_essid_len = max(max([len(hs["essid"]) for hs in handshakes]), len('(truncated) ESSDID')) Color.p(" NUM") - Color.p(" " + "ESSID".ljust(max_essid_len)) + Color.p(" " + "ESSID (truncated)".ljust(max_essid_len)) Color.p(" " + "BSSID".ljust(17)) Color.p(" DATE CAPTURED\n") Color.p(" ---") @@ -77,17 +118,17 @@ class CrackHandshake(object): for idx, hs in enumerate(handshakes, start=1): bssid = hs["bssid"] essid = hs["essid"] - date = datetime.strftime(datetime.fromtimestamp(hs["date"]), "%Y-%m-%dT%H:%M:%S") + date = hs["date"] Color.p(" {G}%s{W}" % str(idx).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) + Color.p(" {O}%s{W}" % bssid) + Color.p(" {W}%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) + raise ValueError("Handshake NUM must be numeric, got (%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)) + raise Exception("Handshake NUM must be between 1 and %d" % len(handshakes)) return handshakes[hs_index - 1]