Defeating the USB Rubber Ducky with Beamgun

November 15, 2016

The USB Rubber Ducky is an awesome little piece of infosec goodness put together by the venerable hackers at HAK5. Ever since it was popularized on Mr. Robot, I’ve wanted to write some software to mitigate the vulnerability:

15 Second Password Hack, Mr. Robot Style

Basically, this little USB device registers itself as a keyboard, waits a bit, then blasts the victim’s computer with a flurry of keystrokes at super-human speed. This requires an active session (i.e. the user is logged in), although obviously the computer need not be unattended.

The possible effects of this attack are devastating. Generally it is trivial to elevate privileges to administrator (since you’re emulating a user typing), so you can install whatever kind of malware you’d like, pull larger scripts down from a remote server, or worse.

What, you ask, can men do against such reckless hate?

Reckless

Install Beamgun!

Beamgun Infographic

You can download and install Beamgun using the simple instructions on Github.

Using Beamgun

Beamgun shows up in the system tray whenever you run BeamgunApp.exe. If you install using the MSI installer, this will happen whenever you login. You can click on the icon to view the application’s status:

Beamgun Screenshot

From here, you can disable Beamgun, e.g. if you are about to insert and remove USB devices frequently, for the next 30 minutes. You can also “Reset” Beamgun if it has alerted, and finally you can force Beamgun to quit by clicking “Exit”.

You can also configure the security settings for Beamgun using the two check boxes. I recommend checking both boxes to get the benefits of both mitigations. Whenever beamgun detects a USB device, it will only execute the mitigations you have checked. If you check “Attempt to steal”, Beamgun will attempt to steal all of the keystrokes and sink them harmlessly into its window. If you check “Lock workstation”, Beamgun will tell Windows to lock, forcing you to type your password in to continue.

Beamgun Internals

There are a few important Win32 API calls that enable us to do the following:

  • monitor for keyboard device insertions so we can alert,
  • hook keystrokes so we can see what the attacker tried to do,
  • continuously steal keyboard focus to stop the attacker from making progress, and ultimately
  • lock the workstation.

Device insertions

The Win32 API gives us the following functions for getting device notifications:

HDEVNOTIFY WINAPI RegisterDeviceNotification(
  _In_ HANDLE hRecipient,
  _In_ LPVOID NotificationFilter,
  _In_ DWORD  Flags
);

BOOL WINAPI UnregisterDeviceNotification(
  _In_ HDEVNOTIFY Handle
);

Basically, we’re telling Windows that we’d like to get notified about device insertions, and we pass off a handle to our main window. When device-related events happen, Windows alerts us and stuffs a 2-byte code into our callback function to tell us what kind of event it was. See UsbMonitor.cs in the Model section of BeamgunApp for the code that implements all of this.

Hook keystrokes

Next, we’d like to hook keystrokes so that when we alert on a USB device insertion, we can record what the attacker was trying to do and present it to the user.

For this, we turn to the tried and true Windows Hooks APIs:

HHOOK WINAPI SetWindowsHookEx(
  _In_ int       idHook,
  _In_ HOOKPROC  lpfn,
  _In_ HINSTANCE hMod,
  _In_ DWORD     dwThreadId
);

BOOL WINAPI UnhookWindowsHookEx(
  _In_ HHOOK hhk
);

Use of these functions is well documented. We’re just using them for good-guy purposes. See KeyStrokeHooker.cs for my implementation (again in Model of BeamgunApp).

Steal focus continuously

I chose Windows Presentation Foundation to build Beamgun, so I used WPF APIs to steal focus:

public static IInputElement Focus(
	IInputElement element
)

The real trick is getting it to run in the thread that’s responsible for the window. This can be done with Dispatcher.Invoke, as in the following snippet:

viewModel.StealFocus += () => Dispatcher.Invoke(new MethodInvoker(delegate
{
    Show();
    Activate();
    Topmost = true;
    Keyboard.Focus(this);
}));

Here I also call the functions Show() and Activate() before stealing keyboard focus. This ensures that the Beamgun alert window pops up for the user to see. See the code-behind in MainWindow.xaml.cs of BeamgunApp for more details.

Lock the workstation

As another (potentially more robust) option, the user can elect to lock the workstation whenever a USB insertion happens. This is safe because we are piggy-backing off the safety mechanisms built into the login screen, e.g. the local security authority subsystem service. The Win32 API for locking the screen is as straightforward as it gets:

BOOL WINAPI LockWorkStation(void);

Special considerations

Since the Rubber Ducky is a keyboard device, I had to be very careful in implementing Beamgun to try to thwart some countermeasures. I’m sure that some enterprising Rubber Ducky fans will try hard to subvert Beamgun, so I hardened the following features:

  • Disabling ALT-F4
  • Using custom buttons that do not respond to keyboard events
  • Stealing focus on a loop with a very tight interval

Feedback

Please post any issues or bugs you find!