Executive Summary

The 24-hour threat window ending 2026-04-30 is dominated by two critical zero-day vulnerabilities under active exploitation — a Windows Shell NTLM coercion flaw (CVE-2026-32202) linked to APT28, and a Microsoft Defender local privilege escalation (CVE-2026-33825) — both now on CISA's Known Exploited Vulnerabilities catalog with federal patch deadlines. Nation-state activity remains elevated: APT28's FrostArmada DNS hijacking operation has been formally disrupted by US/UK agencies but residual infrastructure persists, while China-linked UAT-9244 continues telecom espionage in South America with a novel three-implant toolkit. On the criminal side, NightSpire ransomware is scaling aggressively with a new RaaS model, and a sophisticated PlugX delivery campaign exploiting brand trust (fake Anthropic/Claude installer) remains active.

Threat 1: CVE-2026-32202 — Windows Shell Zero-Day (CRITICAL)

Threat Actor: APT28 (Forest Blizzard / Fancy Bear — Russian GRU)
CVSS: 7.5 | Status: CISA KEV | Patch Deadline: 2026-05-12 (FCEB agencies)
Patch: KB5083769 (Windows 11 24H2/25H2 April Cumulative Update)

An incomplete fix for a related February 2026 vulnerability left a protection mechanism bypass in Windows Shell that enables zero-click NTLM credential coercion. Attackers distribute malicious .lnk files embedding UNC paths (e.g. \\attacker-host\share\payload.cpl). When the file is rendered by Explorer, Windows automatically initiates an outbound SMB handshake to the attacker-controlled server, transmitting the victim's Net-NTLMv2 hash without any user interaction beyond file preview. The stolen hash can be relayed for lateral movement or cracked offline for plaintext credentials.

APT28 exploited the predecessor vulnerability (CVE-2026-21510) against Ukraine and EU targets from January 2026, and is assessed with high confidence to be the primary exploiter of CVE-2026-32202 in current campaigns targeting government ministries and law enforcement agencies.

Key TTPs: T1187 Forced Authentication, T1557.001 SMB Relay, T1566.001 Spearphishing Attachment, T1078 Valid Accounts (post-relay)

Threat 2: CVE-2026-33825 — Microsoft Defender LPE Zero-Day (HIGH)

Threat Actor: Multiple (BlueHammer PoC public; RedSun and UnDefend exploit kits)
CVSS: 7.8 | Status: CISA KEV | Patch Deadline: 2026-05-06 (FCEB agencies)
Patch: Microsoft Defender Antimalware Platform 4.18.26050.3011

A time-of-check to time-of-use (TOCTOU) race condition in Windows Defender's threat remediation engine allows a local unprivileged attacker to achieve SYSTEM-level code execution. The exploit triggers a Defender detection using a crafted file, replaces it with a cloud placeholder via the Windows Cloud Files API, then uses NTFS junctions and opportunistic locks to redirect Defender's rollback write to C:\Windows\System32, overwriting a system binary with attacker-controlled content. No elevated privileges or user interaction required.

Exploitation began on 2026-04-10 with the BlueHammer public PoC; RedSun and UnDefend variants observed by 2026-04-16. This is being chained with initial access exploits to accelerate privilege escalation post-compromise.

Key TTPs: T1068 Exploitation for Privilege Escalation, T1574.010 Services File Permissions Weakness, T1036.005 Match Legitimate Name or Location

Threat 3: APT28 FrostArmada — SOHO Router DNS Hijacking Campaign (HIGH)

Threat Actor: APT28 / Forest Blizzard (Russian GRU Unit 26165)
Status: Joint FBI/NSA/DOJ/NCSC Advisory PSA260407 issued 2026-04-07; operation disrupted but residual infrastructure active
Geographic Scope: 120+ countries

