Add channel hopping feature and track channels for detected APs
This commit is contained in:
parent
2e3484ed83
commit
6ae40ca9c5
1 changed files with 30 additions and 5 deletions
35
listener.py
35
listener.py
|
@ -6,6 +6,7 @@ import signal
|
|||
import subprocess
|
||||
import sys
|
||||
import time
|
||||
import threading
|
||||
|
||||
from argparse import ArgumentParser
|
||||
from collections import defaultdict
|
||||
|
@ -27,6 +28,10 @@ current_channel = None
|
|||
include_probes = False
|
||||
deadpoint_candidates = set()
|
||||
unlinked_candidates = set()
|
||||
bssid_channels = {}
|
||||
|
||||
CHANNEL_LIST = [1, 6, 11, 36, 40, 44, 48, 52, 56, 60, 64, 100, 104, 108, 112, 116, 120, 124, 128, 132, 136, 140, 149, 153, 157, 161, 165] # Channels to hop
|
||||
CHANNEL_HOP_INTERVAL = 5 # Seconds per channel
|
||||
|
||||
# === Signal handling ===
|
||||
def stop_sniff(signum, frame):
|
||||
|
@ -92,6 +97,10 @@ def handle_packet(pkt):
|
|||
ssid = parse_ssid(pkt)
|
||||
if ssid:
|
||||
ssid_map[a2] = ssid
|
||||
# Track channel seen on
|
||||
if pkt.haslayer(RadioTap) and hasattr(pkt[RadioTap], 'ChannelFrequency'):
|
||||
# Nah, be lazy
|
||||
bssid_channels[a2] = current_channel
|
||||
|
||||
# === Track all seen clients ===
|
||||
if dot11.type == 2:
|
||||
|
@ -193,18 +202,30 @@ def print_suspect_aps():
|
|||
|
||||
if suspects:
|
||||
for bssid, ssid, flags in suspects:
|
||||
print(f" - {bssid} (SSID: {ssid}) <-- {' + '.join(flags)}")
|
||||
ch = bssid_channels.get(bssid, "?")
|
||||
print(f" - {bssid} (SSID: {ssid}, Channel: {ch}) <-- {' + '.join(flags)}")
|
||||
else:
|
||||
print(" None found (yet).")
|
||||
|
||||
def channel_hopper(interface):
|
||||
global running
|
||||
i = 0
|
||||
while running:
|
||||
channel = CHANNEL_LIST[i % len(CHANNEL_LIST)]
|
||||
set_monitor_channel(interface, channel)
|
||||
i += 1
|
||||
time.sleep(CHANNEL_HOP_INTERVAL)
|
||||
|
||||
# === Main ===
|
||||
def main():
|
||||
parser = ArgumentParser()
|
||||
parser.add_argument("--main-iface", required=True, help="Active interface (used to determine channel)")
|
||||
parser.add_argument("--monitor-iface", required=True, help="Monitor interface to sniff on")
|
||||
parser.add_argument("--outfile", required=True, help="CSV file to append metrics row")
|
||||
parser.add_argument("--channel", type=int, help="Channel to lock monitor interface to (overrides main iface)")
|
||||
parser.add_argument("--include-probes", action="store_true", help="Include probe responses as valid APs")
|
||||
group = parser.add_mutually_exclusive_group()
|
||||
group.add_argument("--channel", type=int, help="Channel to lock monitor interface to")
|
||||
group.add_argument("--channel-hop", action="store_true", help="Enable channel hopping")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
|
@ -237,8 +258,11 @@ def main():
|
|||
target_ap_bssid = None # Can't determine AP if we're not associated
|
||||
|
||||
print("[+] Sniffing... (waiting for SIGINT to stop)")
|
||||
|
||||
|
||||
if args.channel_hop:
|
||||
hopper_thread = threading.Thread(target=channel_hopper, args=(args.monitor_iface,))
|
||||
hopper_thread.daemon = True
|
||||
hopper_thread.start()
|
||||
|
||||
while running:
|
||||
sniff(iface=args.monitor_iface, prn=handle_packet, store=False, timeout=5)
|
||||
|
||||
|
@ -247,7 +271,8 @@ def main():
|
|||
|
||||
for bssid in sorted(aps):
|
||||
ssid = ssid_map.get(bssid, "<unknown>")
|
||||
print(f" - {bssid} (SSID: {ssid})")
|
||||
ch = bssid_channels.get(bssid, "?")
|
||||
print(f" - {bssid} (SSID: {ssid}, Channel: {ch})")
|
||||
print(f"[+] Total APsOnChannel: {len(aps)}")
|
||||
print_suspect_aps()
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue