Exploiting the USB Ninja BLE Connection
This documentation is a summary how I exploited the USB Ninja BLE Connection, so that it is able to Control the Bad USB cable with a raspberry pi an a simple python script that is linked in the sources.
Used Hardware and Software
- The USB Ninja Pro-kit with Remote control
- Containing 3 Bad USB cables (only one is needed).
- Remote Control
- Hacking Hardware
- Hacking Software
- Hcitool (Linux preinstalled)
- Gatttool (Linux preinstalled)
- Ubertooth Tools (Too install them read: Bluetooth Sniffing with Ubertooth: A Step-by-step guide)
USB Ninja Pro-kit
The USB Ninja is a Rubberducky in a USB cable that comes in the flavours USB to USB micro, USB to USB-C and USB to Lightning. The bad USB cable can be programmed with two payloads. The payloads are developed under the usage of the Arduino IDE with the USBNinja libraries. During the attack phase its possible to start triggered payloads can be either by plugging the bad USB cable in or with the magnet or via the BLE 4.0 Remote. The trigger modes get defined by the way the c code is programmed.
The Remote itself has a leaver to turn it on and off and the button A and button B, which activate their corresponding payload. There is also a USB micro input to charge the Remote or to edit the shared secret.
The website states that the remote automatically connects to the bad USB cable if the defined passwords are the same. Where the Remote need a driver and a program to set the password, it can be directly done in the source code of the payload of the bad USB cable.
Sadly the developers require that the user uses Windows based Operating systems because its only possible to update the password of the Remote with a windows program that can be downloaded on the manufacturers website in the help tab. Furthermore, this software gets treated as malicious software form Windows because it doesn't have a manufacturer certificate. So the users have to click threw the warning from windows defender to change the password. I personally would much more like to see a simple shell script for Linux and a batch script for Windows to do the job.
Anyway, the standard password is
126.96.36.199 and as long as the user uses only one Remote at the same time it doesn't really matter. Enough background knowledge let's get to the pen testing.
Reverse Engeneering The Remote
Step one: Standard BLE Actions
As I started to test the USBNinja in a normal fashion, I got curios, how much information I can gather by using the standard the programmes that come with Linux. I shut down the Remote, so the bad USB Cable BLE Module can be found by devices. Then I run the
hcitool lescan command that is used by the usual Linux BLE discovery function.
sudo hcitool lescan
LE Scan ... E1:F1:22:F6:28:B5 (unknown) E1:F1:22:F6:28:B5 Ninja XX:XX:XX:XX:XX:XX XX:XX:XX:XX:XX:XX (unknown)
The Raspberry instantly found the BLE signal of the bad USB cable and i might be lucky to gather informaten with the gatttool. As I connected via the gatttool tho the USB cable it closed the connection after two seconds due to invalid file descriptor in the glib. This error makes the Interactive mode useless.
[ ][LE]> connect E1:F1:22:F6:28:B5 Attempting to connect to E1:F1:22:F6:28:B5 Connection successful [E1:F1:22:F6:28:B5][LE]> (gatttool:32016): GLib-WARNING **: 13:54:39.135: Invalid file descriptor.
But the not interactive mode did succeed fast enough to work before the Error occurs. So I used the characteristics command form gatttool to list all discoverable characteristics of the device.
gatttool -b E1:F1:22:F6:28:B5 --characteristics handle = 0x0002, char properties = 0x0a, char value handle = 0x0003, uuid = 00002a00-0000-1000-8000-00805f9b34fb handle = 0x0004, char properties = 0x02, char value handle = 0x0005, uuid = 00002a01-0000-1000-8000-00805f9b34fb handle = 0x0006, char properties = 0x02, char value handle = 0x0007, uuid = 00002a04-0000-1000-8000-00805f9b34fb handle = 0x0008, char properties = 0x02, char value handle = 0x0009, uuid = 00002aa6-0000-1000-8000-00805f9b34fb handle = 0x000b, char properties = 0x20, char value handle = 0x000c, uuid = 00002a05-0000-1000-8000-00805f9b34fb handle = 0x000f, char properties = 0x02, char value handle = 0x0010, uuid = 00002a29-0000-1000-8000-00805f9b34fb handle = 0x0011, char properties = 0x02, char value handle = 0x0012, uuid = 00002a24-0000-1000-8000-00805f9b34fb handle = 0x0013, char properties = 0x02, char value handle = 0x0014, uuid = 00002a25-0000-1000-8000-00805f9b34fb handle = 0x0015, char properties = 0x02, char value handle = 0x0016, uuid = 00002a27-0000-1000-8000-00805f9b34fb handle = 0x0017, char properties = 0x02, char value handle = 0x0018, uuid = 00002a26-0000-1000-8000-00805f9b34fb handle = 0x0019, char properties = 0x02, char value handle = 0x001a, uuid = 00002a28-0000-1000-8000-00805f9b34fb handle = 0x001b, char properties = 0x02, char value handle = 0x001c, uuid = 00002a23-0000-1000-8000-00805f9b34fb handle = 0x001d, char properties = 0x02, char value handle = 0x001e, uuid = 00002a50-0000-1000-8000-00805f9b34fb handle = 0x0020, char properties = 0x10, char value handle = 0x0021, uuid = 0000fff1-0000-1000-8000-00805f9b34fb handle = 0x0024, char properties = 0x0e, char value handle = 0x0025, uuid = 0000fff2-0000-1000-8000-00805f9b34fb handle = 0x0027, char properties = 0x1c, char value handle = 0x0028, uuid = 0000fff3-0000-1000-8000-00805f9b34fb handle = 0x002c, char properties = 0x28, char value handle = 0x002d, uuid = 8ec90003-f315-4f60-9fb8-838830daea50
So the characteristics are not encrypted and can be read without the key. Furthermore the first 13 of are well-known GATT Services defined by the Bluetooth Special Interest group. These handles and their values are listed in the table below:
|0x0003||Read and Write||Device Name||USBNinja+|
|0x0007||Read||Pheripheral preffered connection Parameters||08 00 08 00 00 00 f4 01|
|0x0009||Read||Central Address Resolution||01|
|0x0010||Read||Manufacturer Name String||Proxgrind|
|0x0012||Read||Model Number String||Ninja|
|0x0014||Read||Serial Number String||20190912|
|0x0016||Read||Hardware Revision String||V2.0|
|0x0018||Read||Firmware Revision String||V1.0|
|0x001a||Read||Software Revision String||v5.0|
|0x001c||Read||System ID||64 00 00 00 00 9e 00 00|
|0x001e||Read||PnP ID||01 d2 00 10 08 01 00|
The wellknown Services were easy to read and to decipher but the four custom services couldn't be reverse engineered by using only the gatttool. The rest of this paragraph is a listing of the commands used to create the table above and how to decode the values. So feel free to jump to the Ubertooth BLE connection sniffing part by klicking this link: Step Two: Ubertooth BLE Connection Sniffing.
 [Device Name] [RW] handle: 0x0002, char properties: 0x0a, char value handle: 0x0003, uuid: 00002a00-0000-1000-8000-00805f9b34fb
