Dev.to Security 🔐 Cybersecurity 👁 0 📖 5 min read

The Art of Passive: How to Survey 2.4/5GHz Without Transmitting a Single Frame

Every modern device screams into the void. Your phone, even with WiFi "off," sends probe requests: Is Starbucks_WiFi here? Is Home_Network here? Your laptop does it faster. The standard wardriving setup — a phone runnin

Every modern device screams into the void.

Your phone, even with WiFi "off," sends probe requests: Is Starbucks_WiFi here? Is Home_Network here? Your laptop does it faster. The standard wardriving setup — a phone running WiGLE — does it constantly. You're not just surveying the city. You're announcing yourself to it.

I wanted the opposite. A pocket rig that listens and never speaks.

Active vs. Passive is a physical difference

Most people think wardriving is about connecting. It's not.

Active scanning = you transmit. You send probe requests on every channel, you wait for probe responses, you might even try association. Every access point and every sniffer within 300 meters now knows your MAC, your radio capabilities, and that you were at that corner at 14:32:07.

Passive scanning = you shut up and listen. Access points are required to shout their existence 10 times per second — that's the beacon frame. It contains everything you need for a survey: BSSID, SSID (or that it's hidden), channel, RSSI, supported rates, security suite (WPA2/WPA3/OWE), WPS, PMF status. You don't have to ask.

On the ESP32-S3, the difference is one line in the driver:

// Active: sends probes, gets more responses, leaks more
wifi_scan_config_t active = { .scan_type = WIFI_SCAN_TYPE_ACTIVE };

// Passive: just sits on channel, counts beacons
wifi_scan_config_t passive = { 
  .scan_type = WIFI_SCAN_TYPE_PASSIVE,
  .scan_time.passive = 250 // ms per channel
};

That .scan_type changes everything about your footprint.

When you go passive:

  1. Your transmit power amplifier stays off. Power draw drops ~90mA.
  2. Your MAC never leaves your antenna.
  3. You become invisible to intrusion detection systems that trigger on probe floods.
  4. You also miss client devices. That's a feature. Clients are people. We don't log people.

Why the ESP32-S3 is perfect for this

It's not the most sensitive radio. An ALFA card is hotter. But it has three properties you can't beat for a backpack rig:

1. It has real promiscuous mode that reports 802.11 mgmt frames to you.
You get WIFI_PKT_MGMT callbacks with full beacon bodies. You can parse the Information Elements yourself instead of trusting the dumbed-down scan result.

2. It has enough RAM to buffer without an SD stall.
WiFi beacons in a city: ~400-800 per second on 2.4GHz. If you write to SD on every packet, you'll brown out. The S3 lets you ring-buffer in PSRAM and flush every 2 seconds.

3. It doesn't run Android.
No baseband that phones home. No location service. No Google Play Services asking for ACCESS_FINE_LOCATION. The firmware I run doesn't have a TCP stack compiled in at all.

The architecture is stupid simple:

[2.4/5GHz Antenna] -> [ESP32-S3 Radio] -> [Beacon Parser]
                                      |
                       [u-blox GPS UART] -> [TinyGPS++ / PPS sync]
                                      |
                               [PSRAM Ring Buffer]
                                      |
                              [SD Card - FAT32 + ChaCha20]

No display needed for operation. The display is just for confidence: SATS: 8 FIX: 3D LOG: 14329.

The GPS lie everyone believes

Your GPS doesn't give you position. It gives you time that you convert to position.

For wardriving, time sync is more important than a dot on a map. If your ESP32 clock drifts 2 seconds from GPS time, your KML track will place a network 40 meters behind you at walking speed. That's the difference between "this coffee shop" and "that apartment building."

Cheap NEO-6M modules send NMEA at 1Hz with ~100ms jitter. That's garbage for correlation. The trick:

  • Parse $GPRMC for UTC, not just $GPGGA for position
  • Use the PPS pin if your module has it (ATGM336H does) — it pulses exactly on the second
  • Stamp each WiFi observation with gps.time + millis_since_pps
  • Don't log anything until hdop < 1.5 and sats >= 6

My rule: No fix, no log. I would rather walk a block with no data than poison my dataset with 50-meter drift.

Offline maps aren't nostalgic, they're operational

Online map tiles in the field are an OPSEC failure. Every tile request is:

GET /14/4823/6160.png
With your IP, your user-agent, at a precise time, correlated to where you were.

Offline MBTiles on SD fixes this. It's a SQLite file with all tiles to zoom 17 for your city. ~1.2GB for all of Charlotte. The ESP32 never needs it — you render it later on your air-gapped laptop.

The pipeline I settled on after 3 corrupted SD cards:

  1. Field: LOG_20260418_1432.CHA — encrypted binary, not plaintext CSV
  2. Home: Python decrypts, dedupes BSSID (keep strongest RSSI per 10m grid)
  3. Enrich: add WPA3/SAE detection, PMF required/optional, 802.11k/v flags
  4. Export: KML with ExtendedData so Google Earth can filter by security

A KML entry looks like this:

<Placemark>
  <name>CALYPSO_COFFEE_2G</name>
  <ExtendedData>
    <Data name="BSSID"><value>24:5A:4C:XX:XX:XX</value></Data>
    <Data name="SEC"><value>WPA2-PSK / WPA3-SAE Transition</value></Data>
    <Data name="PMF"><value>Optional</value></Data>
    <Data name="RSSI"><value>-62</value></Data>
  </ExtendedData>
  <Point><coordinates>-80.84,35.22,0</coordinates></Point>
</Placemark>

No client MACs. No traffic. Just beacons that were already public.

FIELD NOTE: What I actually see

After ~60km walked in Charlotte:

  • 68% of networks are still WPA2-PSK only. Transition mode to WPA3 is at ~22% now, up from 11% last year.
  • The noisiest SSIDs: XFINITY, SpectrumWiFi, HP-Print-XX, hidden SSIDs that are obviously printers
  • Battery reality: 2x Samsung 35E 18650 + MP1584EN buck = 11h 20m continuous with a 2dBi duck. The cheap powerbank died at 3h because it went to sleep between SD flushes.
  • SD card that doesn't corrupt: SanDisk High Endurance, not Ultra. FAT32, 32KB allocation, pre-allocated 100MB file.

And the thing nobody tells you: you find infrastructure. The water utility's LoRa gateway with a misconfigured WiFi AP. The traffic light controller with Cisco123 still as its SSID. It's a census, not a hack.

Why not just use your phone?

You can. But you shouldn't if you care about:

  1. Your own privacy. Your phone's survey is linked to your Google account.
  2. Data quality. Phones aggressively filter and cache scans to save battery. You'll miss 40% of networks.
  3. Control. You can't set passive mode. You can't get raw IE tags.

A dedicated rig costs $68 and weighs 180g. It lives in a small Pelican knockoff. It has one switch. On/off.

I got tired of explaining this in DMs, so I turned the entire build into a single-file field operations terminal.

It looks like it was downloaded from a BBS in 1999 — Mac System 7 chrome, bone paper, warning stamps, file CRCs — but it's a fully interactive manual with schematics in SVG, copyable terminal sessions, diagnostic flowcharts, and a real failure database. One HTML file. No install. Works air-gapped.

If you want to build the thing that doesn't phone home:

Wardriver's Backpack v2: ESP32-S3 + GPS + Offline Maps — Field Terminal v2.1.4

BOM + firmware + KML pipeline + checklists + cheat sheet. Unclassified//Open Source.

Passive only. Never transmit.

📰 Read the original article on Dev.to Security

Originally published by Dev.to Security. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.