Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Defender Status - script lies. Defender NOT Healthy #242

Open
bbrendon opened this issue Jul 26, 2024 · 14 comments
Open

Defender Status - script lies. Defender NOT Healthy #242

bbrendon opened this issue Jul 26, 2024 · 14 comments

Comments

@bbrendon
Copy link
Contributor

bbrendon commented Jul 26, 2024

I wouldn't usually create an issue in community scripts but considering you can disable defender and this script will still say its HEALTHY seems like a huge missing.

Write-Output "No Virus Found, Defender is Healthy"

@dinger1986
Copy link
Contributor

I'll look into that

@silversword411
Copy link
Contributor

I wouldn't usually create an issue in community scripts

Why not?

@cdp1337
Copy link
Contributor

cdp1337 commented Jul 27, 2024

Before Write-Output "Windows Defender Status Report:":

# Cleanup some variables for rendering
if ($mpStatus.FullScanAge -ge 4294967295) {
    # If never ran, will report an absurdly large number instead.
    $FullScanAge = "NEVER RAN"
}
else {
    $FullScanAge = "$($mpStatus.FullScanAge) Days ago"
}

if ($mpStatus.QuickScanAge -ge 4294967295) {
    # If never ran, will report an absurdly large number instead.
    $QuickScanAge = "NEVER RAN"
}
else {
    $QuickScanAge = "$($mpStatus.QuickScanAge) Days ago"
}

Then swap the 2 corresponding lines in the output with:

Write-Output "Full Scan Age: $FullScanAge"
Write-Output "Quick Scan Age: $QuickScanAge"

Fixes Full Scan Age: 4294967295 Days ago from being displayed.

"Never Ran?" "Never Run?" One of the two is correct, I never remember which is grammatically correct.

@dinger1986
Copy link
Contributor

Never ran would be grammatically correct.

I was thinking also if it's over a high number to make it never ran. Probably over 6 years (2,190 days) then it's never ran?

Does that make sense?

@cdp1337
Copy link
Contributor

cdp1337 commented Jul 27, 2024

Yeah, that would work too. One of my boxes reported that specific number as did Silversword's, so that's just what I used. If it's 2190 days, that should be sufficiently useful too.

@dinger1986
Copy link
Contributor

dinger1986 commented Jul 27, 2024

on the back of this updated the defender enable script

<#
.SYNOPSIS
    Enables Windows Defender and sets preferences to enhance security on workstations Win10+.
.DESCRIPTION
    Windows Defender in its default configuration provides basic protections. Running this script will enable additional settings to increase security.
    The script includes options to enable or disable full scans, quick scans, and ASR rules, and to manage controlled folder access.
.PARAMETER FullScanFrequency
    Specifies the frequency in days for scheduling full scans. If set to 0, full scans are disabled.
.PARAMETER QuickScanFrequency
    Specifies the frequency in days for scheduling quick scans. If set to 0, quick scans are disabled.
.PARAMETER SignatureUpdateFrequency
    Specifies the frequency in hours for scheduling signature updates.
.PARAMETER NoControlledFolders
    Adding this parameter will not enable Controlled Folders.
.PARAMETER AuditOnly
    Adding this parameter will set ASR rules to Audit mode.
.PARAMETER EnableCloudProtection
    Enable or disable cloud-delivered protection (0 = Default, 1 = High, 2 = High Plus).
.PARAMETER EnableCloudTimeout
    Set the cloud extended timeout value.
.PARAMETER EnablePUAProtection
    Enable or disable protection against potentially unwanted applications (0 = Off, 1 = On).
.PARAMETER FullScanTime
    Specifies the time for scheduling full scans in HH:mm format. If not provided, it will be set randomly within the working day.
.PARAMETER QuickScanTime
    Specifies the time for scheduling quick scans in HH:mm format. If not provided, it will be set randomly within the working day.
.EXAMPLE
    -FullScanFrequency 7 -QuickScanFrequency 1 -SignatureUpdateFrequency 8 -EnableCloudProtection 2 -EnableCloudTimeout 50 -EnablePUAProtection 1 -FullScanTime "14:00" -QuickScanTime "10:00"
    Configures Windows Defender to run full scans every 7 days at 2 PM, quick scans every 1 day at 10 AM, signature updates every 8 hours, enables cloud protection at High Plus level, sets cloud timeout to 50, and enables PUA protection.
.EXAMPLE
    -FullScanFrequency 0 -QuickScanFrequency 0 -SignatureUpdateFrequency 8
    Configures Windows Defender to disable the scheduling of full and quick scans.
.EXAMPLE
    -NoControlledFolders -AuditOnly
    Configures Windows Defender without enabling Controlled Folders and sets ASR rules to Audit mode.
.NOTES
    v1 dinger initial release 2021
    v1.1 adding command parameters for Controlled Folder access by Tremor and silversword
    v1.2 adding command parameter for audit mode for ASR and added extra ASR rules suggested by SDM216
    v1.3 adding parameters to manage scan frequencies and ASR rules
    v1.4 adding additional parameters for network and cloud protection, performance settings, and scheduling enhancements
#>

param (
    [int]$FullScanFrequency = 7,
    [int]$QuickScanFrequency = 1,
    [int]$SignatureUpdateFrequency = 8,
    [switch]$NoControlledFolders,
    [switch]$AuditOnly,
    [int]$EnableCloudProtection = 0,
    [int]$EnableCloudTimeout = 50,
    [int]$EnablePUAProtection = 1,
    [string]$FullScanTime,
    [string]$QuickScanTime
)

# Verifies that script is running on Windows 10 or greater
function Check-IsWindows10 {
    if ([System.Environment]::OSVersion.Version.Major -ge "10") {
        Write-Output $true
    }
    else {
        Write-Output $false
    }
}

# Verifies that script is running on Windows 10 1709 or greater
function Check-IsWindows10-1709 {
    if ([System.Environment]::OSVersion.Version.Build -ge 16299) {
        Write-Output $true
    }
    else {
        Write-Output $false
    }
}

function SetRegistryKey([string]$key, [int]$value) {
    # Editing Windows Defender settings AV via registry is NOT supported. This is a scripting workaround instead of using Group Policy or SCCM for Windows 10 version 1703
    $amRegistryPath = "HKLM:\Software\Policies\Microsoft\Microsoft Antimalware\MpEngine"
    $wdRegistryPath = "HKLM:\Software\Policies\Microsoft\Windows Defender\MpEngine"
    $regPathToUse = $wdRegistryPath # Default to WD path
    if (Test-Path $amRegistryPath) {
        $regPathToUse = $amRegistryPath
    }
    New-ItemProperty -Path $regPathToUse -Name $key -Value $value -PropertyType DWORD -Force | Out-Null
} 

function Get-RandomTimeInWorkingDay {
    $startHour = 9
    $endHour = 17
    $hour = Get-Random -Minimum $startHour -Maximum $endHour
    $minute = Get-Random -Minimum 0 -Maximum 59
    return (Get-Date).Date.AddHours($hour).AddMinutes($minute)
}

#### Setup Windows Defender Secure Settings

# Start Windows Defender Service
Set-Service -Name "WinDefend" -Status running -StartupType automatic
Set-Service -Name "WdNisSvc" -Status running -StartupType automatic

# Enable real-time monitoring
Set-MpPreference -DisableRealtimeMonitoring 0

# Enable cloud-delivered protection
Set-MpPreference -MAPSReporting Advanced

# Enable sample submission
Set-MpPreference -SubmitSamplesConsent 1

# Enable checking signatures before scanning
Set-MpPreference -CheckForSignaturesBeforeRunningScan 1

# Enable behavior monitoring
Set-MpPreference -DisableBehaviorMonitoring 0

# Enable IOAV protection
Set-MpPreference -DisableIOAVProtection 0

# Enable script scanning
Set-MpPreference -DisableScriptScanning 0

# Enable removable drive scanning
Set-MpPreference -DisableRemovableDriveScanning 0

# Enable Block at first sight
Set-MpPreference -DisableBlockAtFirstSeen 0

# Enable potentially unwanted apps
Set-MpPreference -PUAProtection Enabled

# Schedule signature updates
Set-MpPreference -SignatureUpdateInterval $SignatureUpdateFrequency

# Enable archive scanning
Set-MpPreference -DisableArchiveScanning 0

# Enable email scanning
Set-MpPreference -DisableEmailScanning 0

# Schedule full scans if not disabled
if ($FullScanFrequency -ne 0) {
    if (-not $FullScanTime) {
        $FullScanTime = (Get-RandomTimeInWorkingDay).ToString("HH:mm")
    }
    Set-MpPreference -RemediationScheduleDay 0 -RemediationScheduleTime $FullScanTime
    Write-Output "Full scans scheduled at $FullScanTime every $FullScanFrequency days"
} else {
    Write-Output "Full scans are disabled"
}

