Using PowerShell for Brute-Force Password Cracking (Example Script)
Can PowerShell be used as a penetration testing tool? The answer is yes. Here is a script for a brute-force password cracker.
April 17, 2024
I recently used PowerShell to build an app for generating strong, random passwords based on a selectable criteria. After writing my GUI-based password generator, I wondered about using PowerShell to do the opposite: crack passwords.
As I pondered the idea, I contemplated which type of password I might try to crack, given the variety available. Ultimately, I decided to try my luck with a password-protected file I had long been locked out of due to forgetting the password.
After extensive trial and error, I successfully used PowerShell to crack the password for protected file. However, as I prepared to write this article about the experiment, I asked myself whether publishing a tool designed to defeat a password prompt would be irresponsible. Ultimately, I decided to publish a modified version of my script. After all, a PowerShell brute-force password cracker could serve legitimate purposes in penetration testing. My modification involved removing certain code segments from the script to limit its functionality.
This modified script should be considered a do-it-yourself penetration testing tool, providing the basic structure for brute-force password cracking. I have stopped short of publicly releasing a tool that can crack passwords without being modified.
PowerShell Script for Brute-Force Password Cracking
With that all said, here is my script:
Function Test-Password
{
Param(
[String]$Password
)
$ErrorOccurred = $False
Try{
# Insert the code here to attempt using the current password
}
Catch {
$ErrorOccurred = $True
Return $ErrorOccurred
}
Return $ErrorOccurred
}
$UpperCase = @('A','B','C','D','E','F','G','H','I','J','K','L','M','N','O','P','Q','R','S','T','U','V','W','X','Y','Z')
$LowerCase = @('a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z')
$Numbers = @('1','2','3','4','5','6','7','8','9','0')
$Symbols = @('!','@','$','?','<','>','*','&')
$Charset = @()
ForEach-Object {
$UpperCase | ForEach-Object {
$Charset += $_
}
$LowerCase | ForEach-Object {
$Charset += $_
}
$Numbers | ForEach-Object {
$Charset += $_
}
$Symbols | ForEach-Object {
$Charset += $_
}
}
$MaxDepth = 8
$combinations = @("")
for ($depth = 1; $depth -le $MaxDepth; $depth++) {
$newCombinations = @()
foreach ($combination in $combinations) {
foreach ($char in $Charset) {
$newCombination = $combination + $char
Write-Host $newCombination
$Password = $NewCombination
$ErrorOccurred = Test-Password -Password $Password
If ($ErrorOccurred -eq $False){
Write-Host "Password Found: " $Password
Exit
}
If ($ErrorOccurred -eq $True){
Write-Host "Password Not Found: " $Password
}
$newCombinations += $newCombination
}
}
$combinations = $newCombinations
}
How the PowerShell Script Works
Let’s look at how this script works.
1. The script body begins by defining several character sets, including $UpperCase, $LowerCase, $Numbers, and $Symbols. These sets determine the characters in password-guessing attempts. The lines of code are directly copied from my GUI password generator script but can be adjusted to include additional characters if necessary.
2. Following this, a code block creates an array called $Charset. I add each character defined within $UpperCase, $LowerCase, $Numbers, and $Symbols to the $CharSet array. That way, a single array contains every possible character for password-guessing attempts.
3. Next, a line of code sets $MaxDepth to 8. The $MaxDepth variable defines the maximum password length. With $MaxDepth set to 8, the script will attempt password guesses of up to 8 characters long. You can change this number to adjust the maximum password length.
4. The subsequent lines of code use a For statement and a couple of ForEach statements to cycle through all possible passwords. The current password guess is stored in a variable called $NewCombination, while the $Password variable also stores the current password guess.
5. Just after the $Password variable is defined, you will notice a line:
$ErrorOccurred = Test-Password -Password $Password
This line of code passes the current password guess to a function called Test-Password. The function returns a variable called $ErrorOccurred, which will be assigned a $True or $False value.
The function itself is relatively simple. It initially sets $ErrorOccurred to $False. Incidentally, if you want to see the script cycling through all possible password combinations on screen without cracking a password, you can change the initial value of $ErrorOccurred to $True. You can see what the script does after such a modification in Figure 1.
Figure 1. This is what happens if you change $False to $True.
6. After setting $ErrorOccurred, you will notice a Try statement. This is where you insert the code to test the current password guess for validity. The approach here is that if the password guess fails (because the password is incorrect), PowerShell will return an error. The error triggers the Catch section to execute, setting $ErrorOccurred to $True before returning to the script’s main body. If no error occurs, the password is presumed correct, leaving $ErrorOccurred as $False.
Before moving forward, I will give you one last hint about making this script work as a brute-force cracking tool. To make the script work as intended, I had to append -ErrorAction Stop to the end of the line of code that submits the password guess to the file I aimed to crack. This addition ensures that the code within the Catch section is executing.
7. Once PowerShell returns to the script’s main body, there is a simple check to see if $ErrorOccurred is set to $True or $False. If $ErrorOccurred is true, the current password guess was rejected, meaning the password is incorrect. Conversely, if ErrorOccurred is false, the password was accepted, meaning that the password is correct. At that point, the script should display the new password and terminate.
It is worth noting that when I used this script to crack a password, the Exit command did not terminate the script. That meant I had to remove the “Password Not Found” line to see which password was accepted. However, I believe this anomaly had more to do with the type of password being cracked and the approach taken rather than an issue with the script itself.
About the Author
You May Also Like