Active since at least May 2025, this campaign compromised insecure MikroTik and TP-Link SOHO routers — exploiting CVE-2023-50224 (TP-Link WR841N authentication bypass) — and modified DNS resolver settings to point to attacker-controlled VPS infrastructure. At campaign peak (December 2025), 18,000+ unique device IPs communicated with APT28 DNS servers. When users queried targeted domains (primarily Microsoft 365 / government webmail), traffic was silently redirected to adversary-in-the-middle nodes where credentials were harvested.

Impact: 200+ organisations, 5,000+ consumer devices confirmed compromised; M365 OAuth tokens and credential material exfiltrated.

Key TTPs: T1584.008 Compromise Infrastructure: Network Devices, T1565.002 DNS Response Manipulation, T1040 Network Sniffing, T1557 Adversary-in-the-Middle

Threat 4: Fake Claude AI Installer — PlugX RAT Campaign (HIGH)

Threat Actor: Unattributed (tooling consistent with Chinese-linked operators)
Delivery: Typosquatted Anthropic website distributing trojanised ZIP
Status: Active; C2 infrastructure confirmed live

A sophisticated social engineering campaign distributes a malicious Windows installer (Claude-Pro-windows-x64.zip) via a fake Anthropic/Claude website. The installer employs a classic three-component DLL sideloading triad: a signed legitimate executable (NOVUpdate.exe), a trojanised DLL (avk.dll), and an encrypted payload blob (NOVUpdate.exe.dat). Upon execution, WScript.exe drops the components into C:\Program Files (x86)\Anthropic\Claude\Cluade\ (note the intentional directory name misspelling "Cluade") and adds them to the Startup folder for persistence. PlugX establishes a TCP connection to C2 at 8.217.190.58:443 within 22 seconds of execution.

Key TTPs: T1566.002 Phishing: Spearphishing Link, T1574.002 DLL Side-Loading, T1547.001 Startup Folder Persistence, T1071.001 Web Protocol C2, T1036.005 Masquerading

Threat 5: NightSpire Ransomware — Scaling RaaS Operations (HIGH)

Active Since: February 2025; significantly expanding in Q1-Q2 2026
Victim Count: 175 confirmed victims across 28 industries
Primary Targets: US (51% of victims), manufacturing, healthcare, professional services

NightSpire uses double-extortion: data exfiltration before encryption ensures leverage even against victims with strong backups. Initial access is primarily via exploitation of CVE-2024-55591 (FortiOS super-admin authentication bypass), supplemented by RDP brute-force, VPN credential stuffing, and MFA fatigue attacks. Post-compromise activity is heavily LOLBin-dependent: PowerShell, WMI, and PsExec for lateral movement; Mimikatz for credential dumping; WinSCP, MEGACmd, and Rclone for staged exfiltration. Ransomware payload is Go-based, appending .nspire extension with hybrid AES/RSA encryption. A readme.txt ransom note is dropped in each encrypted directory.

Key TTPs: T1190 Exploit Public-Facing Application, T1078 Valid Accounts, T1059.001 PowerShell, T1003.001 LSASS Memory, T1567.002 Exfiltration to Cloud Storage, T1486 Data Encrypted for Impact

Threat 6: UAT-9244 — Telecom Espionage Novel Implants (MEDIUM-HIGH)

Threat Actor: UAT-9244 (China-nexus; overlaps with FamousSparrow / Salt Typhoon)
Targeted Sectors: Telecommunications (South American providers)

Cisco Talos documented a sophisticated three-implant toolkit deployed against South American telcos:

Key TTPs: T1133 External Remote Services, T1095 Non-Application Layer Protocol (BitTorrent C2), T1584.005 Botnet/ORB Network, T1110.001 Brute Force

IOC Pack