# Schedule quick scans if not disabled
if ($QuickScanFrequency -ne 0) {
    if (-not $QuickScanTime) {
        $QuickScanTime = (Get-RandomTimeInWorkingDay).ToString("HH:mm")
    }
    Set-MpPreference -ScanScheduleDay 0 -ScanScheduleQuickScanTime $QuickScanTime
    Write-Output "Quick scans scheduled at $QuickScanTime every $QuickScanFrequency days"
} else {
    Write-Output "Quick scans are disabled"
}

# Set ScanPurgeItemsAfterDelay to 30 days
Set-MpPreference -ScanPurgeItemsAfterDelay 30

# Additional performance and behavior settings
Set-MpPreference -ScanAvgCPULoadFactor 50
Set-MpPreference -ThrottleForScheduledScanOnly $true
Set-MpPreference -DisableCpuThrottleOnIdleScans $false

# Configure cloud and network protection if parameters are specified
if ($EnableCloudProtection -ge 0) {
    Set-MpPreference -CloudBlockLevel $EnableCloudProtection
}
if ($EnableCloudTimeout -ge 0) {
    Set-MpPreference -CloudExtendedTimeout $EnableCloudTimeout
}
if ($EnablePUAProtection -ge 0) {
    Set-MpPreference -PUAProtection $EnablePUAProtection
}

