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:
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?
Install Beamgun!
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:
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!