Detection rules › YARA-L
YARA-L rules: 0p
Domain Prevalence
#Detects DNS events querying domains that have a low rolling max prevalence.
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 22: DNSEvent (DNS query) |
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule domain_prevalence {
meta:
author = "Google Cloud Security"
description = "Detects DNS events querying domains that have a low rolling max prevalence."
rule_id = "mr_cf5dd851-d7e9-42b8-baf9-f4527ab61bf3"
rule_name = "Domain Prevalence"
type = "alert"
tags = "prevalence"
data_source = "extrahop, tanium, microsoft sysmon, gcp dns, crowdstrike"
severity = "Low"
priority = "Low"
events:
$dns.metadata.event_type = "NETWORK_DNS"
$dns.network.dns.questions.name = $domain
// derived from events ingested by Chronicle
$prevalence.graph.metadata.entity_type = "DOMAIN_NAME"
$prevalence.graph.metadata.source_type = "DERIVED_CONTEXT"
$prevalence.graph.entity.hostname = $domain
$prevalence.graph.entity.domain.prevalence.day_count = 10
$prevalence.graph.entity.domain.prevalence.rolling_max <= 3
$prevalence.graph.entity.domain.prevalence.rolling_max > 0
match:
$domain over 5m
outcome:
$risk_score = max(35)
$event_count = count_distinct($dns.metadata.id)
$network_dns_questions_name = array_distinct($dns.network.dns.questions.name)
$network_dns_answers_data = array_distinct($dns.network.dns.answers.data)
// added to populate alert graph with additional context
$principal_ip = array_distinct($dns.principal.ip)
$target_ip = array_distinct($dns.target.ip)
$principal_process_pid = array_distinct($dns.principal.process.pid)
$principal_process_file_full_path = array_distinct($dns.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($dns.principal.process.product_specific_process_id)
$principal_process_command_line = array_distinct($dns.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($dns.principal.process.file.sha256)
$principal_process_parent_process_product_specific_process_id = array_distinct($dns.principal.process.parent_process.product_specific_process_id)
$principal_user_userid = array_distinct($dns.principal.user.userid)
condition:
$dns and $prevalence
}
YARA-L Rule Structure
Condition
Fires when at least one $dns event in the 5m window and $prevalence matches entity context.
Events
$dns
$prevalence
graph.metadata.entity_type = "DOMAIN_NAME"graph.metadata.source_type = "DERIVED_CONTEXT"graph.entity.domain.prevalence.day_count = "10"graph.entity.domain.prevalence.rolling_max <= "3"graph.entity.domain.prevalence.rolling_max > "0"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(35) |
event_count | count_distinct($dns.metadata.id) |
network_dns_questions_name | array_distinct($dns.network.dns.questions.name) |
network_dns_answers_data | array_distinct($dns.network.dns.answers.data) |
principal_ip | array_distinct($dns.principal.ip) |
target_ip | array_distinct($dns.target.ip) |
principal_process_pid | array_distinct($dns.principal.process.pid) |
principal_process_file_full_path | array_distinct($dns.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($dns.principal.process.product_specific_process_id) |
principal_process_command_line | array_distinct($dns.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($dns.principal.process.file.sha256) |
principal_process_parent_process_product_specific_process_id | array_distinct($dns.principal.process.parent_process.product_specific_process_id) |
principal_user_userid | array_distinct($dns.principal.user.userid) |
Entra ID Recently Created User Assigned an Entra ID Role
#Detect users who are newly created and then immediately assigned administrator level roles
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Persistence |
References
Telemetry Coverage
| Platform | Record / event type |
|---|---|
| Azure | Add member to role |
| Azure | Add user |
Rules Detecting the Same Action
These rules filter on the same operation.
- [Entra ID] Application Assigned Administrator Permissions Immediately After Obtaining Role Management Permissions (Kusto)
- [Entra ID] Authentication Method Changed for Privileged Account (Kusto)
- [Entra ID] Mass Privileged Role Change Activity Detected (Kusto)
- [Entra ID] Privilege Elevation Request Denied (Kusto)
- [Entra ID] Privileged Role Assigned to a New User (Kusto)
- [Entra ID] Privileged Role Assigned to User (Kusto)
- Account Created and Deleted in Short Timeframe (Kusto)
- Account Created And Deleted Within A Close Time Frame (Sigma)
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule entra_id_recently_created_user_assigned_entra_id_roles {
meta:
author = "Google Cloud Security"
description = "Detect users who are newly created and then immediately assigned administrator level roles"
rule_id = "mr_ab6067cd-b8a0-49f7-9efb-8a9b3b096a49"
rule_name = "Entra ID Recently Created User Assigned an Entra ID Role"
tactic = "TA0003"
technique = "T1098.003"
assumption = "The list msgraph_watchlist_roles_guid is popualted with admin role guids, ie 62e90394-69f5-4237-9190-012177145e10"
reference = "https://learn.microsoft.com/en-us/entra/identity/role-based-access-control/permissions-reference"
type = "alert"
platform = "azure"
data_source = "azure ad"
severity = "High"
priority = "High"
events:
(
$create.metadata.event_type = "USER_CREATION" and
$create.metadata.product_event_type = "Add user" and
$create.metadata.product_name = "Azure AD Directory Audit" and
$create.metadata.vendor_name = "Microsoft" and
$create.security_result.action = "ALLOW" and
$create.principal.user.userid = $principal_userid and
$create.target.user.userid = $target_userid
)
$create.metadata.event_timestamp.seconds < $role.metadata.event_timestamp.seconds
(
$role.metadata.event_type = "USER_CHANGE_PERMISSIONS" and
$role.metadata.product_event_type = "Add member to role" and
$role.metadata.product_name = "Azure AD Directory Audit" and
$role.metadata.vendor_name = "Microsoft" and
$role.security_result.action = "ALLOW" and
//To detect on specific roles, they can be added to a reference list and the following line uncommented
//$role.target.resource.attribute.labels["Role.Role.TemplateId"] in %msgraph_watchlist_roles_guid and
$role.principal.user.userid = $principal_userid and
re.replace($role.target.user.userid, `@.*$`, "") = $target_userid
)
match:
$principal_userid, $target_userid over 30m
outcome:
$risk_score = 85
$principal_county_region = array_distinct(strings.concat($create.principal.location.city," ",$create.principal.location.state," ",$create.principal.location.country_or_region))
$assigned_role = array_distinct($role.target.user.title)
$assigned_role_guid = array_distinct($role.target.resource.attribute.labels["Role.TemplateId"])
condition:
$create and $role
}
YARA-L Rule Structure
Condition
Fires when at least one $create event in the 30m window and at least one $role event in the 30m window.
Events
$create
metadata.product_event_type = "Add user"security_result.action = "ALLOW"
$role
metadata.product_event_type = "Add member to role"security_result.action = "ALLOW"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | 85 |
principal_county_region | array_distinct(strings.concat($create.principal.location.city," ",$create.principal.location.state," ",$create.principal.location.country_or_region)) |
assigned_role | array_distinct($role.target.user.title) |
assigned_role_guid | array_distinct($role.target.resource.attribute.labels["Role.TemplateId"]) |
File Download Via Windows Defender MpCmpRun.EXE
#Detects the use of Windows Defender MpCmdRun.EXE to download files
Known False Positives
- Unknown
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Command & Control |
References
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule file_download_via_windows_defender_mpcmdrun_exe {
meta:
author = "Matthew Matchen"
description = "Detects the use of Windows Defender MpCmdRun.EXE to download files"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_mpcmdrun_download_arbitrary_file.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "File Download Via Windows Defender MpCmpRun.EXE"
sigma_uuid = "46123129-1024-423e-9fae-43af4a0fa9a5"
sigma_status = "test"
rule_id = "mr_22c73791-b666-436e-b584-f14afb3cf6d5"
tactic = "TA0011"
technique = "T1105"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Unknown"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
$process.src.process.file.full_path = "mpcmdrun.exe" nocase or
re.regex($process.target.process.file.full_path, `\\mpcmdrun\.exe$`) nocase or
strings.contains(strings.to_lower($process.target.process.command_line), "mpcmdrun.exe") or
$process.target.asset.software.description = "Microsoft Malware Protection Command Line Utility" nocase
)
(
strings.contains(strings.to_lower($process.target.process.command_line), "downloadfile") and
strings.contains(strings.to_lower($process.target.process.command_line), "url")
)
$process.principal.hostname = $hostname
match:
$hostname over 1m
outcome:
//example usage of specifying test user and hostname to adjust risk score
$risk_score = max(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15))
$principal_process_pid = array_distinct($process.principal.process.pid)
$principal_process_command_line = array_distinct($process.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($process.principal.process.file.full_path)
$principal_process_product_specfic_process_id = array_distinct($process.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specfic_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($process.target.process.pid)
$target_process_command_line = array_distinct($process.target.process.command_line)
$target_process_file_sha256 = array_distinct($process.target.process.file.sha256)
$target_process_file_full_path = array_distinct($process.target.process.file.full_path)
$target_process_product_specfic_process_id = array_distinct($process.target.process.product_specific_process_id)
$principal_user_userid = array_distinct($process.principal.user.userid)
$log_type = array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type))
condition:
$process
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 1m window.
Events
$process
src.process.file.full_path = "mpcmdrun.exe"target.process.file.full_path matches "\\mpcmdrun\.exe$"target.process.command_line contains "mpcmdrun.exe"target.asset.software.description = "Microsoft Malware Protection Command Line Utility"target.process.command_line contains "downloadfile"target.process.command_line contains "url"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15)) |
principal_process_pid | array_distinct($process.principal.process.pid) |
principal_process_command_line | array_distinct($process.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($process.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($process.principal.process.file.full_path) |
principal_process_product_specfic_process_id | array_distinct($process.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specfic_process_id | array_distinct($process.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($process.target.process.pid) |
target_process_command_line | array_distinct($process.target.process.command_line) |
target_process_file_sha256 | array_distinct($process.target.process.file.sha256) |
target_process_file_full_path | array_distinct($process.target.process.file.full_path) |
target_process_product_specfic_process_id | array_distinct($process.target.process.product_specific_process_id) |
principal_user_userid | array_distinct($process.principal.user.userid) |
log_type | array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type)) |
MITRE ATT&CK T1140 Encoded Powershell Command
#Detects encoded powershell commands
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Stealth |
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
// Copyright 2023 Google LLC. Licensed under Apache-2.0.
rule mitre_attack_T1140_encoded_powershell_command {
meta:
author = "Google Cloud Security"
description = "Detects encoded powershell commands"
rule_id = "mr_c01d7d92-db49-4044-a2c5-5a16c74a141d"
rule_name = "MITRE ATT&CK T1140 Encoded Powershell Command"
tactic = "TA0005"
technique = "T1140"
type = "hunt"
platform = "Windows"
data_source = "microsoft sysmon, microsoft windows events"
severity = "Info"
priority = "Info"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
$process.principal.hostname = $hostname
re.regex($process.target.process.file.full_path, `(system32|syswow64)\\WindowsPowerShell\\v1\.0\\powershell(|\_ise)\.exe`) nocase
re.regex($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*\S*`)
$encoded_value = re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`)
$decoded_value = re.replace(strings.base64_decode(re.capture($process.target.process.command_line, `(?i)(?:-enc|-ec|-en)\s*(\S*)`)),`\0`, "")
match:
$hostname over 5m
outcome:
$risk_score = 10
$event_count = count_distinct($process.metadata.id)
$encoded_powershell = array_distinct($encoded_value)
$decoded_powershell = array_distinct($decoded_value)
// added to populate alert graph with additional context
// Commented out principal.hostname because it is already represented in graph as match variable. If match changes, can uncomment to add to results
$principal_hostname = array_distinct($process.principal.hostname)
$principal_process_pid = array_distinct($process.principal.process.pid)
$principal_process_command_line = array_distinct($process.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($process.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($process.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($process.target.process.pid)
$target_process_command_line = array_distinct($process.target.process.command_line)
$target_process_file_sha256 = array_distinct($process.target.process.file.sha256)
$target_process_file_full_path = array_distinct($process.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($process.target.process.product_specific_process_id)
$principal_user_userid = array_distinct($process.principal.user.userid)
condition:
$process
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 5m window.
Events
$process
target.process.file.full_path matches "(system32|syswow64)\\WindowsPowerShell\\v1\.0\\powershell(|\_ise)\.exe"target.process.command_line matches "(?i)(?:-enc|-ec|-en)\s*\S*"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | 10 |
event_count | count_distinct($process.metadata.id) |
encoded_powershell | array_distinct($encoded_value) |
decoded_powershell | array_distinct($decoded_value) |
principal_hostname | array_distinct($process.principal.hostname) |
principal_process_pid | array_distinct($process.principal.process.pid) |
principal_process_command_line | array_distinct($process.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($process.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($process.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($process.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($process.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($process.target.process.pid) |
target_process_command_line | array_distinct($process.target.process.command_line) |
target_process_file_sha256 | array_distinct($process.target.process.file.sha256) |
target_process_file_full_path | array_distinct($process.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($process.target.process.product_specific_process_id) |
principal_user_userid | array_distinct($process.principal.user.userid) |
potential lsass process dump via procdump
#Detects suspicious uses of the SysInternals Procdump utility by using a special command line parameter in combination with the lsass.exe process. This way we are also able to catch cases in which the attacker has renamed the procdump executable. Procdump dump of lsass using minidump or memory dump options. Covers atomic tests 1 and 8
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Credential Access |
References
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule potential_lsass_process_dump_via_procdump {
meta:
author = "Florian Roth (Nextron Systems)"
description = "Detects suspicious uses of the SysInternals Procdump utility by using a special command line parameter in combination with the lsass.exe process. This way we are also able to catch cases in which the attacker has renamed the procdump executable. Procdump dump of lsass using minidump or memory dump options. Covers atomic tests 1 and 8"
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/process_creation/proc_creation_win_sysinternals_procdump_lsass.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
sigma_uuid = "5afee48e-67dd-4e03-a783-f74259dcf998"
sigma_status = "stable"
rule_id = "mr_f7efb1a2-866c-4505-947e-3b06d4240262"
tactic = "TA0006"
technique = "T1003.001"
type = "Detection"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
falsepositives = "Unlikely, because no one should dump an lsass process memory, another tool that uses command line flags similar to ProcDump"
events:
$process.metadata.event_type = "PROCESS_LAUNCH"
(
strings.contains($process.target.process.command_line, " -ma ") or
strings.contains($process.target.process.command_line, " -mm ")
)
strings.contains(strings.to_lower($process.target.process.command_line), " ls")
$process.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
//example usage of specifying test user and hostname to adjust risk score
$risk_score = max(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15))
$principal_process_pid = array_distinct($process.principal.process.pid)
$principal_process_command_line = array_distinct($process.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($process.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($process.principal.process.file.full_path)
$principal_process_product_specfic_process_id = array_distinct($process.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specfic_process_id = array_distinct($process.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($process.target.process.pid)
$target_process_command_line = array_distinct($process.target.process.command_line)
$target_process_file_sha256 = array_distinct($process.target.process.file.sha256)
$target_process_file_full_path = array_distinct($process.target.process.file.full_path)
$target_process_product_specfic_process_id = array_distinct($process.target.process.product_specific_process_id)
$principal_user_userid = array_distinct($process.principal.user.userid)
$log_type = array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type))
condition:
$process
}
YARA-L Rule Structure
Condition
Fires when at least one $process event in the 5m window.
Events
$process
target.process.command_line contains " -ma "target.process.command_line contains " -mm "target.process.command_line contains " ls"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(if($process.principal.user.userid = "user" and $process.principal.hostname = "hostname", 0, 15)) |
principal_process_pid | array_distinct($process.principal.process.pid) |
principal_process_command_line | array_distinct($process.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($process.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($process.principal.process.file.full_path) |
principal_process_product_specfic_process_id | array_distinct($process.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specfic_process_id | array_distinct($process.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($process.target.process.pid) |
target_process_command_line | array_distinct($process.target.process.command_line) |
target_process_file_sha256 | array_distinct($process.target.process.file.sha256) |
target_process_file_full_path | array_distinct($process.target.process.file.full_path) |
target_process_product_specfic_process_id | array_distinct($process.target.process.product_specific_process_id) |
principal_user_userid | array_distinct($process.principal.user.userid) |
log_type | array_distinct(strings.concat($process.metadata.log_type,"/",$process.metadata.product_event_type)) |
Potential Remote PowerShell Session Initiated
#Detects a process that initiated a network connection over ports 5985 or 5986 from a non-network service account. This could potentially indicates a remote PowerShell connection.
Known False Positives
- Legitimate usage of remote PowerShell, e.g. remote administration and monitoring. Network Service user name of a not-covered localization
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Lateral Movement |
References
Telemetry Coverage
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule potential_remote_powershell_session_initiated {
meta:
author = "Roberto Rodriguez @Cyb3rWard0g"
description = "Detects a process that initiated a network connection over ports 5985 or 5986 from a non-network service account. This could potentially indicates a remote PowerShell connection."
reference = "https://github.com/SigmaHQ/sigma/blob/master/rules/windows/network_connection/net_connection_win_susp_remote_powershell_session.yml"
license = "https://github.com/SigmaHQ/Detection-Rule-License/blob/main/LICENSE.Detection.Rules.md"
rule_name = "Potential Remote PowerShell Session Initiated"
sigma_uuid = "c539afac-c12a-46ed-b1bd-5a5567c9f045"
sigma_status = "test"
rule_id = "mr_7186feaf-ab01-4c41-b17f-994b08b5bc33"
tactic = "TA0008"
technique = "T1021.006"
type = "Hunt"
data_source = "Sysmon"
platform = "Windows"
severity = "High"
priority = "High"
false_positives = "Legitimate usage of remote PowerShell, e.g. remote administration and monitoring. Network Service user name of a not-covered localization"
events:
$net.metadata.event_type = "NETWORK_CONNECTION"
$net.metadata.product_event_type = "3"
$net.metadata.product_name = "Microsoft-Windows-Sysmon"
$net.metadata.vendor_name = "Microsoft"
(
$net.target.port = 5985 or
$net.target.port = 5986
)
//Parser extension added for Initiated/true field/value, not currently in Sysmon parser
//Initiated: 'true'
$net.additional.fields["Initiated"] = "true"
net.ip_in_range_cidr($net.principal.ip, "0.0.0.0/0")
NOT (
strings.contains(strings.to_upper($net.principal.user.userid), "NETWORK SERVICE") or
strings.contains(strings.to_upper($net.principal.user.userid), "NETZWERKDIENST") or
strings.contains(strings.to_upper($net.principal.user.userid), "SERVICIO DE RED") or
strings.contains(strings.to_upper($net.principal.user.userid), "SERVIZIO DI RETE")
or
(
strings.contains(strings.to_upper($net.principal.user.userid), "SERVICE R") and
strings.contains(strings.to_upper($net.principal.user.userid), "SEAU")
)
)
NOT (
$net.principal.ip = "::1" or
$net.principal.ip = "127.0.0.1" or
$net.target.ip = "::1" or
$net.target.ip = "127.0.0.1"
)
NOT (
$net.principal.process.file.full_path = "C:\\Program Files\\Avast Software\\Avast\\AvastSvc.exe" nocase or
$net.principal.process.file.full_path = "C:\\Program Files (x86)\\Avast Software\\Avast\\AvastSvc.exe" nocase
)
$net.principal.hostname = $hostname
match:
$hostname over 5m
outcome:
//example usage of specifying test user and hostname to adjust risk score
$risk_score = max(if($net.principal.user.userid = "user" and $net.principal.hostname = "hostname", 0, 15))
$principal_ip = array_distinct($net.principal.ip)
$principal_port = array_distinct($net.principal.port)
$principal_process_pid = array_distinct($net.principal.process.pid)
$principal_process_command_line = array_distinct($net.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($net.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($net.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($net.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($net.principal.process.parent_process.product_specific_process_id)
$principal_user_userid = array_distinct($net.principal.user.userid)
$target_ip = array_distinct($net.target.ip)
$target_port = array_distinct($net.target.port)
condition:
$net
}
YARA-L Rule Structure
Condition
Fires when at least one $net event in the 5m window.
Events
$net
metadata.product_event_type = "3"target.port = "5985" or "5986"additional.fields["Initiated"] = "true"principal.ip cidr_match "0.0.0.0/0"principal.user.userid contains "NETWORK SERVICE"principal.user.userid contains "NETZWERKDIENST"principal.user.userid contains "SERVICIO DE RED"principal.user.userid contains "SERVIZIO DI RETE"principal.user.userid contains "SERVICE R"principal.user.userid contains "SEAU"principal.ip = "::1"principal.ip = "127.0.0.1"target.ip = "::1"target.ip = "127.0.0.1"principal.process.file.full_pathis one of:C:\Program Files\Avast Software\Avast\AvastSvc.exeC:\Program Files (x86)\Avast Software\Avast\AvastSvc.exe
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(if($net.principal.user.userid = "user" and $net.principal.hostname = "hostname", 0, 15)) |
principal_ip | array_distinct($net.principal.ip) |
principal_port | array_distinct($net.principal.port) |
principal_process_pid | array_distinct($net.principal.process.pid) |
principal_process_command_line | array_distinct($net.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($net.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($net.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($net.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($net.principal.process.parent_process.product_specific_process_id) |
principal_user_userid | array_distinct($net.principal.user.userid) |
target_ip | array_distinct($net.target.ip) |
target_port | array_distinct($net.target.port) |
Purple Knight Tool Execution Detected
#This detection rule identifies the execution of the Purple Knight tool, a free Active Directory security assessment utility developed by Semperis. Purple Knight is designed to scan for AD vulnerabilities, misconfigurations, and common attack paths. While it is a legitimate tool used by defenders, its execution in production environments may also indicate red team activity or unauthorized reconnaissance by adversaries attempting to map domain weaknesses.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Discovery |
References
Telemetry Coverage
| Provider | Record / event type |
|---|---|
| Sysmon | Event ID 1: Process creation |
| Security-Auditing | Event ID 4688: A new process has been created. |
Rule Body
// Copyright 2025 Google LLC. Licensed under Apache-2.0.
rule hacktool_purpleknight_execution {
meta:
author = "Georg Lauenstein - suresecure GmbH"
description = "This detection rule identifies the execution of the Purple Knight tool, a free Active Directory security assessment utility developed by Semperis. Purple Knight is designed to scan for AD vulnerabilities, misconfigurations, and common attack paths. While it is a legitimate tool used by defenders, its execution in production environments may also indicate red team activity or unauthorized reconnaissance by adversaries attempting to map domain weaknesses."
rule_id = "mr_69e428bb-c946-4e3f-abb8-0e28316f2389"
rule_name = "Purple Knight Tool Execution Detected"
tactic = "TA0007"
technique = "T1087"
references = "https://www.purple-knight.com/"
type = "alert"
platform = "Windows, EDR"
data_source = "Microsoft Sysmon, Windows Event Logs"
severity = "Medium" // Adjust based on your risk assessment
priority = "Medium" // Adjust based on your incident response process
events:
$purple_knight.metadata.event_type = "PROCESS_LAUNCH"
(
$purple_knight.target.process.file.full_path = /\\PurpleKnight\.exe$/ nocase or
$purple_knight.principal.process.file.full_path = /\\PurpleKnight\.exe$/ nocase or
$purple_knight.principal.process.command_line = /PurpleKnight/ nocase
)
// Capture the hostname where the event occurred
$purple_knight.principal.hostname = $hostname
match:
$hostname over 10m
outcome:
$risk_score = max(65)
$event_count = count_distinct($purple_knight.metadata.id)
$principal_process_pid = array_distinct($purple_knight.principal.process.pid)
$principal_process_command_line = array_distinct($purple_knight.principal.process.command_line)
$principal_process_file_sha256 = array_distinct($purple_knight.principal.process.file.sha256)
$principal_process_file_full_path = array_distinct($purple_knight.principal.process.file.full_path)
$principal_process_product_specific_process_id = array_distinct($purple_knight.principal.process.product_specific_process_id)
$principal_process_parent_process_product_specific_process_id = array_distinct($purple_knight.principal.process.parent_process.product_specific_process_id)
$target_process_pid = array_distinct($purple_knight.target.process.pid)
$target_process_command_line = array_distinct($purple_knight.target.process.command_line)
$target_process_file_sha256 = array_distinct($purple_knight.target.process.file.sha256)
$target_process_file_full_path = array_distinct($purple_knight.target.process.file.full_path)
$target_process_product_specific_process_id = array_distinct($purple_knight.target.process.product_specific_process_id)
$principal_user_userid = array_distinct($purple_knight.principal.user.userid)
condition:
$purple_knight
}
YARA-L Rule Structure
Condition
Fires when at least one $purple_knight event in the 10m window.
Events
$purple_knight
target.process.file.full_path matches "\\PurpleKnight\.exe$"principal.process.file.full_path matches "\\PurpleKnight\.exe$"principal.process.command_line matches "PurpleKnight"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
risk_score | max(65) |
event_count | count_distinct($purple_knight.metadata.id) |
principal_process_pid | array_distinct($purple_knight.principal.process.pid) |
principal_process_command_line | array_distinct($purple_knight.principal.process.command_line) |
principal_process_file_sha256 | array_distinct($purple_knight.principal.process.file.sha256) |
principal_process_file_full_path | array_distinct($purple_knight.principal.process.file.full_path) |
principal_process_product_specific_process_id | array_distinct($purple_knight.principal.process.product_specific_process_id) |
principal_process_parent_process_product_specific_process_id | array_distinct($purple_knight.principal.process.parent_process.product_specific_process_id) |
target_process_pid | array_distinct($purple_knight.target.process.pid) |
target_process_command_line | array_distinct($purple_knight.target.process.command_line) |
target_process_file_sha256 | array_distinct($purple_knight.target.process.file.sha256) |
target_process_file_full_path | array_distinct($purple_knight.target.process.file.full_path) |
target_process_product_specific_process_id | array_distinct($purple_knight.target.process.product_specific_process_id) |
principal_user_userid | array_distinct($purple_knight.principal.user.userid) |
sap change documents sensitive role assignment
#Detects the assignment of highly privileged SAP roles via Change Documents.
MITRE ATT&CK Coverage
| Tactic | Techniques |
|---|---|
| Privilege Escalation |
Rule Body
// Copyright 2026 Google LLC. Licensed under Apache-2.0.
rule sap_change_documents_sensitive_role_assignment {
meta:
author = "Google Cloud Security"
description = "Detects the assignment of highly privileged SAP roles via Change Documents."
severity = "Critical"
tactic = "TA0004"
technique = "T1098"
events:
$e.metadata.log_type = "SAP_CHANGE_DOCUMENT"
$e.target.resource.product_object_id in %sap_sensitive_roles.role
$principal_user = $e.principal.user.userid
match:
$principal_user over 30m
outcome:
$target_user = array_distinct($e.target.resource.product_object_id)
$tcode = array_distinct($e.target.application)
$tabname = array_distinct($e.target.resource.attribute.labels["TABNAME"])
$sensitive_role_assigned = array_distinct($e.target.resource.attribute.labels["TABKEY"])
condition:
$e
}
YARA-L Rule Structure
Condition
Fires when at least one $e event in the 30m window.
Events
$e
metadata.log_type = "SAP_CHANGE_DOCUMENT"target.resource.product_object_id in "%sap_sensitive_roles.role"
Match and Correlation
Outcome
Outcome variables add context to a detection. When the rule generates an alert, $risk_score is displayed with it.
| Field | Expression |
|---|---|
target_user | array_distinct($e.target.resource.product_object_id) |
tcode | array_distinct($e.target.application) |
tabname | array_distinct($e.target.resource.attribute.labels["TABNAME"]) |
sensitive_role_assigned | array_distinct($e.target.resource.attribute.labels["TABKEY"]) |