Skip to content
Branch: master
Find file Copy path
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
254 lines (189 sloc) 11.8 KB

Enable Debugging Features in the Android Bluetooth Stack

The Android Bluetooth stack has debugging features which are disabled in normal builds. To enable them, the Bluetooth stack ( has to be build with debugging preprocessor defines.

Another issue is that the Android Bluetooth stack does not support Broadcom vendor specific H4 messages by default. Patching a few checks inside the Android's Bluetooth stack soruce code enables forwarding these from and to Android. Broadcom H4 messages enable useful features such as monitoring LMP and LCP messages.

This tutorial shows how to compile and install such a debugging Bluetooth Stack. Inside this directory are also several precompiled Bluetooth Stacks which have been created according to the tutorial below. You can skip the build if you happen to have a device for which a precompiled exists.

NEW: Serial Forwarding

With Android Oreo (8), significant parts of the network debug interface were removed from the source code. Reintroducing these features would be ABI-breaking.

We introduced an experimental serial forwarding. If the connection to a patched Bluetooth stack fails on Android, InternalBlue tries to setup sockets with shell scripting. The only requirement is a rooted smartphone. This hack even works on a recent Samsung Galaxy S10e with Android Pie (9) (Patchlevel June 2019).

In, we have a fallback that executes _setupSerialSu. This starts the following processes:

tail -f -n +0 /data/log/bt/btsnoop_hci.log | nc -l -p 8872
nc -l -p 8873 >/sdcard/internalblue_input.bin
tail -f /sdcard/internalblue_input.bin >>/dev/ttySAC1

To run netcat, you need to install the busybox app. Depending on your Android version, the paths for *btsnoop_hci.log and /dev/tty* might differ. Execute lsof | grep bluetooth to get hints on the serial device used for Bluetooth.

Note that this solution is much slower than patching The delay per command is quite long, but overall throughput is okay, i.e., stackdumps can be received.

Prebuilt Library Status

Folder Tag HCI forwarding H4 Broadcom Diagnostics Notes
none Android 8+9 yes no Serial and BT Snoop forwarding with nc (in busybox app), tested on rooted Samsung Galaxy S10e
android5_1_1 android-5.1.1_r3 rx only no Tested on Nexus 5 - HCI sniffing only!
android6_0_1 android-6.0.1_r81 yes yes Recommended for Nexus 5 (android-6.0.1_r77), also works on Nexus 6P, seems like the version tag can differ a bit.
android7_1_2 android-7.1.2_r28 yes yes Recommended for Nexus 6P, but it might run on Nexus 5X, Nexus Player, Pixel C.
android8_1_0 android-8.1.0_r1 yes no Tested on Nexus 6P, but it might run on Pixel 2 XL, Pixel 2, Pixel XL, Pixel, Pixel C, Nexus 5X.
lineageos14_1_hammerhead cm-14.1 yes yes Recommended for Nexus 5
lineageos14_1_zerofltexx cm-14.1 yes yes Recommended for Samsung Galaxy S6. Works on official Lineage OS build from January 2019, also verified on
lineageos14_1_zeroltexx cm-14.1 yes yes Recommended for Samsung Galaxy S6 edge

If Broadcom H4 diagnostic support is included, the according diff is located inside the folder. You can apply it inside the /bt folder with:

git apply android_receive_diagnostics.diff


After the build process is done, the shared library can be found in /home/ubuntu/mnt/android/out/target/product/hammerhead/system/lib/hw/ and pushed onto the smartphone via ADB. To overwrite the existing library on the Android system partition it must first be remounted in order to make it writable. It is also important to verify that the new library is actually set to be executable, otherwise Bluetooth will not work on the device.

adb push /sdcard/
adb shell 'su -c "mount -o remount,rw /system"'
adb shell 'su -c "cp /sdcard/ /system/lib/hw/"'
adb shell 'su -c "chmod 644 /system/lib/hw/"'
adb shell 'su -c "chown root:root /system/lib/hw/"'

Finally, the HCI snoop log feature has to be enabled in the developer settings of the Android phone.

On Android 7 / Nexus 6P, you might need to install the busybox app, open the app to actually install busybox and then run the following second step instead:

adb shell 'su -c "busybox mount -o remount,rw /system"'

Build (AOSP)

In order to build a custom Bluetooth stack with enabled debugging features for Android it is necessary to setup a build environment for the AOSP. In recent versions of Android the Bluetooth stack can also be built as standalone project. However, this guide explains the build process for the Nexus 5 running Android 6.0.1 which requires the complete AOSP build setup. The build process of an Android ROM needs around 100 GB of storage for the source tree and the compiled outputs.

Most steps of this tutorial are taken from an online tutorial from Sony. For the most recent Android version (at the time this tutorial was written the most recent Android version is 8.1) there exist preconfigured AWS instances which come with the latest AOSP repository and all necessary tools installed. However, for a significantly older version, it is easier to setup a fresh instance with an older Ubuntu version to get all necessary tools (Java, gcc, etc.) in their correct versions. The instance should have high network throughput, fast storage (dedicated SSD) and a decent amount of virtual CPU cores for the build process. A reasonable option would be the i3.large instance which comes with a dedicated NVME SSD.

After connecting to the instance via SSH the necessary tools have to be installed as shown in the listing below. The listing also shows how to format and mount the NCME drive that comes with the AWS instance. Now the AOSP repository of the corresponding Android version can be downloaded onto the SSD with the help of the repo tool.

# Install all necessary tools for the build
sudo dpkg --add-architecture i386
sudo apt update && sudo apt upgrade
sudo apt install openjdk-7-jdk gcc-multilib g++ bison git zip
sudo apt install g++-multilib gperf libxml2-utils make zlib1g-dev:i386
mkdir ~/bin
curl > ~/bin/repo
chmod a+x ~/bin/repo
export PATH=~/bin:$PATH

# Prepare the SSD
sudo mkfs.ext4 /dev/nvme0n1 
sudo mount /dev/nvme0n1 mnt
chown -R ubuntu:ubuntu mnt/
mkdir mnt/android
cd mnt/android/

# Clone the Android repository
repo init -u -b android-6.0.1_r81
repo sync

Then it is possible to build the Bluetooth stack with all necessary dependencies. The lunch script can also be invoked without any arguments to select the build target from an interactive list. The debugging features of the Bluetooth stack are enabled by setting the preprocessor define BT_NET_DEBUG=TRUE. The build script is called mma and takes an optional argument -j to specify the number of CPU cores to use in parallel. It should be chosen according to the selected AWS instance. The following command sequence builds just the Bluetooth stack of the AOSP:

source build/
lunch aosp_hammerhead-userdebug
cd system/bt/
git apply android_receive_diagnostics.diff  # if available in the corresponding InternalBlue folder
bdroid_CFLAGS='-DBT_NET_DEBUG=TRUE' mma -j4

Debugging an AOSP Build

Similar to the Lineage OS Build (see below), starting at Android 7 you might get a Flex error that can be solved as follows:

export LC_ALL=C

Due to various reasons it might happen that you successfully build a new module which still does not contain Bluetooth network debugging features. You can check if the Bluetooth network debugging features were acutally enabled as follows:

grep bt_snoop_net
grep hci_inject

If any of these does not return a binary match, enabling these debugging features failed for sure. From Android 6.0.1 to Android 7.2.1 flag names changed, in this case you can try compiling the module as follows:

bluetooth_CFLAGS='-DBT_NET_DEBUG=TRUE' mma -j4

Android 5 Issues

Android 5 does not yet know the global flag to enable network logging. Moreover files are located in different paths. Java needs to be downgraded to java-7-openjdk, i.e. via update-alternatives --config java. Afterwards, compilation works as follows:

source build/
lunch aosp_hammerhead-userdebug
cd external/bluetooth/bluedroid/
sed -i 's/BtSnoopLogOutput=false/BtSnoopLogOutput=true/' conf/bt_stack.conf
mma -j4

However, HCI injection is not yet included in this old driver version. Hence we only support HCI sniffing and no Broadcom diagnostics.

Android 8 Issues

Android 8 did major changes to their modules. Changing compiler flags will enable HCI sniffing but not HCI injection. The code for HCI injection is still there but simply no longer addressed in the according HCI layer implementation. To get injection working you already need to apply a patch:

source build/
lunch aosp_angler-eng
cd system/bt/
git apply enable_hci_inject.diff

For installation, copy both, the 32 and 64 bit versions.

adb shell 'su -c "mount -o remount,rw /system"'
adb shell 'su -c "cp /sdcard/ /system/lib/hw/"'
adb shell 'su -c "cp /sdcard/ /system/lib64/hw/"'
adb shell 'su -c "chmod 644 /system/lib/hw/"'
adb shell 'su -c "chmod 644 /system/lib64/hw/"'
adb shell 'su -c "chown root:root /system/lib/hw/"'
adb shell 'su -c "chown root:root /system/lib64/hw/"'

Broadcom H4 support would break a couple of things. First of all, Android 8 defines all valid H4 messages (standard HCI only) inside the Bluetooth interface. Any change to the Bluetooth interface is ABI-breaking. The Bluetooth interface rejects Broadcom H4 responses from the chip, so enforcing diagnostic capabilities by directly writing to the chip's serial console causes the driver to restart. If you need to use diagnostic features, switch back to Android 7.

Build (Lineage OS)

To compile the Bluetooth debug library for LineageOS 14.1, the steps are slightly different than for AOSP:

Follow the build setup steps according to until the Start the build section. Then do:

cd system/bt/
git apply android_receive_diagnostics.diff  # probably the same for any LineageOS 14.1 device
bluetooth_CFLAGS='-DBT_NET_DEBUG=TRUE' mma -j4

Flex crashes on Ubuntu 18.04 - workaround:

export LC_ALL=C

Empty Device List

If adb devices returns something, but InternalBlue cannot find your device, you might try to comment out the following lines in pwnlib/adb/

    #for field in fields[2:]:
    #    k,v = field.split(':', 1)
    #    kwargs[k] = v
You can’t perform that action at this time.