[GH-ISSUE #242] Defender Status - script lies. Defender NOT Healthy #313

Open
opened 2026-03-14 01:13:33 +03:00 by kerem · 14 comments
Owner

Originally created by @bbrendon on GitHub (Jul 26, 2024).
Original GitHub issue: https://github.com/amidaware/community-scripts/issues/242

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.

github.com/amidaware/community-scripts@116e51dcfa/scripts/Win_Defender_Status_Report.ps1 (L35)

Originally created by @bbrendon on GitHub (Jul 26, 2024). Original GitHub issue: https://github.com/amidaware/community-scripts/issues/242 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. https://github.com/amidaware/community-scripts/blob/116e51dcfa448e37fee787c22f5300dd4c636619/scripts/Win_Defender_Status_Report.ps1#L35
Author
Owner

@dinger1986 commented on GitHub (Jul 26, 2024):

I'll look into that

<!-- gh-comment-id:2253636089 --> @dinger1986 commented on GitHub (Jul 26, 2024): I'll look into that
Author
Owner

@silversword411 commented on GitHub (Jul 27, 2024):

I wouldn't usually create an issue in community scripts

Why not?

<!-- gh-comment-id:2253705767 --> @silversword411 commented on GitHub (Jul 27, 2024): > I wouldn't usually create an issue in community scripts Why not?
Author
Owner

@cdp1337 commented on GitHub (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.

<!-- gh-comment-id:2254160828 --> @cdp1337 commented on GitHub (Jul 27, 2024): Before `Write-Output "Windows Defender Status Report:"`: ```powershell # 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: ```powershell 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.
Author
Owner

@dinger1986 commented on GitHub (Jul 27, 2024):

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?

<!-- gh-comment-id:2254162708 --> @dinger1986 commented on GitHub (Jul 27, 2024): 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?
Author
Owner

@cdp1337 commented on GitHub (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.

<!-- gh-comment-id:2254164771 --> @cdp1337 commented on GitHub (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.
Author
Owner

@dinger1986 commented on GitHub (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
<!-- gh-comment-id:2254181879 --> @dinger1986 commented on GitHub (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 ```
Author
Owner

@silversword411 commented on GitHub (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)
}

<!-- gh-comment-id:2254207029 --> @silversword411 commented on GitHub (Jul 27, 2024): For Defender Status 1.4 Added WarnOnMissedScans switch and date on scan stuff ```ps <# .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) } ```
Author
Owner

@dinger1986 commented on GitHub (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

<!-- gh-comment-id:2254212099 --> @dinger1986 commented on GitHub (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
Author
Owner

@dinger1986 commented on GitHub (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)
}
<!-- gh-comment-id:2254216197 --> @dinger1986 commented on GitHub (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) } ```
Author
Owner

@bbrendon commented on GitHub (Jul 27, 2024):

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.

<!-- gh-comment-id:2254282456 --> @bbrendon commented on GitHub (Jul 27, 2024): 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.
Author
Owner

@dinger1986 commented on GitHub (Jul 28, 2024):

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.

<!-- gh-comment-id:2254580221 --> @dinger1986 commented on GitHub (Jul 28, 2024): 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.
Author
Owner

@dinger1986 commented on GitHub (Jul 28, 2024):

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

<!-- gh-comment-id:2254616866 --> @dinger1986 commented on GitHub (Jul 28, 2024): 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
Author
Owner

@silversword411 commented on GitHub (Jul 28, 2024):

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 :)

<!-- gh-comment-id:2254628434 --> @silversword411 commented on GitHub (Jul 28, 2024): > 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 :)
Author
Owner

@dinger1986 commented on GitHub (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

<!-- gh-comment-id:2254640318 --> @dinger1986 commented on GitHub (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 in to join this conversation.
No milestone
No project
No assignees
1 participant
Notifications
Due date
The due date is invalid or out of range. Please use the format "yyyy-mm-dd".

No due date set.

Dependencies

No dependencies set.

Reference
starred/community-scripts#313
No description provided.