Three small Pi builds that each go deep on a single radio protocol. Not products, not portfolio polish — these are the experiments where I forced myself to actually understand the layer below the abstraction. The Wi-Fi scanner taught me 802.11 frame internals; the BLE sniffer demystified GATT and advertisements; the NFC toolkit broke the spell of "tap-to-pay magic."
Build 1 · Wi-Fi scanner
A Pi 4 with the TP-Link AC600 in monitor mode, running a 60-line scapy script that channel-hops 1→13 every 250ms and logs every beacon, probe request, and association frame it sees. Output is a live-updating terminal table sorted by RSSI.
from scapy.all import sniff, Dot11Beacon, Dot11Elt
def handle(pkt):
if pkt.haslayer(Dot11Beacon):
ssid = pkt[Dot11Elt].info.decode(errors="ignore")
bssid = pkt.addr2
rssi = pkt.dBm_AntSignal
channel = ord(pkt[Dot11Elt:3].info)
log(ssid, bssid, rssi, channel)
sniff(iface="wlan1mon", prn=handle, store=0)
The lesson was that beacons are noisy and probes are interesting. Devices broadcast the SSIDs they're looking for in probe requests — often including networks they've previously joined. Walk through a coffee shop with a sniffer and you can map who's been to whose house.
Build 2 · BLE sniffer
The BLE build runs on a Pi Zero 2 W using bluez and a custom Python script around btmon. The goal was to parse advertisement packets and identify device types — fitness trackers, AirPods, cheap IoT — by their advertisement structure, not just their MAC.
[ BLE ADVERTISEMENT ] ┌──────┬──────┬──────────────────┬────────┐ │ TYPE │ LEN │ MANUF DATA │ FLAGS │ ├──────┼──────┼──────────────────┼────────┤ │ 0xFF │ 0x1A │ Apple · 0x004C │ 0x0A │ → AirPods │ 0xFF │ 0x0F │ Samsung · 0x0075 │ 0x06 │ → Galaxy Buds │ 0x16 │ 0x09 │ Service · Fitbit │ 0x06 │ → Fitbit Charge └──────┴──────┴──────────────────┴────────┘
The MAC address rotates on most modern devices. The advertisement data does not. Apple's manufacturer-specific format alone tells you whether the device is an iPhone, MacBook, AirPod, or AirTag — useful for inventory, awkward for privacy.
Build 3 · NFC / RFID toolkit
The PN532 connected to a Pi 4 over I2C, running libnfc and mfoc for MIFARE Classic auth recovery. This was the most legally sensitive build of the three — anything you can do here that isn't against your own cards is a problem. So everything I've done with it has been on cards I own: hotel keys handed to me, bus passes from countries I've left, gym fobs after I've cancelled.
Reading NFC tags you own is fine. Cloning them onto a different fob to avoid paying for a service is fraud. Cloning a card you do not own is theft. The toolkit exists to understand the protocol — that's where it stops in this writeup.
What I learned from owning the actual chip: MIFARE Classic uses a 1994-vintage proprietary cipher (CRYPTO1) that has been broken for over a decade. Despite this it is still in widespread use for door access in offices and hotels worldwide. The toolkit takes about 90 seconds to recover all keys on a default-keyed card and dump the contents.
Three small builds, three months. The depth I got from each one is the kind you can't shortcut by reading. You have to wire the chip up, get the wrong byte order, fix it, and watch the first packet decode cleanly.