Last reviewed 11 min read

Discovery
Beginner
T1040 T1592

WiFi Reconnaissance

Reconnaissance involves discovering available networks (ESSIDs), their security configurations, and connected clients.

What to Record During Recon

For each target AP note: BSSID, channel, encryption type (ENC), signal strength (PWR), and the number of associated clients. A strong signal (better than -60 dBm, i.e. closer to 0) plus active clients makes an ideal handshake target. Save airodump output with -w so you can re-analyse offline.

Airodump-ng Scanning

Airodump-ng is the primary wireless recon tool. It channel-hops across all bands and displays discovered APs and associated clients in real time.

01-airodump-scan.sh
# Full scan — all channels, all bands
sudo airodump-ng wlan0mon

# Target a specific channel and BSSID (stops channel hopping)
sudo airodump-ng -c 6 --bssid AA:BB:CC:DD:EE:FF -w capture wlan0mon

# 5 GHz only scan (UNII-1..3, channels 36-177)
sudo airodump-ng --band a wlan0mon

# Dual-band scan (2.4 + 5 GHz simultaneously)
sudo airodump-ng --band abg wlan0mon

Understanding Airodump Output

Column Meaning Attack Relevance
BSSIDAP MAC addressTarget identifier, vendor OUI (Organizationally Unique Identifier) lookup
PWRSignal strength in dBm (closer to 0 = stronger)-60 dBm ≈ good, -40 dBm ≈ very close
BeaconsBeacon frames receivedRapid increase = active AP near you
#DataData frames capturedHigh count = active clients (WEP/handshake targets)
CHChannelLock to this channel for targeted attacks
ENCEncryption (WPA2, WEP, OPN)Determines attack approach
CIPHERCCMP or TKIPTKIP = vulnerable to TKIP Michael attacks
AUTHAuthentication type (PSK or MGT)MGT = Enterprise (802.1X), PSK = Pre-shared key
ESSIDNetwork nameBlank or <length: N> = hidden SSID
MBMax speed (Mbps)802.11n/ac indicator, helps ID hardware gen

Hidden SSID Discovery

Hidden SSIDs Are Not Security

Hiding an SSID only removes the name from beacon frames — the network still broadcasts beacons and responds to directed probe requests. Any client that connects (or has the SSID saved) will reveal it in plaintext. This is security through obscurity with zero cryptographic value.

Hidden networks appear in airodump-ng as <length: N> where N is the SSID length. There are four reliable methods to reveal the actual SSID:

Method 1: Passive Wait

Lock airodump to the hidden AP's channel and wait. When any client connects or sends a directed probe request, the ESSID will appear automatically.

02-hidden-passive.sh
# Lock to hidden AP's channel and wait for client probe
sudo airodump-ng -c 11 --bssid AA:BB:CC:DD:EE:FF wlan0mon
# ESSID will populate when a client sends a probe request

Method 2: Forced Deauthentication

If no clients are actively associating, force a disconnect. The reconnection handshake reveals the SSID.

03-hidden-deauth.sh
# Deauth a connected client — they'll re-probe with the SSID
sudo aireplay-ng -0 5 -a AA:BB:CC:DD:EE:FF -c CC:DD:EE:FF:00:11 wlan0mon

# Watch airodump — ESSID appears on reassociation
sudo airodump-ng -c 11 --bssid AA:BB:CC:DD:EE:FF wlan0mon

Method 3: Probe Request Sniffing with Wireshark

Capture all probe requests to see which SSIDs clients around you are searching for — including hidden ones.

04-hidden-probe-sniff.sh
# Capture and filter for probe requests containing the target BSSID
tshark -i wlan0mon -Y "wlan.fc.type_subtype == 0x04" \
  -T fields -e wlan.ssid -e wlan.sa | sort -u

# Wireshark display filter for probe requests
wlan.fc.type_subtype == 0x04 && wlan.ssid != ""

Method 4: MDK4 SSID Brute Force

If the SSID length is known (from the <length: N> value), brute-force or dictionary attack the name. This works because APs respond to correct probe requests even when hidden.

