PMKID: * `--pmkid` option only attacks WPA networks with PMKID capture + crack * Decreased PMKID capture time from 60 seconds to 15 seconds. * Ignores PMKID attack if `--wps-only` is set. WPS: * Ctrl+C while waiting for `bully` to fetch PSK = remembers PIN, PSK is unknown. Misc: * `--cracked` prints results on single lines (much easier to read) * Fixed typo when required dependencies are not found (closes #127)
155 lines
5.4 KiB
Python
Executable File
155 lines
5.4 KiB
Python
Executable File
#!/usr/bin/env python
|
|
# -*- coding: utf-8 -*-
|
|
|
|
from ..util.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())
|
|
self.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(self.date))
|
|
|
|
def dump(self):
|
|
raise Exception('Unimplemented method: dump()')
|
|
|
|
def to_dict(self):
|
|
raise Exception('Unimplemented method: to_dict()')
|
|
|
|
def print_single_line(self, longest_essid):
|
|
raise Exception('Unimplemented method: print_single_line()')
|
|
|
|
def print_single_line_prefix(self, longest_essid):
|
|
essid = self.essid if self.essid else 'N/A'
|
|
Color.p('{W} ')
|
|
Color.p('{C}%s{W}' % essid.ljust(longest_essid))
|
|
Color.p(' ')
|
|
Color.p('{GR}%s{W}' % self.bssid.ljust(17))
|
|
Color.p(' ')
|
|
Color.p('{D}%s{W}' % self.readable_date.ljust(19))
|
|
Color.p(' ')
|
|
|
|
def save(self):
|
|
''' Adds this crack result to the cracked file and saves it. '''
|
|
name = CrackResult.cracked_file
|
|
json = []
|
|
if os.path.exists(name):
|
|
with open(name, 'r') as fid:
|
|
text = fid.read()
|
|
try:
|
|
json = loads(text)
|
|
except Exception as e:
|
|
Color.pl('{!} error while loading %s: %s' % (name, str(e)))
|
|
json.append(self.to_dict())
|
|
with open(name, 'w') as fid:
|
|
fid.write(dumps(json, indent=2))
|
|
Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})'
|
|
% (name, len(json)))
|
|
|
|
@classmethod
|
|
def display(cls):
|
|
''' Show cracked targets from cracked.txt '''
|
|
name = cls.cracked_file
|
|
if not os.path.exists(name):
|
|
Color.pl('{!} {O}file {C}%s{O} not found{W}' % name)
|
|
return
|
|
|
|
with open(name, 'r') as fid:
|
|
cracked_targets = loads(fid.read())
|
|
|
|
if len(cracked_targets) == 0:
|
|
Color.pl('{!} {R}no results found in {O}%s{W}' % name)
|
|
return
|
|
|
|
Color.pl('\n{+} Displaying {G}%d{W} cracked target(s) from {C}%s{W}\n' % (
|
|
len(cracked_targets), name))
|
|
|
|
results = sorted([cls.load(item) for item in cracked_targets], key=lambda x: x.date, reverse=True)
|
|
longest_essid = max([len(result.essid or 'ESSID') for result in results])
|
|
|
|
# Header
|
|
Color.p('{D} ')
|
|
Color.p('ESSID'.ljust(longest_essid))
|
|
Color.p(' ')
|
|
Color.p('BSSID'.ljust(17))
|
|
Color.p(' ')
|
|
Color.p('DATE'.ljust(19))
|
|
Color.p(' ')
|
|
Color.p('TYPE'.ljust(5))
|
|
Color.p(' ')
|
|
Color.p('KEY')
|
|
Color.pl('{D}')
|
|
Color.p(' ' + '-' * (longest_essid + 17 + 19 + 5 + 11 + 12))
|
|
Color.pl('{W}')
|
|
# Results
|
|
for result in results:
|
|
result.print_single_line(longest_essid)
|
|
Color.pl('')
|
|
|
|
|
|
@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 '''
|
|
if json['type'] == 'WPA':
|
|
from .wpa_result import CrackResultWPA
|
|
result = CrackResultWPA(json['bssid'],
|
|
json['essid'],
|
|
json['handshake_file'],
|
|
json['key'])
|
|
elif json['type'] == 'WEP':
|
|
from .wep_result import CrackResultWEP
|
|
result = CrackResultWEP(json['bssid'],
|
|
json['essid'],
|
|
json['hex_key'],
|
|
json['ascii_key'])
|
|
|
|
elif json['type'] == 'WPS':
|
|
from .wps_result import CrackResultWPS
|
|
result = CrackResultWPS(json['bssid'],
|
|
json['essid'],
|
|
json['pin'],
|
|
json['psk'])
|
|
|
|
elif json['type'] == 'PMKID':
|
|
from .pmkid_result import CrackResultPMKID
|
|
result = CrackResultPMKID(json['bssid'],
|
|
json['essid'],
|
|
json['pmkid_file'],
|
|
json['key'])
|
|
result.date = json['date']
|
|
result.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(result.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()
|