UAT-11587 Antino Backdoor: Microsoft 365 Dead-Drop C2 Hunt

Threat Overview

Cisco Talos reported on September 30, 2026 that the China-nexus cluster UAT-11587 used a previously undocumented Rust backdoor, Antino, against government and policy organizations across Asia. Talos identified roughly 350 compromised endpoints across eight countries and activity from September 2025 through July 2026. The recurring chain starts with tailored spear-phishing, a fake Gmail attachment widget, and a Cloudflare Pages link; HTA or WSF launches mshta.exe or Windows Script Host, retrieves encrypted JScript and .NET BinaryFormatter resources from Cloudflare R2 or CloudFront, loads TestAssembly.dll in memory, and launches Antino by sideloading slc.dll through the Microsoft-signed GatherOsState.exe.

Antino uses Microsoft Graph exclusively for native C2: login.microsoftonline.com for OAuth client-credentials authentication, Outlook messages with command_req_<session_id> and command_res_<session_id> subjects for commands/results, and OneDrive paths under /antino/heartbeats/, /antino_uploads/, and /antino_downloads/ for beaconing and file transfer. It supports command and PowerShell execution, file transfer, directory/process discovery, operator-supplied program execution, in-memory shellcode, and HKCU Run persistence. It can proxy PowerShell through sdiagnhost.exe and the Program Compatibility Wizard diagnostic package, creating result.ps1 under C:\Windows\Temp\SDIAG_<GUID>. This hunt treats Talos’s China-nexus attribution as a high-confidence researcher assessment; the infection chain, victim telemetry, malware behavior, and infrastructure are researcher-confirmed observations.

References

Impacted Systems

  • Platform: Microsoft Windows endpoints, 32-bit and 64-bit; government, policy, diplomatic, defense, research, civil-society, and national-security-adjacent environments were observed targets.
  • Delivery/exposure: A user receives and executes a tailored HTA/WSF or standalone fake installer reached through attacker-controlled or abused Cloudflare/Amazon infrastructure. No vulnerable product version is required.
  • Execution roles: mshta.exe/WSH, in-memory .NET deserialization, GatherOsState.exe DLL sideloading of slc.dll, and sdiagnhost.exe-mediated PowerShell.
  • Cloud dependency: Outbound HTTPS to Microsoft Graph and Microsoft identity endpoints; attacker-controlled Microsoft 365 resources serve as dead drops. Normal enterprise access to these services can mask C2.
  • Persistence/staging: %LOCALAPPDATA%\Windows GatherOSStateKit\, HKCU Run, and temporary C:\Windows\Temp\SDIAG_<GUID>\result.ps1.
  • Versions/fixes: This is a malware campaign, not a vendor CVE. No affected or fixed Windows/Microsoft 365 version applies.

Why this matters

The campaign produced confirmed compromises at material scale, uses a multi-stage Windows chain with signed-binary sideloading, and moves C2 into high-trust Microsoft 365 destinations. Those choices weaken domain-only controls and make process ancestry, file placement, Registry activity, and process-to-cloud correlation especially important for MSSP customers.

Exploitation Status

Confirmed campaign activity and endpoint compromise; not vulnerability exploitation. Talos observed activity from September 2025 through July 2026 and reported at least 10 confirmed and five probable affected institutional environments. Talos did not identify a software vulnerability as the initial-access requirement. Public reporting does not establish indiscriminate global distribution, and Microsoft Graph traffic alone is not evidence of Antino.

What this hunt looks for

HTA/WSF script-host delivery, GatherOsState execution from user-writable paths, sdiagnhost-mediated PowerShell, Antino staging paths, HKCU Run persistence, published delivery infrastructure, rare Microsoft Graph access, and Windows process-creation fallback activity.

Required logs

Microsoft Defender for Endpoint DeviceProcessEvents, DeviceFileEvents, DeviceRegistryEvents, and DeviceNetworkEvents; Microsoft 365 Defender email telemetry; and Windows Security Event 4688 with command-line auditing for fallback coverage.

Hunt 1 — HTA/WSF script hosts downloading or launching follow-on content

let lookback = 90d;
DeviceProcessEvents
| where Timestamp >= ago(lookback)
| where FileName in~ ("mshta.exe", "wscript.exe", "cscript.exe")
| extend Cmd = tolower(ProcessCommandLine)
| where Cmd has_any ("pages.dev", "r2.dev", "cloudfront.net", "http://", "https://") or InitiatingProcessFileName in~ ("outlook.exe", "chrome.exe", "msedge.exe", "firefox.exe")
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, SHA256
| order by Timestamp desc

Hunt 2 — GatherOsState execution from a user-writable directory

let lookback = 90d;
DeviceProcessEvents
| where Timestamp >= ago(lookback)
| where FileName =~ "GatherOsState.exe"
| where FolderPath has_any ("\\Users\\", "\\AppData\\", "\\Temp\\", "\\Downloads\\", "Windows GatherOSStateKit")
| project Timestamp, DeviceName, AccountName, FolderPath, ProcessCommandLine, SHA256, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Hunt 3 — Scripted Diagnostics host executing PowerShell

let lookback = 90d;
DeviceProcessEvents
| where Timestamp >= ago(lookback)
| where FileName in~ ("powershell.exe", "pwsh.exe")
| where InitiatingProcessFileName =~ "sdiagnhost.exe" or InitiatingProcessCommandLine has "sdiagnhost.exe"
| project Timestamp, DeviceName, AccountName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessFolderPath, InitiatingProcessCommandLine, SHA256
| order by Timestamp desc

Hunt 4 — Antino staging and diagnostic-script file creation

let lookback = 90d;
DeviceFileEvents
| where Timestamp >= ago(lookback)
| where FolderPath has_any ("Windows GatherOSStateKit", "\\Windows\\Temp\\SDIAG_") or FileName in~ ("slc.dll", "result.ps1", "OsGather.dat", "GatherOsState.exe")
| project Timestamp, DeviceName, ActionType, FolderPath, FileName, SHA256, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Hunt 5 — HKCU Run persistence created by the diagnostic or sideload chain

let lookback = 90d;
DeviceRegistryEvents
| where Timestamp >= ago(lookback)
| where RegistryKey has @"\Software\Microsoft\Windows\CurrentVersion\Run"
| where InitiatingProcessFileName in~ ("sdiagnhost.exe", "powershell.exe", "GatherOsState.exe") or RegistryValueData has "Windows GatherOSStateKit"
| project Timestamp, DeviceName, ActionType, RegistryKey, RegistryValueName, RegistryValueData, InitiatingProcessFileName, InitiatingProcessCommandLine
| order by Timestamp desc

Hunt 6 — Published and patterned Antino delivery infrastructure

let lookback = 90d;
let exactDomains = dynamic(["oisadjfoinsiduhfnoisdnfosdnoifnsoid.pages.dev", "d2nq35tel3ucuo.cloudfront.net", "d32tpl7xt7175h.cloudfront.net", "microsoft-flash.com", "wps-cn.com"]);
DeviceNetworkEvents
| where Timestamp >= ago(lookback)
| where RemoteUrl in~ (exactDomains) or RemoteUrl endswith ".r2.dev" or (RemoteUrl endswith ".pages.dev" and InitiatingProcessFileName in~ ("mshta.exe", "wscript.exe", "cscript.exe"))
| project Timestamp, DeviceName, InitiatingProcessAccountName, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort
| order by Timestamp desc

Hunt 7 — Rare Microsoft Graph access by non-browser, non-Office processes

let baseline = 30d;
let recent = 2d;
let known = DeviceNetworkEvents
| where Timestamp between (ago(baseline) .. ago(recent))
| where RemoteUrl in~ ("graph.microsoft.com", "login.microsoftonline.com")
| summarize by DeviceId, InitiatingProcessFileName;
DeviceNetworkEvents
| where Timestamp >= ago(recent)
| where RemoteUrl in~ ("graph.microsoft.com", "login.microsoftonline.com")
| where InitiatingProcessFileName !in~ ("msedge.exe", "chrome.exe", "firefox.exe", "outlook.exe", "onedrive.exe", "teams.exe")
| join kind=leftanti known on DeviceId, InitiatingProcessFileName
| summarize FirstSeen=min(Timestamp), LastSeen=max(Timestamp), Connections=count(), RemoteIPs=make_set(RemoteIP, 20), Commands=make_set(InitiatingProcessCommandLine, 10) by DeviceId, DeviceName, InitiatingProcessFileName
| order by LastSeen desc

Hunt 8 — Suspicious process followed by Microsoft Graph connectivity

let lookback = 90d;
let suspicious = DeviceProcessEvents
| where Timestamp >= ago(lookback)
| where FileName in~ ("GatherOsState.exe", "sdiagnhost.exe", "mshta.exe", "wscript.exe", "cscript.exe") or FolderPath has "Windows GatherOSStateKit"
| project DeviceId, ProcessId, ProcessTime=Timestamp, FileName, ProcessCommandLine;
DeviceNetworkEvents
| where Timestamp >= ago(lookback)
| where RemoteUrl in~ ("graph.microsoft.com", "login.microsoftonline.com")
| join kind=inner suspicious on DeviceId
| where Timestamp between (ProcessTime .. ProcessTime + 30m)
| project Timestamp, DeviceName, FileName, ProcessCommandLine, InitiatingProcessFileName, InitiatingProcessCommandLine, RemoteUrl, RemoteIP, RemotePort
| order by Timestamp desc

Hunt 9 — Windows process-creation fallback for Antino execution boundaries

let lookback = 90d;
SecurityEvent
| where TimeGenerated >= ago(lookback)
| where EventID == 4688
| extend NewProcess=tostring(NewProcessName), Parent=tostring(ParentProcessName), Cmd=tostring(CommandLine)
| where NewProcess endswith "\\GatherOsState.exe" or NewProcess endswith "\\sdiagnhost.exe" or (Parent endswith "\\sdiagnhost.exe" and NewProcess endswith "\\powershell.exe") or Cmd has_any ("Windows GatherOSStateKit", "\\Windows\\Temp\\SDIAG_", "slc.dll")
| project TimeGenerated, Computer, SubjectUserName, NewProcess, Parent, Cmd
| order by TimeGenerated desc

Detection Notes

  • Hunts 2–5 are the highest-signal behavior set: GatherOsState.exe in user-writable paths, sdiagnhost.exe launching PowerShell, the named staging paths, and Run-key creation are materially more specific than Microsoft Graph traffic.
  • GatherOsState.exe can be legitimate in Windows assessment workflows. Its directory, sibling files, parent process, signature, hash prevalence, and nearby network activity determine confidence.
  • Cloudflare Pages/R2, CloudFront, Microsoft Graph, and Microsoft identity endpoints are common legitimate services. Do not block or declare compromise on destination alone; require process or campaign-context correlation.
  • Hunt 7 is a first-seen heuristic and can surface legitimate custom Graph clients and management agents. Establish allowlists by signed binary, owner, application, and expected device group.
  • Standard M365 audit logs from the victim tenant generally cannot expose Outlook subjects or OneDrive paths in an attacker-controlled tenant. Endpoint HTTPS events also do not expose the Graph object names because TLS hides paths.
  • DeviceRegistryEvents and process ancestry require supported endpoint telemetry. SecurityEvent 4688 needs process creation auditing and command-line capture; otherwise Hunt 9 will be incomplete.