Skip to content

Commit 489e04d

Browse files
committed
add custom channels and bbsid
1 parent 936ab5c commit 489e04d

File tree

1 file changed

+67
-5
lines changed

1 file changed

+67
-5
lines changed

wifi-deauth.py

Lines changed: 67 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@
2828

2929

3030
class Interceptor:
31-
def __init__(self, net_iface, skip_monitor_mode_setup, kill_networkmanager):
31+
def __init__(self, net_iface, skip_monitor_mode_setup, kill_networkmanager, bssid_name, custom_channels):
3232
self.interface = net_iface
3333
self._channel_sniff_timeout = 2
3434
self._scan_intv = 0.1
@@ -61,6 +61,36 @@ def __init__(self, net_iface, skip_monitor_mode_setup, kill_networkmanager):
6161
self._channel_range = {channel: defaultdict(dict) for channel in self._get_channels()}
6262
self._all_ssids: Dict[BandType, Dict[str, SSID]] = {band: dict() for band in BandType}
6363

64+
self._custom_bssid_name: Union[str, None] = self.parse_custom_bssid_name(bssid_name)
65+
self._custom_bssid_channels: List[int] = self.parse_custom_channels(custom_channels)
66+
self._custom_bbsid_last_ch = 0 # to avoid overlapping
67+
68+
@staticmethod
69+
def parse_custom_bssid_name(bssid_name: Union[None, str]) -> Union[None, str]:
70+
if bssid_name is not None:
71+
bssid_name = str(bssid_name)
72+
if len(bssid_name) != 0:
73+
print_error(f"Custom BSSID name cannot be an empty string")
74+
raise Exception("Invalid BSSID name")
75+
return bssid_name
76+
77+
def parse_custom_channels(self, channel_list: Union[None, str]):
78+
ch_list = list()
79+
if channel_list is not None:
80+
try:
81+
ch_list = channel_list.split(',')
82+
except Exception as exc:
83+
print_error(f"Invalid custom channel input -> {channel_list}")
84+
raise Exception("Bad custom channel input")
85+
86+
if len(ch_list):
87+
for ch in ch_list:
88+
if ch not in self._channel_range:
89+
print_error(f"Custom channel {ch} is not supported by the network interface")
90+
raise Exception("Unsupported channel")
91+
return ch_list
92+
93+
6494
def _enable_monitor_mode(self):
6595
for cmd in [f"sudo ip link set {self.interface} down",
6696
f"sudo iw {self.interface} set monitor control",
@@ -76,6 +106,7 @@ def _kill_networkmanager():
76106
print_cmd(f"Running command -> '{BOLD}{cmd}{RESET}'")
77107
return not os.system(cmd)
78108

109+
79110
def _set_channel(self, ch_num):
80111
os.system(f"iw dev {self.interface} set channel {ch_num}")
81112
self._current_channel_num = ch_num
@@ -90,30 +121,52 @@ def _ap_sniff_cb(self, pkt):
90121
if pkt.haslayer(Dot11Beacon) or pkt.haslayer(Dot11ProbeResp):
91122
ap_mac = str(pkt.addr3)
92123
ssid = pkt[Dot11Elt].info.strip(b'\x00').decode('utf-8').strip() or ap_mac
93-
if ap_mac == BD_MACADDR or not ssid:
124+
if ap_mac == BD_MACADDR or not ssid or (self._custom_bbsid_name_is_set()
125+
and ssid != self._custom_bssid_name):
94126
return
95127
pkt_ch = frequency_to_channel(pkt[RadioTap].Channel)
96128
band_type = BandType.T_50GHZ if pkt_ch > 14 else BandType.T_24GHZ
97129
if ssid not in self._all_ssids[band_type]:
98130
self._all_ssids[band_type][ssid] = SSID(ssid, ap_mac, band_type)
99131
self._all_ssids[band_type][ssid].add_channel(pkt_ch if pkt_ch in self._channel_range else self._current_channel_num)
132+
if self._custom_bbsid_name_is_set():
133+
self._custom_bbsid_last_ch = self._all_ssids[band_type][ssid].channel
100134
else:
101135
self._clients_sniff_cb(pkt) # pass forward to find potential clients
102136
except Exception as exc:
103137
pass
104138

105139
def _scan_channels_for_aps(self):
140+
channels_to_scan = self._custom_bssid_channels or self._channel_range
141+
print_info(f"Starting AP scan, please wait... ({len(channels_to_scan)} channels total)")
142+
if self._custom_bbsid_name_is_set():
143+
print_info(f"Scanning for target BBSID -> {self._custom_bssid_name}")
144+
106145
try:
107-
for idx, ch_num in enumerate(self._channel_range):
146+
for idx, ch_num in enumerate(channels_to_scan):
147+
if self._custom_bbsid_name_is_set() and self._found_custom_bssid_name() \
148+
and self._current_channel_num - self._custom_bbsid_last_ch > 2:
149+
# make sure sniffing doesn't stop on an overlapped channel for custom BBSIDs
150+
return
108151
self._set_channel(ch_num)
109152
print_info(f"Scanning channel {self._current_channel_num} (left -> "
110-
f"{len(self._channel_range) - (idx + 1)})", end="\r")
153+
f"{len(channels_to_scan) - (idx + 1)})", end="\r")
111154
sniff(prn=self._ap_sniff_cb, iface=self.interface, timeout=self._channel_sniff_timeout)
112155
except KeyboardInterrupt:
113156
self.user_abort()
114157
finally:
115158
printf("")
116159

160+
def _found_custom_bssid_name(self):
161+
for all_channel_aps in self._channel_range.values():
162+
for ssid_name in all_channel_aps.keys():
163+
if ssid_name == self._custom_bssid_name:
164+
return True
165+
return False
166+
167+
def _custom_bbsid_name_is_set(self):
168+
return self._custom_bssid_name is not None
169+
117170
def _start_initial_ap_scan(self) -> SSID:
118171
print_info(f"Starting AP scan, please wait... ({len(self._channel_range)} channels total)")
119172

@@ -142,7 +195,10 @@ def _start_initial_ap_scan(self) -> SSID:
142195
exit(0)
143196

144197
printf(DELIM)
198+
145199
chosen = -1
200+
if self._custom_bbsid_name_is_set() and self._found_custom_bssid_name():
201+
chosen = 0
146202
while chosen not in target_map.keys():
147203
user_input = print_input(f"Choose a target from {min(target_map.keys())} to {max(target_map.keys())}:")
148204
try:
@@ -261,10 +317,16 @@ def user_abort(self):
261317
default=False, dest="skip_monitormode", required=False)
262318
parser.add_argument('-k', '--kill', help='kill NetworkManager (might interfere with the process)',
263319
action='store_true', default=False, dest="kill_networkmanager", required=False)
320+
parser.add_argument('-b', '--bbsid', help='custom BBSID name (case-sensitive)',
321+
action='store', default=None, dest="custom_bbsid", required=False)
322+
parser.add_argument('-c', '--channel', help='custom channels to scan, separated by a comma (i.e -> 1,3,4)',
323+
action='store', default=None, dest="custom_channels", required=False)
264324
pargs = parser.parse_args()
265325

266326
invalidate_print() # after arg parsing
267327
attacker = Interceptor(net_iface=pargs.net_iface,
268328
skip_monitor_mode_setup=pargs.skip_monitormode,
269-
kill_networkmanager=pargs.kill_networkmanager)
329+
kill_networkmanager=pargs.kill_networkmanager,
330+
bssid_name=custom_bbsid,
331+
custom_channels=custom_channels)
270332
attacker.run()

0 commit comments

Comments
 (0)