Cheap Multipayload Rubber Ducky with Adafruit Neo Trinkey
How to create a multipayload Rubber Ducky with Adafruit Neo Trinkey for less than 10$ step by step.
Within the hacking community, the Hak5 website is well known for the number of cybersecurity-related tools it has. Within its catalog we can find from tools for wifi auditing, such as Wifi Pineapple, to data capture devices, such as Key Croc, which is a keylogger with tools that allow remote actions to be performed on the connected device.
Inside the "HOTPLUG ATTACKS" category, we find the USB Rubber Ducky. This device, when connected to a computer, behaves like a keyboard and sends the signals of the previously programmed keys (which we call payload) as if someone were typing, but at maximum speed. This allows to automate a task that could take several minutes to run running it in seconds, being able to execute a large number of commands in a very short lapse of time. In addition, keyboards are trusted devices by default so the operating systems usally doesn't have any problem when using this type of tools.
The main problem we have with this device is, on the one hand, its price, since it is around $80 on the official website. On the other hand, you can only have one payload configured at the same time, so if you want to use another payload you have to delete the previous one, not being able to have several configured at the same time.
The idea
Researching through the hardware store Adafruit I found a device that caught my attention, the Adafruit Neo Trinkey - SAMD21 USB Key with 4 NeoPixels. This device, which costs just $7, gives us on a tiny board (12mm x 32mm) with USB port, 4 LEDs, 2 touch pads, 256KB of flash memory, and can be programmed with both Arduino and Circuit Python. To top it off, it says that it can be used as a Keyboard/Mouse HID, so we can make it behave like a keyboard.
This little board gives us everything we need to program our own Rubber Ducky multipayload. The idea is the following:
- Use the 4 LEDs to give visual feedback of the selected payload.
- Use one of the touch pads to switch payloads.
- Use the other pad to execute the payload.
This way we can quickly interact with the device, choose the payload that fits the situation, and execute it without reprogramming.
Let's get to work
The first thing we have to do is to install Circuit Python on the board. To do this we download the latest version from the Circuit Python page:
After downloading the file, connect the Neo Trinkey to the computer and, once it is booted, press the reset button twice. This should make the TRINKEYBOOT device appear as connected (if not, repeat, sometimes it doesn't happen the first time). Then copy the file adafruit-circuitpython-neopixel_trinkey_m0-**-**-*.*.*.uf2
to that device. After this the LEDs will blink and the CIRCUITPY device will appear. With this we will have it ready to execute our program in Python.
After this, the next thing we have to do is to download the adafruit_ducky.mpy
library. To do this we go to the Circuit Python libraries section and download the bundle corresponding to the version of Circuit Python that we have installed:
Once downloaded, we unzip the .zip
, go into the lib
folder and copy the adafruit_ducky.mpy
file inside our board, in CIRCUITPY/lib/
(it may be necessary to create this folder if it did not exist before).
Now we have our Neo Trinkey ready to run Python and the library that is able to convert our payload in DuckyScript (this is the name of the scripting language that will generate the payloads) to keystrokes, so now it is time to write our Python program that will orchestrate all this.
The first thing we have to do is to create our payloads. For that we are going to create a payloads
folder with 3 payloads inside, inside the CIRCUITPY
device folder. The folder structure should look like this:
CIRCUITPY ├── code.py ├── lib │ └── adafruit_ducky.mpy └── payloads ├── payload_bbgg.txt ├── payload_rrbb.txt └── payload_rrrr.txt
We will forget about the code.py
file for the moment, and focus on the payloads. As you can see in the names, all of them have a suffix preceded by _
. This suffix is the one that will indicate the colors of the leds when that payload is selected, so it is important that all the payloads have it, and that this sequence is not repeated in any payload. In this example, only the following colors are available (you can modify the code if you want others or more colors):
- r: red
- g: green
- b: blue
Behind each payload we are going to put the following replacing color_code
by the color pattern chosen in the file name:
STRING Hello World <color_code>
Now all that remains is to program our Python script. The script that Circuit Python executes at startup is the code.py
file, so that is where we have to insert our code (the comments are merely explanatory, I recommend removing them since after installing Circuit Python there is barely 48KB of free space left for our program and payloads):
import time import os import usb_hid from adafruit_hid.keyboard import Keyboard from adafruit_hid.keyboard_layout_us import KeyboardLayoutUS import adafruit_ducky import touchio import board import neopixel # Specifies payloads folder and color mappings payloads_folder = 'payloads' colors_mappings = { 'r': 0xFF0000, 'g': 0x00FF00, 'b': 0x0000FF } # Inits touchpads and LEDs touch1 = touchio.TouchIn(board.TOUCH1) touch2 = touchio.TouchIn(board.TOUCH2) pixels = neopixel.NeoPixel(board.NEOPIXEL, 4) # Switch of LEDs and decrease brightness pixels.fill((0x000000)) pixels.brightness = 0.05 # Sleep 1s to avoid a race condition on some systems time.sleep(1) # Inits keyboard interface (US layout) keyboard = Keyboard(usb_hid.devices) keyboard_layout = KeyboardLayoutUS(keyboard) # Blinks to indicate that is ready pixels.fill((0xFFFFFF)) time.sleep(0.1) pixels.fill((0x000000)) time.sleep(0.1) pixels.fill((0xFFFFFF)) time.sleep(0.1) pixels.fill((0x000000)) # Gets hexa colors from payload name def get_payload_color(payload_file_name): color_code = payload_file_name.split('_')[-1].split('.')[0] colors = [] for key_color_code in color_code: colors.append(colors_mappings[key_color_code]) return colors # Sets LEDs colors based on selected payload def set_leds_colors(): for led_index in range(4): led_color = payloads[selected_payload]['colors'][led_index] pixels[led_index] = led_color # Generates an array with payloads with their colors payloads_file_names = os.listdir(payloads_folder) payloads = [] for payload_file_name in payloads_file_names: payload = { 'path': payloads_folder + '/' + payload_file_name, 'colors': get_payload_color(payload_file_name) } payloads.append(payload) # Select first payload and set LEDs colors selected_payload = 0 set_leds_colors() # Needs touched times to avoid false positives touched = time.monotonic() # Indicates if adafruit ducky is running is_running = False while True: if is_running: # Run next line from payload is_running = duck.loop() continue if time.monotonic() - touched < 0.25: # False positive touch continue if touch1.value: # Select next payload and set LEDs colors selected_payload = (selected_payload + 1) % len(payloads) set_leds_colors() touched = time.monotonic() if touch2.value: # start running the selected payload duck = adafruit_ducky.Ducky( payloads[selected_payload]['path'], keyboard, keyboard_layout ) is_running = True touched = time.monotonic()
After this, and if no error has been made in the process, our Rubber Ducky multipayload is ready. When connecting it to the computer the LEDs should light up based on the selected payload (initially the first file in the payloads
folder) and, when clicking on the touch pad farthest from the reset button, the LEDs should change indicating the current selected payload. Once the payload is selected by clicking on the touch pad closest to the reset button it should start writing following the payload instructions.
The program code can be found in the following repository: