Btproxy – Man in the Middle analysis tool for Bluetooth. – GitHub

Bluetooth Proxy tool
Tested Devices
Pebble Steel smart watch
Moto 360 smart watch
OBDLink OBD-II Bluetooth Dongle
Withings Smart Baby Monitor
If you have tried anything else, please let me know at conorpp (at) vt (dot) edu.
Need at least 1 Bluetooth card (either USB or internal).
Need to be running Linux or another *nix.
BlueZ 4
For a debian system, run
sudo apt-get install bluez bluez-tools libbluetooth-dev python-dev
sudo python install
To run a simple MiTM or proxy on two devices, run
Run btproxy to get a list of command arguments.
# This will connect to the slave 40:14:33:66:CC:FF device and
# wait for a connection from the master F1:64:F3:31:67:88 device
btproxy F1:64:F3:31:67:88 40:14:33:66:CC:FF
Where the master is typically the phone and the slave mac
address is typically the other peripherial device (smart watch, headphones, keyboard, obd2 dongle, etc).
The master is the device the sends the connection request and the slave is
the device listening for something to connect to it.
After the proxy connects to the slave device and the master connects to the proxy device,
you will be able to see traffic and modify it.
How to find the BT MAC Address?
Well, you can look it up in the settings usually for a phone. The most
robost way is to put the device in advertising mode and scan for it.
There are two ways to scan for devices: scanning and inquiring.
hcitool can be used to do this:
To get a list of services on a device:
sdptool records
Some devices may restrict connecting based on the name, class, or address of another bluetooth device.
So the program will lookup those three properties of the target devices to be proxied,
and then clone them onto the proxying adapter(s).
Then it will first try connecting to the slave device from the
cloned master adaptor. It will make a socket for each service
hosted by the slave and relay traffic for each one independently.
After the slave is connected, the cloned slave adaptor will be set
to be listening for a connection from the master. At this point, the real master device
should connect to the adaptor. After the master connects, the proxied connection
is complete.
Using only one adapter
This program uses either 1 or 2 Bluetooth adapters. If you use one adapter, then only
the slave device will be cloned. Both devices will be cloned if 2 adapters are used; this might
be necessary for more restrictive Bluetooth devices.
Advanced Usage
Manipulation of the traffic can be handled via python
by passing an inline script. Just implement the master_cb and
slave_cb callback functions. This are called upon receiving
data and the returned data is sent back out to the corresponding device.
def master_cb(req):
Received something from master, about to be sent to slave.
print ‘<< ', repr(req) open('', 'a+b')(req) return req def slave_cb(res): Same as above but it's from slave about to be sent to master print '>> ‘, repr(res)
open(”, ‘a+b’)(res)
return res
Also see the example functions for manipulating Pebble watch traffic in
This code can be edited and reloaded during runtime by entering ‘r’
into the program console. This avoids the pains of reconnecting. Any errors
will be caught and regular transmission will continue.
Improve the file logging of the traffic and make it more interactive for
Indicate which service is which in the output.
Provide control for disconnecting/connecting services.
PCAP file support
How it works
This program starts by killing the bluetoothd process, running it again with
a LD_PRELOAD pointed to a wrapper for the bind system call to block bluetoothd
from binding to L2CAP port 1 (SDP). All SDP traffic goes over L2CAP port 1 so
this makes it easy to MiTM/forward between the two devices and we don’t have to
worry about mimicking the advertising.
The program first scans each device for their name and device class to make
accurate clones. It will append the string ‘_btproxy’ to each name to make them
distinguishable from a user perspective. Alternatively, you can specify the
names to use at the command line.
The program then scans the services of the slave device. It makes a socket
connection to each service and open a listening port for the master device to
connect to. Once the master connects, the Proxy/MiTM is complete and output will be
sent to STDOUT.
Some bluetooth devices have different methods of pairing which
makes this process more complicated. Right now it supports SPP and legacy pin pairing.
This program doesn’t yet have support for Bluetooth Low Energy.
A similiar approach to BLE can be taken.
btproxy or bluetoothd hangs
If you are using bluez 5, you should try uninstalling and installing bluez 4. I’ve had problems with
bluez 5 hanging.
error accessing bluetooth device
Make sure the bluetooth adaptors are plugged in and enabled.
# See the list of all adaptors
hciconfig -a
# Enable
sudo hciconfig hciX up
# if you get this message
Can’t init device hci0: Operation not possible due to RF-kill (132)
# Then try unblocking it with the rfkill command
sudo rfkill unblock all
UserWarning: / is writable by group/others
chmod g-rw, o-x /
Proxying Bluetooth devices for security analysis using btproxy

