← Blog · · df00tech

Ransomware Detection: TTPs, Indicators, and KQL Queries for 2026

ransomware LockBit BlackCat T1486 T1490 T1562.001 KQL SPL

By the time the ransom note appears it’s already over. The file encryption happens in minutes. The opportunity to detect ransomware is in the 24–72 hours before — the dwell time spent escalating, disabling EDR, and prepping shadow copies for deletion.

That pre-detonation window is where every good ransomware detection rule actually fires. The encryption event itself is the loudest possible signal and the one that matters least for response: by then your files are gone, your backups have already been targeted, and the attacker has been inside your environment for days or weeks. The rules that save data are the ones watching for the boring stuff — a vssadmin delete shadows, a Defender service stop, a strange sc config start= disabled against Veeam at 2am.

This guide walks through the 2026 ransomware kill chain as operators actually run it, maps each stage to MITRE ATT&CK, and gives you production KQL queries from the df00tech detection library that catch each phase.

1. The Ransomware Kill Chain in 2026

Ransomware in 2026 is not a malware problem. It’s a hands-on-keyboard intrusion problem. LockBit, BlackCat/ALPHV, Akira, BlackSuit, and Play affiliates all follow the same broad sequence:

  1. Initial access — usually via a patched-but-exposed edge device (Fortinet, Ivanti, Citrix NetScaler), a phished MFA bypass, or a legitimate VPN login on stolen creds from an infostealer log.
  2. Credential theft — LSASS dumping, SAM/SYSTEM hive extraction, DPAPI abuse. See T1003.001 for LSASS-focused detections. Without domain admin, most modern ransomware deployments stall.
  3. Lateral movement — SMB admin shares, RDP, PsExec, WMI. The T1021.001 detection covers the RDP angle specifically.
  4. Defense evasion — stopping EDR, disabling Defender, adding C:\ as an exclusion. This is T1562.001 and the rule set that most often fires first in a real incident.
  5. Recovery sabotage — shadow copy deletion, wbadmin delete catalog, bcdedit tampering. Covered by T1490.
  6. Service stop — backup agents, SQL, Exchange, anything holding file locks. T1489.
  7. Exfiltration — 2026 affiliates almost universally double-extort. Data leaves before encryption via rclone, MEGAsync, or custom tooling.
  8. EncryptionT1486. The loud event.

If you only watch for step 8, you’ve already lost. The queries below focus on steps 4–6 because that’s where you still have options.

2. Pre-Encryption Signals: Shadow Copy Deletion and Recovery Sabotage (T1490)

Shadow copy deletion is the single highest-fidelity ransomware precursor in existence. There are essentially no legitimate reasons for a domain workstation to run vssadmin delete shadows /all /quiet at 3am, and yet every major ransomware family — Ryuk, Black Basta, Medusa, LockBit, BlackCat, Akira, BlackSuit — does exactly that within seconds to minutes of detonation.

The full T1490 detection covers six distinct recovery-inhibition paths: vssadmin, wmic shadowcopy, diskshadow, wbadmin catalog deletion, bcdedit boot recovery tampering, and reagentc WinRE disabling. Here’s the production KQL:

let RecoveryInhibitPatterns = dynamic([
  "delete shadows", "delete catalog", "shadowcopy delete", "delete shadow",
  "recoveryenabled no", "bootstatuspolicy ignoreallfailures",
  "resize shadowstorage", "diskshadow",
  "reagentc"
]);
let ShadowDeleteBinaries = dynamic(["vssadmin.exe", "wmic.exe", "diskshadow.exe", "wbadmin.exe"]);
let BcdEditBinary = dynamic(["bcdedit.exe"]);
let ReagentBinary = dynamic(["reagentc.exe"]);
// VSS and backup catalog deletion
let ShadowDeletes = DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ (ShadowDeleteBinaries)
| where ProcessCommandLine has_any (RecoveryInhibitPatterns)
| extend TechniqueCategory = case(
    ProcessCommandLine has_any ("delete shadows", "delete shadow", "shadowcopy delete"), "VSS_Delete",
    ProcessCommandLine has "delete catalog", "BackupCatalog_Delete",
    ProcessCommandLine has "resize shadowstorage", "VSS_Resize",
    "Other"
  )
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
         InitiatingProcessFileName, InitiatingProcessCommandLine, TechniqueCategory;
