diff --git a/Dockerfile b/Dockerfile index 2d956ba1e..098777ea7 100644 --- a/Dockerfile +++ b/Dockerfile @@ -44,7 +44,7 @@ RUN make install # Workdir / WORKDIR / -#Install and configure hashcat +# Install and configure hashcat RUN mkdir hashcat && \ cd hashcat && \ wget https://hashcat.net/files_legacy/${HASHCAT_VERSION}.7z && \ @@ -54,6 +54,14 @@ RUN mkdir hashcat && \ #Add link for binary RUN ln -s /hashcat/hashcat-cli64.bin /usr/bin/hashcat +# Install hcxtools +RUN git clone https://github.com/ZerBea/hcxtools.git +WORKDIR /hcxtools/ +RUN make +RUN make install + +# Workdir / +WORKDIR / # Install reaver RUN git clone https://github.com/gabrielrcouto/reaver-wps.git diff --git a/wifite/__main__.py b/wifite/__main__.py index 314bcb1f6..d6df796e6 100755 --- a/wifite/__main__.py +++ b/wifite/__main__.py @@ -9,7 +9,6 @@ from .util.color import Color import os -import sys class Wifite(object): @@ -53,8 +52,8 @@ def start(self): Configuration.get_monitor_mode_interface() self.scan_and_attack() - - def print_banner(self): + @staticmethod + def print_banner(): '''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) @@ -63,8 +62,8 @@ def print_banner(self): Color.pl(r' {G} ` {GR}{D}/¯¯¯\{W}{G} ´ {W}') Color.pl('') - - def scan_and_attack(self): + @staticmethod + def scan_and_attack(): ''' 1) Scans for targets, asks user to select targets 2) Attacks each target diff --git a/wifite/attack/all.py b/wifite/attack/all.py index 6db4d3718..976466a54 100755 --- a/wifite/attack/all.py +++ b/wifite/attack/all.py @@ -59,7 +59,7 @@ def attack_single(cls, target, targets_remaining): # WPS if not Configuration.use_pmkid_only: - if target.wps != False and AttackWPS.can_attack_wps(): + if not target.wps and AttackWPS.can_attack_wps(): # Pixie-Dust if Configuration.wps_pixie: attacks.append(AttackWPS(target, pixie_dust=True)) diff --git a/wifite/attack/pmkid.py b/wifite/attack/pmkid.py index 01f3680a5..eacd3cb24 100755 --- a/wifite/attack/pmkid.py +++ b/wifite/attack/pmkid.py @@ -76,7 +76,7 @@ def run(self): pmkid_file = None - if Configuration.ignore_old_handshakes == False: + if not Configuration.ignore_old_handshakes: # Load exisitng PMKID hash from filesystem pmkid_file = self.get_existing_pmkid_file(self.target.bssid) if pmkid_file is not None: diff --git a/wifite/attack/wep.py b/wifite/attack/wep.py index cef71cfd9..92be0742d 100755 --- a/wifite/attack/wep.py +++ b/wifite/attack/wep.py @@ -154,8 +154,7 @@ def run(self): ivs_files = ivs_files[-1] # Use most-recent .ivs file aircrack = Aircrack(ivs_files) - elif Configuration.wep_restart_aircrack > 0 and \ - aircrack.pid.running_time() > Configuration.wep_restart_aircrack: + elif 0 < Configuration.wep_restart_aircrack < aircrack.pid.running_time(): # Restart aircrack after X seconds #Color.pl('\n{+} {C}aircrack{W} ran for more than {C}%d{W} seconds, restarting' % Configuration.wep_restart_aircrack) aircrack.stop() @@ -223,9 +222,9 @@ def run(self): Color.pl('\n{!} restarting {C}aireplay{W} after' + ' {C}%d{W} seconds of no new IVs' % stale_seconds) - aireplay = Aireplay(self.target, \ - wep_attack_type, \ - client_mac=client_mac, \ + aireplay = Aireplay(self.target, + wep_attack_type, + client_mac=client_mac, replay_file=replay_file) time_unchanged_ivs = time.time() last_ivs_count = airodump_target.ivs diff --git a/wifite/attack/wpa.py b/wifite/attack/wpa.py index 199965bbd..64f09a3cf 100755 --- a/wifite/attack/wpa.py +++ b/wifite/attack/wpa.py @@ -96,7 +96,7 @@ def capture_handshake(self): self.clients = [] # Try to load existing handshake - if Configuration.ignore_old_handshakes == False: + if not Configuration.ignore_old_handshakes: bssid = airodump_target.bssid essid = airodump_target.essid if airodump_target.essid_known else None handshake = self.load_handshake(bssid=bssid, essid=essid) @@ -171,7 +171,7 @@ def capture_handshake(self): if handshake is None: # No handshake, attack failed. - Color.pl('\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds' % (Configuration.wpa_attack_timeout)) + Color.pl('\n{!} {O}WPA handshake capture {R}FAILED:{O} Timed out after %d seconds' % Configuration.wpa_attack_timeout) return handshake else: # Save copy of handshake to ./hs/ diff --git a/wifite/config.py b/wifite/config.py index 9759ff5b5..d2ccc7faf 100755 --- a/wifite/config.py +++ b/wifite/config.py @@ -117,6 +117,9 @@ def initialize(cls, load_interface=True): cls.check_handshake = None cls.crack_handshake = False + # A list to cache all checked commands (e.g. `which hashcat` will execute only once) + cls.existing_commands = {} + # Overwrite config values with arguments (if defined) cls.load_from_arguments() @@ -193,15 +196,15 @@ def parse_settings_args(cls, args): Color.pl('{+} {C}option:{W} targeting BSSID ' + '{G}%s{W}' % args.target_bssid) - if args.five_ghz == True: + if args.five_ghz: cls.five_ghz = True Color.pl('{+} {C}option:{W} including {G}5Ghz networks{W} in scans') - if args.show_bssids == True: + if args.show_bssids: cls.show_bssids = True Color.pl('{+} {C}option:{W} showing {G}bssids{W} of targets during scan') - if args.no_deauth == True: + if args.no_deauth: cls.no_deauth = True Color.pl('{+} {C}option:{W} will {R}not{W} {O}deauth{W} clients ' + 'during scans or captures') @@ -220,7 +223,7 @@ def parse_settings_args(cls, args): Color.pl('{+} {C}option:{W} {O}ignoring ESSIDs that include {R}%s{W}' % ( args.ignore_essid)) - if args.clients_only == True: + if args.clients_only: cls.clients_only = True Color.pl('{+} {C}option:{W} {O}ignoring targets that do not have ' + 'associated clients') diff --git a/wifite/model/handshake.py b/wifite/model/handshake.py index 630357047..fd4ccb825 100755 --- a/wifite/model/handshake.py +++ b/wifite/model/handshake.py @@ -183,7 +183,7 @@ def print_pairs(pairs, capfile, tool=None): tool_str = '{C}%s{W}: ' % tool.rjust(8) if len(pairs) == 0: - Color.pl('{!} %s.cap file {R}does not{O} contain a valid handshake{W}' % (tool_str)) + Color.pl('{!} %s.cap file {R}does not{O} contain a valid handshake{W}' % capfile) return for (bssid, essid) in pairs: diff --git a/wifite/tools/aircrack.py b/wifite/tools/aircrack.py index bb0bbe228..26d7b1999 100755 --- a/wifite/tools/aircrack.py +++ b/wifite/tools/aircrack.py @@ -101,7 +101,6 @@ def crack_handshake(handshake, show_command=False): # Report progress of cracking aircrack_nums_re = re.compile(r'(\d+)/(\d+) keys tested.*\(([\d.]+)\s+k/s') aircrack_key_re = re.compile(r'Current passphrase:\s*([^\s].*[^\s])\s*$') - num_tried = num_total = 0 percent = num_kps = 0.0 eta_str = 'unknown' current_key = '' diff --git a/wifite/tools/aireplay.py b/wifite/tools/aireplay.py index 07cb6b777..90481d06c 100755 --- a/wifite/tools/aireplay.py +++ b/wifite/tools/aireplay.py @@ -250,8 +250,7 @@ def get_aireplay_command(target, attack_type, if Configuration.interface is None: raise Exception('Wireless interface must be defined (-i)') - cmd = ['aireplay-ng'] - cmd.append('--ignore-negative-one') + cmd = ['aireplay-ng', '--ignore-negative-one'] if client_mac is None and len(target.clients) > 0: # Client MAC wasn't specified, but there's an associated client. Use that. diff --git a/wifite/tools/airmon.py b/wifite/tools/airmon.py index a2a45381b..9cbda290e 100755 --- a/wifite/tools/airmon.py +++ b/wifite/tools/airmon.py @@ -121,7 +121,7 @@ def start_bad_driver(iface): iface_type_path = os.path.join('/sys/class/net', iface, 'type') if os.path.exists(iface_type_path): with open(iface_type_path, 'r') as f: - if (int(f.read()) == Airmon.ARPHRD_IEEE80211_RADIOTAP): + if int(f.read()) == Airmon.ARPHRD_IEEE80211_RADIOTAP: return iface return None @@ -140,7 +140,7 @@ def stop_bad_driver(iface): iface_type_path = os.path.join('/sys/class/net', iface, 'type') if os.path.exists(iface_type_path): with open(iface_type_path, 'r') as f: - if (int(f.read()) == Airmon.ARPHRD_ETHER): + if int(f.read()) == Airmon.ARPHRD_ETHER: return iface return None @@ -283,7 +283,7 @@ def ask(): # Assume we're using the device already in montior mode iface = monitor_interfaces[0] Color.clear_entire_line() - Color.pl('{+} Using {G}%s{W} already in monitor mode' % iface); + Color.pl('{+} Using {G}%s{W} already in monitor mode' % iface) Airmon.base_interface = None return iface @@ -308,7 +308,7 @@ def ask(): choice = 1 else: # Multiple interfaces found - question = Color.s('{+} Select wireless interface ({G}1-%d{W}): ' % (count)) + question = Color.s('{+} Select wireless interface ({G}1-%d{W}): ' % count) choice = raw_input(question) iface = a.get(choice) @@ -373,7 +373,7 @@ def terminate_conflicting_processes(): @staticmethod def put_interface_up(iface): - Color.p('{!} {O}putting interface {R}%s up{O}...' % (iface)) + Color.p('{!} {O}putting interface {R}%s up{O}...' % iface) Ifconfig.up(iface) Color.pl(' {G}done{W}') diff --git a/wifite/tools/airodump.py b/wifite/tools/airodump.py index 0092af117..8b3db60fb 100755 --- a/wifite/tools/airodump.py +++ b/wifite/tools/airodump.py @@ -225,7 +225,7 @@ def get_targets_from_csv(csv_filename): # The current row corresponds to a 'Client' (computer) try: client = Client(row) - except (IndexError, ValueError) as e: + except (IndexError, ValueError): # Skip if we can't parse the client row continue diff --git a/wifite/tools/dependency.py b/wifite/tools/dependency.py index c1a11b22e..3d3f90610 100755 --- a/wifite/tools/dependency.py +++ b/wifite/tools/dependency.py @@ -24,15 +24,11 @@ def exists(cls): def run_dependency_check(cls): from ..util.color import Color - from .airmon import Airmon - from .airodump import Airodump from .aircrack import Aircrack - from .aireplay import Aireplay from .ifconfig import Ifconfig from .iwconfig import Iwconfig from .bully import Bully from .reaver import Reaver - from .wash import Wash from .pyrit import Pyrit from .tshark import Tshark from .macchanger import Macchanger diff --git a/wifite/tools/hashcat.py b/wifite/tools/hashcat.py index 89aa01731..30ff8b26e 100755 --- a/wifite/tools/hashcat.py +++ b/wifite/tools/hashcat.py @@ -26,8 +26,8 @@ def crack_handshake(handshake, show_command=False): hccapx_file = HcxPcapTool.generate_hccapx_file( handshake, show_command=show_command) - key = None # Crack hccapx + key = None # Avoid unresolved reference when hccapx not cracked for additional_arg in ([], ['--show']): command = [ 'hashcat', diff --git a/wifite/tools/pyrit.py b/wifite/tools/pyrit.py index 90e16920a..76b829ad4 100755 --- a/wifite/tools/pyrit.py +++ b/wifite/tools/pyrit.py @@ -39,7 +39,7 @@ def bssid_essid_with_handshakes(capfile, bssid=None, essid=None): for line in pyrit.stdout().split('\n'): mac_regex = ('[a-zA-Z0-9]{2}:' * 6)[:-1] - match = re.search("^#\d+: AccessPoint (%s) \('(.*)'\):$" % (mac_regex), line) + match = re.search("^#\d+: AccessPoint (%s) \('(.*)'\):$" % mac_regex, line) if match: # We found a new BSSID and ESSID (current_bssid, current_essid) = match.groups() diff --git a/wifite/tools/wash.py b/wifite/tools/wash.py index 2ef48382b..201df1017 100755 --- a/wifite/tools/wash.py +++ b/wifite/tools/wash.py @@ -43,7 +43,7 @@ def check_for_wps_and_update_targets(capfile, targets): obj = json.loads(line) bssid = obj['bssid'] locked = obj['wps_locked'] - if locked != True: + if not locked: wps_bssids.add(bssid) else: locked_bssids.add(bssid) diff --git a/wifite/util/crack.py b/wifite/util/crack.py index 68ee19bb6..aa001b6c6 100755 --- a/wifite/util/crack.py +++ b/wifite/util/crack.py @@ -38,6 +38,8 @@ def run(cls): if not Configuration.wordlist: Color.p('\n{+} Enter wordlist file to use for cracking: {G}') Configuration.wordlist = raw_input() + Color.p('{W}') + if not os.path.exists(Configuration.wordlist): Color.pl('{!} {R}Wordlist {O}%s{R} not found. Exiting.' % Configuration.wordlist) return @@ -83,6 +85,8 @@ def run(cls): 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() + Color.p('{W}') + if tool_name not in available_tools: Color.pl('{!} {R}"%s"{O} tool not found, defaulting to {C}aircrack{W}' % tool_name) tool_name = 'aircrack' @@ -92,6 +96,7 @@ def run(cls): if tool_name != 'hashcat' and hs['type'] == 'PMKID': if 'hashcat' in missing_tools: Color.pl('{!} {O}Hashcat is missing, therefore we cannot crack PMKID hash{W}') + continue cls.crack(hs, tool_name) except KeyboardInterrupt: Color.pl('\n{!} {O}Interrupted{W}') @@ -206,6 +211,7 @@ def get_user_selection(cls, handshakes): Color.p('{+} Select handshake(s) to crack ({G}%d{W}-{G}%d{W}, select multiple with {C},{W} or {C}-{W} or {C}all{W}): {G}' % (1, len(handshakes))) choices = raw_input() + Color.p('{W}') selection = [] for choice in choices.split(','): diff --git a/wifite/util/process.py b/wifite/util/process.py index 1200d6b3d..7168f8d83 100755 --- a/wifite/util/process.py +++ b/wifite/util/process.py @@ -43,7 +43,6 @@ def call(command, cwd=None, shell=False): if type(stdout) is bytes: stdout = stdout.decode('utf-8') if type(stderr) is bytes: stderr = stderr.decode('utf-8') - if Configuration.verbose > 1 and stdout is not None and stdout.strip() != '': Color.pe('{P} [stdout] %s{W}' % '\n [stdout] '.join(stdout.strip().split('\n'))) if Configuration.verbose > 1 and stderr is not None and stderr.strip() != '': @@ -54,14 +53,19 @@ def call(command, cwd=None, shell=False): @staticmethod def exists(program): ''' Checks if program is installed on this system ''' + + if Configuration.initialized: # Maybe we already checked this program + if program in set(Configuration.existing_commands.keys()): + return Configuration.existing_commands[program] + p = Process(['which', program]) stdout = p.stdout().strip() stderr = p.stderr().strip() - if stdout == '' and stderr == '': - return False - - return True + exist = not stdout == stderr == '' + if Configuration.initialized: + Configuration.existing_commands.update({program: exist}) + return exist def __init__(self, command, devnull=False, stdout=PIPE, stderr=PIPE, cwd=None, bufsize=0, stdin=PIPE): ''' Starts executing command ''' @@ -211,4 +215,3 @@ def interrupt(self, wait_time=2.0): time.sleep(1) print('yes should stop now') # After program loses reference to instance in 'p', process dies. -