Recently Omri Iluz wrote about his experiences capturing BLE very cheaply using an RTL-SDR and an MMDS downconverter. His work is very interesting and is a good way to get starting playing with BLE on the cheap.
A software defined radio approach is very powerful, and if you're interested in sniffing Bluetooth with SDR you should definitely check out gr-bluetooth. Another interesting approach is to use a narrowband radio as a sniffer, like the one on the Ubertooth.
I've been researching BLE (also known as Bluetooth Low Energy and Bluetooth Smart) since 2012, and I wanted to share the BLE sniffer I built on the Ubertooth platform. My sniffer is highly robust and can capture data from connections on data channels. I also discovered weaknesses in BLE's security and wrote a tool to decrypt packets under some circumstances.
The sniffer is turnkey and painless: if you have an Ubertooth you can begin sniffing packets right now by running a single command. Our tools capture to PCAP files that can be loaded into Wireshark for analysis using the BLE plugin that ships with recent development builds of Wireshark.
My BLE sniffer and Ubertooth itself are 100% open source. The source for the Ubertooth firmware, host tools, and board design can be found on the Ubertooth Github.
Ubertooth is an open source platform for Bluetooth research. It has a powerful ARM microcontroller connected to a reconfigurable radio chip, the TI CC2400. Although it was originally built to monitor classic Basic Rate (BR) Bluetooth, it serves as an excellent platform for building a BLE sniffer.
At the physical layer, our BLE sniffer works by configuring the CC2400's modulation parameters to match those of BLE. We also program the radio to search for a 32 bit value known as the Access Address that is at the beginning of every packet. When a nearby BLE device transmits, our radio sees the 32 bit Access Address and begins sending data to the ARM microcontroller.
Before we can read the data, we have to dewhiten it. This is done by XOR'ing the data with the output of a 7 bit LFSR. Our implementation dewhitens 32 bits at a time thanks to an impressive algorithm by Dominic Spill and Michael Ossmann. After this we parse the header and validate the CRC. Valid packets are passed up to the PC via USB where they are displayed and logged to PCAP files.
Timing Is Everything
Almost everything above happens on the Ubertooth dongle itself, and the PC just acts as a logging platform. This was a deliberate design choice made to satisfy one key requirement: timing.
In BLE, timing is everything. During connections devices hop to different channels relatively frequently, on the order of milliseconds. In this time we must receive the data, dewhiten it, parse the header, and make a decision about hopping very quickly. Sending the data to the PC and waiting for it to send a decision back would take too long for all but the slowest connections. USB latency alone is measured in milliseconds.
Additionally, on advertising channels and during connections two devices will transmit very quickly in sequence. First one device will transmit, and then 150 microseconds later the other will transmit. If we're busy analyzing the data from the first transmission, we may miss the second one altogether! This type of latency would be impossible to achieve over USB.
Following connections is where everything comes together. Advertising packets are sent on three channels in no particular order and can be captured easily. Connections hop along a sequence of 37 data channels very quickly, spending between 7.5 ms and 4 seconds on a given channel. If we wish to capture data from a BLE connection, we must hop along with the master and slave and listen for their packets on each data channel.
First we must sniff a CONNECT_REQ packet, which is transmitted by a BLE master device on an advertising channel. This packet initiates a connection between two devices and contains all the connection-specific details, such as Access Address, how frequently to hop, and in what order to visit data channels.
Once we have the details from the CONNECT_REQ packet, we have everything we need to follow along with the master and slave as they hop among the data channels. We hop to data channel 0 and wait for the first transmission. First the master transmits and then 150 microseconds later the slave transmits. We minimally process these packets and send them along to the PC. Then we hop to the next channel in the sequence and wait for the next packets. This continues until the master or slave closes the connection.
BLE conections are actually quite simple, significantly moreso than the hop pattern of BR Bluetooth. The only difficulty is meeting timing requirements, which we can do easily since all our processing occurs on the ARM microcontroller.
Our Ubertooth BLE sniffer also includes support for capturing data from connections that are already active at the time of sniffing. This feature, called promiscuous mode, is not supported by any other inexpensive commercial or open source sniffer. The only other tool I know of with support for this costs over US$ 20,000.
Due to the nature of BLE, without observing a CONNECT_REQ packet it is extremely difficult to recover all the parameters needed to successfully follow connections as they hop among the data channels. Hop timing, channel ordering, and even CRC calculation elude us.
I developed a few clever tricks to recover these key parameters using Ubertooth. Once we've recovered them, we feed them back into the normal connection following code and can actually begin following these active connections. For more details on how we recover the parameters, refer to my USENIX WOOT whitepaper.
Disclaimer: This mode is a little touchy: recovering the parameters can be tricky and we don't filter false positives well. However, once the parameters have been recovered, connection following is just as robust as if the CONNECT_REQ packet had been observed.
In early 2013 I discovered that BLE's encryption has a fatal flaw. I wrote a tool called crackle to automatically exploit this flaw and decrypt encrypted BLE data.
An attacker present during pairing can recover the encryption keys used to protect data during connections. Furthermore, since these encryption keys are reused, this attacker can decrypt every future conversation between the master and slave devices.
This attack is completely passive. The attacker simply has to capture the packets sent by the pairing devices using a tool such as Ubertooth. No packets are ever transmitted by the attacker, and the victims will have no knowledge that they are being eavesdropped on.
If you give crackle a PCAP file that contains the pairing data, it will automatically crack the encryption key and decrypt any further data sent during the connection. If you give it a key and a PCAP file filled with encrypted data, it will decrypt the data.
Obviously this is a huge weakness in BLE and severely weakens the security of the system. I was surprised that, although this weakness has been public for a while, the latest version of the Bluetooth Core Specification (version 4.1, published in December 2013) does not address it.
I've intentionally left out a lot of details since this blog post is already long-winded enough as-is. If you're interested in more depth, you can do any of the following:
- Check out my USENIX talk and white paper
- Watch my earlier, related talks
- Send me an email: mikeryan at lacklustre dot net
- Tweet me @mpeg4codec
- Drop into #ubertooth on freenode and say hello!
Ubertooth can be purchased from several places, the full list is available on the Great Scott Gadgets web site.
Finally I would like to express thanks to the many people who helped make this work possible, but in particular: