Hacking Bluetooth To Learn More About Boondock Battery Life
Capturing Bluetooth Data
Where to Intercept Data in the BluetoothLE Software Stack
Bluetooth is a very complicated protocol. A few years ago I wrote "What is Bluetooth 5? Learn about the Bit Paths Behind the New BLE Standard" for AllAboutCircuits.com. That article looked at the bit manipulations performed on raw data in the Link Layer just before it hits the airwaves in the Physical Layer. There are convolutional encoders that provide forward error correction, data whitening filters, and oh, the standard allows the data to jump over a variety of channels. All of this makes intercepting and then interpreting over-the-air packets relatively cumbersome. While you can use Software Defined Radios to capture and channelize RF data and convert it into packets, it is much easier to capture data at the Host Controller Interface (HCI) level in the Bluetooth Software Stack, and that's the method I chose.
Use an Android Phone
Android phones can capture data packets at the Host Controller Interface level and write it to internal memory for later analysis. Start by putting your device into developer mode.
Go into Settings, find Build Number and tap it repeatedly until the phone switches to developer mode.
Next, in settings, find Developer Options and enable the Enable Bluetooth HCI Snoop Log option. Then power cycle Bluetooth to turn snooping on -- you'll need Bluetooth to be active for the next part to work.
Connect to the Device and Systematicaly Press Every Button
Open the app you're interested in reverse engineering and connect to your Bluetooth enabled device. Then systematically press every button in the app. If the app collects data, let it collect data for several minutes. If possible, carefully control the inputs so you'll know what the values should be. Finally disconnect the bluetooth device and close the app.
Turn off Developer Mode and Export the Logfile
Go back into Settings and disable Enable HCI Snoop Log. Then open up the phone calling app and type #9900# or *#9900# to enter a hidden screen. Click Run dumpstate/logcat and once complete, click Copy to sdcard(include CP Ramdump).
Find the Logfile and Copy it to Your Computer
Open up your Files app, navigate to Internal Storage > log > bluetooth. Look for btsnoop_hci_yyyymmddhhmm.cfa Once you find it, transfer that file to your computer
Open the logfile in WireShark
You're going to get a lot of data, not all of which is relevant. To filter just the relevant conversation, and only when there is data, use the following filter in Wireshark:
bluetooth.addr == 98:da:b0:08:aa:88 && btatt.value >= 0
Then, in WireShark, go to File > Export Packet Dissections > As CSV
Then you can open the .csv file and you'll have all the packets.
At this point, the data analysis is part art and part science. Start by looking for repeating bytes. In this case, 0xAA shows up at the beginning of every data frame. So I split all the data everytime I saw 0xAA, and then sorted by the next packet number.
|
||||||||||||||||||||
00 | 01 | 02 | 03 | 04 | 05 | 06 | 07 | 08 | 09 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 |
aa | 04 | 0c | 99 | c5 | 00 | 00 | da | 03 | 00 | 00 | 7e | 13 | 00 | 00 | 92 | |||||
aa | 04 | 0c | 51 | c6 | 00 | 00 | 21 | 03 | 00 | 00 | e5 | 0f | 00 | 00 | 81 | |||||
aa | 04 | 0c | 82 | c4 | 00 | 00 | dc | 03 | 00 | 00 | 6d | 13 | 00 | 00 | 0c | |||||
aa | 04 | 0c | ee | c7 | 00 | 00 | f7 | 02 | 00 | 00 | 2e | 0f | 00 | 00 | 8e | |||||
aa | 05 | 07 | 05 | d3 | 07 | 00 | 01 | 52 | 01 | c7 | ||||||||||
aa | 05 | 07 | 09 | aa | 09 | 00 | 01 | 52 | 01 | 7a | ||||||||||
aa | 05 | 07 | 8e | c3 | 07 | 00 | 01 | 52 | 01 | 95 | ||||||||||
aa | 05 | 07 | c2 | 48 | 0a | 00 | 01 | 52 | 01 | ea | ||||||||||
aa | 06 | 06 | 7a | 0b | 7b | 0b | 00 | 00 | c2 | |||||||||||
aa | 06 | 06 | 78 | 0b | 76 | 0b | 00 | 00 | 04 | |||||||||||
aa | 06 | 06 | 72 | 0b | 72 | 0b | 00 | 00 | f7 | |||||||||||
aa | 06 | 06 | 79 | 0b | 7a | 0b | 00 | 00 | 96 | |||||||||||
aa | 06 | 06 | 7f | 0b | 7e | 0b | 00 | 00 | 86 | |||||||||||
aa | 06 | 06 | 76 | 0b | 76 | 0b | 00 | 00 | a7 | |||||||||||
aa | 06 | 06 | 74 | 0b | 73 | 0b | 00 | 00 | a2 | |||||||||||
aa | 06 | 06 | 76 | 0b | 78 | 0b | 00 | 00 | fd | |||||||||||
aa | 06 | 06 | 7f | 0b | 7f | 0b | 00 | 00 | 32 | |||||||||||
aa | 06 | 06 | 6d | 0b | 6e | 0b | 00 | 00 | e5 | |||||||||||
aa | 06 | 06 | 7c | 0b | 7b | 0b | 00 | 00 | 23 | |||||||||||
aa | 07 | 04 | d1 | 13 | 4d | 00 | 12 | |||||||||||||
aa | 07 | 04 | bd | 13 | 63 | 00 | 1b | |||||||||||||
aa | 07 | 04 | cf | 13 | 6a | 00 | 9e | |||||||||||||
aa | 07 | 04 | d4 | 13 | 50 | 00 | 78 | |||||||||||||
aa | 07 | 04 | b1 | 13 | 68 | 00 | d3 | |||||||||||||
aa | 07 | 04 | e8 | 13 | 4a | 00 | 1b | |||||||||||||
aa | 07 | 04 | a6 | 13 | 5d | 00 | 39 | |||||||||||||
aa | 07 | 04 | ba | 13 | 51 | 00 | c1 | |||||||||||||
aa | 07 | 04 | fe | 13 | 4b | 00 | 14 | |||||||||||||
aa | 07 | 04 | a7 | 13 | 71 | 00 | 06 | |||||||||||||
aa | 07 | 04 | ce | 13 | 52 | 00 | 16 | |||||||||||||
aa | 08 | 11 | 02 | c4 | d5 | 00 | 00 | 11 | 2a | 00 | 00 | 10 | 0e | 00 | 00 | 28 | 00 | 00 | 00 | 31 |
aa | 08 | 11 | 02 | c4 | d5 | 00 | 00 | 11 | 2a | 00 | 00 | 10 | 0e | 00 | 00 | 29 | 00 | 00 | 00 | 85 |
That's when things started making a bit more sense. Here's the basic structure.
Byte |
Values |
Notes |
01 | 0xAA | Start of frame |
02 | 0x04, 0x05, 0x06, 0x07, 0x08 | Data type (e.g. 0x07 is Voltage and Current, 0x06 appears to be DP and DN voltage, 0x04 might be Impedance, etc.) |
03 | 0x04, 0x06, 0x07, 0x0C, 0x11, 0xC4 | Data length |
04/05 | 0xXXYY | Little-Endian Values |
etc. | 0xZZ | The last byte in each data packet isn't clear. It doesn't appear to be a CRC. It might be a nib that adds a degree of precision to the previous doubles, making them 24 bit-depth. Unknown. |
That's the hard part. Now to determine which data types the other parts are, you've just got to match screen values to little-endian doible values. That's been left as an exercise for the reader.
Happy Hacking everyone!