Programmable HID USB Keystroke Dongle: Using the Teensy as a pen testing device

Programmable HID USB Keystroke Dongle: Using the Teensy as a pen testing device

Quick Links To Sections:

Introduction

While I was at Shmoocon 2010, I was given a Phantom Keystroker. It's a neat little USB dongle which looks like a thumbdrive that you could surreptitiously install in the back of someone's computer. The Phantom Keystroker acts as a keyboard/mouse USB HID (Human Interface Device) to send keystrokes, move the mouse pointer around randomly, toggle caps lock and other things to annoy your co-workers and loved ones. This started me thinking, what if you could make something like this that was programmable? There are all sorts of things you could do with it.

The Hak5 U3 USB switch blade is pretty cool, but lots of folks have autorun turned off by default now. That said, they don't turn off the adding of a new USB keyboard! A programmable USB key stroke dongle could replace U3 switchblades in places where autorun from removable storage it is disabled. A USB HID device also does not need special drivers installed on modern operating systems, much like how a thumbdrive does not need drivers if the host supports USB mass storage. This would allow for doing things on a terminal quickly, and without drawing as much attention as sitting down in front of the terminal would. The person turns their head for a minute, the pen-tester plugs in their programmable USB key stroke dongle, and Bob's your uncle, instant pwnage. All sorts of command could be run, but more on that later in the examples section.

The programmable key stroke dongle could be set to run by a timer. The pen-tester programs the dongle to wait for a certain amount of time after install before doing its thing, a time when the pen-tester suspects that a user with extra privileges will be logged into the target workstation. If timed right, all sorts of privilege escalation can happen. There are more options than just a timer however. If the dongle has heat sensor or a photo resistor built in it could be programmed to dump its key stroke/mouse payload when the heater kicks in or the lights come on in an office. Think of the possibilities!