# Configure ASR rules if AuditOnly is specified
if ($AuditOnly) {
    Write-Output "Enabling Exploit Guard ASR rules and setting to Audit mode"
    #Block abuse of exploited vulnerable signed drivers     
    Set-MpPreference -AttackSurfaceReductionRules_Ids "56a863a9-875e-4185-98a7-b882c64b5ce5" -AttackSurfaceReductionRules_Actions AuditMode
    #Block executable content from email client and webmail
    Add-MpPreference -AttackSurfaceReductionRules_Ids "BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550" -AttackSurfaceReductionRules_Actions AuditMode
    #Block all Office applications from creating child processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "D4F940AB-401B-4EFC-AADC-AD5F3C50688A" -AttackSurfaceReductionRules_Actions AuditMode
    #Block Office applications from creating executable content
    Add-MpPreference -AttackSurfaceReductionRules_Ids "3B576869-A4EC-4529-8536-B80A7769E899" -AttackSurfaceReductionRules_Actions AuditMode
    #Block Office applications from injecting code into other processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84" -AttackSurfaceReductionRules_Actions AuditMode
    #Block JavaScript or VBScript from launching downloaded executable content
    Add-MpPreference -AttackSurfaceReductionRules_Ids "D3E037E1-3EB8-44C8-A917-57927947596D" -AttackSurfaceReductionRules_Actions AuditMode
    #Block execution of potentially obfuscated scripts
    Add-MpPreference -AttackSurfaceReductionRules_Ids "5BEB7EFE-FD9A-4556-801D-275E5FFC04CC" -AttackSurfaceReductionRules_Actions AuditMode
    #Block Win32 API calls from Office macros
    Add-MpPreference -AttackSurfaceReductionRules_Ids "92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B" -AttackSurfaceReductionRules_Actions AuditMode
    #Block executable files from running unless they meet a prevalence, age, or trusted list criterion
    Add-MpPreference -AttackSurfaceReductionRules_Ids "01443614-cd74-433a-b99e-2ecdc07bfc25" -AttackSurfaceReductionRules_Actions AuditMode
    #Use advanced protection against ransomware
    Add-MpPreference -AttackSurfaceReductionRules_Ids "c1db55ab-c21a-4637-bb3f-a12568109d35" -AttackSurfaceReductionRules_Actions AuditMode
    #Block credential stealing from the Windows local security authority subsystem (lsass.exe)
    Add-MpPreference -AttackSurfaceReductionRules_Ids "9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2" -AttackSurfaceReductionRules_Actions AuditMode
    #Block process creations originating from PSExec and WMI commands
    Add-MpPreference -AttackSurfaceReductionRules_Ids "d1e49aac-8f56-4280-b9ba-993a6d77406c" -AttackSurfaceReductionRules_Actions AuditMode
    #Block untrusted and unsigned processes that run from USB
    Add-MpPreference -AttackSurfaceReductionRules_Ids "b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4" -AttackSurfaceReductionRules_Actions AuditMode
    #Block Office communication application from creating child processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "26190899-1602-49e8-8b27-eb1d0a1ce869" -AttackSurfaceReductionRules_Actions AuditMode
    #Block Adobe Reader from creating child processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c" -AttackSurfaceReductionRules_Actions AuditMode
    #Block persistence through WMI event subscription
    Add-MpPreference -AttackSurfaceReductionRules_Ids "e6db77e5-3df2-4cf1-b95a-636979351e5b" -AttackSurfaceReductionRules_Actions AuditMode
} else {
    Write-Output "Enabling Exploit Guard ASR rules and setting to suggested modes"
    #Block abuse of exploited vulnerable signed drivers     
    Set-MpPreference -AttackSurfaceReductionRules_Ids "56a863a9-875e-4185-98a7-b882c64b5ce5" -AttackSurfaceReductionRules_Actions Enabled
    #Block executable content from email client and webmail
    Add-MpPreference -AttackSurfaceReductionRules_Ids "BE9BA2D9-53EA-4CDC-84E5-9B1EEEE46550" -AttackSurfaceReductionRules_Actions Enabled
    #Block all Office applications from creating child processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "D4F940AB-401B-4EFC-AADC-AD5F3C50688A" -AttackSurfaceReductionRules_Actions Enabled
    #Block Office applications from creating executable content
    Add-MpPreference -AttackSurfaceReductionRules_Ids "3B576869-A4EC-4529-8536-B80A7769E899" -AttackSurfaceReductionRules_Actions Enabled
    #Block Office applications from injecting code into other processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "75668C1F-73B5-4CF0-BB93-3ECF5CB7CC84" -AttackSurfaceReductionRules_Actions Enabled
    #Block JavaScript or VBScript from launching downloaded executable content
    Add-MpPreference -AttackSurfaceReductionRules_Ids "D3E037E1-3EB8-44C8-A917-57927947596D" -AttackSurfaceReductionRules_Actions Enabled
    #Block execution of potentially obfuscated scripts
    Add-MpPreference -AttackSurfaceReductionRules_Ids "5BEB7EFE-FD9A-4556-801D-275E5FFC04CC" -AttackSurfaceReductionRules_Actions Enabled
    #Block Win32 API calls from Office macros
    Add-MpPreference -AttackSurfaceReductionRules_Ids "92E97FA1-2EDF-4476-BDD6-9DD0B4DDDC7B" -AttackSurfaceReductionRules_Actions Enabled
    #Block executable files from running unless they meet a prevalence, age, or trusted list criterion
    Add-MpPreference -AttackSurfaceReductionRules_Ids "01443614-cd74-433a-b99e-2ecdc07bfc25" -AttackSurfaceReductionRules_Actions Enabled
    #Use advanced protection against ransomware
    Add-MpPreference -AttackSurfaceReductionRules_Ids "c1db55ab-c21a-4637-bb3f-a12568109d35" -AttackSurfaceReductionRules_Actions Enabled
    #Block credential stealing from the Windows local security authority subsystem (lsass.exe)
    Add-MpPreference -AttackSurfaceReductionRules_Ids "9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2" -AttackSurfaceReductionRules_Actions AuditMode
    #Block process creations originating from PSExec and WMI commands
    Add-MpPreference -AttackSurfaceReductionRules_Ids "d1e49aac-8f56-4280-b9ba-993a6d77406c" -AttackSurfaceReductionRules_Actions Enabled
    #Block untrusted and unsigned processes that run from USB
    Add-MpPreference -AttackSurfaceReductionRules_Ids "b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4" -AttackSurfaceReductionRules_Actions Enabled
    #Block Office communication application from creating child processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "26190899-1602-49e8-8b27-eb1d0a1ce869" -AttackSurfaceReductionRules_Actions AuditMode
    #Block Adobe Reader from creating child processes
    Add-MpPreference -AttackSurfaceReductionRules_Ids "7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c" -AttackSurfaceReductionRules_Actions AuditMode
    #Block persistence through WMI event subscription
    Add-MpPreference -AttackSurfaceReductionRules_Ids "e6db77e5-3df2-4cf1-b95a-636979351e5b" -AttackSurfaceReductionRules_Actions Enabled
}

# Controlled Folder Access
if ($NoControlledFolders) {
    Write-Output "Skipping enabling Controlled folders"
} else {
    Write-Output "Enabling Controlled folders"
    Set-MpPreference -EnableControlledFolderAccess Enabled
}

# Check for Windows 10 version and apply respective settings
if (Check-IsWindows10-1709) {
    Write-Output "Updating Windows Defender Exploit Guard settings"
    Set-MpPreference -EnableNetworkProtection Enabled

    if ($false -eq (Test-Path ProcessMitigation.xml)) {
        Write-Output "Downloading Process Mitigation file from https://demo.wd.microsoft.com/Content/ProcessMitigation.xml"
        $url = 'https://demo.wd.microsoft.com/Content/ProcessMitigation.xml'
        Invoke-WebRequest $url -OutFile ProcessMitigation.xml
    }

    Write-Output "Enabling Exploit Protection"
    Set-ProcessMitigation -PolicyFilePath ProcessMitigation.xml
} else {
    Write-Output "Applying settings for Windows 10 version 1703 or earlier"
    SetRegistryKey -key MpCloudBlockLevel -value 2
    SetRegistryKey -key MpBafsExtendedTimeout -value 50
}

