Potential Process Injection via PowerShell

Detects PowerShell scripts that combine Win32 APIs for allocation, protection, process access, or dynamic resolution with injection or execution APIs. Attackers use these API chains for potential process injection or in-memory payload execution.

Elastic rule (View on GitHub)

  1[metadata]
  2creation_date = "2021/10/14"
  3integration = ["windows"]
  4maturity = "production"
  5updated_date = "2026/04/30"
  6
  7[rule]
  8author = ["Elastic"]
  9description = """
 10Detects PowerShell scripts that combine Win32 APIs for allocation, protection, process access, or dynamic resolution with
 11injection or execution APIs. Attackers use these API chains for potential process injection or in-memory payload execution.
 12"""
 13false_positives = ["Controlled red-team, malware-analysis, detection-validation, or harness activity where script content, target process set, origin, user/host scope, and recovered launcher align."]
 14from = "now-9m"
 15index = ["logs-windows.powershell*", "winlogbeat-*"]
 16language = "kuery"
 17license = "Elastic License v2"
 18name = "Potential Process Injection via PowerShell"
 19references = [
 20    "https://github.com/EmpireProject/Empire/blob/master/data/module_source/management/Invoke-PSInject.ps1",
 21    "https://github.com/EmpireProject/Empire/blob/master/data/module_source/management/Invoke-ReflectivePEInjection.ps1",
 22    "https://github.com/BC-SECURITY/Empire/blob/master/empire/server/data/module_source/credentials/Invoke-Mimikatz.ps1",
 23    "https://www.elastic.co/security-labs/detect-credential-access",
 24]
 25risk_score = 73
 26rule_id = "2e29e96a-b67c-455a-afe4-de6183431d0d"
 27severity = "high"
 28tags = [
 29    "Domain: Endpoint",
 30    "OS: Windows",
 31    "Use Case: Threat Detection",
 32    "Tactic: Defense Evasion",
 33    "Tactic: Execution",
 34    "Resources: Investigation Guide",
 35    "Data Source: PowerShell Logs",
 36]
 37timestamp_override = "event.ingested"
 38type = "query"
 39
 40query = '''
 41event.category:process and host.os.type:windows and
 42  powershell.file.script_block_text : (
 43   (VirtualAlloc or VirtualAllocEx or VirtualProtect or LdrLoadDll or LoadLibrary or LoadLibraryA or
 44      LoadLibraryEx or GetProcAddress or OpenProcess or OpenProcessToken or AdjustTokenPrivileges) and
 45   (WriteProcessMemory or CreateRemoteThread or NtCreateThreadEx or CreateThread or QueueUserAPC or
 46      SuspendThread or ResumeThread or GetDelegateForFunctionPointer)
 47  ) and not 
 48  file.directory: (
 49    "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\SenseCM" or
 50    "C:\ProgramData\Microsoft\Windows Defender Advanced Threat Protection\Downloads"
 51  )
 52'''
 53
 54note = """## Triage and analysis
 55
 56### Investigating Potential Process Injection via PowerShell
 57
 58#### Possible investigation steps
 59
 60- Does the reconstructed script show an executable injection path or only isolated helper code?
 61  - Focus: reconstruct with `powershell.file.script_block_id`, `powershell.sequence`, and `powershell.total`, then review `powershell.file.script_block_text` and `powershell.file.script_block_length`. $investigate_2
 62  - Implication: escalate when the ordered script combines target access, memory allocation/protection, remote write, and thread/APC execution; lower concern when reconstruction proves only comments, imports, or unused helper functions in a bounded test script.
 63
 64- If endpoint process telemetry is available for this host, can you recover how PowerShell was launched?
 65  - Focus: same-host process starts for the PowerShell instance: `process.command_line`, `process.parent.executable`, `process.parent.command_line`, and `process.entity_id`. $investigate_3
 66  - Hint: recover the matching process via `host.id + process.pid` before interpreting `process.*` or `process.parent.*`; if absent, expand the same-host window. Missing endpoint process telemetry is unresolved, not benign.
 67  - Implication: escalate when the launcher is a document, browser, remote-management tool, scheduled task, encoded command, or user-writable path that does not fit the user; lower concern when launch chain and script origin match the same recognized lab or validation workflow.
 68
 69- What payload style does the reconstructed script stage?
 70  - Why: Empire-style loaders commonly patch or reflectively load PE bytes before injection, so payload form changes what to preserve and how urgently to respond.
 71  - Focus: `powershell.file.script_block_text` for byte arrays, Base64 PE blobs, reflective loader names, Mimikatz or credential-dumping commands, and PE/DLL paths or URLs. If endpoint telemetry is available, recover same-PID file and network/DNS events surrounding `@timestamp` to validate writes, staging, or retrieval. Missing file or network/DNS telemetry is unresolved, not benign. $investigate_4 $investigate_5
 72  - Implication: escalate when the script embeds or fetches shellcode/PE content, calls reflective loading, or references credential dumping; lower concern only when payload handling is absent and the code remains a controlled harness with no execution path.
 73
 74- Which target and access path does the script choose?
 75  - Focus: `powershell.file.script_block_text` for process-name or PID selectors, credential-rich or security-sensitive targets, token changes, broad access masks, and thread/APC primitives.
 76  - Implication: escalate when the script targets credential-rich, security-sensitive, user-facing, or many candidate processes and requests broad rights or debug privilege; lower concern when the target is one controlled lab process and the access path matches the recognized exercise.
 77
 78- Does the user, host, and script origin fit one controlled workflow?
 79  - Focus: `user.id`, `user.domain`, `host.id`, `host.name`, and `file.path` when present, interpreted with the reconstructed script and recovered launch chain.
 80  - Implication: escalate when the script is fileless or sourced from temp, profile, share, or staging paths under an unexpected account or host; lower concern only when user, host cohort, source path or fileless launcher pattern, target process, and payload choice all align with one controlled test or diagnostic workflow.
 81
 82- If local evidence remains suspicious or unresolved, does the same injection pattern appear elsewhere?
 83  - Focus: smallest stable suspicious pattern from `powershell.file.script_block_text`, such as loader function, target process, Mimikatz command, or distinctive payload string, plus `user.id` for actor scope. $investigate_0
 84  - Hint: run the `host.id` asset-scope check only after script logic, target/access path, and launch context remain suspicious or incomplete. $investigate_1
 85  - Implication: broaden when the same injection pattern or target selection appears on unrelated hosts or users; keep scope local when it stays confined to one recognized testing cohort or one unresolved host.
 86
 87- What disposition is supported?
 88  - Escalate on script logic plus payload, sensitive target, broad access, suspicious launcher, or spread; close only when telemetry proves one controlled workflow with no contradictory payload or target abuse; preserve artifacts and escalate when evidence is mixed or endpoint process recovery is unavailable.
 89
 90### False positive analysis
 91
 92- Authorized red-team, malware-analysis, or detection-validation exercises can trigger this rule when the reconstructed script injects only into controlled targets on lab or canary hosts. Require `powershell.file.script_block_text`, target process names, `file.path` when present, `user.id`, and `host.id` to align with the exercise. If endpoint process telemetry is available, recover via `host.id + process.pid` and require `process.command_line` plus `process.parent.executable` to align. Use calendars or change records only to document telemetry-aligned activity; do not close when script, target, or launcher evidence conflicts.
 93- Security-product validation or compatibility harnesses are rare; do not close unless the script stays limited to the product's expected target set and lacks embedded payloads, Mimikatz commands, privilege escalation, or broad target loops. If endpoint process telemetry is available, recover via `host.id + process.pid` and require `process.parent.executable` plus `process.command_line` to match the same controlled path or harness. Build exceptions only from the minimum confirmed pattern: stable script origin or distinctive harness substring, bounded target set, `host.id` or `user.id`, and recovered launcher when available; never exempt generic API names alone.
 94
 95### Response and remediation
 96
 97- If confirmed benign:
 98  - Document the reconstructed script, target process set, script origin, `user.id`, `host.id`, and the exercise or harness evidence that established the workflow before reversing temporary containment. If endpoint process telemetry was available and recovered via `host.id + process.pid`, include the recovered `process.command_line` and `process.parent.executable`. Build exceptions only from the minimum confirmed workflow pattern, not from generic API names.
 99- If suspicious but unconfirmed:
100  - Preserve the reconstructed `powershell.file.script_block_text`, every fragment tied to `powershell.file.script_block_id`, target process names or PIDs, payload strings, `file.path` when present, alert `process.pid`, `user.id`, and `host.id` before cleanup. If endpoint process telemetry was available and recovered via `host.id + process.pid`, also preserve `process.entity_id`, `process.command_line`, and `process.parent.command_line`.
101  - Apply reversible containment such as temporary network restrictions, heightened monitoring, or access limits on the affected `host.id` and `user.id`; escalate to host isolation only when host criticality permits or payload execution, sensitive target selection, or spread evidence raises confidence.
102- If confirmed malicious:
103  - Record the preserved evidence set and recovered process identifiers first when endpoint process telemetry was available. Then isolate the host when script logic, target selection, payload style, recovered launcher, or related-alert scope confirms malicious injection; if direct endpoint response is unavailable, hand off that evidence set to the team that can contain the host.
104  - Block confirmed malicious payload file paths and infrastructure indicators found during investigation, then review related hosts and users for the same loader, payload, target process, or recovered launcher pattern before eradication. Do not block on generic API names.
105  - Remove the malicious script, payload files, scheduled tasks, startup paths, or delivery artifacts identified during the investigation. Reset or investigate affected accounts when the payload, target process, or Mimikatz command indicates credential access, then remediate the path that launched PowerShell.
106- Post-incident hardening:
107  - Keep Script Block logging and the endpoint process telemetry needed for `host.id + process.pid` recovery enabled on the affected host class.
108  - Restrict PowerShell execution, Constrained Language Mode, or code-signing policy where appropriate for the host role, and record any telemetry gaps that limited reconstruction or process recovery.
109"""
110
111setup = """## Setup
112
113PowerShell Script Block Logging must be enabled to generate the events used by this rule (e.g., 4104).
114Setup instructions: https://ela.st/powershell-logging-setup
115"""
116
117[[rule.filters]]
118
119[rule.filters.meta]
120negate = true
121[rule.filters.query.wildcard."file.path"]
122case_insensitive = true
123value = "?:\\\\ProgramData\\\\Microsoft\\\\Windows Defender Advanced Threat Protection\\\\DataCollection\\\\*"
124
125[rule.investigation_fields]
126field_names = [
127    "@timestamp",
128    "user.name",
129    "user.id",
130    "user.domain",
131    "powershell.file.script_block_text",
132    "powershell.file.script_block_id",
133    "powershell.sequence",
134    "powershell.total",
135    "file.path",
136    "file.directory",
137    "file.name",
138    "process.pid",
139    "host.name",
140    "host.id",
141    "powershell.file.script_block_length"
142]
143
144[transform]
145
146[[transform.investigate]]
147label = "Alerts associated with the user"
148description = ""
149providers = [
150  [
151    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
152    { excluded = false, field = "user.id", queryType = "phrase", value = "{{user.id}}", valueType = "string" }
153  ]
154]
155relativeFrom = "now-48h/h"
156relativeTo = "now"
157
158[[transform.investigate]]
159label = "Alerts associated with the host"
160description = ""
161providers = [
162  [
163    { excluded = false, field = "event.kind", queryType = "phrase", value = "signal", valueType = "string" },
164    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
165  ]
166]
167relativeFrom = "now-48h/h"
168relativeTo = "now"
169
170[[transform.investigate]]
171label = "Script block fragments for the same script"
172description = ""
173providers = [
174  [
175    { excluded = false, field = "powershell.file.script_block_id", queryType = "phrase", value = "{{powershell.file.script_block_id}}", valueType = "string" },
176    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" }
177  ]
178]
179relativeFrom = "now-1h"
180relativeTo = "now"
181
182[[transform.investigate]]
183label = "Process events for the PowerShell instance"
184description = ""
185providers = [
186  [
187    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" },
188    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
189    { excluded = false, field = "event.category", queryType = "phrase", value = "process", valueType = "string" }
190  ]
191]
192relativeFrom = "now-1h"
193relativeTo = "now"
194
195[[transform.investigate]]
196label = "File events for the PowerShell PID"
197description = ""
198providers = [
199  [
200    { excluded = false, field = "event.category", queryType = "phrase", value = "file", valueType = "string" },
201    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
202    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
203  ]
204]
205relativeFrom = "now-1h"
206relativeTo = "now"
207
208[[transform.investigate]]
209label = "Network and DNS events for the PowerShell PID"
210description = ""
211providers = [
212  [
213    { excluded = false, field = "event.category", queryType = "phrase", value = "network", valueType = "string" },
214    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
215    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
216  ],
217  [
218    { excluded = false, field = "event.category", queryType = "phrase", value = "dns", valueType = "string" },
219    { excluded = false, field = "host.id", queryType = "phrase", value = "{{host.id}}", valueType = "string" },
220    { excluded = false, field = "process.pid", queryType = "phrase", value = "{{process.pid}}", valueType = "string" }
221  ]
222]
223relativeFrom = "now-1h"
224relativeTo = "now"
225
226[[rule.threat]]
227framework = "MITRE ATT&CK"
228
229[[rule.threat.technique]]
230id = "T1055"
231name = "Process Injection"
232reference = "https://attack.mitre.org/techniques/T1055/"
233
234[[rule.threat.technique.subtechnique]]
235id = "T1055.001"
236name = "Dynamic-link Library Injection"
237reference = "https://attack.mitre.org/techniques/T1055/001/"
238
239[[rule.threat.technique.subtechnique]]
240id = "T1055.002"
241name = "Portable Executable Injection"
242reference = "https://attack.mitre.org/techniques/T1055/002/"
243
244[[rule.threat.technique.subtechnique]]
245id = "T1055.003"
246name = "Thread Execution Hijacking"
247reference = "https://attack.mitre.org/techniques/T1055/003/"
248
249[[rule.threat.technique.subtechnique]]
250id = "T1055.004"
251name = "Asynchronous Procedure Call"
252reference = "https://attack.mitre.org/techniques/T1055/004/"
253
254[rule.threat.tactic]
255id = "TA0005"
256name = "Defense Evasion"
257reference = "https://attack.mitre.org/tactics/TA0005/"
258
259[[rule.threat]]
260framework = "MITRE ATT&CK"
261
262[[rule.threat.technique]]
263id = "T1059"
264name = "Command and Scripting Interpreter"
265reference = "https://attack.mitre.org/techniques/T1059/"
266
267[[rule.threat.technique.subtechnique]]
268id = "T1059.001"
269name = "PowerShell"
270reference = "https://attack.mitre.org/techniques/T1059/001/"
271
272[[rule.threat.technique]]
273id = "T1106"
274name = "Native API"
275reference = "https://attack.mitre.org/techniques/T1106/"
276
277[rule.threat.tactic]
278id = "TA0002"
279name = "Execution"
280reference = "https://attack.mitre.org/tactics/TA0002/"

Triage and analysis

Investigating Potential Process Injection via PowerShell

Possible investigation steps

  • Does the reconstructed script show an executable injection path or only isolated helper code?

    • Focus: reconstruct with powershell.file.script_block_id, powershell.sequence, and powershell.total, then review powershell.file.script_block_text and powershell.file.script_block_length. $investigate_2
    • Implication: escalate when the ordered script combines target access, memory allocation/protection, remote write, and thread/APC execution; lower concern when reconstruction proves only comments, imports, or unused helper functions in a bounded test script.
  • If endpoint process telemetry is available for this host, can you recover how PowerShell was launched?

    • Focus: same-host process starts for the PowerShell instance: process.command_line, process.parent.executable, process.parent.command_line, and process.entity_id. $investigate_3
    • Hint: recover the matching process via host.id + process.pid before interpreting process.* or process.parent.*; if absent, expand the same-host window. Missing endpoint process telemetry is unresolved, not benign.
    • Implication: escalate when the launcher is a document, browser, remote-management tool, scheduled task, encoded command, or user-writable path that does not fit the user; lower concern when launch chain and script origin match the same recognized lab or validation workflow.
  • What payload style does the reconstructed script stage?

    • Why: Empire-style loaders commonly patch or reflectively load PE bytes before injection, so payload form changes what to preserve and how urgently to respond.
    • Focus: powershell.file.script_block_text for byte arrays, Base64 PE blobs, reflective loader names, Mimikatz or credential-dumping commands, and PE/DLL paths or URLs. If endpoint telemetry is available, recover same-PID file and network/DNS events surrounding @timestamp to validate writes, staging, or retrieval. Missing file or network/DNS telemetry is unresolved, not benign. $investigate_4 $investigate_5
    • Implication: escalate when the script embeds or fetches shellcode/PE content, calls reflective loading, or references credential dumping; lower concern only when payload handling is absent and the code remains a controlled harness with no execution path.
  • Which target and access path does the script choose?

    • Focus: powershell.file.script_block_text for process-name or PID selectors, credential-rich or security-sensitive targets, token changes, broad access masks, and thread/APC primitives.
    • Implication: escalate when the script targets credential-rich, security-sensitive, user-facing, or many candidate processes and requests broad rights or debug privilege; lower concern when the target is one controlled lab process and the access path matches the recognized exercise.
  • Does the user, host, and script origin fit one controlled workflow?

    • Focus: user.id, user.domain, host.id, host.name, and file.path when present, interpreted with the reconstructed script and recovered launch chain.
    • Implication: escalate when the script is fileless or sourced from temp, profile, share, or staging paths under an unexpected account or host; lower concern only when user, host cohort, source path or fileless launcher pattern, target process, and payload choice all align with one controlled test or diagnostic workflow.
  • If local evidence remains suspicious or unresolved, does the same injection pattern appear elsewhere?

    • Focus: smallest stable suspicious pattern from powershell.file.script_block_text, such as loader function, target process, Mimikatz command, or distinctive payload string, plus user.id for actor scope. $investigate_0
    • Hint: run the host.id asset-scope check only after script logic, target/access path, and launch context remain suspicious or incomplete. $investigate_1
    • Implication: broaden when the same injection pattern or target selection appears on unrelated hosts or users; keep scope local when it stays confined to one recognized testing cohort or one unresolved host.
  • What disposition is supported?

    • Escalate on script logic plus payload, sensitive target, broad access, suspicious launcher, or spread; close only when telemetry proves one controlled workflow with no contradictory payload or target abuse; preserve artifacts and escalate when evidence is mixed or endpoint process recovery is unavailable.

False positive analysis

  • Authorized red-team, malware-analysis, or detection-validation exercises can trigger this rule when the reconstructed script injects only into controlled targets on lab or canary hosts. Require powershell.file.script_block_text, target process names, file.path when present, user.id, and host.id to align with the exercise. If endpoint process telemetry is available, recover via host.id + process.pid and require process.command_line plus process.parent.executable to align. Use calendars or change records only to document telemetry-aligned activity; do not close when script, target, or launcher evidence conflicts.
  • Security-product validation or compatibility harnesses are rare; do not close unless the script stays limited to the product's expected target set and lacks embedded payloads, Mimikatz commands, privilege escalation, or broad target loops. If endpoint process telemetry is available, recover via host.id + process.pid and require process.parent.executable plus process.command_line to match the same controlled path or harness. Build exceptions only from the minimum confirmed pattern: stable script origin or distinctive harness substring, bounded target set, host.id or user.id, and recovered launcher when available; never exempt generic API names alone.

Response and remediation

  • If confirmed benign:
    • Document the reconstructed script, target process set, script origin, user.id, host.id, and the exercise or harness evidence that established the workflow before reversing temporary containment. If endpoint process telemetry was available and recovered via host.id + process.pid, include the recovered process.command_line and process.parent.executable. Build exceptions only from the minimum confirmed workflow pattern, not from generic API names.
  • If suspicious but unconfirmed:
    • Preserve the reconstructed powershell.file.script_block_text, every fragment tied to powershell.file.script_block_id, target process names or PIDs, payload strings, file.path when present, alert process.pid, user.id, and host.id before cleanup. If endpoint process telemetry was available and recovered via host.id + process.pid, also preserve process.entity_id, process.command_line, and process.parent.command_line.
    • Apply reversible containment such as temporary network restrictions, heightened monitoring, or access limits on the affected host.id and user.id; escalate to host isolation only when host criticality permits or payload execution, sensitive target selection, or spread evidence raises confidence.
  • If confirmed malicious:
    • Record the preserved evidence set and recovered process identifiers first when endpoint process telemetry was available. Then isolate the host when script logic, target selection, payload style, recovered launcher, or related-alert scope confirms malicious injection; if direct endpoint response is unavailable, hand off that evidence set to the team that can contain the host.
    • Block confirmed malicious payload file paths and infrastructure indicators found during investigation, then review related hosts and users for the same loader, payload, target process, or recovered launcher pattern before eradication. Do not block on generic API names.
    • Remove the malicious script, payload files, scheduled tasks, startup paths, or delivery artifacts identified during the investigation. Reset or investigate affected accounts when the payload, target process, or Mimikatz command indicates credential access, then remediate the path that launched PowerShell.
  • Post-incident hardening:
    • Keep Script Block logging and the endpoint process telemetry needed for host.id + process.pid recovery enabled on the affected host class.
    • Restrict PowerShell execution, Constrained Language Mode, or code-signing policy where appropriate for the host role, and record any telemetry gaps that limited reconstruction or process recovery.

References

Related rules

to-top