Compare commits

...

3 commits

View file

@ -39,6 +39,12 @@ vendor_cache = {}
CHANNEL_LIST = [1, 6, 11, 36, 40, 48, 52, 64, 100, 104, 108, 112, 149, 153, 161] # Channels to hop CHANNEL_LIST = [1, 6, 11, 36, 40, 48, 52, 64, 100, 104, 108, 112, 149, 153, 161] # Channels to hop
CHANNEL_HOP_INTERVAL = 5 # Seconds per channel CHANNEL_HOP_INTERVAL = 5 # Seconds per channel
def safe_call(cmd):
try:
subprocess.check_call(cmd)
except subprocess.CalledProcessError as e:
print(f"[!] Command failed: {' '.join(cmd)}\n{e}")
def get_channel_from_freq(freq): def get_channel_from_freq(freq):
if 2412 <= freq <= 2472: if 2412 <= freq <= 2472:
return (freq - 2407) // 5 return (freq - 2407) // 5
@ -202,11 +208,11 @@ def write_csv(outfile):
def reset_interface(interface): def reset_interface(interface):
print(f"[~] Resetting interface {interface} to default state...") print(f"[~] Resetting interface {interface} to default state...")
try: try:
subprocess.call(["ip", "link", "set", interface, "down"]) safe_call(["ip", "link", "set", interface, "down"])
time.sleep(1) time.sleep(1)
subprocess.call(["iw", interface, "set", "type", "monitor"]) safe_call(["iw", interface, "set", "type", "monitor"])
time.sleep(1) time.sleep(1)
subprocess.call(["ip", "link", "set", interface, "up"]) safe_call(["ip", "link", "set", interface, "up"])
time.sleep(1) time.sleep(1)
print(f"[+] Interface {interface} reset complete.") print(f"[+] Interface {interface} reset complete.")
except Exception as e: except Exception as e:
@ -258,16 +264,28 @@ def channel_hopper(interface, hop_interval):
def is_deadpoint(ap_bssid): def is_deadpoint(ap_bssid):
return sum(ap_clients[ap_bssid].values()) < 2 # No meaningful client interaction return sum(ap_clients[ap_bssid].values()) < 2 # No meaningful client interaction
def wait_for_interface_up(iface, timeout=5): def wait_for_interface_up(interface, timeout=5):
print(f"[~] Waiting for interface {iface} to become available...") import shutil
for _ in range(timeout * 10): # check every 0.1s for `timeout` seconds import time
if iface in psutil.net_if_stats():
print(f"[+] Interface {iface} is up!") for _ in range(timeout * 5):
return True result = shutil.which("iw") # Just checking iw exists first
time.sleep(0.1) if not result:
print(f"[!] Interface {iface} did not become available in {timeout} seconds.") print("[!] 'iw' not found.")
return False return False
try:
info = subprocess.check_output(["iw", "dev"]).decode()
if f"Interface {interface}" in info:
if "type monitor" in info:
return True
except subprocess.CalledProcessError:
pass
time.sleep(0.2)
print(f"[!] Timeout waiting for interface {interface} to be up and in monitor mode.")
return False
# === Main === # === Main ===
def main(): def main():
parser = ArgumentParser() parser = ArgumentParser()
@ -284,8 +302,10 @@ def main():
reset_interface(args.monitor_iface) reset_interface(args.monitor_iface)
if not wait_for_interface_up(args.monitor_iface): if not wait_for_interface_up(args.monitor_iface):
print("[!] Interface failed to become available. Exiting.")
sys.exit(1) sys.exit(1)
print(f"[+] Starting passive observer.") print(f"[+] Starting passive observer.")
print(f" Main interface: {args.main_iface}") print(f" Main interface: {args.main_iface}")
print(f" Monitor interface: {args.monitor_iface}") print(f" Monitor interface: {args.monitor_iface}")
@ -339,8 +359,6 @@ def main():
print(f" {bssid}{vendor}") print(f" {bssid}{vendor}")
reset_interface(args.monitor_iface) reset_interface(args.monitor_iface)
if not wait_for_interface_up(args.monitor_iface):
sys.exit(1)
def get_mac_vendor(mac): def get_mac_vendor(mac):
prefix = mac.upper()[0:8].replace(":", "-") prefix = mac.upper()[0:8].replace(":", "-")