Detection rules › Kusto

Prestige ransomware IOCs Oct 2022

Severity
high
Time window
1d
Author
Microsoft Security Research
Source
github.com/Azure/Azure-Sentinel

'This query looks for file hashes and AV signatures associated with Prestige ransomware payload.'

MITRE ATT&CK coverage

Rule body kusto

id: bca9c877-2afc-4246-a26d-087ab1cdcd5f
name: Prestige ransomware IOCs Oct 2022
description: |
  'This query looks for file hashes and AV signatures associated with Prestige ransomware payload.'
severity: High
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceEvents
      - DeviceFileEvents
      - DeviceImageLoadEvents
  - connectorId: SecurityEvents
    dataTypes:
      - SecurityEvents  
queryFrequency: 1d
queryPeriod: 1d
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Execution
relevantTechniques:
  - T1203
tags:
  - Prestige
  - Ransomware
query: |
  let sha256Hashes = dynamic(["5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d", "5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57", "6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c"]);
  let signames = dynamic(["Ransom:Win32/Prestige"]);
  (union isfuzzy=true
  (CommonSecurityLog
  | where FileHash in (sha256Hashes)
  | project TimeGenerated, Message, SourceUserID, FileHash, Type
  | extend timestamp = TimeGenerated, Algorithm = "SHA256", AccountNTName = SourceUserID
  ),
  (imFileEvent
  | where TargetFileSHA256 has_any (sha256Hashes)
  | extend AccountNT = ActorUsername, Computer = DvcHostname, IPAddress = SrcIpAddr, CommandLine = ActingProcessCommandLine, FileHash = TargetFileSHA256
  | project Type, TimeGenerated, Computer, AccountNT, IPAddress, CommandLine, FileHash, Algorithm = "SHA256"
  ),
  (Event
  | where Source =~ "Microsoft-Windows-Sysmon"
  | where EventID == 1
  | extend EvData = parse_xml(EventData)
  | extend EventDetail = EvData.DataItem.EventData.Data
  | extend ProcessId = tolong(EventDetail.[3].["#text"]), Image = tostring(EventDetail.[4].["#text"]), CommandLine = tostring(EventDetail.[10].["#text"]), Hashes = tostring(EventDetail.[17].["#text"])
  | extend Hashes = extract_all(@"(?P<key>\w+)=(?P<value>[a-zA-Z0-9]+)", dynamic(["key","value"]), Hashes)
  | extend Hashes = column_ifexists("Hashes", dynamic(["", ""])), CommandLine = column_ifexists("CommandLine", "")
  | mv-expand Hashes
  | where Hashes[0] =~ "SHA256" and Hashes[1] has_any (sha256Hashes)  
  | project TimeGenerated, EventDetail, UserName, Computer, Type, Source, ProcessId, Hashes, CommandLine, Image
  | extend Type = strcat(Type, ": ", Source)
  | extend AccountNT = UserName, InitiatingProcessId = ProcessId
  | extend Process = tostring(split(Image, '\\', -1)[-1]), Algorithm = "SHA256", FileHash = tostring(Hashes[1]) 
  ),
  (DeviceEvents
  | where InitiatingProcessSHA256 has_any (sha256Hashes) or SHA256 has_any (sha256Hashes)
  | project TimeGenerated, ActionType, DeviceId, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessId, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessSHA256, Type
  | extend AccountNT = InitiatingProcessAccountName, Computer = DeviceName
  | extend Algorithm = "SHA256", FileHash = tostring(InitiatingProcessSHA256), CommandLine = InitiatingProcessCommandLine, Image = InitiatingProcessFolderPath
  ),
  (DeviceFileEvents
  | where SHA256 has_any (sha256Hashes)
  | project TimeGenerated, ActionType, DeviceId, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessId, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessSHA256, Type
  | extend AccountNT = InitiatingProcessAccountName, Computer = DeviceName
  | extend Algorithm = "SHA256", FileHash = tostring(InitiatingProcessSHA256), CommandLine = InitiatingProcessCommandLine, Image = InitiatingProcessFolderPath
  ),
  (DeviceImageLoadEvents
  | where SHA256 has_any (sha256Hashes)
  | project TimeGenerated, ActionType, DeviceId, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessId, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessSHA256, Type
  | extend AccountNT = InitiatingProcessAccountName, Computer = DeviceName
  | extend Algorithm = "SHA256", FileHash = tostring(InitiatingProcessSHA256), CommandLine = InitiatingProcessCommandLine, Image = InitiatingProcessFolderPath
  ),
  (SecurityAlert
  | where ProductName == "Microsoft Defender Advanced Threat Protection"
  | extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
  | where isnotempty(ThreatName)
  | where ThreatName has_any (signames)
  | extend Computer = tostring(parse_json(Entities)[0].HostName)
  )
  )
  | extend AccountNTName = tostring(split(AccountNT, "\\")[0]), AccountNTDomain = tostring(split(AccountNT, "\\")[1])
  | extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
  | extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
  | project-away DomainIndex