// BCD boot recovery disable
let BcdDisable = DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ (BcdEditBinary)
| where ProcessCommandLine has_any ("recoveryenabled", "bootstatuspolicy", "safeboot")
| extend TechniqueCategory = "BCD_Recovery_Disable"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
         InitiatingProcessFileName, InitiatingProcessCommandLine, TechniqueCategory;
// WinRE disable via REAgentC
let WinREDisable = DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName =~ "reagentc.exe"
| where ProcessCommandLine has_any ("/disable", "-disable")
| extend TechniqueCategory = "WinRE_Disable"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine,
         InitiatingProcessFileName, InitiatingProcessCommandLine, TechniqueCategory;
ShadowDeletes
| union BcdDisable
| union WinREDisable
| sort by Timestamp desc

What this catches: Any recovery-inhibiting command across all six known paths. A single hit warrants triage. Two or more within five minutes from the same host is a confirmed pre-detonation sequence — isolate the endpoint immediately and do not wait for the encryption event.

Tuning: Allowlist legitimate backup software by parent process, not command pattern. VeeamAgent.exe, AcronisAgent.exe, beremote.exe, and BackupExec.exe are the big ones. Never exclude on command line alone — ransomware is perfectly capable of naming its process VeeamAgent.exe.

Ryuk-style operators specifically avoid the delete shadows command and instead run vssadmin resize shadowstorage /maxsize=401MB to force Windows to auto-discard existing snapshots. The query above catches that variant via the resize shadowstorage pattern.

3. EDR Tampering (T1562.001)

The canonical 2026 ransomware intrusion opens with defense evasion, not with payload delivery. Affiliates have a playbook: stop the Windows Defender service, add C:\ to the exclusion list, kill MsSense.exe, and — increasingly — drop a signed-but-vulnerable driver (BYOVD) to unhook the EDR from kernel mode.

The T1562.001 detection covers the process- and service-level techniques. Here’s the query, covering Defender, MDE, CrowdStrike, SentinelOne, Cylance, Carbon Black, and Tanium:

let SecurityProcesses = dynamic(["MsMpEng.exe", "MsSense.exe", "SenseCncProxy.exe", "SenseIR.exe", "SenseSampleUploader.exe", "SecurityHealthService.exe", "SecurityHealthSystray.exe", "csfalconservice.exe", "csfalconcontainer.exe", "CylanceSvc.exe", "cb.exe", "CbDefense.exe", "SentinelAgent.exe", "SentinelServiceHost.exe", "taniumclient.exe", "TmCCSF.exe", "coreServiceShell.exe"]);
let SecurityServices = dynamic(["WinDefend", "Sense", "MsMpSvc", "WdNisSvc", "SecurityHealthService", "wscsvc", "CrowdStrike", "CylanceSvc", "CbDefense", "SentinelAgent"]);
let SuspiciousActions = dynamic(["sc stop", "sc delete", "sc config", "net stop", "taskkill /f /im", "Set-MpPreference -DisableRealtimeMonitoring", "Set-MpPreference -DisableBehaviorMonitoring", "Set-MpPreference -DisableIOAVProtection", "Set-MpPreference -DisableScriptScanning", "Add-MpPreference -ExclusionPath", "Add-MpPreference -ExclusionProcess", "Set-MpPreference -DisableBlockAtFirstSeen", "DisableAntiSpyware", "SystemSettingsAdminFlows.exe"]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where ProcessCommandLine has_any (SuspiciousActions)
   or (FileName =~ "taskkill.exe" and ProcessCommandLine has_any (SecurityProcesses))
   or (FileName in~ ("sc.exe", "net.exe", "net1.exe") and ProcessCommandLine has_any (SecurityServices))
| extend TargetTool = case(
    ProcessCommandLine has_any ("WinDefend", "MsMpEng", "MsSense", "Sense", "Defender"), "Windows Defender/MDE",
    ProcessCommandLine has_any ("CrowdStrike", "csfalcon"), "CrowdStrike Falcon",
    ProcessCommandLine has_any ("Cylance"), "Cylance",
    ProcessCommandLine has_any ("Carbon", "CbDefense", "cb.exe"), "Carbon Black",
    ProcessCommandLine has_any ("Sentinel"), "SentinelOne",
    ProcessCommandLine has_any ("Tanium", "taniumclient"), "Tanium",
    ProcessCommandLine has_any ("ExclusionPath", "ExclusionProcess"), "Defender Exclusion",
    "Other/Unknown")
| extend ActionType2 = case(
    ProcessCommandLine has "taskkill", "Process Kill",
    ProcessCommandLine has "sc stop" or ProcessCommandLine has "net stop", "Service Stop",
    ProcessCommandLine has "sc delete", "Service Delete",
    ProcessCommandLine has "sc config", "Service Reconfigure",
    ProcessCommandLine has "MpPreference", "Defender Policy Change",
    ProcessCommandLine has "Exclusion", "Exclusion Added",
    "Other")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, TargetTool, ActionType2
| sort by Timestamp desc

What this catches: Service stops, process kills, Defender preference changes, and exclusion additions targeting any named EDR or AV. The TargetTool enrichment lets you triage immediately — a non-admin account dropping Add-MpPreference -ExclusionPath C:\ is an instant P1.

The uninstall angle: 2026 affiliates have increasingly shifted from killing the EDR to uninstalling it via the vendor’s own tooling (CsUninstallTool.exe, SentinelCtl.exe unload). Most of these require a site token, which is why credential theft of IT staff accounts is a specific LockBit and Akira objective. If you see the EDR vendor’s uninstaller running outside a change window, treat it the same as a sc stop.

4. Service Stop — The Backup and Database Kill List (T1489)

Before encryption starts, ransomware operators stop every service that could hold a file lock or provide a recovery path. The target list is remarkably consistent across families: VSS, wbengine, Veeam, Acronis, MSSQL, Exchange, MySQL, Oracle.

The T1489 detection uses a curated service list and a risk score that prioritizes security + backup + database targets:

let TargetedServices = dynamic([
  // Backup and recovery
  "vss", "VSS", "wbengine", "SDRSVC", "VeeamBackupSvc", "VeeamTransportSvc",
  "AcronisAgent", "BackupExecAgentAccelerator", "BackupExecAgentBrowser",
  "BackupExecDeviceMediaService", "BackupExecJobEngine", "BackupExecManagementService",
  "BackupExecRPCService", "SQLBackupMon",
  // Security / AV / EDR
  "WinDefend", "MsMpSvc", "SecurityHealthService", "Sense", "WdNisSvc",
  "CrowdStrike", "CSAgent", "CSFalconService", "McShield", "McTaskManager",
  "MfeEERM", "mfemms", "mfevtp", "SAVService", "SepMasterService",
  "Symantec", "SNAC", "TmCCSF", "SentinelAgent", "CarbonBlack",
  // Database and email
  "MSSQLSERVER", "MSSQL$", "SQLWriter", "SQLSERVERAGENT", "MsDtsServer",
  "ReportServer", "MSSQLFDLauncher", "MySQL", "OracleService",
  "MSExchangeIS", "MSExchangeTransport", "MSExchangeEdgeSync",
  "MSExchangeFDS", "MSExchangeMailboxAssistants", "MSExchangeRPC",
  "MSExchangeSA", "MSExchangeThrottling",
  // IT infrastructure
  "IISADMIN", "W3SVC", "WAS"
]);
DeviceProcessEvents
| where Timestamp > ago(24h)
| where FileName in~ ("sc.exe", "net.exe", "net1.exe", "taskkill.exe", "powershell.exe", "pwsh.exe", "wmic.exe")
| where ProcessCommandLine has_any (TargetedServices)
    or (
        (FileName in~ ("sc.exe") and ProcessCommandLine has_any ("stop", "config", "delete"))
        or (FileName in~ ("net.exe", "net1.exe") and ProcessCommandLine has "stop")
        or (FileName in~ ("taskkill.exe") and ProcessCommandLine has "/f")
        or (FileName in~ ("powershell.exe", "pwsh.exe") and ProcessCommandLine has_any ("Stop-Service", "Set-Service", "sc.exe stop", "sc stop"))
        or (FileName in~ ("wmic.exe") and ProcessCommandLine has_any ("service", "call", "stopservice", "ChangeStartMode"))
    )
| extend TargetsSecurityService = ProcessCommandLine has_any ("WinDefend", "MsMpSvc", "Sense", "CrowdStrike", "CSFalconService", "SentinelAgent", "CarbonBlack", "McShield", "SAVService", "SepMasterService", "WdNisSvc", "SecurityHealthService")
| extend TargetsBackupService = ProcessCommandLine has_any ("vss", "VSS", "wbengine", "VeeamBackupSvc", "SDRSVC", "BackupExec", "AcronisAgent", "SQLBackupMon")
| extend TargetsDatabaseService = ProcessCommandLine has_any ("MSSQLSERVER", "MySQL", "OracleService", "MSExchangeIS", "MSExchangeTransport", "SQLWriter")
| project Timestamp, DeviceName, AccountName, AccountDomain,
         FileName, ProcessCommandLine, InitiatingProcessFileName,
         InitiatingProcessCommandLine, InitiatingProcessParentFileName,
         TargetsSecurityService, TargetsBackupService, TargetsDatabaseService
| sort by Timestamp desc

What this catches: Stops, disables, and deletes against the high-value service list via sc, net, taskkill, PowerShell, or WMI. The three category flags (TargetsSecurityService, TargetsBackupService, TargetsDatabaseService) tell you at a glance what the operator is going after.

The bulk-stop pattern is the tell: Legitimate admin work stops one service for one reason. Ransomware stops 10–50 services in under two minutes. Run the companion hunting query from the T1489 detection page that bins stops into 5-minute windows with a threshold of >= 5 — it’s dramatically higher fidelity than single-service alerts.

5. The Encryption Event (T1486) — Last-Chance Detection

If pre-encryption detection fails, the T1486 query gives you one more swing. It correlates mass file renames to known ransomware extensions with shadow copy deletion on the same host, then scores the combination:

let TimeWindow = 1h;
let RenameThreshold = 50;
let ShadowDeleteCommands = dynamic(["vssadmin delete shadows", "vssadmin.exe delete shadows", "wmic shadowcopy delete", "bcdedit /set {default} recoveryenabled no", "bcdedit /set {default} bootstatuspolicy ignoreallfailures", "wbadmin delete catalog", "wbadmin delete systemstatebackup"]);
// Detection 1: Mass file rename/encryption activity
let MassRename = DeviceFileEvents
| where Timestamp > ago(TimeWindow)
| where ActionType in ("FileRenamed", "FileModified", "FileCreated")
| where FileName endswith_any (".encrypted", ".locked", ".crypt", ".enc", ".ransom", ".cry", ".lock64", ".cuba", ".avos", ".avos2", ".play", ".blackbyte")
| summarize
    RenamedFiles = count(),
    UniqueExtensions = dcount(FileName),
    FileTypes = make_set(tostring(split(FileName, ".")[-1]), 10),
    FirstSeen = min(Timestamp),
    LastSeen = max(Timestamp)
    by DeviceName, InitiatingProcessFileName, InitiatingProcessId, InitiatingProcessCommandLine
| where RenamedFiles > RenameThreshold;
// Detection 2: Shadow copy deletion and recovery sabotage
let ShadowDelete = DeviceProcessEvents
| where Timestamp > ago(TimeWindow)
| where ProcessCommandLine has_any (ShadowDeleteCommands)
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName;
// Combine both signals
MassRename
| join kind=leftouter (ShadowDelete) on DeviceName
| extend ShadowsDeleted = isnotempty(ProcessCommandLine)
| extend RansomwareConfidence = case(
    RenamedFiles > 500 and ShadowsDeleted, "critical",
    RenamedFiles > 200 or ShadowsDeleted, "high",
    RenamedFiles > RenameThreshold, "medium",
    "low")
| project FirstSeen, LastSeen, DeviceName, InitiatingProcessFileName, InitiatingProcessCommandLine, RenamedFiles, UniqueExtensions, FileTypes, ShadowsDeleted, RansomwareConfidence
| sort by RenamedFiles desc

What this catches: A single process producing more than 50 file renames to known ransomware extensions inside an hour, cross-referenced with shadow deletion. The extension list covers WannaCry, REvil, Maze, BlackCat, Babuk, Royal, Cuba, AvosLocker, Play, and BlackByte markers, and should be refreshed against your current threat feed.

The entropy angle the query doesn’t cover: Modern families (LockBit 5, BlackCat variants) often keep original extensions or use randomized ones. For those, you want a Sysmon + file-entropy correlation that’s outside the scope of native MDE telemetry — consider feeding FileCreate events through a Logic App that calls an entropy scorer on the first 4KB of the file. The high-entropy-write + shadow-delete combo fires even when the extension is randomized.

6. Actor-Specific Tells

Generic detections catch generic behavior. If you want to catch specific affiliates, tune to their signatures:

LockBit (3.0 / 4.0 / 5.0) — Uses bcdedit.exe /set {default} bootstatuspolicy ignoreallfailures in a paired command with recoveryenabled no. The two commands fire within milliseconds of each other from the same parent. LockBit 5 (2025+) builds bring a Linux/ESXi variant targeting .vmdk and .vmx files directly via vim-cmd vmsvc/power.off — hunt these in /var/log/shell.log and ESXi audit trails.

BlackCat / ALPHV — Rust-based. Spawns from a Rust runtime stub; parent process anomaly is your best bet since the binary name is typically randomized per-victim. Uses a configuration JSON embedded in the binary; PowerShell command lines with base64-encoded JSON arguments on the same host as VSS deletion is a high-fidelity ALPHV indicator.

Akira — Heavy RDP and VPN abuse for initial access (SonicWall, Cisco ASA). Uses net stop loops rather than sc stop. Specifically stops Veeam and Acronis services before encryption. Drops the ransom note akira_readme.txt — file-write monitoring for that exact filename is zero-false-positive.

BlackSuit (formerly Royal) — Aggressive ESXi targeting. Uses esxcli vm process kill --type=force to forcibly power off VMs before encrypting .vmdk files. On Windows, uses wmic shadowcopy delete rather than vssadmin — variant coverage for the WMIC path is essential against BlackSuit.

Play (Playcrypt) — Uses the .play extension (caught by the T1486 query above). Heavy use of AdFind and NetScan for reconnaissance immediately before encryption — a sudden burst of LDAP queries from a workstation paired with VSS deletion on the same host within 30 minutes is the Play kill chain in one sentence.

7. Containment Timeline and Escalation Criteria

When a pre-encryption rule fires, minutes matter. A reference timeline:

  • T+0 — Alert fires on shadow delete, EDR tamper, or bulk service stop. Auto-isolate the endpoint via EDR (Defender for Endpoint isolate-machine, CrowdStrike RTR network-contain). Do not wait for analyst review.
  • T+5 min — Scope other endpoints touched by the same parent process, user account, or source IP. If lateral movement is visible, isolate those too.
  • T+15 min — Identify the compromised account. Disable in AD, revoke Kerberos tickets, invalidate cloud SSO sessions. If a domain admin is involved, assume KRBTGT compromise and plan a reset.
  • T+30 min — Check backups. Shadow copies, offline/immutable backups, cloud backup agent status. If the attacker has reached backup infrastructure, recovery options collapse fast.
  • T+60 min — Hunt for the initial access vector. Edge device logs, VPN logs, phishing delivery, infostealer creds. If you don’t close the door, they come back.

Escalate to full IR immediately if any of these are true:

  • Shadow copy deletion from a non-backup-service parent process
  • Two or more recovery-inhibiting commands within five minutes on the same host
  • An EDR service successfully stopped (not just attempted)
  • Bulk service stop hitting security + backup + database categories together
  • Domain controller or certificate authority involved
  • Evidence of exfiltration in the 72 hours preceding the alert (double-extortion is the 2026 default — if data left before encryption, regulatory notification clocks are already ticking)

Ransomware detection is a time game. The pre-detonation phase is measured in hours to days. The encryption phase is measured in minutes. Build your rules to fire on the former, not the latter.

Browse the full df00tech detection library — 700+ KQL and SPL queries mapped to MITRE ATT&CK, free forever.