SOC Analyst Cheat Sheet
Hand-curated queries · Clankerusecase
← Back to main site

Microsoft 365 Defender · Advanced Hunting

Pick a table from the sidebar (or scroll) — every query is schema-validated against the canonical column list and follows the BluRaven house style: time-bound first (Timestamp), machine-account excluded, case-insensitive equality, indexed token matching.

25 tables curated 96 queries 25 schema tables Click Copy on any query to paste into Defender Advanced Hunting.

DeviceProcessEvents

56 columns · 10 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · FileName · FolderPath · SHA1 · SHA256 · MD5 · FileSize · ProcessVersionInfoCompanyName · ProcessVersionInfoProductName · ProcessVersionInfoProductVersion · ProcessVersionInfoInternalFileName · ProcessVersionInfoOriginalFileName · ProcessVersionInfoFileDescription · ProcessId · ProcessCommandLine · ProcessIntegrityLevel · ProcessTokenElevation · ProcessCreationTime · AccountDomain · AccountName · AccountSid · AccountUpn · AccountObjectId · LogonId · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessAccountSid · InitiatingProcessAccountUpn · InitiatingProcessAccountObjectId · InitiatingProcessLogonId · InitiatingProcessIntegrityLevel · InitiatingProcessTokenElevation · InitiatingProcessSHA1 · InitiatingProcessSHA256 · InitiatingProcessMD5 · InitiatingProcessFileName · InitiatingProcessFileSize · InitiatingProcessVersionInfoCompanyName · InitiatingProcessVersionInfoProductName · InitiatingProcessVersionInfoProductVersion · InitiatingProcessVersionInfoInternalFileName · InitiatingProcessVersionInfoOriginalFileName · InitiatingProcessVersionInfoFileDescription · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · InitiatingProcessFolderPath · InitiatingProcessParentId · InitiatingProcessParentFileName · InitiatingProcessParentCreationTime · ReportId · AppGuardContainerId · AdditionalFields

Recent processes on a device

Quick triage: every process spawned on a host in the last hour. Replace `<DeviceName>`.

DeviceProcessEvents
| where Timestamp > ago(1h)
| where DeviceName =~ "<DeviceName>"
| project Timestamp, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName
| order by Timestamp desc

Processes spawned by a user in the last 24h

User-scoped activity. Replace `<UserName>`.

DeviceProcessEvents
| where Timestamp > ago(24h)
| where AccountName =~ "<UserName>"
| where AccountName !endswith "$"
| project Timestamp, DeviceName, FileName, ProcessCommandLine, InitiatingProcessFileName
| order by Timestamp desc

LOLBin executions (living-off-the-land binaries)

Built-in binaries adversaries abuse — high-signal when paired with unusual parents/cmdlines.

DeviceProcessEvents
| where Timestamp > ago(7d)
| where AccountName !endswith "$"
| where FileName in~ ("certutil.exe","bitsadmin.exe","mshta.exe","regsvr32.exe",
                      "rundll32.exe","wmic.exe","msbuild.exe","installutil.exe",
                      "wscript.exe","cscript.exe","cmstp.exe","forfiles.exe")
| project Timestamp, DeviceName, AccountName, FileName,
          ProcessCommandLine, InitiatingProcessFileName
| order by Timestamp desc

Office app spawning a script host

Classic macro-payload signal — Word/Excel/Outlook spawning powershell/cmd/wscript.

DeviceProcessEvents
| where Timestamp > ago(7d)
| where AccountName !endswith "$"
| where InitiatingProcessFileName in~ ("winword.exe","excel.exe","powerpnt.exe",
                                         "outlook.exe","onenote.exe","mspub.exe","visio.exe")
| where FileName in~ ("cmd.exe","powershell.exe","pwsh.exe","wscript.exe","cscript.exe",
                       "mshta.exe","rundll32.exe","regsvr32.exe")
| project Timestamp, DeviceName, AccountName,
          ParentImage = InitiatingProcessFolderPath,
          ChildImage  = FolderPath,
          ChildCmd    = ProcessCommandLine
| order by Timestamp desc

PowerShell with `-EncodedCommand` (decode inline)

Decodes the base64 payload right in the result so analysts can read it.

DeviceProcessEvents
| where Timestamp > ago(7d)
| where AccountName !endswith "$"
| where FileName in~ ("powershell.exe","pwsh.exe")
| where ProcessCommandLine has_any ("-EncodedCommand","-enc ","-EC ")
| extend B64 = extract(@"(?i)(?:-(?:e(?:nc(?:odedcommand)?)?))\s+([A-Za-z0-9+/=]{20,})", 1, ProcessCommandLine)
| extend Decoded = base64_decode_tostring(B64)
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, Decoded
| order by Timestamp desc

Suspicious PowerShell flags

Hidden window, no-profile, bypass-policy — common evasion combos.

DeviceProcessEvents
| where Timestamp > ago(7d)
| where AccountName !endswith "$"
| where FileName in~ ("powershell.exe","pwsh.exe")
| where ProcessCommandLine matches regex @"(?i)-w(in)?(dow)?style?\s+h(idden)?|-nop(rofile)?|-ep\s+bypass|frombase64string|invoke-expression|iex\s*\(|net\.webclient"
| project Timestamp, DeviceName, AccountName, ProcessCommandLine, InitiatingProcessFileName
| order by Timestamp desc

Rare child by parent (anti-baseline, 30d)

Anti-baseline join. A child binary spawned by a parent that has never spawned it during the 30d baseline.

let BaselineDays = 30d;
let RecentHours = 4h;
let Baseline = DeviceProcessEvents
    | where Timestamp between (ago(BaselineDays) .. ago(RecentHours))
    | summarize by InitiatingProcessFileName, FileName;
DeviceProcessEvents
| where Timestamp > ago(RecentHours)
| where AccountName !endswith "$"
| where FileName !in~ ("conhost.exe","svchost.exe","backgroundtaskhost.exe",
                       "wermgr.exe","wuauclt.exe","searchindexer.exe")
| join kind=leftanti Baseline on InitiatingProcessFileName, FileName
| project Timestamp, DeviceName, AccountName,
          Parent = InitiatingProcessFileName, Child = FileName,
          ChildCmd = ProcessCommandLine
| order by Timestamp desc

Files run from temp / AppData

Most user-mode malware drops to %TEMP% or %APPDATA% before execution.

