--crack: Dependency management, avoid dupes in cracked.txt

* Dupes are skipped if everything *except* date matches (same bssid/ssid/type/key)
* John: Detect and use OpenCL or CUDA using `john --list=formats`
* Removed `wifite.py` as it's no longer used & is confusing.
This commit is contained in:
derv82
2018-08-21 00:00:58 -07:00
parent 4173ef46e5
commit dd0e44cf53
5 changed files with 68 additions and 132 deletions

View File

@@ -39,19 +39,31 @@ class CrackResult(object):
def save(self): def save(self):
''' Adds this crack result to the cracked file and saves it. ''' ''' Adds this crack result to the cracked file and saves it. '''
name = CrackResult.cracked_file name = CrackResult.cracked_file
json = [] saved_results = []
if os.path.exists(name): if os.path.exists(name):
with open(name, 'r') as fid: with open(name, 'r') as fid:
text = fid.read() text = fid.read()
try: try:
json = loads(text) saved_results = loads(text)
except Exception as e: except Exception as e:
Color.pl('{!} error while loading %s: %s' % (name, str(e))) Color.pl('{!} error while loading %s: %s' % (name, str(e)))
json.append(self.to_dict())
# Check for duplicates
this_dict = self.to_dict()
this_dict.pop('date')
for entry in saved_results:
this_dict['date'] = entry.get('date')
if entry == this_dict:
# Skip if we already saved this BSSID+ESSID+TYPE+KEY
Color.pl('{+} {C}%s{O} already exists in {G}cracked.txt{O}, skipping.' % (
self.essid))
return
saved_results.append(self.to_dict())
with open(name, 'w') as fid: with open(name, 'w') as fid:
fid.write(dumps(json, indent=2)) fid.write(dumps(saved_results, indent=2))
Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})' Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})'
% (name, len(json))) % (name, len(saved_results)))
@classmethod @classmethod
def display(cls): def display(cls):

View File

@@ -21,27 +21,39 @@ class John(Dependency):
def crack_handshake(handshake, show_command=False): def crack_handshake(handshake, show_command=False):
john_file = HcxPcapTool.generate_john_file(handshake, show_command=show_command) john_file = HcxPcapTool.generate_john_file(handshake, show_command=show_command)
# Use `john --list=formats` to find if OpenCL or CUDA is supported.
formats_stdout = Process(['john', '--list=formats']).stdout()
if 'wpapsk-opencl' in formats_stdout:
john_format = 'wpapsk-opencl'
elif 'wpapsk-cuda' in formats_stdout:
john_format = 'wpapsk-cuda'
else:
john_format = 'wpapsk'
# Crack john file # Crack john file
command = [ command = [
'john', 'john',
'--format=wpapsk', # wpapsk-cuda or wpapsk-opencl '--format', john_format,
'--wordlist', Configuration.wordlist, '--wordlist', Configuration.wordlist,
john_file john_file
] ]
if show_command: if show_command:
Color.pl('{+} {D}{C}Running %s{W}' % ' '.join(command)) Color.pl('{+} {D}{C}Running %s{W}' % ' '.join(command))
process = Process(command) process = Process(command)
process.wait() process.wait()
# Show the password (if found) # Run again with --show to consistently get the password
command = ['john', '--show', john_file] command = ['john', '--show', john_file]
if show_command: if show_command:
Color.pl('{+} {D}{C}Running %s{W}' % ' '.join(command)) Color.pl('{+} {D}{C}Running %s{W}' % ' '.join(command))
process = Process(command) process = Process(command)
stdout, stderr = process.get_output() stdout, stderr = process.get_output()
# Parse password (regex doesn't work for some reason)
if '0 password hashes cracked' in stdout:
key = None key = None
if not '0 password hashes cracked' in stdout: else:
for line in stdout.split('\n'): for line in stdout.split('\n'):
if handshake.capfile in line: if handshake.capfile in line:
key = line.split(':')[1] key = line.split(':')[1]

View File

