Great Scott Gadgets

open source tools for innovative people

My First Look at rad1o Badge

Over the next several days, thousands of hackers will gather at the Chaos Communication Camp in Germany. An electronic badge for the event is being prepared, and it is based on my design for HackRF One!

At DEF CON over the weekend, I was fortunate to be able to meet up with Ray, one of the members of the Munich CCC group responsible for the rad1o badge. Ray was wearing one of the prototype units, so I was able to take a close look.

rad1o prototype at DEF CON 23

The design is a variation of HackRF One. It includes a small LCD and an audio interface, so it is a bit like having a HackRF One plus a PortaPack H1 on a single board. A slim, rechargeable LiPo battery is mounted on the back. The visual design of the PCB looks like a traditional AM/FM radio receiver complete with an antenna (which is not the actual RF antenna) and a dial (which is not really a dial).

There are some design modifications, especially in the RF section, that seemed strange to me at first. The reason for many of these changes is that the rad1o team was able to get certain chip vendors to agree to sponsor the badge by donating parts. By redesigning around donated components they were able to reduce the cost to a small fraction of the cost of manufacturing HackRF One, making it possible to build the rad1o badge for several thousand campers.

The firmware for rad1o is derived from HackRF One firmware but is in a separate repository. Because of the LCD and other differences between the two hardware designs, they are not firmware-compatible. When using rad1o as a USB peripheral, it is fully supported by existing software that supports HackRF One. Future rad1o firmware will use a USB product ID of 0xCC15 assigned from the Openmoko pool, but the shipping firmware will borrow HackRF One's product ID. This will ensure that any existing software for HackRF One will work with rad1o during camp. The new product ID (0xCC15) is already supported in libhackrf release 2015.07.2, so it should be easy for people to update to it in the near future.

If you are new to Software Defined Radio and are looking forward to using the badge as a way to get started with SDR, I recommend starting with my video series. You might want to download the videos before leaving for camp. Also take a look at Getting Started with HackRF and GNU Radio and the recommended software for rad1o. If you plan to do firmware or hardware hacking, be sure to clone the rad1o repositories. For examples of Digital Signal Processing (DSP) on the LPC43xx, I suggest studying Jared Boone's firmware for PortaPack H1. Also check out the video of Jared's Software-Defined Radio Signal Processing with a $5 Microcontroller at BSidesLV 2015.

As an open source hardware developer, it is extremely satisfying to see folks start with my design and do something amazing like the rad1o badge. I'm excited to be attending camp for my first time ever, and I can't wait to see the projects people will come up with!

Wassenaar Comments

Today I submitted the following comment on the Bureau of Industry and Security (BIS) Proposed Rule: Wassenaar Arrangement Plenary Agreements Implementation; Intrusion and Surveillance Items.

Thank you for inviting comments on the Wassenaar Arrangement Plenary Agreements Implementation for Intrusion and Surveillance Items. As a member of the information security community, I am concerned about the effects of the proposed implementation on my industry.

I'll keep this brief by voicing support for the comments made by other prominent members of the community: Google, Katie Moussouris, Robert Graham, and Sergey Bratus et al.

My greatest concern is clarity of the proposed rule. If you must provide an answer to a frequently asked question about what a rule means, it may be because the rule was not written clearly. I was particularly troubled by the publication of the FAQ regarding the proposed rule, partly because it indicated a lack of clarity in the rule but also because the answers didn't seem much clearer. Had the answers been clear, I would still be concerned that the text of the rule would not be interpreted in the future in the same manner as your present interpretation. The text matters, and it is overbroad and unclear even to well informed members of the information security community.

Unfortunately, computer security is an unsolved problem. The people who are working to improve the state of the art of computer security are diverse members of a global community of researchers. The proposed rule directly prevents the sharing of information among those researchers, and it will have a negative impact on the security of computing systems and software for the entire world.

