Blog: Hardware Hacking

Introduction to Bluetooth Low Energy

Phil Eveleigh 12 Mar 2020

Bluetooth Low Energy (BLE) is used by almost everyone in our everyday lives, from wireless headphones, to car stereos, computer keyboards and mice, and other everyday items.

Even though this standard is popular there seems a general lack of understanding of how it works and what certain terms mean. I’m going to explore some of the basic concepts and key terms to help demystify this technology.

BLE works over a short range using radio waves, in a central / peripheral configuration. This means that one central device (i.e your phone) will send data to the peripheral devices, (such as your wireless headphones).

To do this, the devices need to connect together. This is achieved by the devices advertising themselves over three different channels which are regularly scanned by the connecting device. There are three main different types of connections within BLE, these are connected, pairing and bonding. These have slightly different meanings:


Connected is an unencrypted one-time connection. This provides a simple connection without any security features.


Pairing is a one-time connection. During the pairing process security features are exchanged including temporary security keys so that the data is secure between the two devices. This however is only a temporary connection so once the Bluetooth is turned off, or gone out of range, the device is free to connect to any other device.


Bonding is a more permanent solution so once the pairing has been complete the devices then store the security keys and use them for all future communication. This means that for every subsequent connection after the initial pairing no keys are being transmitted between the devices.

When looking at BLE there are a few different tools that can be used to enumerate it, the most popular of these are:

  • Hciconfig – To configure Bluetooth interface
  • Hcitool – Used for scanning and discovery
  • Bleah – Can be used to enumerate Bluetooth devices
  • Gatttool – Interacting with the Bluetooth device
  • Bettercap – Interacting with the Bluetooth device
  • Bluepy – The python library for communicating directly with BLE

To start Bluetooth hacking all you need is a USB dongle, or a raspberry pi with a Bluetooth module (model 3 or Zero)

When enumerating a device, there are a few different headings which will often appear:


The handles are the locations in memory where the data is stored.


The characteristic is a UUID which refers to the same location in memory as the handle.


This is the information about what is allowed at each handle location. These are primarily:

  • Read
  • Write
  • Notify
  • Indicate
  • Broadcast


This is the data stored at that memory address location, it can be a message, or piece of code.

To show some of the Bluetooth terms in action, my colleague @tautology0 created a BLE CTF which was first used as a training tool at BSides LDN. The CTF looks at some of the key features of Bluetooth and how to use them.

Let’s get into this…

So after the success of hackgnar BLE challenge that I recently did which can be found here, my colleague told me that he had also created a CTF that was first used as a training tool at Bsides London.

In order to cement some of the BLE hacking knowledge previously learnt, I’m going to do this CTF. If you want to play along, the CTF is available on a sketchy google drive link!

To do the CTF it needs to be written to an SD card and inserted into a pi that has a bluetooth module (so 3 or zero).

One that pi is up and running, connect into your pi running raspbian (or use a USB dongle if you can make it work) and check that the bluetooth module is running.

sudo hciconfig

Once that is confirmed as being up, we can do a scan for all BLE devices

sudo hcitools lescan

There are a few available, but we are interested in the “BSidesLDN CTF”

From this, we now have the MAC address of the device:


Using bleah we can get enumerate the device and see what’s on it.

sudo bleah -b "B8:27:EB:4E:8B:2F" -e

That runs through and we see that the creator of this is trying their hardest to be northern!

So we have a few handles that have data. My understanding is that the flags are “Digit:Code” so I think we already have the second flag


That’s a nice easy win, but where the heck is the first flag?

We can double-check that by doing a read of that 0x000c handle!

Now I’m confident that this is the second flag!

Let’s loop back round and try and find flag 1. Looking at the handles down the side, the values increase by 1, and as they are hex it goes up to 8 then up to f. So there are no gaps on the handles that look to be hiding flag 1.

Parking the first flag for the moment, let’s go and have a look at 3.

As it’s got a write attribute, let’s write some data to it, then see if we can read it back.

gatttool -b b8:27:eb:4e:8b:2f --char-write-req -a 0x000f -n $(echo -n "test" | xxd -ps)

That got written successfully. So if we read that back, we then get the flag!

Moving onto Flag 4, there is a notify characteristic, if we write some data with the –listen flag, this should bring back some data!

However, it did not!

It wrote successfully, but didn’t seem to listen or make any response. Very strange.

Trying to change the type of input:

gatttool -b b8:27:eb:4e:8b:2f --char-write-req -a 0x0012 -n $(echo -n "test" | xxd -ps) --listen

We still don’t get a response.

Reading a little more into notify on BLE, there is what is known as a CCCD which stands for Client Characteristic Configuration Descriptor, to get a notification first we need to set this CCCD to say that we want to get notifications. To do this, we need to write the correct code of 0100 to the CCCD handler, which in this case is 0x0013.

To do this, I headed into the interactive gatttools:

gatttool -I

Then connected to the device:

connect b8:27:eb:4e:8b:2f

Once there, I wrote to the CCCD, with the code of 0100 to say that I wanted notifications.

char-write-req 0x0013 0100

In interactive mode, it doesn’t need the flags, it just has “action” “handler” “data”

Then when writing to 0x0012, we get the answer back!

Using cyberchef to decode this, we get the 4th flag!

With that success, looking at flag 5, it only has the read characteristic. Reading back 0x0016 brings back the known “nowt here”, however this flag has a range of handles, going up to 0x0017, reading this higher range brings back the flag.

gatttool -b b8:27:eb:4e:8b:2f --char-read -a 0x0017|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'


Flag 6 also only has the read characteristic, reading that we get the Owt here reply.

Doing the same as before and reading one up, we get a new clue!

Ok, so let’s read 0x3000

gatttool -b b8:27:eb:4e:8b:2f --char-read -a 0x3000|awk -F':' '{print $2}'|tr -d ' '|xxd -r -p;printf '\n'


That’s flag 6 done!

So now I guess we really have to loop back round and try to find flag 1!

As there is no obvious gap on the device within the handlers, it can’t be stored there. Thinking about how bluetooth works, before a connection is made, the device must advertise itself. This is what we saw on the lescan at the start. But is there anymore data than just the MAC address and name of the device?

It’s possible to intercept the traffic while the scan, just as it would be with network traffic, so either using wireshark or in this case tcpdump.

Running tcpdump with the bluetooth interface:

sudo tcpdump -i bluetooth1 -s 0

We then run another lescan and watch the data flood in!

So looks like we have our first and final flag. This is sneaky but always worth checking what data is being transmitted at every stage, including the scan and connections!

Another decent BLE CTF, which looks at slightly different bits and hid flags in some odd places, helping to both cement knowledge and further learn about the workings of BLE!