⚠️ Disclaimer
This project is for educational purposes only.
Devices like the Rubber Ducky and its DIY clones can be powerful tools for penetration testing and automation but they should only be strictly used on systems you own or have explicit permission to test.
The Idea
The idea for this project came while watching a movie where the main character wanted to damage a bank that caused problems to his parents, so he went inside the bank pretending to be a British business man that wanted to create an account at their bank, he "accidentally" pushes the pen case to the ground so he can plug a tiny USB device in the computer. Once he does that the bankers monitor is blocked and you can see code being executed with lightning speeds.
So I had to find out what that tiny USB device was that did all of this chaos. I researched a bit and it turned out to be a Rubber Ducky, they were on sale but lets be real, when you are a student and on a budget you aren't going to spend $100 on a USB that acts as a keyboard and mouse, you have to improvise.
So I said lets try and do this myself with the resources I had.
Resources
- Pro Micro with 32u4 Chip
- Slide Switches (Pack of 40)
- DuPont female cables (Pack of 40)
Total: ~$30
The Process
Wiring the switch
I first started with the switch. Out of the pack, I had two types of switches. One had big pins that didn't fit the DuPont cable, and the other one had small pins and holes for connecting wires. Naturally I went with the second one since I had no other choice. I took 1 DuPont cable and cut it in half with pliers and stripped about 1.5 cm of insulation covering the cable inside. Then I tied one half of the cable to the middle pin of the switch, and the other one to an outer pin.
The Schema:
Why the switch?
Once the code has been uploaded to the Pro Micro, it cannot be plugged into your computer to change the code without causing the payload to be executed.
So this switch acts like a mode selector:
- Left: Programming mode (safe to upload new code)
- Right: Execution mode (it runs the payload once plugged in)
Programming the board
Now comes the fun part...programming!
I used the Arduino IDE to make the write and upload the code into the board.
The setup
- Tools -> Board -> Boards Manager
- Select "Arduino Leonardo" (it uses the same bootloader as the Pro Micro)
- Choose your port and board
- Create a new sketch
This is how it should look like when you first start your project.
Now we are going to start by including the libraries.
#include <Keyboard.h>
void setup() {
// put your setup code here, to run once:
}
void loop() {
// put your main code here, to run repeatedly
}
We will include the Keyboard library so the Pro Micro board can act as a Keyboard.
Next we need to act logic to the switch.
Adding the mode switch logic
#include <Keyboard.h>
const int switch_mode = 2; // You can change this depending on which pin you wired the middle pin of the switch
void setup() {
pinMode(switch_mode, INPUT_PULLUP); // Normally HIGH, LOW when switch connect to GND (When we slide it to the left)
bool execute_mode = (digitalRead(switch_mode) == LOW);
if(!execute_mode){
// Off / Standby (Payload doesn't execute)
// So it gives us the opportunity to change and upload new
// code to the board
return;
}
// if it's on the other side then we will execute code down here
}
void loop() {
// put your main code here, to run repeatedly:
}
Now the board can tell weather to execute the payload or to stay idle based on where the switch is staying.
Writing the payload
Here's a more complete version that opens the terminal(on Linux) and executes whoami
#include <Keyboard.h>
const uint8_t switch_mode = 2; // D2 (switch middle)
const unsigned long WAIT_SHORT = 300; // short pause
const unsigned long WAIT_MED = 550; // medium pause
void attempt_open_terminal() {
Keyboard.press(KEY_LEFT_CTRL);
Keyboard.press(KEY_LEFT_ALT);
delay(30);
Keyboard.write('t');
Keyboard.releaseAll();
}
void send_payload() {
delay(WAIT_MED);
Keyboard.begin();
delay(100);
Keyboard.println("whoami");
delay(100);
Keyboard.end();
}
void setup() {
pinMode(switch_mode, INPUT_PULLUP);
// HIGH normally, LOW when switch connects to GND
delay(50);
bool executeMode = (digitalRead(switch_mode) == LOW);
if (!executeMode) {
// Off / Standby (Payload doesn't execute)
return;
}
delay(1000); // give OS/USB time to detect the HID device
attempt_open_terminal();
send_payload();
}
void loop() {
// nothing repeated
}
Breaking it down
We added the attempt_open_terminal
and send_payload_commands
functions. Lets go through each one of them and see what they do.
- attempt_open_terminal() This function simulates pressing CTRL + ALT + T, the linux shortcut to open the terminal.
It uses the Keyboard library to press multiple keys at once (CTRL + ALT + T) and then release them, just like a real user would do.
-
send_payload()
Once the terminal opens, this function executese the payload.
Here, it simply types
whoami
, which prints the currently logged-in user.
You can replace that line with any other commands, like opening websites, or running system commands (ethically, of course).
Top comments (0)