Software is a form of information, and control of the flow of information is very different from control of the transport of physical goods. I urge you to remove software from the scope of the Wassenaar Arrangement at the annual meeting of Wassenaar Arrangement members in December 2015.

Black Hat Student Pass

If you are a full-time university student and would like a free ticket to this summer's Black Hat Briefings, send an email to today. We have two tickets to give away, and we would like to give them to students who share our interests. You must meet Black Hat's criteria, and you will be responsible for your own travel and lodging.

We'll be busy at Black Hat USA this year. I'm teaching two sessions of my Software Defined Radio class, and I will be giving a talk at the Briefings about the NSA Playset. Additionally, Taylor and I will show off a new project called YARD Stick One at the Black Hat Arsenal.

HackRF One at 1 MHz

We've decided to advertise the fact that HackRF One operates all the way down to 1 MHz, not just to 10 MHz. This isn't a change to the hardware design; it is simply an acknowledgment that the hardware has always worked at such low frequencies and that we support operation down to 1 MHz.

transmit power plot

In fact, HackRF One can even function below 1 MHz, but the performance drops considerably as the frequency decreases. The curve is reasonably flat down to about 1 MHz, so we consider that to be the lower limit for most uses.

Now that we've seen consistent low frequency performance across multiple manufacturing runs, we're comfortable changing the official specification: HackRF One operates from 1 MHz to 6 GHz. Try attaching a long wire antenna to listen to shortwave radio!

Although HackRF One has reasonable performance down to 1 MHz, it performs better at higher frequencies. To get the best possible performance down to 1 MHz and lower, I recommend using an external upconverter/downconverter such as the excellent Ham It Up, open source hardware designed by Opendous.

Open House Invitation

For the first time ever, Dominic, Taylor, and I will all be in the same place at the same time in June. We decided we should celebrate, and you are invited!

Please join us at our recently expanded lab in Evergreen, Colorado on 11 June 2015 from 17:00 to 19:00. You can see the lab, talk to us about our projects, check out our latest prototypes, and even learn to solder!

RSVP to by 4 June 2015 so we don't run out of refreshments.

Great Scott Gadgets
27902 Meadow Drive, Suite 150
Evergreen, Colorado 80439
(the Canyon Courier building)

Free Stuff, February 2015

Great Scott Gadgets is pleased to announce the recipients of our inaugural Free Stuff give-away. This being our first give-away, we got a little overexcited and ended up giving away 5 HackRF One units to people who made requests in February! We were excited to see so much interest in our Free Stuff program, and after much deliberation we were able to narrow the field down to these 5 entrants. Congratulations, and we can't wait to see what you do with your HackRF Ones!

Alex Page wrote to us representing the Interlock hackerspace in Rochester, New York, which has recently begun hosting SDR meetups. They have been encouraging those new to SDR as well as seasoned veterans, and they have made a space where they can all interact. We are awarding Interlock a HackRF One unit to encourage this sharing of knowledge. Thanks Alex, and keep up the good work.

JinGen Lim is a promising student and developer from Singapore. When HackRF One was released he used it as an inspiration to build his own open source device called CCManager. We awarded JinGen a HackRF One unit to see what he can come up with next. Thanks for making your ideas open source JinGen!

Rajesh Kannan is a licensed amateur radio operator and enthusiast as well as a rather successful amateur meteorologist. Rajesh has plans to use his HackRF One to help develop an HRPT satellite receiver with a group of students in India. Thanks Rajesh for igniting the RF spark in the next generation!

Taavi Laadung is a graduate student at the Tallinn University of Technology in Estonia. He is working on a nanosatellite project and plans to use the HackRF One that we give him to help build a ground station. Thanks Taavi for including the HackRF One in your research.

Chris Johns is a student at Spokane Community College in Spokane, Washington, and with the help of a few other members of their technology club Chris plans to use his HackRF One to start an amateur digital TV station. It's an interesting proposition, and we thank you for trying it out, Chris. Good luck!

Thanks to everyone that sent us a request. If you didn’t send us a request, why not? It never hurts to ask. We look forward to seeing what you come up with next!

Discovering the Bluetooth UAP

During an interview the other day I was asked to describe how we determine the UAP of a Bluetooth address with Ubertooth. A few minutes after the interview I realized that I oversimplified and got one detail wrong: I mentioned whitening when I should have talked about the HEC and CRC. Considering that only a few people in the world have intimate knowledge of our method, I thought it would be a good idea to describe it more thoroughly and correctly for posterity. It’s complicated, and I don’t think we’ve ever attempted to fully describe it anywhere but in the convoluted source code of libbtbb.

I’m writing about classic Bluetooth, by the way, not Bluetooth Low Energy (LE) also known as Bluetooth Smart. In general, these sorts of things are easier with LE, so they do not require such long-winded explanations.

The Upper Address Part (UAP) is a particular 8 bit section of a Bluetooth Device Address (BD_ADDR). In order to fully decode Bluetooth packets, determine a Bluetooth hopping sequence, or do anything else interesting with Bluetooth, we need to know the UAP in addition to the Lower Address Part (LAP) of the piconet’s master device.


The master’s 24 bit LAP is easy to discover using a tool like Ubertooth that can demodulate Bluetooth packets. Every Bluetooth packet includes the master’s LAP as a part of the sync word at the beginning of the packet. It is transmitted in the clear, so we only have to capture and demodulate one packet in order to learn the LAP.

The UAP is harder to determine, but there are multiple methods available to us. The simplest method is brute force search. As Joshua Wright showed in Hacking Exposed Wireless, Second Edition, it is possible to try connecting to a target’s BD_ADDR over and over, guessing a new UAP each time. Because the Non-significant Address Part (NAP) is ignored during the initial connection process, it doesn’t matter what value we use; we only need the correct LAP and UAP. Since the UAP is 8 bits, there are only 256 possible values to try, and a correct match can typically be found quite quickly by prioritizing common UAPs, possible because the UAP is part of the Organizationally Unique Identifier (OUI) assigned to manufacturers (and there is a fairly small number of companies that make the majority of Bluetooth devices). Common UOIs can be identified thanks to the BNAP BNAP project.

Brute force is an excellent method to have in our toolbox, but it has some drawbacks. First, it is an active attack that can influence the behavior of the target devices and that can be detected by a monitoring system. Second, it only works if the master device is in a connectable state. Many devices do not enter the connectable state when they already have an active connection. Annoyingly, many devices are connectable for only brief periods of time (one out of every five seconds, for example), slowing down a brute force search.

The Ubertooth project aims to provide the best possible tools for passive monitoring of Bluetooth systems, so we implement a method of UAP discovery that does not require active transmission.

We think of the problem as being a search for the correct UAP out of a search space that is 8 bits in size (having 256 candidates). We do not have any method to observe the UAP directly, so we instead perform a series of techniques that reduce the search space by a process of elimination until only one possible UAP remains.

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.

Apart from the ID packet type which is transmitted frequently during inquiry (searching for devices) and paging (connecting), every Bluetooth packet contains a header with HEC. This makes it possible for us to perform this technique frequently for a busy piconet even though we are monitoring only one out of 79 channels.

This may sound like an easy victory, but it is complicated by one significant problem: whitening. 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.

Up to this point, this method was described in BlueSniff: Eve meets Alice and Bluetooth.

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.

The next method we use to validate CLK1-6 is to perform a series of sanity checks on the packet format. The unwhitened packet header includes a four bit packet type field. If, for example, the packet type field is 5, then we know that it is an HV1 packet. HV1 packets do not have CRCs, but they have a payload encoded with a 1/3 rate Forward Error Correction (FEC) method implemented by repeating every bit three times in a row. Since different packet types use different FEC methods, we can perform a sanity check that verifies that every bit is repeated three times for the expected packet length (with some allowance for bit errors). If the FEC check fails, then we can be pretty sure we have the wrong CLK1-6 value.

