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
Parameters
let recycle_bin_paths = dynamic([@":\RECYCLER", @":\$RECYCLE.BIN"]);
Let binding: procList
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);
union isfuzzy=true (2 sources)
Each leg below queries one source; the rule matches if any leg does. Sources: SecurityEvent, WindowsEvent
Leg 1: SecurityEvent
SecurityEvent
| where EventID==4688
| where isnotempty(CommandLine)
| project TimeGenerated, Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName, NewProcessName,
FileName = Process, CommandLine, ParentProcessName
Leg 2: WindowsEvent
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
Applied to the combined result
| 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),'')
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 |