char-read-hnd 3 Characteristic value/descriptor: 55 53 42 4e 69 6e 6a 61 2b 55 53 42 4e 69 6e 6a 61 2b hex = USBNinja+ ASCII char-write-req 3 4861636b6564 Characteristic value was written successfully char-read-hnd 3 Characteristic value/descriptor: 48 61 63 6b 65 64
 [Appearance] [R] handle: 0x0004, char properties: 0x02, char value handle: 0x0005, uuid: 00002a01-0000-1000-8000-00805f9b34fb
char-read-hnd 5 Characteristic value/descriptor: 00 00 0 -> Appearance Unknown
 [Pheripheral preffered connection Parameters] [R] handle: 0x0006, char properties: 0x02, char value handle: 0x0007, uuid: 00002a04-0000-1000-8000-00805f9b34fb
char-read-hnd 7 Characteristic value/descriptor: 08 00 08 00 00 00 f4 01
 [Central Address Resolution] [R] handle: 0x0008, char properties: 0x02, char value handle: 0x0009, uuid: 00002aa6-0000-1000-8000-00805f9b34fb
char-read-hnd 9 Characteristic value/descriptor: 01
 [Service Change] [Indication] handle: 0x000b, char properties: 0x20, char value handle: 0x000c, uuid: 00002a05-0000-1000-8000-00805f9b34fb
Indication services are for notifications and can not be read that easily.
 [Manufacturer Name String] [R] handle: 0x000f, char properties: 0x02, char value handle: 0x0010, uuid: 00002a29-0000-1000-8000-00805f9b34fb
char-read-hnd 10 Characteristic value/descriptor: 50 72 6f 78 67 72 69 6e 64 50 72 6f 78 67 72 69 6e 64 hex = Proxgrind ASCII
 [Model Number String] [R] handle: 0x0011, char properties: 0x02, char value handle: 0x0012, uuid: 00002a24-0000-1000-8000-00805f9b34fb
