Make a Rubber Ducky with a Raspberry Pico

I am taking a slight detour from the Raycasting series of posts (don’t worry, the next post in the series is coming soon) to cover another small project I have been working on, creating a Rubber Duckly using a Raspberry Pico and CircuitPython.


A Rubber Ducky is a keystroke injection tool that is often disguised as a USB flash drive to trick an unsuspecting victim into plugging it into their computer. The computer recognizes the Rubber Ducky as a USB keyboard (and mouse if required), and when it is plugged in, it executes a sequence of pre-programmed keystrokes, which will be executed against the target computer, as if the user did it. This attack thus exploits the security roles and permissions assigned to the user logged in at the time.
This is a good time to note that using a Rubber Ducky for dubious intents is illegal and a terrible idea, and I take no responsibility for the consequences if anyone chooses to use what they learn here to commit such acts.

To create the Rubber Ducky described in this post, you will need four things:
1. A Rasberry Pico
2. A Micro USB Cable
3. CircuitPython
4. The Adafruit HID Library of CircuitPython

First, you will need to install CircuitPython on your Raspberry Pico. This link will provide all the instructions and downloads you will require to do this.
Next, you will need to install the Adafruit HID Library. Instructions on how to do this can be found here.

Now that all the pre-requisites are installed and configured, the source code below can be deployed using the process described in the first link. The Source code below executes a sequence of keystrokes that opens Notepad on the target computer and type out a message. Just note that the keystrokes are slowed down significantly to make what is happening visible to the user Typically, this will not be done with a Rubber Ducky.

import board
import digitalio
import time
import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode

kbd = Keyboard(usb_hid.devices)

led = digitalio.DigitalInOut(board.LED)
led.direction = digitalio.Direction.OUTPUT
led.value = True
time.sleep(10)
while True:
    kbd.press(Keycode.GUI, Keycode.R)
    time.sleep(.09)
    kbd.release_all()
    kbd.press(Keycode.N)
    time.sleep(.09)
    kbd.release(Keycode.N)
    time.sleep(.09)
    kbd.press(Keycode.O)
    time.sleep(.09)
    kbd.release(Keycode.O)
    time.sleep(.09)
    kbd.press(Keycode.T)
    time.sleep(.09)
    kbd.release(Keycode.T)
    time.sleep(.09)
    kbd.press(Keycode.E)
    time.sleep(.09)
    kbd.release(Keycode.E)
    time.sleep(.09)
    kbd.press(Keycode.P)
    time.sleep(.09)
    kbd.release(Keycode.P)
    time.sleep(.09)
    kbd.press(Keycode.A)
    time.sleep(.09)
    kbd.release(Keycode.A)
    time.sleep(.09)
    kbd.press(Keycode.D)
    time.sleep(.09)
    kbd.release(Keycode.D)
    time.sleep(.09)
    kbd.press(Keycode.ENTER)
    time.sleep(.09)
    kbd.release(Keycode.ENTER)
    time.sleep(.09)

    kbd.press(Keycode.H)
    time.sleep(.09)
    kbd.release(Keycode.H)
    time.sleep(.09)
    kbd.press(Keycode.E)
    time.sleep(.09)
    kbd.release(Keycode.E)
    time.sleep(.09)
    kbd.press(Keycode.L)
    time.sleep(.09)
    kbd.release(Keycode.L)
    time.sleep(.09)
    kbd.press(Keycode.L)
    time.sleep(.09)
    kbd.release(Keycode.L)
    time.sleep(.09)
    kbd.press(Keycode.O)
    time.sleep(.09)
    kbd.release(Keycode.O)
    time.sleep(.09)
    kbd.press(Keycode.ENTER)
    time.sleep(.09)
    kbd.release(Keycode.ENTER)
    time.sleep(100)

led.value = False

Here is a video of the Rubbert Ducky in Action:

Make a Rubber Ducky with a Raspberry Pico