Hash (SHA-256)FilenameThreat
35feef0e6806c14f4ccdb4fceff8a5757956c50fb5ec9644dedae665304f9f96Claude-Pro-windows-x64.zipPlugX Dropper ZIP
be153ac4db95db7520049a4c1e5182be07d27d2c11088a2d768e931b9a981c7fNOVUpdate.exePlugX Loader
d5590802bf0926ac30d8e31c0911439c35aead82bf17771cfd1f9a785a7bf143avk.dllPlugX Trojanised DLL
8ac88aeecd19d842729f000c6ab732261cb11dd15cdcbb2dd137dc768b2f12bcNOVUpdate.exe.datPlugX Encrypted Payload
IP AddressPortThreat
8.217.190.58443PlugX C2 — Alibaba Cloud ASN
CVEProductCVSSCISA KEVDeadline
CVE-2026-32202Windows Shell7.5YES2026-05-12
CVE-2026-33825Microsoft Defender7.8YES2026-05-06
CVE-2023-50224TP-Link WR841N8.8NOImmediate
CVE-2024-55591Fortinet FortiOS9.8YESPast due

KQL Hunting Queries

HUNT-01: LNK File Execution Triggering Outbound SMB (CVE-2026-32202)

// HUNT-01: LNK files triggering outbound SMB — potential CVE-2026-32202 NTLM coercion
let PrivateRanges = dynamic(["10.", "172.16.", "172.17.", "172.18.", "172.19.",
    "172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.", "172.26.",
    "172.27.", "172.28.", "172.29.", "172.30.", "172.31.", "192.168.", "127."]);
DeviceProcessEvents
| where TimeGenerated > ago(24h)
| where InitiatingProcessCommandLine contains ".lnk"
    or ProcessCommandLine contains ".lnk"
| where InitiatingProcessFileName in~ ("explorer.exe", "rundll32.exe", "cmd.exe")
| project DeviceId, DeviceName, LnkTime=TimeGenerated,
          LnkProcess=ProcessCommandLine, AccountName
| join kind=inner (
    DeviceNetworkEvents
    | where TimeGenerated > ago(24h)
    | where RemotePort == 445
    | where not(RemoteIP has_any (PrivateRanges))
    | project DeviceId, NetTime=TimeGenerated, RemoteIP, RemotePort,
              InitiatingProcessFileName
) on DeviceId
| where NetTime between (LnkTime .. (LnkTime + 30s))
| project LnkTime, NetTime, DeviceName, AccountName, RemoteIP,
          LnkProcess, InitiatingProcessFileName
| order by LnkTime desc

HUNT-02: Anomalous DNS Resolver Usage (FrostArmada Router Compromise)

// HUNT-02: Hosts querying non-standard external DNS resolvers
// FrostArmada indicator: compromised SOHO routers redirect DNS to APT28 VPS
let AuthorisedPublicDNS = dynamic([
    "8.8.8.8", "8.8.4.4",
    "1.1.1.1", "1.0.0.1",
    "9.9.9.9", "149.112.112.112",
    "208.67.222.222", "208.67.220.220"
]);
// Populate with your internal DNS server IPs
let InternalDNS = dynamic(["<YOUR_INTERNAL_DNS_1>", "<YOUR_INTERNAL_DNS_2>"]);
DeviceNetworkEvents
| where TimeGenerated > ago(24h)
| where RemotePort == 53
| where not(RemoteIP has_any (AuthorisedPublicDNS))
| where not(RemoteIP has_any (InternalDNS))
| where not(RemoteIP startswith "10."
    or RemoteIP startswith "192.168."
    or RemoteIP startswith "172.")
| summarize
    QueryCount = count(),
    UniqueDNS  = dcount(RemoteIP),
    DNS_IPs    = make_set(RemoteIP, 10),
    FirstSeen  = min(TimeGenerated),
    LastSeen   = max(TimeGenerated)
    by DeviceId, DeviceName, LocalIP
| where QueryCount > 5
| order by QueryCount desc

HUNT-03: NightSpire Precursor — Credential Dump + Exfil Tool Co-Occurrence