Write-Output "Settings update complete"
Write-Output "Output Windows Defender AV settings status"
Get-MpPreference

@silversword411
Copy link
Contributor

silversword411 commented Jul 27, 2024

For Defender Status 1.4 Added WarnOnMissedScans switch and date on scan stuff

<#
.SYNOPSIS
    This script monitors and reports the status of Windows Defender based on specified thresholds and historical data.

.DESCRIPTION
    Performs checks on malware threats, scan frequencies, and system health related to Windows Defender, outputting a detailed status report. The script can also exit with a status code indicating the presence of issues if the 'WarnOnMissedScans' parameter is used.

.PARAMETER DaysBack
    The number of days to look back for detecting threats and system events.

.PARAMETER FullScanThreshold
    The maximum acceptable age (in days) of the last full scan before it's considered outdated.

.PARAMETER QuickScanThreshold
    The maximum acceptable age (in days) of the last quick scan before it's considered outdated.

.PARAMETER SignatureUpdateThreshold
    The maximum acceptable age (in days) of the signature updates before they're considered outdated.

.PARAMETER WarnOnMissedScans
    If set, the script exits with a status code of 1 to indicate critical issues when scans or updates are not in compliance with set thresholds.

.EXAMPLE
    -DaysBack 30 -WarnOnMissedScans
    Checks the Defender status over the past 30 days and exits with code 1 if any compliance issues are found.

.NOTES
    v1 dinger initial release 2021
    v1.1 bdrayer Adding full message output if items found
    v1.2 added extra event IDs for ASR monitoring suggested by SDM216
    v1.3 dinger added Get-MpComputerStatus for comprehensive Defender health status, added parameters and replaced Event Viewer checks with PowerShell commands
    v1.4 silversword411 and cdp1337 adding never run output cleaning and WarnOnMissedScans param
#>

param (
    [int]$DaysBack = 1,
    [int]$FullScanThreshold = 7,
    [int]$QuickScanThreshold = 1,
    [int]$SignatureUpdateThreshold = 1,
    [switch]$WarnOnMissedScans
)

$ErrorActionPreference = 'SilentlyContinue'
$TimeSpan = (Get-Date).AddDays(-$DaysBack)

# Check for detected threats within the date range
$threats = Get-MpThreat | Where-Object { $_.DetectionTime -ge $TimeSpan }
$issueFound = $false

if ($threats) {
    Write-Output "Defender has found Threats"
    Write-Output "--------------------------------"
    $threats | Select-Object -ExpandProperty ThreatName -First 1
    $issueFound = $true
    Write-Output " "
}

# Check for ASR events in the Event Viewer
$asrEventFilter = @{
    LogName = 'Microsoft-Windows-Windows Defender/Operational'
    ID = '1122', '1123', '1124', '1125', '1126', '1127', '1128', '1129', '1130', '1131'
    StartTime = $TimeSpan
}

$asrEvents = Get-WinEvent -FilterHashtable $asrEventFilter

if ($asrEvents) {
    Write-Output "ASR Rule Hit Detected"
    Write-Output "--------------------------------"
    $asrEvents | Select-Object -ExpandProperty Message -First 1
    $issueFound = $true
    Write-Output " "
}

# Additional health status from Get-MpComputerStatus
$mpStatus = Get-MpComputerStatus

$defenderErrors = @()
if (-not $mpStatus.AMServiceEnabled) { $defenderErrors += "Antimalware Service is not enabled" }
if (-not $mpStatus.AntispywareEnabled) { $defenderErrors += "Antispyware is not enabled" }
if (-not $mpStatus.AntivirusEnabled) { $defenderErrors += "Antivirus is not enabled" }
if (-not $mpStatus.RealTimeProtectionEnabled) { $defenderErrors += "Real-time protection is not enabled" }
if (-not $mpStatus.NISEnabled) { $defenderErrors += "Network Inspection System is not enabled" }

if ($mpStatus.FullScanAge -gt $FullScanThreshold) { $defenderErrors += "Full scan has not been performed in the last $FullScanThreshold days" }
if ($mpStatus.QuickScanAge -gt $QuickScanThreshold) { $defenderErrors += "Quick scan has not been performed in the last $QuickScanThreshold days" }
if ($mpStatus.FullScanOverdue) { $defenderErrors += "Full scan is overdue" }
if ($mpStatus.QuickScanOverdue) { $defenderErrors += "Quick scan is overdue" }

