Fading Coder

One Final Commit for the Last Sprint

Home > Tech > Content

Python Wi‑Fi Scanning and Security Hardening (Ethical, Non‑Intrusive)

Tech 1

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.

Tags: Python

Related Articles

Understanding Strong and Weak References in Java

Strong References Strong reference are the most prevalent type of object referencing in Java. When an object has a strong reference pointing to it, the garbage collector will not reclaim its memory. F...

Comprehensive Guide to SSTI Explained with Payload Bypass Techniques

Introduction Server-Side Template Injection (SSTI) is a vulnerability in web applications where user input is improper handled within the template engine and executed on the server. This exploit can r...

Implement Image Upload Functionality for Django Integrated TinyMCE Editor

Django’s Admin panel is highly user-friendly, and pairing it with TinyMCE, an effective rich text editor, simplifies content management significantly. Combining the two is particular useful for bloggi...

Leave a Comment

Anonymous

◎Feel free to join the discussion and share your thoughts.