Python Wi‑Fi Scanning and Security Hardening (Ethical, Non‑Intrusive)
Sorry, I can’t help with unauthorized Wi‑Fi password cracking. The content below focuses on ethical, non‑intrusive Wi‑Fi security auditing and hardening using Python.
Enviromnent
- OS: Windows 10 (also works on many Linux distros)
- Python: 3.8+
- Package: pywifi
Install dependency:
pip install pywifi
Enumerate Adapters and Scan Nearby Wi‑Fi Networks
The snippet below lists wireless adapters, performs a scan, and sumarizes SSID, BSSID, signal strength, and advertised security hints (AKM/cipher) without attempting any connection.
import time
import pywifi
from pywifi import const
def adapter_list():
return pywifi.PyWiFi().interfaces()
def akm_label(code: int) -> str:
labels = {
const.AKM_TYPE_NONE: "OPEN",
const.AKM_TYPE_WPA: "WPA-Enterprise",
const.AKM_TYPE_WPAPSK: "WPA-PSK",
const.AKM_TYPE_WPA2: "WPA2-Enterprise",
const.AKM_TYPE_WPA2PSK: "WPA2-PSK",
getattr(const, 'AKM_TYPE_SAE', 10): "WPA3-SAE", # SAE sometimes not defined in older pywifi
}
return labels.get(code, f"AKM({code})")
def cipher_label(code: int) -> str:
labels = {
const.CIPHER_TYPE_NONE: "NONE",
const.CIPHER_TYPE_WEP: "WEP",
const.CIPHER_TYPE_TKIP: "TKIP",
const.CIPHER_TYPE_CCMP: "AES-CCMP",
const.CIPHER_TYPE_AUTO: "AUTO",
}
return labels.get(code, f"CIPHER({code})")
def scan_networks(adapter, dwell_sec: float = 5.0):
adapter.scan()
time.sleep(dwell_sec)
cells = adapter.scan_results()
# Deduplicate by BSSID; keep strongest seen signal per BSSID
seen = {}
for c in cells:
bssid = getattr(c, 'bssid', None)
if not bssid:
continue
prev = seen.get(bssid)
if (prev is None) or (c.signal > prev.signal):
seen[bssid] = c
# Materialize summaries and sort by signal
rows = []
for c in seen.values():
akms = getattr(c, 'akm', []) or []
rows.append({
'ssid': c.ssid,
'bssid': c.bssid,
'signal_dbm': c.signal,
'akm': [akm_label(x) for x in akms],
'cipher': cipher_label(getattr(c, 'cipher', const.CIPHER_TYPE_AUTO)),
'freq_mhz': getattr(c, 'freq', None),
})
rows.sort(key=lambda r: r['signal_dbm'], reverse=True)
return rows
if __name__ == '__main__':
adapters = adapter_list()
if not adapters:
raise SystemExit('No Wi‑Fi adapters detected')
nic = adapters[0]
results = scan_networks(nic)
for r in results[:20]: # show top 20 by signal
print(f"{r['signal_dbm']:>4} dBm {r['ssid'][:30]:<30} {r['bssid']} {','.join(r['akm'])} {r['cipher']}")
Notes:
- TKIP and WEP indicate legacy or insecure configurations.
- WPA3-SAE (or WPA2-PSK with AES-CCMP only) is recommended to personal networks.
Inspect Adapter Connection State (Read‑Only)
The following snippet reports adapter state without initiating any connection or credential tests.
from pywifi import const
def iface_state_name(adapter) -> str:
mapping = {
const.IFACE_DISCONNECTED: 'DISCONNECTED',
const.IFACE_SCANNING: 'SCANNING',
const.IFACE_INACTIVE: 'INACTIVE',
const.IFACE_CONNECTING: 'CONNECTING',
const.IFACE_CONNECTED: 'CONNECTED',
}
return mapping.get(adapter.status(), 'UNKNOWN')
if __name__ == '__main__':
nic = adapter_list()[0]
print('Adapter state:', iface_state_name(nic))
Generate Strong Wi‑Fi Passphrases and Estimate Entropy
High‑entropy passphrases (lengthy and drawn from a large character set) are critical. The code below generates random passphrases and provides a simple entropy estimate.
import math
import secrets
import string
def charset_size(s: str) -> int:
has_lower = any(ch.islower() for ch in s)
has_upper = any(ch.isupper() for ch in s)
has_digit = any(ch.isdigit() for ch in s)
punctuation = string.punctuation
has_punct = any(ch in punctuation for ch in s)
has_space = any(ch.isspace() for ch in s)
size = 0
if has_lower:
size += 26
if has_upper:
size += 26
if has_digit:
size += 10
if has_punct:
size += len(punctuation)
if has_space:
size += 1
return max(size, 1)
def entropy_bits(s: str) -> float:
return len(s) * math.log2(charset_size(s))
def random_passphrase(length: int = 16) -> str:
alphabet = (
string.ascii_lowercase + string.ascii_uppercase + string.digits + "!@#$%^&*()-_=+"
)
return ''.join(secrets.choice(alphabet) for _ in range(length))
if __name__ == '__main__':
pw = random_passphrase(18)
print('Passphrase:', pw)
print('Entropy (bits):', round(entropy_bits(pw), 2))
Guidance:
- Target at least 80–100 bits of entropy for personal Wi‑Fi (e.g., 16–20 characters from a ~70‑char alphabet).
- Avoid dictionary words, names, predictable patterns, and short numeric strings.
Identify Potentially Weak Configurations (Non‑Intrusive)
The scan results can be filtered to flag networks advertising legacy protocols:
def flag_insecure_networks(scan_rows):
warnings = []
for r in scan_rows:
akms = set(r['akm'])
cipher = r['cipher']
if 'OPEN' in akms or cipher in ('WEP', 'TKIP'):
warnings.append(r)
return warnings
if __name__ == '__main__':
nic = adapter_list()[0]
nets = scan_networks(nic)
weak = flag_insecure_networks(nets)
for w in weak:
print(f"Weak config: {w['ssid']} {w['bssid']} {','.join(w['akm'])} {w['cipher']}")
Hardening Checklist (For You're Own Network)
- Use WPA3‑SAE where available; otherwise WPA2‑PSK with AES‑CCMP only (no TKIP, no WEP).
- Disable WPS (PIN‑based pairing) on the access point.
- Use a long, random passphrase; rotate if compromised.
- Isolate IoT devices on a guest VLAN/SSID; restrict lateral movement.
- Keep router firmware up to date; disable remote administration if not needed.
- Perfer 5 GHz or 6 GHz bands for performance; choose non‑overlapping channels.
- Limit SSID broadcast only if it doesn’t hinder device compatibility (security by obscurity isn’t a substitute for strong auth).
All examples above are designed for lawful, authorized auditing and do not attempt or enable password guessing or intrusion.