Last night was one of those nights where security hardening did exactly what it is supposed to do, and also reminded us that “secure by default” can break perfectly legitimate workloads if you do not have the right troubleshooting muscle memory.
This post is a continuation and completion of my notes at MS Defender ASR Debugging, but written as a story from the field. It covers what happened, how we proved the root cause, and how we fixed it in a way that is compatible with a strict PCI DSS posture for one of my favourite customers.
Context: why ASR matters in PCI DSS environments
In a PCI DSS journey, endpoint hardening is not optional. If you operate Windows servers that are in scope (or adjacent to in scope systems), you want strong preventative controls that reduce attacker techniques. Attack Surface Reduction (ASR) rules are a powerful part of that story when they are enforced in Block mode and paired with proper monitoring, documentation, and exception handling.
- We want default deny behaviour for common abuse techniques.
- We also need an operational process for legitimate software that triggers those same detections.
- In PCI DSS work, the exception process must be controlled, minimal, and auditable.
Symptoms: “Action blocked by your organisation” and Error 5
The issue presented as a service that ran once and then stopped working after an update. Attempts to start it again produced:
- “Action blocked by your organisation”
- Service start failure, often showing as “Access is denied” (Error 5)
The affected service binary was:
C:\Program Files (x86)\Neuron\Waher.IoTGateway.Svc.exe
At first glance, this can look like permissions, service accounts, or local policy. It was none of those.
Important detail: the machine was enforced by MDE, not enrolled into Intune
This is where a lot of troubleshooting goes wrong. The server was not “managed by Intune” in the classic MDM sense. It was onboarded to Microsoft Defender for Endpoint (MDE). However, our tenant is configured so that ASR policies authored in Intune are picked up and enforced through MDE security settings management.
- That means the rules show up on the server and are enforced.
- It also means classic “sync now” workflows do not behave like a normal Intune Windows client.
- And in hardened setups, restarting
SenseorWinDefendcan be blocked by self protection and tamper protection.
Step 1: Confirm ASR rules are actually enforced in Block mode
First, we verified that ASR rules were present and set to Block. This removes guesswork about whether the policy applied at all.
Get-MpPreference | Select AttackSurfaceReductionRules_Ids, AttackSurfaceReductionRules_Actions
Then we printed them one by one to prove we had a full ruleset and that all were in action 1 which means Block.
$mp = Get-MpPreference
0..($mp.AttackSurfaceReductionRules_Ids.Count - 1) | ForEach-Object {
"{0} {1}" -f $mp.AttackSurfaceReductionRules_Ids[$_], $mp.AttackSurfaceReductionRules_Actions[$_]
}
Result: a complete list of ASR rules in Block mode, including the rule IDs that would later show up in the block events.
Step 2: confirm whether we already have ASR exclusions loaded
We then checked whether any ASR exclusions were already loaded on the machine. This is critical because normal Defender AV exclusions do not necessarily override ASR.
(Get-MpPreference).AttackSurfaceReductionRules_Exclusions
Step 3: go to the only source of truth: Defender Operational events
When ASR blocks, it writes evidence. The fastest way to identify exactly which rule triggered is the Defender Operational log. We pulled the relevant ASR events:
Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational" |
Where-Object { $_.Id -in 1121,1122,1123,1124,1125 } |
Select TimeCreated, Message |
Format-Table -Wrap
This immediately showed repeated blocks for our Neuron service binary, and importantly, it showed the ASR rule ID that triggered:
- ID: 01443614-CD74-433A-B99E-2ECDC07BFC25
- Path:
C:\Program Files (x86)\Neuron\Waher.IoTGateway.Svc.exe - Process Name often:
C:\Windows\System32\services.exe(Service Control Manager starting the service)
We also saw additional ASR activity that was unrelated to the Neuron service (for example LSASS related ASR detections), which is normal in hardened environments and a good reminder to separate the primary incident from the background noise.
Step 4: aggregate and quantify the evidence
To make this usable in an incident note, change request, or PCI DSS evidence pack, we parsed all ASR events and aggregated by unique rule ID, path, and process name. This turns a wall of logs into a summary you can hand to stakeholders.
$events = Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational" |
Where-Object { $_.Id -in 1121,1122,1123,1124,1125 } |
Select-Object TimeCreated, Id, Message
$parsed = foreach ($e in $events) {
$ruleId = [regex]::Match($e.Message, '(?im)^\s*ID:\s*([0-9A-Fa-f-]{36})\s*$').Groups[1].Value
$path = [regex]::Match($e.Message, '(?im)^\s*Path:\s*(.+?)\s*$').Groups[1].Value
$proc = [regex]::Match($e.Message, '(?im)^\s*Process Name:\s*(.+?)\s*$').Groups[1].Value
if ([string]::IsNullOrWhiteSpace($ruleId)) { $ruleId = "(missing)" }
if ([string]::IsNullOrWhiteSpace($path)) { $path = "(missing)" }
if ([string]::IsNullOrWhiteSpace($proc)) { $proc = "(missing)" }
[PSCustomObject]@{
TimeCreated = $e.TimeCreated
EventId = $e.Id
RuleId = $ruleId.ToUpper()
Path = $path
ProcessName = $proc
}
}
$parsed |
Group-Object RuleId, Path, ProcessName |
Sort-Object Count -Descending |
ForEach-Object {
$first = $_.Group | Sort-Object TimeCreated | Select-Object -First 1
$last = $_.Group | Sort-Object TimeCreated | Select-Object -Last 1
[PSCustomObject]@{
Count = $_.Count
RuleId = $first.RuleId
Path = $first.Path
ProcessName = $first.ProcessName
FirstSeen = $first.TimeCreated
LastSeen = $last.TimeCreated
}
} |
Format-Table -AutoSize
Count RuleId Path ProcessName FirstSeen LastSeen ----- --------------------------------------- ------------------------------------------------- -------------------------------------------- --------------------- --------------------- 7 01443614-CD74-433A-B99E-2ECDC07BFC25 C:\Program Files (x86)\Neuron\Waher.IoTGateway.Svc.exe C:\Windows\System32\services.exe 2026-02-05 19:19:36 2026-02-05 19:40:21 2 9E6C4E1F-7D60-472F-BA1A-A39EF669E4B2 C:\WindowsAzure\GuestAgent_2.7.41491.1183\WaAppAgent.exe C:\Windows\System32\lsass.exe 2026-02-05 19:33:36 2026-02-05 19:35:01 1 9E6C4E1F-7D60-472F-BA1A-A39EF669E4B2 C:\Windows\System32\svchost.exe C:\Windows\System32\lsass.exe 2026-02-05 19:33:36 2026-02-05 19:33:36
With this, we had a clean summary showing that the same ASR rule ID was repeatedly blocking the same binary, usually launched by services.exe.
By grouping on RuleId, you can immediately see which ASR rules are responsible for the majority of blocks. This is extremely useful when validating a baseline, identifying overly aggressive rules for a specific workload, or preparing justification for a controlled exception in a PCI DSS context.
# 2) Optional: counts per RuleId only
"`nCounts per RuleId:`n"
$parsed |
Group-Object RuleId |
Sort-Object Count -Descending |
Select-Object Count, Name |
Format-Table -AutoSize
Counts per RuleId: Count Name ----- --------------------------------------- 7 01443614-CD74-433A-B99E-2ECDC07BFC25 3 9E6C4E1F-7D60-472F-BA1A-A39EF669E4B2 1 5BEB7EFE-FD9A-4556-801D-275E5FFC04CC
By grouping on Path, you shift the perspective from “which rule fired” to “which component is affected”. This helps distinguish between a single misbehaving application and broad systemic issues, and it quickly highlights binaries that are repeatedly evaluated and blocked by Defender.
# 3) Optional: counts per Path only
"`nCounts per Path:`n"
$parsed |
Group-Object Path |
Sort-Object Count -Descending |
Select-Object Count, Name |
Format-Table -AutoSize
Counts per Path: Count Name ----- ------------------------------------------------------------- 7 C:\Program Files (x86)\Neuron\Waher.IoTGateway.Svc.exe 2 C:\WindowsAzure\GuestAgent_2.7.41491.1183\WaAppAgent.exe 1 C:\Windows\System32\svchost.exe 1 C:\Windows\System32\conhost.exe
Root cause: legitimate service binary blocked by ASR enforcement
The root cause was simple and brutal:
- The environment is hardened and runs a strict ASR baseline in Block mode.
- A legitimate vendor service binary was considered disallowed under one of those rules.
- The service start was blocked at execution time, which looks like “access denied” at the Windows service layer.
In other words, Defender was doing its job. Our job was to make a controlled, minimal exception that preserved the PCI DSS posture.
The fix: create a controlled ASR per rule exclusion for the Neuron folder
We chose a folder-based ASR exclusion for operational stability because updates can replace binaries in place. Excluding only a single file can lead to repeat incidents after the next update. The folder was:
C:\Program Files (x86)\Neuron\
Key point: this is not the same thing as a classic Defender AV exclusion. The exclusion must be applied as an ASR exclusion (per rule exclusions) so that ASR rules stop blocking the process in that path.
- We did not disable ASR globally.
- We did not weaken the baseline for the rest of the server fleet.
- We created a targeted exception with clear evidence and justification.
Applying the fix via Intune (ASR per rule exclusion)
Once the blocking ASR rule had been positively identified, the remediation was implemented centrally via Intune. Rather than weakening the baseline or disabling the rule, a targeted per-rule ASR exclusion was added for the affected application path. This was done under Endpoint security → Attack surface reduction by editing the active ASR policy and adding the Neuron installation directory to the per-rule exclusions section. Because the environment uses Defender for Endpoint security settings management, the policy was authored in Intune but enforced through Defender, even though the server itself was not Intune-enrolled. After policy propagation, the exclusion became visible locally via Get-MpPreference, ASR blocks for the service ceased, and the service could start normally while all other ASR rules remained enforced in Block mode. This approach preserves a strong PCI DSS posture while allowing explicitly approved software to operate.
Operational challenge: we could not restart Sense or WinDefend
In a hardened server setup, restarting Sense (MDE) and WinDefend can be blocked. That is expected. So instead, we used safe “poke the engine” techniques that do not require restarting protected services.
We used these to trigger cloud communication and content refresh:
& "$Env:ProgramFiles\Windows Defender\MpCmdRun.exe" -GetFiles
& "$Env:ProgramFiles\Windows Defender\MpCmdRun.exe" -SignatureUpdate
Note: in PowerShell, you need the call operator & when running an executable path, otherwise parameters can be parsed incorrectly.
Validation: prove the exclusion is loaded and the service starts
After propagation, we verified the ASR exclusion was loaded locally:
(Get-MpPreference).AttackSurfaceReductionRules_Exclusions
Then we attempted service start again and confirmed:
- No new ASR block events for
Waher.IoTGateway.Svc.exe - The service starts normally
- ASR baseline remains in Block mode for everything else
Lessons learned (and how we will apply this going forward)
- Always start with evidence. Do not guess. ASR always writes a trail in Defender Operational logs.
- Differentiate exclusion types. AV exclusions are not ASR exclusions. Controlled Folder Access is a separate system too.
- In PCI DSS, exceptions must be minimal and documented. Aggregated log evidence makes this easy.
- Plan for legitimate software friction. Vendor services in
Program Files (x86)can trip strict baselines. - Know your management plane. Intune authored policies can be enforced through MDE even when the server is not Intune enrolled.
Quick reference commands
-
List ASR rules and enforcement:
Get-MpPreference | Select AttackSurfaceReductionRules_Ids, AttackSurfaceReductionRules_Actions -
Show loaded ASR exclusions:
(Get-MpPreference).AttackSurfaceReductionRules_Exclusions -
Show ASR events and rule IDs that triggered:
Get-WinEvent -LogName "Microsoft-Windows-Windows Defender/Operational" | Where-Object { $_.Id -in 1121,1122,1123,1124,1125 } | Select TimeCreated, Message | Format-Table -Wrap -
Force content refresh without restarting protected services:
& "$Env:ProgramFiles\Windows Defender\MpCmdRun.exe" -GetFiles & "$Env:ProgramFiles\Windows Defender\MpCmdRun.exe" -SignatureUpdate
Closing note
This is exactly what a mature security program looks like in practice. Strong controls, real friction, evidence-driven troubleshooting, and a controlled exception process that keeps the baseline intact. This is how we move forward in a PCI DSS journey without sacrificing operations or security.| Rule Name | Rule GUID |
|---|---|
| Block abuse of exploited vulnerable signed drivers | 56a863a9-875e-4185-98a7-b882c64b5ce5 |
| Block Adobe Reader from creating child processes | 7674ba52-37eb-4a4f-a9a1-f0f9a1619a2c |
| Block all Office applications from creating child processes | d4f940ab-401b-4efc-aadc-ad5f3c50688a |
| Block credential stealing from the Windows local security authority subsystem (lsass.exe) | 9e6c4e1f-7d60-472f-ba1a-a39ef669e4b2 |
| Block executable content from email client and webmail | be9ba2d9-53ea-4cdc-84e5-9b1eeee46550 |
| Block executable files from running unless they meet a prevalence, age, or trusted list criterion* | 01443614-cd74-433a-b99e-2ecdc07bfc25 |
| Block execution of potentially obfuscated scripts | 5beb7efe-fd9a-4556-801d-275e5ffc04cc |
| Block JavaScript or VBScript from launching downloaded executable content | d3e037e1-3eb8-44c8-a917-57927947596d |
| Block Office applications from creating executable content | 3b576869-a4ec-4529-8536-b80a7769e899 |
| Block Office applications from injecting code into other processes | 75668c1f-73b5-4cf0-bb93-3ecf5cb7cc84 |
| Block Office communication application from creating child processes | 26190899-1602-49e8-8b27-eb1d0a1ce869 |
| Block persistence through WMI event subscription * File and folder exclusions not supported. |
e6db77e5-3df2-4cf1-b95a-636979351e5b |
| Block process creations originating from PSExec and WMI commands | d1e49aac-8f56-4280-b9ba-993a6d77406c |
| Block rebooting machine in Safe Mode | 33ddedf1-c6e0-47cb-833e-de6133960387 |
| Block untrusted and unsigned processes that run from USB | b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4 |
| Block use of copied or impersonated system tools | c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb |
| Block Webshell creation for Servers | a8f5898e-1dc8-49a9-9878-85004b8a61e6 |
| Block Win32 API calls from Office macros | 92e97fa1-2edf-4476-bdd6-9dd0b4dddc7b |
| Use advanced protection against ransomware | c1db55ab-c21a-4637-bb3f-a12568109d35 |