Detection rules › Kusto

Probable AdFind Recon Tool Usage

Status
available
Severity
high
Time window
1h
Source
github.com/Azure/Azure-Sentinel

This query identifies the host and account that executed AdFind, by hash and filename, in addition to the flags commonly utilized by various threat actors during the reconnaissance phase.

MITRE ATT&CK coverage

Telemetry coverage

Rule body

id: c63ae777-d5e0-4113-8c9a-c2c9d3d09fcd
name: Probable AdFind Recon Tool Usage
description: |
  'This query identifies the host and account that executed AdFind, by hash and filename, in addition to the flags commonly utilized by various threat actors during the reconnaissance phase.'
severity: High
status: Available
requiredDataConnectors:
  - connectorId: MicrosoftThreatProtection
    dataTypes:
      - DeviceProcessEvents
queryFrequency: 1h
queryPeriod: 1h
triggerOperator: gt
triggerThreshold: 0
tactics:
  - Discovery
relevantTechniques:
  - T1016
  - T1018
  - T1069.002
  - T1087.002
  - T1482
query: |
 let args = dynamic(["objectcategory","domainlist","dcmodes","adinfo","trustdmp","computers_pwdnotreqd","Domain Admins", "objectcategory=person", "objectcategory=computer", "objectcategory=*","dclist"]);
 let parentProcesses = dynamic(["pwsh.exe","powershell.exe","cmd.exe"]);
 DeviceProcessEvents
 //looks for execution from a shell
 | where InitiatingProcessFileName in~ (parentProcesses)
 // main filter
 | where FileName =~ "AdFind.exe" or SHA256 == "c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"
    // AdFind common Flags to check for from various threat actor TTPs
     or ProcessCommandLine has_any (args)
 | extend HostName = split(DeviceName, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(DeviceName, '.'), 1, -1), '.'), FileHashAlgorithm = "SHA256"
entityMappings:
  - entityType: Account
    fieldMappings:
      - identifier: Name
        columnName: AccountName
      - identifier: UPNSuffix
        columnName: AccountDomain 
  - entityType: Host
    fieldMappings:
      - identifier: HostName
        columnName: HostName
      - identifier: DnsDomain
        columnName: DnsDomain
  - entityType: Process
    fieldMappings:
      - identifier: ProcessId
        columnName: InitiatingProcessFileName
      - identifier: CommandLine
        columnName: ProcessCommandLine
  - entityType: FileHash
    fieldMappings:
      - identifier: Algorithm
        columnName: FileHashAlgorithm
      - identifier: Value
        columnName: SHA256

version: 1.0.3
kind: Scheduled

Stages and Predicates

Parameters

let parentProcesses = dynamic(["pwsh.exe","powershell.exe","cmd.exe"]);

Let binding: args used in Stage 3

let args = dynamic(["objectcategory","domainlist","dcmodes","adinfo","trustdmp","computers_pwdnotreqd","Domain Admins", "objectcategory=person", "objectcategory=computer", "objectcategory=*","dclist"]);

Stage 1: source

DeviceProcessEvents

Stage 2: where

| where InitiatingProcessFileName in~ (parentProcesses)

Stage 3: where

| where FileName =~ "AdFind.exe" or SHA256 == "c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"
    or ProcessCommandLine has_any (args)

Stage 4: extend

| extend HostName = split(DeviceName, '.', 0)[0], DnsDomain = strcat_array(array_slice(split(DeviceName, '.'), 1, -1), '.'), FileHashAlgorithm = "SHA256"

Indicators

These rows show field, operator, and value matches.

FieldKindValuesSearch
FileNameeq
  • AdFind.exe
field:"file_name" kind:eq value:"AdFind.exe"
InitiatingProcessFileNamein
  • cmd.exe corpus 36 (elastic 31, splunk 4, kusto 1)
  • powershell.exe corpus 39 (elastic 36, kusto 2, splunk 1)
  • pwsh.exe corpus 5 (elastic 5)
field:"parent_process_name" kind:in
ProcessCommandLinematch
  • Domain Admins transforms: term corpus 5 (sigma 2, kusto 2, splunk 1)
  • adinfo transforms: term corpus 4 (sigma 2, kusto 2)
  • computers_pwdnotreqd transforms: term corpus 4 (sigma 2, kusto 2)
  • dclist transforms: term corpus 2 (kusto 2)
  • dcmodes transforms: term corpus 4 (sigma 2, kusto 2)
  • domainlist transforms: term corpus 4 (sigma 2, kusto 2)
  • objectcategory transforms: term corpus 2 (kusto 2)
  • objectcategory=* transforms: term corpus 2 (kusto 2)
  • objectcategory=computer transforms: term corpus 2 (kusto 2)
  • objectcategory=person transforms: term corpus 2 (kusto 2)
  • trustdmp transforms: term corpus 4 (sigma 2, kusto 2)
field:"CommandLine" kind:match
SHA256eq
  • c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3 corpus 2 (kusto 2)
field:"sha256" kind:eq value:"c92c158d7c37fea795114fa6491fe5f145ad2f8c08776b18ae79db811e8e36a3"

Output fields

These fields are emitted when the rule matches.

FieldSource
DnsDomainextend
FileHashAlgorithmextend
HostNameextend