UAP retrieval

Up to this point, this method was described in Building an All-Channel Bluetooth Monitor.

Unfortunately, CRC and sanity checks are not as useful as you might think. Originally we thought that we could simply look for correct CRCs, but they turned out to be rare. Then we thought that we could use a process of elimination where incorrect CRCs or sanity check failures would allow us to remove large numbers of candidate CLK1-6 values, but those cases also turned out to be less frequent than we thought.

The main reason we are often unable to eliminate a candidate CLK1-6 value is that Bluetooth has more than sixteen packet types, so the 4 bit packet type field in the header is overloaded. Here’s an example:

For a trial CLK1-6 value, the packet type field is decoded as 10. This could indicate that the packet type is DM3, a data packet carrying 2 to 123 data bytes and a CRC, or it could indicate that the packet type is 2-DH3, an Enhanced Data Rate (EDR) packet that uses a modulation for the payload that cannot be demodulated by Ubertooth One. (We can demodulate the packet header but not the payload.)

Without prior knowledge of the state of the piconet, we don’t know which of the two packet types is present. We assume it is a DM3 packet and check for a CRC. If we get a CRC match then we win, but this is rare. More often the CRC check fails. This means one of two things: Either the CLK1-6 value is wrong, or the packet is actually a 2-DH3 packet that we can’t verify. Since we can’t verify one of the possible reasons for CRC failure, we can’t eliminate that CLK1-6 value from our list of candidates.

Some of our CRC and sanity checks have a positive result indicating a correct CLK1-6. Some of them have a negative result indicating that the CLK1-6 value can be eliminated. However, the majority of our checks have an inconclusive result. This means that the process of elimination is rarely successful with just one packet.

Fortunately Bluetooth piconets tend to transmit packets fairly often, so we can continue the process of elimination across multiple received packets. Once we have the first packet, we can usually reduce the 64 CLK1-6 values to 50 to 60 candidates. With each subsequent packet, we can usually eliminate a few more candidates, but it is tricky.

The trickiness has to do with inter-packet timing. All packets are transmitted in time slots dictated by the master’s clock. We know how often the clock increments, and we have guesses as to the lower 6 bits of the clock. When we receive a subsequent packet, we can measure the time interval from one packet to the next and determine how many time slots have elapsed. This tells us how much to increment our original guesses when testing the new packet.

This would be a fairly reliable method if it were possible to have two clocks perfectly agree with each other. The crystal on Ubertooth One meets the requirements of the Bluetooth specification, so it is just as good as any Bluetooth device (with a frequency stability of 20 ppm). However, we don’t know how much faster or slower the target master’s clock is compared with the clock on the Ubertooth. It might be as much as 40 ppm different. Even if we had the best clock in the universe on Ubertooth, the target master’s clock will still drift by up to 20 ppm (assuming it is operating within spec).

Because of clock drift, we sometimes eliminate a candidate CLK1-6 value that might be correct simply because we counted the wrong number of time slots between packets. Additionally, bit errors in packets may cause us to incorrectly eliminate a candidate (e.g. if the bit error caused a CRC failure on a packet type without an overloaded packet type field). These things happen, and that’s why UAP discovery sometimes fails with zero candidates remaining. In these cases we simply start the process over as new packets arrive, and we usually get a correct result before having to restart very many times.

A nice enhancement to the code would be consideration of the maximum possible clock drift when computing time slot intervals. If we considered three intervals instead of one, for example, we might avoid a lot of cases where we improperly eliminate the correct CLK1-6 value. Additionally, we could benefit from keeping a running estimate of the master’s clock drift after we have determined the UAP.

