Detection rules › Kusto
Malware in the recycle bin
The query detects Windows binaries that can be used for executing malware and have been hidden in the recycle bin. The list of these binaries is sourced from https://lolbas-project.github.io/ References: https://azure.microsoft.com/blog/how-azure-security-center-helps-reveal-a-cyberattack/.
MITRE ATT&CK coverage
| Tactic | Techniques |
|---|---|
| Stealth | T1564 Hide Artifacts |
Event coverage
| Provider | Event | Title |
|---|---|---|
| Security-Auditing | Event ID 4688 | A new process has been created. |
Rule body kusto
id: 75bf9902-0789-47c1-a5d8-f57046aa72df
name: Malware in the recycle bin
description: |
'The query detects Windows binaries that can be used for executing malware and have been hidden in the recycle bin.
The list of these binaries is sourced from https://lolbas-project.github.io/
References: https://azure.microsoft.com/blog/how-azure-security-center-helps-reveal-a-cyberattack/.'
severity: Medium
status: Available
requiredDataConnectors:
- connectorId: SecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvent
- connectorId: WindowsSecurityEvents
dataTypes:
- SecurityEvents
- connectorId: WindowsForwardedEvents
dataTypes:
- WindowsEvent
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
- DefenseEvasion
relevantTechniques:
- T1564
query: |
let procList = externaldata(Process:string) [@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Microsoft_Lolbas_Execution_Binaries.csv"] with (format="csv", ignoreFirstRecord=True);
let recycle_bin_paths = dynamic([@":\RECYCLER", @":\$RECYCLE.BIN"]);
let ProcessCreationEvents=(union isfuzzy=true
(SecurityEvent
| where EventID==4688
| where isnotempty(CommandLine)
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine, ParentProcessName
),
(WindowsEvent
| where EventID==4688 and EventData has_any (procList) and EventData has_any (recycle_bin_paths)
| extend CommandLine = tostring(EventData.CommandLine)
| where isnotempty(CommandLine)
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| extend NewProcessName = tostring(EventData.NewProcessName)
| extend ParentProcessName = tostring(EventData.ParentProcessName)
| extend Process=tostring(split(NewProcessName, '\\')[-1])
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine, ParentProcessName
));
ProcessCreationEvents
| where FileName in~ (procList)
| where CommandLine has_any (recycle_bin_paths)
| project StartTimeUtc = TimeGenerated, Computer, Account, NewProcessName, FileName, CommandLine, ParentProcessName
| extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')
entityMappings:
- entityType: Account
fieldMappings:
- identifier: Name
columnName: Account
- entityType: Host
fieldMappings:
- identifier: FullName
columnName: Computer
- identifier: HostName
columnName: HostName
- identifier: DnsDomain
columnName: DnsDomain
version: 1.1.5
kind: Scheduled
Stages and Predicates
Stage 0: let
let procList = externaldata(Process:string) [@"https://raw.githubusercontent.com/Azure/Azure-Sentinel/master/Sample%20Data/Microsoft_Lolbas_Execution_Binaries.csv"] with (format="csv", ignoreFirstRecord=True);
let recycle_bin_paths = dynamic([@":\RECYCLER", @":\$RECYCLE.BIN"]);
let ProcessCreationEvents = (union <inlined as stages below>;
Stage 1: source
let ProcessCreationEvents
Stage 2: union
union isfuzzy=true
Stage 3: source time_window=86400s
SecurityEvent
Stage 4: where
| where EventID==4688
Stage 5: where
| where isnotempty(CommandLine)
Stage 6: project
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine, ParentProcessName
Stage 7: source
WindowsEvent
Stage 8: where
| where EventID==4688 and EventData has_any (procList) and EventData has_any (recycle_bin_paths)
Stage 9: extend
| extend CommandLine = tostring(EventData.CommandLine)
Stage 10: where
| where isnotempty(CommandLine)
Stage 11: extend
| extend SubjectUserName = tostring(EventData.SubjectUserName)
Stage 12: extend
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
Stage 13: extend
| extend NewProcessName = tostring(EventData.NewProcessName)
Stage 14: extend
| extend ParentProcessName = tostring(EventData.ParentProcessName)
Stage 15: extend
| extend Process=tostring(split(NewProcessName, '\\')[-1])
Stage 16: project
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine, ParentProcessName
Stage 17: where
| where FileName in~ (procList)
Stage 18: where
| where CommandLine has_any (recycle_bin_paths)
Stage 19: project
| project StartTimeUtc = TimeGenerated, Computer, Account, NewProcessName, FileName, CommandLine, ParentProcessName
Stage 20: extend
| extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')
Indicators
Each row is a field, operator, and value that the rule matches. The corpus column counts how many other rules in the catalog look for the same combination: high numbers point to widely-used, community-vetted indicators. Blank or 1 shows that the indicator is specific to this rule.
| Field | Kind | Values |
|---|---|---|
CommandLine | is_not_null | |
CommandLine | match |
|
EventData | match |
|
EventID | eq |
|
FileName | in |
|
Output fields
Fields the rule emits when it matches. Chronicle authors list these in the outcome block; they appear on the detection and $risk_score drives alerting. Sentinel / Defender XDR rules build them up through project / summarize / extend stages. Sentinel maps these into alert fields via entityMappings and customDetails; Defender XDR custom detections surface them as alert fields directly.
| Field | Source |
|---|---|
Account | project |
CommandLine | project |
Computer | project |
FileName | project |
NewProcessName | project |
ParentProcessName | project |
StartTimeUtc | project |
DnsDomain | extend |
HostName | extend |