// HUNT-03: Credential dumping followed by known exfil tools on same host
let ExfilTools = dynamic([
    "WinSCP.exe", "MEGAcmd.exe", "rclone.exe", "Everything.exe"
]);
let CredDumpPatterns = dynamic([
    "sekurlsa", "lsadump", "mimikatz", "comsvcs.dll",
    "procdump", "lsass", "ntds.dit"
]);
DeviceProcessEvents
| where TimeGenerated > ago(24h)
| where ProcessCommandLine has_any (CredDumpPatterns)
    or (FileName =~ "rundll32.exe" and ProcessCommandLine contains "comsvcs.dll")
| project DeviceId, DeviceName, CredTime=TimeGenerated,
          CredCmd=ProcessCommandLine, AccountName
| join kind=inner (
    DeviceProcessEvents
    | where TimeGenerated > ago(24h)
    | where FileName has_any (ExfilTools)
        or ProcessCommandLine has_any (
            "rclone copy", "rclone sync", "megacmd", "winscp /log")
    | project DeviceId, ExfilTime=TimeGenerated,
              ExfilProcess=FileName, ExfilCmd=ProcessCommandLine
) on DeviceId
| where ExfilTime between ((CredTime - 4h) .. (CredTime + 8h))
| project CredTime, ExfilTime, DeviceName, AccountName,
          CredCmd, ExfilProcess, ExfilCmd
| order by CredTime desc

HUNT-04: Startup Folder Drops from Script Interpreters

// HUNT-04: Script interpreter dropping PE/DLL into Startup locations
// Covers PlugX delivery and general LOLBin persistence establishment
let ScriptHosts = dynamic([
    "wscript.exe", "cscript.exe", "mshta.exe",
    "powershell.exe", "pwsh.exe", "cmd.exe"
]);
let StartupPaths = dynamic([
    @"AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup",
    @"ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp"
]);
DeviceFileEvents
| where TimeGenerated > ago(24h)
| where ActionType in ("FileCreated", "FileModified")
| where FolderPath has_any (StartupPaths)
| where FileName endswith ".exe"
    or FileName endswith ".dll"
    or FileName endswith ".vbs"
| join kind=inner (
    DeviceProcessEvents
    | where TimeGenerated > ago(24h)
    | where FileName has_any (ScriptHosts)
    | project DeviceId, ScriptTime=TimeGenerated, ScriptCmd=ProcessCommandLine
) on DeviceId
| where TimeGenerated between ((ScriptTime - 60s) .. (ScriptTime + 60s))
| project TimeGenerated, DeviceName, FileName, FolderPath, ScriptCmd
| order by TimeGenerated desc

HUNT-05: NTLM Relay Lateral Movement Post-LNK

// HUNT-05: Network logons across multiple internal systems shortly after LNK activity
DeviceLogonEvents
| where TimeGenerated > ago(24h)
| where LogonType in ("Network", "3")
| where ActionType == "LogonSuccess"
| join kind=inner (
    DeviceProcessEvents
    | where TimeGenerated > ago(24h)
    | where InitiatingProcessCommandLine contains ".lnk"
        or ProcessCommandLine contains ".lnk"
    | summarize LnkTime=max(TimeGenerated) by DeviceId
) on DeviceId
| where TimeGenerated between (LnkTime .. (LnkTime + 30m))
| summarize
    UniqueTargets = dcount(DeviceName),
    Accounts      = make_set(AccountName, 5),
    FirstLogon    = min(TimeGenerated),
    LastLogon     = max(TimeGenerated)
    by DeviceId, bin(TimeGenerated, 15m)
| where UniqueTargets > 2
| order by UniqueTargets desc

KQL Detection Rules (High Fidelity)

DET-01: CVE-2026-32202 — LNK-Triggered NTLM Coercion to External SMB Host

Severity: High | MITRE: T1187, T1557.001 | FP Rate: Very Low