Proxying Bluetooth devices for security analysis using btproxy

I’ve recently been interested in investigating the security of new technologies. New devices,
especially in the “IoT” realm, use Bluetooth to communicate. I got interested finding a good
way to get insight to Bluetooth connections. I wanted to be able to see traffic in clear text
and modify it actively, similar to many existing tools for internet traffic. However, there
isn’t really any cheap and easy methods for doing so.
I wrote a tool that will leverage 1 or 2 regular Bluetooth adapters to act as a proxy for two other
devices connecting to each other. Proxying the connection allows insight into clear text
traffic and the ability to modify it in real time.
The code currently lives on Github and currently only works on Linux or OS X. It relies on BlueZ.
Install the dependencies:
sudo apt-get install bluez bluez-utils bluez-tools libbluetooth-dev python-dev
Install btproxy:
git clone cd btproxy
sudo python install
To run it, you will need two Bluetooth devices to proxy (Bluetooth low energy doesn’t work yet).
I choose to use my Phone (Nexus 6) and Pebble Steel watch.
So I went ahead and made each device Bluetooth discoverable. For
the Nexus 6 running Android L, this just means opening Bluetooth
in the settings. For the Pebble watch, you just open Bluetooth
in the settings as well.
Now that they are visible, the Proxy can run.
I use hcitool to scan for the devices so I know their Bluetooth MAC addresses.
77:88:99:AA:BB:CC Pebble 9FAA
11:22:33:44:55:66 conorpp’s Nexus 6
Now to run the Bluetooth proxy.
sudo btproxy 11:22:33:44:55:66 77:88:99:AA:BB:CC
Notice I put the phone’s MAC address first. This is important because the
phone is the master device in the connection and the watch is the slave.
This master/slave setup is part of the Bluetooth protocol. Slave devices
are typically the ones to sit and advertise until a master device requests
for a connection. A master can connect to multiple devices while a slave
can only have one connection.
Now let’s follow the output of the proxy.
$ sudo btproxy 11:22:33:44:55:66 77:88:99:AA:BB:CC
Running proxy on master 11:22:33:44:55:66 and slave 77:88:99:AA:BB:CC
Using shared adapter
Slave adapter: hci0
Master adapter: hci0
Looking up info on slave (77:88:99:AA:BB:CC)
Looking up info on master (11:22:33:44:55:66)
Spoofing master name as Pebble 9FAA_btproxy
Running inquiry scan
Proxy listening for connections for “Serial Port Server Port 1”
Proxy listening for connections for “Audio/Video Remote Control”
Attempting connections with 2 services on slave
Connected to service “Audio/Video Remote Control”
Connected to service “Serial Port Server Port 1”
Now you’re free to connect to “Pebble 9FAA_btproxy” from master device.
The Proxy will look up the name and class of the devices about to be proxied
so it can copy the name and class to the Bluetooth adapters being used. In this
case only one adapter is being used so it will only copy the slave’s properties.
Halfway through this it makes a pairing request to my Pebble watch, to which I accept.
The proxy then opens Bluetooth sockets for each service that the watch device hosts, which will be
what the phone connects to. The proxy connects to the services on the watch. Once this is done,
I connect the master device (my phone) to the proxy device (Pebble 9FAA_btproxy).
btproxy output:
Accepted connection from (’11:22:33:44:55:66′, 1)
>> b’x00x1ex001x01x1bx07xe0xd9xcbx89WKxf7x9dB5xbfGxcaxadxfex01x01x00x00x00x02x04x00x01x00x00x00x00x01x00x11x00′
<< b'x00x11x00x11x01xffxffxffxffx00x00x00x00x00x00x00x02x02x02x04x00' << b'x00x01x00x10x00' >> b’x00x96x00x10x01Utxb4xfbv2. 9. 1x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x0054664bdx00x00x06x01R”T_v1. 5. 5x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x00x001c16275x00x01x06x01Rxe2xf82102V1x00x00x00x00Q206134E01L3xaax9fxa6xe9x17x00&ex8ax03Utxb4xfben_USx00x00x01XXXXXXXx00′
<< b'x00x0bx13x89x00tmfg_color' >> b’x00x06x13x89x01x04x00x00x00x07′
<< b'x00x01x17px01' >> b’x00tx17px01x00x00x00x08x00x00x00x00′
<< b'x00x05x00x0bx02Uxec^4' There are two protocols getting dumped here: SPP and Pebble. They are binary protocols which is why it’s unreadable. But sending a notification should come up as clear text. Here is what gets logged after I sent myself a text message: << b'x00Fx0bxc2x00x01x00x00x00x00x00x00x00x00x00x00x00x00K_xecUx01x02x03x01x0ex00(123) 456-6789x03x0cx00Hello Pebblexffx05x00xfex05x00x01x03x01x01x05x00Reply' You can see the phone number and the contents of the text message, “Hello Pebble”. Here’s the packet sent after I sent myself a Google Hangouts message: << b'x00bx0bxc2x00x01x00x00x00x00x01x00x00x00x00x00x00x00xf2_xecUx01x02x02x01rx00Conor Patrickx03x1ax00Sent a message on Hangoutsx01x02x01x01rx00Open on phonex02x04x01x01x07x00Dismiss' You can see it sent two options: “Open on phone” and “Dismiss”. Anything in the packets can be altered in real time using an inline Python script. For example: # # This replaces the options in a Pebble notification packet def master_cb(req): req = place(b'Open on phone', b'Hi welcome to') req = place(b'Dismiss', b'Btproxy') print( '<< ', repr(req)) return req def slave_cb(res): print('>> ‘, repr(res))
return res
master_cb is called when the master device (phone) is sending a packet to the slave (watch). And vice versa with slave_cb.
Restart btproxy:
sudo btproxy 11:22:33:44:55:66 77:88:99:AA:BB:CC -s
Then send a notification:
I’ve intended this tool to be used for analysis, and can be used for getting security insights for the increasing amount of
“IoT” devices out there.
So far I’ve used it to pull apps, firmware updates, certificates/credentials, and change identifiers.
It’s not ideal for an actual attack, unless there was some clever way for forcing already paired devices to unpair and then
hope they reconnect to the proxy. Forcing unpairing has been done using an Ubertooth but it’s not something that I have
looked into yet.
Have any questions or comments? Contact me or comment below!
Follow @_conorpp
Tweet to @_conorpp
BTProxy - Internet Of Things Communications - GitBook

BTProxy – Internet Of Things Communications – GitBook

Internet Of Things CommunicationsSearch…CoverSummaryAbout This TrainingOnce Upon A Time troductionConnectivitySerialTelephonyWiFiBluetoothArchitectureProtocol StackLinuxHCIToolBlueZL2PingSDPToolGATTToolBTMonBTProxyDevelopment BoardsLaboratoryLow-Power Wide-Area NetworksRFIDZigBeeZ-WaveThreadHomeKitSatelliteNear Field CommunicationNeulRFProtocolsLibrariesWrap-UpSandBoxPowered By GitBookBTProxyMan in the Middle analysis tool for Bluetooth Github​PreviousBTMonNextDevelopment BoardsLast modified 3yr agoCopy link

Frequently Asked Questions about btproxy

Leave a Reply

Your email address will not be published. Required fields are marked *