WDAC Policy File by an Unusual Process

Identifies the creation of a Windows Defender Application Control (WDAC) policy file by an unusual process. Adversaries may use a specially crafted WDAC policy to restrict the execution of security products.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2025/02/28"
  3integration = ["endpoint", "windows", "m365_defender", "sentinel_one_cloud_funnel", "crowdstrike"]
  4maturity = "production"
  5updated_date = "2026/04/30"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Identifies the creation of a Windows Defender Application Control (WDAC) policy file by an unusual process. Adversaries
 11may use a specially crafted WDAC policy to restrict the execution of security products.
 12"""
 13from = "now-9m"
 14index = [
 15    "winlogbeat-*",
 16    "logs-endpoint.events.file-*",
 17    "logs-windows.sysmon_operational-*",
 18    "endgame-*",
 19    "logs-m365_defender.event-*",
 20    "logs-sentinel_one_cloud_funnel.*",
 21    "logs-crowdstrike.fdr*",
 22]
 23language = "eql"
 24license = "Elastic License v2"
 25name = "WDAC Policy File by an Unusual Process"
 26references = [
 27    "https://github.com/logangoins/Krueger/tree/main",
 28    "https://beierle.win/2024-12-20-Weaponizing-WDAC-Killing-the-Dreams-of-EDR/",
 29]
 30risk_score = 73
 31rule_id = "3aaf37f3-05a1-40a5-bb6e-e380c4f92c52"
 32severity = "high"
 33tags = [
 34    "Domain: Endpoint",
 35    "OS: Windows",
 36    "Use Case: Threat Detection",
 37    "Tactic: Defense Evasion",
 38    "Data Source: Elastic Endgame",
 39    "Resources: Investigation Guide",
 40    "Data Source: Elastic Defend",
 41    "Data Source: Sysmon",
 42    "Data Source: Microsoft Defender XDR",
 43    "Data Source: SentinelOne",
 44    "Data Source: Crowdstrike",
 45]
 46timestamp_override = "event.ingested"
 47type = "eql"
 48
 49query = '''
 50file where host.os.type == "windows" and event.action != "deletion" and
 51  file.extension : ("p7b", "cip") and
 52  file.path : (
 53    "?:\\Windows\\System32\\CodeIntegrity\\*.p7b",
 54    "?:\\Windows\\System32\\CodeIntegrity\\CiPolicies\\Active\\*.cip",
 55    "\\Device\\HarddiskVolume*\\Windows\\System32\\CodeIntegrity\\*.p7b",
 56    "\\Device\\HarddiskVolume*\\Windows\\System32\\CodeIntegrity\\CiPolicies\\Active\\*.cip"
 57  ) and
 58  not process.executable : (
 59    "C:\\Windows\\System32\\poqexec.exe",
 60    "\\Device\\HarddiskVolume*\\Windows\\System32\\poqexec.exe",
 61    "?:\\Windows\\WinSxS\\*\\TiWorker.exe",
 62    "?:\\Windows\\System32\\omadmclient.exe"
 63  ) and
 64  /* System / ntoskrnl.exe (PID 4) */
 65  not process.pid == 4
 66'''
 67
 68note = """## Triage and analysis
 69
 70### Investigating WDAC Policy File by an Unusual Process
 71
 72#### Possible investigation steps
 73
 74- Does the alert show active WDAC policy placement by a non-servicing writer?
 75  - Focus: `file.path`, `file.extension`, optional rename source `file.Ext.original.path`, writer `process.executable`, and `process.entity_id`. Separate "CodeIntegrity\\SiPolicy.p7b" base-policy placement from "CodeIntegrity\\CiPolicies\\Active\\*.cip" activation.
 76  - Implication: escalate when an active WDAC path is written or renamed by anything other than a recognized WDAC or Windows servicing component such as "poqexec.exe"; lower suspicion only when active path, original path when present, and writer align with one recognized WDAC rollout or servicing package.
 77- Is the writer a recognized deployment component or suspicious execution host?
 78  - Focus: `process.executable`, `process.command_line`, `process.hash.sha256`, `process.code_signature.subject_name`, and `process.code_signature.trusted`.
 79  - Implication: escalate when a script host, LOLBin, remote administration tool, or custom .NET assembly writes the policy, especially from temp, user, or share-backed paths; lower suspicion when the signer, hash, executable path, and command line all match a recognized WDAC deployment component.
 80- Does the launch chain and user context fit WDAC administration?
 81  - Focus: `process.parent.executable`, `process.parent.command_line`, and `user.id`.
 82  - Implication: escalate when the parent chain suggests in-memory tooling, service-control abuse, remote execution, or an unexpected admin/service identity; lower suspicion when parent context and `user.id` match the same recognized WDAC workflow for this host.
 83- Was the policy staged, renamed, or rapidly replaced before activation?
 84  - Focus: same-writer file events on `host.id` and `process.entity_id`: `file.path`, optional `file.Ext.original.path`, `file.size`, and `file.Ext.header_bytes` when populated. $investigate_3
 85  - Hint: file telemetry does not decode WDAC policy intent; preserve the written policy artifact for offline review before cleanup.
 86  - Implication: escalate when rename evidence shows the policy moving from a temp, user-writable, or share-backed location into the active Code Integrity path, or when repeated writes suggest last-minute replacement; lower suspicion when file movement stays inside one recognized rollout cache path and preserves the same writer. Missing rename or header detail is unresolved, not benign.
 87- Was the write followed by reboot preparation or activation behavior?
 88  - Why: Krueger-style WDAC abuse relies on the next boot to make the malicious policy block security tooling, so reboot preparation changes response urgency.
 89  - Focus: later process activity from the writer or its children on `host.id`: `process.name`, `process.executable`, and `process.command_line` for "shutdown.exe", restart tooling, service-control utilities, or custom reboot helpers. $investigate_4 $investigate_5
 90  - Implication: escalate when the writer or parent chain quickly prepares a reboot; absence of a visible reboot helper leaves activation timing unresolved, not benign.
 91- If local evidence is suspicious or unresolved, does the same writer or host pattern repeat?
 92  - Focus: related alerts for `user.id` and `host.id`, compared against `process.executable`, `process.hash.sha256`, active-policy `file.path`, and any staging `file.Ext.original.path`.
 93  - Hint: review Alerts associated with the user, host, and writer process. $investigate_0 $investigate_1 $investigate_2
 94  - Implication: broaden scope when the same writer, hash, user, or host pattern repeats across active WDAC placements; keep scope local only when the activity is confined to one host and one bounded change window.
 95- Based on active placement, writer identity, launch context, staging, reboot behavior, and recurrence, what disposition is supported?
 96  - Implication: escalate on suspicious writer identity, lineage, staging, reboot, or recurrence; close only when active path, writer, lineage, and any observed staging or reboot evidence bind one recognized WDAC rollout or servicing workflow; preserve the policy artifact and escalate when evidence stays mixed or incomplete.
 97
 98### False positive analysis
 99
100- WDAC management, servicing, security management, OEM device-control, or endpoint-hardening products can legitimately place active "SiPolicy.p7b" or "*.cip" policies. Confirm writer identity (`process.executable`, `process.hash.sha256`, `process.code_signature.subject_name`), launch context (`process.parent.executable`, `process.parent.command_line`, `user.id`), artifact path (`file.path`, and `file.Ext.original.path` when present), cache location, and reboot behavior all align with the same rollout or product writer. External change records or product inventory can corroborate only after those telemetry anchors align; contradictory identity, lineage, staging, or reboot evidence should not close as benign.
101- Bootable media creation, disk imaging, and backup tools (e.g., Rufus, Acronis, Windows Backup Engine) writing to non-system drives or volumes can trigger the rule when copying or restoring Windows installations that include CodeIntegrity policies. Check `file.path` drive letter or volume number against the host's system drive; writes to removable, secondary, or high-numbered volumes do not affect the host's WDAC protection.
102- Before creating an exception, require recurrence for the same stable writer identity, signer, parent workflow, `user.id`, `host.id`, and bounded active `file.path`. Avoid exceptions on `file.extension`, `file.name`, or the broad "CodeIntegrity" prefix alone because those conditions would suppress malicious lookalike policies.
103
104### Response and remediation
105
106- If confirmed benign, reverse any temporary containment and document the evidence that justified closure: writer identity, parent workflow, `user.id`, `file.path`, staging path, and reboot behavior all pointed to one recognized WDAC rollout or maintenance path. Create an exception only after that bounded pattern recurs.
107- If suspicious but unconfirmed, preserve the alert file event, the written "SiPolicy.p7b" or "*.cip" artifact, any rename-source evidence, the writer identity bundle, parent command context, `user.id`, and reboot-command evidence before destructive action. Apply reversible containment first, such as delaying an imminent reboot when operationally safe or temporarily restricting the writer, `user.id`, or management channel that introduced the policy.
108- If confirmed malicious, first export the preserved policy artifact and process/file evidence set. Then isolate the host when active policy placement by an unauthorized writer, repeated placement, or reboot preparation makes containment necessary. After evidence export and containment decisions, remove only the malicious WDAC policy artifacts, restore the known-good WDAC state, and review other hosts and users for the same writer, hash, active `file.path`, or staging pattern.
109- Post-incident hardening should restrict who can write to active Code Integrity paths, limit management channels that can copy policy files and reboot hosts, require controlled WDAC deployment records, and retain process and file telemetry around "CodeIntegrity" changes.
110"""
111
112setup = """## Setup
113
114This rule is designed for data generated by [Elastic Defend](https://www.elastic.co/security/endpoint-security), which provides native endpoint detection and response, along with event enrichments designed to work with our detection rules.
115
116Setup instructions: https://ela.st/install-elastic-defend
117
118### Additional data sources
119
120This rule also supports the following third-party data sources. For setup instructions, refer to the links below:
121
122- [CrowdStrike](https://ela.st/crowdstrike-integration)
123- [Microsoft Defender XDR](https://ela.st/m365-defender)
124- [SentinelOne Cloud Funnel](https://ela.st/sentinel-one-cloud-funnel)
125- [Sysmon Event ID 11 - File Create](https://ela.st/sysmon-event-11-setup)
126"""
127
128[rule.investigation_fields]
129field_names = [
130    "@timestamp",
131    "event.action",
132    "host.name",
133    "host.id",
134    "user.name",
135    "user.id",
136    "process.entity_id",
137    "process.executable",
138    "process.command_line",
139    "process.hash.sha256",
140    "process.code_signature.subject_name",
141    "process.code_signature.trusted",
142    "process.parent.executable",
143    "process.parent.command_line",
144    "file.path",
145]
146
147[transform]
148
149[[transform.investigate]]
150label = "Alerts associated with the user"
151description = ""
152providers = [
153  [
154    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
155    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
156  ]
157]
158relativeFrom = "now-48h/h"
159relativeTo = "now"
160
161[[transform.investigate]]
162label = "Alerts associated with the host"
163description = ""
164providers = [
165  [
166    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
167    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
168  ]
169]
170relativeFrom = "now-48h/h"
171relativeTo = "now"
172
173[[transform.investigate]]
174label = "Alerts associated with the writer process"
175description = ""
176providers = [
177  [
178    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
179    { excluded = false, field = "process.executable", queryType = "phrase", value = "{{process.executable}}", valueType = "string" }
180  ]
181]
182relativeFrom = "now-48h/h"
183relativeTo = "now"
184
185[[transform.investigate]]
186label = "File events for the writer process"
187description = ""
188providers = [
189  [
190    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
191    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
192    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
193  ]
194]
195relativeFrom = "now-1h"
196relativeTo = "now"
197
198[[transform.investigate]]
199label = "Process events for the writer process"
200description = ""
201providers = [
202  [
203    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
204    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
205    { excluded = false, field = "process.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
206  ]
207]
208relativeFrom = "now-1h"
209relativeTo = "now"
210
211[[transform.investigate]]
212label = "Child process events for the writer process"
213description = ""
214providers = [
215  [
216    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" },
217    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
218    { excluded = false, field = "process.parent.entity_id", queryType = "phrase", value = "{{process.entity_id}}", valueType = "string" }
219  ]
220]
221relativeFrom = "now-1h"
222relativeTo = "now"
223
224[[rule.threat]]
225framework = "MITRE ATT&CK"
226
227[[rule.threat.technique]]
228id = "T1562"
229name = "Impair Defenses"
230reference = "https://attack.mitre.org/techniques/T1562/"
231
232[[rule.threat.technique.subtechnique]]
233id = "T1562.001"
234name = "Disable or Modify Tools"
235reference = "https://attack.mitre.org/techniques/T1562/001/"
236
237[rule.threat.tactic]
238id = "TA0005"
239name = "Defense Evasion"
240reference = "https://attack.mitre.org/tactics/TA0005/"

Triage and analysis

Investigating WDAC Policy File by an Unusual Process

Possible investigation steps

  • Does the alert show active WDAC policy placement by a non-servicing writer?
    • Focus: file.path, file.extension, optional rename source file.Ext.original.path, writer process.executable, and process.entity_id. Separate "CodeIntegrity\SiPolicy.p7b" base-policy placement from "CodeIntegrity\CiPolicies\Active*.cip" activation.
    • Implication: escalate when an active WDAC path is written or renamed by anything other than a recognized WDAC or Windows servicing component such as "poqexec.exe"; lower suspicion only when active path, original path when present, and writer align with one recognized WDAC rollout or servicing package.
  • Is the writer a recognized deployment component or suspicious execution host?
    • Focus: process.executable, process.command_line, process.hash.sha256, process.code_signature.subject_name, and process.code_signature.trusted.
    • Implication: escalate when a script host, LOLBin, remote administration tool, or custom .NET assembly writes the policy, especially from temp, user, or share-backed paths; lower suspicion when the signer, hash, executable path, and command line all match a recognized WDAC deployment component.
  • Does the launch chain and user context fit WDAC administration?
    • Focus: process.parent.executable, process.parent.command_line, and user.id.
    • Implication: escalate when the parent chain suggests in-memory tooling, service-control abuse, remote execution, or an unexpected admin/service identity; lower suspicion when parent context and user.id match the same recognized WDAC workflow for this host.
  • Was the policy staged, renamed, or rapidly replaced before activation?
    • Focus: same-writer file events on host.id and process.entity_id: file.path, optional file.Ext.original.path, file.size, and file.Ext.header_bytes when populated. $investigate_3
    • Hint: file telemetry does not decode WDAC policy intent; preserve the written policy artifact for offline review before cleanup.
    • Implication: escalate when rename evidence shows the policy moving from a temp, user-writable, or share-backed location into the active Code Integrity path, or when repeated writes suggest last-minute replacement; lower suspicion when file movement stays inside one recognized rollout cache path and preserves the same writer. Missing rename or header detail is unresolved, not benign.
  • Was the write followed by reboot preparation or activation behavior?
    • Why: Krueger-style WDAC abuse relies on the next boot to make the malicious policy block security tooling, so reboot preparation changes response urgency.
    • Focus: later process activity from the writer or its children on host.id: process.name, process.executable, and process.command_line for "shutdown.exe", restart tooling, service-control utilities, or custom reboot helpers. $investigate_4 $investigate_5
    • Implication: escalate when the writer or parent chain quickly prepares a reboot; absence of a visible reboot helper leaves activation timing unresolved, not benign.
  • If local evidence is suspicious or unresolved, does the same writer or host pattern repeat?
    • Focus: related alerts for user.id and host.id, compared against process.executable, process.hash.sha256, active-policy file.path, and any staging file.Ext.original.path.
    • Hint: review Alerts associated with the user, host, and writer process. $investigate_0 $investigate_1 $investigate_2
    • Implication: broaden scope when the same writer, hash, user, or host pattern repeats across active WDAC placements; keep scope local only when the activity is confined to one host and one bounded change window.
  • Based on active placement, writer identity, launch context, staging, reboot behavior, and recurrence, what disposition is supported?
    • Implication: escalate on suspicious writer identity, lineage, staging, reboot, or recurrence; close only when active path, writer, lineage, and any observed staging or reboot evidence bind one recognized WDAC rollout or servicing workflow; preserve the policy artifact and escalate when evidence stays mixed or incomplete.

False positive analysis

  • WDAC management, servicing, security management, OEM device-control, or endpoint-hardening products can legitimately place active "SiPolicy.p7b" or "*.cip" policies. Confirm writer identity (process.executable, process.hash.sha256, process.code_signature.subject_name), launch context (process.parent.executable, process.parent.command_line, user.id), artifact path (file.path, and file.Ext.original.path when present), cache location, and reboot behavior all align with the same rollout or product writer. External change records or product inventory can corroborate only after those telemetry anchors align; contradictory identity, lineage, staging, or reboot evidence should not close as benign.
  • Bootable media creation, disk imaging, and backup tools (e.g., Rufus, Acronis, Windows Backup Engine) writing to non-system drives or volumes can trigger the rule when copying or restoring Windows installations that include CodeIntegrity policies. Check file.path drive letter or volume number against the host's system drive; writes to removable, secondary, or high-numbered volumes do not affect the host's WDAC protection.
  • Before creating an exception, require recurrence for the same stable writer identity, signer, parent workflow, user.id, host.id, and bounded active file.path. Avoid exceptions on file.extension, file.name, or the broad "CodeIntegrity" prefix alone because those conditions would suppress malicious lookalike policies.

Response and remediation

  • If confirmed benign, reverse any temporary containment and document the evidence that justified closure: writer identity, parent workflow, user.id, file.path, staging path, and reboot behavior all pointed to one recognized WDAC rollout or maintenance path. Create an exception only after that bounded pattern recurs.
  • If suspicious but unconfirmed, preserve the alert file event, the written "SiPolicy.p7b" or "*.cip" artifact, any rename-source evidence, the writer identity bundle, parent command context, user.id, and reboot-command evidence before destructive action. Apply reversible containment first, such as delaying an imminent reboot when operationally safe or temporarily restricting the writer, user.id, or management channel that introduced the policy.
  • If confirmed malicious, first export the preserved policy artifact and process/file evidence set. Then isolate the host when active policy placement by an unauthorized writer, repeated placement, or reboot preparation makes containment necessary. After evidence export and containment decisions, remove only the malicious WDAC policy artifacts, restore the known-good WDAC state, and review other hosts and users for the same writer, hash, active file.path, or staging pattern.
  • Post-incident hardening should restrict who can write to active Code Integrity paths, limit management channels that can copy policy files and reboot hosts, require controlled WDAC deployment records, and retain process and file telemetry around "CodeIntegrity" changes.

References

Related rules

to-top