// DET-01: CVE-2026-32202 - LNK-initiated NTLM coercion to external SMB
let PrivateRanges = dynamic(["10.", "172.16.", "172.17.", "172.18.", "172.19.",
    "172.20.", "172.21.", "172.22.", "172.23.", "172.24.", "172.25.", "172.26.",
    "172.27.", "172.28.", "172.29.", "172.30.", "172.31.", "192.168.", "127.",
    "169.254."]);
let LNKEvents = DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where InitiatingProcessCommandLine contains ".lnk"
    or ProcessCommandLine contains ".lnk"
| where InitiatingProcessFileName in~ ("explorer.exe", "rundll32.exe")
| project DeviceId, DeviceName, AccountName, LnkTime=TimeGenerated,
          LnkCmd=ProcessCommandLine, InitProcess=InitiatingProcessFileName;
DeviceNetworkEvents
| where TimeGenerated > ago(1h)
| where RemotePort == 445
| where ActionType in ("ConnectionSuccess", "ConnectionRequest", "ConnectionAttempt")
| where not(RemoteIP has_any (PrivateRanges))
| join kind=inner LNKEvents on DeviceId
| where TimeGenerated between (LnkTime .. (LnkTime + 30s))
| project
    TimeGenerated,
    DeviceName,
    AccountName,
    RemoteIP,
    RemotePort,
    LnkCmd,
    InitProcess,
    TriggerWindow_Seconds = datetime_diff('second', TimeGenerated, LnkTime)
| extend
    AlertTitle    = "CVE-2026-32202 — LNK-Triggered Outbound SMB (NTLM Coercion)",
    AlertSeverity = "High",
    MITRE_TTP     = "T1187 / T1557.001",
    Remediation   = "Block outbound SMB (TCP 445) at perimeter. Apply KB5083769. Quarantine host."

DET-02: PlugX / Fake Claude Installer — IOC-Matched Components

Severity: Critical | MITRE: T1574.002, T1547.001, T1071.001 | FP Rate: Negligible

// DET-02: PlugX Fake Claude Installer - Hash, C2, and persistence directory detection
let PlugX_Hashes = dynamic([
    "35feef0e6806c14f4ccdb4fceff8a5757956c50fb5ec9644dedae665304f9f96",
    "be153ac4db95db7520049a4c1e5182be07d27d2c11088a2d768e931b9a981c7f",
    "d5590802bf0926ac30d8e31c0911439c35aead82bf17771cfd1f9a785a7bf143",
    "8ac88aeecd19d842729f000c6ab732261cb11dd15cdcbb2dd137dc768b2f12bc"
]);
let PlugX_C2_IPs = dynamic(["8.217.190.58"]);
let PlugX_PersistDir = @"Anthropic\Claude\Cluade";
// Branch 1: Hash Match
DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where SHA256 in~ (PlugX_Hashes)
| project TimeGenerated, DeviceName, AccountName, FileName, SHA256,
          FolderPath, ProcessCommandLine
| extend DetectionBranch = "FileHashMatch",
         AlertTitle      = "PlugX — Fake Claude Installer Component Hash Matched",
         AlertSeverity   = "Critical",
         MITRE_TTP       = "T1574.002"
| union (
    // Branch 2: C2 Connectivity
    DeviceNetworkEvents
    | where TimeGenerated > ago(1h)
    | where RemoteIP in (PlugX_C2_IPs) and RemotePort == 443
    | project TimeGenerated, DeviceName,
              AccountName    = InitiatingProcessAccountName,
              FileName       = InitiatingProcessFileName,
              FolderPath     = InitiatingProcessFolderPath,
              SHA256         = "",
              ProcessCommandLine = InitiatingProcessCommandLine
    | extend DetectionBranch = "C2Beacon",
             AlertTitle      = "PlugX C2 Beacon — 8.217.190.58:443 (Confirmed IOC)",
             AlertSeverity   = "Critical",
             MITRE_TTP       = "T1071.001"
)
| union (
    // Branch 3: Persistence Directory Artefact
    DeviceFileEvents
    | where TimeGenerated > ago(1h)
    | where FolderPath contains PlugX_PersistDir
    | project TimeGenerated, DeviceName, AccountName = "",
              FileName, FolderPath, SHA256 = "", ProcessCommandLine = ""
    | extend DetectionBranch = "PersistDirArtefact",
             AlertTitle      = "PlugX Persistence Directory — 'Cluade' Misspelling Detected",
             AlertSeverity   = "Critical",
             MITRE_TTP       = "T1547.001"
)
| project TimeGenerated, DeviceName, FileName, FolderPath, SHA256,
          ProcessCommandLine, DetectionBranch, AlertTitle, AlertSeverity, MITRE_TTP