@@ -22,6 +22,8 @@ import os
# TODO: Do not show handshake files that are in cracked.txt with a key (match on filename). # TODO: Do not show handshake files that are in cracked.txt with a key (match on filename).
# TODO: --no-crack option while attacking targets (implies user will run --crack later)
class CrackHelper: class CrackHelper:
'''Manages handshake retrieval, selection, and running the cracking commands.''' '''Manages handshake retrieval, selection, and running the cracking commands.'''
@@ -52,20 +54,35 @@ class CrackHelper:
hs_to_crack = cls.get_user_selection(handshakes) hs_to_crack = cls.get_user_selection(handshakes)
# Get tool # Tools for cracking & their dependencies.
available_tools = ['aircrack', 'hashcat', 'john', 'cowpatty'] available_tools = {
if not Process.exists(HcxPcapTool.dependency_name): 'aircrack': [Aircrack],
Color.pl('{!} {R}Unable to use hashcat: {O}missing required hcxpcaptool{W}') 'hashcat': [Hashcat, HcxPcapTool],
available_tools.remove('hashcat') 'john': [John, HcxPcapTool],
if not Process.exists(John.dependency_name): 'cowpatty': [Cowpatty]
Color.pl('{!} {R}Unable to use john: {O}missing required "john" program{W}') }
available_tools.remove('john') # Identify missing tools
missing_tools = []
for tool, dependencies in available_tools.items():
missing = [
dep for dep in dependencies
if not Process.exists(dep.dependency_name)
]
if len(missing) > 0:
available_tools.pop(tool)
missing_tools.append( (tool, missing) )
Color.p('{+} Enter the {C}cracking tool{W} to use ({C}%s{W}): {G}' % ( if len(missing_tools) > 0:
'{W}, {C}'.join(available_tools))) Color.pl('\n{!} {O}Unavailable tools (install to enable):{W}')
for tool, deps in missing_tools:
dep_list = ', '.join([dep.dependency_name for dep in deps])
Color.pl(' {R}* {R}%s {W}({O}%s{W})' % (tool, dep_list))
Color.p('\n{+} Enter the {C}cracking tool{W} to use ({C}%s{W}): {G}' % (
'{W}, {C}'.join(available_tools.keys())))
tool_name = raw_input() tool_name = raw_input()
if tool_name not in available_tools: if tool_name not in available_tools:
Color.pl('{!} {O}%s not found, defaulting to aircrack' % tool_name) Color.pl('{!} {R}"%s"{O} tool not found, defaulting to {C}aircrack{W}' % tool_name)
tool_name = 'aircrack' tool_name = 'aircrack'
try: try:
@@ -85,7 +102,7 @@ class CrackHelper:
Color.pl('\n{!} {O}directory not found: {R}%s{W}' % hs_dir) Color.pl('\n{!} {O}directory not found: {R}%s{W}' % hs_dir)
return [] return []
Color.pl('\n{+} Listing captured handshakes from {C}%s{W} ...\n' % os.path.abspath(hs_dir)) Color.pl('\n{+} Listing captured handshakes from {C}%s{W}:\n' % os.path.abspath(hs_dir))
for hs_file in os.listdir(hs_dir): for hs_file in os.listdir(hs_dir):
if hs_file.count('_') != 3: if hs_file.count('_') != 3:
continue continue
@@ -146,7 +163,7 @@ class CrackHelper:
Color.p(' ---') Color.p(' ---')
Color.p(' ' + ('-' * max_essid_len)) Color.p(' ' + ('-' * max_essid_len))
Color.p(' ' + ('-' * 17)) Color.p(' ' + ('-' * 17))
Color.p(' ' + ('-' * 6)) Color.p(' ' + ('-' * 5))
Color.p(' ' + ('-' * 19) + '{W}\n') Color.p(' ' + ('-' * 19) + '{W}\n')
# Handshakes # Handshakes
for index, handshake in enumerate(handshakes, start=1): for index, handshake in enumerate(handshakes, start=1):

View File

@@ -1,105 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
try:
from .config import Configuration
except (ValueError, ImportError) as e:
raise Exception('You may need to run wifite from the root directory (which includes README.md)', e)
from .util.color import Color
import os
import sys
class Wifite(object):
def __init__(self):
'''
Initializes Wifite. Checks for root permissions and ensures dependencies are installed.
'''
self.print_banner()
Configuration.initialize(load_interface=False)
if os.getuid() != 0:
Color.pl('{!} {R}error: {O}wifite{R} must be run as {O}root{W}')
Color.pl('{!} {R}re-run with {O}sudo{W}')
Configuration.exit_gracefully(0)
from .tools.dependency import Dependency
Dependency.run_dependency_check()
def start(self):
'''
Starts target-scan + attack loop, or launches utilities dpeending on user input.
'''
from .model.result import CrackResult
from .model.handshake import Handshake
from .util.crack import CrackHelper
if Configuration.show_cracked:
CrackResult.display()
elif Configuration.check_handshake:
Handshake.check()
elif Configuration.crack_handshake:
CrackHelper.run()
else:
Configuration.get_monitor_mode_interface()
self.scan_and_attack()
def print_banner(self):
'''Displays ASCII art of the highest caliber.'''
Color.pl(r'{G} . {GR}{D} {W}{G} . {W}')
Color.pl(r'{G}.´ · .{GR}{D} {W}{G}. · `. {G}wifite {D}%s{W}' % Configuration.version)
Color.pl(r'{G}: : : {GR}{D} (¯) {W}{G} : : : {W}{D}automated wireless auditor{W}')
Color.pl(r'{G}`. · `{GR}{D}\ {W}{G}´ · .´ {C}{D}https://github.com/derv82/wifite2{W}')
Color.pl(r'{G} ` {GR}{D}/¯¯¯\{W}{G} ´ {W}')
Color.pl('')
def scan_and_attack(self):
'''
1) Scans for targets, asks user to select targets
2) Attacks each target
'''
from .util.scanner import Scanner
from .attack.all import AttackAll
Color.pl('')
# Scan
s = Scanner()
targets = s.select_targets()
# Attack
attacked_targets = AttackAll.attack_multiple(targets)
Color.pl('\n{+} Finished attacking {C}%d{W} target(s), exiting' % attacked_targets)
##############################################################
def entry_point():
try:
wifite = Wifite()
wifite.start()
except Exception as e:
Color.pexception(e)
Color.pl('\n{!} {R}Exiting{W}\n')
except KeyboardInterrupt:
Color.pl('\n{!} {O}interrupted, shutting down...{W}')
Configuration.exit_gracefully(0)
if __name__ == '__main__':
entry_point()