05-hidden-bruteforce.sh
# Brute force hidden SSID using MDK4 probe mode
# mdk4 reads the candidate SSIDs from a file (-f), not from a pipe
sudo mdk4 wlan0mon p -t AA:BB:CC:DD:EE:FF -f /usr/share/wordlists/ssid-list.txt

# Generate an SSID candidate list from common patterns, then feed it with -f
crunch 8 8 abcdefghijklmnopqrstuvwxyz0123456789 -o ssid-candidates.txt
sudo mdk4 wlan0mon p -t AA:BB:CC:DD:EE:FF -f ssid-candidates.txt

# -s sets the probe-request rate in packets per second (optional throttle)
sudo mdk4 wlan0mon p -t AA:BB:CC:DD:EE:FF -f ssid-candidates.txt -s 50

Kismet Deep Dive

Kismet is a passive wireless network detector, sniffer, wardriving tool, and wireless intrusion detection system (WIDS) framework. Unlike airodump-ng, Kismet runs a persistent web UI, supports multiple data sources simultaneously, logs to a SQLite database for post-analysis, and detects non-802.11 protocols (Bluetooth, Zigbee, Bluetooth Low Energy).

Installation & Configuration

06-kismet-install.sh
# Install Kismet (Kali/Debian)
sudo apt install kismet

# Add your user to the kismet group (avoids running as root)
sudo usermod -aG kismet $USER

# Start Kismet with a Wi-Fi source
kismet -c wlan0mon

# Start with multiple sources (dual-band + Bluetooth)
kismet -c wlan0mon:name=WiFi_2G -c wlan1mon:name=WiFi_5G -c hci0:name=BTLE

Access the Kismet web UI at http://localhost:2501. The dashboard shows live AP discovery, client associations, alerts, and GPS mapping (if a GPS receiver is attached).

Kismet Configuration Tuning

kismet.conf
# /etc/kismet/kismet.conf — key settings

# Override default source (or add via CLI)
source=wlan0mon:name=MainWiFi,channel_hop=true,channel_hoprate=5/sec

# Channel lock for targeted recon
source=wlan0mon:name=TargetCH,channel=6

# Enable PCAP logging for offline analysis
log_types=kismet,pcapng

# Wardriving — enable GPS
gps=gpsd:host=localhost,port=2947

# Alert on rogue APs — compare against known BSSID list
# (edit /etc/kismet/kismet_alerts.conf)
apspoof=CorpWiFi:ssidregex="CorpWiFi",validmacs=AA:BB:CC:DD:EE:FF

Querying the Kismet Database

Kismet stores results in a SQLite .kismet database. Query it for post-engagement analysis.

07-kismet-query.sh
# List all discovered SSIDs with encryption types
sqlite3 Kismet-*.kismet "SELECT devmac, type, CAST(device AS TEXT) FROM devices WHERE type='Wi-Fi AP';" | head -20

# REST API — query device list (while Kismet is running)
curl -s http://localhost:2501/devices/summary/devices.json \
  -H 'KISMET: admin:changeme' | python3 -m json.tool | head -30

# Export to Wigle CSV for wardriving upload
kismetdb_to_wiglecsv --in Kismet-*.kismet --out wardriving-results.csv

# Convert to pcapng for Wireshark analysis
kismetdb_to_pcap --in Kismet-*.kismet --out capture.pcapng

Kismet vs. Airodump-ng

Use airodump-ng for quick tactical scans — it's faster to launch and simpler to read. Use Kismet for long-duration wardriving, multi-source recon, WIDS alerting, and when you need structured database output for reporting. The two complement each other.

WiGLE & Wardriving

WiGLE is a global wardriving database of Wi-Fi and cell-site observations. For an authorised assessment it is an OSINT source: its public JSON API lets you correlate an observed BSSID or SSID to locations where other people have already seen it, and it accepts uploads of your own survey. That can place an access point when beacon data alone cannot, and it shows which areas are already mapped so you do not re-wardrive them.