DET-03: CVE-2026-33825 — Defender TOCTOU LPE (BlueHammer/RedSun Pattern)

Severity: Critical | MITRE: T1068, T1036.005 | FP Rate: Low

// DET-03: CVE-2026-33825 - Defender engine spawning shell + NTFS junction activity
let ShellProcesses = dynamic([
    "cmd.exe", "powershell.exe", "pwsh.exe", "wscript.exe",
    "mshta.exe", "regsvr32.exe", "msiexec.exe"
]);
let DefenderSpawns = DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where InitiatingProcessFileName =~ "MsMpEng.exe"
| where FileName has_any (ShellProcesses)
    or (FolderPath startswith @"C:\Windows\System32"
        and ActionType == "ProcessCreated"
        and not(FileName in~ (
            "MpCopyAccelerator.exe", "MpSigStub.exe", "MpCmdRun.exe")))
| project DeviceId, DeviceName, AccountName, SpawnTime=TimeGenerated,
          SpawnedProcess=FileName, SpawnCmd=ProcessCommandLine;
DeviceEvents
| where TimeGenerated > ago(1h)
| where ActionType in ("NtfsJunctionCreated", "FileOpLockSet", "ReparsePointCreated")
| join kind=inner DefenderSpawns on DeviceId
| where TimeGenerated between ((SpawnTime - 90s) .. (SpawnTime + 90s))
| project
    TimeGenerated, DeviceName, AccountName,
    SpawnedProcess, SpawnCmd, JunctionAction = ActionType, SpawnTime
| extend
    AlertTitle    = "CVE-2026-33825 — Suspected BlueHammer/RedSun Defender LPE",
    AlertSeverity = "Critical",
    MITRE_TTP     = "T1068 / T1036.005",
    Remediation   = "Update Defender to 4.18.26050.3011 immediately. Isolate host."

DET-04: NightSpire Ransomware — Active File Encryption

Severity: Critical | MITRE: T1486 | FP Rate: Very Low

// DET-04: NightSpire Ransomware - Active encryption in progress
DeviceFileEvents
| where TimeGenerated > ago(1h)
| where ActionType in ("FileCreated", "FileRenamed", "FileModified")
| where FileName endswith ".nspire" or FileName =~ "readme.txt"
| summarize
    NspireFiles   = countif(FileName endswith ".nspire"),
    ReadmeDrops   = countif(FileName =~ "readme.txt"),
    AffectedPaths = make_set(FolderPath, 20),
    FirstActivity = min(TimeGenerated),
    LastActivity  = max(TimeGenerated),
    UniqueParents = dcount(FolderPath)
    by DeviceId, DeviceName,
       InitiatingProcessFileName,
       InitiatingProcessCommandLine
| where NspireFiles >= 5
    or (NspireFiles >= 1 and ReadmeDrops >= 1)
    or (ReadmeDrops >= 10 and UniqueParents >= 5)
| extend
    AlertTitle    = "NightSpire Ransomware — Active File Encryption Detected",
    AlertSeverity = "Critical",
    MITRE_TTP     = "T1486",
    Remediation   = "IMMEDIATELY network-isolate host. Preserve memory. Activate IR plan. Check FortiGate for CVE-2024-55591."