A problem people sometimes have with Ubertooth is that the correct UAP is determined but is subsequently lost. This happens because a packet is received that doesn’t agree with the previously determined UAP, probably because of bit errors but possibly due to clock drift. Since we have an all-or-nothing approach to determining the UAP, a single disagreement can result in losing the correct value. Another nice enhancement would be maintaining a confidence value for the current UAP (or perhaps for multiple candidates). If a UAP has proven correct for 1000 packets, it would be nice not to throw it out when one packet disagrees. This would complicate some already convoluted code, but it is definitely worth trying.

Overall, we have a very effective method of determining the master’s UAP through passive monitoring. It is complicated, but it is only a small part of the even more complicated process of determining a piconet’s frequency hopping pattern and hopping along.

Ubertooth Release 2014-02-R2

After a very long break, we are pleased to announce a new release of Ubertooth and libbtbb code. Release notes are given below but for those short on time, the summary is: a major update with complete rewrites of the libbtbb API, greatly improved BTLE support and a migration to GitHub. You can find the release here.

Release Notes

The Ubertooth host utilities in this release require libbtbb-2014-02-R2 or greater.

The release archive is ubertooth-2014-02-R2.tar.xz, it contains binary firmware images and PCB layouts as well as the project source code. The source code links do not include the binary files.

These are just the highlights, for a complete list of changes since the previous release, see the git commit log.

  • Bluetooth Smart (Low Energy) Support

    • Promiscuous and follow modes
    • Pcap format packet logging
    • Pairing / encryption support when paired with crackle
    • Credit for BLE features goes to Mike Ryan
  • Unified host tool for monitoring Basic Rate

    • ubertooth-rx replaces -lap, -uap, -hop tools
    • Once UAP is discovered, ubertooth-rx automatically tries to find clock values and begin hopping
    • Thanks to Will Code for working on this
  • Survey tool - ubertooth-scan

    • Combining both Ubertooth and a standard Bluetooth dongle
    • Ubertooth scans for non-discoverable master devices
    • Dongle probes devices for piconet information and features
  • Cmake now used for the build system

    • Improves support for non-Linux operating systems
    • More sensible handling of dependencies
    • New build instructions
  • Packaging (Experimental)

    • Early stage support for packaging systems
    • libbtbb in Homebrew repository, Ubertooth coming soon
    • MacPorts availability is under test
    • Release already available in Pentoo
  • GitHub migration

    • libbtbb, Ubertooth and gr-bluetooth all hosted on GitHub
    • Allows for more open development and collaboration model
    • Already seeing an increase in issue reporting and pull requests

Speeding up CRC calculations for Bluetooth Low Energy

Over the past few days Mike Ryan has been working hard to cram as much of the Bluetooth Low Energy (BTLE) functionality as possible in to the Ubertooth firmware. In doing so he plans to relieve the host system of the work involved in finding and processing packets. In time this will allow Ubertooth to monitor and inject packets in to BTLE connections while running from a very low powered host, or possibly without a host system at all.

This has involved some excellent work using the CC2400 chip to automatically detect BTLE packets, a task which it is unfortunately unable to achieve for basic rate Bluetooth. Once we know where a packet starts we are able to handle the packet data as a set of bytes rather than needing to break the data up in to bits before running through the whitening and CRC algorithms.

While Mike worked on the whitening algorithm, he set the CRC as an open challenge, which I gladly took up. I thought that it may make an interesting post to explain how CRC algorithms are implemented and show how to trade off time for memory, or time for space complexity for the computational theorists among us, by using a look up table (LUT). This may be common knowledge to many people and there are automated tools to achieve it, but I wanted to work it out by hand.

This part is, at least in part, for my own reference when I look at the code in a year’s time and ask “who did that? And how o we know it’s correct?”

Linear Feedback Shift Registers

Linear Feedback Sift Registers (LFSRs) are often used for CRC checks, forward error correction or to generate pseudo-random data. They are computationally cheap and simple to implement in hardware if required, so they are perfect for low cost networking chips. Bluetooth uses them to implement data whitening, header error checks, CRCs and forward error correction on packet data.