The API is RPC-style under https://api.wigle.net/ — interactive documentation is at /swagger and CSV upload at /csvFormat.html. Authentication uses the API Name and API Token generated on your account page, sent over HTTP Basic. Commercial use requires a separate licence.

wigle-api.sh
# Search the global database by BSSID (HTTP Basic with API Name + API Token)
curl -s -u "$WIGLE_API_NAME:$WIGLE_API_TOKEN" \
  "https://api.wigle.net/api/v2/network/search?netid=AA:BB:CC:DD:EE:FF"

# Search by SSID instead
curl -s -u "$WIGLE_API_NAME:$WIGLE_API_TOKEN" \
  "https://api.wigle.net/api/v2/network/search?ssid=CorpWiFi"

Stay Within Authorisation

WiGLE returns historical observations from a third-party database, not a live scan. Use it only to enrich data you already collected lawfully during a scoped engagement, and treat a returned location as a lead to verify rather than proof that the AP is still there.

Channel Strategy & Band Planning

Understanding channel allocation is critical for efficient scanning and avoiding interference during attacks. Locking to the wrong channel wastes time and misses handshakes.

2.4 GHz Band (802.11b/g/n)

Channels Non-Overlapping Width Notes
1 – 141, 6, 1120 MHzMost APs on 1/6/11 — scan these first
14—22 MHzJapan only (802.11b), rarely seen
1 – 131, 5, 9, 13 (EU)20 MHzEuropean 4-channel plan

5 GHz Band (802.11a/n/ac/ax)

Band Channels DFS Required Notes
UNII-136, 40, 44, 48NoMost common — scan first
UNII-252, 56, 60, 64YesShared with radar — APs may vacate
UNII-2 Ext100–144YesOften empty — targets here are less monitored
UNII-3149, 153, 157, 161, 165NoCommon in US, less in EU

DFS Channels &amp; Radar Detection

DFS (Dynamic Frequency Selection) channels require APs to vacate if radar is detected. During pentesting, you can abuse this: spoofing radar pulses with an SDR forces all APs on DFS channels offline. This is federally illegal in most countries (it disrupts aviation/weather radar). Only test on isolated lab networks.

Efficient Scanning Strategy

08-channel-strategy.sh
# Quick 2.4 GHz sweep — channels 1, 6, 11 only (covers ~90% of APs)
sudo airodump-ng --channel 1,6,11 wlan0mon -w quick-scan --output-format csv

# Full 5 GHz sweep (if adapter supports it)
sudo airodump-ng --band a wlan0mon -w 5ghz-scan --output-format csv

# Lock to target channel for handshake capture
sudo airodump-ng -c 6 --bssid AA:BB:CC:DD:EE:FF -w target wlan0mon

# Tip: -f sets the channel-hop dwell time in milliseconds
# Shorter dwell = wider scan, fewer packets per channel
# Longer dwell = narrower scan, more packets, better for remote APs
sudo airodump-ng -f 500 wlan0mon

Passive Fingerprinting

Beyond basic SSID/BSSID enumeration, you can extract detailed information about AP hardware, firmware, and security capabilities from passive observation alone — no active probing required.

09-passive-fingerprint.sh
# OUI vendor lookup from BSSID (first 3 octets)
# AA:BB:CC:DD:EE:FF → look up AA:BB:CC at https://maclookup.app
# This reveals the AP manufacturer (Ubiquiti, Cisco, TP-Link, etc.)

# Extract supported rates and capabilities from beacons
tshark -i wlan0mon -Y "wlan.fc.type_subtype == 0x08" \
  -T fields -e wlan.bssid -e wlan.ssid -e wlan.fixed.capabilities \
  -e wlan_radio.channel -e wlan.rsn.pcs.type | sort -u

# Identify WPS-enabled APs (Wash)
sudo wash -i wlan0mon -C
# Look for "Lck" column = WPS lock status
# Version 1.0 = vulnerable to Pixie Dust and brute force

# Probe for 802.11w Management Frame Protection (MFP) support
tshark -i wlan0mon -Y "wlan.fc.type_subtype == 0x08 && wlan.rsn.capabilities.mfpc == 1" \
  -T fields -e wlan.bssid -e wlan.ssid -e wlan.rsn.capabilities.mfpr

Client Enumeration & Probe Analysis

Client devices leak valuable intelligence through probe requests — they broadcast the names of every network they've previously connected to. This enables targeted evil twin attacks.

10-client-probes.sh
# List all client probes visible in the area
tshark -i wlan0mon -Y "wlan.fc.type_subtype == 0x04" \
  -T fields -e wlan.sa -e wlan.ssid 2>/dev/null | sort | uniq -c | sort -rn

# Example output:
#   47 CC:DD:EE:FF:00:11  CorpWiFi          ← employee phone, searching for work SSID
#   23 CC:DD:EE:FF:00:11  Hilton_WiFi       ← recently stayed at Hilton
#   12 AA:BB:CC:DD:EE:22  ATT-WIFI-1234     ← home network name
#    8 AA:BB:CC:DD:EE:33  <Broadcast>       ← modern device, doesn't leak SSIDs

# Correlate clients to APs (airodump lower pane)
# The "Probes" column shows SSIDs each client has searched for
# The "BSSID" column shows which AP they're currently associated to

# Probe requests always use the broadcast DA (ff:ff:ff:ff:ff:ff), so a DA
# filter alone cannot separate associated from unassociated clients.
# List every client that emits probe requests:
tshark -i wlan0mon -Y "wlan.fc.type_subtype == 0x04" \
  -T fields -e wlan.sa -e wlan.ssid | sort -u

# Then drop any MAC that also appears in data frames to isolate clients that
# are only probing (i.e. not currently associated to an AP).

MAC Randomization

Modern iOS and Android devices randomize their MAC address during probe requests. The real MAC is only revealed after the device associates to an AP. Look for locally-administered MACs (second hex digit is 2, 6, A, or E) — these are randomized and won't match the real device MAC.

Output Formats & Post-Processing

11-output-formats.sh
# Save in all useful formats simultaneously
sudo airodump-ng -w recon --output-format pcap,csv,kismet,netxml wlan0mon

# Output files created:
# recon-01.cap     — full packet capture (Wireshark, hashcat, hcxpcapngtool)
# recon-01.csv     — parseable spreadsheet (Excel, grep, awk)
# recon-01.kismet.csv  — Kismet-compatible CSV
# recon-01.kismet.netxml — XML format for scripting

# Quick CSV analysis — top APs by client count
awk -F',' 'NR>2 && $1!="" {print $14, $1}' recon-01.csv | sort | uniq -c | sort -rn | head -20

# Parse with Python for reporting
python3 -c "
import csv
with open('recon-01.csv') as f:
    reader = csv.reader(f)
    for row in reader:
        if len(row) > 13 and row[5].strip():
            print(f'{row[0].strip():20s} CH:{row[3].strip():3s} ENC:{row[5].strip():6s} {row[13].strip()}')" 

Verify It Worked

Check Expected Where to look
Target AP appears in the scan airodump-ng lists the BSSID with its channel, ENC and PWR, and a hidden SSID shows as <length: N> The airodump-ng AP list
Capture files are written The -w recon --output-format pcap,csv,kismet,netxml run creates recon-01.cap, recon-01.csv, recon-01.kismet.csv and recon-01.kismet.netxml The working directory
Kismet database query returns APs sqlite3 Kismet-*.kismet returns Wi-Fi AP device rows The Kismet SQLite query
WPS-enabled APs identified wash -i wlan0mon -C lists APs with their WPS lock (Lck) status and version The wash output

Practice Labs

Practice wireless recon techniques in isolated environments.

Wireless Security TryHackMe easy
wireless attack conceptsrogue AP / evil twin (conceptual)WPSWPA3 & 802.1XBLE/RFID
Dumping Router Firmware TryHackMe medium
firmware extractionembedded OS analysisrouter secretsbinwalk