Enable Debugging Features in the Android Bluetooth Stack ======================================================== The Android Bluetooth stack has [debugging features](https://chromium.googlesource.com/aosp/platform/system/bt/+/master/doc/network_ports.md) which are disabled in normal builds. To enable them, the Bluetooth stack (*bluetooth.default.so*) 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 *bluetooth.default.so* 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/S20__ with __Android Pie (10)__ (Patchlevel March 2020). In `adbcore.py`, 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 *bluetooth.default.so*. The delay per command is quite long, but overall throughput is okay, i.e., stackdumps can be received. However, it runs out of the box, also if your *Android 6/7* setup does not work. Bypass: Broadcom Read_RAM Fix ----------------------------- On the *Samsung Galaxy S10/S20*, the newest `.hcd` patches remove the commands that allow reading, writing, and launching RAM after applying these patches. However, this can easily be fixed by applying an older patch state. Since the Bluetooth firmware is in ROM, the patches are only temporary breakpoints (up to 256 on the S10e) that are applied via the `/vendor/firmware/*.hcd` files. These files are not signed. So, to get *InternalBlue* working again, simply use some older `.hcd` files. One set of files that still works is available in [`samsung_s10e_2019-06-04_vendor_firmware.zip`](../android/samsung_s10e_2019-06-04_vendor_firmware.zip). You need to remount the according partition to replace the files with `mount -o remount,rw /vendor`. As the Samsung Galaxy S10e, S10+, S10, Note 10, and S20 all have the same firmware, this should work on all of them. We also extracted the file `/vendor/firmware/bcm4361B0_semco.hcd` from a *Samsung Galaxy S8*, which should be compatible with the *S8+* and *Note 8* as well. The Samsung patch level is June 2020 and includes the RNG patch for CVE-2020-6616. We customized it to no longer block the HCI commands read RAM and write RAM to be able to debug the RNG during runtime again. This `.hcd` file is available in [`samsung_s8_2020-06_vendor_firmware_rng-patched_rw-ram-unpatched.zip`](../android/samsung_s8_2020-06_vendor_firmware_rng-patched_rw-ram-unpatched.zip). New dirty hack that should work for the *Samsung Galaxy Note 20 5G* from which this file was extracted but also on the *S10/10e/10+/20/* and *Note 20*: Use the file [`samsung_s10e_note20-5g_2021-01-21_bcm4375B1_semco.hcd`](../android/samsung_s10e_note20-5g_2021-01-21_bcm4375B1_semco.hcd). Your new `Write_RAM` handler must be set in `hci.py`: ``` VSC_Write_RAM = 0xC6F ``` Then, re-enalbe all blocked commands by executing: ``` > writeasm 0x17A210 b.w 0x5E980 ``` Just accept this magic, writeup will follow :) Prebuilt Library Status ----------------------- Folder | Tag | HCI forwarding | H4 Broadcom Diagnostics | Notes ------ | --- | -------------- | ----------------------- | ----- \- | Android 8+9+10 | yes | no | Serial and BT Snoop forwarding with `nc` (in `busybox` app), tested on rooted __Samsung Galaxy S10e__ [android5_1_1](../android/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) | 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/android/7_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/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](../android/lineageos14_1_hammerhead) | cm-14.1 | yes | __yes__ | Recommended for __Nexus 5__ [lineageos14_1_zerofltexx](../android/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 lineage-14.1-20170103-UNOFFICIAL-zerofltexx.zip [lineageos14_1_zeroltexx](../android/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 Installation ------------ After the build process is done, the `bluetooth.default.so` shared library can be found in `/home/ubuntu/mnt/android/out/target/product/hammerhead/system/lib/hw/bluetooth.default.so` 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 bluetooth.default.so /sdcard/bluetooth.default.so adb shell 'su -c "mount -o remount,rw /system"' adb shell 'su -c "cp /sdcard/bluetooth.default.so /system/lib/hw/bluetooth.default.so"' adb shell 'su -c "chmod 644 /system/lib/hw/bluetooth.default.so"' adb shell 'su -c "chown root:root /system/lib/hw/bluetooth.default.so"' 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](https://developer.sonymobile.com/open-devices/aosp-build-instructions/how-to-build-aosp-marshmallow-for-unlocked-xperia-devices/). 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](https://aws.amazon.com/marketplace/pp/B01AOKYCZY) 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 http://commondatastorage.googleapis.com/git-repo-downloads/repo > ~/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 https://android.googlesource.com/platform/manifest -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/envsetup.sh 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 `bluetooth.default.so` module which still does not contain Bluetooth network debugging features. You can check if the Bluetooth network debugging features were actually enabled as follows: grep bt_snoop_net bluetooth.default.so grep hci_inject bluetooth.default.so 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/envsetup.sh 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/envsetup.sh lunch aosp_angler-eng cd system/bt/ git apply enable_hci_inject.diff CFLAGS='-DBT_NET_DEBUG=TRUE' mma -j4 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/bluetooth.default.so /system/lib/hw/bluetooth.default.so"' adb shell 'su -c "cp /sdcard/bluetooth.default.so.64 /system/lib64/hw/bluetooth.default.so"' adb shell 'su -c "chmod 644 /system/lib/hw/bluetooth.default.so"' adb shell 'su -c "chmod 644 /system/lib64/hw/bluetooth.default.so"' adb shell 'su -c "chown root:root /system/lib/hw/bluetooth.default.so"' adb shell 'su -c "chown root:root /system/lib64/hw/bluetooth.default.so"' 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 https://wiki.lineageos.org/devices/hammerhead/build 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](https://stackoverflow.com/questions/49301627/android-7-1-2-armv7): export LC_ALL=C