entityMappings:
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: Algorithm
      - identifier: Value
        columnName: FileHash
  - entityType: Process
    fieldMappings:
      - identifier: ProcessId
        columnName: InitiatingProcessId
      - identifier: CommandLine
        columnName: CommandLine
  - entityType: Account
    fieldMappings:
      - identifier: FullName
        columnName: AccountNT
      - identifier: Name
        columnName: AccountNTName
      - identifier: UPNSuffix
        columnName: AccountNTDomain
  - entityType: Host
    fieldMappings:
      - identifier: FullName
        columnName: Computer
      - identifier: HostName
        columnName: HostName
      - identifier: NTDomain
        columnName: HostNameDomain
version: 1.0.4
kind: Scheduled
metadata:
    source:
        kind: Community
    author:
        name: Microsoft Security Research
    support:
        tier: Community
    categories:
        domains: [ "Security - Others" ]

Stages and Predicates

Parameters

let signames = dynamic(["Ransom:Win32/Prestige"]);

Let binding: sha256Hashes

let sha256Hashes = dynamic(["5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d", "5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57", "6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c"]);

union isfuzzy=true (7 sources)

Each leg below queries one source; the rule matches if any leg does. Sources: CommonSecurityLog, imFileEvent, Event, DeviceEvents, DeviceFileEvents, DeviceImageLoadEvents, SecurityAlert

Leg 1: CommonSecurityLog

CommonSecurityLog
| where FileHash in (sha256Hashes)
| project TimeGenerated, Message, SourceUserID, FileHash, Type
| extend timestamp = TimeGenerated, Algorithm = "SHA256", AccountNTName = SourceUserID

Leg 2: imFileEvent

imFileEvent
| where TargetFileSHA256 has_any (sha256Hashes)
| extend AccountNT = ActorUsername, Computer = DvcHostname, IPAddress = SrcIpAddr, CommandLine = ActingProcessCommandLine, FileHash = TargetFileSHA256
| project Type, TimeGenerated, Computer, AccountNT, IPAddress, CommandLine, FileHash, Algorithm = "SHA256"

Leg 3: Event

Event
| where Source =~ "Microsoft-Windows-Sysmon"
| where EventID == 1
| extend EvData = parse_xml(EventData)
| extend EventDetail = EvData.DataItem.EventData.Data
| extend ProcessId = tolong(EventDetail.[3].["#text"]), Image = tostring(EventDetail.[4].["#text"]), CommandLine = tostring(EventDetail.[10].["#text"]), Hashes = tostring(EventDetail.[17].["#text"])
| extend Hashes = extract_all(@"(?P<key>\w+)=(?P<value>[a-zA-Z0-9]+)", dynamic(["key","value"]), Hashes)
| extend Hashes = column_ifexists("Hashes", dynamic(["", ""])), CommandLine = column_ifexists("CommandLine", "")
| mv-expand Hashes
| where Hashes[0] =~ "SHA256" and Hashes[1] has_any (sha256Hashes)  
| project TimeGenerated, EventDetail, UserName, Computer, Type, Source, ProcessId, Hashes, CommandLine, Image
| extend Type = strcat(Type, ": ", Source)
| extend AccountNT = UserName, InitiatingProcessId = ProcessId
| extend Process = tostring(split(Image, '\\', -1)[-1]), Algorithm = "SHA256", FileHash = tostring(Hashes[1])

Leg 4: DeviceEvents