char-read-hnd 12 Characteristic value/descriptor: 4e 69 6e 6a 61
4e 69 6e 6a 61 hex = Ninja ASCII
 [Serial Number String] [R] handle: 0x0013, char properties: 0x02, char value handle: 0x0014, uuid: 00002a25-0000-1000-8000-00805f9b34fb
char-read-hnd 14 Characteristic value/descriptor: 32 30 31 39 30 39 31 32
32 30 31 39 30 39 31 32 hex = 20190912 ASCII
 [Hardware Revision String] [R] handle: 0x0015, char properties: 0x02, char value handle: 0x0016, uuid: 00002a27-0000-1000-8000-00805f9b34fb
char-read-hnd 16 Characteristic value/descriptor: 56 32 2e 30 56 32 2e 30 hex = V2.0 ASCII
 [Firmware Revision String] [R] handle: 0x0017, char properties: 0x02, char value handle: 0x0018, uuid: 00002a26-0000-1000-8000-00805f9b34fb
char-read-hnd 18 Characteristic value/descriptor: 56 31 2e 30
56 31 2e 30 hex = V1.0 ASCII
 [Software Revision String] [R] handle: 0x0019, char properties: 0x02, char value handle: 0x001a, uuid: 00002a28-0000-1000-8000-00805f9b34fb
char-read-hnd 1a Characteristic value/descriptor: 76 35 2e 30
76 35 2e 30 hex = v5.0 ASCII
 [System ID] [R] handle: 0x001b, char properties: 0x02, char value handle: 0x001c, uuid: 00002a23-0000-1000-8000-00805f9b34fb
char-read-hnd 1c Characteristic value/descriptor: 64 00 00 00 00 9e 00 00
 [PnP ID] [R] handle: 0x001d, char properties: 0x02, char value handle: 0x001e, uuid: 00002a50-0000-1000-8000-00805f9b34fb
char-read-hnd 1e Characteristic value/descriptor: 01 d2 00 10 08 01 00
Step Two: Ubertooth BLE Connection Sniffing
After installing the Ubertooth functions and get the device running, I started to sniff the transferred data and piped it directly into wireshark
Terminal A: mkfifo /tmp/pipe sudo wireshark -i /tmp/pipe Terminal B: ubertooth-btle -f E1:F1:22:F6:28:B5 -c /tmp/pipe
The Wireshark output shows that the transmitter only interacts with the handle 0x22 and 0x25. I the following figure shows the connection in a simplified way.
During the Connection establishment the exchange MTX gets discussed followed by a write request to the handle 0x22 with the value 0x0100. Then the USB Cable responds with an acknowledgement. I think that this operation causes the Error in interactive mode of the gatttool but I did use it in script of Step Three.
When a button is Pressed it first send a write request to the handle 0x25 with the value 0x38383838. This value is the Password in plaintext but coded as hex (0x38383838 = 8888). Because of that it is possible to overtake the connection if the password got sniffed. After the acknowldgment its send either the value 0x413d4c0d0a (Button A) or 0x423d4c0d0a (Button A) to tirgger the corresponding Payload. Attentive observer will instandly recognize that the first hexpair 0x41 and 0x42 of the sent values are A and B in ASCII and indicate the used buttons.
Step Three: Writing a Contolling Python Script
After the BLE connection sniffing process, I started to write a Python script that mimics and the USB Ninja Remote and it instantly worked to print well-known characteristics of the device and to trigger the payload A. After a bit of bug fixing I figured out how to payload B and converted the simple script to an advanced application which will be publicly available on gitlab under this link soon.
Usage: ./USBNinja.py -m <mode> [options] Modes: r Remote: Mimics the USB ninja Remote c Converter: Converts ducky.txt payloads into USBNinja.c u TBA: TBA Remote: ./USBNinja.py -m r -d <BDADDR> Info Prints device info Button A Triggers payload A Button B Triggers payload B Quit Leaves interactive mode Converter: ./USBNinja.py -m c -i <input file> -j <input file 2> -o <output file> -l <keyboard language> -t <triggermode> TBA: ...
Example usage of the Remote mode:
./USBNinja.py -m r -d E1:F1:22:F6:28:B5 [E1:F1:22:F6:28:B5][LE]>info Device name: Ninja Model number string: Ninja Serial number string: 20190912 Hardware revision string: V2.0 Firmware revision string: V1.0 Software revision string: v5.0 System id: 00 00 00 00 9e 00 00 PnP id: 01 d2 00 10 08 01 00 [E1:F1:22:F6:28:B5][LE]>Button A Pressed Button A [E1:F1:22:F6:28:B5][LE]>Button B Pressed Button B [E1:F1:22:F6:28:B5][LE]>Quit