While at Shmoocon I saw the Hak5 crew setting up, and went by to talk to Daren and Snubs. I mentioned the Phantom Keystroker to Darren, and how I thought it would be great to be able to make a programmable one. Daren told me he had something to tell me later. It seems Darren (http://www.hak5.org/) and Robin Wood (digininja http://www.digininja.org) had been working on just such a project. Cool, great (or devious) minds think alike! I was looking forward to their product.

After the con, I decided to see if I could come up with a ghetto way to make a programmable USB keystroker. I started looking around, and found programmable promotional USB buttons used for marketing that took people to a predefined website. Neat, but not easily reprogrammed. I then started looking into Arduino, since my buddy Morgellon turned me on to them. But implementing a USB HID with the standard Arduino is a bit of a pain. Then I found a related device called the Teensy ( http://www.pjrc.com/teensy/ ) which you could program in C, or the easier Arduino development environment, and that already supported USB HID out of the box! Rock on, and it was only $18 to $27 depending on how you got it. I opted for the Teensy over the Teensy++ since it was cheaper, smaller and I did not need many I/O pins.





For those who want a more professional device with nicer packaging, Daren and Robin have a product coming soon. I encourage you to buy theirs when it comes out to help promote their work, and so Daren can spend more time on the Hak5 projects we so love. For those who have an electronics/DIY bent, and like to "Go ugly early" what follows are details on how I made my programmable USB key stroke dongle.

So, why would a pen-tester want one?

1. Likely types faster than you can, without errors. This is important when physical access time to the target system is limited.

2. Works even if U3 autorun is turned off.

3. Draws less attention than sitting down in front of the terminal would. The person turns their head for a minute, the pen-tester plugs in their programmable USB key stroke dongle, and the box is popped as Dave Kennedy likes to say.

5. The HID can also be set to go off on a timer when you know a target will be logged in, or by sensor when certain conditions are met.

6. You could embed a hub and a flash drive in your package so that you have storage and the programmable USB HID all in one nice neat package.

7. Embed your device in a USB toy or peripheral (lots of spare room in a printer or dancing USB penguin) and give it to your target as a 'gift'. Packaging that looks like a normal thumb drive is also an option.

8. After your Trojan USB device is in place, program it to "wake up", mount onboard storage, run a program that fakes an error to cover what it is doing (fake BSOD for example), do its thing, then stop (leaving the target to think "it's just one of those things").

Just use your imagination!

What sort of commands would you use?

All sorts of things could be done:

1. Add a user to the box or the domain.

2. Run a program that sets up a back door.

3. Copy files to your thumbdrive (see example code for how to find the flash drive by volume name)

4. Go to a website they have a cookie for, and do some sort of transaction (sort of like CSRF, but hardware based).

I'd like to note one disadvantage of the device. The first time you plug in a USB HID it takes a bit of time to enumerate. This seems to take a little longer with a USB HID than a new U3 thumbdrive does. Still, I think there are many applications for this USB keyboard/mouse device.

What's in a name?

You know, 'A programmable USB keystroke dongle' is kind of a mouthful to say. I needed a shorter name for this sort of device. Lots of folks build their electronics projects in Altoids tins, so I thought about calling it MintyPwn, in honor of LadyAda's MintyBoost. Also, since it's a USB stick, and I planned to use DIP switched to select what keystrokes/mouse movements to send, DIPStick sounded like a cool name. Neither of those however really seem to describe what the device was, so I thought maybe an acronym was in order:

P rogrammable H ID U SB K eystroke D ongle,

or PHUKD for short.

How it's built

What follows is a rough schematic (with light sensor) and set of pictures that should be enough for you to build your own. Please keep in mind, my soldering and rotary tool skills are not yet up to snuff, so the packaging can be made better/smaller. Also included is some sample code for the Arduino development environment. I plan to add more code and pictures as the project matures. If you have any ideas for useful payloads for the PHUKD type, please let me know.

More Pics and Videos

People requested I add more photos so they know what is soldered where, so I hope the following helps them out.

A few updated pics (added 4/1/2010):

Notice how I soldered in the photoresistor and 10kΩ resistor, it's ugly but it works with the code below.

I used a 24 pin IC mount and soldered it on backward, that way I could use the pin holes as sort of a mini bread board. The DIP switch I'm using in the pic requires the use of something like a paper clip to set the switches, but at least I won't accidently set them wrong in my pocket as easily.

I used heat shrink tubing to make the package a little neater, and hold it all together.

A few even newer pics (added 6/3/2010):

These are two new units I've put together, one with a normal Teensy 2.0 and an SD adapter, the other with a Teensy++ 2.0. Notice I used heat shrink to make the shell, this works pretty well as I can start shrinking it, cut holes for the switches as it shrinks, and then slit the whole thing so I can take it on and off as needed.

The Teensy 2.0 unit, disassembled

The naked Teensy++. Yes, my soldering skills need work. I've added a momentary push button for diagnostic and demo help.

Here is the other side, with the shield taken off. I really like using the shield concept, as headers are cheap and easy to solder. Now I can repurpose the unit anytime I like by just swapping shields made on cheap perf board.

I've also made a trojaned mouse. The way this one works is there is a USB hub, and a microSD USB adapter soldered into the mouse along with the Teensy. I've got this one set to run it's payload when scroll lock is toggled. The following video should explain more:

Short presentation I did for the Bob talks at Outerz0ne 2010 on the concept



Download MP4 from:

http://blip.tv/file/get/Irongeek-phukd880.mp4

Slides here:

http://irongeek.com/downloads/phid.pptx

http://irongeek.com/downloads/phid.pdf

This video will show you the basics of setting up the Teensyduino environment in Windows

Defcon Slides

Video:

Download:

http://www.archive.org/download/ProgrammableHidUsbKeystrokeDongleUsingTheTeensyAsAPenTestingDevice/10_defcon_113.mov

http://vimeo.com/download/video:28325339?v=2&e=1284637240&h=d36e95a75ee6c8f304129758b2661b2d&uh=f4afcf834d3f6b50bab666fc1bc75195

Programming examples and my PHUKD library

To make things a little easier on you, I've made a simple library for common tasks.

Download PHUKD Library 0.4

(Note: Most of the code on this page is for versions of the library before 0.3, but it should be easy to adapt.)

Download PHUKD Library 0.3

Download PHUKD Library 0.2

To use the library, copy the files phukdlib.h and phukdlib.cpp into <arduino folder>\libraries\PhukdLib\, then add this include line to your sketch:



#include <phukdlib.h>



I've put a little demo sketch in the zip file under examples to help illustrate how it can be used. Keep in mind, I've been mostly implementing for Windows so far. Linux and OS X will take other keystrokes to accomplish the same effects. The function names are fairly self explanatory, but just in case:

CommandAtRunBarMSWIN(char *SomeCommand) Opens the MS Windows run bar and executes the given command. CommandAtRunBarGnome(char *SomeCommand) Opens a run bar in Gnome under Linux and executes the given command. CommandAtRunBarOSX(char *SomeCommand); Opens Spotlight under OS X and executes the given command. CommandAtNewTerminal(char *SomeCommand); Opens a Terminal under OS X and executes the given command. ShrinkCurWinMSWIN() Shrinks the active window to help hide it in MS Windows. ShrinkCurWinGnome() Shrinks the active window to help hide it in Gnome. ShrinkCurWinOSX(); Shrinks the active window to help hide it in OS X. PressAndRelease(int KeyCode, int KeyCount) This function simplifies the pressing and releasing of a key. You can also specify how many times to hit the key (really useful for tabbing to where you need to be on web sites). ShowDiag() Just sends diagnostic info out the keyboard interface. Things like the reading on analog pin 0, and the state of each input. Should work on both types of Teensy, but I've not done a lot of testing. DIPOptions Not really a function, but a string you can set in your sketch that ShowDiag will print out. I kept forgetting which DIP switch I had set to run which function, so I use this as a reminder at runtime. int ledkeys(void) I noticed when I logged into a box, the Num Lock LED would often toggle (depending on how it was set last). I thought this would make a great way to know when someone just logged in, since the Num lock, Caps lock and Scroll lock events are sent to every attached keyboard on the system. Now we can have a sort of two way communication giving us a better idea of when a user is really sitting at the system, and it's logged in and ready for mischief. Also, thanks to KennyG for the CAPS lock trap idea. All we do is turn on CAPS lock, and when we see it go off we know someone is at the keyboard to turn it off. ledkeys returns the setting of the "lock keys"

Num Lock = 1

CAPS Lock = 2

Scroll Lock = 4

Add them together to get combos, for example if all threm are on 7 would be the result. You can use binary operators to separate out just the lock keys you are looking for, but I've made that a little easier with the IsXOn functions below. boolean IsNumbOn(void) Returns TRUE if NUM Lock LED is on and FALSE otherwise. boolean IsCapsOn(void) Returns TRUE if Caps Lock LED is on and FALSE otherwise. boolean IsScrlOn(void) Returns TRUE if Scroll Lock LED is on and FALSE otherwise.

I'm also open to adding more functions, and taking code contributions.



The following are some simple examples of programming the PHUKD using the Arduino environment (from before I made my PHUKD library, so look at the example code that came with the PHUKD library if you intend to use it). More details on the language can be found at the following two links:

http://arduino.cc/en/Reference/

http://www.pjrc.com/teensy/teensyduino.html

When I started this project I had to delve into the Teensyduino source code to figure out how to send some control keys. Since then, Paul has done a lot of work on the Teensyduino documentation, especially when it comes to USB HID support. Check out these two pages:

http://www.pjrc.com/teensy/td_ keyboard.html

http://www.pjrc.com/teensy/td_ mouse.html

Also, while it's not PHUKD related, Paul has some great docs on the peculiarities of using the Teensy to control servos:

http://www.pjrc.com/teensy/td_libs_Servo.html

I'm working on a laser projector and a hexapod project that these docs will help greatly.

Hopefully my sample code will help you figure it out how to use this functionality as well. If you wish to change the USB Vendor and Product ID look in arduino-xxxx\hardware\teensy\cores\tensy_hid\usb_private.h

If you come up with any useful keyboard commands, please send them to me as functions that are easy to include in other's projects. Note that in the code below, I have one DIP switch determine one function, but with an 8 position dip I could program it so I had the choice of 256 different functions.





The following program, "phukdexample.pde", should get you started. Just read the comments. /*The following is Irongeek's code to do simple keyboard/mouse functions with the Teensy, including

something like U3 functionality that will work even if autorun is disabled.

http://www.irongeek.com/i.php?page=security/programmable-hid-usb-keystroke-dongle



To learn more about Teensyduino see:

http://www.pjrc.com/teensy/teensyduino.html

http://www.arduino.cc/en/Reference/HomePage

Look in arduino-xxxx\hardware\teensy\cores\tensy_hid\usb_api.h for key definitions

Edit arduino-xxxx\hardware\teensy\cores\tensy_hid\usb_private.h to change USB Vendor and Product ID

*/

int ledPin = 11 ;

int DIP_1 = 14 ;

int DIP_2 = 15 ;

int DIP_3 = 16 ;

int DIP_4 = 17 ;

int DIP_5 = 18 ;

int DIP_6 = 19 ;

int DIP_7 = 20 ;

int DIP_8 = 21 ;

int PhotoRead = 0 ;

unsigned long LastTimerCheck = millis ();

// The setup() method runs once, when the sketch starts

void setup () {

// initialize the digital pin as an output:

pinMode ( ledPin , OUTPUT );

pinMode ( DIP_1 , INPUT_PULLUP ); // Dip

pinMode ( DIP_2 , INPUT_PULLUP ); // Dip

pinMode ( DIP_3 , INPUT_PULLUP ); // Dip

pinMode ( DIP_4 , INPUT_PULLUP ); // Dip

pinMode ( DIP_5 , INPUT_PULLUP ); // Dip

pinMode ( DIP_6 , INPUT_PULLUP ); // Dip

pinMode ( DIP_7 , INPUT_PULLUP ); // Dip

pinMode ( DIP_8 , INPUT_PULLUP ); // Dip

}

// the loop() method runs over and over again,

// as long as the Arduino has power

void loop ()

{

PhotoRead = analogRead ( 8 );

//Timer example, millis() returns the number of milliseconds since being plugged in. It will roll over to 0 at about 50 days.

// This example does not use the DIP switches, but should fire off about ever minute.

if (( millis () - LastTimerCheck ) >= 60000 ){

digitalWrite ( ledPin , HIGH ); // set the LED on

CommandAtRunBar ( "notepad.exe" );

delay ( 1000 );

Keyboard . print ( "It has been about a minute since I executed last, current time is " );

Keyboard . print ( millis ());

Keyboard . print ( " and I was set to go off after " );

Keyboard . print ( LastTimerCheck );

Keyboard . println ( " plus 60000 milliseconds." );

LastTimerCheck = millis ();

}



//Please note: I use negative logic here, when a pin goes to ground the code us run.

//My version of Hello World, just opens up notepad and says I'm here. :)

if (! digitalRead ( DIP_1 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

CommandAtRunBar ( "notepad.exe" );

delay ( 1000 );

Keyboard . print ( "Adrian Was here!!! :)" );

}



//Locks the workstaion if you are in Windows

if (! digitalRead ( DIP_2 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

Keyboard . set_modifier ( MODIFIERKEY_CTRL | MODIFIERKEY_ALT );

Keyboard . set_key1 ( KEY_DELETE ); // use delete key

Keyboard . send_now (); // send strokes

Keyboard . set_modifier ( 0 ); //prep release of control keys

Keyboard . set_key1 ( KEY_ENTER );

delay ( 1500 );

Keyboard . send_now (); //Send the key changes

Keyboard . set_key1 ( 0 );

Keyboard . send_now ();

}

//Moves the mouse around and clicks to be annoying

if (! digitalRead ( DIP_3 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

Mouse . move ( random (- 100 , 100 ) , random (- 100 , 100 ) );

Mouse . click ();

}

//Opens a browser to http://irongeek.com

if (! digitalRead ( DIP_4 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

CommandAtRunBar ( "cmd /c start http://irongeek.com" );

}

/*

This sectiont sends a command to the run bar, finds the drive letter by its volume name (MYTHUMB in

this ecample, and case sensitive), then runs your script. Thanks to Tim Medin for this more

elegant command line then what I had for finding the

thumbdrive by volume name.

*/

if (! digitalRead ( DIP_5 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

CommandAtRunBar ( "cmd /c for /F %i in ('WMIC logicaldisk where \"DriveType=2\" list brief ^| find \"MYTHUMB\"') do %i\\myscript.bat" );

}

//Make a facebook post, assumes the person is logged in.

if (! digitalRead ( DIP_6 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

CommandAtRunBar ( "cmd /c start http://m.facebook.com" );

delay ( 6000 );

PressAndRelease ( KEY_TAB , 8 );

Keyboard . print ( "Test from Phukd device, more info at http://www.irongeek.com/i.php?page=security/programmable-hid-usb-keystroke-dongle" );

PressAndRelease ( KEY_TAB , 1 );

PressAndRelease ( KEY_ENTER , 1 );

}

//Check light, do funny stuff

if (! digitalRead ( DIP_7 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

CommandAtRunBar ( "notepad.exe" );

delay ( 1000 );

if ( PhotoRead < 400 ) {

Keyboard . print ( "I'm scared of the dark" );

}

if ( PhotoRead >= 400 && PhotoRead <= 900 ) {

Keyboard . print ( "The lights are on it seems" );

}

if ( PhotoRead > 900 ) {

Keyboard . print ( "What the hell?!?!?! Is that a laser or a nuke flash?" );

}

}

if (! digitalRead ( DIP_8 )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

ShowDiag ();

}

digitalWrite ( ledPin , LOW ); // set the LED off

delay ( 6000 ); //keeps commands from being sent one after the other too fast

}



void CommandAtRunBar ( char * SomeCommand ){

digitalWrite ( ledPin , HIGH ); // set the LED on

Keyboard . set_modifier ( 128 ); //Windows key

Keyboard . set_key1 ( KEY_R ); // use r key

Keyboard . send_now (); // send strokes

Keyboard . set_modifier ( 0 ); //prep release of control keys

Keyboard . set_key1 ( 0 ); //have to do this to keep it from hitting key multiple times.

Keyboard . send_now (); //Send the key changes

delay ( 1500 );

Keyboard . print ( SomeCommand );

Keyboard . set_key1 ( KEY_ENTER );

Keyboard . send_now ();

Keyboard . set_key1 ( 0 );

Keyboard . send_now ();

}

void PressAndRelease ( int KeyCode , int KeyCount ){

int KeyCounter = 0 ;

for ( KeyCounter = 0 ; KeyCounter != KeyCount ; KeyCounter ++){

Keyboard . set_key1 ( KeyCode ); // use r key

Keyboard . send_now (); // send strokes

Keyboard . set_key1 ( 0 );

Keyboard . send_now (); // send strokes

}

}

void ShowDiag (){

digitalWrite ( ledPin , HIGH );

for ( int thispin = 0 ; thispin < 23 ; thispin ++){

if (! digitalRead ( thispin )) {

digitalWrite ( ledPin , HIGH ); // set the LED on

Keyboard . print ( thispin );

Keyboard . println ( " is low" );

}

else {

Keyboard . print ( thispin );

Keyboard . println ( " is high" );

}

}

Keyboard . print ( "analog pin 8 is: " );

Keyboard . println ( PhotoRead );

digitalWrite ( ledPin , LOW );

}



A note on packaging

There are many options for how to package up your USB dongle. I ordered an enclosure form Mouser that seems to hold the Teensy well:

http://www.mouser.com/search/refine.aspx?Ntk=P_MarCom&Ntt=175697523

I had to make a hole in the case to fit the dip switches, and have yet to solder things together in this package. I hate to spend money on enclosures, so I go to the candy aisle looking for good boxes. As mentioned before, Altoids cans are an option, but I don't like the fact that they are metal. Ice Breakers makes a type of sour gum that comes in a rectangular plastic box with rounded edges, and it's big enough to hold a small bread board. MudFlap of the Hacker Consortium pointed me towards using TicTac containers, and they look like they will work well, especially if you want to put a photoresistor in your device (transparent plastic walls). If you are in need of a small USB A to USB Micro B connecto, DealExtreme has a cheap solution:

http://www.dealextreme.com/details.dx/sku.2704~r.48687660

The plastic casing around it is also easy to remove if you need more flexibility. I plan to keep updating this page as the project progresses, so please check back again.







Robin's Site

http://www.digininja.org

Darren's Site

http://www.hak5.org/

Get your Teensy product and programming information here, but please let them know I sent you (Maybe I can get some free samples for my project)

http://www.pjrc.com/teensy/

Need a small USB A to USB Micro B? This is a good cheap solution

http://www.dealextreme.com/details.dx/sku.2704~r.48687660

Changelog :

12/05/2011: I updated the PHUKD library to 0.4. There are some new function. OS X Spotlight and Terminal code was provided by Adam Baldwin and Aaron Howell ngenuity-is.com / evilpacket.net.

jp (.ronin) http://www.hackfromacave.com also provide some source code for the OS X side, but I ended up using Adam and Aaron's. The functions added were:

extern void CommandAtRunBarOSX(char *SomeCommand);

extern void CommandAtNewTerminal(char *SomeCommand);

extern void ShrinkCurWinOSX();



I also tested to make sure it worked with Arduino 1.0.

09/25/2011: I put up the version 0.3 of the Programmable HID USB Keyboard/Mouse Dongle Library. It should now work with newer versions of the Arduino and the Teensyduino environments.

09/16/2010: I've added my Defcon video to the bottom of the Videos and Pictures section of the PHUKD article.

08/03/2010: I've added my Defcon Slides to the bottom of the Videos and Pictures section of the PHUKD article.

07/14/2010: Added a video that will show you the basics of setting up the Teensyduino environment in Windows so you can start developing PHUKD devices.

06/28/2010: I've updated the PHUKD Library to 0.2.

The main changes are that I've added two functions for the Gnome desktop under Linux:

ShrinkCurWinGnome()

CommandAtRunBarGnome(char *SomeCommand)

you may also see something about OS X, but it does not work. Can anyone tell me a run bar equivalent that works in OS X?

I've also changed the library so that it goes in the normal libraries folder, and not the same folder as your sketch.

06/03/2010: I've added some links to Paul's updated Teensyduino documentation:

http://www.pjrc.com/teensy/td_ keyboard.html

http://www.pjrc.com/teensy/td_ mouse.html

http://www.pjrc.com/teensy/td_libs_Servo.html

06/03/2010: I've updated the Programmable HID USB Keyboard Dongle project page with:

More pics of newer units.

A video of the trojaned color changing mouse.

A PHUKD Arduino library to help developers.

I've also made a bunch of anchor tags to help in navigating to the part you want.

As a side note, I'll be speaking about the PHUKD project at Defcon! Thanks to Paul for the help with the hardware, the Kentuckian ISSA for helping to get me to Defcon, and Tenacity Solutions for their support on this project.

04/01/2010: I've updated my Programmable HID USB Keyboard Dongle project page with:

Photos of a soldered, heat shrink packaged, thumbdrive sized unit.

Code example that demonstrates timer delays and using the light sensor.

Code for doing quick diagnostics on the PHUKED unit to see which pins are connected and what the analog pin reads.

Added a comment about being able to use the 8 position DIP switch to choose from 256 different options.

Hope you find the updates useful.



03/23/2010: First posted