DET-05: NightSpire Precursor — Credential Dump + Exfil Tool Combination

Severity: High | MITRE: T1003.001, T1567.002 | FP Rate: Low

// DET-05: NightSpire pre-ransomware activity - credential dump then data staging
let CredDumpIndicators = dynamic([
    "sekurlsa", "lsadump", "mimikatz", "procdump -ma lsass",
    "comsvcs.dll", "ntdsutil", "ntds.dit", "vssadmin"
]);
let ExfilBinaries = dynamic([
    "WinSCP.exe", "MEGAcmd.exe", "rclone.exe",
    "Everything.exe", "cloudfiles.exe"
]);
let CredDumps = DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where ProcessCommandLine has_any (CredDumpIndicators)
    or (FileName =~ "rundll32.exe" and ProcessCommandLine has "comsvcs.dll")
    or (FileName =~ "powershell.exe" and ProcessCommandLine has "lsass")
| project DeviceId, DeviceName, AccountName, CredTime=TimeGenerated,
          CredProcess=FileName, CredCmd=ProcessCommandLine;
DeviceProcessEvents
| where TimeGenerated > ago(1h)
| where FileName has_any (ExfilBinaries)
    or ProcessCommandLine has_any (
        "rclone copy", "rclone sync", "mega-put", "winscp.com /log")
| join kind=inner CredDumps on DeviceId
| where TimeGenerated between ((CredTime - 30m) .. (CredTime + 4h))
| project
    CredTime, ExfilTime = TimeGenerated, DeviceName, AccountName,
    CredProcess, CredCmd, ExfilProcess = FileName, ExfilCmd = ProcessCommandLine,
    Gap_Minutes = datetime_diff('minute', TimeGenerated, CredTime)
| extend
    AlertTitle    = "NightSpire Precursor — Credential Dump + Exfil Tool Detected",
    AlertSeverity = "High",
    MITRE_TTP     = "T1003.001 / T1567.002",
    Remediation   = "Isolate host. Rotate all credentials. Check FortiGate/VPN logs for CVE-2024-55591."

DET-06: APT28 FrostArmada — DNS Queries to Rogue External Resolver

Severity: High | MITRE: T1584.008, T1565.002 | FP Rate: Low

// DET-06: APT28 FrostArmada - sustained DNS to unauthorised external resolver
// REQUIRED: Replace <YOUR_INTERNAL_DNS_*> with your environment's DNS server IPs
let AuthorisedPublicDNS = dynamic([
    "8.8.8.8", "8.8.4.4",
    "1.1.1.1", "1.0.0.1",
    "9.9.9.9", "149.112.112.112",
    "208.67.222.222", "208.67.220.220"
]);
let InternalDNS = dynamic(["<YOUR_INTERNAL_DNS_1>", "<YOUR_INTERNAL_DNS_2>"]);
DeviceNetworkEvents
| where TimeGenerated > ago(1h)
| where RemotePort == 53
| where ActionType in ("ConnectionSuccess", "ConnectionRequest")
| where not(RemoteIP in (AuthorisedPublicDNS))
| where not(RemoteIP in (InternalDNS))
| where not(RemoteIP startswith "10."
    or RemoteIP startswith "192.168."
    or RemoteIP startswith "172.1"
    or RemoteIP startswith "172.2"
    or RemoteIP startswith "172.3"
    or RemoteIP == "127.0.0.1")
| summarize
    QueryCount = count(),
    UniqueDNS  = dcount(RemoteIP),
    DNS_IPs    = make_set(RemoteIP, 5),
    FirstSeen  = min(TimeGenerated),
    LastSeen   = max(TimeGenerated)
    by DeviceId, DeviceName, LocalIP
| where QueryCount >= 10 or UniqueDNS >= 3
| extend
    AlertTitle    = "APT28 FrostArmada — DNS to Unauthorised External Resolver",
    AlertSeverity = "High",
    MITRE_TTP     = "T1584.008 / T1565.002",
    Remediation   = "Audit SOHO/edge device DNS settings. Block outbound UDP/TCP 53 to non-authorised resolvers. Patch TP-Link WR841N (CVE-2023-50224)."

