--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:
@@ -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):
|
||||||
|
|||||||
@@ -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]
|
||||||
|
|||||||
@@ -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):
|
||||||
|
|||||||
105
wifite/wifite.py
105
wifite/wifite.py
@@ -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()
|
|
||||||
Reference in New Issue
Block a user