Test-WannaCryVulnerability.ps1

<#PSScriptInfo
 
.Version
    1.2
.Guid
    477aa3f4-0434-4925-9c92-7323066cceb7
.Author
    Thomas J. Malkewitz @dotps1
.Tags
    WannaCry, SMB1, Malware
.ProjectUri
    https://github.com/dotps1/PSFunctions
.ReleaseNotes
    Added a try catch to first WMI call in the 'ByComputerName' parameter set. If the call fails the entire loop for that system will be terminated.
 
#>


<#
 
.Synopsis
    Tests for WannaCry vulnerabilities.
.Description
    Test for applicable patches to prevent the WannaCry malware. Tests for SMB1 protocol and component.
.Inputs
    System.String
    Microsoft.Management.Infrastructure.CimSession
.Outputs
    System.Management.Automation.PSCustomObject
.Parameter ComputerName
    System.String
    ComputerName to test.
.Parameter Credential
    System.Management.Automation.PSCredential
    Credential to test with.
.Parameter CimSession
    Microsoft.Management.Infrastructure.CimSession
    CimSession to test.
.Example
    PS C:\> Test-WannaCryVulnerability
 
    PSComputerName : myrig
    OperatingSystem : Microsoft Windows 7 Professional
    Vulnerable : False
    AppliedHotFixIds : KB4012212|KB4015546|KB4015549
    SMB1FeatureEnabled : False
    SMB1ProtocolEnabled : False
.Example
    PS C:\> Get-ADComputer -Filter * -OrganizationalUnit OU=workstations,DC=domain,DC=org | Test-WannaCryVulnerability
 
    PSComputerName : workstation
    OperatingSystem : Microsoft Windows 7 Professional
    Vulnerable : True
    AppliedHotFixIds :
    SMB1FeatureEnabled : False
    SMB1ProtocolEnabled : True
.Notes
    Not applicable to windows 10.
.Link
    https://dotps1.github.io
.Link
    https://www.powershellgallery.com/packages/New-ADUserName
.Link
    https://grposh.github.io
 
#>



[CmdletBinding(
    DefaultParameterSetName = "ByComputerName"
)]
[OutputType(
    [PSCustomObject]
)]

param (
    [Parameter(
        ParameterSetName = "ByComputerName",
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
    )]
    [Alias(
        "ComputerName"    
    )]
    [String[]]
    $Name = $env:COMPUTERNAME,

    [Parameter(
        ParameterSetName = "ByComputerName"
    )]
    [System.Management.Automation.PSCredential]
    $Credential = [PSCredential]::Empty,

    [Parameter(
        ParameterSetName = "ByCimSession",
        ValueFromPipeline = $true,
        ValueFromPipelineByPropertyName = $true
    )]
    [Microsoft.Management.Infrastructure.CimSession[]]
    $CimSession
)

begin {
    $hotFixIDs = @(
        "KB3205409", 
        "KB3210720", 
        "KB3210721", 
        "KB3212646", 
        "KB3213986", 
        "KB4012212", 
        "KB4012213", 
        "KB4012214", 
        "KB4012215", 
        "KB4012216", 
        "KB4012217", 
        "KB4012218", 
        "KB4012220", 
        "KB4012598", 
        "KB4012606", 
        "KB4013198", 
        "KB4013389", 
        "KB4013429", 
        "KB4015217", 
        "KB4015438", 
        "KB4015546", 
        "KB4015547", 
        "KB4015548", 
        "KB4015549", 
        "KB4015550", 
        "KB4015551", 
        "KB4015552", 
        "KB4015553", 
        "KB4015554", 
        "KB4016635", 
        "KB4019213", 
        "KB4019214", 
        "KB4019215", 
        "KB4019216", 
        "KB4019263", 
        "KB4019264", 
        "KB4019472"
    )
}