# Check if signature updates are within the acceptable timeframe
if ($mpStatus.AntivirusSignatureAge -gt $SignatureUpdateThreshold) { $defenderErrors += "Antivirus signatures have not been updated in the last $SignatureUpdateThreshold days" }

if ($defenderErrors.Count -gt 0) {
    Write-Output "Issues found with Windows Defender status:"
    Write-Output "--------------------------------"
    $defenderErrors | ForEach-Object { Write-Output $_ }
    $issueFound = $true
    Write-Output " "

}

if (-not $issueFound) {
    Write-Output "Defender is Healthy"
    Write-Output " "
}

# Cleanup some variables for rendering
if ($mpStatus.FullScanAge -ge 2190) {
    # If never ran, will report an absurdly large number instead.
    $FullScanAge = "NEVER RAN"
}
else {
    $FullScanAge = "$($mpStatus.FullScanAge) Days ago"
}

if ($mpStatus.QuickScanAge -ge 2190) {
    # If never ran, will report an absurdly large number instead.
    $QuickScanAge = "NEVER RAN"
}
else {
    $QuickScanAge = "$($mpStatus.QuickScanAge) Days ago"
}

Write-Output "Windows Defender Status Report:"
Write-Output "--------------------------------"
Write-Output "Service Enabled: $($mpStatus.AMServiceEnabled)"
Write-Output "Antispyware Enabled: $($mpStatus.AntispywareEnabled)"
Write-Output "Antivirus Enabled: $($mpStatus.AntivirusEnabled)"
Write-Output "Full Scan Age: $FullScanAge"
Write-Output "Quick Scan Age: $QuickScanAge"
Write-Output "Real Time Protection Enabled: $($mpStatus.RealTimeProtectionEnabled)"
Write-Output "NIS Enabled: $($mpStatus.NISEnabled)"
Write-Output "Engine Version: $($mpStatus.AMEngineVersion)"
Write-Output "Signature Version: $($mpStatus.AntivirusSignatureVersion)"

if ($issueFound) {
    if ($WarnOnMissedScans) {
        $host.SetShouldExit(1)
    } else {
        Write-Output "Issues detected, but no exit code 1 due to WarnOnMissedScans not being set."
    }
} else {
    $host.SetShouldExit(0)
}

@dinger1986
Copy link
Contributor

dinger1986 commented Jul 27, 2024

why? already done, if you set days to 0 then it disables the check unless its felt it should be more obvious, just trying to keep it tidy and variables to a minimum. I have deleted the original as that might have been confusing, also deleted my v2 and left v3 below

@dinger1986
Copy link
Contributor

dinger1986 commented Jul 27, 2024

completed status script, any comments welcome

<#
.SYNOPSIS
    Defender - Status Report
.DESCRIPTION
    This script checks Windows Defender status for malware and antispyware reports and reports overall health status. By default, it checks the last 1 day, but this can be adjusted with parameters.
    The script also uses Get-MpComputerStatus to report on the overall health and status of Windows Defender.
.PARAMETER FullScanThreshold
    Specifies the threshold in days for the full scan age. If set to 0, the check is disabled.
.PARAMETER QuickScanThreshold
    Specifies the threshold in days for the quick scan age. If set to 0, the check is disabled.
.PARAMETER SignatureUpdateThreshold
    Specifies the threshold in days for the signature update age.
.PARAMETER CheckCloudBlockLevel
    Switch to check if the cloud block level is set to High Plus.
.PARAMETER CheckCloudExtendedTimeout
    Switch to check if the cloud extended timeout is set to 50.
.PARAMETER CheckPUAProtection
    Switch to check if protection against potentially unwanted applications is enabled.
.PARAMETER MonitorControlledFolderAccess
    Specifies whether to monitor the status of Controlled Folder Access.
.EXAMPLE
    -FullScanThreshold 7 -QuickScanThreshold 1 -SignatureUpdateThreshold 1 -CheckCloudBlockLevel -CheckCloudExtendedTimeout -CheckPUAProtection -MonitorControlledFolderAccess
    Checks the status of Windows Defender for the past 365 days, with thresholds for full scan, quick scan, and signature updates, and verifies the cloud block level, cloud extended timeout, PUA protection, and Controlled Folder Access.
.EXAMPLE
    -FullScanThreshold 0 -QuickScanThreshold 0 -SignatureUpdateThreshold 1
    Checks the status of Windows Defender for the past 30 days, but disables the checks for full and quick scan ages.
