commit 3393a859c912fd286aa460d6aca1284a7cf4b6ef Author: Franck Thiaw Date: Thu Sep 3 08:35:19 2026 +0400 Parse airodump-ng CSV dumps into AP and station lists Co-Authored-By: Claude Sonnet 5 Claude-Session: https://claude.ai/code/session_01HHYXPc5u9FfVNS8auAUgC4 diff --git a/wifi_deauth.py b/wifi_deauth.py new file mode 100644 index 0000000..76c0ac4 --- /dev/null +++ b/wifi_deauth.py @@ -0,0 +1,72 @@ +#!/usr/bin/env python3 +"""airodump-ng CSV parser for the wifi deauth tool (+ a hardware-free selftest).""" +import os +import sys +import tempfile + + +def parse_airodump_csv(path): + try: + with open(path, encoding="utf-8", errors="replace") as f: + text = f.read() + except OSError: + return [], [] + aps, stations, section = [], [], None + for line in text.splitlines(): + s = line.strip() + if not s: + continue + if s.startswith("BSSID,"): + section = "ap" + continue + if s.startswith("Station MAC,"): + section = "sta" + continue + # naive comma split; an ESSID containing a comma will skew fields. + parts = [c.strip() for c in line.split(",")] + if section == "ap" and len(parts) >= 14: + aps.append({ + "bssid": parts[0], "channel": parts[3], "power": parts[8], + "privacy": parts[5], "essid": parts[13], + }) + elif section == "sta" and len(parts) >= 6: + stations.append({ + "station": parts[0], "power": parts[3], + "packets": parts[4], "bssid": parts[5], + }) + return aps, stations + + +def _selftest(): + sample = ( + "BSSID, First time seen, Last time seen, channel, Speed, Privacy, Cipher, " + "Authentication, Power, # beacons, # IV, LAN IP, ID-length, ESSID, Key\r\n" + "\r\n" + "AA:BB:CC:DD:EE:FF, 2024-01-01 00:00:00, 2024-01-01 00:01:00, 6, 130, " + "WPA2, CCMP, PSK, -40, 10, 0, 0.0.0.0, 6, MyWiFi, \r\n" + "\r\n" + "Station MAC, First time seen, Last time seen, Power, # packets, BSSID, " + "Probed ESSIDs\r\n" + "\r\n" + "11:22:33:44:55:66, 2024-01-01 00:00:10, 2024-01-01 00:01:00, -50, 25, " + "AA:BB:CC:DD:EE:FF, MyWiFi\r\n" + "99:88:77:66:55:44, 2024-01-01 00:00:10, 2024-01-01 00:01:00, -60, 5, " + "(not associated), Other\r\n" + ) + p = os.path.join(tempfile.gettempdir(), "wd_selftest.csv") + with open(p, "w") as f: + f.write(sample) + aps, sts = parse_airodump_csv(p) + os.remove(p) + assert len(aps) == 1, aps + assert aps[0]["essid"] == "MyWiFi" and aps[0]["channel"] == "6", aps + assert len(sts) == 2, sts + assoc = [s for s in sts if s["bssid"].lower() == "aa:bb:cc:dd:ee:ff"] + assert len(assoc) == 1 and assoc[0]["station"] == "11:22:33:44:55:66", sts + print("selftest ok") + + +if __name__ == "__main__": + if "--selftest" in sys.argv: + _selftest() + sys.exit(0)