The LFSR that implements the CRC on BTLE packets looks something like this:

LFSR Light

The LFSR for CRC on BTLE packets as drawn by me. See Vol 6, part B, Section 3.2 of the Bluetooth specification for a better, but non-free version of the diagram. For simplicity we can imagine the LFSR as parts, a shift register and the feedback element, using XOR. Each incoming bit of packet data is XOR’d with the right-most bit of the register, for consistency we’ll assume that the bits are numbered 0-23 from left to right. Bit 23 is XOR’d with the incoming data bit and becomes next_bit. The register is shifted one bit to the right and next_bit is added to the end, becoming bit 0. This is a shift register.

Now for the feedback part, each of those arrows feeding in to the top of the register represents a bit in the register that will be XOR’d with next_bit. T\hat is all you need to know about LFSRs for most usese, in fact it should be trivial to implement one using the above information. Here’s our implementation of the above LFSR:

u32 btle_calc_crc(u32 crc_init, u8 *data, int len) {
    u32 state = crc_init;
    u32 lfsr_mask = 0x5a6000; // 010110100110000000000000
    int i, j;

   for (i = 0; i < len; ++i) {
        u8 cur = data[i];
        for (j = 0; j < 8; ++j) {
            int next_bit = (state ^ cur) & 1;
            cur >>= 1;
            state >>= 1;
            if (next_bit) {
                state |= 1 << 23;
                state ^= lfsr_mask;

    return state;

Optimising the LFSR

As you can see, we run through the inner loop for each bit of data, although we only perform the XOR if we next_bit was set. This is a very small optimisation that makes use of the shift operation filling with 0s and the fact that XOR with 0 would have no effect. Logically this process looks a little like this:

CRC Light

The LFSR split in to a shift and a feedback, or XOR, component. The diagram above shows the two stage LFSR, with the second stage containing the different masks to be XOR’d with the register depending on the state of next_bit. This is a two value look up table holding 24 bits od XOR mask.

If we can shift then look up the XOR for one bit, why not more? As long as we shift by the appropriate amount, the XOR result only relies on the incoming data and the state of the register. Even better, there is no feedback in to the lowest byte of the register, so early bits in an incoming byte don’t affect the value of later bits.

Working with Bytes

Taking a byte of input data, we first XOR it with the lowest byte of the register to get next_byte, then we shift the register to the right by a byte and append next_byte. This takes care of the shift.

To finish off we need to apply the eight XOR masks based on the content of next_byte. As the register is shifted for each bit, the masks are XOR’d together with each successive mask shifted by one bit, this is shown in the diagram below.


The final mask is produced by XORing the mask for each bit of next_byte.

The derived mask is specific to the next_byte value of 01101101, so we are able to store it in a table and retrieve it for future use. If we do this for all 256 values of next_byte we can build a full look up table, and use it to calculate the CRC.

The following code implements the CRC using a LUT:

u32 crcgen_lut(u32 crc_init, char *payload, int len)
    u32 state = crc_init;
    int i;
    u8 key;
    for (i = 0; i < len; ++i) {
        key = payload[i] ^ (state & 0xff);
        state = (state >> 8) ^ crc_lut[key];
    return state;

The LUT itself consists of 256 32bit values, so is too large to reproduce here, but it can be found on Github.

While it is possible to write code to that builds the LUT from shifted masks for each value of next_byte, it was easier to use the known good implementation of the CRC algorithm given earlier to provide the final state of the register for all one byte payloads and then XOR it with the pre-mask state, as shown below.


The XOR mask for each key is calculated and then stored in the LUT. After looking at the code, Michael Ossmann pointed out that leaving the key byte blank while building the LUT would yield the same result and avoid a pointless shift operation in the final algorithm. It seems that no matter how nerdy you try to be, someone will out-geek you.

Motivating the Problem

One of the most difficult aspects of talking to people about Bluetooth packet sniffing is what my university supervisor called “motivating the problem”. What he meant by this was trying to convince others that the problem which you were trying to solve was really as hard as you know it to be.

Sniffing Bluetooth is Hard

Over the past five years we have dedicated a lot of time to motivating the problem when we give presentations on Bluetooth security, often resulting in glazed looks from some audience members. This post is intended to go some way towards explaining the challenges facing our project and to encourage anyone interested to participate.

Bluetooth packet sniffing falls foul of the motivation problem because it is so often compared to other wireless protocols that appeared at around the same time, such as 802.11 and Zigbee, which had promiscuous packet sniffing solutions available, using commodity hardware, soon after their release.

Another reason that Bluetooth sniffing is hard to discuss is the set of terms that need to be defined before we can even begin to describe the problems involved. At a minimum, the following are useful to know before entering in to a discussion about Bluetooth packets:

Piconet - A personal area network with one master device connected to potentially many slave devices.

Master device - The device that defines a piconet, often but not always the “smartest” device, e.g. a PC or phone.

Slave device - The device being connected to the master, e.g. a keyboard, mouse or headset.

Bluetooth Device Address - A 48 bit unique device address, usually shown in the same format as IEEE 802 MAC addresses and issued from the same address space. It is common for smartphones to have consecutive Bluetooth device and wifi MAC addresses.

NAP - Non-significant Address Part. The first two bytes of the device address.

UAP - Upper Address Part. The third byte of the device address. Forms the organizationally unique identifier when combined with the NAP.

LAP - Lower Address Part. The lower three bytes of the device address, assigned by the manufacturer.

CLK27 - A 27 bit counter that increments 3200 times per second and wraps in slightly less than 24 hours. Every device maintains an internal clock value, although we are mostly concerned with the master device’s clock. Often referred to as “the clock”.

CLKN - The upper 26 bits of CLK27. This is a clock that ticks 1600 times per second, once per packet “slot”.

AFH Map - Adaptive Frequency Hopping allows Bluetooth connections to avoid using noisy channels, such as channels that overlap nearby wireless networks. The map specifies which channels are available for a given connection.

The feature of Bluetooth that makes packet sniffing so hard is frequency hopping. Originally designed to ensure robust connections, it causes more problems and confusion for packet sniffers than any other feature. The pseudo-random hopping sequence that all devices within a piconet share is determined by the LAP, UAP and CLKN of the master device. To have any chance of extracting useful data from a Bluetooth connection we need to know these three values.

The situation gets even worse for encrypted links. To have any chance of sniffing the pairing process, and using the extracted data to find the pin (see: ), we must know these three values before the target devices begin to communicate.

One solution to this is to begin sniffing all traffic in a target piconet on the assumption that a new device will be paired with it in the future. In many ways it is good that this is not a practical attack vector, however it makes research and investigation in to Bluetooth authentication and encryption a harder task.

Devices that support Bluetooth v2.0+ also support adaptive frequency hopping (AFH), which adds an additional variable to the list that we have to find before we can monitor a connection.

The Ubertooth tools passively monitor each channel in turn to find piconets and build up information on the LAP, UAP, CLKN and AFH map, this behaviour can be seen in the Kismet plugin. Ubertooth-follow is the one exception to this method as it uses a Bluetooth dongle to acquire the values that the Ubertooth needs to follow a hopping pattern.

Hopefully this has provided a crash course in Bluetooth packet sniffing for anyone who wants to get involved or try out the Ubertooth tools. We’re working hard to improve the amount of data that we are able to collect as well as adding features such as packet injection, Bluetooth Low Energy support, integration with external tools such as Wireshark and Kismet and support for more low cost embedded platforms such as ARM (raspberryPi, BeagleBone) and Android.

subscribe to GSG feed