10 Commits

Author SHA1 Message Date
Alexandre CHAZAL
cfeaa3f066 Update README.md 2019-04-22 17:18:59 +08:00
104e45637b Migrated from ifconfig to ip 2019-01-27 17:11:56 +01:00
4baf8f5c46 Forgot to push this file. 2019-01-27 12:49:24 +01:00
Alexandre CHAZAL
5badcf2488 Update README.md 2019-01-27 12:43:10 +01:00
ceebb14ea8 Migrated from iwconfig to iw 2019-01-27 12:39:59 +01:00
derv82
e190794149 Use enums to describe target WPS state.
To avoid confusion about wps = True/False/None.
Came about because of #130
2018-09-09 10:39:57 -07:00
WhiteOnBlackCode
355f891d0f Created PMKID argument group (#136)
* Added PMKID argument group
2018-09-09 09:47:54 -07:00
derv82
710dd98b66 Detect when --dict is a directory, show warning and ignore wordlist.
In case people pass in a directory, until we figure out #135
2018-09-03 17:02:27 -07:00
derv82
79b2753929 Small fixes for #133
* Avoid cracking the same PMKID twice when selecting multiple files &
specifying a tool that is not hashcat.

* Mention PMKID hashes can only be cracked using hashcat:
  1. If all files are PMKID, or
  2. If the file is PMKID but a tool other than hashcat was chosen.

* Fix header colors if a warning is printed before the handshake files.
2018-09-03 11:02:34 -07:00
WhiteOnBlackCode
6d492aca44 Do not show handshake files that are in cracked.txt with a key (match on filename) (#133)
Make cracked.txt a configurable variable
* Do not show handshake files that are in cracked.txt with a key (match on filename).
* Don't ask user for a crack-tool when attacking PMKIDs only
* Few minor cleanups

Fixed any_pmkid -> all_pmkid (to decide that we are strictly using hashcat)
* Added a safe-check to make sure we are indeed using hashcat for the PMKID hashes
* Changed the ugly split() to basename()

Making an FR from the TODO
2018-09-03 10:53:59 -07:00
20 changed files with 245 additions and 183 deletions

View File

@@ -1,3 +1,9 @@
Fork note
=========
This fork has made the migration from the deprecated iwconfig and ifconfig to iw and ip.
I also added an option to disable monitor mode on the wifi antenna after wifite quits.
Wifite Wifite
====== ======
@@ -29,7 +35,7 @@ Second, only the latest versions of these programs are supported and must be ins
**Required:** **Required:**
* `python`: Wifite is compatible with both `python2` and `python3`. * `python`: Wifite is compatible with both `python2` and `python3`.
* [`iwconfig`](https://wiki.debian.org/iwconfig): For identifying wireless devices already in Monitor Mode. * [`iw`](https://wireless.wiki.kernel.org/en/users/documentation/iw): For identifying wireless devices already in Monitor Mode.
* [`ifconfig`](https://en.wikipedia.org/wiki/Ifconfig): For starting/stopping wireless devices. * [`ifconfig`](https://en.wikipedia.org/wiki/Ifconfig): For starting/stopping wireless devices.
* [`Aircrack-ng`](http://aircrack-ng.org/) suite, includes: * [`Aircrack-ng`](http://aircrack-ng.org/) suite, includes:
* [`airmon-ng`](https://tools.kali.org/wireless-attacks/airmon-ng): For enumerating and enabling Monitor Mode on wireless devices. * [`airmon-ng`](https://tools.kali.org/wireless-attacks/airmon-ng): For enumerating and enabling Monitor Mode on wireless devices.

View File

@@ -31,6 +31,7 @@ class Arguments(object):
self._add_wep_args(parser.add_argument_group(Color.s('{C}WEP{W}'))) self._add_wep_args(parser.add_argument_group(Color.s('{C}WEP{W}')))
self._add_wpa_args(parser.add_argument_group(Color.s('{C}WPA{W}'))) self._add_wpa_args(parser.add_argument_group(Color.s('{C}WPA{W}')))
self._add_wps_args(parser.add_argument_group(Color.s('{C}WPS{W}'))) self._add_wps_args(parser.add_argument_group(Color.s('{C}WPS{W}')))
self._add_pmkid_args(parser.add_argument_group(Color.s('{C}PMKID{W}')))
self._add_eviltwin_args(parser.add_argument_group(Color.s('{C}EVIL TWIN{W}'))) self._add_eviltwin_args(parser.add_argument_group(Color.s('{C}EVIL TWIN{W}')))
self._add_command_args(parser.add_argument_group(Color.s('{C}COMMANDS{W}'))) self._add_command_args(parser.add_argument_group(Color.s('{C}COMMANDS{W}')))
@@ -153,6 +154,11 @@ class Arguments(object):
help=self._verbose('Number of deauth packets to send (default: ' + help=self._verbose('Number of deauth packets to send (default: ' +
'{G}%d{W})' % self.config.num_deauths)) '{G}%d{W})' % self.config.num_deauths))
glob.add_argument('--demon',
action='store_true',
dest='demon',
help=Color.s('Puts device back in managed mode after quitting (default: '+
'{G}off{W})'))
def _add_eviltwin_args(self, group): def _add_eviltwin_args(self, group):
pass pass
@@ -292,23 +298,6 @@ class Arguments(object):
wpa.add_argument('-wpa', help=argparse.SUPPRESS, action='store_true', wpa.add_argument('-wpa', help=argparse.SUPPRESS, action='store_true',
dest='wpa_filter') dest='wpa_filter')
wpa.add_argument('--pmkid',
action='store_true',
dest='use_pmkid_only',
help=Color.s('{O}Only{W} use {C}PMKID capture{W}, avoids other WPS & ' +
'WPA attacks (default: {G}off{W})'))
# Alias
wpa.add_argument('-pmkid', action='store_true', dest='use_pmkid_only',
help=argparse.SUPPRESS)
wpa.add_argument('--pmkid-timeout',
action='store',
dest='pmkid_timeout',
metavar='[sec]',
type=int,
help=self._verbose('Time to wait for PMKID capture ' +
'(default: {G}%d{W} seconds)' % self.config.pmkid_timeout))
wpa.add_argument('--hs-dir', wpa.add_argument('--hs-dir',
action='store', action='store',
dest='wpa_handshake_dir', dest='wpa_handshake_dir',
@@ -443,6 +432,22 @@ class Arguments(object):
wps.add_argument('-wpsto', help=argparse.SUPPRESS, action='store', wps.add_argument('-wpsto', help=argparse.SUPPRESS, action='store',
dest='wps_timeout_threshold', type=int) dest='wps_timeout_threshold', type=int)
def _add_pmkid_args(self, pmkid):
pmkid.add_argument('--pmkid',
action='store_true',
dest='use_pmkid_only',
help=Color.s('{O}Only{W} use {C}PMKID capture{W}, avoids other WPS & ' +
'WPA attacks (default: {G}off{W})'))
# Alias
pmkid.add_argument('-pmkid', help=argparse.SUPPRESS, action='store_true', dest='use_pmkid_only')
pmkid.add_argument('--pmkid-timeout',
action='store',
dest='pmkid_timeout',
metavar='[sec]',
type=int,
help=Color.s('Time to wait for PMKID capture ' +
'(default: {G}%d{W} seconds)' % self.config.pmkid_timeout))
def _add_command_args(self, commands): def _add_command_args(self, commands):
commands.add_argument('--cracked', commands.add_argument('--cracked',
@@ -470,7 +475,7 @@ class Arguments(object):
if __name__ == '__main__': if __name__ == '__main__':
from .util.color import Color from .util.color import Color
from config import Configuration from .config import Configuration
Configuration.initialize(False) Configuration.initialize(False)
a = Arguments(Configuration) a = Arguments(Configuration)
args = a.args args = a.args

View File

@@ -5,7 +5,7 @@ from ..model.attack import Attack
from ..tools.airodump import Airodump from ..tools.airodump import Airodump
from ..tools.aireplay import Aireplay, WEPAttackType from ..tools.aireplay import Aireplay, WEPAttackType
from ..tools.aircrack import Aircrack from ..tools.aircrack import Aircrack
from ..tools.ifconfig import Ifconfig from ..tools.ip import Ip
from ..config import Configuration from ..config import Configuration
from ..util.color import Color from ..util.color import Color
from ..util.input import raw_input from ..util.input import raw_input
@@ -67,7 +67,7 @@ class AttackWEP(Attack):
if self.fake_auth(): if self.fake_auth():
# We successfully authenticated! # We successfully authenticated!
# Use our interface's MAC address for the attacks. # Use our interface's MAC address for the attacks.
client_mac = Ifconfig.get_mac(Configuration.interface) client_mac = Ip.get_mac(Configuration.interface)
# Keep us authenticated # Keep us authenticated
fakeauth_proc = Aireplay(self.target, 'fakeauth') fakeauth_proc = Aireplay(self.target, 'fakeauth')
elif len(airodump_target.clients) == 0: elif len(airodump_target.clients) == 0:
@@ -303,7 +303,7 @@ class AttackWEP(Attack):
Color.p('\r{+} {O}Deauthenticating *broadcast*{W} (all clients)...') Color.p('\r{+} {O}Deauthenticating *broadcast*{W} (all clients)...')
Aireplay.deauth(target.bssid, essid=target.essid) Aireplay.deauth(target.bssid, essid=target.essid)
attacking_mac = Ifconfig.get_mac(Configuration.interface) attacking_mac = Ip.get_mac(Configuration.interface)
for client in target.clients: for client in target.clients:
if attacking_mac.lower() == client.station.lower(): if attacking_mac.lower() == client.station.lower():
continue # Don't deauth ourselves. continue # Don't deauth ourselves.

View File

@@ -48,6 +48,7 @@ class Configuration(object):
cls.random_mac = False # Should generate a random Mac address at startup. cls.random_mac = False # Should generate a random Mac address at startup.
cls.no_deauth = False # Deauth hidden networks & WPA handshake targets cls.no_deauth = False # Deauth hidden networks & WPA handshake targets
cls.num_deauths = 1 # Number of deauth packets to send to each target. cls.num_deauths = 1 # Number of deauth packets to send to each target.
cls.demon = False # Don't put back interface back in managed mode
cls.encryption_filter = ['WEP', 'WPA', 'WPS'] cls.encryption_filter = ['WEP', 'WPA', 'WPS']
@@ -78,10 +79,13 @@ class Configuration(object):
cls.wpa_handshake_dir = 'hs' # Dir to store handshakes cls.wpa_handshake_dir = 'hs' # Dir to store handshakes
cls.wpa_strip_handshake = False # Strip non-handshake packets cls.wpa_strip_handshake = False # Strip non-handshake packets
cls.ignore_old_handshakes = False # Always fetch a new handshake cls.ignore_old_handshakes = False # Always fetch a new handshake
# PMKID variables
cls.use_pmkid_only = False # Only use PMKID Capture+Crack attack cls.use_pmkid_only = False # Only use PMKID Capture+Crack attack
cls.pmkid_timeout = 30 # Time to wait for PMKID capture cls.pmkid_timeout = 30 # Time to wait for PMKID capture
# Default dictionary for cracking # Default dictionary for cracking
cls.cracked_file = 'cracked.txt'
cls.wordlist = None cls.wordlist = None
wordlists = [ wordlists = [
'./wordlist-top4800-probable.txt', # Local file (ran from cloned repo) './wordlist-top4800-probable.txt', # Local file (ran from cloned repo)
@@ -140,6 +144,7 @@ class Configuration(object):
cls.parse_wep_args(args) cls.parse_wep_args(args)
cls.parse_wpa_args(args) cls.parse_wpa_args(args)
cls.parse_wps_args(args) cls.parse_wps_args(args)
cls.parse_pmkid_args(args)
cls.parse_encryption() cls.parse_encryption()
# EvilTwin # EvilTwin
@@ -169,6 +174,7 @@ class Configuration(object):
@classmethod @classmethod
def parse_settings_args(cls, args): def parse_settings_args(cls, args):
'''Parses basic settings/configurations from arguments.''' '''Parses basic settings/configurations from arguments.'''
if args.random_mac: if args.random_mac:
cls.random_mac = True cls.random_mac = True
Color.pl('{+} {C}option:{W} using {G}random mac address{W} ' + Color.pl('{+} {C}option:{W} using {G}random mac address{W} ' +
@@ -202,6 +208,10 @@ class Configuration(object):
Color.pl('{+} {C}option:{W} will {R}not{W} {O}deauth{W} clients ' + Color.pl('{+} {C}option:{W} will {R}not{W} {O}deauth{W} clients ' +
'during scans or captures') 'during scans or captures')
if args.demon == True:
cls.demon = True
Color.pl('{+} {C}option:{W} will put interface back to managed mode')
if args.num_deauths and args.num_deauths > 0: if args.num_deauths and args.num_deauths > 0:
cls.num_deauths = args.num_deauths cls.num_deauths = args.num_deauths
Color.pl('{+} {C}option:{W} send {G}%d{W} deauth packets when deauthing' % ( Color.pl('{+} {C}option:{W} send {G}%d{W} deauth packets when deauthing' % (
@@ -282,12 +292,15 @@ class Configuration(object):
cls.wpa_filter = args.wpa_filter cls.wpa_filter = args.wpa_filter
if args.wordlist: if args.wordlist:
if os.path.exists(args.wordlist): if not os.path.exists(args.wordlist):
cls.wordlist = args.wordlist
Color.pl('{+} {C}option:{W} using wordlist {G}%s{W} to crack WPA handshakes' % args.wordlist)
else:
cls.wordlist = None cls.wordlist = None
Color.pl('{+} {C}option:{O} wordlist {R}%s{O} was not found, wifite will NOT attempt to crack handshakes' % args.wordlist) Color.pl('{+} {C}option:{O} wordlist {R}%s{O} was not found, wifite will NOT attempt to crack handshakes' % args.wordlist)
elif os.path.isfile(args.wordlist):
cls.wordlist = args.wordlist
Color.pl('{+} {C}option:{W} using wordlist {G}%s{W} to crack WPA handshakes' % args.wordlist)
elif os.path.isdir(args.wordlist):
cls.wordlist = None
Color.pl('{+} {C}option:{O} wordlist {R}%s{O} is a directory, not a file. Wifite will NOT attempt to crack handshakes' % args.wordlist)
if args.wpa_deauth_timeout: if args.wpa_deauth_timeout:
cls.wpa_deauth_timeout = args.wpa_deauth_timeout cls.wpa_deauth_timeout = args.wpa_deauth_timeout
@@ -304,14 +317,6 @@ class Configuration(object):
Color.pl('{+} {C}option:{W} will {O}ignore{W} existing handshakes ' + Color.pl('{+} {C}option:{W} will {O}ignore{W} existing handshakes ' +
'(force capture)') '(force capture)')
if args.use_pmkid_only:
cls.use_pmkid_only = True
Color.pl('{+} {C}option:{W} will ONLY use {C}PMKID{W} attack on WPA networks')
if args.pmkid_timeout:
cls.pmkid_timeout = args.pmkid_timeout
Color.pl('{+} {C}option:{W} will wait {G}%d{W} seconds during {C}PMKID{W} capture')
if args.wpa_handshake_dir: if args.wpa_handshake_dir:
cls.wpa_handshake_dir = args.wpa_handshake_dir cls.wpa_handshake_dir = args.wpa_handshake_dir
Color.pl('{+} {C}option:{W} will store handshakes to ' + Color.pl('{+} {C}option:{W} will store handshakes to ' +
@@ -356,7 +361,7 @@ class Configuration(object):
'(no {O}Pixie-Dust{W}) on targets') '(no {O}Pixie-Dust{W}) on targets')
if args.use_bully: if args.use_bully:
from tools.bully import Bully from .tools.bully import Bully
if not Bully.exists(): if not Bully.exists():
Color.pl('{!} {R}Bully not found. Defaulting to {O}reaver{W}') Color.pl('{!} {R}Bully not found. Defaulting to {O}reaver{W}')
cls.use_bully = False cls.use_bully = False
@@ -384,6 +389,16 @@ class Configuration(object):
cls.wps_ignore_lock = True cls.wps_ignore_lock = True
Color.pl('{+} {C}option:{W} will {O}ignore{W} WPS lock-outs') Color.pl('{+} {C}option:{W} will {O}ignore{W} WPS lock-outs')
@classmethod
def parse_pmkid_args(cls, args):
if args.use_pmkid_only:
cls.use_pmkid_only = True
Color.pl('{+} {C}option:{W} will ONLY use {C}PMKID{W} attack on WPA networks')
if args.pmkid_timeout:
cls.pmkid_timeout = args.pmkid_timeout
Color.pl('{+} {C}option:{W} will wait {G}%d seconds{W} during {C}PMKID{W} capture' % args.pmkid_timeout)
@classmethod @classmethod
def parse_encryption(cls): def parse_encryption(cls):
'''Adjusts encryption filter (WEP and/or WPA and/or WPS)''' '''Adjusts encryption filter (WEP and/or WPA and/or WPS)'''
@@ -406,9 +421,9 @@ class Configuration(object):
def parse_wep_attacks(cls): def parse_wep_attacks(cls):
'''Parses and sets WEP-specific args (-chopchop, -fragment, etc)''' '''Parses and sets WEP-specific args (-chopchop, -fragment, etc)'''
cls.wep_attacks = [] cls.wep_attacks = []
import sys from sys import argv
seen = set() seen = set()
for arg in sys.argv: for arg in argv:
if arg in seen: continue if arg in seen: continue
seen.add(arg) seen.add(arg)
if arg == '-arpreplay': cls.wep_attacks.append('replay') if arg == '-arpreplay': cls.wep_attacks.append('replay')
@@ -465,14 +480,15 @@ class Configuration(object):
Macchanger.reset_if_changed() Macchanger.reset_if_changed()
from .tools.airmon import Airmon from .tools.airmon import Airmon
if cls.interface is not None and Airmon.base_interface is not None: if cls.interface is not None and Airmon.base_interface is not None:
if not cls.demon:
Color.pl('{!} {O}Note:{W} Leaving interface in Monitor Mode!') Color.pl('{!} {O}Note:{W} Leaving interface in Monitor Mode!')
Color.pl('{!} To disable Monitor Mode when finished: ' + Color.pl('{!} To disable Monitor Mode when finished: ' +
'{C}airmon-ng stop %s{W}' % cls.interface) '{C}airmon-ng stop %s{W}' % cls.interface)
else:
# Stop monitor mode # Stop monitor mode
#Airmon.stop(cls.interface) Airmon.stop(cls.interface)
# Bring original interface back up # Bring original interface back up
#Airmon.put_interface_up(Airmon.base_interface) Airmon.put_interface_up(Airmon.base_interface)
if Airmon.killed_network_manager: if Airmon.killed_network_manager:
Color.pl('{!} You can restart NetworkManager when finished ({C}service network-manager start{W})') Color.pl('{!} You can restart NetworkManager when finished ({C}service network-manager start{W})')

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from ..util.color import Color from ..util.color import Color
from ..config import Configuration
import os import os
import time import time
@@ -11,7 +12,7 @@ class CrackResult(object):
''' Abstract class containing results from a crack session ''' ''' Abstract class containing results from a crack session '''
# File to save cracks to, in PWD # File to save cracks to, in PWD
cracked_file = 'cracked.txt' cracked_file = Configuration.cracked_file
def __init__(self): def __init__(self):
self.date = int(time.time()) self.date = int(time.time())
@@ -55,8 +56,8 @@ class CrackResult(object):
this_dict['date'] = entry.get('date') this_dict['date'] = entry.get('date')
if entry == this_dict: if entry == this_dict:
# Skip if we already saved this BSSID+ESSID+TYPE+KEY # Skip if we already saved this BSSID+ESSID+TYPE+KEY
Color.pl('{+} {C}%s{O} already exists in {G}cracked.txt{O}, skipping.' % ( Color.pl('{+} {C}%s{O} already exists in {G}%s{O}, skipping.' % (
self.essid)) self.essid, Configuration.cracked_file))
return return
saved_results.append(self.to_dict()) saved_results.append(self.to_dict())
@@ -67,7 +68,7 @@ class CrackResult(object):
@classmethod @classmethod
def display(cls): def display(cls):
''' Show cracked targets from cracked.txt ''' ''' Show cracked targets from cracked file '''
name = cls.cracked_file name = cls.cracked_file
if not os.path.exists(name): if not os.path.exists(name):
Color.pl('{!} {O}file {C}%s{O} not found{W}' % name) Color.pl('{!} {O}file {C}%s{O} not found{W}' % name)

View File

@@ -5,6 +5,11 @@ from ..util.color import Color
import re import re
class WPSState:
NONE, UNLOCKED, LOCKED, UNKNOWN = range(0, 4)
class Target(object): class Target(object):
''' '''
Holds details for a 'Target' aka Access Point (e.g. router). Holds details for a 'Target' aka Access Point (e.g. router).
@@ -60,8 +65,7 @@ class Target(object):
self.essid = None # '(%s)' % self.bssid self.essid = None # '(%s)' % self.bssid
self.essid_known = False self.essid_known = False
# False=No WPS, None=Locked WPS, True=Unlocked WPS self.wps = WPSState.UNKNOWN
self.wps = False
self.decloaked = False # If ESSID was hidden but we decloaked it. self.decloaked = False # If ESSID was hidden but we decloaked it.
@@ -133,13 +137,14 @@ class Target(object):
color = 'R' color = 'R'
power = Color.s('{%s}%s' % (color, power)) power = Color.s('{%s}%s' % (color, power))
wps = Color.s('{O} n/a') if self.wps == WPSState.UNLOCKED:
if self.wps == True:
wps = Color.s('{G} yes') wps = Color.s('{G} yes')
elif self.wps == False: elif self.wps == WPSState.NONE:
wps = Color.s('{O} no') wps = Color.s('{O} no')
elif self.wps is None: elif self.wps == WPSState.LOCKED:
wps = Color.s('{R}lock') wps = Color.s('{R}lock')
elif self.wps == WPSState.UNKNOWN:
wps = Color.s('{O} n/a')
clients = ' ' clients = ' '
if len(self.clients) > 0: if len(self.clients) > 0:

View File

@@ -2,8 +2,8 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .dependency import Dependency from .dependency import Dependency
from .ifconfig import Ifconfig from .ip import Ip
from .iwconfig import Iwconfig from .iw import Iw
from ..util.process import Process from ..util.process import Process
from ..util.color import Color from ..util.color import Color
from ..util.input import raw_input from ..util.input import raw_input
@@ -113,9 +113,9 @@ class Airmon(Dependency):
Manually put interface into monitor mode (no airmon-ng or vif). Manually put interface into monitor mode (no airmon-ng or vif).
Fix for bad drivers like the rtl8812AU. Fix for bad drivers like the rtl8812AU.
''' '''
Ifconfig.down(iface) Ip.down(iface)
Iwconfig.mode(iface, 'monitor') Iw.mode(iface, 'monitor')
Ifconfig.up(iface) Ip.up(iface)
# /sys/class/net/wlan0/type # /sys/class/net/wlan0/type
iface_type_path = os.path.join('/sys/class/net', iface, 'type') iface_type_path = os.path.join('/sys/class/net', iface, 'type')
@@ -132,9 +132,9 @@ class Airmon(Dependency):
Manually put interface into managed mode (no airmon-ng or vif). Manually put interface into managed mode (no airmon-ng or vif).
Fix for bad drivers like the rtl8812AU. Fix for bad drivers like the rtl8812AU.
''' '''
Ifconfig.down(iface) Ip.down(iface)
Iwconfig.mode(iface, 'managed') Iw.mode(iface, 'managed')
Ifconfig.up(iface) Ip.up(iface)
# /sys/class/net/wlan0/type # /sys/class/net/wlan0/type
iface_type_path = os.path.join('/sys/class/net', iface, 'type') iface_type_path = os.path.join('/sys/class/net', iface, 'type')
@@ -182,17 +182,17 @@ class Airmon(Dependency):
if enabled_iface is None: if enabled_iface is None:
Color.pl('{R}failed{W}') Color.pl('{R}failed{W}')
monitor_interfaces = Iwconfig.get_interfaces(mode='Monitor') monitor_interfaces = Iw.get_interfaces(mode='monitor')
# Assert that there is an interface in monitor mode # Assert that there is an interface in monitor mode
if len(monitor_interfaces) == 0: if len(monitor_interfaces) == 0:
Color.pl('{R}failed{W}') Color.pl('{R}failed{W}')
raise Exception('Cannot find any interfaces in Mode:Monitor') raise Exception('Cannot find any interfaces in monitor mode')
# Assert that the interface enabled by airmon-ng is in monitor mode # Assert that the interface enabled by airmon-ng is in monitor mode
if enabled_iface not in monitor_interfaces: if enabled_iface not in monitor_interfaces:
Color.pl('{R}failed{W}') Color.pl('{R}failed{W}')
raise Exception('Cannot find %s with Mode:Monitor' % enabled_iface) raise Exception('Cannot find %s with type:monitor' % enabled_iface)
# No errors found; the device 'enabled_iface' was put into Mode:Monitor. # No errors found; the device 'enabled_iface' was put into Mode:Monitor.
Color.pl('{G}enabled {C}%s{W}' % enabled_iface) Color.pl('{G}enabled {C}%s{W}' % enabled_iface)
@@ -216,20 +216,20 @@ class Airmon(Dependency):
@staticmethod @staticmethod
def stop(iface): def stop(iface):
Color.p('{!} {R}disabling {O}monitor mode{O} on {R}%s{O}... ' % iface) Color.p('{!}{W} Disabling {O}monitor{W} mode on {R}%s{W}...\n' % iface)
airmon_output = Process(['airmon-ng', 'stop', iface]).stdout() airmon_output = Process(['airmon-ng', 'stop', iface]).stdout()
(disabled_iface, enabled_iface) = Airmon._parse_airmon_stop(airmon_output) (disabled_iface, enabled_iface) = Airmon._parse_airmon_stop(airmon_output)
if not disabled_iface and iface in Airmon.BAD_DRIVERS: if not disabled_iface and iface in Airmon.BAD_DRIVERS:
Color.p('{O}"bad driver" detected{W} ') Color.p('{!} {O}"bad driver" detected{W} ')
disabled_iface = Airmon.stop_bad_driver(iface) disabled_iface = Airmon.stop_bad_driver(iface)
if disabled_iface: if disabled_iface:
Color.pl('{G}disabled %s{W}' % disabled_iface) Color.pl('{+}{W} Disabled monitor mode on {G}%s{W}' % disabled_iface)
else: else:
Color.pl('{O}could not disable on {R}%s{W}' % iface) Color.pl('{!} {O}Could not disable {R}%s{W}' % iface)
return (disabled_iface, enabled_iface) return (disabled_iface, enabled_iface)
@@ -278,7 +278,7 @@ class Airmon(Dependency):
Airmon.terminate_conflicting_processes() Airmon.terminate_conflicting_processes()
Color.p('\n{+} Looking for {C}wireless interfaces{W}...') Color.p('\n{+} Looking for {C}wireless interfaces{W}...')
monitor_interfaces = Iwconfig.get_interfaces(mode='Monitor') monitor_interfaces = Iw.get_interfaces(mode='monitor')
if len(monitor_interfaces) == 1: if len(monitor_interfaces) == 1:
# Assume we're using the device already in montior mode # Assume we're using the device already in montior mode
iface = monitor_interfaces[0] iface = monitor_interfaces[0]
@@ -373,9 +373,9 @@ class Airmon(Dependency):
@staticmethod @staticmethod
def put_interface_up(iface): def put_interface_up(iface):
Color.p('{!} {O}putting interface {R}%s up{O}...' % (iface)) Color.p('{!}{W} Putting interface {R}%s{W} {G}up{W}...\n' % (iface))
Ifconfig.up(iface) Ip.up(iface)
Color.pl(' {G}done{W}') Color.pl('{+}{W} Done !')
@staticmethod @staticmethod
def start_network_manager(): def start_network_manager():

View File

@@ -6,7 +6,7 @@ from .tshark import Tshark
from .wash import Wash from .wash import Wash
from ..util.process import Process from ..util.process import Process
from ..config import Configuration from ..config import Configuration
from ..model.target import Target from ..model.target import Target, WPSState
from ..model.client import Client from ..model.client import Client
import os, time import os, time
@@ -18,7 +18,8 @@ class Airodump(Dependency):
dependency_url = 'https://www.aircrack-ng.org/install.html' dependency_url = 'https://www.aircrack-ng.org/install.html'
def __init__(self, interface=None, channel=None, encryption=None,\ def __init__(self, interface=None, channel=None, encryption=None,\
wps=False, target_bssid=None, output_file_prefix='airodump',\ wps=WPSState.UNKNOWN, target_bssid=None,
output_file_prefix='airodump',\
ivs_only=False, skip_wps=False, delete_existing_files=True): ivs_only=False, skip_wps=False, delete_existing_files=True):
'''Sets up airodump arguments, doesn't start process yet.''' '''Sets up airodump arguments, doesn't start process yet.'''
@@ -260,7 +261,7 @@ class Airodump(Dependency):
result.append(target) result.append(target)
elif 'WPA' in Configuration.encryption_filter and 'WPA' in target.encryption: elif 'WPA' in Configuration.encryption_filter and 'WPA' in target.encryption:
result.append(target) result.append(target)
elif 'WPS' in Configuration.encryption_filter and target.wps != False: elif 'WPS' in Configuration.encryption_filter and target.wps in [WPSState.UNLOCKED, WPSState.LOCKED]:
result.append(target) result.append(target)
elif skip_wps: elif skip_wps:
result.append(target) result.append(target)

View File

@@ -134,7 +134,8 @@ class Bully(Attack, Dependency):
return return
else: else:
if self.locked and not Configuration.wps_ignore_lock: if self.locked and not Configuration.wps_ignore_lock:
self.pattack('{R}Failed: {O}AP became {R}Locked{O}', newline=True) self.pattack('{R}Failed: {O}Access point is {R}Locked{O}',
newline=True)
self.stop() self.stop()
return return

View File

@@ -28,8 +28,8 @@ class Dependency(object):
from .airodump import Airodump from .airodump import Airodump
from .aircrack import Aircrack from .aircrack import Aircrack
from .aireplay import Aireplay from .aireplay import Aireplay
from .ifconfig import Ifconfig from .ip import Ip
from .iwconfig import Iwconfig from .iw import Iw
from .bully import Bully from .bully import Bully
from .reaver import Reaver from .reaver import Reaver
from .wash import Wash from .wash import Wash
@@ -42,7 +42,7 @@ class Dependency(object):
# Aircrack # Aircrack
Aircrack, #Airodump, Airmon, Aireplay, Aircrack, #Airodump, Airmon, Aireplay,
# wireless/net tools # wireless/net tools
Iwconfig, Ifconfig, Iw, Ip,
# WPS # WPS
Reaver, Bully, Reaver, Bully,
# Cracking/handshakes # Cracking/handshakes

View File

@@ -5,17 +5,17 @@ import re
from .dependency import Dependency from .dependency import Dependency
class Ifconfig(Dependency): class Ip(Dependency):
dependency_required = True dependency_required = True
dependency_name = 'ifconfig' dependency_name = 'ip'
dependency_url = 'apt-get install net-tools' dependency_url = 'apt-get install ip'
@classmethod @classmethod
def up(cls, interface, args=[]): def up(cls, interface, args=[]):
'''Put interface up''' '''Put interface up'''
from ..util.process import Process from ..util.process import Process
command = ['ifconfig', interface] command = ['ip', 'link', 'set', interface]
if type(args) is list: if type(args) is list:
command.extend(args) command.extend(args)
elif type(args) is 'str': elif type(args) is 'str':
@@ -33,7 +33,7 @@ class Ifconfig(Dependency):
'''Put interface down''' '''Put interface down'''
from ..util.process import Process from ..util.process import Process
pid = Process(['ifconfig', interface, 'down']) pid = Process(['ip', 'link', 'set', interface, 'down'])
pid.wait() pid.wait()
if pid.poll() != 0: if pid.poll() != 0:
raise Exception('Error putting interface %s down:\n%s\n%s' % (interface, pid.stdout(), pid.stderr())) raise Exception('Error putting interface %s down:\n%s\n%s' % (interface, pid.stdout(), pid.stderr()))
@@ -43,19 +43,11 @@ class Ifconfig(Dependency):
def get_mac(cls, interface): def get_mac(cls, interface):
from ..util.process import Process from ..util.process import Process
output = Process(['ifconfig', interface]).stdout() output = Process(['ip', 'link show', interface]).stdout()
# Mac address separated by dashes match = re.search(r'([a-fA-F0-9]{2}[-:]){5}[a-fA-F0-9]{2}', output)
mac_dash_regex = ('[a-zA-Z0-9]{2}-' * 6)[:-1]
match = re.search(' ({})'.format(mac_dash_regex), output)
if match: if match:
return match.group(1).replace('-', ':') return match.group(0).replace('-', ':')
# Mac address separated by colons
mac_colon_regex = ('[a-zA-Z0-9]{2}:' * 6)[:-1]
match = re.search(' ({})'.format(mac_colon_regex), output)
if match:
return match.group(1)
raise Exception('Could not find the mac address for %s' % interface) raise Exception('Could not find the mac address for %s' % interface)

53
wifite/tools/iw.py Executable file
View File

@@ -0,0 +1,53 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .dependency import Dependency
class Iw(Dependency):
dependency_required = True
dependency_name = 'iw'
dependency_url = 'apt-get install iw'
@classmethod
def mode(cls, iface, mode_name):
from ..util.process import Process
pid = None
if mode_name == "monitor":
pid = Process(['iw', iface, 'set monitor control'])
else:
pid = Process(['iw', iface, 'type', mode_name])
pid.wait()
return pid.poll()
@classmethod
def get_interfaces(cls, mode=None):
from ..util.process import Process
import re
ireg = re.compile(r"\s+Interface\s[a-zA-Z0-9]+")
mreg = re.compile(r"\s+type\s[a-zA-z]+")
ires = None
mres = None
interfaces = set()
iface = ''
(out, err) = Process.call('iw dev')
if mode is None:
for line in out.split('\n'):
ires = ireg.search(line)
if ires:
interfaces.add(ires.group().split("Interface")[-1])
else:
for line in out.split('\n'):
ires = ireg.search(line)
mres = mreg.search(line)
if mres:
if mode == mres.group().split("type")[-1][1:]:
interfaces.add(iface)
if ires:
iface = ires.group().split("Interface")[-1][1:]
return list(interfaces)

View File

@@ -1,49 +0,0 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-
from .dependency import Dependency
class Iwconfig(Dependency):
dependency_required = True
dependency_name = 'iwconfig'
dependency_url = 'apt-get install wireless-tools'
@classmethod
def mode(cls, iface, mode_name):
from ..util.process import Process
pid = Process(['iwconfig', iface, 'mode', mode_name])
pid.wait()
return pid.poll()
@classmethod
def get_interfaces(cls, mode=None):
from ..util.process import Process
interfaces = set()
iface = ''
(out, err) = Process.call('iwconfig')
for line in out.split('\n'):
if len(line) == 0: continue
if not line.startswith(' '):
iface = line.split(' ')[0]
if '\t' in iface:
iface = iface.split('\t')[0].strip()
iface = iface.strip()
if len(iface) == 0:
continue
if mode is None:
interfaces.add(iface)
if mode is not None and 'Mode:{}'.format(mode) in line and len(iface) > 0:
interfaces.add(iface)
return list(interfaces)

View File

@@ -2,7 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .dependency import Dependency from .dependency import Dependency
from ..tools.ifconfig import Ifconfig from ..tools.ip import Ip
from ..util.color import Color from ..util.color import Color
class Macchanger(Dependency): class Macchanger(Dependency):
@@ -20,7 +20,7 @@ class Macchanger(Dependency):
Color.clear_entire_line() Color.clear_entire_line()
Color.p('\r{+} {C}macchanger{W}: taking interface {C}%s{W} down...' % iface) Color.p('\r{+} {C}macchanger{W}: taking interface {C}%s{W} down...' % iface)
Ifconfig.down(iface) Ip.down(iface)
Color.clear_entire_line() Color.clear_entire_line()
Color.p('\r{+} {C}macchanger{W}: changing mac address of interface {C}%s{W}...' % iface) Color.p('\r{+} {C}macchanger{W}: changing mac address of interface {C}%s{W}...' % iface)
@@ -38,7 +38,7 @@ class Macchanger(Dependency):
Color.clear_entire_line() Color.clear_entire_line()
Color.p('\r{+} {C}macchanger{W}: bringing interface {C}%s{W} up...' % iface) Color.p('\r{+} {C}macchanger{W}: bringing interface {C}%s{W} up...' % iface)
Ifconfig.up(iface) Ip.up(iface)
return True return True
@@ -56,7 +56,7 @@ class Macchanger(Dependency):
Color.pl('\r{+} {C}macchanger{W}: resetting mac address on %s...' % iface) Color.pl('\r{+} {C}macchanger{W}: resetting mac address on %s...' % iface)
# -p to reset to permanent MAC address # -p to reset to permanent MAC address
if cls.down_macch_up(iface, ['-p']): if cls.down_macch_up(iface, ['-p']):
new_mac = Ifconfig.get_mac(iface) new_mac = Ip.get_mac(iface)
Color.clear_entire_line() Color.clear_entire_line()
Color.pl('\r{+} {C}macchanger{W}: reset mac address back to {C}%s{W} on {C}%s{W}' % (new_mac, iface)) Color.pl('\r{+} {C}macchanger{W}: reset mac address back to {C}%s{W} on {C}%s{W}' % (new_mac, iface))
@@ -76,7 +76,7 @@ class Macchanger(Dependency):
# -e to keep vendor bytes the same # -e to keep vendor bytes the same
if cls.down_macch_up(iface, ['-e']): if cls.down_macch_up(iface, ['-e']):
cls.is_changed = True cls.is_changed = True
new_mac = Ifconfig.get_mac(iface) new_mac = Ip.get_mac(iface)
Color.clear_entire_line() Color.clear_entire_line()
Color.pl('\r{+} {C}macchanger{W}: changed mac address to {C}%s{W} on {C}%s{W}' % (new_mac, iface)) Color.pl('\r{+} {C}macchanger{W}: changed mac address to {C}%s{W} on {C}%s{W}' % (new_mac, iface))

View File

@@ -117,7 +117,7 @@ class Reaver(Attack, Dependency):
# Check if locked # Check if locked
if self.locked and not Configuration.wps_ignore_lock: if self.locked and not Configuration.wps_ignore_lock:
raise Exception('{O}Because access point is {R}Locked{W}') raise Exception('{O}Access point is {R}Locked{W}')
time.sleep(0.5) time.sleep(0.5)

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .dependency import Dependency from .dependency import Dependency
from ..model.target import WPSState
from ..util.process import Process from ..util.process import Process
import re import re
@@ -188,7 +189,6 @@ class Tshark(Dependency):
if ',' not in line: if ',' not in line:
continue continue
bssid, locked = line.split(',') bssid, locked = line.split(',')
# Ignore if WPS is locked?
if '1' not in locked: if '1' not in locked:
wps_bssids.add(bssid.upper()) wps_bssids.add(bssid.upper())
else: else:
@@ -197,11 +197,11 @@ class Tshark(Dependency):
for t in targets: for t in targets:
target_bssid = t.bssid.upper() target_bssid = t.bssid.upper()
if target_bssid in wps_bssids: if target_bssid in wps_bssids:
t.wps = True t.wps = WPSState.UNLOCKED
elif target_bssid in locked_bssids: elif target_bssid in locked_bssids:
t.wps = None t.wps = WPSState.LOCKED
else: else:
t.wps = False t.wps = WPSState.NONE
if __name__ == '__main__': if __name__ == '__main__':
@@ -224,7 +224,8 @@ if __name__ == '__main__':
# Should update 'wps' field of a target # Should update 'wps' field of a target
Tshark.check_for_wps_and_update_targets(test_file, targets) Tshark.check_for_wps_and_update_targets(test_file, targets)
print('Target(BSSID={}).wps = {} (Expected: True)'.format(targets[0].bssid, targets[0].wps)) print('Target(BSSID={}).wps = {} (Expected: 1)'.format(
assert targets[0].wps == True targets[0].bssid, targets[0].wps))
assert targets[0].wps == WPSState.UNLOCKED
print(Tshark.bssids_with_handshakes(test_file, bssid=target_bssid)) print(Tshark.bssids_with_handshakes(test_file, bssid=target_bssid))

View File

@@ -2,6 +2,7 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from .dependency import Dependency from .dependency import Dependency
from ..model.target import WPSState
from ..util.process import Process from ..util.process import Process
import json import json
@@ -53,11 +54,11 @@ class Wash(Dependency):
for t in targets: for t in targets:
target_bssid = t.bssid.upper() target_bssid = t.bssid.upper()
if target_bssid in wps_bssids: if target_bssid in wps_bssids:
t.wps = True t.wps = WPSState.UNLOCKED
elif target_bssid in locked_bssids: elif target_bssid in locked_bssids:
t.wps = None t.wps = WPSState.LOCKED
else: else:
t.wps = False t.wps = WPSState.NONE
if __name__ == '__main__': if __name__ == '__main__':
@@ -80,7 +81,8 @@ if __name__ == '__main__':
# Should update 'wps' field of a target # Should update 'wps' field of a target
Wash.check_for_wps_and_update_targets(test_file, targets) Wash.check_for_wps_and_update_targets(test_file, targets)
print('Target(BSSID={}).wps = {} (Expected: True)'.format(targets[0].bssid, targets[0].wps)) print('Target(BSSID={}).wps = {} (Expected: 1)'.format(
targets[0].bssid, targets[0].wps))
assert targets[0].wps == True assert targets[0].wps == WPSState.UNLOCKED

View File

@@ -97,6 +97,10 @@ class Color(object):
'''Prints an exception. Includes stack trace if necessary.''' '''Prints an exception. Includes stack trace if necessary.'''
Color.pl('\n{!} {R}Error: {O}%s' % str(exception)) Color.pl('\n{!} {R}Error: {O}%s' % str(exception))
# Don't dump trace for the "no targets found" case.
if 'No targets found' in str(exception):
return
from ..config import Configuration from ..config import Configuration
if Configuration.verbose > 0 or Configuration.print_stack_traces: if Configuration.verbose > 0 or Configuration.print_stack_traces:
Color.pl('\n{!} {O}Full stack trace below') Color.pl('\n{!} {O}Full stack trace below')

View File

@@ -13,15 +13,13 @@ from ..tools.cowpatty import Cowpatty
from ..tools.hashcat import Hashcat, HcxPcapTool from ..tools.hashcat import Hashcat, HcxPcapTool
from ..tools.john import John from ..tools.john import John
from datetime import datetime from json import loads
import os import os
# TODO: Bring back the 'print' option, for easy copy/pasting. Just one-liners people can paste into terminal. # TODO: Bring back the 'print' option, for easy copy/pasting. Just one-liners people can paste into terminal.
# 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) # TODO: --no-crack option while attacking targets (implies user will run --crack later)
class CrackHelper: class CrackHelper:
@@ -32,7 +30,6 @@ class CrackHelper:
'PMKID': 'PMKID Hash' 'PMKID': 'PMKID Hash'
} }
@classmethod @classmethod
def run(cls): def run(cls):
Configuration.initialize(False) Configuration.initialize(False)
@@ -53,7 +50,7 @@ class CrackHelper:
return return
hs_to_crack = cls.get_user_selection(handshakes) hs_to_crack = cls.get_user_selection(handshakes)
any_pmkid = any([hs['type'] == 'PMKID' for hs in hs_to_crack]) all_pmkid = all([hs['type'] == 'PMKID' for hs in hs_to_crack])
# Tools for cracking & their dependencies. # Tools for cracking & their dependencies.
available_tools = { available_tools = {
@@ -79,26 +76,46 @@ class CrackHelper:
dep_list = ', '.join([dep.dependency_name for dep in deps]) dep_list = ', '.join([dep.dependency_name for dep in deps])
Color.pl(' {R}* {R}%s {W}({O}%s{W})' % (tool, dep_list)) Color.pl(' {R}* {R}%s {W}({O}%s{W})' % (tool, dep_list))
if all_pmkid:
Color.pl('{!} {O}Note: PMKID hashes can only be cracked using {C}hashcat{W}')
tool_name = 'hashcat'
else:
Color.p('\n{+} Enter the {C}cracking tool{W} to use ({C}%s{W}): {G}' % ( Color.p('\n{+} Enter the {C}cracking tool{W} to use ({C}%s{W}): {G}' % (
'{W}, {C}'.join(available_tools.keys()))) '{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('{!} {R}"%s"{O} tool not found, defaulting to {C}aircrack{W}' % tool_name) Color.pl('{!} {R}"%s"{O} tool not found, defaulting to {C}aircrack{W}' % tool_name)
tool_name = 'aircrack' tool_name = 'aircrack'
elif any_pmkid and tool_name != 'hashcat':
Color.pl('{!} {O}Note: PMKID hashes will be cracked using {C}hashcat{W}')
try: try:
for hs in hs_to_crack: for hs in hs_to_crack:
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}')
cls.crack(hs, tool_name) cls.crack(hs, tool_name)
except KeyboardInterrupt: except KeyboardInterrupt:
Color.pl('\n{!} {O}Interrupted{W}') Color.pl('\n{!} {O}Interrupted{W}')
@classmethod
def is_cracked(cls, file):
if not os.path.exists(Configuration.cracked_file):
return False
with open(Configuration.cracked_file) as f:
json = loads(f.read())
if json is None:
return False
for result in json:
for k in result.keys():
v = result[k]
if 'file' in k and os.path.basename(v) == file:
return True
return False
@classmethod @classmethod
def get_handshakes(cls): def get_handshakes(cls):
handshakes = [] handshakes = []
skipped_pmkid_files = 0 skipped_pmkid_files = skipped_cracked_files = 0
hs_dir = Configuration.wpa_handshake_dir hs_dir = Configuration.wpa_handshake_dir
if not os.path.exists(hs_dir) or not os.path.isdir(hs_dir): if not os.path.exists(hs_dir) or not os.path.isdir(hs_dir):
@@ -110,6 +127,10 @@ class CrackHelper:
if hs_file.count('_') != 3: if hs_file.count('_') != 3:
continue continue
if cls.is_cracked(hs_file):
skipped_cracked_files += 1
continue
if hs_file.endswith('.cap'): if hs_file.endswith('.cap'):
# WPA Handshake # WPA Handshake
hs_type = '4-WAY' hs_type = '4-WAY'
@@ -148,7 +169,9 @@ class CrackHelper:
handshakes.append(handshake) handshakes.append(handshake)
if skipped_pmkid_files > 0: if skipped_pmkid_files > 0:
Color.pl('{!} {O}Skipping %d {R}*.16800{O} files because {R}hashcat{O} is missing.' % skipped_pmkid_files) Color.pl('{!} {O}Skipping %d {R}*.16800{O} files because {R}hashcat{O} is missing.{W}\n' % skipped_pmkid_files)
if skipped_cracked_files > 0:
Color.pl('{!} {O}Skipping %d already cracked files.{W}\n' % skipped_cracked_files)
# Sort by Date (Descending) # Sort by Date (Descending)
return sorted(handshakes, key=lambda x: x.get('date'), reverse=True) return sorted(handshakes, key=lambda x: x.get('date'), reverse=True)
@@ -158,7 +181,7 @@ class CrackHelper:
def print_handshakes(cls, handshakes): def print_handshakes(cls, handshakes):
# Header # Header
max_essid_len = max([len(hs['essid']) for hs in handshakes] + [len('ESSID (truncated)')]) max_essid_len = max([len(hs['essid']) for hs in handshakes] + [len('ESSID (truncated)')])
Color.p('{D} NUM') Color.p('{W}{D} NUM')
Color.p(' ' + 'ESSID (truncated)'.ljust(max_essid_len)) Color.p(' ' + 'ESSID (truncated)'.ljust(max_essid_len))
Color.p(' ' + 'BSSID'.ljust(17)) Color.p(' ' + 'BSSID'.ljust(17))
Color.p(' ' + 'TYPE'.ljust(5)) Color.p(' ' + 'TYPE'.ljust(5))
@@ -170,8 +193,6 @@ class CrackHelper:
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):
bssid = handshake['bssid']
date = handshake['date']
Color.p(' {G}%s{W}' % str(index).rjust(3)) Color.p(' {G}%s{W}' % str(index).rjust(3))
Color.p(' {C}%s{W}' % handshake['essid'].ljust(max_essid_len)) Color.p(' {C}%s{W}' % handshake['essid'].ljust(max_essid_len))
Color.p(' {O}%s{W}' % handshake['bssid'].ljust(17)) Color.p(' {O}%s{W}' % handshake['bssid'].ljust(17))
@@ -253,7 +274,10 @@ class CrackHelper:
@classmethod @classmethod
def crack_pmkid(cls, hs, tool_name): def crack_pmkid(cls, hs, tool):
if tool != 'hashcat':
Color.pl('{!} {O}Note: PMKID hashes can only be cracked using {C}hashcat{W}')
key = Hashcat.crack_pmkid(hs['filename'], verbose=True) key = Hashcat.crack_pmkid(hs['filename'], verbose=True)
if key is not None: if key is not None:

View File

@@ -4,7 +4,7 @@
from ..util.color import Color from ..util.color import Color
from ..tools.airodump import Airodump from ..tools.airodump import Airodump
from ..util.input import raw_input, xrange from ..util.input import raw_input, xrange
from ..model.target import Target from ..model.target import Target, WPSState
from ..config import Configuration from ..config import Configuration
from time import sleep, time from time import sleep, time
@@ -88,7 +88,7 @@ class Scanner(object):
return False # No specific target from user. return False # No specific target from user.
for target in self.targets: for target in self.targets:
if Configuration.wps_only and target.wps == False: if Configuration.wps_only and target.wps not in [WPSState.UNLOCKED, WPSState.LOCKED]:
continue continue
if bssid and target.bssid and bssid.lower() == target.bssid.lower(): if bssid and target.bssid and bssid.lower() == target.bssid.lower():
self.target = target self.target = target