cs

Hunting Queries: CrowdStrike Query Language

Find ScheduledTaskRegistered events by host

#event_simpleName=ScheduledTaskRegistered
| groupBy([aid, TaskName, TaskExecCommand, TaskAuthor], limit=max)

Find ScheduledTaskDeleted events by host

#event_simpleName=ScheduledTaskDeleted
| groupBy(aid, function=collect([TaskName, UserName]), limit=max)

Find events triggered at logon

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| Trigger:=rename(Task.Triggers.LogonTrigger.Enabled)
| Trigger=* // Remove this line if you don't care if it's empty
| table([aid, Trigger, TaskXml], limit=1000)

Find events triggered at startup

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| Trigger:=rename(Task.Triggers.BootTrigger.Enabled)
| Trigger=* // Remove this line if you don't care if it's empty
| table([aid, Trigger, TaskXml], limit=1000)

Find events triggered at a specific time

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| Trigger:=rename(Task.Triggers.TimeTrigger.Enabled)
| Trigger=* // Remove this line if you don't care if it's empty
| table([aid, Trigger, TaskXml], limit=1000)

For info about how you can convert or translate timestamps and other time related values to alternative formats, see Time Syntax.

Find events that are scheduled

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| Trigger:=rename(Task.Triggers.CalendarTrigger.Enabled)
| Trigger=* // Remove this line if you don't care if it's empty
| table([aid, Trigger, TaskXml], limit=1000)

Find events triggered on an event

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| Trigger:=rename(Task.Triggers.EventTrigger.Enabled)
| Trigger=* // Remove this line if you don't care if it's empty
| table([aid, Trigger, TaskXml], limit=1000)

Find tasks scheduled by logon type

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| LogonType:=rename(Task.Principals.Principal.LogonType)
| LogonType=* // Remove this line if you don't care if it's empty
| table([aid, LogonType, TaskXml], limit=1000)

Find tasks scheduled by user ID

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| UserId:=rename(Task.Principals.Principal.UserId)
| table([aid, UserId, TaskXml], limit=1000)

Find tasks scheduled by run level

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| RunLevel:=rename(Task.Principals.Principal.RunLevel)
| RunLevel=* // Remove this line if you don't care if it's empty
| table([aid, RunLevel, TaskXml], limit=1000)

Find tasks scheduled with ComHandler

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| ComHandlerData:=rename(Task.Actions.ComHandler.Data)
| ComHandlerData=* // Remove this line if you don't care if it's empty
| table([aid, ComHandlerData, TaskXml], limit=1000)

Find hidden scheduled tasks

#event_simpleName=ScheduledTaskRegistered
| parseXml(TaskXml)
| Hidden:=rename(Task.Settings.Hidden)
| Hidden=/true/i
| table([aid,Hidden,TaskXml],limit=1000)


Hunting suspicious processes

Find any instances of common reconnaissance tools on a host

#event_simpleName=ProcessRollup2
| aid=?aid
| ImageFileName=/(?<FileName>[^\\/|\\\\]*)$/
| FileName = /^(net|ipconfig|whoami|quser|ping|netstat|tasklist|hostname|at)\.exe$/i
| table([aid, UserName, ParentBaseFileName, ImageFileName, CommandLine], limit=1000)

Find any instances where multiple recon commands were executed by the same parent process

#event_simpleName=ProcessRollup2
| aid=?aid
| ImageFileName=/(?<FileName>[^\\/|\\\\]*)$/
| FileName = /^(net|ipconfig|whoami|quser|ping|netstat|tasklist|hostname|at)\.exe$/i
| groupBy([aid, ParentProcessId], function=[collect([UserName, ParentProcessId, ParentBaseFileName, FileName, CommandLine]), count(FileName, as="fname_count"), count(CommandLine, as="CLI_count")], limit=max)
| fname_count > 1 OR CLI_count > 1

Find any BITS transfers (can be used to transfer malicious binaries)

