Detection rules › Kusto

Base64 encoded Windows process command-lines

Status
available
Severity
medium
Time window
1d
Group by
Account, AccountDomain, CommandLine, Computer, FileName, ParentProcessName
Source
github.com/Azure/Azure-Sentinel

Identifies instances of a base64-encoded PE file header seen in the process command line parameter.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

id: ca67c83e-7fff-4127-a3e3-1af66d6d4cad
name: Base64 encoded Windows process command-lines
description: |
  'Identifies instances of a base64-encoded PE file header seen in the process command line parameter.'
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:
  - Execution
  - DefenseEvasion
relevantTechniques:
  - T1059
  - T1027
  - T1140
query: |
  let ProcessCreationEvents=(union isfuzzy=true
  (SecurityEvent
  | where EventID==4688
  | where isnotempty(CommandLine)
  | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count() by Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName,
  FileName = Process, CommandLine, ParentProcessName
  ),
  (WindowsEvent
  | where EventID==4688
  | where EventData has "TVqQAAMAAAAEAAA"
  | extend CommandLine = tostring(EventData.CommandLine)
  | where isnotempty(CommandLine)
  | extend ParentProcessName = tostring(EventData.ParentProcessName)
  | extend NewProcessName = tostring(EventData.NewProcessName)
  | extend Process=tostring(split(NewProcessName, '\\')[-1])
  | extend SubjectUserName = tostring(EventData.SubjectUserName)
  | extend SubjectDomainName = tostring(EventData.SubjectDomainName)
  | summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count() by Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName,
  FileName = Process, CommandLine, ParentProcessName));
  ProcessCreationEvents
  | where CommandLine contains "TVqQAAMAAAAEAAA"
  | 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.4
kind: Scheduled

Stages and Predicates

Stage 0: let

let ProcessCreationEvents = (union <inlined as stages below>;

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)
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count() by Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName,
FileName = Process, CommandLine, ParentProcessName

Leg 2: WindowsEvent

WindowsEvent
| where EventID==4688
| where EventData has "TVqQAAMAAAAEAAA"
| extend CommandLine = tostring(EventData.CommandLine)
| where isnotempty(CommandLine)
| extend ParentProcessName = tostring(EventData.ParentProcessName)
| extend NewProcessName = tostring(EventData.NewProcessName)
| extend Process=tostring(split(NewProcessName, '\\')[-1])
| extend SubjectUserName = tostring(EventData.SubjectUserName)
| extend SubjectDomainName = tostring(EventData.SubjectDomainName)
| summarize StartTimeUtc = min(TimeGenerated), EndTimeUtc = max(TimeGenerated), count() by Computer, Account = SubjectUserName, AccountDomain = SubjectDomainName,
FileName = Process, CommandLine, ParentProcessName

Applied to the combined result

| where CommandLine contains "TVqQAAMAAAAEAAA" | extend HostName = iif(Computer has '.',substring(Computer,0,indexof(Computer,'.')),Computer) , DnsDomain = iif(Computer has '.',substring(Computer,indexof(Computer,'.')+1),'')

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
CommandLinecontains
  • TVqQAAMAAAAEAAA corpus 3 (kusto 3)
field:"CommandLine" kind:contains value:"TVqQAAMAAAAEAAA"
CommandLineis_not_null
  • (no value, null check)
field:"CommandLine" kind:is_not_null
EventDatamatch
  • TVqQAAMAAAAEAAA transforms: term
field:"EventData" kind:match value:"TVqQAAMAAAAEAAA"
EventIDeq
  • 4688 corpus 317 (splunk 283, kusto 33, elastic 1)
field:"EventID" kind:eq value:"4688"

Output fields

These fields are emitted when the rule matches.

FieldSource
Accountsummarize
AccountDomainsummarize
CommandLinesummarize
Computersummarize
EndTimeUtcsummarize
FileNamesummarize
ParentProcessNamesummarize
StartTimeUtcsummarize
DnsDomainextend
HostNameextend