DeviceProcessEvents
| where Timestamp > ago(7d)
| where AccountName !endswith "$"
| where FolderPath has_any (@"\AppData\Local\Temp\", @"\AppData\Roaming\",
                             @"\Windows\Temp\", @"\Users\Public\")
| where FileName endswith ".exe" or FileName endswith ".dll"
| project Timestamp, DeviceName, AccountName, FolderPath, FileName,
          ProcessCommandLine, InitiatingProcessFileName, SHA256
| order by Timestamp desc

Process count timechart

Sudden volume spikes — beaconing or compromise-driven hyperactivity.

DeviceProcessEvents
| where Timestamp > ago(7d)
| summarize ProcessCount = count() by bin(Timestamp, 1h), DeviceName
| render timechart with (ytitle="Processes per hour")

Hash IOC sweep

Replace the dynamic list with article-specific hashes.

let BadHashes = dynamic(["<sha256-1>","<sha256-2>"]);
DeviceProcessEvents
| where Timestamp > ago(7d)
| where SHA256 in~ (BadHashes)
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
          InitiatingProcessFileName, SHA256
| order by Timestamp desc

DeviceNetworkEvents

36 columns · 8 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · RemoteIP · RemotePort · RemoteUrl · LocalIP · LocalPort · Protocol · LocalIPType · RemoteIPType · InitiatingProcessSHA1 · InitiatingProcessSHA256 · InitiatingProcessMD5 · InitiatingProcessFileName · InitiatingProcessFileSize · InitiatingProcessVersionInfoCompanyName · InitiatingProcessVersionInfoProductName · InitiatingProcessVersionInfoProductVersion · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · InitiatingProcessFolderPath · InitiatingProcessParentFileName · InitiatingProcessParentId · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessAccountSid · InitiatingProcessAccountUpn · InitiatingProcessAccountObjectId · InitiatingProcessIntegrityLevel · InitiatingProcessTokenElevation · ReportId · AppGuardContainerId · AdditionalFields

Recent outbound from a device

First-look network telemetry. Replace `<DeviceName>`.

DeviceNetworkEvents
| where Timestamp > ago(1h)
| where DeviceName =~ "<DeviceName>"
| where ActionType == "ConnectionSuccess"
| project Timestamp, RemoteIP, RemotePort, RemoteUrl,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Public-IP egress only

Strip out internal-LAN noise — focuses on internet-bound traffic.

DeviceNetworkEvents
| where Timestamp > ago(24h)
| where ActionType == "ConnectionSuccess"
| where RemoteIPType == "Public"
| project Timestamp, DeviceName, RemoteIP, RemotePort, RemoteUrl,
          InitiatingProcessFileName, InitiatingProcessAccountName
| order by Timestamp desc

LOLBin reaching the internet

LOLBin + public destination = high signal. LOLBin alone is noise.

DeviceNetworkEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName in~ (
    "certutil.exe","bitsadmin.exe","mshta.exe","regsvr32.exe","rundll32.exe",
    "msbuild.exe","installutil.exe","wmic.exe","wscript.exe","cscript.exe",
    "cmstp.exe","forfiles.exe","ftp.exe","tftp.exe","odbcconf.exe")
| where RemoteIPType == "Public"
| project Timestamp, DeviceName, InitiatingProcessFileName,
          InitiatingProcessCommandLine, RemoteIP, RemoteUrl, RemotePort
| order by Timestamp desc

Beaconing detector — periodic outbound

Sustained, periodic connections to one destination from one process — C2 signature.

DeviceNetworkEvents
| where Timestamp > ago(2h)
| where RemoteIPType == "Public"
| summarize ConnCount = count(),
            DistinctMinutes = dcount(bin(Timestamp, 1m))
            by DeviceId, DeviceName, RemoteIP, RemotePort, InitiatingProcessFileName
| where ConnCount > 50 and DistinctMinutes > 30   // sustained, not bursty
| order by ConnCount desc

Connections by IP block-list

Bring your own IOC list.

let BadIPs = dynamic(["1.2.3.4","5.6.7.8"]);
DeviceNetworkEvents
| where Timestamp > ago(7d)
| where ActionType in ("ConnectionSuccess","ConnectionAttempt")
| where RemoteIP in (BadIPs)
| project Timestamp, DeviceName, RemoteIP, RemotePort, RemoteUrl,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Rare destination (org-wide first-seen)

Domain seen for the first time across the org in the last hour.

let Baseline = DeviceNetworkEvents
    | where Timestamp between (ago(30d) .. ago(1h))
    | summarize BaselineHosts = dcount(DeviceName) by RemoteUrl
    | where BaselineHosts > 2;
DeviceNetworkEvents
| where Timestamp > ago(1h)
| where isnotempty(RemoteUrl)
| join kind=leftanti Baseline on RemoteUrl
| summarize FirstSeen = min(Timestamp), HostsCount = dcount(DeviceName)
            by RemoteUrl
| order by FirstSeen desc

Top destinations by data volume

If your tenant tracks byte counts. Useful for exfil triage.

DeviceNetworkEvents
| where Timestamp > ago(24h)
| where RemoteIPType == "Public"
| summarize TotalConnections = count(),
            UniqueDevices    = dcount(DeviceName)
            by RemoteUrl, RemoteIP
| order by TotalConnections desc
| take 50

Listening services on a device

Server-side foothold detection. Replace `<DeviceName>`.

DeviceNetworkEvents
| where Timestamp > ago(7d)
| where DeviceName =~ "<DeviceName>"
| where ActionType == "ListeningConnectionCreated"
| project Timestamp, LocalIP, LocalPort, InitiatingProcessFileName,
          InitiatingProcessCommandLine
| order by Timestamp desc

DeviceFileEvents

49 columns · 6 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · FileName · FolderPath · SHA1 · SHA256 · MD5 · FileOriginUrl · FileOriginReferrerUrl · FileOriginIP · PreviousFolderPath · PreviousFileName · FileSize · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessAccountSid · InitiatingProcessAccountUpn · InitiatingProcessAccountObjectId · InitiatingProcessMD5 · InitiatingProcessSHA1 · InitiatingProcessSHA256 · InitiatingProcessFolderPath · InitiatingProcessFileName · InitiatingProcessFileSize · InitiatingProcessVersionInfoCompanyName · InitiatingProcessVersionInfoProductName · InitiatingProcessVersionInfoProductVersion · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · InitiatingProcessIntegrityLevel · InitiatingProcessTokenElevation · InitiatingProcessParentId · InitiatingProcessParentFileName · InitiatingProcessParentCreationTime · RequestProtocol · RequestSourceIP · RequestSourcePort · RequestAccountName · RequestAccountDomain · RequestAccountSid · ShareName · SensitivityLabel · IsAzureInfoProtectionApplied · ReportId · AppGuardContainerId · AdditionalFields

Recent file creates in suspect paths

Most user-mode malware drops to temp/AppData; this is the first-look query.

DeviceFileEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where ActionType == "FileCreated"
| where FolderPath has_any (@"\AppData\Local\Temp\", @"\AppData\Roaming\",
                             @"\Windows\Temp\", @"\Users\Public\")
| where FileName endswith ".exe" or FileName endswith ".dll"
   or FileName endswith ".ps1" or FileName endswith ".bat"
| project Timestamp, DeviceName, FolderPath, FileName, SHA256,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Hash IOC match across files

Sweep file telemetry for known-bad hashes.

let BadHashes = dynamic(["<sha256-1>","<sha256-2>"]);
DeviceFileEvents
| where Timestamp > ago(7d)
| where SHA256 in~ (BadHashes) or SHA1 in~ (BadHashes) or MD5 in~ (BadHashes)
| project Timestamp, DeviceName, ActionType, FileName, FolderPath, SHA256,
          InitiatingProcessFileName, InitiatingProcessAccountName
| order by Timestamp desc

Mass file rename (ransomware)

200+ unique-file renames in a 1-min window from one process — encryption-stage signal.

DeviceFileEvents
| where Timestamp > ago(1d)
| where InitiatingProcessAccountName !endswith "$"
| where ActionType in ("FileRenamed","FileModified")
| summarize files = dcount(FileName)
            by DeviceName, InitiatingProcessAccountName,
               InitiatingProcessFileName, bin(Timestamp, 1m)
| where files > 200
| order by files desc

Browser cookie / login DB access by non-browser

Infostealer (RedLine, Lumma, Vidar) reading Login Data / cookies.

DeviceFileEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where FolderPath has_any (@"\Google\Chrome\User Data\",
                             @"\Microsoft\Edge\User Data\",
                             @"\Mozilla\Firefox\Profiles\")
| where FileName in~ ("Login Data","Cookies","logins.json","cookies.sqlite")
| where InitiatingProcessFileName !in~ ("chrome.exe","msedge.exe","firefox.exe",
                                          "brave.exe","opera.exe")
| project Timestamp, DeviceName, InitiatingProcessAccountName,
          InitiatingProcessFileName, FolderPath, FileName, ActionType
| order by Timestamp desc

Crypto-wallet keystore access by non-wallet process

MetaMask / Exodus / Bitcoin / Phantom keystore touched by something unexpected.

DeviceFileEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where FolderPath has_any (@"\Ethereum\keystore\", @"\Bitcoin\",
                             @"\Exodus\", @"\Electrum\wallets\",
                             @"\MetaMask\", @"\Phantom\",
                             @"\Atomic\Local Storage\")
| where InitiatingProcessFileName !in~ ("MetaMask.exe","Exodus.exe","Atomic.exe",
                                          "electrum.exe","Bitcoin.exe","Phantom.exe")
| project Timestamp, DeviceName, InitiatingProcessAccountName,
          InitiatingProcessFileName, FolderPath, FileName, ActionType
| order by Timestamp desc

Files dropped under a specific user

User-scoped drop hunt. Replace `<UserName>`.

DeviceFileEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName =~ "<UserName>"
| where ActionType == "FileCreated"
| project Timestamp, DeviceName, FolderPath, FileName, SHA256,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

DeviceLogonEvents

27 columns · 6 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · AccountDomain · AccountName · AccountSid · LogonType · RemoteDeviceName · RemoteIP · RemoteIPType · RemotePort · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessAccountSid · InitiatingProcessAccountUpn · InitiatingProcessAccountObjectId · InitiatingProcessFileName · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · ReportId · AppGuardContainerId · FailureReason · IsLocalAdmin · LogonId · Protocol

Failed logons in last 24h

Brute-force / credential-spray triage.

DeviceLogonEvents
| where Timestamp > ago(24h)
| where ActionType == "LogonFailed"
| where AccountName !endswith "$"
| summarize FailCount = count(),
            DistinctTargets = dcount(DeviceName),
            FirstAttempt = min(Timestamp),
            LastAttempt = max(Timestamp)
            by AccountName, RemoteIP, FailureReason
| where FailCount > 5
| order by FailCount desc

Successful RDP from public IP

RemoteInteractive (LogonType 10) from a public source — high-priority review.

DeviceLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where LogonType == "RemoteInteractive"
| where RemoteIPType == "Public"
| where AccountName !endswith "$"
| project Timestamp, DeviceName, AccountName, RemoteIP, RemoteDeviceName,
          IsLocalAdmin, Protocol
| order by Timestamp desc

NTLM where Kerberos is expected

NTLM-over-RDP or NTLM-from-domain-joined-host = pivot signal for cred theft.

DeviceLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where Protocol == "NTLM"
| where LogonType in ("RemoteInteractive","Network")
| where AccountName !endswith "$"
| project Timestamp, DeviceName, AccountName, RemoteIP, LogonType,
          IsLocalAdmin, RemoteDeviceName
| order by Timestamp desc

Local-admin interactive logons

Privilege use — every hit deserves review on production hosts.

DeviceLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where IsLocalAdmin == true
| where LogonType in ("Interactive","RemoteInteractive")
| where AccountName !endswith "$"
| project Timestamp, DeviceName, AccountName, LogonType, RemoteIP, Protocol
| order by Timestamp desc

After-hours interactive logon

Tune the hour bounds for your business. Default: 21:00–06:00 local.

DeviceLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where LogonType == "Interactive"
| where AccountName !endswith "$"
| extend Hour = datetime_part("hour", Timestamp)
| where Hour >= 21 or Hour < 6
| project Timestamp, Hour, DeviceName, AccountName, RemoteIP, IsLocalAdmin
| order by Timestamp desc

Logon-velocity anomaly per account

Account logging on to >5 distinct hosts in 1h — lateral-movement candidate.

DeviceLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where AccountName !endswith "$"
| summarize HostsCount = dcount(DeviceName)
            by AccountName, bin(Timestamp, 1h)
| where HostsCount > 5
| order by HostsCount desc

DeviceImageLoadEvents

21 columns · 4 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · FileName · FolderPath · SHA1 · SHA256 · MD5 · FileSize · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessSHA1 · InitiatingProcessSHA256 · InitiatingProcessMD5 · InitiatingProcessFileName · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · InitiatingProcessFolderPath · ReportId

DLLs loaded by lsass.exe outside System32

Credential-theft tooling loads custom DLLs into LSASS. Drop System32-resident loads.

DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFileName =~ "lsass.exe"
| where FolderPath !startswith @"C:\Windows\"
| project Timestamp, DeviceName, FolderPath, FileName, SHA256
| order by Timestamp desc

Side-loaded DLLs adjacent to dropped binary

DLL search-order hijack. The loaded module sits next to a binary that isn't its expected loader.

DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where InitiatingProcessFolderPath has_any (@"\AppData\Local\Temp\",
                                              @"\AppData\Roaming\",
                                              @"\Windows\Temp\")
| where FolderPath =~ InitiatingProcessFolderPath
   and SHA256 != InitiatingProcessSHA256
| project Timestamp, DeviceName, InitiatingProcessFileName, FileName, FolderPath, SHA256
| order by Timestamp desc

Loads of a specific suspicious DLL

Replace `<dll-name>` with the IOC.

DeviceImageLoadEvents
| where Timestamp > ago(7d)
| where FileName =~ "<dll-name>"
| project Timestamp, DeviceName, FolderPath, FileName, SHA256,
          InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Volume of image loads per device (anomaly)

Sudden surge in DLL loads = injection or unpacking activity.

DeviceImageLoadEvents
| where Timestamp > ago(7d)
| summarize Loads = count() by DeviceName, bin(Timestamp, 1h)
| render timechart with (ytitle="DLL loads per hour")

DeviceRegistryEvents

31 columns · 4 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · RegistryKey · RegistryValueType · RegistryValueName · RegistryValueData · PreviousRegistryKey · PreviousRegistryValueName · PreviousRegistryValueData · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessAccountSid · InitiatingProcessAccountUpn · InitiatingProcessAccountObjectId · InitiatingProcessSHA1 · InitiatingProcessSHA256 · InitiatingProcessMD5 · InitiatingProcessFileName · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · InitiatingProcessFolderPath · InitiatingProcessParentId · InitiatingProcessParentFileName · InitiatingProcessParentCreationTime · InitiatingProcessIntegrityLevel · InitiatingProcessTokenElevation · ReportId · AppGuardContainerId

Run / RunOnce key changes

Classic persistence locations (HKLM + HKCU).

DeviceRegistryEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where ActionType == "RegistryValueSet"
| where RegistryKey has_any (@"\Run", @"\RunOnce")
| where InitiatingProcessFileName !in~ ("msiexec.exe","explorer.exe")
| project Timestamp, DeviceName, InitiatingProcessAccountName, RegistryKey,
          RegistryValueName, RegistryValueData, InitiatingProcessFileName
| order by Timestamp desc

Image File Execution Options (debugger hijack)

Setting `Debugger` under IFEO redirects a binary's launch — common evasion.

DeviceRegistryEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where ActionType == "RegistryValueSet"
| where RegistryKey has @"\Image File Execution Options\"
| where RegistryValueName =~ "Debugger"
| project Timestamp, DeviceName, RegistryKey, RegistryValueData,
          InitiatingProcessFileName
| order by Timestamp desc

Service installation

New Windows service registration — pair with `sc.exe` cmdline check.

DeviceRegistryEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where ActionType == "RegistryKeyCreated"
| where RegistryKey startswith @"HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\"
| project Timestamp, DeviceName, RegistryKey, InitiatingProcessFileName,
          InitiatingProcessCommandLine
| order by Timestamp desc

Browser extension installs

Watch the extension policy keys.

DeviceRegistryEvents
| where Timestamp > ago(7d)
| where InitiatingProcessAccountName !endswith "$"
| where RegistryKey has_any (@"\Software\Google\Chrome\Extensions\",
                              @"\Software\Microsoft\Edge\Extensions\",
                              @"\Software\Mozilla\Firefox\Extensions\")
| project Timestamp, DeviceName, RegistryKey, RegistryValueName,
          RegistryValueData, InitiatingProcessFileName
| order by Timestamp desc

DeviceEvents

43 columns · 5 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ActionType · FileName · FolderPath · SHA1 · SHA256 · MD5 · AccountName · AccountDomain · AccountSid · RemoteUrl · RemoteDeviceName · ProcessId · ProcessCommandLine · ProcessCreationTime · LogonId · RegistryKey · RegistryValueName · RegistryValueData · RemoteIP · RemotePort · LocalIP · LocalPort · FileOriginUrl · AdditionalFields · InitiatingProcessAccountDomain · InitiatingProcessAccountName · InitiatingProcessAccountSid · InitiatingProcessSHA1 · InitiatingProcessSHA256 · InitiatingProcessMD5 · InitiatingProcessFileName · InitiatingProcessId · InitiatingProcessCommandLine · InitiatingProcessCreationTime · InitiatingProcessFolderPath · InitiatingProcessParentId · InitiatingProcessParentFileName · InitiatingProcessParentCreationTime · ReportId · AppGuardContainerId

AMSI scan results — flagged content

AMSI providers scan in-memory script payloads; non-clean ScanResult is high-signal.

DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "AmsiScanResult"
| extend Result = tostring(parse_json(AdditionalFields).ScanResult),
         Content = tostring(parse_json(AdditionalFields).ContentName)
| where Result != "Clean"
| project Timestamp, DeviceName, InitiatingProcessFileName, Content, Result
| order by Timestamp desc

DNS queries to suspect TLDs

TLD-based heuristic.

DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "DnsQueryResponse"
| extend Q = tostring(parse_json(AdditionalFields).QueryName)
| where Q endswith ".onion" or Q endswith ".ru" or Q endswith ".su" or Q endswith ".cn"
| project Timestamp, DeviceName, Q, InitiatingProcessFileName
| order by Timestamp desc

LSASS process access (credential dumping)

Anything opening LSASS that isn't a Microsoft signed component is suspect.

DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "OpenProcessApiCall"
| where FileName =~ "lsass.exe"
| where InitiatingProcessFileName !in~ ("MsSense.exe","MsMpEng.exe","csrss.exe",
                                          "svchost.exe","wininit.exe","services.exe",
                                          "lsm.exe","SearchProtocolHost.exe")
| project Timestamp, DeviceName, ActionType, FileName,
          InitiatingProcessFileName, InitiatingProcessCommandLine,
          InitiatingProcessFolderPath, AccountName
| order by Timestamp desc

USB drive insertion / new external storage

Data-loss-prevention hunt.

DeviceEvents
| where Timestamp > ago(7d)
| where ActionType in ("UsbDriveMount","UsbDriveDriveLetterChanged")
| project Timestamp, DeviceName, InitiatingProcessAccountName,
          AdditionalFields
| order by Timestamp desc

PowerShell ScriptBlock log — suspicious content

Defender records ScriptBlock content for risky payloads.

DeviceEvents
| where Timestamp > ago(7d)
| where ActionType == "PowerShellCommand"
| extend Cmd = tostring(parse_json(AdditionalFields).Command)
| where Cmd matches regex @"(?i)downloadstring|frombase64string|invoke-expression|new-object\s+net\.webclient"
| project Timestamp, DeviceName, InitiatingProcessAccountName,
          InitiatingProcessCommandLine, Cmd
| order by Timestamp desc

DeviceInfo

26 columns · 4 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · ClientVersion · PublicIP · OSArchitecture · OSPlatform · OSBuild · OSVersion · OSRevision · MachineGroup · ReportId · JoinType · AadDeviceId · LoggedOnUsers · RegistryDeviceTag · OSVersionInfo · AdditionalFields · DeviceCategory · DeviceType · DeviceSubtype · Model · Vendor · OSDistribution · IsAzureADJoined · IsInternetFacing

Inventory: OS distribution

Snapshot of OS spread.

DeviceInfo
| where Timestamp > ago(1d)
| summarize Devices = dcount(DeviceName) by OSPlatform, OSVersion
| order by Devices desc

Internet-facing devices

Pivot for prioritising vulnerability triage.

DeviceInfo
| where Timestamp > ago(1d)
| where IsInternetFacing == true
| project DeviceName, OSPlatform, OSVersion, PublicIP, MachineGroup

Find a device by partial name

Replace `<substring>`.

DeviceInfo
| where Timestamp > ago(1d)
| where DeviceName has "<substring>"
| project DeviceName, OSPlatform, OSVersion, MachineGroup, JoinType, IsAzureADJoined

Build dynamic device set for filtering

Use this snippet to scope another query to (e.g.) only Win10 hosts.

let win10 = DeviceInfo
    | where Timestamp > ago(1d)
    | where OSPlatform == "Windows10"
    | summarize make_set(DeviceName);
DeviceProcessEvents
| where DeviceName in (win10)
| where FileName =~ "<binary>"

DeviceNetworkInfo

15 columns · 2 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · NetworkAdapterName · NetworkAdapterType · NetworkAdapterStatus · TunnelType · MacAddress · IPAddresses · IPv4Dhcp · IPv6Dhcp · DefaultGateways · DnsAddresses · ConnectedNetworks · ReportId

Recent IP changes per device

Useful for tracking dynamic-IP movement of a target host.

DeviceNetworkInfo
| where Timestamp > ago(7d)
| mv-expand IP = parse_json(IPAddresses)
| project Timestamp, DeviceName, NetworkAdapterName, IP = tostring(IP.IPAddress)
| order by Timestamp desc

VPN-tunnel adapters

Adapters indicating tunnel software in play.

DeviceNetworkInfo
| where Timestamp > ago(1d)
| where TunnelType !in ("None","")
| project DeviceName, NetworkAdapterName, TunnelType, NetworkAdapterStatus

EmailEvents

37 columns · 5 queries

Schema (click to expand)

Timestamp · NetworkMessageId · InternetMessageId · SenderMailFromAddress · SenderFromAddress · SenderDisplayName · SenderObjectId · SenderMailFromDomain · SenderFromDomain · SenderIPv4 · SenderIPv6 · RecipientEmailAddress · RecipientObjectId · Subject · EmailClusterId · EmailLanguage · EmailDirection · DeliveryAction · DeliveryLocation · PhishConfidenceLevel · ThreatTypes · ThreatNames · DetectionMethods · ConfidenceLevel · EmailAction · EmailActionPolicy · EmailActionPolicyGuid · AttachmentCount · UrlCount · OrgLevelAction · OrgLevelPolicy · UserLevelAction · UserLevelPolicy · ReportId · AdditionalFields · Connectors · AuthenticationDetails

Inbound mail to a recipient

Replace `<user@domain>` to triage one user's mailbox traffic.

EmailEvents
| where Timestamp > ago(24h)
| where EmailDirection == "Inbound"
| where RecipientEmailAddress =~ "<user@domain>"
| project Timestamp, SenderFromAddress, Subject, DeliveryAction,
          DeliveryLocation, NetworkMessageId
| order by Timestamp desc

Phish blocked vs delivered for a sender

Sender-level triage. Replace `<sender@domain>`.

EmailEvents
| where Timestamp > ago(7d)
| where SenderFromAddress =~ "<sender@domain>"
| summarize Count = count() by DeliveryAction, EmailDirection
| order by Count desc

Senders with high recipient fan-out

Mass-mail / spam-spike pattern.

EmailEvents
| where Timestamp > ago(24h)
| where EmailDirection == "Inbound"
| where DeliveryAction == "Delivered"
| summarize Recipients = dcount(RecipientEmailAddress)
            by SenderFromAddress, SenderFromDomain
| where Recipients > 25                      // threshold tuneable
| order by Recipients desc

Authentication-fail mail (SPF/DKIM/DMARC)

Spoofed envelope vs header. Inspect the AuthenticationDetails JSON.

EmailEvents
| where Timestamp > ago(7d)
| where EmailDirection == "Inbound"
| where AuthenticationDetails has_any ("SPF=fail","DKIM=fail","DMARC=fail")
| project Timestamp, SenderMailFromAddress, SenderFromAddress,
          RecipientEmailAddress, Subject, AuthenticationDetails
| order by Timestamp desc

Phish + URL + click — full chain

Joins the three phishing tables for end-to-end correlation.

EmailEvents
| where Timestamp > ago(7d)
| where EmailDirection == "Inbound" and DeliveryAction == "Delivered"
| join kind=inner (
    EmailUrlInfo | project NetworkMessageId, Url, UrlDomain
  ) on NetworkMessageId
| join kind=inner (
    UrlClickEvents
    | where ActionType in ("ClickAllowed","ClickedThrough")
    | project NetworkMessageId, ClickTime = Timestamp, AccountUpn
  ) on NetworkMessageId
| project Timestamp, ClickTime, SenderFromAddress, RecipientEmailAddress,
          Subject, Url, UrlDomain, AccountUpn

EmailUrlInfo

6 columns · 2 queries

Schema (click to expand)

Timestamp · NetworkMessageId · Url · UrlDomain · UrlLocation · ReportId

URLs in mail to a recipient

Useful for retro phish-URL retrieval. Replace `<user@domain>`.

EmailEvents
| where Timestamp > ago(7d)
| where RecipientEmailAddress =~ "<user@domain>"
| join kind=inner (
    EmailUrlInfo | project NetworkMessageId, Url, UrlDomain, UrlLocation
  ) on NetworkMessageId
| project Timestamp, SenderFromAddress, Subject, Url, UrlDomain, UrlLocation
| order by Timestamp desc

All URLs from a specific domain in inbound mail

Replace `<bad-domain.com>`.

EmailUrlInfo
| where Timestamp > ago(30d)
| where UrlDomain =~ "<bad-domain.com>"
| project Timestamp, NetworkMessageId, Url, UrlDomain, UrlLocation
| order by Timestamp desc

EmailAttachmentInfo

14 columns · 3 queries

Schema (click to expand)

Timestamp · NetworkMessageId · SenderFromAddress · RecipientEmailAddress · FileName · FileType · SHA256 · FileSize · MalwareFilterVerdict · MalwareDetectionMethod · ThreatTypes · ThreatNames · DetectionMethods · ReportId

Malicious attachments delivered to mailbox

Defender-verdicted Malware that still landed in user inbox = high-priority remediation.

EmailAttachmentInfo
| where Timestamp > ago(7d)
| where MalwareFilterVerdict == "Malware"
| project Timestamp, SenderFromAddress, RecipientEmailAddress,
          FileName, FileType, FileSize, SHA256, ThreatNames
| order by Timestamp desc

Specific file-type attachments

Hunt for risky attachment types — ISO, IMG, ZIP, HTML.

EmailAttachmentInfo
| where Timestamp > ago(7d)
| where FileType in~ ("ISO","IMG","ZIP","RAR","HTML","HTM","DOCM","XLSM")
| project Timestamp, SenderFromAddress, RecipientEmailAddress,
          FileName, FileType, FileSize, SHA256
| order by Timestamp desc

Attachment SHA256 sweep across endpoints

Match attachment hashes against endpoint file-write telemetry.

let MalHashes = EmailAttachmentInfo
    | where Timestamp > ago(7d)
    | where MalwareFilterVerdict == "Malware"
    | summarize make_set(SHA256);
DeviceFileEvents
| where Timestamp > ago(7d)
| where SHA256 in (MalHashes)
| project Timestamp, DeviceName, FolderPath, FileName, SHA256,
          InitiatingProcessFileName

EmailPostDeliveryEvents

10 columns · 2 queries

Schema (click to expand)

Timestamp · NetworkMessageId · InternetMessageId · Action · ActionType · ActionTrigger · ActionResult · DeliveryLocation · RecipientEmailAddress · ReportId

ZAP (Zero-hour Auto Purge) actions

Defender retroactively yanked a delivered message.

EmailPostDeliveryEvents
| where Timestamp > ago(7d)
| where ActionType == "ZAP"
| project Timestamp, NetworkMessageId, Action, ActionTrigger,
          ActionResult, DeliveryLocation, RecipientEmailAddress
| order by Timestamp desc

User-initiated message deletes

Sometimes a user reports phish themselves; this surfaces those signals.

EmailPostDeliveryEvents
| where Timestamp > ago(7d)
| where ActionTrigger == "User"
| where Action in ("Delete","MoveToJunk")
| project Timestamp, NetworkMessageId, Action, RecipientEmailAddress
| order by Timestamp desc

UrlClickEvents

13 columns · 3 queries

Schema (click to expand)

Timestamp · Url · ActionType · AccountUpn · Workload · NetworkMessageId · ThreatTypes · DetectionMethods · IPAddress · IsClickedThrough · UrlChain · ReportId · Application

All Safe-Links click-throughs (user bypass)

Inherently rare and high-fidelity — Safe Links warned and the user proceeded.

UrlClickEvents
| where Timestamp > ago(30d)
| where ActionType == "ClickedThrough"
| project Timestamp, AccountUpn, IPAddress, Url, Workload, NetworkMessageId
| order by Timestamp desc

Clicks on a domain pattern

Hunt clicks on a brand-impersonation pattern.

UrlClickEvents
| where Timestamp > ago(30d)
| where Url has "<suspect-domain-pattern>"
| project Timestamp, AccountUpn, IPAddress, Url, ActionType, Workload, NetworkMessageId
| order by Timestamp desc

Clicks on URLs not from email (Teams / Office)

Clicks delivered via Teams chat or Office docs, not just mail.

UrlClickEvents
| where Timestamp > ago(7d)
| where Workload != "Email"
| project Timestamp, AccountUpn, IPAddress, Url, Workload, ActionType
| order by Timestamp desc

IdentityLogonEvents

26 columns · 3 queries

Schema (click to expand)

Timestamp · ActionType · Application · LogonType · Protocol · FailureReason · AccountName · AccountDomain · AccountUpn · AccountSid · AccountObjectId · AccountDisplayName · DeviceName · DeviceType · OSPlatform · IPAddress · Port · DestinationDeviceName · DestinationIPAddress · DestinationPort · TargetDeviceName · TargetAccountUpn · Location · IsLocalAdmin · ReportId · AdditionalFields

Failed Kerberos auth (T1110 brute-force)

Repeated failures from one source = spray candidate.

IdentityLogonEvents
| where Timestamp > ago(24h)
| where ActionType == "LogonFailed"
| where Protocol == "Kerberos"
| where AccountName !endswith "$"
| summarize FailCount = count(),
            Targets = dcount(AccountUpn)
            by IPAddress, FailureReason
| where FailCount > 10
| order by FailCount desc

NTLM where Kerberos is expected

NTLM RemoteInteractive on a domain-joined estate is unusual and worth review.

IdentityLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where Protocol == "NTLM" and LogonType == "RemoteInteractive"
| where AccountName !endswith "$"
| project Timestamp, AccountUpn, DeviceName, IPAddress, LogonType, Protocol
| order by Timestamp desc

Service-account interactive logons

Service accounts shouldn't sit at a console. Tune the prefix list.

IdentityLogonEvents
| where Timestamp > ago(7d)
| where ActionType == "LogonSuccess"
| where LogonType in ("Interactive","RemoteInteractive")
| where AccountName startswith "svc-" or AccountName startswith "sa-"
| project Timestamp, AccountUpn, DeviceName, IPAddress, LogonType
| order by Timestamp desc

IdentityQueryEvents

17 columns · 3 queries

Schema (click to expand)

Timestamp · ActionType · Query · QueryTarget · QueryType · Protocol · AccountName · AccountDomain · AccountUpn · AccountSid · AccountObjectId · DeviceName · IPAddress · Port · ReportId · AdditionalFields · Application

BloodHound-style enumeration

All-users LDAP query — recon tooling signature.

IdentityQueryEvents
| where Timestamp > ago(7d)
| where ActionType == "LDAPQuery"
| where Query has "(samAccountType=805306368)"        // user objects
| summarize Count = count() by AccountName, IPAddress, DeviceName
| where Count > 1
| order by Count desc

Kerberoasting recon — SPN enumeration

Querying for accounts with servicePrincipalName.

IdentityQueryEvents
| where Timestamp > ago(7d)
| where ActionType == "LDAPQuery"
| where Query has "servicePrincipalName"
| project Timestamp, AccountName, DeviceName, IPAddress, Query
| order by Timestamp desc

LDAP query volume per source

Outlier-volume detection.

IdentityQueryEvents
| where Timestamp > ago(24h)
| where ActionType == "LDAPQuery"
| summarize Queries = count() by AccountName, DeviceName, IPAddress, bin(Timestamp, 1h)
| where Queries > 200
| order by Queries desc

IdentityDirectoryEvents

19 columns · 3 queries

Schema (click to expand)

Timestamp · ActionType · Application · TargetAccountDisplayName · TargetAccountUpn · AccountName · AccountDomain · AccountUpn · AccountObjectId · AccountDisplayName · DeviceName · IPAddress · Port · DestinationDeviceName · DestinationIPAddress · Location · Protocol · ReportId · AdditionalFields

Privileged-group membership changes

Adds to Domain Admins / Enterprise Admins / DnsAdmins are crown-jewel events.

IdentityDirectoryEvents
| where Timestamp > ago(7d)
| where ActionType == "Group Membership changed"
| where AdditionalFields has_any ("Domain Admins","Enterprise Admins","DnsAdmins",
                                    "Schema Admins","Account Operators")
| project Timestamp, ActionType, AccountUpn,
          TargetAccountUpn, AdditionalFields
| order by Timestamp desc

Forced password resets

Common pre-impersonation step.

IdentityDirectoryEvents
| where Timestamp > ago(7d)
| where ActionType == "Forced password reset"
| project Timestamp, AccountUpn, TargetAccountUpn,
          DestinationDeviceName, DestinationIPAddress
| order by Timestamp desc

New account creation from non-admin source

Account creation outside helpdesk / IT-admin endpoints.

IdentityDirectoryEvents
| where Timestamp > ago(7d)
| where ActionType == "Account created"
| project Timestamp, AccountUpn, TargetAccountUpn,
          DestinationDeviceName, DestinationIPAddress, AdditionalFields
| order by Timestamp desc

IdentityInfo

28 columns · 2 queries

Schema (click to expand)

Timestamp · AccountObjectId · AccountUpn · AccountSid · AccountName · AccountDomain · AccountDisplayName · City · Country · Department · EmailAddress · GivenName · JobTitle · Manager · Phone · Surname · Title · OnPremSid · ReportId · DeletedDateTime · BlockedDateTime · PrivacySetting · AzureADGroup · OrgGroup · EmployeeId · AssignedRoles · Type · IsAccountEnabled

Disabled accounts that have signed in recently

A disabled account producing sign-in events is a major red flag.

AADSignInEventsBeta
| where Timestamp > ago(7d)
| where ErrorCode == 0
| join kind=inner (
    IdentityInfo | project AccountUpn, IsAccountEnabled, JobTitle, Department
  ) on AccountUpn
| where IsAccountEnabled == false
| project Timestamp, AccountUpn, JobTitle, Department, IPAddress, Application
| order by Timestamp desc

Privileged-role members

Enrich with role title / department for triage.

IdentityInfo
| where Timestamp > ago(1d)
| where JobTitle has_any ("CEO","CFO","CISO","CIO","Director","VP","Admin")
| project AccountUpn, JobTitle, Department, City, Country, IsAccountEnabled

AADSignInEventsBeta

47 columns · 6 queries

Schema (click to expand)

Timestamp · Application · ApplicationId · LogonType · ErrorCode · AccountDisplayName · AccountObjectId · AccountUpn · IsExternalUser · IsGuestUser · AlternateSignInName · LastPasswordChangeTimestamp · ResourceDisplayName · ResourceId · ResourceTenantId · DeviceName · AadDeviceId · OSPlatform · DeviceTrustType · Browser · IPAddress · Country · State · City · Latitude · Longitude · NetworkLocationDetails · RequestId · ReportId · ConditionalAccessPolicies · ConditionalAccessStatus · RiskLevelAggregated · RiskLevelDuringSignIn · RiskState · UserAgent · ClientAppUsed · Status · AuthenticationDetails · AuthenticationProcessingDetails · AuthenticationRequirement · TokenIssuerType · IsInteractive · ErrorDetails · AdditionalFields · AppDisplayName · IsAnonymousProxy · IsCompliantUser

Failed sign-ins by user

Replace `<user@domain>`.

AADSignInEventsBeta
| where Timestamp > ago(24h)
| where AccountUpn =~ "<user@domain>"
| where ErrorCode != 0
| project Timestamp, IPAddress, Country, Application, ErrorCode, RiskLevelDuringSignIn
| order by Timestamp desc

Impossible travel

Two successful sign-ins from different countries within 60 minutes.

let WindowMinutes = 60;
AADSignInEventsBeta
| where Timestamp > ago(7d)
| where ErrorCode == 0
| where isnotempty(Country)
| project Timestamp, AccountUpn, Country, City, IPAddress, Application
| order by AccountUpn asc, Timestamp asc
| extend PrevCountry = prev(Country),
         PrevCity    = prev(City),
         PrevTime    = prev(Timestamp),
         PrevAccount = prev(AccountUpn)
| where AccountUpn == PrevAccount
   and Country != PrevCountry
   and datetime_diff('minute', Timestamp, PrevTime) <= WindowMinutes
| project AccountUpn,
          From = PrevCountry, FromTime = PrevTime,
          To = Country, ToTime = Timestamp,
          MinutesDelta = datetime_diff('minute', Timestamp, PrevTime),
          IPAddress, Application
| order by ToTime desc

Legacy auth still in use

`Other clients` = legacy protocols (POP/IMAP/SMTP basic). Should be zero in modern tenants.

AADSignInEventsBeta
| where Timestamp > ago(7d)
| where ClientAppUsed == "Other clients"
| where ErrorCode == 0
| summarize Sessions = count() by AccountUpn, IPAddress, Application
| order by Sessions desc

Sign-ins from anonymous proxy / Tor

IsAnonymousProxy is M365D's tag.

AADSignInEventsBeta
| where Timestamp > ago(7d)
| where IsAnonymousProxy == true
| project Timestamp, AccountUpn, IPAddress, Country, Application,
          ErrorCode, RiskLevelDuringSignIn
| order by Timestamp desc

MFA Challenge failed (push fatigue)

Repeated MFA challenges to the same user from the same IP — push-bombing.

AADSignInEventsBeta
| where Timestamp > ago(24h)
| where ErrorCode == 50158                    // MFA Challenge required / failed
| summarize Attempts = count() by AccountUpn, IPAddress, bin(Timestamp, 5m)
| where Attempts > 3
| order by Attempts desc

New AAD application — first-seen org-wide

First sign-in to an AAD app the tenant has never touched before — illicit-consent risk.

AADSignInEventsBeta
| where Timestamp > ago(7d)
| where ErrorCode == 0
| where Application !in~ ("Microsoft Authenticator","Office 365","Microsoft Office",
                            "Microsoft Teams","Microsoft Edge","Outlook")
| where ResourceId == "00000003-0000-0000-c000-000000000000"   // Microsoft Graph
| summarize FirstSeen = min(Timestamp), LastSeen = max(Timestamp),
            UserCount = dcount(AccountUpn)
            by Application, ApplicationId
| where FirstSeen > ago(2h)
| order by FirstSeen desc

AlertInfo

8 columns · 3 queries

Schema (click to expand)

Timestamp · AlertId · Title · Category · Severity · ServiceSource · DetectionSource · AttackTechniques

New alert titles last 24h

Detection-rule volume / variety.

AlertInfo
| where Timestamp > ago(24h)
| summarize FirstSeen = min(Timestamp), LastSeen = max(Timestamp), Count = count()
            by Title, Category, Severity
| order by Count desc

High / critical alerts only

Severity-scoped triage feed.

AlertInfo
| where Timestamp > ago(7d)
| where Severity in ("High","Medium")
| project Timestamp, AlertId, Title, Category, Severity, ServiceSource, DetectionSource
| order by Timestamp desc

Top MITRE techniques observed

Unique-technique frequency.

AlertInfo
| where Timestamp > ago(7d)
| mv-expand todynamic(AttackTechniques)
| extend Technique = tostring(AttackTechniques)
| summarize Count = count() by Technique
| order by Count desc

AlertEvidence

22 columns · 3 queries

Schema (click to expand)

Timestamp · AlertId · DeviceId · DeviceName · EntityType · EvidenceRole · EvidenceDirection · FileName · FolderPath · SHA1 · SHA256 · FileSize · ThreatFamily · RemoteIP · RemoteUrl · AccountName · AccountDomain · AccountSid · AccountUpn · AccountObjectId · ProcessCommandLine · AdditionalFields

Per-alert entity summary

BluRaven course's alert-context query — answers the analyst's first questions.

AlertEvidence
| where Timestamp > ago(7d)
| join kind=inner AlertInfo on AlertId
| summarize Count = count(),
            FirstTriggered = min(Timestamp),
            LastTriggered  = max(Timestamp),
            DeviceCount    = dcountif(DeviceName, EntityType == "Machine"),
            Devices        = make_set_if(DeviceName, EntityType == "Machine", 50),
            UserCount      = dcountif(AccountUpn, EntityType == "User"),
            Users          = make_set_if(AccountUpn, EntityType == "User", 50),
            Files          = make_set_if(FileName, EntityType == "File", 50),
            IPs            = make_set_if(RemoteIP, EntityType == "Ip", 50)
            by Title, Severity, Category
| order by Count desc

Alerts on a specific device

Pivot to one machine.

AlertEvidence
| where Timestamp > ago(7d)
| where DeviceName =~ "<DeviceName>"
| join kind=inner AlertInfo on AlertId
| project Timestamp, Title, Severity, EntityType, EvidenceRole,
          FileName, RemoteUrl, AccountName
| order by Timestamp desc

All file IOCs across active alerts

Pivot for sweep against `DeviceFileEvents`.

AlertEvidence
| where Timestamp > ago(7d)
| where EntityType == "File" and isnotempty(SHA256)
| summarize Alerts = dcount(AlertId), FirstSeen = min(Timestamp)
            by FileName, SHA256
| order by Alerts desc

CloudAppEvents

28 columns · 3 queries

Schema (click to expand)

Timestamp · ActionType · Application · ApplicationId · AccountObjectId · AccountId · AccountDisplayName · IsAdminOperation · DeviceType · OSPlatform · IPAddress · IsAnonymousProxy · CountryCode · City · ISP · UserAgent · ActivityType · ActivityObjects · ObjectName · ObjectType · ObjectId · ReportId · RawEventData · AdditionalFields · AccountType · RequestId · AppInstanceId · IPTags

New external-domain user activity in OneDrive

External-collaboration risk.

CloudAppEvents
| where Timestamp > ago(7d)
| where Application == "Microsoft OneDrive for Business"
| where AccountDisplayName !endswith "@yourdomain.com"
| project Timestamp, ActionType, AccountDisplayName, ObjectName, IPAddress, CountryCode

Admin actions from anonymous proxy

Admin operation + anonymous source = compromise red-flag.

CloudAppEvents
| where Timestamp > ago(7d)
| where IsAdminOperation == true
| where IsAnonymousProxy == true
| project Timestamp, AccountDisplayName, ActionType, Application,
          IPAddress, CountryCode, UserAgent

Newly authorised SaaS app

First-seen application in tenant audit.

CloudAppEvents
| where Timestamp > ago(7d)
| summarize FirstSeen = min(Timestamp), Activities = count(),
            Users = dcount(AccountObjectId)
            by Application, ApplicationId
| where FirstSeen > ago(1d)
| order by Activities desc

DeviceTvmSoftwareInventory

10 columns · 2 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · OSPlatform · OSVersion · SoftwareVendor · SoftwareName · SoftwareVersion · EndOfSupportStatus · EndOfSupportDate

Outdated browsers on production hosts

Tune `<min-version>` to your target threshold.

DeviceTvmSoftwareInventory
| where Timestamp > ago(1d)
| where SoftwareName has_any ("chrome","msedge","firefox")
| where SoftwareVersion < "<min-version>"
| project DeviceName, OSPlatform, SoftwareVendor, SoftwareName, SoftwareVersion

End-of-support OSes

Where you're knowingly running risk.

DeviceTvmSoftwareInventory
| where Timestamp > ago(1d)
| where EndOfSupportStatus != "Supported"
| project DeviceName, OSPlatform, OSVersion, SoftwareName,
          SoftwareVersion, EndOfSupportStatus, EndOfSupportDate

DeviceTvmSoftwareVulnerabilities

13 columns · 2 queries

Schema (click to expand)

Timestamp · DeviceId · DeviceName · OSPlatform · OSVersion · SoftwareVendor · SoftwareName · SoftwareVersion · CveId · VulnerabilitySeverityLevel · RecommendedSecurityUpdate · RecommendedSecurityUpdateId · AffectedSoftwareSku

Devices vulnerable to a specific CVE

Replace `<CVE-id>`.

DeviceTvmSoftwareVulnerabilities
| where Timestamp > ago(1d)
| where CveId =~ "<CVE-id>"
| project DeviceName, OSPlatform, SoftwareName, SoftwareVersion,
          VulnerabilitySeverityLevel, RecommendedSecurityUpdate

Critical CVEs unpatched

Severity-driven priority list.

DeviceTvmSoftwareVulnerabilities
| where Timestamp > ago(1d)
| where VulnerabilitySeverityLevel == "Critical"
| summarize DeviceCount = dcount(DeviceName) by CveId, SoftwareName
| order by DeviceCount desc

DeviceTvmSoftwareVulnerabilitiesKB

8 columns · 2 queries

Schema (click to expand)

CveId · CvssScore · IsExploitAvailable · VulnerabilitySeverityLevel · LastModifiedTime · PublishedDate · VulnerabilityDescription · AffectedSoftware

Critical CVEs published in the last 30 days

Patch-priority feed.

DeviceTvmSoftwareVulnerabilitiesKB
| where PublishedDate > ago(30d)
| where VulnerabilitySeverityLevel == "Critical"
| project CveId, CvssScore, IsExploitAvailable, PublishedDate
| order by PublishedDate desc

CVEs with public exploit + active in env

Join KB with per-device coverage.

let KnownExploited = DeviceTvmSoftwareVulnerabilitiesKB
    | where IsExploitAvailable == true
    | project CveId;
DeviceTvmSoftwareVulnerabilities
| where Timestamp > ago(1d)
| where CveId in (KnownExploited)
| summarize DeviceCount = dcount(DeviceName), AffectedSoftware = make_set(SoftwareName)
            by CveId, VulnerabilitySeverityLevel
| order by DeviceCount desc

Microsoft Sentinel · KQL Search

Sentinel speaks the same KQL but on a different schema — TimeGenerated instead of Timestamp, SecurityEvent/SigninLogs/OfficeActivity/ASIM Im* instead of the Defender Device* tables. Every query below is schema-validated against the canonical Sentinel column list.

16 tables curated 56 queries 33 schema tables Click Copy on any query to paste into Log Analytics / Sentinel.

SigninLogs

62 columns · 8 queries

Schema (click to expand)

TimeGenerated · OperationName · Identity · Type · Category · UserDisplayName · UserPrincipalName · UserId · UserType · AlternateSignInName · AppId · AppDisplayName · AuthenticationContextClassReferences · AuthenticationDetails · AuthenticationMethodsUsed · AuthenticationProcessingDetails · AuthenticationRequirement · AuthenticationRequirementPolicies · ClientAppUsed · ConditionalAccessPolicies · ConditionalAccessStatus · CreatedDateTime · DeviceDetail · FlaggedForReview · HomeTenantId · HomeTenantName · IPAddress · IsInteractive · IsRisky · IsTenantRestricted · Location · LocationDetails · MfaDetail · NetworkLocationDetails · OriginalRequestId · ProcessingTimeInMilliseconds · ResourceDisplayName · ResourceId · ResourceTenantId · ResourceServicePrincipalId · ResultDescription · ResultSignature · ResultType · RiskDetail · RiskEventTypes · RiskEventTypes_V2 · RiskLevelAggregated · RiskLevelDuringSignIn · RiskState · ServicePrincipalCredentialKeyId · ServicePrincipalCredentialThumbprint · ServicePrincipalId · ServicePrincipalName · SessionLifetimePolicies · Status · TokenIssuerName · TokenIssuerType · UserAgent · AutonomousSystemNumber · CrossTenantAccessType · AppliedConditionalAccessPolicies · _ResourceId

Failed sign-ins for a user

Replace `<user@domain>`. Useful for triaging an account-takeover ticket.

SigninLogs
| where TimeGenerated > ago(24h)
| where UserPrincipalName =~ "<user@domain>"
| where ResultType != 0
| project TimeGenerated, IPAddress, AppDisplayName, ResultType,
          ResultDescription, RiskLevelDuringSignIn,
          ConditionalAccessStatus, ClientAppUsed
| order by TimeGenerated desc

Impossible travel — same user, two countries within 60 minutes

Successful sign-ins from geographically impossible locations — pivot for compromised credentials.

let WindowMinutes = 60;
SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| extend Country = tostring(parse_json(LocationDetails).countryOrRegion)
| where isnotempty(Country)
| project TimeGenerated, UserPrincipalName, Country, IPAddress, AppDisplayName
| order by UserPrincipalName asc, TimeGenerated asc
| extend Prev = prev(Country),
         PrevTime = prev(TimeGenerated),
         PrevAcct = prev(UserPrincipalName)
| where UserPrincipalName == PrevAcct
   and Country != Prev
   and datetime_diff('minute', TimeGenerated, PrevTime) <= WindowMinutes
| project UserPrincipalName, From = Prev, FromTime = PrevTime,
          To = Country, ToTime = TimeGenerated,
          MinutesDelta = datetime_diff('minute', TimeGenerated, PrevTime),
          IPAddress, AppDisplayName
| order by ToTime desc

Legacy authentication still in use

`Other clients` = POP/IMAP/SMTP basic-auth. Should be zero in modern tenants.

SigninLogs
| where TimeGenerated > ago(7d)
| where ClientAppUsed == "Other clients"
| where ResultType == 0
| summarize Sessions = count() by UserPrincipalName, IPAddress, AppDisplayName
| order by Sessions desc

Risky sign-ins (Identity Protection)

Medium / high risk surfaced by AAD risk scoring.

SigninLogs
| where TimeGenerated > ago(7d)
| where RiskLevelDuringSignIn in ("medium","high")
| where ResultType == 0
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName,
          RiskLevelDuringSignIn, RiskState, RiskEventTypes_V2
| order by TimeGenerated desc

Conditional-Access blocked sign-ins

CA Failures — useful for spotting attacker workflows that hit your gates.

SigninLogs
| where TimeGenerated > ago(7d)
| where ConditionalAccessStatus == "Failure"
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName,
          ResultDescription, ConditionalAccessPolicies
| order by TimeGenerated desc

MFA challenge failures (push-bombing detector)

Repeated MFA challenges to the same user from the same source.

SigninLogs
| where TimeGenerated > ago(24h)
| where ResultType == 50158        // MFA Challenge required / failed
| summarize Attempts = count(), FirstSeen = min(TimeGenerated),
            LastSeen = max(TimeGenerated)
            by UserPrincipalName, IPAddress, bin(TimeGenerated, 5m)
| where Attempts > 3
| order by Attempts desc

First sign-in to a new SaaS app

App with zero history that suddenly gets a successful sign-in — illicit-consent risk.

SigninLogs
| where TimeGenerated > ago(7d)
| where ResultType == 0
| where AppDisplayName !in~ ("Microsoft Authenticator","Office 365","Microsoft Office",
                              "Microsoft Teams","Microsoft Edge","Outlook")
| summarize FirstSeen = min(TimeGenerated), Users = dcount(UserPrincipalName),
            UserList = make_set(UserPrincipalName, 20)
            by AppDisplayName, AppId
| where FirstSeen > ago(2h)
| order by FirstSeen desc

Sign-ins from anonymous proxy IPs

Tor / VPN / abuse-listed sources.

SigninLogs
| where TimeGenerated > ago(7d)
| where RiskEventTypes_V2 has_any ("anonymizedIPAddress","tor")
| project TimeGenerated, UserPrincipalName, IPAddress, AppDisplayName,
          ResultType, RiskLevelDuringSignIn
| order by TimeGenerated desc

SecurityEvent

90 columns · 9 queries

Schema (click to expand)

TimeGenerated · Computer · EventID · Channel · Task · Level · Activity · AccessMask · AccessReason · Account · AccountDomain · AccountName · AccountType · AdvancedAuditCategory · AuthenticationPackageName · CallerComputer · CallerLogonId · CallerProcessId · CallerProcessName · ClientId · CommandLine · EventData · EventLevel · EventLevelName · EventSource · EventSourceName · FailureReason · FileHash · FileName · FilePath · IpAddress · IpPort · KeyName · LogonGuid · LogonId · LogonProcessName · LogonType · LogonTypeName · MasterImage · MemberName · MemberSid · NewProcessId · NewProcessName · OperationsManagerCleared · OriginatorPid · ParentProcessName · PrivilegeList · ProcessId · ProcessName · Protocol · Provider · RestrictedSidCount · ServiceName · ServiceSid · SidHistory · Source · SourceComputerId · SourceDomain · SourceUserName · Status · SubjectAccount · SubjectDomainName · SubjectLogonId · SubjectUserName · SubjectUserSid · SubStatus · TargetAccount · TargetDomainName · TargetLinkedLogonId · TargetLogonGuid · TargetLogonId · TargetUserName · TargetUserSid · TargetServerName · TargetSid · TokenElevationType · TransmittedServices · UserSid · WorkstationName · _ResourceId · ObjectName · ObjectType · ObjectServer · ObjectValueName · ServiceFileName · ServiceType · ServiceStartType · ServiceAccount · HandleId · OperationType

Failed interactive logons (4625)

Brute-force / credential-spray triage. Excludes machine-accounts and service logons.

SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID == 4625
| where Account !endswith "$"
| where LogonType in (2, 10)        // Interactive, RemoteInteractive
| summarize Failures = count(),
            FirstSeen = min(TimeGenerated),
            LastSeen = max(TimeGenerated),
            Targets = dcount(Computer)
            by Account, IpAddress, FailureReason
| where Failures > 5
| order by Failures desc

New process creation (4688)

Requires Audit Process Creation policy + 'Include command line in process creation events'.

SecurityEvent
| where TimeGenerated > ago(24h)
| where EventID == 4688
| where Account !endswith "$"
| project TimeGenerated, Computer, Account,
          NewProcessName, CommandLine, ParentProcessName,
          TokenElevationType
| order by TimeGenerated desc

Office app spawning a script host (4688)

Word/Excel/Outlook spawning powershell/cmd/wscript — macro-payload signature.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4688
| where Account !endswith "$"
| where ParentProcessName endswith "\winword.exe"
   or ParentProcessName endswith "\excel.exe"
   or ParentProcessName endswith "\powerpnt.exe"
   or ParentProcessName endswith "\outlook.exe"
| where NewProcessName endswith "\powershell.exe"
   or NewProcessName endswith "\cmd.exe"
   or NewProcessName endswith "\wscript.exe"
   or NewProcessName endswith "\cscript.exe"
   or NewProcessName endswith "\mshta.exe"
| project TimeGenerated, Computer, Account,
          ParentProcessName, NewProcessName, CommandLine

PowerShell with -EncodedCommand (decode inline)

Decodes the base64 payload right in the result — same as the Defender pattern.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4688
| where Account !endswith "$"
| where NewProcessName endswith "\powershell.exe" or NewProcessName endswith "\pwsh.exe"
| where CommandLine has_any ("-EncodedCommand","-enc ","-EC ")
| extend B64 = extract(@"(?i)(?:-(?:e(?:nc(?:odedcommand)?)?))\s+([A-Za-z0-9+/=]{20,})", 1, CommandLine)
| extend Decoded = base64_decode_tostring(B64)
| project TimeGenerated, Computer, Account, CommandLine, B64, Decoded
| order by TimeGenerated desc

RDP from public IP (4624 LogonType 10)

Successful RemoteInteractive from a public source — high-priority review.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4624
| where LogonType == 10            // RemoteInteractive (RDP)
| where ipv4_is_private(IpAddress) == false
| where Account !endswith "$"
| project TimeGenerated, Computer, Account, IpAddress, WorkstationName,
          AuthenticationPackageName
| order by TimeGenerated desc

Service installation (4697)

Direct service-install signal — pair with image path under user-writable dir for persistence.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4697
| where SubjectUserName !endswith "$"
| project TimeGenerated, Computer, SubjectUserName, ServiceName,
          ServiceFileName, ServiceType, ServiceStartType, ServiceAccount
| order by TimeGenerated desc

LSASS object access (4663)

Anything reading LSASS memory that isn't a Microsoft signed component is suspect.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4663
| where ObjectName endswith "\lsass.exe"
| where Account !endswith "$"
| project TimeGenerated, Computer, Account, ObjectName, ProcessName,
          AccessMask, AccessReason

Account created (4720)

New local user account.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4720
| project TimeGenerated, Computer, SubjectUserName, TargetUserName,
          TargetDomainName

After-hours interactive logon

Tune the hour bounds for your business. Default: 21:00–06:00 local.

SecurityEvent
| where TimeGenerated > ago(7d)
| where EventID == 4624
| where LogonType == 2           // Interactive
| where Account !endswith "$"
| extend Hour = datetime_part("hour", TimeGenerated)
| where Hour >= 21 or Hour < 6
| project TimeGenerated, Hour, Computer, Account, IpAddress
| order by TimeGenerated desc

AuditLogs

19 columns · 4 queries

Schema (click to expand)

TimeGenerated · OperationName · Category · Identity · ActivityDateTime · ActivityDisplayName · AdditionalDetails · InitiatedBy · TargetResources · LoggedByService · OperationType · Result · ResultReason · ResultDescription · ResultSignature · AADTenantId · CorrelationId · Type · _ResourceId

Privileged-role membership changes

Adds to Global Admin / Privileged Role Admin / App Admin.

AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName has "Add member to role"
| extend RoleName = tostring(parse_json(tostring(TargetResources))[0].displayName),
         Member = tostring(parse_json(tostring(TargetResources))[1].displayName),
         Initiator = tostring(parse_json(tostring(InitiatedBy)).user.userPrincipalName)
| where RoleName has_any ("Global Administrator","Privileged Role Administrator",
                           "Application Administrator","User Access Administrator",
                           "Cloud Application Administrator")
| project TimeGenerated, Initiator, Member, RoleName, Result

New OAuth app consent grants

User consenting to a third-party app — illicit-consent attack precursor.

AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName has "Consent to application"
| where Result =~ "success"
| extend AppName = tostring(parse_json(tostring(TargetResources))[0].displayName),
         User = tostring(parse_json(tostring(InitiatedBy)).user.userPrincipalName)
| project TimeGenerated, OperationName, User, AppName, Result, AdditionalDetails
| order by TimeGenerated desc

Password resets (forced or self-service)

Common pre-impersonation step.

AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName in~ ("Reset password (by admin)","Reset user password",
                            "Self-service password reset")
| extend Initiator = tostring(parse_json(tostring(InitiatedBy)).user.userPrincipalName),
         Target = tostring(parse_json(tostring(TargetResources))[0].userPrincipalName)
| project TimeGenerated, OperationName, Initiator, Target, Result

New service principal / application created

Pivot for OAuth-app-based persistence.

AuditLogs
| where TimeGenerated > ago(7d)
| where OperationName in~ ("Add service principal","Add application")
| extend AppName = tostring(parse_json(tostring(TargetResources))[0].displayName),
         User = tostring(parse_json(tostring(InitiatedBy)).user.userPrincipalName)
| project TimeGenerated, OperationName, User, AppName, Result

OfficeActivity

54 columns · 4 queries

Schema (click to expand)

TimeGenerated · OfficeWorkload · Operation · RecordType · ResultStatus · UserKey · UserType · UserId · ClientIP · UserAgent · ItemType · OrganizationId · OrganizationName · OfficeId · ApplicationId · EventSource · ItemName · ParameterName · ParameterValue · EventData · ClientInfoString · Site_Url · ObjectId · SourceFileName · DestinationFileName · SourceFileExtension · DestinationFileExtension · SourceRelativeUrl · DestinationRelativeUrl · SourceFileSize · DestinationFileSize · ObjectFolderPath · SiteName · ListName · ListItemUniqueId · OriginatingServer · ExternalAccess · MailboxOwnerUPN · MailboxOwnerSid · ItemSize · ItemAttachments · MessageId · ClientIPAddress · MailboxGuid · InternetMessageId · Subject · Sender · Recipients · P2Sender · P2RecipientList · DeliveryAction · Verdict · _ResourceId · Parameters

New mailbox inbox rules

BEC artefact — attacker forwards / hides inbound mail.

OfficeActivity
| where TimeGenerated > ago(7d)
| where OfficeWorkload == "Exchange"
| where Operation in~ ("New-InboxRule","Set-InboxRule")
| where ResultStatus == "Succeeded"
| project TimeGenerated, UserId, ClientIP, Operation, Parameters
| order by TimeGenerated desc

Mass file download from SharePoint / OneDrive

Exfil via file-share. Tune the > 100 threshold to estate baseline.

OfficeActivity
| where TimeGenerated > ago(7d)
| where OfficeWorkload in ("SharePoint","OneDrive")
| where Operation =~ "FileDownloaded"
| summarize Files = dcount(SourceFileName), Sites = make_set(Site_Url, 10)
            by UserId, bin(TimeGenerated, 5m)
| where Files > 100
| order by Files desc

External-domain user accessing internal SharePoint

External-collab risk.

OfficeActivity
| where TimeGenerated > ago(7d)
| where OfficeWorkload == "SharePoint"
| where Operation in~ ("FileAccessed","FileDownloaded","ListItemViewed")
| where UserId !endswith "@yourdomain.com"
| project TimeGenerated, UserId, Operation, Site_Url, SourceFileName, ClientIP

Teams external-tenant chat

Tenant-boundary-crossing chats — potential vishing setup.

OfficeActivity
| where TimeGenerated > ago(7d)
| where OfficeWorkload == "MicrosoftTeams"
| where Operation in~ ("MessageSent","ChatCreated","TeamsImpersonationDetected")
| project TimeGenerated, UserId, Operation, Subject, Recipients,
          ClientIP, UserAgent
| order by TimeGenerated desc

AzureActivity

27 columns · 3 queries

Schema (click to expand)

TimeGenerated · OperationNameValue · OperationName · Category · CategoryValue · Authorization · Caller · CallerIpAddress · ResourceGroup · ResourceProvider · ResourceProviderValue · ResourceId · EventSubmissionTimestamp · ActivityStatus · ActivityStatusValue · ActivitySubstatusValue · Properties · ResourceGroupName · OperationId · CorrelationId · EventStartTime · EventEndTime · Level · EventDataId · TenantId · SubscriptionId · _ResourceId

Role-assignment writes outside known IT

RBAC changes are crown-jewel events.

AzureActivity
| where TimeGenerated > ago(7d)
| where OperationNameValue =~ "Microsoft.Authorization/roleAssignments/write"
| where ActivityStatusValue == "Succeeded"
| project TimeGenerated, Caller, CallerIpAddress, ResourceId,
          OperationNameValue, Properties

Key Vault secret reads

Frequent reads from a single caller can indicate credential-harvesting.

AzureActivity
| where TimeGenerated > ago(7d)
| where OperationNameValue =~ "Microsoft.KeyVault/vaults/secrets/read"
| where ActivityStatusValue == "Succeeded"
| summarize Reads = count(), Vaults = dcount(ResourceId),
            Secrets = dcount(tostring(parse_json(tostring(Properties)).resource))
            by Caller, CallerIpAddress
| order by Reads desc

Storage account public-access changes

Storage-container public-blob exposure.

AzureActivity
| where TimeGenerated > ago(7d)
| where OperationNameValue has "Microsoft.Storage/storageAccounts"
| where OperationNameValue has "write"
| project TimeGenerated, Caller, CallerIpAddress, ResourceId,
          OperationNameValue, ActivityStatusValue, Properties
| order by TimeGenerated desc

Syslog

12 columns · 3 queries

Schema (click to expand)

TimeGenerated · Computer · HostName · Facility · FacilityName · SeverityLevel · SyslogMessage · ProcessID · ProcessName · HostIP · EventTime · _ResourceId

Failed sudo attempts

Linux brute-force / privilege-test signal.

Syslog
| where TimeGenerated > ago(24h)
| where Facility =~ "authpriv"
| where SyslogMessage has "sudo:" and SyslogMessage has "FAILED"
| project TimeGenerated, Computer, HostIP, SyslogMessage
| order by TimeGenerated desc

SSH key-based logon

Tracks publickey auth — useful for pivoting on lateral movement.

Syslog
| where TimeGenerated > ago(7d)
| where ProcessName =~ "sshd"
| where SyslogMessage has "Accepted publickey"
| extend SrcIp = extract(@"from\s+(\S+)", 1, SyslogMessage),
         User  = extract(@"for\s+(\S+)\s+from", 1, SyslogMessage)
| project TimeGenerated, Computer, User, SrcIp, SyslogMessage

Audit-policy / sudoers modifications

Tampering with audit infrastructure.

Syslog
| where TimeGenerated > ago(7d)
| where Facility =~ "authpriv" or Facility =~ "auth"
| where SyslogMessage has_any ("/etc/sudoers","/etc/audit","auditctl",
                                "auditd","sudoers.d")
| project TimeGenerated, Computer, ProcessName, SyslogMessage

DnsEvents

15 columns · 2 queries

Schema (click to expand)

TimeGenerated · Computer · ClientIP · Name · QueryType · QueryTypeName · QueryClass · QueryClassName · ResultCode · ResultCodeName · Result · Question · ServerIPAddress · RemoteIp · _ResourceId

Queries to suspect TLDs

Onion / russian / tonkin TLDs.

DnsEvents
| where TimeGenerated > ago(7d)
| where Name endswith ".onion" or Name endswith ".duckdns.org"
| project TimeGenerated, Computer, ClientIP, Name, QueryTypeName, ResultCodeName

DNS-tunnel candidate (TXT-heavy)

Frequent TXT lookups from one source — DNS-tunneling exfil.

DnsEvents
| where TimeGenerated > ago(24h)
| where QueryTypeName == "TXT"
| summarize Queries = count(), DistinctNames = dcount(Name)
            by ClientIP, bin(TimeGenerated, 5m)
| where Queries > 200
| order by Queries desc

CommonSecurityLog

82 columns · 3 queries

Schema (click to expand)

TimeGenerated · DeviceVendor · DeviceProduct · DeviceVersion · DeviceEventClassID · Activity · LogSeverity · DeviceAction · ApplicationProtocol · EventCount · DestinationDnsDomain · DestinationServiceName · DestinationTranslatedAddress · DestinationTranslatedPort · CommunicationDirection · DeviceDnsDomain · DeviceExternalID · DeviceFacility · DeviceInboundInterface · DeviceNtDomain · DeviceOutboundInterface · ProcessName · DeviceTranslatedAddress · DestinationHostName · DestinationMACAddress · DestinationNTDomain · DestinationProcessId · DestinationUserPrivileges · DestinationProcessName · DestinationPort · DestinationIP · DeviceTimeZone · DeviceAddress · DeviceMacAddress · DeviceProcessId · EventOutcome · ExternalID · FileCreateTime · FileHash · FileID · FileModificationTime · FilePath · FilePermission · FileType · FileName · FileSize · ReceiptTime · Message · EndTime · RequestClientApplication · RequestContext · RequestCookies · RequestMethod · ReceivedBytes · DeviceReceiptTime · RequestURL · SentBytes · SourceHostName · SourceMACAddress · SourceNTDomain · SourceDnsDomain · SourceServiceName · SourceTranslatedAddress · SourceTranslatedPort · SourceProcessId · SourceUserPrivileges · SourceProcessName · SourcePort · SourceIP · StartTime · SourceUserID · SourceUserName · EventType · AccountName · AccountID · _ResourceId · DeviceCustomString1 · DeviceCustomString2 · DeviceCustomString3 · DeviceCustomString4 · DeviceCustomString5 · DeviceCustomString6

Firewall denies from public sources

Vendor-agnostic FW deny digest. Pin DeviceVendor + DeviceProduct first.

CommonSecurityLog
| where TimeGenerated > ago(24h)
| where Activity has "deny" or DeviceAction has "deny"
| where ipv4_is_private(SourceIP) == false
| summarize Hits = count() by DeviceVendor, DeviceProduct,
            SourceIP, DestinationIP, DestinationPort, DeviceAction
| order by Hits desc

Web-proxy threat-categorised hits

Vendor-specific category mapping — adjust to your tenant's connector.

CommonSecurityLog
| where TimeGenerated > ago(24h)
| where DeviceVendor =~ "Zscaler"
| where DeviceCustomString1 has_any ("malware","phishing","botnet","spyware")
| project TimeGenerated, SourceIP, SourceUserName,
          DestinationHostName, RequestURL, DeviceCustomString1

File hash matches (NGFW IPS / Sandbox)

Replace `<bad-hash>`.

CommonSecurityLog
| where TimeGenerated > ago(7d)
| where FileHash =~ "<bad-hash>"
| project TimeGenerated, DeviceVendor, DeviceProduct, FileName, FileHash,
          SourceIP, DestinationIP, RequestURL, Message

ThreatIntelligenceIndicator

40 columns · 2 queries

Schema (click to expand)

TimeGenerated · SourceSystem · Action · Active · ConfidenceScore · Confidence · Description · ExpirationDateTime · Indicator · IndicatorId · InternalId · IsActive · LastUpdateTime · Tags · ThreatType · Url · EmailSourceDomain · EmailSourceIpAddress · EmailSubject · EmailRecipient · EmailSenderName · EmailSenderAddress · FileHashType · FileHashValue · FileName · FileType · FileSize · FilePacker · FileMutexName · DomainName · NetworkIP · NetworkSourceIP · NetworkDestinationIP · NetworkPort · NetworkSourcePort · NetworkDestinationPort · NetworkProtocol · NetworkCidrBlock · Type · _ResourceId

Active TI feed sweep against network logs

Pulls all active TI indicators and sweeps against CommonSecurityLog destinations.

let Active = ThreatIntelligenceIndicator
    | where TimeGenerated > ago(30d)
    | where Active == true and ExpirationDateTime > now()
    | summarize arg_max(TimeGenerated, *) by IndicatorId
    | where isnotempty(NetworkIP);
CommonSecurityLog
| where TimeGenerated > ago(7d)
| join kind=inner (Active | project NetworkIP, ThreatType, ConfidenceScore)
    on $left.DestinationIP == $right.NetworkIP
| project TimeGenerated, SourceIP, SourceUserName, DestinationIP,
          ThreatType, ConfidenceScore, Activity

File-hash IOC sweep

TI indicator hashes vs. SecurityEvent / ImFileEvent file telemetry.

let BadHashes = ThreatIntelligenceIndicator
    | where TimeGenerated > ago(30d)
    | where Active == true
    | where isnotempty(FileHashValue)
    | distinct FileHashValue;
ImFileEvent
| where TimeGenerated > ago(7d)
| where TargetFileSHA256 in (BadHashes) or TargetFileSHA1 in (BadHashes)
   or TargetFileMD5 in (BadHashes)
| project TimeGenerated, DvcHostname, ActorUsername, TargetFileName,
          TargetFilePath, TargetFileSHA256

SecurityAlert

27 columns · 2 queries

Schema (click to expand)

TimeGenerated · AlertName · AlertSeverity · Description · ProviderName · VendorName · VendorOriginalId · SystemAlertId · ResourceId · SourceComputerId · AlertType · ConfidenceLevel · ConfidenceScore · IsIncident · StartTime · EndTime · ProcessingEndTime · RemediationSteps · ExtendedProperties · Entities · Status · CompromisedEntity · Tactics · Techniques · ProductComponentName · ProductName · _ResourceId

High-severity alerts from MDE / Defender for Identity

Severity-scoped triage feed.

SecurityAlert
| where TimeGenerated > ago(24h)
| where AlertSeverity in ("High","Medium")
| where ProviderName has_any ("MDATP","AAD Identity Protection","Azure Sentinel",
                                "MicrosoftDefenderForCloud","ASC")
| project TimeGenerated, AlertName, AlertSeverity, ProviderName,
          CompromisedEntity, Description

Per-host incident summary

Group alerts by impacted host for triage.

SecurityAlert
| where TimeGenerated > ago(7d)
| extend Hosts = parse_json(Entities)
| mv-expand Hosts
| where tostring(Hosts.Type) == "host"
| extend Host = tostring(Hosts.HostName)
| summarize Alerts = count(), Names = make_set(AlertName, 5),
            FirstSeen = min(TimeGenerated)
            by Host, AlertSeverity
| order by Alerts desc

ImProcessCreate

77 columns · 5 queries

Schema (click to expand)

TimeGenerated · EventCount · EventType · EventResult · EventOriginalUid · EventSeverity · EventStartTime · EventEndTime · EventVendor · EventProduct · EventSchemaVersion · EventReportUrl · EventOwner · EventOriginalType · EventOriginalSeverity · DvcIpAddr · DvcHostname · DvcDomain · DvcOs · DvcOsVersion · DvcAction · ActorUsernameType · ActorUsername · ActorUserType · ActorUserId · ActorUserIdType · ActorSessionId · ActorScopeId · ActorScope · ActorOriginalUserType · TargetUsername · TargetUserId · TargetUserIdType · TargetUserType · TargetSessionId · TargetUserScope · TargetUserScopeId · TargetOriginalUserType · ActingProcessCommandLine · ActingProcessName · ActingProcessId · ActingProcessGuid · ActingProcessIntegrityLevel · ActingProcessFileSize · ActingProcessFileVersion · ActingProcessFileCompany · ActingProcessFileDescription · ActingProcessFileProduct · ActingProcessFileInternalName · ActingProcessFileOriginalName · ActingProcessSessionId · ActingProcessIsHidden · ParentProcessCommandLine · ParentProcessName · ParentProcessId · ParentProcessGuid · ParentProcessIntegrityLevel · ParentProcessFileCompany · ParentProcessFileDescription · TargetProcessCommandLine · TargetProcessName · TargetProcessId · TargetProcessGuid · TargetProcessIntegrityLevel · TargetProcessFileCompany · TargetProcessFileDescription · TargetProcessSessionId · TargetProcessIsHidden · Hashes · Hash · HashType · MD5 · SHA1 · SHA256 · SHA512 · _ResourceId · Computer

Cross-vendor process create — Office spawning script host

Same shape as the SecurityEvent 4688 query but vendor-agnostic via ASIM.

ImProcessCreate
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where ParentProcessName in~ ("winword.exe","excel.exe","powerpnt.exe",
                                 "outlook.exe","onenote.exe")
| where TargetProcessName in~ ("powershell.exe","pwsh.exe","cmd.exe",
                                 "wscript.exe","cscript.exe","mshta.exe")
| project TimeGenerated, DvcHostname, ActorUsername,
          ParentProcessName, TargetProcessName, TargetProcessCommandLine
| order by TimeGenerated desc

LOLBin executions (cross-vendor)

Living-off-the-land binaries normalised across MDE / Sysmon / AuditD / etc.

ImProcessCreate
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where TargetProcessName in~ ("certutil.exe","bitsadmin.exe","mshta.exe",
                                 "regsvr32.exe","rundll32.exe","wmic.exe",
                                 "msbuild.exe","installutil.exe","cmstp.exe")
| project TimeGenerated, DvcHostname, ActorUsername,
          TargetProcessName, TargetProcessCommandLine, ParentProcessName

PowerShell with suspicious flags

Hidden window, no-profile, bypass — common evasion combos.

ImProcessCreate
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where TargetProcessName in~ ("powershell.exe","pwsh.exe")
| where TargetProcessCommandLine matches regex @"(?i)-w(in)?(dow)?style?\s+h(idden)?|-nop(rofile)?|-ep\s+bypass|frombase64string|invoke-expression|iex\s*\(|net\.webclient"
| project TimeGenerated, DvcHostname, ActorUsername,
          TargetProcessCommandLine, ParentProcessName

Files run from temp / AppData

User-mode malware staging area.

ImProcessCreate
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where TargetProcessName has_any (@"\AppData\Local\Temp\",
                                     @"\AppData\Roaming\",
                                     @"\Windows\Temp\",
                                     @"\Users\Public\")
| project TimeGenerated, DvcHostname, ActorUsername,
          TargetProcessName, TargetProcessCommandLine, SHA256

Hash IOC sweep (cross-vendor)

Replace the dynamic list with article-specific hashes.

let BadHashes = dynamic(["<sha256-1>","<sha256-2>"]);
ImProcessCreate
| where TimeGenerated > ago(7d)
| where SHA256 in~ (BadHashes) or MD5 in~ (BadHashes) or SHA1 in~ (BadHashes)
| project TimeGenerated, DvcHostname, ActorUsername,
          TargetProcessName, TargetProcessCommandLine, SHA256

ImNetworkSession

34 columns · 3 queries

Schema (click to expand)

TimeGenerated · EventCount · EventType · EventResult · EventOriginalUid · EventSeverity · EventStartTime · EventEndTime · EventVendor · EventProduct · DvcIpAddr · DvcHostname · SrcIpAddr · SrcPortNumber · SrcHostname · SrcDomain · SrcUsername · SrcMacAddr · DstIpAddr · DstPortNumber · DstHostname · DstDomain · DstUsername · DstMacAddr · NetworkProtocol · NetworkApplicationProtocol · NetworkDirection · NetworkBytes · NetworkPackets · NetworkSessionId · NetworkDuration · DvcAction · Url · _ResourceId

Egress to public IP

Internet-bound network sessions only.

ImNetworkSession
| where TimeGenerated > ago(24h)
| where DvcAction != "Block"
| where ipv4_is_private(DstIpAddr) == false
| project TimeGenerated, DvcHostname, SrcIpAddr, DstIpAddr,
          DstPortNumber, NetworkProtocol, NetworkBytes
| order by TimeGenerated desc

Beaconing detector

Sustained periodic outbound to one destination — C2 signature.

ImNetworkSession
| where TimeGenerated > ago(2h)
| where ipv4_is_private(DstIpAddr) == false
| summarize ConnCount = count(),
            DistinctMinutes = dcount(bin(TimeGenerated, 1m))
            by DvcHostname, DstIpAddr, DstPortNumber
| where ConnCount > 50 and DistinctMinutes > 30
| order by ConnCount desc

Connections to a domain pattern

Use Url field for HTTP-aware connectors. Replace `<pattern>`.

ImNetworkSession
| where TimeGenerated > ago(7d)
| where Url has "<pattern>"
| project TimeGenerated, DvcHostname, SrcIpAddr, Url,
          DstIpAddr, DstPortNumber, NetworkProtocol

ImAuthentication

33 columns · 2 queries

Schema (click to expand)

TimeGenerated · EventCount · EventType · EventResult · EventResultDetails · EventOriginalUid · EventSeverity · EventStartTime · EventEndTime · EventVendor · EventProduct · DvcIpAddr · DvcHostname · DvcDomain · DvcOs · TargetUsername · TargetUserId · TargetUsernameType · TargetUserType · TargetSessionId · ActorUsername · ActorUserId · ActorUsernameType · ActorUserType · SrcIpAddr · SrcHostname · SrcDomain · LogonMethod · LogonProtocol · TargetAppId · TargetAppName · TargetAppType · _ResourceId

Cross-vendor authentication failures

Aggregates failed auth across cloud + on-prem connectors.

ImAuthentication
| where TimeGenerated > ago(24h)
| where EventResult == "Failure"
| where TargetUsername !endswith "$"
| summarize Failures = count(), FirstSeen = min(TimeGenerated),
            LastSeen = max(TimeGenerated)
            by TargetUsername, SrcIpAddr, EventVendor
| where Failures > 5
| order by Failures desc

Anomalous logon protocol

NTLM where Kerberos is expected — pivot signal.

ImAuthentication
| where TimeGenerated > ago(7d)
| where EventResult == "Success"
| where LogonProtocol =~ "NTLM"
| where TargetUsername !endswith "$"
| project TimeGenerated, DvcHostname, TargetUsername, SrcIpAddr,
          LogonProtocol, LogonMethod, EventVendor
| order by TimeGenerated desc

ImFileEvent

33 columns · 2 queries

Schema (click to expand)

TimeGenerated · EventCount · EventType · EventResult · EventStartTime · EventEndTime · EventVendor · EventProduct · DvcIpAddr · DvcHostname · DvcDomain · ActorUsername · ActorUserId · ActorUsernameType · ActorUserType · ActingProcessCommandLine · ActingProcessName · ActingProcessId · ActingProcessGuid · TargetFilePath · TargetFilePathType · TargetFileName · TargetFileExtension · TargetFileSize · TargetFileMD5 · TargetFileSHA1 · TargetFileSHA256 · TargetFileSHA512 · Hashes · Hash · HashType · DvcAction · _ResourceId

File creates in suspect paths

User-mode malware staging.

ImFileEvent
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where EventType == "FileCreated"
| where TargetFilePath has_any (@"\AppData\Local\Temp\",
                                  @"\AppData\Roaming\",
                                  @"\Windows\Temp\")
| where TargetFileName endswith ".exe" or TargetFileName endswith ".dll"
   or TargetFileName endswith ".ps1"
| project TimeGenerated, DvcHostname, ActorUsername, TargetFilePath,
          TargetFileName, TargetFileSHA256

Cross-vendor mass file rename (ransomware)

Threshold-based encryption signal across MDE / Sysmon / AuditD.

ImFileEvent
| where TimeGenerated > ago(1d)
| where ActorUsername !endswith "$"
| where EventType in ("FileRenamed","FileModified")
| summarize files = dcount(TargetFileName)
            by DvcHostname, ActorUsername, ActingProcessName, bin(TimeGenerated, 1m)
| where files > 200
| order by files desc

ImDnsActivity

28 columns · 2 queries

Schema (click to expand)

TimeGenerated · EventCount · EventType · EventResult · EventResultDetails · EventOriginalUid · EventSeverity · EventStartTime · EventEndTime · EventVendor · EventProduct · DvcIpAddr · DvcHostname · SrcIpAddr · SrcHostname · SrcUsername · DstIpAddr · DstHostname · DnsQuery · DnsQueryName · DnsQueryType · DnsQueryTypeName · DnsResponseCode · DnsResponseCodeName · DnsResponseName · ThreatCategory · ThreatName · _ResourceId

Cross-vendor DNS queries to suspect TLDs

Normalised across Win DNS, Sysmon EID 22, Linux dnsmasq.

ImDnsActivity
| where TimeGenerated > ago(7d)
| where DnsQuery endswith ".onion"
   or DnsQuery endswith ".ru"
   or DnsQuery endswith ".su"
| project TimeGenerated, DvcHostname, SrcIpAddr, DnsQuery,
          DnsQueryTypeName, DnsResponseCodeName

DNS-tunnel signature (TXT-heavy)

TXT-query volume per source.

ImDnsActivity
| where TimeGenerated > ago(24h)
| where DnsQueryTypeName == "TXT"
| summarize Queries = count(), DistinctNames = dcount(DnsQuery)
            by SrcIpAddr, bin(TimeGenerated, 5m)
| where Queries > 200
| order by Queries desc

ImRegistryEvent

27 columns · 2 queries

Schema (click to expand)

TimeGenerated · EventCount · EventType · EventResult · EventStartTime · EventEndTime · EventVendor · EventProduct · DvcIpAddr · DvcHostname · ActorUsername · ActorUserId · ActorUsernameType · ActingProcessCommandLine · ActingProcessName · ActingProcessId · ActingProcessGuid · RegistryKey · RegistryValue · RegistryValueType · RegistryValueData · RegistryPreviousKey · RegistryPreviousValue · RegistryPreviousValueType · RegistryPreviousValueData · RegistryHive · _ResourceId

Run / RunOnce changes

Persistence-key writes — cross-vendor normalisation.

ImRegistryEvent
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where RegistryKey has_any (@"\Run", @"\RunOnce")
| where ActingProcessName !in~ ("msiexec.exe","explorer.exe")
| project TimeGenerated, DvcHostname, ActorUsername,
          RegistryKey, RegistryValue, RegistryValueData, ActingProcessName

IFEO debugger hijack

Image File Execution Options debugger override — classic evasion.

ImRegistryEvent
| where TimeGenerated > ago(7d)
| where ActorUsername !endswith "$"
| where RegistryKey has @"\Image File Execution Options\"
| where RegistryValue =~ "Debugger"
| project TimeGenerated, DvcHostname, RegistryKey, RegistryValueData,
          ActingProcessName

AADManagedIdentitySignInLogs

13 columns · 0 queries (curation pending)

TimeGenerated · OperationName · ServicePrincipalId · ServicePrincipalName · AppId · ResourceId · ResourceDisplayName · IPAddress · ResultType · ResultDescription · Status · ManagedIdentityType · _ResourceId

AADNonInteractiveUserSignInLogs

26 columns · 0 queries (curation pending)

TimeGenerated · OperationName · Identity · UserDisplayName · UserPrincipalName · UserId · AppId · AppDisplayName · ClientAppUsed · IPAddress · ResourceDisplayName · ResourceId · ResultType · ResultSignature · ResultDescription · Status · DeviceDetail · Location · RiskDetail · RiskLevelDuringSignIn · RiskLevelAggregated · RiskState · ConditionalAccessStatus · OriginalRequestId · AuthenticationRequirement · _ResourceId

AADServicePrincipalSignInLogs

15 columns · 0 queries (curation pending)

TimeGenerated · OperationName · ServicePrincipalId · ServicePrincipalName · ServicePrincipalCredentialKeyId · ServicePrincipalCredentialThumbprint · AppId · ResourceId · ResourceDisplayName · IPAddress · Location · ResultType · ResultDescription · Status · _ResourceId

AKSAudit

16 columns · 0 queries (curation pending)

TimeGenerated · Computer · Verb · Username · Method · RequestUri · ObjectRef · ResponseStatus · Stage · User · UserAgent · RequestObject · ResponseObject · AuditId · Annotations · _ResourceId

ASCDeviceEvents

16 columns · 0 queries (curation pending)

TimeGenerated · DeviceName · DeviceId · ActionType · FileName · FolderPath · ProcessCommandLine · InitiatingProcessFileName · InitiatingProcessCommandLine · AccountName · AccountDomain · RemoteIP · RemotePort · RemoteUrl · AdditionalFields · _ResourceId

AppServiceHTTPLogs

18 columns · 0 queries (curation pending)

TimeGenerated · CsHost · CIp · ScStatus · ScSubStatus · ScWin32Status · TimeTaken · CsBytes · ScBytes · CsMethod · CsUriStem · CsUriQuery · UserAgent · Cookie · CsUsername · Referer · ResultDescription · _ResourceId

AzureDiagnostics

17 columns · 0 queries (curation pending)

TimeGenerated · ResourceId · ResourceProvider · ResourceType · Resource · ResourceGroup · SubscriptionId · Category · OperationName · OperationVersion · ResultDescription · ResultType · Properties · Level · CorrelationId · Tenant · _ResourceId

DeviceInfo

24 columns · 0 queries (curation pending)

TimeGenerated · DeviceId · DeviceName · OSPlatform · OSVersion · OSArchitecture · OSDistribution · PublicIP · MachineGroup · JoinType · IsAzureADJoined · IsInternetFacing · LoggedOnUsers · AdditionalFields · ClientVersion · OSBuild · OSRevision · RegistryDeviceTag · AadDeviceId · DeviceCategory · DeviceType · DeviceSubtype · Model · Vendor

DeviceTvmSoftwareVulnerabilities

12 columns · 0 queries (curation pending)

TimeGenerated · DeviceId · DeviceName · OSPlatform · OSVersion · SoftwareVendor · SoftwareName · SoftwareVersion · CveId · VulnerabilitySeverityLevel · RecommendedSecurityUpdate · RecommendedSecurityUpdateId

Event

14 columns · 0 queries (curation pending)

TimeGenerated · Computer · EventID · EventCategory · EventLevel · EventLevelName · EventLog · Source · RenderedDescription · ParameterXml · EventData · UserName · User · _ResourceId

Heartbeat

21 columns · 0 queries (curation pending)

TimeGenerated · Computer · ComputerEnvironment · ComputerIP · ComputerPrivateIPs · OSType · OSName · OSMajorVersion · OSMinorVersion · Version · RemoteIPCountry · RemoteIPLatitude · RemoteIPLongitude · Solutions · ResourceProvider · Resource · ResourceGroup · ResourceId · SubscriptionId · Category · _ResourceId

IdentityInfo

37 columns · 0 queries (curation pending)

TimeGenerated · AccountObjectId · AccountUPN · AccountUpn · AccountSID · AccountName · AccountDomain · AccountTenantId · AccountDisplayName · AccountCloudSID · GivenName · Surname · MailAddress · MailAlias · JobTitle · Department · Manager · City · Country · OfficeLocation · BusinessPhones · MobilePhone · PhysicalAddresses · ProxyAddresses · OnPremisesDistinguishedName · OnPremisesSyncEnabled · Tags · Type · AssignedRoles · GroupMembership · EmployeeId · IsAccountEnabled · ChangeSource · BlastRadius · InsiderRiskLevel · SourceSystem · _ResourceId

ImWebSession

40 columns · 0 queries (curation pending)

TimeGenerated · EventCount · EventType · EventResult · EventOriginalUid · EventSeverity · EventStartTime · EventEndTime · EventVendor · EventProduct · Url · UrlCategory · UrlOriginal · HttpMethod · HttpStatusCode · HttpResponseCode · HttpVersion · HttpHostName · HttpRequestBodyBytes · HttpResponseBodyBytes · HttpRequestHeaderUserAgent · HttpRequestHeaderReferer · HttpRequestHeaderCookie · HttpRequestHeaderAuthorization · HttpResponseHeaderContentType · FileName · FileMimeType · DvcIpAddr · DvcHostname · SrcIpAddr · SrcHostname · SrcUsername · DstIpAddr · DstHostname · DstPortNumber · ThreatCategory · ThreatName · ThreatRiskLevel · DvcAction · _ResourceId

SecurityIncident

28 columns · 0 queries (curation pending)

TimeGenerated · Title · Description · Severity · Status · Classification · ClassificationComment · ClassificationReason · Owner · Labels · FirstActivityTime · LastActivityTime · FirstModifiedTime · LastModifiedTime · IncidentName · IncidentNumber · AlertIds · BookmarkIds · RelatedAnalyticRuleIds · Comments · AdditionalData · ProviderName · ProviderIncidentId · TenantId · TasksCount · Tactics · Techniques · _ResourceId

Update

13 columns · 0 queries (curation pending)

TimeGenerated · Computer · Title · KBID · Classification · MSRCSeverity · PublishedDate · InstalledOn · UpdateState · Optional · RebootBehavior · ApprovalSource · _ResourceId

W3CIISLog

18 columns · 0 queries (curation pending)

TimeGenerated · Computer · sSiteName · csMethod · csUriStem · csUriQuery · sPort · csUserName · cIP · csUserAgent · csReferer · scStatus · scSubStatus · scWin32Status · TimeTaken · csBytes · scBytes · _ResourceId

WindowsEvent

17 columns · 0 queries (curation pending)

TimeGenerated · Computer · EventID · Channel · Provider · Task · Level · EventLevel · EventLevelName · Description · EventData · Keywords · Opcode · ProcessId · ThreadId · Version · _ResourceId

Datadog · Cloud SIEM logs query

Pick a log source from the sidebar — every query is verbatim Datadog Logs Explorer / Cloud SIEM syntax: source: first, @field.path:value filters, uppercase boolean operators, CIDR(@ip, range) for IP filtering. Time windows are configured at rule level in Datadog so they're absent from the query body.

Reference Tables let you maintain large IOC / known-bad / allowlist tables in Datadog and pivot via them in queries — handy for IP-block / hash-list / domain-list filters that grow over time. Syntax: CIDR(@network.client.ip, *RefTable:bad_ips_v2*) or @process.name IN *RefTable:lolbins*. Build / upload tables under Logs → Configuration → Reference Tables; queries below use literal lists for clarity but swap in a Reference Table any time a list grows past ~100 entries.

12 sources curated 65 queries Click Copy on any query to paste into Datadog Logs / Cloud SIEM rule editor.

cloudtrail

14 columns · 6 queries

Schema (click to expand)

@evt.name · @evt.outcome · @userIdentity.type · @userIdentity.userName · @userIdentity.arn · @userIdentity.accountId · @userIdentity.sessionContext.sessionIssuer.userName · @requestParameters.userName · @requestParameters.policyArn · @requestParameters.bucketName · @responseElements.user.userName · @network.client.ip · @aws.region · @aws.account.id

All API activity for a specific user / role

Triage starting point — every CloudTrail event from one identity. Replace `<userName>`.

source:cloudtrail @userIdentity.userName:<userName>

All API activity from a single source IP

Pivot for an attacker IP found elsewhere (NIDS, WAF, CTI). Replace `<IP>`.

source:cloudtrail @network.client.ip:<IP>

All actions on a specific S3 bucket

Investigate exfil / config-change on a named bucket. Replace `<bucketName>`.

source:cloudtrail @requestParameters.bucketName:<bucketName>

Failed actions only (any service)

Quick triage of refused actions — credential-stuffing, perm-discovery, throttled abuse all live here.

source:cloudtrail @evt.outcome:failure

AssumeRole calls into one role

Who has been assuming a privileged role? Replace `<roleName>`.

source:cloudtrail @evt.name:AssumeRole
@requestParameters.roleArn:*<roleName>*

Console-login attempts from foreign geos

Console authentications from outside the expected business geographies.

source:cloudtrail @evt.name:ConsoleLogin
@network.client.geoip.country.iso_code:(CN OR RU OR IR OR KP OR BY)

azure.activity_logs

9 columns · 5 queries

Schema (click to expand)

@operationName.value · @properties.eventName · @properties.activityStatusValue · @identity.claim.upn · @identity.claim.appid · @network.client.ip · @properties.resource · @resource.resourceGroup · @resource.subscriptionId

All resource activity in a resource group

Triage scope: every operation against one RG. Replace `<resourceGroupName>`.

source:azure.activity_logs @resource.resourceGroup:<resourceGroupName>

All actions by a specific identity

Pivot for an account under investigation. Replace `<upn-or-appId>`.

source:azure.activity_logs
(@identity.claim.upn:<upn-or-appId> OR @identity.claim.appid:<upn-or-appId>)

All resource deletions

Wide net for destructive activity — sort by time and pivot on the principal.

source:azure.activity_logs
@operationName.value:*delete*
@properties.activityStatusValue:Succeeded

Storage-account key listings

Storage-key reads bypass RBAC on data — strong signal of data-exfil tradecraft.

source:azure.activity_logs
@operationName.value:Microsoft.Storage/storageAccounts/listKeys/action

Failed Azure operations

Search across denied/failed Azure operations, useful for permission-discovery hunts.

source:azure.activity_logs @properties.activityStatusValue:Failed

azure.activeDirectory

12 columns · 6 queries

Schema (click to expand)

@evt.name · @usr.id · @usr.email · @user.userPrincipalName · @network.client.ip · @network.client.geoip.country.iso_code · @properties.status.errorCode · @properties.appDisplayName · @properties.riskState · @properties.riskLevelDuringSignIn · @properties.authenticationProtocol · @properties.deviceDetail.deviceId

All sign-in activity for one user

User triage — every sign-in (success + fail). Replace `<upn>`.

source:azure.activeDirectory @evt.name:"Sign-in activity"
@user.userPrincipalName:<upn>

All sign-ins from one IP

Pivot for a suspicious source IP — see every account it touched. Replace `<IP>`.

source:azure.activeDirectory @evt.name:"Sign-in activity"
@network.client.ip:<IP>

Failed sign-ins by error code

Filter to a specific failure mode (50126=bad password, 50053=locked, 50058=no session, 50158=external MFA fail). Replace `<errorCode>`.

source:azure.activeDirectory @evt.name:"Sign-in activity"
@properties.status.errorCode:<errorCode>

OAuth app consent grants

Find every consent given to a third-party app — pivot via appDisplayName for the app footprint.

source:azure.activeDirectory
@evt.name:"Add app role assignment to service principal"

Sign-ins flagged risky by Identity Protection

Identity Protection's risk-state field filtered to non-clean states.

source:azure.activeDirectory @evt.name:"Sign-in activity"
@properties.riskState:(atRisk OR confirmedCompromised)

Sign-ins from foreign geographies

Quick hunt for geographically anomalous logins.

source:azure.activeDirectory @evt.name:"Sign-in activity"
@network.client.geoip.country.iso_code:(CN OR RU OR IR OR KP OR BY)

windows.security

13 columns · 6 queries

Schema (click to expand)

@EventID · @Image · @CommandLine · @User · @SubjectUserName · @TargetUserName · @LogonType · @WorkstationName · @IpAddress · @ProcessName · @ParentProcessName · @AccessMask · @PrivilegeList

All security events for one host

Host triage — every Win Security event. Replace `<DeviceName>`.

source:windows.security @WorkstationName:<DeviceName>

Logons by a specific user

EID 4624 (logon) for one identity. Replace `<UserName>`.

source:windows.security @EventID:4624
@TargetUserName:<UserName>
-@TargetUserName:*$

Failed logons (any user)

EID 4625 — all logon failures. Tune by IP / WorkstationName for hunt.

source:windows.security @EventID:4625
-@TargetUserName:*$

Account lockouts

EID 4740 — accounts that hit the lockout threshold. Pivot for credential-spray.

source:windows.security @EventID:4740

Process creation by event ID 4688

Process-create audit log if Sysmon isn't deployed. Replace `<binary>`.

source:windows.security @EventID:4688
@ProcessName:*<binary>*

Privileged group changes

EID 4732/4756/4728 — adds to local-/domain-/universal-admin groups.

source:windows.security @EventID:(4732 OR 4756 OR 4728)
@TargetUserName:(*Admin* OR *Domain* OR *Enterprise*)

windows.sysmon

14 columns · 6 queries

Schema (click to expand)

@EventID · @Image · @CommandLine · @ParentImage · @ParentCommandLine · @Hashes · @DestinationIp · @DestinationPort · @DestinationHostname · @SourceIp · @TargetFilename · @TargetObject · @User · @LogonId

All sysmon activity on a host

Host triage — full process / network / file / registry activity. Replace `<DeviceName>`.

source:windows.sysmon @host:<DeviceName>

Process creates by image name

EID 1 — every spawn of a binary. Both casings (Datadog is case-sensitive). Replace `<binary.exe>`.

source:windows.sysmon @EventID:1
@Image:(*\\<binary.exe> OR *\\<BINARY.EXE>)

Network connections to a destination IP

EID 3 — outbound flows to a target. Replace `<IP>`.

source:windows.sysmon @EventID:3
@DestinationIp:<IP>

File creates by path

EID 11 — file create/modify. Useful for tracking written payloads. Replace `<path-fragment>`.

source:windows.sysmon @EventID:11
@TargetFilename:*<path-fragment>*

Registry writes under Run / RunOnce / Services

EID 13 — persistence-key writes under classic ASEP locations.

source:windows.sysmon @EventID:13
@TargetObject:(*\\Run\\* OR *\\RunOnce\\* OR *\\Services\\* OR "*Image File Execution Options*" OR *\\Winlogon\\*)

Image-load (DLL) by hash

EID 7 — find every host that loaded a known-bad DLL. Replace `<sha256>`.

source:windows.sysmon @EventID:7
@Hashes:*SHA256=<sha256>*

linux.auditd

11 columns · 6 queries

Schema (click to expand)

@process.name · @process.command_line · @process.executable.path · @user.name · @user.id · @auditd.type · @network.client.ip · @network.destination.ip · @host.name · @auditd.uid · @auditd.gid

All auditd activity on a host

Host triage. Replace `<host>`.

source:linux.auditd @host.name:<host>

Process executions by a user

EXECVE filtered to one user. Replace `<userName>`.

source:linux.auditd @auditd.type:EXECVE @user.name:<userName>

Find a binary by name

Every EXECVE of a binary across the fleet. Replace `<binary>`.

source:linux.auditd @auditd.type:EXECVE
@process.name:<binary>

Outbound connections to one host

Network destinations from auditd's syscall logs. Replace `<IP>`.

source:linux.auditd @network.destination.ip:<IP>

Files written under a path

PATH events filtered to a directory. Replace `<directory>`.

source:linux.auditd @auditd.type:PATH
@auditd.path:<directory>/*

Authentication events for a user

USER_AUTH / USER_LOGIN — pam-side authentication trail. Replace `<userName>`.

source:linux.auditd @auditd.type:(USER_AUTH OR USER_LOGIN OR USER_ACCT)
@user.name:<userName>

gcp.audit

8 columns · 6 queries

Schema (click to expand)

@protoPayload.methodName · @protoPayload.authenticationInfo.principalEmail · @protoPayload.requestMetadata.callerIp · @protoPayload.serviceName · @protoPayload.resourceName · @resource.labels.project_id · @resource.type · @severity

All audit log activity in a project

Project-level scope. Replace `<project-id>`.

source:gcp.audit @resource.labels.project_id:<project-id>

Activity by a specific principal

Every method called by one principal email. Replace `<email>`.

source:gcp.audit
@protoPayload.authenticationInfo.principalEmail:<email>

Activity from one source IP

Caller IP pivot. Replace `<IP>`.

source:gcp.audit
@protoPayload.requestMetadata.callerIp:<IP>

IAM policy changes

Every SetIamPolicy across the org — pair with the bindingDeltas.member field for reach.

source:gcp.audit
@protoPayload.methodName:(SetIamPolicy OR setIamPolicy)

Service account key creations

Long-lived credential creations — pivot for token-exfil tradecraft.

source:gcp.audit
@protoPayload.methodName:google.iam.admin.v1.CreateServiceAccountKey

Failed / denied operations

Permission-discovery activity surfaces here.

source:gcp.audit @severity:(ERROR OR WARNING)

kubernetes.audit

11 columns · 6 queries

Schema (click to expand)

@verb · @objectRef.resource · @objectRef.name · @objectRef.namespace · @user.username · @user.groups · @sourceIPs · @requestObject.spec.containers.image · @requestObject.spec.hostPID · @requestObject.spec.hostNetwork · @responseStatus.code

All activity in a namespace

Namespace triage. Replace `<namespace>`.

source:kubernetes.audit @objectRef.namespace:<namespace>

Actions by a user / service account

User pivot. Replace `<username>`.

source:kubernetes.audit @user.username:<username>

Pods created in a namespace

What got deployed where, by whom. Replace `<namespace>`.

source:kubernetes.audit
@verb:create @objectRef.resource:pods
@objectRef.namespace:<namespace>

Privileged / hostPID / hostNetwork pod specs

Container break-out primitives.

source:kubernetes.audit @verb:create @objectRef.resource:pods
(@requestObject.spec.containers.securityContext.privileged:true
 OR @requestObject.spec.hostPID:true
 OR @requestObject.spec.hostNetwork:true)

kubectl exec sessions

Live shells into running pods — operationally normal for engineers, anomalous in prod namespaces.

source:kubernetes.audit
@verb:create @objectRef.subresource:exec

Cluster-admin role bindings

New bindings of high-privilege cluster roles — full-takeover risk.

source:kubernetes.audit
@verb:create
@objectRef.resource:(clusterrolebindings OR rolebindings)
@requestObject.roleRef.name:(cluster-admin OR admin OR edit)

okta

11 columns · 6 queries

Schema (click to expand)

@evt.name · @actor.alternateId · @actor.id · @actor.displayName · @client.ipAddress · @client.geographicalContext.country · @client.geographicalContext.city · @outcome.result · @outcome.reason · @authenticationContext.authenticationProvider · @target.alternateId

All activity for a user

User triage — every Okta event tied to one identity. Replace `<email>`.

source:okta @actor.alternateId:<email>

All activity from one source IP

IP pivot — every account touched from this address. Replace `<IP>`.

source:okta @client.ipAddress:<IP>

Authentication failures

All failed sign-ins.

source:okta @evt.name:user.session.start @outcome.result:FAILURE

Account lockouts

user.account.lock — pair with @client.ipAddress to see lockout sources.

source:okta @evt.name:user.account.lock

MFA factor enrolment / reset

New MFA factor or factor reset — adversary persistence path.

source:okta @evt.name:(user.mfa.factor.activate OR user.mfa.factor.reset_all OR user.mfa.factor.deactivate)

Admin privilege grants

Direct grants of Okta admin roles to a user — anomalous outside scim/automation.

source:okta @evt.name:user.account.privilege.grant

slack

9 columns · 4 queries

Schema (click to expand)

@evt.name · @actor.user.email · @actor.user.name · @actor.user.team · @context.ip_address · @context.location.country · @entity.channel · @entity.file · @entity.app

All activity for a user

User triage — every Slack event tied to one identity. Replace `<email>`.

source:slack @actor.user.email:<email>

File downloads from external workspaces

Cross-workspace file lift — external collaboration risk.

source:slack @evt.name:file_downloaded
@actor.user.team:<external-team-id>

App / integration installed

New third-party Slack app — pivot for OAuth-scope review.

source:slack @evt.name:app_installed

Channel made public

Private channel flipped to public.

source:slack @evt.name:public_channel_created
OR (@evt.name:channel_settings_updated @change.field:visibility @change.new:public)

microsoft.teams

9 columns · 4 queries

Schema (click to expand)

@evt.name · @user.userPrincipalName · @user.id · @network.client.ip · @team.id · @team.displayName · @channel.id · @channel.displayName · @app.displayName

All Teams activity for a user

User triage. Replace `<upn>`.

source:microsoft.teams @user.userPrincipalName:<upn>

External user added to a team

Guest-user invite — pivot for org-policy enforcement.

source:microsoft.teams @evt.name:MemberAdded
@user.userPrincipalName:*#EXT#*

Teams app installed in a tenant

New tenant-wide app installation. Replace `<appName>` if scoping.

source:microsoft.teams @evt.name:AppInstalled

Federated chat with external organisation

External-tenant chat session — guest collaboration / data-leak risk.

source:microsoft.teams @evt.name:MessageSent
@chat.chatType:meetingChat OR @chat.chatType:oneOnOne
@user.userPrincipalName:*#EXT#*

salesforce

9 columns · 4 queries

Schema (click to expand)

@evt.name · @usr.id · @usr.username · @usr.email · @network.client.ip · @object.type · @object.name · @event.type · @status

All activity for a user

User triage. Replace `<username>`.

source:salesforce @usr.username:<username>

Mass record export (Data Loader / report export)

Bulk-export pattern — credential / data exfil indicator.

source:salesforce
@evt.name:(REPORT_EXPORT OR DATA_EXPORT OR BULK_API)

Login from a new IP

Pivot for credential-stuffing or impossible-travel hunts.

source:salesforce @evt.name:Login @status:Success
@network.client.ip:*

Permission set assignment

Privilege drift in Salesforce — user gets new permissions.

source:salesforce @evt.name:PermissionSetAssignment

Sigma · platform-neutral detection rules

Sigma is a generic, YAML-based signature format for SIEM detections. Each rule below is a self-contained Sigma YAML, pre-compiled to Defender KQL, Splunk SPL, and Elastic Lucene at build time — copy whichever format your SIEM speaks. Source rules live under sigma_rules/; re-run python build_soc_cheatsheet.py after editing to refresh.

Sigma syntax cheat sheet — click to expand

Top-level fields:

title:        # Short, descriptive
id:           # UUID — gives the rule a stable identity
status:       # stable | test | experimental | deprecated | unsupported
description:  # 1-3 sentences on what it catches
references:   # URLs to relevant intel / vendor advisories
author:       # Free-form
date:         # 2026/05/07
tags:         # attack.t1059, attack.execution, etc — MITRE ATT&CK
logsource:    # Where the rule applies
  product:    #   windows / linux / macos / aws / azure / etc
  service:    #   security / sysmon / cloudtrail / ...
  category:   #   process_creation / file_event / network_connection / ...
detection:    # The actual matching logic
  selection:  #   Match condition — ANDed by default within a block
  filter:     #   Optional — fields to exclude
  condition:  # selection and not filter / 1 of selection_* / etc.
falsepositives: [...]
level:        # informational | low | medium | high | critical

Field modifiers (suffix after the field name):

  • field|contains: value — substring match
  • field|startswith: value / |endswith: value
  • field|re: regex — Sigma regex (PCRE-flavoured)
  • field|all: [a, b] — list AND (must contain all)
  • field|cased — case-sensitive (default is case-insensitive)
  • field|windash — accept either - or / as the prefix to a Windows-style flag (e.g. -encodedcommand or /encodedcommand)
  • field|expand — expand placeholders defined under placeholders:

Compilation cheat sheet — what each Sigma construct becomes:

  • field|contains: x → KQL field has "x" · SPL field="*x*" · Lucene field:*x*
  • field|startswith: x → KQL field startswith "x" · SPL field="x*" · Lucene field:x*
  • field: [a, b, c] → KQL field in ("a","b","c") · SPL field IN ("a","b","c")
  • condition: 1 of selection_* → OR across every block whose name matches
  • condition: all of selection_* → AND across every matching block
  • timeframe: 5m + aggregation — only some backends support; Splunk does, Defender doesn't

When Sigma is the right tool: single-event-shape detections (one log line matches → fire). When it isn't: multi-stage temporal correlation, threshold-over-window aggregations, joins across data sources — those don't compile cleanly to all backends. Author those directly in KQL or SPL instead.

Reference: SigmaHQ/sigma — the canonical rule repo + the latest spec.

15 rules 3 backends pre-compiled (KQL · SPL · Lucene) Add new rules to sigma_rules/<kill_chain>/ and rebuild.

actions

5 rules · platform-neutral, compiled at build time

Infostealer - Non-Browser Process Accessing Browser Credential Stores

high

Stealers (RedLine, Lumma, Vidar, Atomic) read Login Data / cookies SQLite databases from Chrome/Edge/Firefox profile directories. Any non-browser process touching these files is a high-fidelity signal.

category=file_access · product=windows · sigma_rules/actions/UC_BROWSER_STEALER.yml

attack.t1539 attack.t1555.003 attack.credential-access
title: Infostealer - Non-Browser Process Accessing Browser Credential Stores
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d01
status: experimental
description: |
    Stealers (RedLine, Lumma, Vidar, Atomic) read Login Data / cookies
    SQLite databases from Chrome/Edge/Firefox profile directories. Any
    non-browser process touching these files is a high-fidelity signal.
references:
    - https://attack.mitre.org/techniques/T1539/
    - https://attack.mitre.org/techniques/T1555/003/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1539
    - attack.t1555.003
    - attack.credential-access
logsource:
    category: file_access
    product: windows
detection:
    selection_path:
        TargetFilename|contains:
            - '\Google\Chrome\User Data\'
            - '\Microsoft\Edge\User Data\'
            - '\Mozilla\Firefox\Profiles\'
    selection_file:
        TargetFilename|endswith:
            - '\Login Data'
            - '\Cookies'
            - '\logins.json'
            - '\cookies.sqlite'
    filter_browser:
        Image|endswith:
            - '\chrome.exe'
            - '\msedge.exe'
            - '\firefox.exe'
            - '\brave.exe'
            - '\opera.exe'
    condition: selection_path and selection_file and not filter_browser
falsepositives:
    - Backup utilities reading user profile files
    - Browser sync agents from non-stock vendors
level: high
(TargetFilename contains "\\Google\\Chrome\\User Data\\" or TargetFilename contains "\\Microsoft\\Edge\\User Data\\" or TargetFilename contains "\\Mozilla\\Firefox\\Profiles\\") and (TargetFilename endswith "\\Login Data" or TargetFilename endswith "\\Cookies" or TargetFilename endswith "\\logins.json" or TargetFilename endswith "\\cookies.sqlite") and (not((Image endswith "\\chrome.exe" or Image endswith "\\msedge.exe" or Image endswith "\\firefox.exe" or Image endswith "\\brave.exe" or Image endswith "\\opera.exe")))
TargetFilename IN ("*\\Google\\Chrome\\User Data\\*", "*\\Microsoft\\Edge\\User Data\\*", "*\\Mozilla\\Firefox\\Profiles\\*") TargetFilename IN ("*\\Login Data", "*\\Cookies", "*\\logins.json", "*\\cookies.sqlite") NOT (Image IN ("*\\chrome.exe", "*\\msedge.exe", "*\\firefox.exe", "*\\brave.exe", "*\\opera.exe"))
(TargetFilename:(*\\Google\\Chrome\\User\ Data\\* OR *\\Microsoft\\Edge\\User\ Data\\* OR *\\Mozilla\\Firefox\\Profiles\\*)) AND (TargetFilename:(*\\Login\ Data OR *\\Cookies OR *\\logins.json OR *\\cookies.sqlite)) AND (NOT (Image:(*\\chrome.exe OR *\\msedge.exe OR *\\firefox.exe OR *\\brave.exe OR *\\opera.exe)))

Crypto-Wallet Keystore Access by Non-Wallet Process

high

Stealers / wallet drainers read keystore files from MetaMask, Exodus, Atomic, Phantom, Bitcoin, Electrum, Ethereum-cli wallets. Filtering out the legitimate wallet binaries leaves only attacker activity.

category=file_access · product=windows · sigma_rules/actions/UC_CRYPTO_WALLET.yml

attack.t1005 attack.collection
title: Crypto-Wallet Keystore Access by Non-Wallet Process
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d02
status: experimental
description: |
    Stealers / wallet drainers read keystore files from MetaMask,
    Exodus, Atomic, Phantom, Bitcoin, Electrum, Ethereum-cli wallets.
    Filtering out the legitimate wallet binaries leaves only attacker
    activity.
references:
    - https://attack.mitre.org/techniques/T1005/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1005
    - attack.collection
logsource:
    category: file_access
    product: windows
detection:
    selection_path:
        TargetFilename|contains:
            - '\Ethereum\keystore\'
            - '\Bitcoin\'
            - '\Exodus\'
            - '\Electrum\wallets\'
            - '\MetaMask\'
            - '\Phantom\'
            - '\Atomic\Local Storage\'
    filter_legit:
        Image|endswith:
            - '\MetaMask.exe'
            - '\Exodus.exe'
            - '\Atomic.exe'
            - '\electrum.exe'
            - '\Bitcoin.exe'
            - '\Phantom.exe'
    condition: selection_path and not filter_legit
falsepositives:
    - Backup software
level: high
(TargetFilename contains "\\Ethereum\\keystore\\" or TargetFilename contains "\\Bitcoin\\" or TargetFilename contains "\\Exodus\\" or TargetFilename contains "\\Electrum\\wallets\\" or TargetFilename contains "\\MetaMask\\" or TargetFilename contains "\\Phantom\\" or TargetFilename contains "\\Atomic\\Local Storage\\") and (not((Image endswith "\\MetaMask.exe" or Image endswith "\\Exodus.exe" or Image endswith "\\Atomic.exe" or Image endswith "\\electrum.exe" or Image endswith "\\Bitcoin.exe" or Image endswith "\\Phantom.exe")))
TargetFilename IN ("*\\Ethereum\\keystore\\*", "*\\Bitcoin\\*", "*\\Exodus\\*", "*\\Electrum\\wallets\\*", "*\\MetaMask\\*", "*\\Phantom\\*", "*\\Atomic\\Local Storage\\*") NOT (Image IN ("*\\MetaMask.exe", "*\\Exodus.exe", "*\\Atomic.exe", "*\\electrum.exe", "*\\Bitcoin.exe", "*\\Phantom.exe"))
(TargetFilename:(*\\Ethereum\\keystore\\* OR *\\Bitcoin\\* OR *\\Exodus\\* OR *\\Electrum\\wallets\\* OR *\\MetaMask\\* OR *\\Phantom\\* OR *\\Atomic\\Local\ Storage\\*)) AND (NOT (Image:(*\\MetaMask.exe OR *\\Exodus.exe OR *\\Atomic.exe OR *\\electrum.exe OR *\\Bitcoin.exe OR *\\Phantom.exe)))

PsExec / SMB Lateral Movement Tooling Execution

high

PsExec, paexec, smbexec, csexec, remcom — admin-grade tooling that pivots over SMB. Pair with `wmic /node:` for the full cluster.

category=process_creation · product=windows · sigma_rules/actions/UC_LATERAL_PSEXEC.yml

attack.t1021.002 attack.t1569.002 attack.lateral-movement attack.execution
title: PsExec / SMB Lateral Movement Tooling Execution
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d03
status: experimental
description: |
    PsExec, paexec, smbexec, csexec, remcom — admin-grade tooling that
    pivots over SMB. Pair with `wmic /node:` for the full cluster.
references:
    - https://attack.mitre.org/techniques/T1021/002/
    - https://attack.mitre.org/techniques/T1569/002/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1021.002
    - attack.t1569.002
    - attack.lateral-movement
    - attack.execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_psexec:
        Image|endswith:
            - '\psexec.exe'
            - '\psexec64.exe'
            - '\psexesvc.exe'
            - '\paexec.exe'
            - '\csexec.exe'
            - '\remcom.exe'
            - '\smbexec.py'
    selection_wmic_remote:
        Image|endswith:
            - '\wmic.exe'
        CommandLine|contains:
            - '/node:'
    condition: selection_psexec or selection_wmic_remote
falsepositives:
    - Sysadmins running approved remote-management tooling — wrap with
      a known-admin-host watchlist
level: high
(Image endswith "\\psexec.exe" or Image endswith "\\psexec64.exe" or Image endswith "\\psexesvc.exe" or Image endswith "\\paexec.exe" or Image endswith "\\csexec.exe" or Image endswith "\\remcom.exe" or Image endswith "\\smbexec.py") or (Image endswith "\\wmic.exe" and CommandLine contains "/node:")
Image IN ("*\\psexec.exe", "*\\psexec64.exe", "*\\psexesvc.exe", "*\\paexec.exe", "*\\csexec.exe", "*\\remcom.exe", "*\\smbexec.py") OR (Image="*\\wmic.exe" CommandLine="*/node:*")
(Image:(*\\psexec.exe OR *\\psexec64.exe OR *\\psexesvc.exe OR *\\paexec.exe OR *\\csexec.exe OR *\\remcom.exe OR *\\smbexec.py)) OR (Image:*\\wmic.exe AND CommandLine:*\/node\:*)

LSASS Process Access Outside Microsoft-Signed Tooling

high

Anything opening lsass.exe with read-memory access that isn't a Microsoft signed component (Defender, csrss, etc.) is suspect. Mimikatz / Pypykatz / nanodump signature.

category=process_access · product=windows · sigma_rules/actions/UC_LSASS.yml

attack.t1003.001 attack.credential-access
title: LSASS Process Access Outside Microsoft-Signed Tooling
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d04
status: experimental
description: |
    Anything opening lsass.exe with read-memory access that isn't a
    Microsoft signed component (Defender, csrss, etc.) is suspect.
    Mimikatz / Pypykatz / nanodump signature.
references:
    - https://attack.mitre.org/techniques/T1003/001/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1003.001
    - attack.credential-access
logsource:
    category: process_access
    product: windows
detection:
    selection:
        TargetImage|endswith: '\lsass.exe'
    filter_known_good:
        SourceImage|endswith:
            - '\MsSense.exe'
            - '\MsMpEng.exe'
            - '\csrss.exe'
            - '\svchost.exe'
            - '\wininit.exe'
            - '\services.exe'
            - '\lsm.exe'
            - '\SearchProtocolHost.exe'
    condition: selection and not filter_known_good
falsepositives:
    - Third-party EDR / forensic tools — extend the filter list
level: high
TargetImage endswith "\\lsass.exe" and (not((SourceImage endswith "\\MsSense.exe" or SourceImage endswith "\\MsMpEng.exe" or SourceImage endswith "\\csrss.exe" or SourceImage endswith "\\svchost.exe" or SourceImage endswith "\\wininit.exe" or SourceImage endswith "\\services.exe" or SourceImage endswith "\\lsm.exe" or SourceImage endswith "\\SearchProtocolHost.exe")))
TargetImage="*\\lsass.exe" NOT (SourceImage IN ("*\\MsSense.exe", "*\\MsMpEng.exe", "*\\csrss.exe", "*\\svchost.exe", "*\\wininit.exe", "*\\services.exe", "*\\lsm.exe", "*\\SearchProtocolHost.exe"))
TargetImage:*\\lsass.exe AND (NOT (SourceImage:(*\\MsSense.exe OR *\\MsMpEng.exe OR *\\csrss.exe OR *\\svchost.exe OR *\\wininit.exe OR *\\services.exe OR *\\lsm.exe OR *\\SearchProtocolHost.exe)))

Entra ID Consent to Third-Party OAuth Application

medium

User-driven consent to a third-party OAuth application — illicit- consent attack precursor. Pair with first-time-seen-app heuristic in your SIEM for higher fidelity.

product=azure · service=auditlogs · sigma_rules/actions/UC_OAUTH_ABUSE.yml

attack.t1528 attack.persistence
title: Entra ID Consent to Third-Party OAuth Application
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d05
status: experimental
description: |
    User-driven consent to a third-party OAuth application — illicit-
    consent attack precursor. Pair with first-time-seen-app heuristic
    in your SIEM for higher fidelity.
references:
    - https://attack.mitre.org/techniques/T1528/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1528
    - attack.persistence
logsource:
    product: azure
    service: auditlogs
detection:
    selection:
        OperationName: 'Consent to application'
        Result: 'success'
    condition: selection
falsepositives:
    - Legitimate first-time SaaS app onboarding
level: medium
OperationName =~ "Consent to application" and Result =~ "success"
OperationName="Consent to application" Result="success"
OperationName:Consent\ to\ application AND Result:success

c2

1 rules · platform-neutral, compiled at build time

Outbound Connection to Article-Named IP / Domain

critical

Replace `__IP_LIST__` / `__DOMAIN_LIST__` placeholders with article-specific destinations. For dynamic IOC management, use a watchlist or external feed.

category=network_connection · product=windows · sigma_rules/c2/UC_NETWORK_IOC.yml

attack.command-and-control
title: Outbound Connection to Article-Named IP / Domain
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d0f
status: experimental
description: |
    Replace `__IP_LIST__` / `__DOMAIN_LIST__` placeholders with
    article-specific destinations. For dynamic IOC management, use a
    watchlist or external feed.
references:
    - https://attack.mitre.org/tactics/TA0011/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.command-and-control
logsource:
    category: network_connection
    product: windows
detection:
    selection_ip:
        DestinationIp:
            - '__IP_PLACEHOLDER_1__'
            - '__IP_PLACEHOLDER_2__'
    selection_domain:
        DestinationHostname:
            - '__DOMAIN_PLACEHOLDER_1__'
            - '__DOMAIN_PLACEHOLDER_2__'
    condition: selection_ip or selection_domain
falsepositives:
    - None on a true-positive IOC match
level: critical
(DestinationIp in~ ("__IP_PLACEHOLDER_1__", "__IP_PLACEHOLDER_2__")) or (DestinationHostname in~ ("__DOMAIN_PLACEHOLDER_1__", "__DOMAIN_PLACEHOLDER_2__"))
DestinationIp IN ("__IP_PLACEHOLDER_1__", "__IP_PLACEHOLDER_2__") OR DestinationHostname IN ("__DOMAIN_PLACEHOLDER_1__", "__DOMAIN_PLACEHOLDER_2__")
(DestinationIp:(__IP_PLACEHOLDER_1__ OR __IP_PLACEHOLDER_2__)) OR (DestinationHostname:(__DOMAIN_PLACEHOLDER_1__ OR __DOMAIN_PLACEHOLDER_2__))

exploit

4 rules · platform-neutral, compiled at build time

FakeCaptcha / ClickFix - Clipboard-Injected PowerShell from Explorer

high

"FakeCaptcha" / "ClickFix" social-engineering: malicious site asks user to press Win+R and paste a payload. The result is powershell/mshta launched directly from explorer.exe with iex / base64 / downloadstring in the command line.

category=process_creation · product=windows · sigma_rules/exploit/UC_FAKECAPTCHA.yml

attack.t1059.001 attack.t1204.002 attack.execution
title: FakeCaptcha / ClickFix - Clipboard-Injected PowerShell from Explorer
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d06
status: experimental
description: |
    "FakeCaptcha" / "ClickFix" social-engineering: malicious site asks
    user to press Win+R and paste a payload. The result is
    powershell/mshta launched directly from explorer.exe with iex /
    base64 / downloadstring in the command line.
references:
    - https://attack.mitre.org/techniques/T1059/001/
    - https://attack.mitre.org/techniques/T1204/002/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1059.001
    - attack.t1204.002
    - attack.execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_parent:
        ParentImage|endswith:
            - '\explorer.exe'
            - '\RuntimeBroker.exe'
    selection_child:
        Image|endswith:
            - '\powershell.exe'
            - '\pwsh.exe'
            - '\mshta.exe'
    selection_cmd:
        CommandLine|contains:
            - 'iex'
            - 'invoke-expression'
            - 'frombase64'
            - 'downloadstring'
            - 'hxxp'
            - 'curl '
            - 'wget '
    condition: selection_parent and selection_child and selection_cmd
falsepositives:
    - IT-driven scripted automation that admins paste-launch
level: high
(ParentImage endswith "\\explorer.exe" or ParentImage endswith "\\RuntimeBroker.exe") and (Image endswith "\\powershell.exe" or Image endswith "\\pwsh.exe" or Image endswith "\\mshta.exe") and (CommandLine contains "iex" or CommandLine contains "invoke-expression" or CommandLine contains "frombase64" or CommandLine contains "downloadstring" or CommandLine contains "hxxp" or CommandLine contains "curl " or CommandLine contains "wget ")
ParentImage IN ("*\\explorer.exe", "*\\RuntimeBroker.exe") Image IN ("*\\powershell.exe", "*\\pwsh.exe", "*\\mshta.exe") CommandLine IN ("*iex*", "*invoke-expression*", "*frombase64*", "*downloadstring*", "*hxxp*", "*curl *", "*wget *")
(ParentImage:(*\\explorer.exe OR *\\RuntimeBroker.exe)) AND (Image:(*\\powershell.exe OR *\\pwsh.exe OR *\\mshta.exe)) AND (CommandLine:(*iex* OR *invoke\-expression* OR *frombase64* OR *downloadstring* OR *hxxp* OR *curl\ * OR *wget\ *))

Office Application Spawning Script Host

high

Word/Excel/Outlook/OneNote spawning powershell, cmd, wscript, cscript, mshta, rundll32, regsvr32 — classic macro / embedded- object payload signature.

category=process_creation · product=windows · sigma_rules/exploit/UC_OFFICE_CHILD.yml

attack.t1059 attack.t1566.001 attack.execution
title: Office Application Spawning Script Host
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d07
status: experimental
description: |
    Word/Excel/Outlook/OneNote spawning powershell, cmd, wscript,
    cscript, mshta, rundll32, regsvr32 — classic macro / embedded-
    object payload signature.
references:
    - https://attack.mitre.org/techniques/T1059/
    - https://attack.mitre.org/techniques/T1566/001/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1059
    - attack.t1566.001
    - attack.execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_parent:
        ParentImage|endswith:
            - '\winword.exe'
            - '\excel.exe'
            - '\powerpnt.exe'
            - '\outlook.exe'
            - '\onenote.exe'
            - '\mspub.exe'
            - '\visio.exe'
    selection_child:
        Image|endswith:
            - '\cmd.exe'
            - '\powershell.exe'
            - '\pwsh.exe'
            - '\wscript.exe'
            - '\cscript.exe'
            - '\mshta.exe'
            - '\rundll32.exe'
            - '\regsvr32.exe'
    condition: selection_parent and selection_child
falsepositives:
    - Legitimate automation macros in trusted internal documents
level: high
(ParentImage endswith "\\winword.exe" or ParentImage endswith "\\excel.exe" or ParentImage endswith "\\powerpnt.exe" or ParentImage endswith "\\outlook.exe" or ParentImage endswith "\\onenote.exe" or ParentImage endswith "\\mspub.exe" or ParentImage endswith "\\visio.exe") and (Image endswith "\\cmd.exe" or Image endswith "\\powershell.exe" or Image endswith "\\pwsh.exe" or Image endswith "\\wscript.exe" or Image endswith "\\cscript.exe" or Image endswith "\\mshta.exe" or Image endswith "\\rundll32.exe" or Image endswith "\\regsvr32.exe")
ParentImage IN ("*\\winword.exe", "*\\excel.exe", "*\\powerpnt.exe", "*\\outlook.exe", "*\\onenote.exe", "*\\mspub.exe", "*\\visio.exe") Image IN ("*\\cmd.exe", "*\\powershell.exe", "*\\pwsh.exe", "*\\wscript.exe", "*\\cscript.exe", "*\\mshta.exe", "*\\rundll32.exe", "*\\regsvr32.exe")
(ParentImage:(*\\winword.exe OR *\\excel.exe OR *\\powerpnt.exe OR *\\outlook.exe OR *\\onenote.exe OR *\\mspub.exe OR *\\visio.exe)) AND (Image:(*\\cmd.exe OR *\\powershell.exe OR *\\pwsh.exe OR *\\wscript.exe OR *\\cscript.exe OR *\\mshta.exe OR *\\rundll32.exe OR *\\regsvr32.exe))

Obfuscated / Encoded PowerShell Execution

high

PowerShell launched with -EncodedCommand, base64 strings, hidden window, no-profile, bypass policy, IEX / Invoke-Expression / Net .WebClient.DownloadString — combinations indicating evasion.

category=process_creation · product=windows · sigma_rules/exploit/UC_PS_OBFUSCATED.yml

attack.t1059.001 attack.t1027 attack.execution attack.defense-evasion
title: Obfuscated / Encoded PowerShell Execution
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d08
status: experimental
description: |
    PowerShell launched with -EncodedCommand, base64 strings, hidden
    window, no-profile, bypass policy, IEX / Invoke-Expression / Net
    .WebClient.DownloadString — combinations indicating evasion.
references:
    - https://attack.mitre.org/techniques/T1059/001/
    - https://attack.mitre.org/techniques/T1027/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1059.001
    - attack.t1027
    - attack.execution
    - attack.defense-evasion
logsource:
    category: process_creation
    product: windows
detection:
    selection_image:
        Image|endswith:
            - '\powershell.exe'
            - '\pwsh.exe'
    selection_args:
        CommandLine|contains:
            - '-enc '
            - 'EncodedCommand'
            - 'FromBase64String'
            - 'Invoke-Expression'
            - 'IEX('
            - 'DownloadString'
            - 'Net.WebClient'
            - '-w hidden'
            - '-WindowStyle Hidden'
            - '-nop'
            - '-NoProfile'
            - '-ep bypass'
            - '-ExecutionPolicy Bypass'
    condition: selection_image and selection_args
falsepositives:
    - DevOps tooling that legitimately uses encoded command for
      cross-shell escaping
level: high
(Image endswith "\\powershell.exe" or Image endswith "\\pwsh.exe") and (CommandLine contains "-enc " or CommandLine contains "EncodedCommand" or CommandLine contains "FromBase64String" or CommandLine contains "Invoke-Expression" or CommandLine contains "IEX(" or CommandLine contains "DownloadString" or CommandLine contains "Net.WebClient" or CommandLine contains "-w hidden" or CommandLine contains "-WindowStyle Hidden" or CommandLine contains "-nop" or CommandLine contains "-NoProfile" or CommandLine contains "-ep bypass" or CommandLine contains "-ExecutionPolicy Bypass")
Image IN ("*\\powershell.exe", "*\\pwsh.exe") CommandLine IN ("*-enc *", "*EncodedCommand*", "*FromBase64String*", "*Invoke-Expression*", "*IEX(*", "*DownloadString*", "*Net.WebClient*", "*-w hidden*", "*-WindowStyle Hidden*", "*-nop*", "*-NoProfile*", "*-ep bypass*", "*-ExecutionPolicy Bypass*")
(Image:(*\\powershell.exe OR *\\pwsh.exe)) AND (CommandLine:(*\-enc\ * OR *EncodedCommand* OR *FromBase64String* OR *Invoke\-Expression* OR *IEX\(* OR *DownloadString* OR *Net.WebClient* OR *\-w\ hidden* OR *\-WindowStyle\ Hidden* OR *\-nop* OR *\-NoProfile* OR *\-ep\ bypass* OR *\-ExecutionPolicy\ Bypass*))

Trusted Vendor Binary Launching Unusual Children

medium

A signed vendor binary (in the article's named-vendors list) spawning script-host or LOLBin children. Strongest signal when paired with a recent CVE / supply-chain advisory naming the same vendor.

category=process_creation · product=windows · sigma_rules/exploit/UC_SUPPLY_CHAIN.yml

attack.t1195 attack.initial-access
title: Trusted Vendor Binary Launching Unusual Children
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d09
status: experimental
description: |
    A signed vendor binary (in the article's named-vendors list)
    spawning script-host or LOLBin children. Strongest signal when
    paired with a recent CVE / supply-chain advisory naming the same
    vendor.
references:
    - https://attack.mitre.org/techniques/T1195/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1195
    - attack.initial-access
logsource:
    category: process_creation
    product: windows
detection:
    selection_child:
        Image|endswith:
            - '\powershell.exe'
            - '\pwsh.exe'
            - '\cmd.exe'
            - '\rundll32.exe'
            - '\regsvr32.exe'
            - '\mshta.exe'
            - '\wscript.exe'
            - '\cscript.exe'
            - '\wmic.exe'
            - '\bitsadmin.exe'
    selection_parent_vendor:
        ParentImage|contains:
            - '\Program Files\'
            - '\Program Files (x86)\'
    condition: selection_child and selection_parent_vendor
falsepositives:
    - Many — installers and updaters legitimately spawn children. Pin
      the parent path to specific vendor binaries observed in the
      article before alerting.
level: medium
(Image endswith "\\powershell.exe" or Image endswith "\\pwsh.exe" or Image endswith "\\cmd.exe" or Image endswith "\\rundll32.exe" or Image endswith "\\regsvr32.exe" or Image endswith "\\mshta.exe" or Image endswith "\\wscript.exe" or Image endswith "\\cscript.exe" or Image endswith "\\wmic.exe" or Image endswith "\\bitsadmin.exe") and (ParentImage contains "\\Program Files\\" or ParentImage contains "\\Program Files (x86)\\")
Image IN ("*\\powershell.exe", "*\\pwsh.exe", "*\\cmd.exe", "*\\rundll32.exe", "*\\regsvr32.exe", "*\\mshta.exe", "*\\wscript.exe", "*\\cscript.exe", "*\\wmic.exe", "*\\bitsadmin.exe") ParentImage IN ("*\\Program Files\\*", "*\\Program Files (x86)\\*")
(Image:(*\\powershell.exe OR *\\pwsh.exe OR *\\cmd.exe OR *\\rundll32.exe OR *\\regsvr32.exe OR *\\mshta.exe OR *\\wscript.exe OR *\\cscript.exe OR *\\wmic.exe OR *\\bitsadmin.exe)) AND (ParentImage:(*\\Program\ Files\\* OR *\\Program\ Files\ \(x86\)\\*))

install

5 rules · platform-neutral, compiled at build time

Browser Extension Installation via Registry

medium

Registry writes under the browser extension policy keys — administrative install of an extension. Often used by adware / info-stealers to bypass user-level extension controls.

category=registry_event · product=windows · sigma_rules/install/UC_BROWSER_EXT.yml

attack.t1176 attack.persistence
title: Browser Extension Installation via Registry
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d0a
status: experimental
description: |
    Registry writes under the browser extension policy keys —
    administrative install of an extension. Often used by adware /
    info-stealers to bypass user-level extension controls.
references:
    - https://attack.mitre.org/techniques/T1176/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1176
    - attack.persistence
logsource:
    category: registry_event
    product: windows
detection:
    selection:
        TargetObject|contains:
            - '\Software\Google\Chrome\Extensions\'
            - '\Software\Microsoft\Edge\Extensions\'
            - '\Software\Mozilla\Firefox\Extensions\'
    condition: selection
falsepositives:
    - Group-policy-managed extension whitelists
level: medium
TargetObject contains "\\Software\\Google\\Chrome\\Extensions\\" or TargetObject contains "\\Software\\Microsoft\\Edge\\Extensions\\" or TargetObject contains "\\Software\\Mozilla\\Firefox\\Extensions\\"
TargetObject IN ("*\\Software\\Google\\Chrome\\Extensions\\*", "*\\Software\\Microsoft\\Edge\\Extensions\\*", "*\\Software\\Mozilla\\Firefox\\Extensions\\*")
TargetObject:(*\\Software\\Google\\Chrome\\Extensions\\* OR *\\Software\\Microsoft\\Edge\\Extensions\\* OR *\\Software\\Mozilla\\Firefox\\Extensions\\*)

File or Process Matching Article Hash IOCs

critical

Replace `__HASH_LIST__` placeholder with article-specific SHA256 values. Use a watchlist or external indicator file for management at scale.

category=process_creation · product=windows · sigma_rules/install/UC_HASH_IOC.yml

attack.t1027 attack.defense-evasion
title: File or Process Matching Article Hash IOCs
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d0b
status: experimental
description: |
    Replace `__HASH_LIST__` placeholder with article-specific SHA256
    values. Use a watchlist or external indicator file for management
    at scale.
references:
    - https://attack.mitre.org/techniques/T1027/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1027
    - attack.defense-evasion
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        Hashes|contains:
            - 'SHA256=__HASH_PLACEHOLDER_REPLACE_ME__'
    condition: selection
falsepositives:
    - None on a true-positive hash match
level: critical
Hashes contains "SHA256=__HASH_PLACEHOLDER_REPLACE_ME__"
Hashes="*SHA256=__HASH_PLACEHOLDER_REPLACE_ME__*"
Hashes:*SHA256\=__HASH_PLACEHOLDER_REPLACE_ME__*

Remote-Management (RMM) Tool Execution

high

AnyDesk / TeamViewer / ScreenConnect / Atera / Splashtop / RustDesk — RMM tools attackers commonly install for hands-on- keyboard access. Filter against the IT estate's known tool.

category=process_creation · product=windows · sigma_rules/install/UC_RMM_TOOLS.yml

attack.t1219 attack.command-and-control
title: Remote-Management (RMM) Tool Execution
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d0c
status: experimental
description: |
    AnyDesk / TeamViewer / ScreenConnect / Atera / Splashtop /
    RustDesk — RMM tools attackers commonly install for hands-on-
    keyboard access. Filter against the IT estate's known tool.
references:
    - https://attack.mitre.org/techniques/T1219/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1219
    - attack.command-and-control
logsource:
    category: process_creation
    product: windows
detection:
    selection:
        Image|endswith:
            - '\AnyDesk.exe'
            - '\TeamViewer.exe'
            - '\TeamViewer_Service.exe'
            - '\ScreenConnect.ClientService.exe'
            - '\ConnectWiseControl.ClientService.exe'
            - '\atera_agent.exe'
            - '\SplashtopStreamer.exe'
            - '\RustDesk.exe'
            - '\NinjaOne.exe'
    condition: selection
falsepositives:
    - IT-approved RMM in use across the estate. Maintain a known-IT-
      tool exclusion list per environment.
level: high
Image endswith "\\AnyDesk.exe" or Image endswith "\\TeamViewer.exe" or Image endswith "\\TeamViewer_Service.exe" or Image endswith "\\ScreenConnect.ClientService.exe" or Image endswith "\\ConnectWiseControl.ClientService.exe" or Image endswith "\\atera_agent.exe" or Image endswith "\\SplashtopStreamer.exe" or Image endswith "\\RustDesk.exe" or Image endswith "\\NinjaOne.exe"
Image IN ("*\\AnyDesk.exe", "*\\TeamViewer.exe", "*\\TeamViewer_Service.exe", "*\\ScreenConnect.ClientService.exe", "*\\ConnectWiseControl.ClientService.exe", "*\\atera_agent.exe", "*\\SplashtopStreamer.exe", "*\\RustDesk.exe", "*\\NinjaOne.exe")
Image:(*\\AnyDesk.exe OR *\\TeamViewer.exe OR *\\TeamViewer_Service.exe OR *\\ScreenConnect.ClientService.exe OR *\\ConnectWiseControl.ClientService.exe OR *\\atera_agent.exe OR *\\SplashtopStreamer.exe OR *\\RustDesk.exe OR *\\NinjaOne.exe)

Scheduled Task Creation with Suspicious Image / Encoded Args

high

schtasks.exe /create with payload-shaped action — points at powershell, cmd, rundll32, encoded-base64, or user-writable paths.

category=process_creation · product=windows · sigma_rules/install/UC_SCHEDULED_TASK.yml

attack.t1053.005 attack.persistence attack.execution
title: Scheduled Task Creation with Suspicious Image / Encoded Args
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d0d
status: experimental
description: |
    schtasks.exe /create with payload-shaped action — points at
    powershell, cmd, rundll32, encoded-base64, or user-writable paths.
references:
    - https://attack.mitre.org/techniques/T1053/005/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1053.005
    - attack.persistence
    - attack.execution
logsource:
    category: process_creation
    product: windows
detection:
    selection_schtasks:
        Image|endswith: '\schtasks.exe'
        CommandLine|contains: '/create'
    selection_payload:
        CommandLine|contains:
            - 'powershell'
            - 'cmd.exe'
            - 'rundll32'
            - '-enc'
            - 'FromBase64'
            - '\Users\Public'
            - '\AppData\'
    condition: selection_schtasks and selection_payload
falsepositives:
    - GPO-driven scheduled tasks, MDT/SCCM imaging
level: high
(Image endswith "\\schtasks.exe" and CommandLine contains "/create") and (CommandLine contains "powershell" or CommandLine contains "cmd.exe" or CommandLine contains "rundll32" or CommandLine contains "-enc" or CommandLine contains "FromBase64" or CommandLine contains "\\Users\\Public" or CommandLine contains "\\AppData\\")
Image="*\\schtasks.exe" CommandLine="*/create*" CommandLine IN ("*powershell*", "*cmd.exe*", "*rundll32*", "*-enc*", "*FromBase64*", "*\\Users\\Public*", "*\\AppData\\*")
(Image:*\\schtasks.exe AND CommandLine:*\/create*) AND (CommandLine:(*powershell* OR *cmd.exe* OR *rundll32* OR *\-enc* OR *FromBase64* OR *\\Users\\Public* OR *\\AppData\\*))

Service Persistence via sc.exe with User-Writable Path

high

sc.exe create with the binary path under \Users\, \AppData\, \ProgramData\, or \Temp\ — service-install persistence outside legitimate program directories.

category=process_creation · product=windows · sigma_rules/install/UC_SERVICE_PERSIST.yml

attack.t1543.003 attack.persistence
title: Service Persistence via sc.exe with User-Writable Path
id: 7c8b2e10-4d4f-4a8c-9c1f-bf6e2c4a8d0e
status: experimental
description: |
    sc.exe create with the binary path under \Users\, \AppData\,
    \ProgramData\, or \Temp\ — service-install persistence outside
    legitimate program directories.
references:
    - https://attack.mitre.org/techniques/T1543/003/
author: Clankerusecase
date: 2026/05/02
tags:
    - attack.t1543.003
    - attack.persistence
logsource:
    category: process_creation
    product: windows
detection:
    selection_sc:
        Image|endswith: '\sc.exe'
        CommandLine|contains: 'create'
    selection_path:
        CommandLine|contains:
            - '\Users\'
            - '\AppData\'
            - '\ProgramData\'
            - '\Temp\'
    condition: selection_sc and selection_path
falsepositives:
    - Internal install scripts dropping a service from %ProgramData%
level: high
(Image endswith "\\sc.exe" and CommandLine contains "create") and (CommandLine contains "\\Users\\" or CommandLine contains "\\AppData\\" or CommandLine contains "\\ProgramData\\" or CommandLine contains "\\Temp\\")
Image="*\\sc.exe" CommandLine="*create*" CommandLine IN ("*\\Users\\*", "*\\AppData\\*", "*\\ProgramData\\*", "*\\Temp\\*")
(Image:*\\sc.exe AND CommandLine:*create*) AND (CommandLine:(*\\Users\\* OR *\\AppData\\* OR *\\ProgramData\\* OR *\\Temp\\*))

Splunk · CIM datamodels (SPL)

Pick a CIM datamodel from the sidebar — every query is verbatim Splunk SPL using tstats against accelerated datamodels. House style: summariesonly macro for fast tstats; drop_dm_object_name(<DM>) to flatten object-prefixed fields; <placeholder> fields the analyst replaces during a shift.

tstats vs | from datamodel: vs raw search. tstats queries against an accelerated CIM model are the fastest path — they read the precomputed summary index. If your env has no CIM acceleration, every tstats query below has a Non-summarised toggle that switches to summariesonly=false (slower but works without the summary). Raw search index=... queries always work but won't benefit from any acceleration.

8 CIM datamodels curated 40 queries Click Copy on any query to paste into Splunk Search.

Endpoint.Processes

20 columns · 6 queries

Schema (click to expand)

_time · host · dest · user · process_name · process_path · process · process_id · process_guid · process_hash · parent_process_name · parent_process_path · parent_process · parent_process_id · parent_process_guid · process_integrity_level · action · vendor_product · user_id · session_id

All processes for a user

User triage — every process exec tied to one identity in the last 24h. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Processes.process) AS process, values(Processes.parent_process_name) AS parent
    from datamodel=Endpoint.Processes
    where Processes.user=<UserName> earliest=-24h@h
    by Processes.dest, Processes.process_name, _time span=10m
| `drop_dm_object_name(Processes)`
| sort -_time
| tstats summariesonly=false count, values(Processes.process) AS process, values(Processes.parent_process_name) AS parent
    from datamodel=Endpoint.Processes
    where Processes.user=<UserName> earliest=-24h@h
    by Processes.dest, Processes.process_name, _time span=10m
| `drop_dm_object_name(Processes)`
| sort -_time

All processes on a host

Host triage — every process exec on one device. Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Processes.process) AS process, values(Processes.parent_process_name) AS parent
    from datamodel=Endpoint.Processes
    where Processes.dest=<DeviceName> earliest=-24h@h
    by Processes.user, Processes.process_name, _time span=1m
| `drop_dm_object_name(Processes)`
| sort -_time
| tstats summariesonly=false count, values(Processes.process) AS process, values(Processes.parent_process_name) AS parent
    from datamodel=Endpoint.Processes
    where Processes.dest=<DeviceName> earliest=-24h@h
    by Processes.user, Processes.process_name, _time span=1m
| `drop_dm_object_name(Processes)`
| sort -_time

Children of a specific process

What did `<parent.exe>` spawn? Replace the parent process name.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Processes.process) AS cmdline
    from datamodel=Endpoint.Processes
    where Processes.parent_process_name=<parent.exe> earliest=-24h@h
    by Processes.dest, Processes.user, Processes.process_name
| tstats summariesonly=false count, values(Processes.process) AS cmdline
    from datamodel=Endpoint.Processes
    where Processes.parent_process_name=<parent.exe> earliest=-24h@h
    by Processes.dest, Processes.user, Processes.process_name

Find every host that ran a binary

Binary-name pivot. Replace `<binary.exe>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, min(_time) AS first_seen, max(_time) AS last_seen
    from datamodel=Endpoint.Processes
    where Processes.process_name=<binary.exe> earliest=-7d@d
    by Processes.dest, Processes.user, Processes.process
| tstats summariesonly=false count, min(_time) AS first_seen, max(_time) AS last_seen
    from datamodel=Endpoint.Processes
    where Processes.process_name=<binary.exe> earliest=-7d@d
    by Processes.dest, Processes.user, Processes.process

Find every host that ran a hash

IOC pivot — every host that ran a binary with this SHA256. Replace `<sha256>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, min(_time) AS first_seen, max(_time) AS last_seen
    from datamodel=Endpoint.Processes
    where Processes.process_hash=<sha256> earliest=-30d@d
    by Processes.dest, Processes.user, Processes.process_name, Processes.process
| tstats summariesonly=false count, min(_time) AS first_seen, max(_time) AS last_seen
    from datamodel=Endpoint.Processes
    where Processes.process_hash=<sha256> earliest=-30d@d
    by Processes.dest, Processes.user, Processes.process_name, Processes.process

Process tree for a user during a time window

Reconstruct what a user was doing between `<start>` and `<end>` (use `-2h@h`, `-30m@m`, etc).

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Processes
    where Processes.user=<UserName> earliest=<start> latest=<end>
    by _time, Processes.dest, Processes.parent_process_name, Processes.process_name, Processes.process
| `drop_dm_object_name(Processes)`
| sort _time
| tstats summariesonly=false count
    from datamodel=Endpoint.Processes
    where Processes.user=<UserName> earliest=<start> latest=<end>
    by _time, Processes.dest, Processes.parent_process_name, Processes.process_name, Processes.process
| `drop_dm_object_name(Processes)`
| sort _time

Endpoint.Filesystem

15 columns · 5 queries

Schema (click to expand)

_time · host · dest · user · file_name · file_path · file_hash · file_size · file_create_time · file_modify_time · action · process_name · process_path · process_id · vendor_product

All file activity on a host

Host triage — every create / modify / delete on one device. Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Filesystem
    where Filesystem.dest=<DeviceName> earliest=-24h@h
    by Filesystem.user, Filesystem.action, Filesystem.process_name, Filesystem.file_path, Filesystem.file_name, _time span=10m
| sort -_time
| tstats summariesonly=false count
    from datamodel=Endpoint.Filesystem
    where Filesystem.dest=<DeviceName> earliest=-24h@h
    by Filesystem.user, Filesystem.action, Filesystem.process_name, Filesystem.file_path, Filesystem.file_name, _time span=10m
| sort -_time

All file activity for a user

User triage. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Filesystem
    where Filesystem.user=<UserName> earliest=-24h@h
    by Filesystem.dest, Filesystem.action, Filesystem.process_name, Filesystem.file_path, Filesystem.file_name
| tstats summariesonly=false count
    from datamodel=Endpoint.Filesystem
    where Filesystem.user=<UserName> earliest=-24h@h
    by Filesystem.dest, Filesystem.action, Filesystem.process_name, Filesystem.file_path, Filesystem.file_name

Files written by a process

What did `<binary.exe>` create? Replace the process name.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Filesystem
    where Filesystem.action="created" Filesystem.process_name=<binary.exe> earliest=-24h@h
    by Filesystem.dest, Filesystem.user, Filesystem.file_path, Filesystem.file_name
| tstats summariesonly=false count
    from datamodel=Endpoint.Filesystem
    where Filesystem.action="created" Filesystem.process_name=<binary.exe> earliest=-24h@h
    by Filesystem.dest, Filesystem.user, Filesystem.file_path, Filesystem.file_name

Files written under a directory path

Directory pivot. Replace `<path-fragment>` (e.g. `\\AppData\\Local\\Temp\\`).

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Filesystem.process_name) AS writers
    from datamodel=Endpoint.Filesystem
    where Filesystem.action="created" Filesystem.file_path="*<path-fragment>*" earliest=-24h@h
    by Filesystem.dest, Filesystem.user, Filesystem.file_name
| tstats summariesonly=false count, values(Filesystem.process_name) AS writers
    from datamodel=Endpoint.Filesystem
    where Filesystem.action="created" Filesystem.file_path="*<path-fragment>*" earliest=-24h@h
    by Filesystem.dest, Filesystem.user, Filesystem.file_name

Hash-IOC sweep across the fleet

Was this hash ever written? Replace `<sha256>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Filesystem.dest) AS hosts
    from datamodel=Endpoint.Filesystem
    where Filesystem.file_hash=<sha256> earliest=-30d@d
    by Filesystem.file_name
| tstats summariesonly=false count, values(Filesystem.dest) AS hosts
    from datamodel=Endpoint.Filesystem
    where Filesystem.file_hash=<sha256> earliest=-30d@d
    by Filesystem.file_name

Endpoint.Registry

13 columns · 4 queries

Schema (click to expand)

_time · host · dest · user · registry_path · registry_key_name · registry_value_name · registry_value_data · registry_value_type · action · process_name · process_id · vendor_product

All registry activity on a host

Host triage — every registry write / modify / delete on one device. Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Registry
    where Registry.dest=<DeviceName> earliest=-24h@h
    by Registry.user, Registry.action, Registry.process_name, Registry.registry_path, Registry.registry_value_name
| tstats summariesonly=false count
    from datamodel=Endpoint.Registry
    where Registry.dest=<DeviceName> earliest=-24h@h
    by Registry.user, Registry.action, Registry.process_name, Registry.registry_path, Registry.registry_value_name

Registry activity for a user

User triage. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Registry
    where Registry.user=<UserName> earliest=-24h@h
    by Registry.dest, Registry.action, Registry.process_name, Registry.registry_path
| tstats summariesonly=false count
    from datamodel=Endpoint.Registry
    where Registry.user=<UserName> earliest=-24h@h
    by Registry.dest, Registry.action, Registry.process_name, Registry.registry_path

Registry writes under a key path

Key-path pivot. Replace `<path-fragment>` (e.g. `\\Run\\` or `\\Services\\`).

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Endpoint.Registry
    where Registry.action in ("created","modified")
        and Registry.registry_path="*<path-fragment>*" earliest=-24h@h
    by Registry.dest, Registry.user, Registry.process_name, Registry.registry_path, Registry.registry_value_data
| tstats summariesonly=false count
    from datamodel=Endpoint.Registry
    where Registry.action in ("created","modified")
        and Registry.registry_path="*<path-fragment>*" earliest=-24h@h
    by Registry.dest, Registry.user, Registry.process_name, Registry.registry_path, Registry.registry_value_data

Find which process wrote a registry value

Pivot for an interesting key — who set it? Replace `<value-name>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Registry.registry_value_data) AS data
    from datamodel=Endpoint.Registry
    where Registry.registry_value_name=<value-name> Registry.action in ("created","modified")
        earliest=-7d@d
    by Registry.dest, Registry.user, Registry.process_name, Registry.registry_path
| tstats summariesonly=false count, values(Registry.registry_value_data) AS data
    from datamodel=Endpoint.Registry
    where Registry.registry_value_name=<value-name> Registry.action in ("created","modified")
        earliest=-7d@d
    by Registry.dest, Registry.user, Registry.process_name, Registry.registry_path

Network_Traffic.All_Traffic

21 columns · 5 queries

Schema (click to expand)

_time · src · dest · src_ip · dest_ip · src_port · dest_port · transport · protocol · action · bytes · bytes_in · bytes_out · packets · duration · user · process · rule · vendor_product · src_category · dest_category

All outbound from a host

Host triage — every allowed outbound connection. Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, sum(All_Traffic.bytes_out) AS bytes_out
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.action="allowed"
        earliest=-24h@h
    by All_Traffic.dest, All_Traffic.dest_port, _time span=10m
| `drop_dm_object_name(All_Traffic)`
| sort -_time
| tstats summariesonly=false count, sum(All_Traffic.bytes_out) AS bytes_out
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.action="allowed"
        earliest=-24h@h
    by All_Traffic.dest, All_Traffic.dest_port, _time span=10m
| `drop_dm_object_name(All_Traffic)`
| sort -_time

All connections to an IP

IP IOC pivot — every host that talked to it. Replace `<IP>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(All_Traffic.dest_port) AS ports, sum(All_Traffic.bytes_out) AS bytes_out
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.dest_ip=<IP> earliest=-7d@d
    by All_Traffic.src, All_Traffic.user
| tstats summariesonly=false count, values(All_Traffic.dest_port) AS ports, sum(All_Traffic.bytes_out) AS bytes_out
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.dest_ip=<IP> earliest=-7d@d
    by All_Traffic.src, All_Traffic.user

All connections on a port from a host

Port-specific triage. Replace `<DeviceName>` and `<port>` (e.g. 3389, 22, 445).

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.dest_port=<port> earliest=-24h@h
    by All_Traffic.dest, All_Traffic.action, _time span=5m
| tstats summariesonly=false count
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.dest_port=<port> earliest=-24h@h
    by All_Traffic.dest, All_Traffic.action, _time span=5m

Top destinations for a host

What's a host been talking to most? Useful for first-look beaconing review.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, sum(All_Traffic.bytes_out) AS bytes_out
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.action="allowed" earliest=-24h@h
    by All_Traffic.dest
| `drop_dm_object_name(All_Traffic)`
| sort - count
| tstats summariesonly=false count, sum(All_Traffic.bytes_out) AS bytes_out
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.action="allowed" earliest=-24h@h
    by All_Traffic.dest
| `drop_dm_object_name(All_Traffic)`
| sort - count

Failed / denied connections from a host

What's the firewall blocking from this host? Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.action!="allowed" earliest=-24h@h
    by All_Traffic.dest, All_Traffic.dest_port, All_Traffic.action
| tstats summariesonly=false count
    from datamodel=Network_Traffic.All_Traffic
    where All_Traffic.src=<DeviceName>
        and All_Traffic.action!="allowed" earliest=-24h@h
    by All_Traffic.dest, All_Traffic.dest_port, All_Traffic.action

Authentication.Authentication

17 columns · 5 queries

Schema (click to expand)

_time · src · dest · user · src_user · src_user_id · user_id · action · app · authentication_method · authentication_service · duration · session_id · signature · signature_id · reason · vendor_product

All authentication events for a user

User triage — every login (success + fail) for one identity. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Authentication.Authentication
    where Authentication.user=<UserName> earliest=-24h@h
    by Authentication.action, Authentication.src, Authentication.dest, _time span=10m
| `drop_dm_object_name(Authentication)`
| sort -_time
| tstats summariesonly=false count
    from datamodel=Authentication.Authentication
    where Authentication.user=<UserName> earliest=-24h@h
    by Authentication.action, Authentication.src, Authentication.dest, _time span=10m
| `drop_dm_object_name(Authentication)`
| sort -_time

All logins from an IP

IP pivot — every account this address has authenticated against. Replace `<IP>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Authentication.Authentication
    where Authentication.src=<IP> earliest=-7d@d
    by Authentication.user, Authentication.action, Authentication.dest
| tstats summariesonly=false count
    from datamodel=Authentication.Authentication
    where Authentication.src=<IP> earliest=-7d@d
    by Authentication.user, Authentication.action, Authentication.dest

Logins to a specific host

Host pivot — who's logged on (and tried to log on) here? Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Authentication.Authentication
    where Authentication.dest=<DeviceName> earliest=-24h@h
    by Authentication.user, Authentication.src, Authentication.action
| tstats summariesonly=false count
    from datamodel=Authentication.Authentication
    where Authentication.dest=<DeviceName> earliest=-24h@h
    by Authentication.user, Authentication.src, Authentication.action

Failed authentications for a user

Fast triage on a user's failures. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Authentication.Authentication
    where Authentication.action="failure" Authentication.user=<UserName> earliest=-24h@h
    by Authentication.src, Authentication.dest, Authentication.reason, _time span=10m
| tstats summariesonly=false count
    from datamodel=Authentication.Authentication
    where Authentication.action="failure" Authentication.user=<UserName> earliest=-24h@h
    by Authentication.src, Authentication.dest, Authentication.reason, _time span=10m

All source IPs a user has used

Find the geographic / network footprint for one identity. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` values(Authentication.src) AS src_ips, count
    from datamodel=Authentication.Authentication
    where Authentication.action="success" Authentication.user=<UserName> earliest=-30d@d
    by Authentication.user
| tstats summariesonly=false values(Authentication.src) AS src_ips, count
    from datamodel=Authentication.Authentication
    where Authentication.action="success" Authentication.user=<UserName> earliest=-30d@d
    by Authentication.user

Web.Web

19 columns · 5 queries

Schema (click to expand)

_time · src · dest · user · url · url_domain · url_length · uri_path · uri_query · http_method · http_user_agent · http_content_type · http_referrer · status · response_time · bytes · bytes_in · bytes_out · category

All HTTP traffic for a user

User triage — every web request for one identity. Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Web.Web
    where Web.user=<UserName> earliest=-24h@h
    by Web.url_domain, Web.http_method, Web.status, _time span=10m
| tstats summariesonly=false count
    from datamodel=Web.Web
    where Web.user=<UserName> earliest=-24h@h
    by Web.url_domain, Web.http_method, Web.status, _time span=10m

All HTTP traffic from a source

Source pivot. Replace `<src>` with hostname or IP.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, sum(Web.bytes_out) AS bytes_out
    from datamodel=Web.Web
    where Web.src=<src> earliest=-24h@h
    by Web.url_domain, Web.http_method, Web.status
| tstats summariesonly=false count, sum(Web.bytes_out) AS bytes_out
    from datamodel=Web.Web
    where Web.src=<src> earliest=-24h@h
    by Web.url_domain, Web.http_method, Web.status

All requests to a domain

Domain pivot — every host that fetched it. Replace `<domain>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, values(Web.url) AS urls
    from datamodel=Web.Web
    where Web.url_domain=<domain> earliest=-7d@d
    by Web.src, Web.user, Web.http_method, Web.status
| tstats summariesonly=false count, values(Web.url) AS urls
    from datamodel=Web.Web
    where Web.url_domain=<domain> earliest=-7d@d
    by Web.src, Web.user, Web.http_method, Web.status

Requests with a User-Agent

UA pivot — find every host using a specific UA. Replace `<UA-fragment>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Web.Web
    where Web.http_user_agent="*<UA-fragment>*" earliest=-24h@h
    by Web.src, Web.url_domain, Web.http_user_agent
| tstats summariesonly=false count
    from datamodel=Web.Web
    where Web.http_user_agent="*<UA-fragment>*" earliest=-24h@h
    by Web.src, Web.url_domain, Web.http_user_agent

Top domains for a user

What's a user been browsing most? Replace `<UserName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Web.Web
    where Web.user=<UserName> earliest=-24h@h
    by Web.url_domain
| `drop_dm_object_name(Web)`
| sort - count
| tstats summariesonly=false count
    from datamodel=Web.Web
    where Web.user=<UserName> earliest=-24h@h
    by Web.url_domain
| `drop_dm_object_name(Web)`
| sort - count

Network_Resolution.DNS

13 columns · 5 queries

Schema (click to expand)

_time · src · dest · src_ip · dest_ip · query · query_type · answer · reply_code · reply_code_id · transport · duration · vendor_product

All DNS queries from a host

Host triage — every name resolution from one device. Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Network_Resolution.DNS
    where DNS.src=<DeviceName> earliest=-24h@h
    by DNS.query, DNS.query_type, DNS.reply_code
| tstats summariesonly=false count
    from datamodel=Network_Resolution.DNS
    where DNS.src=<DeviceName> earliest=-24h@h
    by DNS.query, DNS.query_type, DNS.reply_code

Hosts that resolved a domain

Domain pivot — every device that asked for it. Replace `<domain>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count, min(_time) AS first_seen, max(_time) AS last_seen
    from datamodel=Network_Resolution.DNS
    where DNS.query=<domain> earliest=-7d@d
    by DNS.src
| tstats summariesonly=false count, min(_time) AS first_seen, max(_time) AS last_seen
    from datamodel=Network_Resolution.DNS
    where DNS.query=<domain> earliest=-7d@d
    by DNS.src

DNS queries that resolved to an IP

IP-back-pivot — what names point to this address? Replace `<IP>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Network_Resolution.DNS
    where DNS.answer=<IP> earliest=-7d@d
    by DNS.query, DNS.src
| tstats summariesonly=false count
    from datamodel=Network_Resolution.DNS
    where DNS.answer=<IP> earliest=-7d@d
    by DNS.query, DNS.src

Top domains for a host

What's a host been resolving most? Replace `<DeviceName>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Network_Resolution.DNS
    where DNS.src=<DeviceName> earliest=-24h@h
    by DNS.query
| `drop_dm_object_name(DNS)`
| sort - count
| tstats summariesonly=false count
    from datamodel=Network_Resolution.DNS
    where DNS.src=<DeviceName> earliest=-24h@h
    by DNS.query
| `drop_dm_object_name(DNS)`
| sort - count

DNS failures from a host

NXDOMAIN / SERVFAIL responses — failed C2 / DGA / typo-squat indicator.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Network_Resolution.DNS
    where DNS.src=<DeviceName>
        and DNS.reply_code in ("NXDOMAIN","SERVFAIL","REFUSED") earliest=-24h@h
    by DNS.query, DNS.reply_code
| tstats summariesonly=false count
    from datamodel=Network_Resolution.DNS
    where DNS.src=<DeviceName>
        and DNS.reply_code in ("NXDOMAIN","SERVFAIL","REFUSED") earliest=-24h@h
    by DNS.query, DNS.reply_code

Email.All_Email

15 columns · 5 queries

Schema (click to expand)

_time · src_user · recipient · subject · message_id · internal_message_id · message_size · delay · filename · file_hash · url · src · src_ip · vendor_product · action

All inbound for a recipient

Recipient triage — every email this user received. Replace `<email>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Email.All_Email
    where Email.recipient=<email> earliest=-7d@d
    by Email.src_user, Email.subject, Email.action, _time span=1h
| sort -_time
| tstats summariesonly=false count
    from datamodel=Email.All_Email
    where Email.recipient=<email> earliest=-7d@d
    by Email.src_user, Email.subject, Email.action, _time span=1h
| sort -_time

All emails from a sender

Sender pivot. Replace `<email-or-domain>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Email.All_Email
    where Email.src_user=<email-or-domain> earliest=-7d@d
    by Email.recipient, Email.subject, Email.action
| tstats summariesonly=false count
    from datamodel=Email.All_Email
    where Email.src_user=<email-or-domain> earliest=-7d@d
    by Email.recipient, Email.subject, Email.action

Emails by subject

Subject-line pivot. Replace `<subject-fragment>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Email.All_Email
    where Email.subject="*<subject-fragment>*" earliest=-7d@d
    by Email.src_user, Email.recipient, Email.action, Email.filename
| tstats summariesonly=false count
    from datamodel=Email.All_Email
    where Email.subject="*<subject-fragment>*" earliest=-7d@d
    by Email.src_user, Email.recipient, Email.action, Email.filename

Emails with an attachment name / extension

Filename pivot. Replace `<filename-or-ext>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Email.All_Email
    where Email.filename="*<filename-or-ext>*" earliest=-7d@d
    by Email.recipient, Email.src_user, Email.filename, Email.subject
| tstats summariesonly=false count
    from datamodel=Email.All_Email
    where Email.filename="*<filename-or-ext>*" earliest=-7d@d
    by Email.recipient, Email.src_user, Email.filename, Email.subject

Emails with a URL

URL pivot — every recipient who got a message containing this link. Replace `<url-fragment>`.

Toggle if your env has no CIM data-model acceleration.
| tstats `summariesonly` count
    from datamodel=Email.All_Email
    where Email.url="*<url-fragment>*" earliest=-7d@d
    by Email.recipient, Email.src_user, Email.subject
| tstats summariesonly=false count
    from datamodel=Email.All_Email
    where Email.url="*<url-fragment>*" earliest=-7d@d
    by Email.recipient, Email.src_user, Email.subject