DET-07: Script Interpreter Dropping Executable to Startup Folder

Severity: High | MITRE: T1547.001, T1059.005 | FP Rate: Very Low

// DET-07: Script interpreter drops PE/DLL to Windows Startup — PlugX / malware persistence
let ScriptInterpreters = dynamic([
    "wscript.exe", "cscript.exe", "mshta.exe",
    "powershell.exe", "pwsh.exe"
]);
let StartupPaths = dynamic([
    @"Microsoft\Windows\Start Menu\Programs\Startup",
    @"Microsoft\Windows\Start Menu\Programs\StartUp"
]);
let ExecutableExts = dynamic([".exe", ".dll", ".bat", ".vbs", ".ps1", ".com"]);
DeviceFileEvents
| where TimeGenerated > ago(1h)
| where ActionType in ("FileCreated", "FileModified")
| where FolderPath has_any (StartupPaths)
| where FileName has_any (ExecutableExts)
| join kind=inner (
    DeviceProcessEvents
    | where TimeGenerated > ago(1h)
    | where FileName has_any (ScriptInterpreters)
    | project DeviceId, ScriptTime=TimeGenerated,
              ScriptName=FileName, ScriptCmd=ProcessCommandLine
) on DeviceId
| where TimeGenerated between ((ScriptTime - 10s) .. (ScriptTime + 120s))
| project
    TimeGenerated, DeviceName, DroppedFile = FileName, DropPath = FolderPath,
    ScriptName, ScriptCmd, Gap_Seconds = datetime_diff('second', TimeGenerated, ScriptTime)
| extend
    AlertTitle    = "Script Interpreter Dropped Executable to Startup — Malware Persistence",
    AlertSeverity = "High",
    MITRE_TTP     = "T1547.001 / T1059.005",
    Remediation   = "Quarantine host. Hash dropped file against PlugX IOCs (DET-02). Trace script origin."

Recommended Actions

Immediate (0-24 hours):

  1. Patch CVE-2026-33825 — Update Microsoft Defender Antimalware Platform to 4.18.26050.3011. FCEB deadline 2026-05-06.
  2. Patch CVE-2026-32202 — Deploy KB5083769 on all Windows 10/11 and Server systems. Compensating control: block outbound SMB (TCP 445) at the network perimeter immediately.
  3. Block PlugX IOCs — Add SHA-256 hashes and IP 8.217.190.58 to EDR/firewall blocklists. Alert on directory path containing Anthropic\Claude\Cluade.
  4. Deploy DET-01 through DET-07 in Sentinel as Scheduled Analytics Rules on 1-hour cadence.

Short-term (24-72 hours):

  1. Audit SOHO/edge device DNS settings — Verify all DNS resolvers on router and firewall appliances are authorised. Patch TP-Link WR841N firmware (CVE-2023-50224).
  2. Review FortiGate appliances for CVE-2024-55591 exploitation indicators (anomalous admin account creation, unexpected super-admin privilege changes).
  3. Run HUNT-01 through HUNT-05 retrospectively across a 7-day log window to surface undetected compromise.
  4. Validate Cisco SD-WAN Manager deployments against CVE-2026-20122, CVE-2026-20128, CVE-2026-20133 and apply vendor patches.

Sources: CISA KEV Alert Apr 28 | CVE-2026-32202 NVD | The Hacker News — CVE-2026-32202 | Akamai — Incomplete Patch Analysis | Picus Security — BlueHammer / RedSun | The Hacker News — Defender Zero-Days | The Hacker News — APT28 FrostArmada | NCSC Advisory | Malwarebytes — Fake Claude / PlugX | SecurityWeek — PlugX | Huntress — NightSpire | Cisco Talos — UAT-9244