.NOTES
    v1 dinger initial release 2021
    v1.1 bdrayer Adding full message output if items found
    v1.2 added extra event IDs for ASR monitoring suggested by SDM216
    v1.3 dinger added Get-MpComputerStatus for comprehensive Defender health status, added parameters, replaced Event Viewer checks with PowerShell commands, added logic for "Never Ran" and exit codes
    v1.4 added additional checks for cloud block level, cloud extended timeout, and PUA protection
#>

param (
    [int]$FullScanThreshold = 0,
    [int]$QuickScanThreshold = 0,
    [int]$SignatureUpdateThreshold = 1,
    [switch]$CheckCloudBlockLevel,
    [switch]$CheckCloudExtendedTimeout,
    [switch]$CheckPUAProtection,
    [switch]$MonitorControlledFolderAccess
)

$ErrorActionPreference = 'SilentlyContinue'

# Check for detected threats within the date range
$threats = Get-MpThreat | Where-Object { $_.IsActive -eq $true }

if ($threats) {
    Write-Output "Defender has found Threats"
    Write-Output "--------------------------------"
    $threats | ForEach-Object { Write-Output $_.ThreatName }
    $issueFound = $true
    Write-Output " "
}

# Check for ASR events in the Event Viewer
$asrEventFilter = @{
    LogName = 'Microsoft-Windows-Windows Defender/Operational'
    ID = '1122', '1123', '1124', '1125', '1126', '1127', '1128', '1129', '1130', '1131'
    StartTime = $TimeSpan
}

$asrEvents = Get-WinEvent -FilterHashtable $asrEventFilter

if ($asrEvents) {
    Write-Output "ASR Rule Hit Detected"
    Write-Output "--------------------------------"
    $asrEvents | Select-Object -ExpandProperty Message -First 1
    $issueFound = $true
    Write-Output " "
}

# Additional health status from Get-MpComputerStatus
$mpStatus = Get-MpComputerStatus

$defenderErrors = @()
if (-not $mpStatus.AMServiceEnabled) { $defenderErrors += "Antimalware Service is not enabled" }
if (-not $mpStatus.AntispywareEnabled) { $defenderErrors += "Antispyware is not enabled" }
if (-not $mpStatus.AntivirusEnabled) { $defenderErrors += "Antivirus is not enabled" }
if (-not $mpStatus.RealTimeProtectionEnabled) { $defenderErrors += "Real-time protection is not enabled" }
if (-not $mpStatus.NISEnabled) { $defenderErrors += "Network Inspection System is not enabled" }

if ($FullScanThreshold -ne 0) {
    if ($mpStatus.FullScanAge -eq 4294967295 -or $mpStatus.FullScanAge -gt 2190) {
        $defenderErrors += "Full scan has Never Ran"
    } elseif ($mpStatus.FullScanAge -gt $FullScanThreshold) {
        $defenderErrors += "Full scan has not been performed in the last $FullScanThreshold days"
    }

    if ($mpStatus.FullScanOverdue) { $defenderErrors += "Full scan is overdue" }
}

if ($QuickScanThreshold -ne 0) {
    if ($mpStatus.QuickScanAge -eq 4294967295 -or $mpStatus.QuickScanAge -gt 2190) {
        $defenderErrors += "Quick scan has Never Ran"
    } elseif ($mpStatus.QuickScanAge -gt $QuickScanThreshold) {
        $defenderErrors += "Quick scan has not been performed in the last $QuickScanThreshold days"
    }

    if ($mpStatus.QuickScanOverdue) { $defenderErrors += "Quick scan is overdue" }
}

# Check if signature updates are within the acceptable timeframe
if ($mpStatus.AntivirusSignatureAge -gt $SignatureUpdateThreshold) { $defenderErrors += "Antivirus signatures have not been updated in the last $SignatureUpdateThreshold days" }

# Get preferences for additional checks
$mpPreference = Get-MpPreference

# Check if cloud block level is enabled
if ($CheckCloudBlockLevel) {
    if ($mpPreference.CloudBlockLevel -ne 2) {
        $defenderErrors += "Cloud block level is not set to High Plus"
    }
}

# Check if cloud extended timeout is enabled
if ($CheckCloudExtendedTimeout) {
    if ($mpPreference.CloudExtendedTimeout -ne 50) {
        $defenderErrors += "Cloud extended timeout is not set to 50"
    }
}

# Check if PUA protection is enabled
if ($CheckPUAProtection) {
    if ($mpPreference.PUAProtection -ne 1) {
        $defenderErrors += "PUA protection is not enabled"
    }
}