process {
    switch ($PSCmdlet.ParameterSetName) {
        "ByComputerName" { 
            foreach ($nameValue in $Name) {
                if (-not (Test-Connection -ComputerName $nameValue -Count 1 -Quiet)) {
                    Write-Warning -Message "Failed to contact $nameValue."
                    continue
                }

                try {
                    $osCaption = Get-WmiObject -ComputerName $nameValue -Class Win32_OperatingSystem -Property Caption -Credential $Credential -ErrorAction Stop |
                        Select-Object -ExpandProperty Caption
                } catch {
                    Write-Error -Message "Failed to contact WMI on '$nameValue'." -RecommendedAction "Verify WS-MAN is not being blocked by the firewall."
                    continue
                }

                if ($osCaption -match "Windows 10|2016") {
                    Write-Warning -Message "$osCaption is not vulnerable to WannaCry."
                    continue
                }

                # Patches
                $appliedHotFixIds = Get-WmiObject -ComputerName $nameValue -Class Win32_QuickFixEngineering -Credential $Credential |
                    Where-Object -FilterScript { $_.HotFixID -in $hotFixIDs } |
                        Select-Object -ExpandProperty HotFixID

                #SMB1 Feature
                $smb1Feature = Get-WmiObject -ComputerName $nameValue -Class Win32_OptionalFeature -Property InstallState -Filter "Name = 'SMB1Protocol'" -Credential $Credential |
                    Select-Object -ExpandProperty InstallState

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

                #SMB1 Protocol
                $smb1Protocol = Invoke-WmiMethod -ComputerName $nameValue -Class StdRegProv -Name GetDwordValue -ArgumentList @( [uint32]2147483650, "SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters", "SMB1" ) -Credential $Credential |
                    Select-Object -ExpandProperty uValue

                if ($smb1Protocol -eq 0) {
                    $smb1ProtocolEnabled = $false
                } else {
                    $smb1ProtocolEnabled = $true
                }

                if ($appliedHotFixIds.Count -gt 0 -and -not $smb1FeatureEnabled -and -not $smb1ProtocolEnabled) {
                    $vulnerable = $false
                } else {
                    $vulnerable = $true
                }

                $output = [PSCustomObject]@{
                    PSComputerName = $nameValue
                    OperatingSystem = $osCaption
                    Vulnerable = $vulnerable
                    AppliedHotFixIds = $appliedHotFixIds -join "|"
                    SMB1FeatureEnabled = $smb1FeatureEnabled
                    SMB1ProtocolEnabled = $smb1ProtocolEnabled
                }

                Write-Output -InputObject $output
            }
        }
        
        "ByCimSession" {
            foreach ($cimSessionValue in $CimSession) {
                $osCaption = Get-CimInstance -CimSession $cimSessionValue -ClassName Win32_OperatingSystem -Property Caption | 
                    Select-Object -ExpandProperty Caption

                if ($osCaption -match "Windows 10|2016") {
                    Write-Error -Message "$osCaption is not vulnerable to WannaCry."
                    continue
                }

                # Patches
                $appliedHotFixIds = Get-CimInstance -CimSession $CimSession -ClassName Win32_QuickFixEngineering |
                    Where-Object -FilterScript { $_.HotFixID -in $hotFixIds } |
                        Select-Object -ExpandProperty HotFixID

                #SMB1 Feature
                $smb1Feature = Get-CimInstance -CimSession $cimSessionValue -ClassName Win32_OptionalFeature -Property InstallState -Filter "Name = 'SMB1Protocol'" |
                    Select-Object -ExpandProperty InstallState

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

                # SMB1 Protocol
                $smb1Protocol = Invoke-CimMethod -CimSession $cimSessionValue -ClassName StdRegProv -MethodName GetDwordValue -Arguments @{ hDefKey = [uint32]2147483650; sSubKeyName = "SYSTEM\CurrentControlSet\Services\LanmanServer\Parameters"; sValueName = "SMB1" } |
                    Select-Object -ExpandProperty uValue

                if ($smb1Protocol -eq 0) {
                    $smb1ProtocolEnabled = $false
                } else {
                    $smb1ProtocolEnabled = $true
                }

                if ($appliedHotFixIds.Count -gt 0 -and -not $smb1FeatureEnabled -and -not $smb1ProtocolEnabled) {
                    $vulnerable = $false
                }

                $output = [PSCustomObject]@{
                    PSComputerName = $cimSessionValue.ComputerName
                    OperatingSystem = $osCaption
                    Vulnerable = $vulnerable
                    AppliedHotFixIds = $appliedHotFixIds -join "|"
                    SMB1FeatureEnabled = $smb1FeatureEnabled
                    SMB1ProtocolEnabled = $smb1ProtocolEnabled
                }

                Write-Output -InputObject $output
            }
        }
    }
}