Skip to content

Instantly share code, notes, and snippets.

@rvrsh3ll
Last active September 19, 2026 15:01
Show Gist options
  • Select an option

  • Save rvrsh3ll/b5a9e367fad44f59beb37dcf23ba612c to your computer and use it in GitHub Desktop.

Select an option

Save rvrsh3ll/b5a9e367fad44f59beb37dcf23ba612c to your computer and use it in GitHub Desktop.
#!/usr/bin/env python3
import sys
import os
import subprocess
import signal
import time
import re
import argparse
import logging
global uniqueSSID
global detectedSSID
global pid
uniqueSSID = 0
detectedSSID = {}
logging.basicConfig(filename='app.log',level=logging.INFO)
def dumpNetworks(signum, frame):
global detectedSSID
global uniqueSSID
print("!! Dumping detected networks:")
print("!! MAC Address SSID Count Last Seen")
print("!! -------------------- ------------------------------ ---------- -------------------")
for key in detectedSSID:
lastSeen = time.strftime("%Y/%m/%d %H:%M:%S", time.localtime(detectedSSID[key][2]))
print("!! {:20s} {:30s} {:10s} {:20s}".format(detectedSSID[key][2], detectedSSID[key][0], detectedSSID[key][1], lastSeen))
print("!! Total unique SSID: {}".format(uniqueSSID))
def cleanKill(signum, frame):
global pid
global detectedSSID
global uniqueSSID
if pid:
print("!! Received kill signal!")
os.kill(pid, signal.SIGUSR1)
dumpNetworks(signum, frame)
sys.exit(0)
def main(ssid,interface,verbose,dumpfile):
ifconfigPath = "/sbin/ifconfig"
iwconfigPath = "/sbin/iwconfig"
tsharkPath = "/usr/bin/tshark"
uniqueSSID = 0
detectedSSID = {}
# Configure wireless interface
os.system("{} {} up".format(ifconfigPath, interface))
# Set interface in monitor mode
os.system("{} {} mode monitor".format(iwconfigPath, interface))
# Create the child process to change wireless channels
pid = os.fork()
if pid:
# ---------------------------------
# Parent process: run the main loop
# ---------------------------------
if verbose:
print("!! Running with PID: {} (child: {})".format(os.getpid(), pid))
tshark = subprocess.Popen([tsharkPath, "-i", interface, "-n", "-l", "subtype", "probereq"], stdout=subprocess.PIPE, stderr=subprocess.PIPE)
for line in iter(tshark.stdout.readline, b''):
line = line.decode().strip()
if re.match("[a-zA-ZÀ-ÿ0-9\"\s\!\@\$\%\^\&\*\(\)\_\-\+\=\[\]\{\}\,\.\?\>\<]+", line):
(macAddress, newKey) = re.search("\\d+\\.\\d+ ([a-zA-Z0-9:_]+).+SSID=([a-zA-ZÀ-ÿ0-9\"\\s\\!\\@\\$\\%\\^\\&\\*\\(\\)\\_\\-\\+\\=\\[\\]\\{\\}\\,\\.\\?\\>\\<]+)", line).group(1, 2)
if newKey != "Broadcast": # Ignore broadcasts
if newKey not in detectedSSID:
# New network found!
if newKey.replace("\"","") == ssid:
print("Alert! Probe for {} is in-range!!".format(ssid))
newSSID = [newKey, 1, macAddress, time.time()]
detectedSSID[newKey] = newSSID
uniqueSSID += 1
print("++ New probe request from {} with SSID: {} [{}]".format(macAddress, newKey, uniqueSSID))
logging.info("macAddress,{},ssid,{}".format(macAddress,newKey))
else:
# Existing SSID found!
detectedSSID[newKey][1] += 1 # Increase packets counter
detectedSSID[newKey][2] = macAddress # MAC Address
detectedSSID[newKey][3] = time.time() # Now
if verbose:
print("-- Probe seen before: {} [{}]".format(newKey, uniqueSSID))
tshark.stdout.close()
tshark.stderr.close()
tshark.wait()
else:
# --------------------------------------------------
# Child process: Switch channels at regular interval
# --------------------------------------------------
if verbose:
print("!! Switching wireless channel every 5.")
while True:
for channel in range(1, 13):
os.system("{} {} channel {}".format(iwconfigPath, interface, channel))
time.sleep(5)
if __name__ == "__main__":
signal.signal(signal.SIGUSR1, dumpNetworks)
signal.signal(signal.SIGINT, cleanKill)
signal.signal(signal.SIGTERM, cleanKill)
parser = argparse.ArgumentParser()
parser.add_argument('-s', '--SSID', type=str, required=False)
parser.add_argument('-i','--interface', type=str, default="wlan0", required=False)
parser.add_argument('-v','--verbose', action="store_true", required=False)
parser.add_argument('-d','--dumpfile', type=str, required=False)
args = parser.parse_args()
if os.geteuid() != 0:
sys.exit("{} must be run by root!".format(sys.argv[0]))
main(args.SSID,args.interface,args.verbose,args.dumpfile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment