Detection rules › Kusto

AV detections related to Tarrask malware

Status
available
Severity
high
Time window
1d
Group by
AlertSeverity, CompromisedEntity, Description, DeviceId, DeviceName, DisplayName, Entities, ProductName, PublicIP, TenantId, ThreatFamilyName, ThreatName
Source
github.com/Azure/Azure-Sentinel

'This query looks for Microsoft Defender AV detections related to Tarrask malware. In Microsoft Sentinel, the SecurityAlerts table includes only the Device Name of the affected device, this query joins the DeviceInfo table to clearly connect other information such as Device group, ip, logged-on users etc. This would allow the Microsoft Sentinel analyst to have more context related to the alert, if available. Reference: https://www.microsoft.com/security/blog/2022/04/12/tarrask-malware-uses-scheduled-tasks-for-defense-evasion/'

MITRE ATT&CK coverage

TacticTechniques
PersistenceT1053 Scheduled Task/Job

Rule body kusto

id: 1785d372-b9fe-4283-96a6-3a1d83cabfd1
name: AV detections related to Tarrask malware
description: |
  'This query looks for Microsoft Defender AV detections related to Tarrask malware. In Microsoft Sentinel, the SecurityAlerts table includes only the Device Name of the affected device, this query joins the DeviceInfo table to clearly connect other information such as Device group, ip, logged-on users etc. 
   This would allow the Microsoft Sentinel analyst to have more context related to the alert, if available.
   Reference: https://www.microsoft.com/security/blog/2022/04/12/tarrask-malware-uses-scheduled-tasks-for-defense-evasion/'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - SecurityAlert
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Persistence
relevantTechniques:
  - T1053
query: |
  let Tarrask_threats = dynamic(["HackTool:Win64/Tarrask!MS", "HackTool:Win64/Ligolo!MSR", "Behavior:Win32/ScheduledTaskHide.A", "Tarrask"]);
  DeviceInfo
  | extend DeviceName = tolower(DeviceName)
  | join kind=rightouter ( SecurityAlert
  | where ProviderName =~ "MDATP"
  | extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
  | extend ThreatFamilyName = tostring(parse_json(ExtendedProperties).ThreatFamilyName)
  | where ThreatName in~ (Tarrask_threats) or ThreatFamilyName in~ (Tarrask_threats)
  | extend CompromisedEntity = tolower(CompromisedEntity)
  ) on $left.DeviceName == $right.CompromisedEntity
  | summarize by DisplayName, ThreatName, ThreatFamilyName, PublicIP, AlertSeverity, Description, tostring(LoggedOnUsers), DeviceId, TenantId , bin(TimeGenerated, 1d), CompromisedEntity, tostring(LoggedOnUsers), ProductName, Entities
  | extend HostName = tostring(split(CompromisedEntity, ".")[0]), DomainIndex = toint(indexof(CompromisedEntity, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(CompromisedEntity, DomainIndex + 1), CompromisedEntity)
entityMappings:
  - entityType: Host
    fieldMappings:
      - identifier: FullName 
        columnName: CompromisedEntity
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: HostNameDomain
  - entityType: IP
    fieldMappings:
      - identifier: Address
        columnName: PublicIP
version: 1.0.4
kind: Scheduled

Stages and Predicates

Parameters

let Tarrask_threats = dynamic(["HackTool:Win64/Tarrask!MS", "HackTool:Win64/Ligolo!MSR", "Behavior:Win32/ScheduledTaskHide.A", "Tarrask"]);

Stage 1: source

DeviceInfo

Stage 2: extend

| extend DeviceName = tolower(DeviceName)

Stage 3: join

| join kind=rightouter ( SecurityAlert
| where ProviderName =~ "MDATP"
| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
| extend ThreatFamilyName = tostring(parse_json(ExtendedProperties).ThreatFamilyName)
| where ThreatName in~ (Tarrask_threats) or ThreatFamilyName in~ (Tarrask_threats)
| extend CompromisedEntity = tolower(CompromisedEntity)
) on $left.DeviceName == $right.CompromisedEntity

Stage 4: summarize

| summarize by DisplayName, ThreatName, ThreatFamilyName, PublicIP, AlertSeverity, Description, tostring(LoggedOnUsers), DeviceId, TenantId , bin(TimeGenerated, 1d), CompromisedEntity, tostring(LoggedOnUsers), ProductName, Entities

Stage 5: extend

| extend HostName = tostring(split(CompromisedEntity, ".")[0]), DomainIndex = toint(indexof(CompromisedEntity, '.'))

Stage 6: extend

| extend HostNameDomain = iff(DomainIndex != -1, substring(CompromisedEntity, DomainIndex + 1), CompromisedEntity)
HostNameDomain =
ifDomainIndex != -1substring(CompromisedEntity, (DomainIndex + 1))
elseCompromisedEntity

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.

FieldKindValues
ProviderNameeq
  • MDATP corpus 13 (kusto 13)
ThreatFamilyNamein
  • Behavior:Win32/ScheduledTaskHide.A
  • HackTool:Win64/Ligolo!MSR
  • HackTool:Win64/Tarrask!MS
  • Tarrask
ThreatNamein
  • Behavior:Win32/ScheduledTaskHide.A
  • HackTool:Win64/Ligolo!MSR
  • HackTool:Win64/Tarrask!MS
  • Tarrask

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.

FieldSource
AlertSeveritysummarize
CompromisedEntitysummarize
Descriptionsummarize
DeviceIdsummarize
DisplayNamesummarize
Entitiessummarize
ProductNamesummarize
PublicIPsummarize
TenantIdsummarize
ThreatFamilyNamesummarize
ThreatNamesummarize
DomainIndexextend
HostNameextend
HostNameDomainextend