Skip to content

Instantly share code, notes, and snippets.

@dotps1
Last active May 31, 2017 13:31
Show Gist options
  • Save dotps1/afdc76683e3eb5401ea0cd7226ad9aa0 to your computer and use it in GitHub Desktop.
Save dotps1/afdc76683e3eb5401ea0cd7226ad9aa0 to your computer and use it in GitHub Desktop.
Test for WannaCry Vulns using PSJobs
#requires -module ActiveDirectory
# Input computers.
$threshold = (Get-Date).AddDays(-180)
$computers = Get-ADComputer -Filter { OperatingSystem -notlike "*server*" -and OperatingSystem -like "*windows*" -and PasswordLastSet -gt $threshold } |
Select-Object -ExpandProperty Name |
Sort-Object -Property Name
# Make sure there are not existing jobs.
Get-Job |
Remove-Job -Force
# Counters and settings
$throttle = 20
$timeout = 10
$jobs = @()
$count = 0
# Start the jobs.
while ($count -lt $computers.Count) {
if ((Get-Job -State Running).Count -lt $throttle) {
$jobs += Start-Job -ScriptBlock { try { .\Get-EternalBlueVulnerabilityStatistics.ps1 -Name $args[0] -ErrorAction Stop } catch { throw $_ } } -Name $computers[$count] -ArgumentList @($computers[$count])
Write-Progress -Activity "Gathering EternalBlue statistics accross $($computers.Count) systems. Jobs are throttled to $throttle concurrent jobs" -Status "Job started for $($computers[$count].ToString())" -PercentComplete ($jobs.Count / $computers.Count * 100)
$count++
}
}
Write-Progress -Activity "Testing for WannaCry vulnerability accross $($computers.Count) systems" -Completed
# Wait for remaining jobs to finish.
while (($runningJobs = Get-Job -State Running).Count -ne 0) {
Write-Progress -Activity "Waiting for remaining jobs to finish" -Status "$($runningJobs.Count) jobs remaining"
foreach ($runningJob in $runningJobs) {
if ($runningJob.PSBeginTime -lt (Get-Date).AddMinutes(-$timeout)) {
Stop-Job -Job $runningJob
}
}
}
Write-Progress -Activity "Waiting for remaining jobs to finish" -Completed
# Clean up the jobs and export the results to CSVs.
foreach ($job in (Get-Job)) {
switch ($job.State) {
"Completed" {
$receivedJob = Receive-Job -Job $job
$completedOutput = [PSCustomObject]@{
PSComputerName = $job.Name
OperatingSystemCaption = $receivedJob.OperatingSystemCaption
OperatingSystemVersion = $receivedJob.OperatingSystemVersion
LastBootUpTime = $receivedJob.LastBootUpTime
AppliedHotFixID = $receivedJob.AppliedHotFixID
SMB1FeatureEnabled = $receivedJob.SMB1FeatureEnabled
SMB1ProtocolEnabled = $receivedJob.SMB1ProtocolEnabled
Port139Enabled = $receivedJob.Port139Enabled
Port445Enabled = $receivedJob.Port445Enabled
}
Export-Csv -InputObject $completedOutput -Path .\WannaCryVulnerability_Servers.csv -Append -NoTypeInformation
Remove-Job -Job $job
}
"Failed" {
Receive-Job -Job $job -ErrorAction SilentlyContinue
$failedOutput = [PSCustomObject]@{
PSComputerName = $job.Name
FailureReason = $Error[0].Exception.Message
}
Export-Csv -InputObject $failedOutput -Path .\WannaCryVulnerability_Servers_Failures.csv -Append -NoTypeInformation
Remove-Job -Job $job
}
default { continue }
}
}
@dotps1
Copy link
Author

dotps1 commented May 18, 2017

@hawkbox you should be able to use Receive-Job and then extract the error. I would recommend using the -Keep switch while you try it out because once you receive a job you cannot receive it again.

hope that helps!

  • edit
    @hawkbox, I have added what you ask, you can just receive the job, then grab the $Error record.

@hawkbox
Copy link

hawkbox commented May 18, 2017

Thank you sir. I'll take a run at it today.

@blay2
Copy link

blay2 commented May 18, 2017

I'm a powershell beginner. when I run Wannacryvulnerbilitytesting.ps1, the csv file has this output for every computer, 
"The term '.\Get-EternalBlueVulnerabilityStatistics.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again. "

Get-EternalBlueVulnerabilityStatistics.ps1 is in the same directory that Wannacryvulnerbilitytesting.ps1 is in (and is the same directory I'm operating the Powershell window from). What am I doing wrong?

@dotps1
Copy link
Author

dotps1 commented May 18, 2017

@blay2 you probably need to change your working directory to where ever you have the .\GetEtenralBlueVulnerablityStatistics.ps1 saved. or change that line to the full path. .\ means "in the current directory".

hope that helps.

@hawkbox
Copy link

hawkbox commented May 19, 2017

Sorry I lied, got an opportunity to run it this morning. It fails out with
The term '.\Get-EternalBlueVulnerabilityStatistics.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."

So I'm going to read through and see if i can sort it out.

@hawkbox
Copy link

hawkbox commented May 19, 2017

Script name didn't match up, corrected that. When I manually run the script it
PS C:\WannaCry> .\Test-WannaCryVulnerability.ps1

PSComputerName : DC1SCOM01
OperatingSystemCaption : Microsoft Windows Server 2016 Standard
OperatingSystemVersion : 10.0.14393
Vulnerable : True
AppliedHotFixID :
SMB1FeatureEnabled : False
SMB1ProtocolEnabled : True

No problem, when I use yours it gives the same error as above, but with the proper script name. I feel like I'm missing something obvious.

@micmaher
Copy link

micmaher commented May 19, 2017

@Jason_Crichton @dotps1

I think it should be this

            if ($smb1Feature -eq 1) {
                $smb1FeatureEnabled = $true
            } else {
                $smb1FeatureEnabled = $false

Not this
if ($optionalFeature -eq 1) {
$smb1FeatureEnabled = $true
} else {
$smb1FeatureEnabled = $false

The SMB feature installation state will always be false

Thanks for the great work. Why oh why could MS not have come up with something similar to help out.

@dotps1
Copy link
Author

dotps1 commented May 22, 2017

@hawkbox, you just need the updated script, download Get-EternalBlueVulnerabilityStatistics from the PSGallery. There was too much confusion with the Vulnerable property from the first one i made. Also, the new script uses a CIM session so its much faster.

@micmaher, that typo is fixed in the new script as well.

thanks.

@hawkbox
Copy link

hawkbox commented May 23, 2017

Oh I thought that was a typo, I'll go try that.

@hawkbox
Copy link

hawkbox commented May 23, 2017

Hmm I'm still getting the same error after wiping out the scripts and starting from scratch. I have both scripts in the same folder, I've browsed to it, everything works in isolation. But still getting

"2UA22002ZP","The term '.\Get-EternalBlueVulnerabilityStatistics.ps1' is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try again."

@dotps1
Copy link
Author

dotps1 commented May 24, 2017

if you installed it via the Gallery then you need to remove the .\ from the path. I just pasted in my script i was running, and because i wrote it, the script was in my current working directory.

@pythoninthegrass
Copy link

Hey @dotps1, I'm running into the same issue as @blay2 and @hawkbox with calling .\Get-EternalBlueVulnerabilityStatistics.ps1. Running the script by itself works as well as sourcing it outside of the nested if loop. I've tried $PSScriptRoot, no dot sourcing, and different levels of quotation. None have worked so far. It's not installed via the Gallery -- I'd prefer to run it as a standalone script.

Thanks for writing it up -- you've saved myself and dozens of other IT guys quite a bit of leg work.

@dotps1
Copy link
Author

dotps1 commented May 30, 2017

im sorry your all running into this. hope this helps.

if you use Install-Script from the PSGallery, it will append the path to your $env:Path value, which is why after you Install a script you can call it from anywhere. IE PS C:\> Get-EternalBlueVlunerabiltiyStatistics just works.

if you use Save-Script this will do exactly as it sounds, and you will need to specify a path to save the script to. If you have Saved the script, rather then Installed the script. You will need to one of two things.

  1. Change you Working Directory to the path where the script is saved. Use Set-Location -Path C:\Folder\.
  2. Change the path in the code above from .\Get-EternalBlueVulnerabilityStatistics.ps1 to C:\Folder\Get-EternalBlueVulnerabilityStatistics.ps1.

@pythoninthegrass
Copy link

Okay, after adding Set-Location and the absolute location it works. I noticed that if try { ."$pwd\Get-EternalBlueVulnerabilityStatistics.ps1" is run, it sources My Documents instead of the working directory. It'd be nice to not have to hard code the location, but I'm glad it's functioning at least.

Thanks for all of your help @dotps1!

@dotps1
Copy link
Author

dotps1 commented May 31, 2017

if you don't want to hardcode the location, then use Install-Script. Not sure what else to tell you on that one. Its an external resource from this script, so it will need to know where its at. This script is just how i used Get-EternalBlueVulnerabilityStatistics function i wrote to scan my environment. That function is separate from this script so you can use it however you want.

thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment