Bluetooth Low Energy (BLE)
Low-power 2.4GHz wireless built on GATT: services and characteristics for wearables, locks, and beacons.
BLE (Bluetooth Low Energy) is a low-power 2.4GHz wireless protocol built around GATT, a hierarchy of services and characteristics that devices read, write, and notify. It is a distinct stack from classic Bluetooth (BR/EDR), tuned for coin-cell battery life and short bursts of data rather than streaming audio.
What it is
BLE operates in the 2.4GHz ISM band across 40 channels of 2MHz each. Three of them (37, 38, 39) are dedicated advertising channels; a device broadcasts small advertisement packets there, and a central (a phone, a gateway, your laptop) scans, connects, and then hops across the 37 data channels. Every device carries a 48-bit Bluetooth address that may be public or a rotating random address for privacy. Once connected, all application data flows through GATT (Generic Attribute Profile), which sits on top of ATT (the Attribute Protocol). GATT organises everything into services, characteristics, and descriptors, each addressed by a 16-bit or 128-bit UUID.
Why it matters
Smart locks, fitness bands, glucose monitors, industrial sensors, and beacons expose their entire control surface over GATT. If a lock has an "unlock" characteristic and pairing is weak or absent, writing the right bytes to that handle opens the door. Many products ship with Just Works pairing (no out-of-band secret, no numeric comparison), which authenticates nothing and is trivially observed, or they skip encryption entirely and rely on the app "hiding" the characteristic. On the bench, BLE is often the shortest path from radio to the device's actual logic.
How GATT works
A characteristic is the atom you interact with. It has a value handle, a set of properties, and optionally descriptors:
| Level | Holds |
|---|---|
| Service | a UUID grouping related features |
| Characteristic | a value + properties (read/write/notify/indicate) |
| Descriptor | metadata, e.g. the CCCD that enables notifications |
To receive push updates you write 0x0001 to a characteristic's CCCD; the peripheral then sends notifications on that handle as the value changes. See the diagram for the shape.
How to attack it
Work from advertisement to write, using a supported adapter or an nRF52840 dongle:
# 1. Scan for advertising devices (name, address, RSSI).
sudo hcitool lescan
bluetoothctl # scan on; devices; info <MAC>
# 2. Enumerate the full GATT table (services, characteristics, handles).
gatttool -b AA:BB:CC:DD:EE:FF -I
# > connect
# > primary # list services
# > characteristics # list characteristics + handles + properties
# 3. Read and write raw handles.
gatttool -b AA:BB:CC:DD:EE:FF --char-read -a 0x0025
gatttool -b AA:BB:CC:DD:EE:FF --char-write-req -a 0x0025 -n 01
# Modern alternative: bleak (Python) or nRF Connect (mobile) for the same steps.
Then capture the app's own traffic: an nRF52840 running the sniffer firmware feeds a live BLE link into Wireshark, so you can watch which handle the vendor app writes to unlock, and replay it. Test explicitly for Just Works pairing, static or hardcoded keys, and characteristics that accept writes with no bonding.
Pitfalls
- A random resolvable address changes over time; do not assume the MAC is stable across sessions. Bond, or track by the identity resolving key.
- Caching bites you: phones and
bluetoothdcache the GATT table, so a stale handle map hides characteristics the device really exposes. Clear the cache or re-discover. - Encryption is not the same as authentication. An encrypted-but-Just-Works link is still open to a passive sniffer that watched the pairing.
- Connection parameters and channel hopping make blind sniffing hard; follow the connection from the advertisement, do not try to jump into an established link.