Detection rules › Kusto

PowerShell without powershell.exe

Group by
InitiatingProcessSHA1
Author
FalconForce
Source
github.com/FalconForceTeam/FalconFriday

This query detects the use of PowerShell through "system.management.automation.dll" which is invoked by a process with a low global prevalence (i.e., fairly unique binary).

MITRE ATT&CK coverage

Event coverage

Rule body kusto

let timeframe = 2*1h;
let default_global_prevalence = 0;
let suspiciousProcs = materialize(
DeviceImageLoadEvents
| where FileName =~ "system.management.automation.dll" or FileName =~ "system.management.automation.ni.dll" and not(isempty(InitiatingProcessSHA1))
| summarize count() by InitiatingProcessSHA1
// FileProfile is case-sensitive and works on lower-case hashes.
| extend InitiatingProcessSHA1=tolower(InitiatingProcessSHA1)
| invoke FileProfile(InitiatingProcessSHA1, 1000)
| where not(ProfileAvailability =~ "Error")
| where coalesce(IsRootSignerMicrosoft, false) == false or  coalesce(IsCertificateValid, false) == false
| where (IsCertificateValid and coalesce(GlobalPrevalence,default_global_prevalence) < 200) or (not(coalesce(IsCertificateValid, false)) and coalesce(GlobalPrevalence,default_global_prevalence) < 500));
DeviceImageLoadEvents
| where ingestion_time() >= ago(timeframe)
// FileProfile is case-sensitive and works on lower-case hashes.
| extend InitiatingProcessSHA1=tolower(InitiatingProcessSHA1)
| where InitiatingProcessSHA1 in~ ((suspiciousProcs | project InitiatingProcessSHA1)) and FileName startswith "System.Management.Automation"
| join kind=inner suspiciousProcs on InitiatingProcessSHA1
// Begin environment-specific filter.
// End environment-specific filter.

Stages and Predicates

Parameters

let timeframe = 2*1h;
let default_global_prevalence = 0;

Let binding: suspiciousProcs

let suspiciousProcs = materialize(
DeviceImageLoadEvents
| where FileName =~ "system.management.automation.dll" or FileName =~ "system.management.automation.ni.dll" and not(isempty(InitiatingProcessSHA1))
| summarize count() by InitiatingProcessSHA1
| extend InitiatingProcessSHA1=tolower(InitiatingProcessSHA1)
| invoke FileProfile(InitiatingProcessSHA1, 1000)
| where not(ProfileAvailability =~ "Error")
| where coalesce(IsRootSignerMicrosoft, false) == false or  coalesce(IsCertificateValid, false) == false
| where (IsCertificateValid and coalesce(GlobalPrevalence,default_global_prevalence) < 200) or (not(coalesce(IsCertificateValid, false)) and coalesce(GlobalPrevalence,default_global_prevalence) < 500));

Derived from default_global_prevalence.

Stage 1: source

DeviceImageLoadEvents

Stage 2: where

| where ingestion_time() >= ago(timeframe)

Stage 3: extend

| extend InitiatingProcessSHA1=tolower(InitiatingProcessSHA1)

Stage 4: where

| where InitiatingProcessSHA1 in~ ((suspiciousProcs | project InitiatingProcessSHA1)) and FileName startswith "System.Management.Automation"

Stage 5: join

| join kind=inner suspiciousProcs on InitiatingProcessSHA1

Stage 6: summarize

summarize by InitiatingProcessSHA1

Exclusions

Top-level NOT(...) conjuncts: predicates this rule actively suppresses.

FieldKindExcluded values
ProfileAvailabilityeqError

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
FileNameeq
  • system.management.automation.dll
  • system.management.automation.ni.dll
FileNamestarts_with
  • System.Management.Automation
GlobalPrevalencelt
  • 200 transforms: coalesce_default:0 corpus 4 (kusto 4)
  • 500 transforms: coalesce_default:0
IsCertificateValideq
  • false transforms: coalesce_default:false
IsRootSignerMicrosofteq
  • false transforms: coalesce_default:false

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
InitiatingProcessSHA1summarize