Add channel frequency handling and enhance deadpoint detection logic

This commit is contained in:
Yaro Kasear 2025-05-02 09:04:23 -05:00
parent 6ae40ca9c5
commit 89c210bc9c

View file

@ -33,6 +33,15 @@ 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_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 CHANNEL_HOP_INTERVAL = 5 # Seconds per channel
def get_channel_from_freq(freq):
if 2412 <= freq <= 2472:
return (freq - 2407) // 5
elif freq == 2484:
return 14
elif 5180 <= freq <= 5825:
return (freq - 5000) // 5
return None
# === Signal handling === # === Signal handling ===
def stop_sniff(signum, frame): def stop_sniff(signum, frame):
global running global running
@ -87,6 +96,12 @@ def handle_packet(pkt):
a1 = dot11.addr1.lower() if dot11.addr1 else None a1 = dot11.addr1.lower() if dot11.addr1 else None
a2 = dot11.addr2.lower() if dot11.addr2 else None a2 = dot11.addr2.lower() if dot11.addr2 else None
try:
freq = pkt[RadioTap].ChannelFrequency
packet_channel = get_channel_from_freq(freq)
except:
packet_channel = current_channel or "?"
# === Detect APs via beacon (and optionally probe response) frames === # === Detect APs via beacon (and optionally probe response) frames ===
if dot11.type == 0 and dot11.subtype in ([8, 5] if include_probes else [8]): if dot11.type == 0 and dot11.subtype in ([8, 5] if include_probes else [8]):
if a2 and is_unicast(a2): if a2 and is_unicast(a2):
@ -150,7 +165,7 @@ def write_csv(outfile):
"NumberofBSSIDsOnSSID": "N/A", "NumberofBSSIDsOnSSID": "N/A",
"NumberofChannelsOnSSID": "N/A", "NumberofChannelsOnSSID": "N/A",
"UnlinkedDevices": len(unlinked_candidates), "UnlinkedDevices": len(unlinked_candidates),
"Deadpoints": len([ap for ap in deadpoint_candidates if not ap_clients.get(ap)]) "Deadpoints": len([ap for ap in deadpoint_candidates if is_deadpoint(ap)])
} }
new_file = not os.path.exists(outfile) new_file = not os.path.exists(outfile)
@ -195,7 +210,7 @@ def print_suspect_aps():
flags = [] flags = []
if any(kw in ssid.lower() for kw in keywords): if any(kw in ssid.lower() for kw in keywords):
flags.append("Suspicious SSID") flags.append("Suspicious SSID")
if bssid in deadpoint_candidates and not ap_clients.get(bssid): if is_deadpoint(bssid):
flags.append("Deadpoint") flags.append("Deadpoint")
if flags: if flags:
suspects.append((bssid, ssid, flags)) suspects.append((bssid, ssid, flags))
@ -216,6 +231,9 @@ def channel_hopper(interface):
i += 1 i += 1
time.sleep(CHANNEL_HOP_INTERVAL) time.sleep(CHANNEL_HOP_INTERVAL)
def is_deadpoint(ap_bssid):
return sum(ap_clients[ap_bssid].values()) < 2 # No meaningful client interaction
# === Main === # === Main ===
def main(): def main():
parser = ArgumentParser() parser = ArgumentParser()