Mechanism
When a central accepts an advertiser, it sends a CONNECT_IND (CONNECT_REQ) PDU whose LLData field carries everything a third party needs to follow the connection: the 32-bit access address that will tag every subsequent data PDU, the CRC initialisation value, the channel map, the hop increment and the connection interval (Vol 6 Part B §2.3.3.1) [btcorespec]. From that moment the two devices leave the advertising channels (37/38/39) and exchange data PDUs on the 37 data channels, changing channel every connection event according to a channel selection algorithm (Vol 6 Part B §4.5.8) [btcorespec]. A sniffer that read the CONNECT_IND can compute the same channel sequence and hop along with the connection, recording every PDU — the technique Mike Ryan established for BLE [ryan2013btle].
Two channel selection algorithms exist. Connections where at least one peer is pre-BLE-5, or where the ChSel bit is unset, use CSA #1, a simple (channel + hopIncrement) mod 37 walk filtered by the channel map [btcorespec]. BLE 5 connections use CSA #2, a PRNG-style mapping that is harder to track; Cauquil reverse-engineered it and showed the hop sequence can be predicted from the access address alone, by measuring hops across a handful of channels [cauquil2019csa2]. Either way, following is a passive-observation problem, not a cryptographic one — the connection parameters are not secret.
The harder case is a connection that is already established when the sniffer arrives: there is no CONNECT_IND left to read. The access address is still recoverable because it is in the header of every data PDU, but the channel map and the connection-event counter must be reconstructed. A wide-band radio watching several data channels at once can do this by elimination — each observed connection event rules out every counter value incompatible with it — until the hop sequence is pinned down [ballabriga2020sdr]. This is the basis of the SDR all-channel capture path (ice9), which is the only practical way to grab a long-lived connection you did not see start.
This is a capture-feasibility control. It produces a PCAP of link-layer traffic; it does not itself decide whether that traffic is a finding. If the connection is unencrypted, the captured data PDUs are readable in the clear, and the judgement of whether that exposes sensitive data, or whether encryption should have been mandatory, is BSAM’s (BSAM-DI-04 sensitive-data exposure, BSAM-EN-02 force use of encryption). RFSAM owns only the RF prerequisite — reaching the point where those BSAM controls can be applied to real captured traffic. The same captured hop sequence is also the prerequisite that the active controls build on: decrypting a weakly-paired link (RFSAM-BLE-CR-01) and hijacking a live connection (RFSAM-BLE-AT-01) both start from following the connection that this control captures (RFSAM-RES-04).
Procedure
All steps are passive reception. Capture only devices you own or are explicitly authorised in writing to test; data-channel PDUs may carry another party’s personal data.
-
Identify the target connection. Passively scan the advertising channels and note the advertiser’s MAC and the moment it accepts a connection (its advertising stops). With Sniffle on a CatSniffer:
./sniff_receiver.py -c 37 -a -d-astays in passive-scan mode (does not follow yet) and-ddecodes advertising data, so you can read the device name and address and pick the target. Expected output is a running list of advertisements; the target’sAdvAis the MAC you will filter on next. -
Follow the connection from its setup (CSA #1 or #2). Restart Sniffle with a MAC filter and a PCAP output, then trigger or wait for the connection to form:
./sniff_receiver.py -c 37 -m AA:BB:CC:DD:EE:FF -o conn.pcapSniffle hops the advertising channels to catch the
CONNECT_IND, reads the access address and hop parameters from it, and switches to following the data channels. Expected output: theCONNECT_INDline, then a stream ofData / LL DataPDUs with a stable access address — confirmation you are following the connection. The PCAPconn.pcapaccumulates every captured PDU. (Add-e -Hif the device connects via BT5 extended advertising; add-lfor the Coded long-range PHY.) -
Confirm the capture in Wireshark. Open the PCAP and verify you have data-channel traffic, not just advertisements:
wireshark conn.pcapFilter on
btle.data_header(data PDUs) andbtle.access_address == 0x........(the connection’s AA). A populated list means the data channel was followed. Apply!btle.length == 0to drop empty keep-alive PDUs and see only PDUs that carry payload. -
Classify the link as encrypted or clear. In Wireshark, look for
LL_ENC_REQ/LL_ENC_RSPandLL_START_ENC_REQnear the start of the connection. If they are absent, the link is unencrypted and the L2CAP/ATT payloads dissect directly — this is the input BSAM-DI-04 / BSAM-EN-02 judge. If they are present, the data PDUs afterLL_START_ENC_RSPappear as encrypted blobs (decryption, where the pairing was weak, is RFSAM-BLE-CR-01’s scope, not this control’s). -
(Already-running connection, no
CONNECT_IND.) If the connection is already up when you start, the dedicated sniffer in steps 1–2 cannot lock on. Use the SDR all-channel path, which recovers the access address from data PDUs and reconstructs the hop sequence by elimination [ballabriga2020sdr].-l/--capturecaptures live and-wwrites the PCAP;-asniffs all channels (requires a bladeRF 2.0), or use-c/-Cto capture a slice of the band on a HackRF/USRP:ice9-bluetooth -l -a -w established.pcap(HackRF slice instead of
-a:ice9-bluetooth -l -c 2440 -C 20 -w established.pcap.) ice9 channelises the band, detects every BLE burst — including the PDUs of connections already in progress — and logs them toestablished.pcap; there is no separate “list addresses” step, so you filter the capture by the target’s access address in Wireshark afterward (per step 3). Expected output: data PDUs accumulate in the PCAP and the connection’s access address becomes visible once you filter onbtle.data_header. This path needs CPU/GPU for channelisation and a wide-band radio (bladeRF for the full 80 MHz, HackRF for a slice).
Field case
A documented public example shows the full sequence end to end. The BtleJack README walks through catching a new connection off the air with btlejack -c any: it reports Got CONNECT_REQ packet from 55:c5:95:6f:b4:df to 40:23:99:f6:0a:c0, decodes the on-air CONNECT_REQ (05 22 df b4 6f 95 c5 55 c0 0a f6 99 23 40 1d 7b 2f 0a 9a f4 93 01 12 00 27 00 00 00 d0 07 ff ff ff ff 1f 0b), and prints the connection parameters straight from it — access address 0x0a2f7b1d, CRC Init 0x93f49a, hop interval 39 (a 48.75 ms connection interval, since 39 × 1.25 ms), hop increment 11, channel map 0x1fffffffff — then follows the link and emits the data-channel PDUs as LL Data: lines [btlejack]. That is exactly the observable this control produces: a stable access address tagging a continuous stream of followed data-channel PDUs, with the hop sequence read directly from the sniffed connection request.
The same workflow applies to your own bench device — a fitness band and its phone app on a test rig, not a third party’s. With Sniffle on a CatSniffer parked on channel 37, the band advertises as a connectable peripheral; opening the app triggers the phone to connect, Sniffle logs the CONNECT_IND, latches the access address, and switches to following the data channels. Filtering conn.pcap in Wireshark on the connection’s access address shows a continuous stream of data PDUs; if no LL_ENC_REQ appears, the link is unencrypted and the ATT notifications (e.g. step-count and heart-rate handles) dissect in the clear.
That captured-in-the-clear traffic is exactly the input the BSAM judgement consumes: BSAM-DI-04 weighs whether those plaintext readings are sensitive-data exposure, and BSAM-EN-02 weighs whether the service should have refused to operate without encryption. RFSAM’s part ends at producing the PCAP. The remaining per-device specifics on your own bench — the target model, the exact ATT handles exposed, and how many data PDUs were captured before the app disconnected — are left as placeholders rather than fabricated: [FILL: target device model, ATT handles seen, PDU count]. Do not assert a specific finding until these are captured on real hardware.
Remediation
Developer. Capture-in-the-clear is only a problem because the link is readable. Require LE Secure Connections and refuse to expose any sensitive characteristic before encryption starts, so a follower’s PCAP contains only encrypted blobs (the judgement BSAM-EN-02 makes) [btcorespec]. Do not place secrets in pre-encryption link-layer or unencrypted ATT traffic.
Integrator. Verify that the product as shipped actually negotiates encryption for the services that matter — run this capture against the integrated device and confirm LL_ENC_REQ/LL_START_ENC_REQ appear and that no readable sensitive payload precedes them. Prefer components that support and default to LE Secure Connections over LE Legacy pairing.
Operator. Treat the RF link as observable: anyone within range can record an unencrypted connection’s data channel with sub-$150 hardware [ryan2013btle]. Where the threat model includes a nearby observer, deploy only devices whose sensitive functions are gated behind encryption, and re-test after firmware updates that touch the Bluetooth stack. Following a connection is a passive act — encryption is the only control that denies the captured bytes their meaning.