2.1.3: Better WPS attack messaging. Leave device in Monitor Mode.

Unrelated to WPS:
* Do not take device out of monitor mode when finished (informs user)
* Do not restart NetworkManager when finished (informs user)

Changes to CLI switches:
* --wps-time X: Total time for WPS attack to complete
* --wps-timeouts X: Max number of timeouts before failing
* --wps-fails X: Max number of WPSFails before failing
* Removed unused WPS switches.
* Improved --help messaging for WPS switches.
* Fail/Timeout threshold default is 100

Bully now outputs useful information:
* Current PIN + status
* Time remaining
* Number of Timeout messages
* Number of "WPSFail" messages
* If AP is locked

Better reaver output.
* Looks more like Bully's output.
* Timer shows time remaining for attack.
* Mentions "Running pixiewps" during "M2 message" step.
* pixiewps failure looks like this: "Reaver says: 'WPS pin not found'"
* Counts Timeouts and "WPS Transaction Failure" (WPSFail)

For #28
This commit is contained in:
derv82
2018-04-07 06:22:16 -04:00
parent 20ea673a3d
commit 90c99b11f1
5 changed files with 420 additions and 290 deletions

View File

@@ -15,10 +15,10 @@ from threading import Thread
class Bully(Attack):
def __init__(self, target):
super(Bully, self).__init__(target)
self.consecutive_lockouts = self.consecutive_timeouts = self.consecutive_noassoc = 0
self.pins_attempted = 0
self.total_timeouts = 0
self.total_failures = 0
self.locked = False
self.state = "{O}Waiting for beacon{W}"
self.m_state = None
self.start_time = time.time()
self.cracked_pin = self.cracked_key = self.cracked_bssid = self.cracked_essid = None
@@ -46,8 +46,6 @@ class Bully(Attack):
self.bully_proc = None
def attack_type(self):
return "Pixie-Dust"
def run(self):
with Airodump(channel=self.target.channel,
@@ -55,11 +53,7 @@ class Bully(Attack):
skip_wps=True,
output_file_prefix='wps_pin') as airodump:
# Wait for target
Color.clear_entire_line()
Color.pattack("WPS",
self.target,
self.attack_type(),
"Waiting for target to appear...")
self.pattack("Waiting for target to appear...")
self.target = self.wait_for_target(airodump)
# Start bully
@@ -67,27 +61,42 @@ class Bully(Attack):
stderr=Process.devnull(),
bufsize=0,
cwd=Configuration.temp())
# Start bully status thread
t = Thread(target=self.parse_line_thread)
t.daemon = True
t.start()
try:
while self.bully_proc.poll() is None:
try:
self.target = self.wait_for_target(airodump)
except Exception as e:
Color.clear_entire_line()
Color.pattack("WPS",
self.target,
self.attack_type(),
"{R}failed: {O}%s{W}" % e)
Color.pl("")
self.pattack('{R}Failed: {O}%s{W}' % e, newline=True)
self.stop()
break
Color.clear_entire_line()
Color.pattack("WPS",
self.target,
self.attack_type(),
self.get_status())
# Update status
self.pattack(self.get_status())
# Check if entire attack timed out.
if self.running_time() > Configuration.wps_pixie_timeout:
self.pattack('{R}Failed: {O}Timeout after %d seconds{W}' % Configuration.wps_pixie_timeout, newline=True)
self.stop()
return
# Check if timeout threshold was breached
if self.total_timeouts >= Configuration.wps_timeout_threshold:
self.pattack('{R}Failed: {O}More than %d timeouts{W}' % Configuration.wps_timeout_threshold, newline=True)
self.stop()
return
# Check if WPSFail threshold was breached
if self.total_failures >= Configuration.wps_fail_threshold:
self.pattack('{R}Failed: {O}More than %d WPSFails{W}' % Configuration.wps_fail_threshold, newline=True)
self.stop()
return
time.sleep(0.5)
except KeyboardInterrupt as e:
self.stop()
@@ -97,111 +106,97 @@ class Bully(Attack):
raise e
if self.crack_result is None:
Color.clear_entire_line()
Color.pattack("WPS",
self.target,
self.attack_type(),
"{R}Failed{W}\n")
self.pattack("{R}Failed{W}", newline=True)
def pattack(self, message, newline=False):
# Print message with attack information.
time_left = Configuration.wps_pixie_timeout - self.running_time()
Color.clear_entire_line()
Color.pattack("WPS",
self.target,
'Pixie-Dust',
'{W}[{C}%s{W}] %s' % (Timer.secs_to_str(time_left), message))
if newline:
Color.pl("")
def running_time(self):
return int(time.time() - self.start_time)
def get_status(self):
result = self.state
result += " ({C}runtime:%s{W}" % Timer.secs_to_str(self.running_time())
result += " {G}tries:%d{W}" % self.pins_attempted
result += " {O}failures:%d{W}" % (self.consecutive_timeouts + self.consecutive_noassoc)
result += " {R}lockouts:%d{W}" % self.consecutive_lockouts
result += ")"
return result
main_status = self.state
meta_statuses = []
if self.total_timeouts > 0:
meta_statuses.append("{O}Timeouts:%d{W}" % self.total_timeouts)
if self.total_failures > 0:
meta_statuses.append("{O}WPSFail:%d{W}" % self.total_failures)
if self.locked:
meta_statuses.append("{R}Locked{W}")
if len(meta_statuses) > 0:
main_status += ' (%s)' % ', '.join(meta_statuses)
return main_status
def parse_line_thread(self):
for line in iter(self.bully_proc.pid.stdout.readline, b""):
if line == "": continue
line = line.replace("\r", "").replace("\n", "").strip()
if self.parse_line(line): break # Cracked
def parse_line(self, line):
# [+] Got beacon for 'Green House 5G' (30:85:a9:39:d2:1c)
got_beacon = re.search(r".*Got beacon for '(.*)' \((.*)\)", line)
if got_beacon:
# group(1)=ESSID, group(2)=BSSID
self.state = "Got beacon"
if Configuration.verbose > 1:
Color.pe('\n{P} [bully:stdout] %s' % line)
self.state = self.parse_state(line)
# [+] Last State = 'NoAssoc' Next pin '48855501'
last_state = re.search(r".*Last State = '(.*)'\s*Next pin '(.*)'", line)
if last_state:
# group(1)=result, group(2)=PIN
result = "Start" # last_state.group(1)
pin = last_state.group(2)
self.state = "Trying PIN:{C}%s{W}" % pin
self.crack_result = self.parse_crack_result(line)
# [+] Rx( M5 ) = 'Pin1Bad' Next pin '35565505'
# [+] Tx( Auth ) = 'Timeout' Next pin '80241263'
rx_m = re.search(r".*[RT]x\(\s*(.*)\s*\) = '(.*)'\s*Next pin '(.*)'", line)
if rx_m:
# group(1)=M3/M5, group(2)=result, group(3)=PIN
self.m_state = rx_m.group(1)
result = rx_m.group(2) # NoAssoc, WPSFail, Pin1Bad, Pin2Bad
if result in ["Pin1Bad", "Pin2Bad"]:
self.pins_attempted += 1
self.consecutive_lockouts = 0 # Reset lockout count
self.consecutive_timeouts = 0 # Reset timeout count
self.consecutive_noassoc = 0 # Reset timeout count
result = "{G}%s{W}" % result
elif result == "Timeout":
self.consecutive_timeouts += 1
result = "{O}%s{W}" % result
elif result == "NoAssoc":
self.consecutive_noassoc += 1
result = "{O}%s{W}" % result
else:
result = "{R}%s{W}" % result
pin = rx_m.group(3)
self.state = "Trying PIN:{C}%s{W} (%s)" % (pin, result)
# [!] WPS lockout reported, sleeping for 43 seconds ...
lock_out = re.search(r".*WPS lockout reported, sleeping for (\d+) seconds", line)
if lock_out:
sleeping = lock_out.group(1)
self.state = "{R}WPS Lock-out: {O}Waiting %s seconds{W}" % sleeping
self.consecutive_lockouts += 1
# [Pixie-Dust] WPS pin not found
pixie_re = re.search(r".*\[Pixie-Dust\] WPS pin not found", line)
if pixie_re:
self.state = "{R}Failed{W}"
if self.crack_result:
break
# [+] Running pixiewps with the information, wait ...
pixie_re = re.search(r".*Running pixiewps with the information", line)
if pixie_re:
self.state = "{G}Running pixiewps...{W}"
def parse_crack_result(self, line):
# Check for line containing PIN and PSK
# [*] Pin is '80246213', key is 'password'
# [*] Pin is '11867722', key is '9a6f7997'
pin_key_re = re.search(r"Pin is '(\d*)', key is '(.*)'", line)
if pin_key_re:
self.cracked_pin = pin_key_re.group(1)
self.cracked_key = pin_key_re.group(2)
# PIN : '80246213'
pin_re = re.search(r"^\s*PIN\s*:\s*'(.*)'\s*$", line)
if pin_re:
self.cracked_pin = pin_re.group(1)
###############
# Check for PIN
if self.cracked_pin is None:
# PIN : '80246213'
pin_re = re.search(r"^\s*PIN\s*:\s*'(.*)'\s*$", line)
if pin_re:
self.cracked_pin = pin_re.group(1)
# [Pixie-Dust] PIN FOUND: 01030365
pin_re = re.search(r"^\[Pixie-Dust\] PIN FOUND: '?(\d*)'?\s*$", line)
if pin_re:
self.cracked_pin = pin_re.group(1)
if self.cracked_pin is not None:
# Mention the PIN & that we're not done yet.
self.pattack("{G}Cracked PIN: {C}%s{W}" % self.cracked_pin, newline=True)
self.state = "{G}Finding PSK...{C}"
time.sleep(2)
###########################
# KEY : 'password'
key_re = re.search(r"^\s*KEY\s*:\s*'(.*)'\s*$", line)
if key_re:
self.cracked_key = key_re.group(1)
#warn_re = re.search(r"\[\!\]\s*(.*)$", line)
#if warn_re: self.state = "{O}%s{W}" % warn_re.group(1)
if not self.crack_result and self.cracked_pin and self.cracked_key:
Color.clear_entire_line()
Color.pattack("WPS", self.target, "Pixie-Dust", "{G}successfully cracked WPS PIN and PSK{W}")
Color.pl("")
self.pattack("{G}Cracked PSK: {C}%s{W}" % self.cracked_key, newline=True)
self.crack_result = CrackResultWPS(
self.target.bssid,
self.target.essid,
@@ -209,19 +204,81 @@ class Bully(Attack):
self.cracked_key)
Color.pl("")
self.crack_result.dump()
return True
else:
return False
return self.crack_result
def parse_state(self, line):
state = self.state
# [+] Got beacon for 'Green House 5G' (30:85:a9:39:d2:1c)
got_beacon = re.search(r".*Got beacon for '(.*)' \((.*)\)", line)
if got_beacon:
# group(1)=ESSID, group(2)=BSSID
state = "Got beacon"
# [+] Last State = 'NoAssoc' Next pin '48855501'
last_state = re.search(r".*Last State = '(.*)'\s*Next pin '(.*)'", line)
if last_state:
# group(1)=result, group(2)=PIN
pin = last_state.group(2)
state = "Trying PIN {C}%s{W} (%s)" % (pin, last_state.group(1))
# [+] Tx( Auth ) = 'Timeout' Next pin '80241263'
mx_result_pin = re.search(r".*[RT]x\(\s*(.*)\s*\) = '(.*)'\s*Next pin '(.*)'", line)
if mx_result_pin:
self.locked = False
# group(1)=M3/M5, group(2)=result, group(3)=PIN
m_state = mx_result_pin.group(1)
result = mx_result_pin.group(2) # NoAssoc, WPSFail, Pin1Bad, Pin2Bad
pin = mx_result_pin.group(3)
if result == "Timeout":
self.total_timeouts += 1
result = "{O}%s{W}" % result
elif result == "WPSFail":
self.total_failures += 1
result = "{O}%s{W}" % result
elif result == "NoAssoc":
result = "{O}%s{W}" % result
else:
result = "{R}%s{W}" % result
result = "{P}%s{W}:%s" % (m_state.strip(), result.strip())
state = "Trying PIN {C}%s{W} (%s)" % (pin, result)
# [!] WPS lockout reported, sleeping for 43 seconds ...
re_lockout = re.search(r".*WPS lockout reported, sleeping for (\d+) seconds", line)
if re_lockout:
self.locked = True
sleeping = re_lockout.group(1)
state = "{R}WPS Lock-out: {O}Waiting %s seconds{W}" % sleeping
# [Pixie-Dust] WPS pin not found
re_pin_not_found = re.search(r".*\[Pixie-Dust\] WPS pin not found", line)
if re_pin_not_found:
state = "{R}Failed: {O}Bully says 'WPS pin not found'{W}"
# [+] Running pixiewps with the information, wait ...
re_running_pixiewps = re.search(r".*Running pixiewps with the information", line)
if re_running_pixiewps:
state = "{G}Running pixiewps...{W}"
return state
def stop(self):
if hasattr(self, "pid") and self.pid and self.pid.poll() is None:
self.pid.interrupt()
def __del__(self):
self.stop()
@staticmethod
def get_psk_from_pin(target, pin):
# Fetches PSK from a Target assuming "pin" is the correct PIN
'''
bully --channel 1 --bssid 34:21:09:01:92:7C --pin 01030365 --bruteforce wlan0mon
PIN : '01030365'
@@ -229,8 +286,6 @@ class Bully(Attack):
BSSID : '34:21:09:01:92:7c'
ESSID : 'AirLink89300'
'''
Color.pl('\n{+} found PIN: {G}%s{W}' % pin)
Color.p('{+} fetching {C}PSK{W} using {C}bully{W}... ')
cmd = [
'bully',
'--channel', target.channel,
@@ -247,12 +302,11 @@ class Bully(Attack):
key_re = re.search(r"^\s*KEY\s*:\s*'(.*)'\s*$", line)
if key_re is not None:
psk = key_re.group(1)
Color.pl('{W}found PSK: {G}%s{W}' % psk)
return psk
Color.pl('{R}failed{W}')
return None
if __name__ == '__main__':
Configuration.initialize()
Configuration.interface = 'wlan0mon'

View File

@@ -5,6 +5,7 @@ from ..model.attack import Attack
from ..config import Configuration
from ..util.color import Color
from ..util.process import Process
from ..util.timer import Timer
from ..tools.airodump import Airodump
from ..tools.bully import Bully # for PSK retrieval
from ..model.wps_result import CrackResultWPS
@@ -14,155 +15,228 @@ import os, time, re
class Reaver(Attack):
def __init__(self, target):
super(Reaver, self).__init__(target)
self.success = False
self.start_time = None
self.state = 'Initializing'
self.locked = False
self.total_timeouts = 0
self.total_wpsfails = 0
self.crack_result = None
self.output_filename = Configuration.temp('reaver.out')
if os.path.exists(self.output_filename):
os.remove(self.output_filename)
self.output_write = open(self.output_filename, 'a')
self.reaver_cmd = [
'reaver',
'--interface', Configuration.interface,
'--bssid', self.target.bssid,
'--channel', self.target.channel,
'--pixie-dust', '1', # pixie-dust attack
'--session', '/dev/null', # Don't restart session
'-vv' # (very) verbose
]
self.reaver_proc = None
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)
def run(self):
''' Returns True if attack is successful. '''
try:
self._run() # Run-loop
except Exception as e:
# Failed with error
self.pattack('{R}Failed:{O} %s' % str(e), newline=True)
return self.crack_result is not None
command = [
'reaver',
'--interface', Configuration.interface,
'--bssid', self.target.bssid,
'--channel', self.target.channel,
'--pixie-dust', '1', # pixie-dust attack
'--session', '/dev/null', # Don't restart session
'-vv' # (very) verbose
]
stdout_write = open(self.stdout_file, 'a')
reaver = Process(command, stdout=stdout_write, stderr=Process.devnull())
# Stop reaver if it's still running
if self.reaver_proc.poll() is None:
self.reaver_proc.interrupt()
pin = None
step = 'initializing'
time_since_last_step = 0
# Clean up open file handle
if self.output_write:
self.output_write.close()
return self.crack_result is not None
def _run(self):
self.start_time = time.time()
with Airodump(channel=self.target.channel,
target_bssid=self.target.bssid,
skip_wps=True,
output_file_prefix='pixie') as airodump:
Color.clear_line()
Color.pattack("WPS", self.target, "Pixie Dust", "Waiting for target to appear...")
# Wait for target
self.pattack("Waiting for target to appear...")
self.target = self.wait_for_target(airodump)
while True:
try:
airodump_target = self.wait_for_target(airodump)
except Exception as e:
Color.pattack("WPS", self.target, "Pixie-Dust", "{R}failed: {O}%s{W}" % e)
# Start reaver
self.reaver_proc = Process(self.reaver_cmd,
stdout=self.output_write,
stderr=Process.devnull())
# Loop while reaver is running
while self.crack_result is None and self.reaver_proc.poll() is None:
# Refresh target information (power)
self.target = self.wait_for_target(airodump)
# Update based on reaver output
stdout = self.get_output()
self.state = self.parse_state(stdout)
self.parse_failure(stdout)
# Print status line
self.pattack(self.get_status())
# Check if we cracked it
self.crack_result = self.parse_crack_result(stdout)
time.sleep(0.5)
# Check if crack result is in output
stdout = self.get_output()
self.crack_result = self.parse_crack_result(stdout)
# Show any failures found
if self.crack_result is None:
self.parse_failure(stdout)
if self.crack_result is None and self.reaver_proc.poll() is not None:
raise Exception('Reaver process stopped (exit code: %s)' % self.reaver_proc.poll())
def get_status(self):
main_status = self.state
meta_statuses = []
if self.total_timeouts > 0:
meta_statuses.append("{O}Timeouts:%d{W}" % self.total_timeouts)
if self.total_wpsfails > 0:
meta_statuses.append("{O}WPSFail:%d{W}" % self.total_wpsfails)
if self.locked:
meta_statuses.append("{R}Locked{W}")
if len(meta_statuses) > 0:
main_status += ' (%s)' % ', '.join(meta_statuses)
return main_status
def parse_crack_result(self, stdout):
if self.crack_result is not None:
return self.crack_result
(pin, psk, ssid) = self.get_pin_psk_ssid(stdout)
# Check if we cracked it, or if process stopped.
if pin is not None:
# We cracked it.
if psk is not None:
# Reaver provided PSK
self.pattack('{G}Cracked WPS PIN: {C}%s{W} {G}PSK: {C}%s{W}' % (pin, psk), newline=True)
else:
self.pattack('{G}Cracked WPS PIN: {C}%s' % pin, newline=True)
# Try to derive PSK from PIN using Bully
self.pattack('{W}Retrieving PSK using {C}bully{W}...')
psk = Bully.get_psk_from_pin(self.target, pin)
if psk is None:
Color.pl("")
return False
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 is not None or reaver.poll() is not None:
reaver.interrupt()
# Check one-last-time for PIN/PSK/SSID, in case of race condition.
stdout = self.get_stdout()
(pin, psk, ssid) = Reaver.get_pin_psk_ssid(stdout)
# Check if we cracked it.
if pin is not None:
# We cracked it.
if psk is None:
# Try to derive PSK from PIN using Bully
psk = Bully.get_psk_from_pin(self.target, pin)
bssid = self.target.bssid
Color.clear_entire_line()
if psk is None:
Color.pattack("WPS", airodump_target, "Pixie-Dust", "{G}successfully cracked WPS PIN{W} (but not PSK)")
else:
Color.pattack("WPS", airodump_target, "Pixie-Dust", "{G}successfully cracked WPS PIN and PSK{W}")
Color.pl("")
self.crack_result = CrackResultWPS(bssid, ssid, pin, psk)
self.crack_result.dump()
return True
else:
# Failed to crack, reaver proces ended.
Color.clear_line()
Color.pattack("WPS", airodump_target, "Pixie-Dust", "{R}Failed: {O}WPS PIN not found{W}\n")
return False
if 'WPS pin not found' in stdout:
Color.pl('{R}failed: {O}WPS pin not found{W}')
break
last_step = step
# Status updates, depending on last line of stdout
if 'Waiting for beacon from' in stdout_last_line:
step = '({C}step 1/8{W}) waiting for beacon'
elif 'Associated with' in stdout_last_line:
step = '({C}step 2/8{W}) waiting to start session'
elif 'Starting Cracking Session.' in stdout_last_line:
step = '({C}step 3/8{W}) waiting to try pin'
elif 'Trying pin' in stdout_last_line:
step = '({C}step 4/8{W}) trying pin'
elif 'Sending EAPOL START request' in stdout_last_line:
step = '({C}step 5/8{W}) sending eapol start request'
elif 'Sending identity response' in stdout_last_line:
step = '({C}step 6/8{W}) sending identity response'
elif 'Sending M2 message' in stdout_last_line:
step = '({C}step 7/8{W}) sending m2 message (may take a while)'
elif 'Detected AP rate limiting,' in stdout_last_line:
if Configuration.wps_skip_rate_limit:
Color.pl('{R}failed: {O}hit WPS rate-limit{W}')
Color.pl('{!} {O}use {R}--ignore-ratelimit{O} to ignore' +
' this kind of failure in the future{W}')
break
step = '({C}step -/8{W}) waiting for AP rate limit'
if step != last_step:
# Step changed, reset step timer
time_since_last_step = 0
self.pattack('{R}Failed {O}to get PSK using bully', newline=True)
else:
time_since_last_step += 1
self.pattack('{G}Cracked WPS PSK: {C}%s' % psk, newline=True)
if time_since_last_step > Configuration.wps_pixie_step_timeout:
Color.pl('{R}failed: {O}step-timeout after %d seconds{W}' % Configuration.wps_pixie_step_timeout)
break
crack_result = CrackResultWPS(self.target.bssid, ssid, pin, psk)
crack_result.dump()
return crack_result
# TODO: Timeout check
if reaver.running_time() > Configuration.wps_pixie_timeout:
Color.pl('{R}failed: {O}timeout after %d seconds{W}' % Configuration.wps_pixie_timeout)
break
return None
# Reaver Failure/Timeout check
fail_count = stdout.count('WPS transaction failed')
if fail_count > Configuration.wps_fail_threshold:
Color.pl('{R}failed: {O}too many failures (%d){W}' % fail_count)
break
timeout_count = stdout.count('Receive timeout occurred')
if timeout_count > Configuration.wps_timeout_threshold:
Color.pl('{R}failed: {O}too many timeouts (%d){W}' % timeout_count)
break
Color.clear_line()
Color.pattack("WPS", airodump_target, "Pixie-Dust", step)
def parse_failure(self, stdout):
# Total failure
if 'WPS pin not found' in stdout:
raise Exception('Reaver says "WPS pin not found"')
time.sleep(1)
continue
# Running-time failure
if self.running_time() > Configuration.wps_pixie_timeout:
raise Exception('Timeout after %d seconds' % Configuration.wps_pixie_timeout)
# WPSFail count
self.total_wpsfails = stdout.count('WPS transaction failed')
if self.total_wpsfails >= Configuration.wps_fail_threshold:
raise Exception('Too many failures (%d)' % self.total_wpsfails)
# Timeout count
self.total_timeouts = stdout.count('Receive timeout occurred')
if self.total_timeouts >= Configuration.wps_timeout_threshold:
raise Exception('Too many timeouts (%d)' % self.total_timeouts)
def parse_state(self, stdout):
state = self.state
stdout_last_line = stdout.split('\n')[-1]
if 'Waiting for beacon from' in stdout_last_line:
state = 'Waiting for beacon'
elif 'Associated with' in stdout_last_line:
state = 'Associated'
elif 'Starting Cracking Session.' in stdout_last_line:
state = 'Waiting to try PIN'
elif 'Trying pin' in stdout_last_line:
state = 'Trying PIN'
elif 'Sending EAPOL START request' in stdout_last_line:
state = 'Sending EAPOL Start request'
elif 'Sending identity response' in stdout_last_line:
state = 'Sending identity response'
self.locked = False
elif 'Sending M2 message' in stdout_last_line:
state = 'Sending M2 / Running pixiewps'
self.locked = False
elif 'Detected AP rate limiting,' in stdout_last_line:
state = 'Rate-Limited by AP'
self.locked = True
return state
def pattack(self, message, newline=False):
# Print message with attack information.
time_left = Configuration.wps_pixie_timeout - self.running_time()
Color.clear_entire_line()
Color.pattack("WPS",
self.target,
'Pixie-Dust',
'{W}[{C}%s{W}] %s' % (Timer.secs_to_str(time_left), message))
if newline:
Color.pl("")
def running_time(self):
return int(time.time() - self.start_time)
# Attack failed, already printed reason why
reaver.interrupt()
stdout_write.close()
return False
@staticmethod
def get_pin_psk_ssid(stdout):
@@ -196,12 +270,21 @@ class Reaver(Attack):
return (pin, psk, ssid)
def get_stdout(self):
''' Gets output from stdout_file '''
if not self.stdout_file:
def get_output(self):
''' Gets output from reaver's output file '''
if not self.output_filename:
return ''
with open(self.stdout_file, 'r') as fid:
if self.output_write:
self.output_write.flush()
with open(self.output_filename, 'r') as fid:
stdout = fid.read()
if Configuration.verbose > 1:
Color.pe('\n{P} [reaver:stdout] %s' % '\n [reaver:stdout] '.join(stdout.split('\n')))
return stdout.strip()