DeviceEvents
| where InitiatingProcessSHA256 has_any (sha256Hashes) or SHA256 has_any (sha256Hashes)
| project TimeGenerated, ActionType, DeviceId, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessId, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessSHA256, Type
| extend AccountNT = InitiatingProcessAccountName, Computer = DeviceName
| extend Algorithm = "SHA256", FileHash = tostring(InitiatingProcessSHA256), CommandLine = InitiatingProcessCommandLine, Image = InitiatingProcessFolderPath

Leg 5: DeviceFileEvents

DeviceFileEvents
| where SHA256 has_any (sha256Hashes)
| project TimeGenerated, ActionType, DeviceId, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessId, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessSHA256, Type
| extend AccountNT = InitiatingProcessAccountName, Computer = DeviceName
| extend Algorithm = "SHA256", FileHash = tostring(InitiatingProcessSHA256), CommandLine = InitiatingProcessCommandLine, Image = InitiatingProcessFolderPath

Leg 6: DeviceImageLoadEvents

DeviceImageLoadEvents
| where SHA256 has_any (sha256Hashes)
| project TimeGenerated, ActionType, DeviceId, DeviceName, InitiatingProcessAccountDomain, InitiatingProcessAccountName, InitiatingProcessCommandLine, InitiatingProcessFolderPath, InitiatingProcessId, InitiatingProcessParentFileName, InitiatingProcessFileName, InitiatingProcessSHA256, Type
| extend AccountNT = InitiatingProcessAccountName, Computer = DeviceName
| extend Algorithm = "SHA256", FileHash = tostring(InitiatingProcessSHA256), CommandLine = InitiatingProcessCommandLine, Image = InitiatingProcessFolderPath

Leg 7: SecurityAlert

SecurityAlert
| where ProductName == "Microsoft Defender Advanced Threat Protection"
| extend ThreatName = tostring(parse_json(ExtendedProperties).ThreatName)
| where isnotempty(ThreatName)
| where ThreatName has_any (signames)
| extend Computer = tostring(parse_json(Entities)[0].HostName)

Applied to the combined result

| extend AccountNTName = tostring(split(AccountNT, "\\")[0]), AccountNTDomain = tostring(split(AccountNT, "\\")[1])
| extend HostName = tostring(split(Computer, ".")[0]), DomainIndex = toint(indexof(Computer, '.'))
| extend HostNameDomain = iff(DomainIndex != -1, substring(Computer, DomainIndex + 1), Computer)
| project-away DomainIndex

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
EventIDeq
  • 1 transforms: cased corpus 237 (splunk 224, kusto 13)
FileHashin
  • 5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d transforms: cased
  • 5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57 transforms: cased
  • 6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c transforms: cased
Hashes[0]eq
  • SHA256 corpus 3 (kusto 3)
Hashes[1]match
  • 5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d
  • 5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57
  • 6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c
InitiatingProcessSHA256match
  • 5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d
  • 5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57
  • 6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c
ProductNameeq
  • Microsoft Defender Advanced Threat Protection transforms: cased
SHA256match
  • 5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d
  • 5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57
  • 6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c
TargetFileSHA256match
  • 5dd1ca0d471dee41eb3ea0b6ea117810f228354fc3b7b47400a812573d40d91d
  • 5fc44c7342b84f50f24758e39c8848b2f0991e8817ef5465844f5f2ff6085a57
  • 6cff0bbd62efe99f381e5cc0c4182b0fb7a9a34e4be9ce68ee6b0d0ea3eee39c
ThreatNameis_not_null
  • (no value, null check)
ThreatNamematch
  • signames

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
ActionTypeproject
DeviceIdproject
DeviceNameproject
InitiatingProcessAccountDomainproject
InitiatingProcessAccountNameproject
InitiatingProcessCommandLineproject
InitiatingProcessFileNameproject
InitiatingProcessFolderPathproject
InitiatingProcessIdproject
InitiatingProcessParentFileNameproject
InitiatingProcessSHA256project
TimeGeneratedproject
Typeproject
AccountNTextend
Computerextend
Algorithmextend
CommandLineextend
FileHashextend
Imageextend
ThreatNameextend
AccountNTDomainextend
AccountNTNameextend
HostNameextend
HostNameDomainextend