#event_simpleName=ProcessRollup2
| ImageFileName=/\\bitsadmin\.exe/i CommandLine=/(Transfer|Addfile)/i
| join({#event_simpleName=UserIdentity | groupBy([aid, AuthenticationId, UserName], limit=max)}, field=AuthenticationId, include=UserName)
| groupBy([aid, CommandHistory], function=collect([UserName, CommandLine, ImageFileName, SHA256HashData]), limit=max)

Find any powershell.exe downloads

#event_simpleName=ProcessRollup2
| ImageFileName=/\\powershell\.exe/i CommandLine=/(Invoke-WebRequest|Net\.WebClient|Start-BitsTransfer)/i
| join({#event_simpleName=UserIdentity | groupBy([aid, AuthenticationId, UserName], limit=max)}, field=AuthenticationId, include=UserName)
| table([aid, UserName, ImageFileName, CommandLine], limit=1000)

Find any encoded PowerShell commands

#event_simpleName=ProcessRollup2
| ImageFileName=/\\powershell\.exe/i CommandLine=/\s-[e^]{1,2}[ncodema^]+\s/i
| join({#event_simpleName=UserIdentity | groupBy([aid, AuthenticationId, UserName], limit=max)}, field=AuthenticationId, include=UserName)
| table([aid, UserName, ImageFileName, CommandLine], limit=1000)

Find a list of processes that executed from the Recycle Bin

#event_simpleName=ProcessRollup2
| aid=?aid ImageFileName=/\$Recycle\.Bin/i
| groupBy(aid, function=collect([SHA256HashData, ImageFileName]), limit=max)

Find a list of processes executing from User Profile file paths

Processes generally shouldn’t be executing from user spaces. These paths cover spaces that are considered to be User Paths.

#event_simpleName=ProcessRollup2 OR #event_simpleName=SyntheticProcessRollup2
| ImageFileName=/(\\Desktop\\|\\AppData\\)/
| join({#event_simpleName=UserIdentity | groupBy([aid, AuthenticationId, UserName], limit=max)}, field=AuthenticationId, include=UserName)
| table([aid, UserName, ImageFileName, SHA256HashData], limit=1000)

Find a list of processes executing from browser file paths

Similar to the previous query, processes typically shouldn’t be running from these locations.

#event_simpleName=ProcessRollup2 OR #event_simpleName=SyntheticProcessRollup2
ImageFileName=/(\\AppData\\Local\\Microsoft\\Windows\\Temporary.Internet.Files\\[^\/|\\]*\.exe|.*\\AppData\\Local\\Mozilla\\Firefox\\Profiles\\[^\/|\\]*\.exe|\\AppData\\Local\\Google\\Chrome\\[^\/|\\]*\.exe|\\Downloads\\[^\/|\\]*\.exe)/i
| aid=?aid
| ImageFileName=/(?<FileName>[^\\/|\\\\]*)$/
| table([aid, ImageFileName, FileName, SHA256HashData], limit=1000

Find the responsible process for starting a service

#event_simpleName=ProcessRollup2
| join({#event_simpleName=ServiceStarted}, key=RpcClientProcessId, field=SourceProcessId, include=ServiceDisplayName)
| table([aid, ImageFileName, ServiceDisplayName], limit=1000)

Find binaries running as a service that do not originate from "System32"

#event_simpleName=ServiceStarted
| ImageFileName!=/\\System32\\/i
| table([aid, ServiceDisplayName, ImageFileName, CommandLine, ComputerName], limit=1000)

Find an expected service running from an unexpected location

#event_simpleName=ServiceStarted
| ImageFileName=/\\svchost\.exe/i
| ImageFileName!=/\\System32\\/i
| case {
aid=* AND ComputerName!=*
| match(file="fdr_aidmaster.csv", field=aid, include=ComputerName, ignoreCase=true, strict=true);
* | default(field=ComputerName, value=NotMatched);
}
| table([aid, ComputerName, ServiceDisplayName, ImageFileName, CommandLine, ClientComputerName, RemoteAddressIP4, RemoteAddressIP6], limit=1000)

Find a specific service name

#event_simpleName=ServiceStarted
| ServiceDisplayName=?service
| case {
aid=* AND ComputerName!=*
| match(file="fdr_aidmaster.csv", field=aid, include=ComputerName, ignoreCase=true, strict=true);
* | default(field=ComputerName, value=NotMatched);
}
| table([aid, ComputerName, ServiceDisplayName, ImageFileName, CommandLine, ClientComputerName, RemoteAddressIP4, RemoteAddressIP6], limit=1000)

Find a list of services that were stopped and on which hosts

#event_simpleName=ProcessRollup2 OR #event_simpleName=SyntheticProcessRollup2
| join({#event_simpleName=ServiceStopped}, key=TargetProcessId, field=TargetProcessId)

--

Last updated