-
Notifications
You must be signed in to change notification settings - Fork 167
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Implement ignore feature #322
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
#!/usr/bin/env python | ||
# -*- coding: utf-8 -*- | ||
|
||
from ..util.color import Color | ||
from ..model.result import CrackResult | ||
from contextlib import contextmanager, redirect_stderr, redirect_stdout | ||
from os import devnull | ||
|
||
|
||
@contextmanager | ||
def suppress_stdout_stderr(): | ||
"""A context manager that redirects stdout and stderr to devnull""" | ||
with open(devnull, 'w') as fnull: | ||
with redirect_stderr(fnull) as err, redirect_stdout(fnull) as out: | ||
yield err, out | ||
|
||
|
||
class CrackResultIgnored(CrackResult): | ||
def __init__(self, bssid, essid): | ||
self.result_type = 'IGN' | ||
self.bssid = bssid | ||
self.essid = essid | ||
super(CrackResultIgnored, self).__init__() | ||
|
||
def dump(self): | ||
if self.essid is not None: | ||
Color.pl(f'{{+}} {"ESSID".rjust(12)}: {{C}}{self.essid}{{W}}') | ||
Color.pl('{+} %s: {C}%s{W}' % ('BSSID'.rjust(12), self.bssid)) | ||
|
||
def print_single_line(self, longest_essid): | ||
self.print_single_line_prefix(longest_essid) | ||
Color.p('{G}%s{W}' % 'IGN'.ljust(9)) | ||
Color.pl('') | ||
|
||
def to_dict(self): | ||
with suppress_stdout_stderr(): | ||
print('@@@ to dict', self.__dict__) | ||
return { | ||
'type': self.result_type, | ||
'date': self.date, | ||
'essid': self.essid, | ||
'bssid': self.bssid, | ||
} | ||
|
||
|
||
if __name__ == '__main__': | ||
crw = CrackResultIgnored('AA:BB:CC:DD:EE:FF', 'Test Router') | ||
crw.dump() | ||
crw.save() |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -64,28 +64,33 @@ def save(self): | |
saved_results.append(self.to_dict()) | ||
with open(name, 'w') as fid: | ||
fid.write(dumps(saved_results, indent=2)) | ||
Color.pl('{+} saved crack result to {C}%s{W} ({G}%d total{W})' | ||
Color.pl('{+} saved result to {C}%s{W} ({G}%d total{W})' | ||
% (name, len(saved_results))) | ||
|
||
@classmethod | ||
def display(cls): | ||
""" Show cracked targets from cracked file """ | ||
def display(cls, result_type): | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. issue (complexity): Consider refactoring the 'display' method into smaller, more focused methods. The
def get_filtered_results(cls, result_type):
targets = cls.load_all()
if result_type == 'cracked':
return [item for item in targets if item.get('type') != 'IGN']
else:
return [item for item in targets if item.get('type') == 'IGN']
@classmethod
def display(cls, result_type):
name = cls.cracked_file
if not os.path.exists(name):
Color.pl('{!} {O}file {C}%s{O} not found{W}' % name)
return
filtered_results = cls.get_filtered_results(result_type)
if len(filtered_results) == 0:
Color.pl('{!} {R}no results found in {O}%s{W}' % name)
return
Color.pl('\n{+} Displaying {G}%d{W} %s target(s) from {C}%s{W}\n' % (
len(filtered_results), 'cracked' if result_type == 'cracked' else 'ignored', cls.cracked_file))
results = sorted([cls.load(item) for item in filtered_results], key=lambda x: x.date, reverse=True)
cls.print_results_table(results, result_type == 'cracked')
@classmethod
def print_results_table(cls, results, show_key):
longest_essid = max(len(result.essid or 'ESSID') for result in results)
cls.print_table_header(longest_essid, show_key)
for result in results:
result.print_single_line(longest_essid)
Color.pl('')
@classmethod
def print_table_header(cls, longest_essid, show_key):
# ... (existing header printing code) ... These changes separate concerns, making each method more focused and easier to understand. The |
||
""" Show targets from results file """ | ||
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()) | ||
targets = cls.load_all() | ||
only_cracked = result_type == 'cracked' | ||
|
||
if len(cracked_targets) == 0: | ||
if only_cracked: | ||
targets = [item for item in targets if item.get('type') != 'IGN'] | ||
else: | ||
targets = [item for item in targets if item.get('type') == 'IGN'] | ||
|
||
if len(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)) | ||
Color.pl('\n{+} Displaying {G}%d{W} %s target(s) from {C}%s{W}\n' % ( | ||
len(targets), result_type, cls.cracked_file)) | ||
|
||
results = sorted([cls.load(item) for item in cracked_targets], key=lambda x: x.date, reverse=True) | ||
results = sorted([cls.load(item) for item in targets], key=lambda x: x.date, reverse=True) | ||
longest_essid = max(len(result.essid or 'ESSID') for result in results) | ||
|
||
# Header | ||
|
@@ -98,9 +103,10 @@ def display(cls): | |
Color.p(' ') | ||
Color.p('TYPE'.ljust(5)) | ||
Color.p(' ') | ||
Color.p('KEY') | ||
Color.pl('{D}') | ||
Color.p(' ' + '-' * (longest_essid + 17 + 19 + 5 + 11 + 12)) | ||
if only_cracked: | ||
Color.p('KEY') | ||
Color.pl('{D}') | ||
Color.p(' ' + '-' * (longest_essid + 17 + 19 + 5 + 11 + 12)) | ||
Color.pl('{W}') | ||
# Results | ||
for result in results: | ||
|
@@ -118,6 +124,24 @@ def load_all(cls): | |
return [] | ||
return json | ||
|
||
@classmethod | ||
def load_ignored_bssids(cls, ignore_cracked = False): | ||
json = cls.load_all() | ||
ignored_bssids = [ | ||
item.get('bssid', '') | ||
for item in json | ||
if item.get('result_type') == 'IGN' | ||
] | ||
|
||
if not ignore_cracked: | ||
return ignored_bssids | ||
|
||
return ignored_bssids + [ | ||
item.get('bssid', '') | ||
for item in json | ||
if item.get('result_type') != 'IGN' | ||
] | ||
|
||
@staticmethod | ||
def load(json): | ||
""" Returns an instance of the appropriate object given a json instance """ | ||
|
@@ -149,10 +173,30 @@ def load(json): | |
essid=json['essid'], | ||
pmkid_file=json['pmkid_file'], | ||
key=json['key']) | ||
|
||
else: | ||
from .ignored_result import CrackResultIgnored | ||
result = CrackResultIgnored(bssid=json['bssid'], | ||
essid=json['essid']) | ||
|
||
result.date = json['date'] | ||
result.readable_date = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(result.date)) | ||
return result | ||
|
||
@classmethod | ||
def ignore_target(cls, target): | ||
ignored_targets = cls.load_all() | ||
|
||
for ignored_target in ignored_targets: | ||
is_ignored = ignored_target == 'IGN' | ||
bssid_match = target.bssid == ignored_target.get('bssid') | ||
essid_match = target.essid == ignored_target.get('essid') | ||
if is_ignored and bssid_match and essid_match: | ||
return | ||
|
||
from .ignored_result import CrackResultIgnored | ||
ignored_target = CrackResultIgnored(target.bssid, target.essid) | ||
ignored_target.save() | ||
|
||
if __name__ == '__main__': | ||
# Deserialize WPA object | ||
|
@@ -178,3 +222,11 @@ def load(json): | |
'"date": 1433403278, "type": "WPS"}') | ||
obj = CrackResult.load(json) | ||
obj.dump() | ||
|
||
# Deserialize Ignored object | ||
Color.pl('\nIgnored:') | ||
json = loads( | ||
'{"bssid": "AA:BB:CC:DD:EE:FF", "essid": "Test Router", ' | ||
'"date": 1433403278, "type": "IGN"}') | ||
obj = CrackResult.load(json) | ||
obj.dump() |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
suggestion: Consider adding validation for bssid and essid parameters in the constructor
It might be beneficial to add some basic validation for the
bssid
andessid
parameters in the constructor. This could include checking for correct format of BSSID and ensuring that ESSID is not empty or too long.