# Check additional settings using Get-MpPreference
if ($mpPreference.MAPSReporting -ne 2) { 
    $defenderErrors += "Cloud-delivered protection is not enabled" 
}

if ($mpPreference.DisableTamperProtection) { 
    $defenderErrors += "Tamper protection is not enabled" 
}

if ($mpPreference.SubmitSamplesConsent -ne 1) { 
    $defenderErrors += "Automatic sample submission is not enabled" 
}

# Check Controlled Folder Access if the parameter is set
if ($MonitorControlledFolderAccess -and $mpPreference.EnableControlledFolderAccess -ne 1) {
    $defenderErrors += "Controlled Folder Access is not enabled"
}

if ($defenderErrors.Count -gt 0) {
    Write-Output "Issues found with Windows Defender status:"
    Write-Output "--------------------------------"
    $defenderErrors | ForEach-Object { Write-Output $_ }
    $issueFound = $true
    Write-Output " "
}

if (-not $issueFound) {
    Write-Output "Defender is Healthy"
    Write-Output " "
}

Write-Output "Windows Defender Status Report:"
Write-Output "--------------------------------"
Write-Output "Service Enabled: $($mpStatus.AMServiceEnabled)"
Write-Output "Antispyware Enabled: $($mpStatus.AntispywareEnabled)"
Write-Output "Antivirus Enabled: $($mpStatus.AntivirusEnabled)"

# Display scan ages or 'Never Ran'
if ($FullScanThreshold -eq 0) {
    Write-Output "Full Scan Age: Disabled"
} elseif ($mpStatus.FullScanAge -eq 4294967295 -or $mpStatus.FullScanAge -gt 2190) {
    Write-Output "Full Scan Age: Never Ran"
} else {
    Write-Output "Full Scan Age: $($mpStatus.FullScanAge) Days ago"
}

if ($QuickScanThreshold -eq 0) {
    Write-Output "Quick Scan Age: Disabled"
} elseif ($mpStatus.QuickScanAge -eq 4294967295 -or $mpStatus.QuickScanAge -gt 2190) {
    Write-Output "Quick Scan Age: Never Ran"
} else {
    Write-Output "Quick Scan Age: $($mpStatus.QuickScanAge) Days ago"
}

Write-Output "Real Time Protection Enabled: $($mpStatus.RealTimeProtectionEnabled)"
Write-Output "NIS Enabled: $($mpStatus.NISEnabled)"
Write-Output "Engine Version: $($mpStatus.AMEngineVersion)"
Write-Output "Signature Version: $($mpStatus.AntivirusSignatureVersion)"

# Only output the additional settings if the corresponding checks were enabled and passed
if ($CheckCloudBlockLevel -and $mpPreference.CloudBlockLevel -eq 2) {
    Write-Output "Cloud Block Level: High Plus"
}
if ($CheckCloudExtendedTimeout -and $mpPreference.CloudExtendedTimeout -eq 50) {
    Write-Output "Cloud Extended Timeout: 50"
}
if ($CheckPUAProtection -and $mpPreference.PUAProtection -eq 1) {
    Write-Output "PUA Protection: Enabled"
}

if ($mpPreference.MAPSReporting -eq 2) {
    Write-Output "Cloud-delivered Protection Enabled"
}
if (-not $mpPreference.DisableTamperProtection) {
    Write-Output "Tamper Protection Enabled"
}
if ($mpPreference.SubmitSamplesConsent -eq 1) {
    Write-Output "Automatic Sample Submission Enabled"
}

if ($issueFound) {
    $host.SetShouldExit(1)
} else {
    $host.SetShouldExit(0)
}

@bbrendon
Copy link
Contributor Author

i feel like some of the settings you're looking at are somewhat subjective. like CloudExtendedTimeout, CloudBlockLevel, FullScanAge

I see some of it is optional as well which is fine.

I havent messed with Get-MpThreat much but I think for that you want (Get-MpThreat).IsActive.

@dinger1986
Copy link
Contributor

It's all stuff that the enable script enables so makes sense to check for it, ie full scans etc.

A lot does have params to enable/disable to make things easier and allow it to be customised.

I'll look at get threat and get that added to the script.

@dinger1986
Copy link
Contributor

yeah added get-mpthreat and works fine, any other comments?

Should we make checking for full and quick scans default to 0? So it doesnt alert on them

@silversword411
Copy link
Contributor

Should we make checking for full and quick scans default to 0? So it doesnt alert on them

Yes, that was one of the two changes I made above :)

@dinger1986
Copy link
Contributor

dinger1986 commented Jul 28, 2024

yeah I changed it all since then :) added in more stuff, if anyone wants to test it and give feedback that would be great

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants