This post will primarily be an introduction into Bluetooth and Bluetooth Low Energy testing, along with information on setting up the environment and tools required.
Other resources were referenced for this post, and the respective links can be found throughout and in the final section.
Step 1 - Setup
- Ubertooth-One USB
- Unix-based OS (OS X is compatible)
- Software listed below
Build Guide from GreatScottGadgets focusing on other OS setups: https://github.com/greatscottgadgets/ubertooth/wiki/Build-Guide
Install the necessary libraries and tools:
1 apt-get install cmake libusb-1.0-0-dev make gcc g++ libbluetooth-dev pkg-config libpcap-dev python-numpy python-pyside python-qt4
Next, install the Bluetooth baseband library:
1 cd /opt && wget https://github.com/greatscottgadgets/libbtbb/archive/2015-09-R2.tar.gz -O libbtbb-2015-09-R2.tar.gz && tar xf libbtbb-2015-09-R2.tar.gz && cd libbtbb-2015-09-R2 && mkdir build && cd build && cmake .. && make && sudo make install
Now the Ubertooth tools can be downloaded and configured:
1 cd /opt && wget https://github.com/greatscottgadgets/ubertooth/releases/download/2015-09-R2/ubertooth-2015-09-R2.tar.xz -O ubertooth-2015-09-R2.tar.xz && tar xf ubertooth-2015-09-R2.tar.xz && cd ubertooth-2015-09-R2/host && mkdir build && cd build && cmake .. && make && sudo make install && sudo ldconfig
Install the Kismet tools if desired. I have added a oneliner Sed command to replace the manual change described in the build guide. I have also changed one of the libraries (libncurses-dev) as I kept getting package errors when trying to install via apt:
1 cd /opt && sudo apt-get install libpcap0.8-dev libcap-dev pkg-config build-essential libnl-dev libncurses5-dev libpcre3-dev libpcap-dev libcap-dev && wget https://kismetwireless.net/code/kismet-2013-03-R1b.tar.xz && tar xf kismet-2013-03-R1b.tar.xz && cd kismet-2013-03-R1b && ln -s ../ubertooth-2015-09-R2/host/kismet/plugin-ubertooth . && ./configure && make && make plugins && sudo make suidinstall && sudo make plugins-install && sed -i 's/logtypes=pcapdump,gpsxml,netxml,nettxt,alert/logtypes=pcapdump,gpsxml,netxml,nettxt,alert,pcapbtbb/g' /etc/kismet/kismet.conf
You’ll likely have Wireshark installed already so I’ve omitted the apt install of the base package:
1 apt-get install wireshark-dev libwireshark-dev && cd /opt/libbtbb-2015-09-R2/wireshark/plugins/btbb && mkdir build && cd build && cmake -DCMAKE_INSTALL_LIBDIR=/usr/lib/x86_64-linux-gnu/wireshark/libwireshark3/plugins .. && make && sudo make install
Lastly install the BTBREDR libary:
1 cd /opt/libbtbb-2015-09-R2/wireshark/plugins/btbredr && mkdir build && cd build && cmake -DCMAKE_INSTALL_LIBDIR=/usr/lib/x86_64-linux-gnu/wireshark/libwireshark3/plugins .. && make && sudo make install
To decrypt Bluetooth Low Energy (BTLE) you will need to use something like Crackle to process the PCAP file that you’ve output from ubertooth-btle. We’ll go in to this later, but for now you can just install it with the following one-liner:
1 cd /opt && git clone https://github.com/mikeryan/crackle.git && cd crackle/ && make && sudo make install
Step 2 - Capturing
Start up Kismet from the command line or the task menu. Once it is running, accept all of the default options (colours, etc) and start the Kismet server when prompted.
Next you will be prompted to add a source interface. Use the following options:
1 2 3 Intf: ubertooth Name: ubertooth Opt: [blank]
Navigate to [Kismet > Plugins > Select Plugin] and enable ‘ubertooth_ui.so’. The status will change to ‘pending’, which is intended.
Logged packets will be stored in the working directory for Kismet, which if you started the application via the command line will be the directory you were in. If this is the case, you can change to that terminal window and see a live output of the Bluetooth packets that were captured, likely displaying the LAP (Lower-Address-Part).
Upon exiting Kismet the output should be saved to a pcapbtbb file, which can be imported into Wireshark.
Standard Bluetooth is a tough cookie to crack as the protocol is setup to channel hop repeatedly and very, very quickly - hence why the Ubertooth-One was created to offload the channel hopping to dedicated hardware. Each hopped packet transmits a LAP, a Lower Address Part, which is one of three address parts used by the protocol. The others are the UAP (Upper Address Part - something we need), and the NAP (Non-significant Address Part), both of which make up the ‘Company ID’ that is assigned much like a network adaptor MAC address.
Lower Address Part - LAP:
The LAP is transmitted with every packet and is easy to demodulate, however the UAP is the pot of gold at the end of the rainbow. Once we’ve captured and demodulated at least one Bluetooth packet we then have the LAP. We can do this with the Ubertooth by using the following comand without any arguments:
The output will be something vaguely similar to the following output, where the LAP is clearly displayed next to the Channel (ch).
1 systime=1444317293 ch=39 LAP=28c03f err=2 clk100ns=798510522 clk1=127761 s=-29 n=-62 snr=33
Upper Address Part - UAP:
The UAP is only 8 bits long, and the easiest method to determine it’s value is a brute force (maximum 256 potential values) attack, however this requires interaction with the target. The NAP is not required as it is ignored on the initial connection process. This is only possible however if the target device is in a connectible state.
I won’t go in to too much detail as the guys over at the Ubertooth project have written a fantastic blog post about their process: http://ubertooth.blogspot.co.uk/2014/06/discovering-bluetooth-uap.html.
As for the commands to use for determining the UAP, we can run the following:
1 ubertooth-rx -l 28c03f
This command targets the device with the LAP we identified earlier. The Ubertooth will passively listen and will attempt to identify the hopping pattern of the target device. The first method for obtaining the UAP that was created by the Ubertooth team was to reverse the Header Error Check that appears within the header of the packets. An except from the Project Ubertooth blog post relating to this is as follows:
Our first technique is to compute the UAP by reversing the Header Error Check (HEC) that appears at the end of the header of every packet that has a header. The HEC is an 8 bit value computed from the master’s UAP and the header bytes. The purpose of the HEC is to allow a receiver to verify that the packet header was received correctly, without any unrecovered bit errors. We assume that we received the packet without bit errors (which is true most of the time). After decoding the HEC and the packet bytes it is possible to determine the one missing variable, the UAP. This is particularly easy because Bluetooth’s HEC algorithm is reversible; we can run it forward to determine the HEC from the UAP and packet bytes, or we can run it backward to determine the UAP from the HEC and packet bytes.
Every Bluetooth packet is whitened or scrambled by XOR with a pseudo-random bit sequence before transmission. Since the packet header is whitened, we have to unwhiten it before we can reverse the HEC algorithm.
There are 64 possible pseudo-random sequences that can be used to whiten a packet. The particular sequence is selected by the lower six bits of the master’s clock (CLK1-6) that is used for other things such as synchronizing the frequency hopping pattern.
When we receive a packet, we try each of the 64 possible CLK1-6 values. For each value, we determine the whitening sequence, unwhiten the packet using that sequence, and reverse the HEC algorithm to determine the UAP. This gives us 64 candidate UAP values, so we’ve reduced the search space from 8 bits to 6 bits. Because we have a way to compute the UAP for a particular CLK1-6, we take the approach of trying to determine CLK1-6.
There is one easy way to determine the correct CLK1-6. If a packet has a payload that includes a Cyclic Redundancy Check (CRC), then we can use the CRC to verify that we have unwhitened the packet correctly. If one of our 64 possible CLK1-6 values results in a CRC match, then we win.
The main problem with the CRC method is that it only works on packets that have CRCs. If you look through the Bluetooth Core Specification, you’ll find that only certain packet types have payloads with CRCs, and it turns out that these are the minority of Bluetooth packets in the wild. It is very common to see thousands of packets from a piconet without ever capturing one CRC with Ubertooth. Because of this, we needed another method to determine if a CLK1-6 value is correct or incorrect.
Unfortunately there is a problem with error checking when trying to obtain the UAP, which means that it may be possible to obtain the UAP and then actually lose it. This happens when a packet is received that conflicts with the identified UAP, which then renders it void.
Bluetooth Low Energy (BTLE):
Capturing BTLE is fairly straight forward. Initially you’ll want to find connections and output the data to a PCAP file for later cracking using Crackle. Much like the ubertooth-rx tool it is possible to follow connections, sniff promiscuously, and set addresses to follow rather than listening to all connections.
Basic capture to stdout can be performed with the following command:
1 ubertooth-btle -p
This will enable promiscuous mode and will output data that looks similar to this:
1 2 3 4 5 6 7 8 9 systime=1444318925 freq=2440 addr=43bf3d62 delta_t=0.800 ms 01 00 9f 8a 2b Data / AA 43bf3d62 (valid) / 0 bytes Channel Index: 17 LLID: 1 / LL Data PDU / empty or L2CAP continuation NESN: 0 SN: 0 MD: 0 Data: CRC: 9f 8a 2b
Ideally, what we are looking for is to capture connection and pairing requests, along with the necessary responses. Once we’ve done this we can move on to decryption with Crackle.
Using the newly-created PCAP file from the ubertooth-btle session earlier we can run Crackle using the PCAP file within the -i (input) argument. For this to actually decrypt the data we need to also specify an output file with -o <output.pcap>:
1 crackle -i btle-capture.pcap -o btle-decrypted.pcap
If we are able to capture the pairing then we can obtain the encryption key (LTK - Long Term Key) that are used to encrypt the data, and since these keys are reused on the paired devices we could continue to decode and decrypt future data if we are in proximity of the devices again.
Crackle can crack the encryption key and will decrypt any data that is sent during the connected session. If the key is specified along with encrypted data in a PCAP file then crackle will decrypt the data too:
1 crackle -i btle-capture.pcap -o btle-decrypted.pcap -l 11223344556677889900aabbccddeeff
This would decrypt the captured data that was encrypted with the aforementioned LTK (Long Term Key) and output it to the ‘btle-decrypted’ PCAP file.
Pentura Labs offer some very good information into other avenues and tools that can be used to decrypt BTLE and Bluetooth. The main article I’m referring to can be found here.
Tools such as hcidump, csrsniff, and the brute-force bt-uap-search.rb file (which I cannot seem to find anywhere else on the internet).
For csrsniff the C code can be found on Google Code, although you’ll need to compile it manually:
1 gcc csrsniff.c -o csrsniff -lbluetooth
Once complete the binary file will be executable. The
-h argument provides some information on the tool’s functionality.
Step 3 - Analysis
Open Wireshark and navigate to [File > Open] and select the pcapbtbb file, which should be imported and readable much like network TCPIP captures.