DOUBLECUP — ClickFix Loader-as-a-Service
Executive Summary
DOUBLECUP is a Russian Loader-as-a-Service sold to ClickFix operators, assessed active since early June 2026 and documented by SOCRadar's Threat Research Unit on 2026-08-03. It is not a malware family. It is delivery infrastructure. Operators buy a license and a Go-based Windows GUI client, paste generated frontend code into their own lure pages, and DOUBLECUP handles the rest: hosting the steganographic PNG, session tracking, encryption keys and automatic stub rebuilds. Observed campaigns run through a cluster of fake CRM login pages impersonating NetSuite, Odoo, HubSpot and Salesforce, which inject the loader through embedded iframes.
The attacker objective is straightforward payload delivery at scale with minimal forensic residue. The chain is built so that almost nothing lands on disk in a form a scanner can judge. The payload arrives as an ordinary PNG in the browser cache, is located by exact file size and carved out with findstr or certutil, and the final stage is decrypted in memory using a custom SHA-256 stream cipher in CTR mode plus bitwise XOR, keyed on the victim's own public IPv4 address passed through PBKDF2. That last detail is the important one for defenders: a sample pulled into a sandbox or detonated from any other network derives the wrong key and simply fails to decrypt, so the payload is never revealed to an analyst.
Two final payloads have been observed. CountLoader 4.5p ships as fileless PowerShell for Windows and a cross-compiled Mach-O for macOS. Its notable new trick is process masquerading: it copies conhost.exe, powershell.exe and mshta.exe out of System32 into a user-writable directory, renames them after a harvested autostart application, and overwrites the UTF-16LE PE metadata fields (OriginalFilename, InternalName, FileDescription) so both name-based and header-based inspection are defeated. It persists through two redundant 25-minute scheduled tasks, audits browser extensions for crypto wallets, and profiles the host for Signal Desktop. DeviceManager is a previously undocumented modular Python RAT delivered as a Delphi-compiled Inno Setup installer that unpacks a full embedded Python runtime. It persists through scheduled tasks or WMI Event Subscriptions, resolves its live C2 from an Ethereum/Polygon smart contract via EtherHiding, and tunnels over DNS A and TXT records with a hardcoded microsoft.com apex appended so the traffic reads as ordinary Microsoft telemetry in a DNS log.
Highest-value defensive angle. Despite the sophistication of the packaging, the chain has two mandatory, unavoidable steps that no amount of operator-side obfuscation removes: a human pastes a command into the Run dialog, and a local shell then reads a file out of a browser cache directory. Both are cheap to detect and neither depends on an indicator the operator can rotate. Removing the Run dialog by policy and blocking the browser clipboard-write permission removes the delivery mechanism outright rather than detecting it after the fact.
Defender priority: treat the IP and domain list here as retro-hunt and blocklist material, not as the detection. DeviceManager resolves its C2 from a smart contract, so the operator rotates infrastructure by writing one blockchain transaction without redeploying a single implant. The durable coverage is Q1 (cache carve), Q2 (wildcard LOLBin), Q3 (renamed conhost) and Q5 (impostor task names). Deploy those first.
Source Review & Web Hunter Notes
| Tier | Source | Key finding | Carry forward |
|---|---|---|---|
| TIER 1 | SOCRadar Threat Research Unit, "Introducing DOUBLECUP", 2026-08-03 | Primary technical analysis. Full execution chain, CountLoader 4.5p and DeviceManager internals, complete network and host IOC tables, vendor ATT&CK mapping. | Yes |
| TIER 2 | The Hacker News, 2026-08-04 | Independent restatement of the SOCRadar report. Confirms the DeviceManager C2, the Telegram bot and the VS Code extension link. No original indicators. | Partial |
| TIER 2 | BleepingComputer, 2026-08-03 | Confirms the findstr/certutil carve, the macOS LaunchAgent persistence and the DNS A/TXT transport. Adds that the macOS build targets both Intel and Apple Silicon. | Partial |
| TIER 1 | Microsoft Learn, ASR rules reference | Authoritative GUIDs for the four ASR rules cited in Hardening, including "Block use of copied or impersonated system tools". | Yes (control citation) |
| TIER 2 | Chrome Enterprise policy list, DefaultClipboardSetting | Confirms value 2 blocks all sites from the clipboard site permission. Registry path not confirmed from a rendered page. | Partial (control citation) |
Collection notes
- Primary source access. The SOCRadar article returned HTTP 403 to the automated fetcher and then a bot-check interstitial. It was retrieved on a later attempt once the interstitial cleared on its own. No bot protection was bypassed or solved. All three threat-intel sources are snapshotted verbatim alongside this pack.
- Prompt-injection screen. Every fetched page was screened for text addressed to an automated agent (instructions to run commands, fetch further URLs for "the real IOCs", or claims of authorisation). None was found. No source was dropped.
- Date discrepancy. SOCRadar's own page is dated Aug 03, 2026 and BleepingComputer published the same day. The Hacker News carries Aug 04, 2026. Treated as a 2026-08-03 publication with next-day syndication. Nothing detection-relevant turns on this.
- Actor handle discrepancy. The primary names the operator Rognar with Telegram handle
@johnysilverhe(single n). The Hacker News renders itjohnnysilverhe(double n) as the VS Code marketplace publisher. Both spellings are recorded. Neither is a detection input, but if you pivot on the marketplace publisher, search both. - Deliberately not carried forward. The Web3 RPC endpoints DeviceManager contacts (Sepolia, Polygon and Ethereum mainnet public nodes) are named only by network in the source, not by provider hostname. No RPC provider domain is shipped as an indicator, because blocking a public RPC endpoint is both over-broad and unsupported by the source.
- Abused legitimate infrastructure. DeviceManager was staged on Seagate Lyve object storage. The full object URL ships as an indicator. The
seagate.comapex must not be blocked.
Hunt Brief & Attack Chain
Attack chain
| # | Step | Telemetry | Hunt angle |
|---|---|---|---|
| 1 | Victim lands on a fake CRM login page. An iframe loads DOUBLECUP frontend code, which fetches /api/config, registers a session and resolves the victim public IP via an actor-controlled echo host or a third-party API. | Proxy / web gateway logs, DnsRequest | Q14. DNS to the lure domains. Proxy hunt for the /api/config plus /session/reg URI pair. |
| 2 | The page force-caches a steganographic PNG (/stego-image.png?sid=...) and polls /session/check every 1.2 to 3 seconds until the server flags the image ready. | Proxy logs, browser cache artifacts | Native hunt N5. Cache entry of an anomalous fixed size written immediately before a shell launch. |
| 3 | A FakeCaptcha prompt copies a browser-matched command to the clipboard. The victim pastes it into the Run dialog. | RunMRU registry, ProcessRollup2 | Native hunt N1. Q1 catches the pasted command itself. |
| 4 | The command walks the browser cache for a file whose size matches exactly, then carves the embedded stage 1 out with findstr or certutil and pipes it into a wildcard-obfuscated PowerShell (pow?r?hell.exe). | ProcessRollup2 | Q1 and Q2. Highest-fidelity detections in this pack. |
| 5 | Stage 1 signals /session/signal and launches stage 2, a fileless JScript, VBScript or PowerShell dropper. | ScriptControlScanTelemetry, NetworkConnectIP4 | Script-block telemetry. Q13 for the infrastructure callback. |
| 6 | Stage 2 fetches the public IPv4 from an IP-echo service, derives a key with PBKDF2, decrypts the payload with a SHA-256 CTR stream cipher plus XOR, validates it against a hardcoded hash, then reflectively loads a .NET assembly in memory. | ProcessRollup2, DnsRequest | GAP No reliable endpoint signal for reflective load. Detect the surrounding behavior, not the decryption. |
| 7a | CountLoader 4.5p. Self-deletes, then copies conhost/powershell/mshta from System32 to a user-writable path, renames each after a harvested autostart binary, and patches the PE metadata fields. | ProcessRollup2, PeFileWritten | Q3. A process running with --headless that is not named conhost.exe. |
| 7b | CountLoader installs two 25-minute tasks: GoogleUpdateService<GUID> (pulls embeddable Python 3.13 and drops App.py) and MSEdgeUpdateService<GUID> (patched conhost running irm | iex). | ScheduledTaskRegistered, ProcessRollup2 | Q5, Q4, Q11. |
| 7c | CountLoader profiles wallets, browser extensions and Signal Desktop, then beacons over HTTP GET /connect?... with hex-encoded XOR telemetry and a JWT bearer token. | ProcessRollup2, NetworkConnectIP4 | Q10, Q13. |
| 7d | Operator tasks: rundll32 a downloaded DLL, silent MSI install, remote mshta, .lnk drops across all drives for USB spread, and scheduled-task cleanup to erase evidence. | ProcessRollup2 | Q12. ASR rules in Hardening block the USB and MSI paths. |
| 8a | DeviceManager. Inno Setup stager drops is-*.tmp and re-launches with /SL5=, then extracts an embedded Python runtime and run.pyw. | ProcessRollup2, PeFileWritten | Q16 (triage view), Q9. |
| 8b | Persists via schtasks /Create /F /TN MicroUpdaterV1 /XML %TEMP%\t.xml (XML deleted immediately) or, when configured, a WMI Event Subscription built through ctypes COM calls rather than wmic.exe. | ScheduledTaskRegistered, WMI-Activity log | Q5, Q6. Native hunt N3 for the WMI path, which has no clean Falcon event. |
| 8c | Checks GetUserDefaultUILanguage and self-deletes on CIS locales. Otherwise collects Machine GUID, volume serial, user SID, hostname, OS, architecture, AV and domain. | ProcessRollup2 | Partial Recon runs through ctypes and hidden PowerShell, so command-line visibility is limited. |
| 8d | Resolves the live C2 by eth_call to a smart contract, ChaCha20-decrypts the response, then tunnels over DNS A and TXT with a spoofed microsoft.com apex and 63-character label chunking. | DnsRequest, NetworkConnectIP4 | Q7, Q8, Q13. |
| 9 | macOS CountLoader. setup.sh stager drops a Mach-O for x86_64 and arm64, installs a LaunchAgent plist and profiles with sw_vers, system_profiler, ioreg and curl. | ProcessRollup2 (macOS) | Q15. Native hunt N6. |
Hunt hypotheses, ordered by fidelity
| ID | Hypothesis | MITRE | Falcon events | Expected FP source | Conf |
|---|---|---|---|---|---|
| H1 | A shell on a user endpoint reads a browser cache file selected by exact byte size and pipes the result into an interpreter. | T1204.004, T1027.003 | ProcessRollup2 | None known. No benign analogue. | HIGH |
| H2 | A command line resolves the PowerShell binary through a wildcard pattern rather than by name, to defeat string matching. | T1027, T1059.001 | ProcessRollup2 | Rare. Some admin one-liners use where with globs. | HIGH |
| H3 | A process not named conhost.exe is invoked with the conhost-specific --headless switch, indicating a renamed system binary. | T1036.003 | ProcessRollup2 | Windows Terminal, but always as conhost.exe. | HIGH |
| H4 | Scheduled tasks exist whose names imitate Google or Edge updater services but do not match the genuine task-naming convention. | T1053.005 | ScheduledTaskRegistered | None. Genuine tasks are GoogleUpdateTaskMachine* / MicrosoftEdgeUpdateTaskMachine*. | HIGH |
| H5 | Hosts emit DNS queries whose leading label is an operation prefix plus a hex device hash, consistent with a tunnelled C2 protocol. | T1071.004 | DnsRequest | Very low. The shape is specific. | HIGH |
| H6 | A PowerShell process combines an execution-policy bypass with a remote-fetch cmdlet and an in-memory evaluation cmdlet. | T1059.001, T1105 | ProcessRollup2 | Package managers, vendor bootstrap installers. | HIGH |
| H7 | A Python interpreter runs from a user-writable path with DeviceManager's specific entry-point script names. | T1059.006 | ProcessRollup2 | None. Names are family-specific. | HIGH |
| H8 | A host is beaconing to published DOUBLECUP or DeviceManager infrastructure. | T1071.001, T1102.001 | NetworkConnectIP4, DnsRequest | None. Dedicated actor infrastructure. | HIGH |
| H9 | A process enumerates crypto-wallet directories and Signal Desktop in a single burst, consistent with loader profiling. | T1518.001, T1083 | ProcessRollup2 | Low. Legitimate wallet use does not produce these as arguments. | MED |
| H10 | schtasks.exe registers a task from an XML file staged in a user-writable directory. | T1053.005 | ProcessRollup2 | Vendor installers and MDM agents do this legitimately. | MED |
| H11 | A single parent process invokes several macOS profiling utilities in quick succession outside a managed inventory cycle. | T1082, T1543.001 | ProcessRollup2 (macOS) | MDM, patch and inventory agents. | MED |
| H12 | Hosts with no blockchain workload emit DNS or TLS to public Web3 RPC nodes, indicating EtherHiding C2 resolution. | T1102.001 | DnsRequest, NetworkConnectIP4 | Developer and finance workstations. | LOW |
Unmappable chain steps (carried into the Coverage Map as gaps): the in-memory PBKDF2 key derivation and reflective .NET load at step 6 produce no distinct Falcon event. DeviceManager's WMI Event Subscription persistence at step 8b is built through direct ole32/oleaut32 COM calls precisely to avoid a wmic.exe or powershell.exe process ancestor, so process-lineage detection does not see it. Both are covered by native audit-log hunts and by preventive controls instead.
Consolidated IOC Table
All indicators below are drawn from the SOCRadar primary report and are traceable to the saved source snapshots shipped with this pack. Expiry follows the pack convention: detect plus six months, hunt plus three months.
Network
| Type | Value | Conf | Action | Context | Expiry |
|---|---|---|---|---|---|
| IPv4 | 213.139.77[.]109 | High | detect | DOUBLECUP license panel and the open directory that started the investigation. Port 9090. | 2026-11-05 |
| IPv4 | 91.92.240[.]100 | High | detect | DeviceManager C2, recovered by decrypting the latest smart-contract global-update transaction. Expect rotation. | 2026-11-05 |
| IPv4 | 67.219.107[.]181 | High | detect | Payload Builder host referenced by the operator Telegram bot callback URL. | 2026-11-05 |
| IPv4 | 80.96.109[.]229 | Medium | detect | Activity against the DOUBLECUP license panel. | 2026-11-05 |
| IPv4 | 167.148.201[.]131 | Medium | detect | Activity against the DOUBLECUP license panel. | 2026-11-05 |
| IPv4 | 89.124.117[.]12 | Medium | detect | Activity against the DOUBLECUP license panel. | 2026-11-05 |
| IPv4 | 103.22.137[.]227 | Medium | detect | DOUBLECUP server-side activity. | 2026-11-05 |
| IPv4 | 146.70.124[.]154 | Medium | detect | DOUBLECUP server-side activity. | 2026-11-05 |
| Domain | login-netsuite[.]com | High | detect | CRM-lure phishing page injecting DOUBLECUP. | 2026-11-05 |
| Domain | login-odoo[.]com | High | detect | CRM-lure phishing page injecting DOUBLECUP. | 2026-11-05 |
| Domain | login-salesforce[.]com | High | detect | CRM-lure phishing page injecting DOUBLECUP. | 2026-11-05 |
| Domain | verification-salesforce[.]com | High | detect | CRM-lure phishing page injecting DOUBLECUP. | 2026-11-05 |
| Domain | login-hubspot[.]com | High | detect | CRM-lure phishing page injecting DOUBLECUP. | 2026-11-05 |
| Domain | pending-verification[.]com | High | detect | CRM-lure phishing page injecting DOUBLECUP. | 2026-11-05 |
| Domain | doublecap[.]ltd | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | doublecap[.]live | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | canva-arts[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | cloudscraft[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | examcanvas[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | storagepioneer[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | supercloudsaver[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | ticgo-cloud[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | roqqcloud[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | cloud-electronic[.]com | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | cap[.]spec-connectweb3[.]tv | High | detect | Delivers DOUBLECUP. Part of a three-host lure cluster. | 2026-11-05 |
| Domain | cap-t1[.]spec-connectweb3[.]tv | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | cap-t2[.]spec-connectweb3[.]tv | High | detect | Delivers DOUBLECUP. | 2026-11-05 |
| Domain | nxtdrcliam[.]site | High | detect | Hosts a DOUBLECUP server component. | 2026-11-05 |
| Domain | srv641398444[.]host[.]ultaserver[.]net | High | detect | Hosts a DOUBLECUP server component. Block this FQDN only, not the hosting provider apex. | 2026-11-05 |
| Domain | alphastore[.]vg | High | detect | Delivers DOUBLECUP and serves as a CountLoader C2. | 2026-11-05 |
| Domain | appleid-customertelemetry[.]gl | High | detect | macOS CountLoader C2 and stager host. | 2026-11-05 |
| URL | hxxp[://]67[.]219[.]107[.]181/hgflssvslvidfugvbldiuv | High | detect | Payload Builder callback URL used by the operator Telegram bot. | 2026-11-05 |
| URL | hxxps[://]appleid-customertelemetry[.]gl/setup[.]sh | High | detect | Delivers the macOS CountLoader stager. | 2026-11-05 |
| URL | hxxps[://]appleid-customertelemetry[.]gl/AppleIDVerificationService | High | detect | Delivers the macOS CountLoader Mach-O. | 2026-11-05 |
| URL | hxxps[://]s3[.]us2[.]lyve[.]seagate[.]com/fullstack09/MicroUpdaterV1[.]exe | High | hunt | DeviceManager delivery staged on abused Seagate Lyve object storage. Block the full object path only. Blocking the seagate.com apex will break legitimate storage traffic. | 2026-11-05 |
Blockchain (EtherHiding)
| Type | Value | Conf | Action | Context | Expiry |
|---|---|---|---|---|---|
| Smart contract | 0xc027490AF56a9d7050fc259Ecd03DA1580b84aae | High | pivot | DeviceManager C2 resolver contract. Not importable into Falcon. Monitor externally for new write transactions to get the next C2 before it is used. | 2026-09-05 |
| Ethereum address | 0xCE17b1EF00d47105Bc127BbE6fC45dE47BC22fb8 | High | pivot | Operator address that writes C2 updates to the contract. | 2026-09-05 |
| Function selector | 0x1dcf296b | High | enrich | Contract read function DeviceManager calls with its device_hash to fetch a per-victim C2. | 2026-09-05 |
| Function selector | 0xc474520d | High | enrich | Global C2 update. A transaction calling this selector means the whole botnet is being re-pointed. | 2026-09-05 |
| Function selector | 0x71c28139 | High | enrich | Targeted C2 assignment to a specific infected device. | 2026-09-05 |
File hashes (SHA-256)
| Hash | Conf | Action | Context |
|---|---|---|---|
| 882914f9014f14e89123e835f103ac8f9d4b2e358c1f21c1cbc7f1054e6afed6 | High | prevent | DOUBLECUP Go client (operator tooling) |
| 8585721cbc46780903bd727e37a9ed07a33463852046ff65bc718ded4c80dfb1 | High | prevent | DOUBLECUP Go client (operator tooling) |
| 28cbbca8099bb1b27668d135314842c69ceb478a7d6b4b08f063d106a06c8f9d | High | detect | DOUBLECUP stage 2, the steganographic PNG |
| 6e08cb5602f63bee2b40739167b4aef77763bc8fb47b4839ca2fc1607ad35cba | High | prevent | MicroUpdaterV1.exe, DeviceManager Inno Setup stager |
| ea70895620f955b0712b85c3fee41de7437d5068267966f0b4fb6fa2704c3a50 | High | prevent | run.pyw, DeviceManager RAT core |
| bdf28e611d77362c40a0445655a35943c03accf21bb9a5af755da7eac5ea5e40 | High | prevent | CountLoader |
| afe273533d6f9d0b8852988f6a4b34571dd52af4c690e54723a86257aa8a015d | High | prevent | setup.sh, stager for macOS CountLoader |
| 08730fda7366104b1461b12834f55723381bf34a234947689c708b1ee431af69 | High | prevent | AppleIDVerificationService, macOS CountLoader |
Host artifacts
| Type | Value | Family | Note |
|---|---|---|---|
| Task name | MicroUpdaterV1 | DeviceManager | Primary persistence, fires every 10 minutes. |
| Task name | PythonAppUpdater | DeviceManager | Fallback task name. |
| Task name | GoogleUpdateService<GUID> | CountLoader | Primary task, every 25 minutes, WakeToRun enabled. |
| Task name | MSEdgeUpdateService<GUID> | CountLoader | Fallback task, every 25 minutes. |
| Task name | DOUBLECUP | DOUBLECUP client | Operator-side tooling, not victim-side. |
| WMI filter | PythonAppUpdateFilter | DeviceManager | Bound to __IntervalTimerInstruction PythonAppTimer_600. |
| WMI consumer | PythonAppUpdateConsumer | DeviceManager | CommandLineEventConsumer running pythonw plus the agent script. |
| File path | %LOCALAPPDATA%\DeviceManager\config.json | DeviceManager | Serialized AgentConfig, contains contract address and blockchain key. |
| File path | %LOCALAPPDATA%\DeviceManager\agent.log | DeviceManager | Rotating log. Highest-value forensic artifact on a live host. |
| File path | %LOCALAPPDATA%\DeviceManager\agent_main.pyw | DeviceManager | Hidden Python entry point. |
| File path | %TEMP%\t.xml | DeviceManager | Scheduled-task XML, deleted immediately after task creation. |
| File path | %TEMP%\_dm_task.py | DeviceManager | In-memory Python task wrapper, deleted after execution. |
| File path | %USERPROFILE%\App_<GUID>.py | CountLoader | PowerShell process-masquerading helper. |
| Campaign key | K94DGQ99VYCCH52TKOT2 | CountLoader | Hardcoded campaign tracking token sent in the C2 beacon. |
Affected Surface & Telemetry Matrix
DOUBLECUP itself is browser-resident and platform-agnostic. The payloads split by operating system: CountLoader covers Windows and macOS, DeviceManager is Windows only. Nothing in this chain requires local administrator rights, so a standard user endpoint is fully sufficient for the attacker.
| Surface | Exposure | Required telemetry | Priority | Gap risk if missing |
|---|---|---|---|---|
| Windows workstations (all users) | Full chain. Delivery, both loaders and all persistence. | ProcessRollup2, SyntheticProcessRollup2, ScheduledTaskRegistered, DnsRequest, NetworkConnectIP4 | CRITICAL | Total. Without process command lines, Q1 through Q6 and Q9 through Q12 all go blind. |
| macOS workstations | CountLoader Mach-O for Intel and Apple Silicon, LaunchAgent persistence. | ProcessRollup2 (macOS), NetworkConnectIP4 | HIGH | Q15 unavailable. macOS is frequently under-instrumented relative to Windows, so confirm sensor coverage rather than assuming it. |
| Web proxy / secure web gateway | Lure pages, /api/config, /session/reg, /session/check, /session/signal, stego PNG fetch. | Full URI logging with query strings, not just hostnames | HIGH | Loses the earliest possible detection point. Hostname-only logging cannot see the DOUBLECUP URI pattern. |
| DNS resolver / DNS firewall | DeviceManager tunnelling, lure-domain resolution. | Per-client query logs including record type and full QNAME | CRITICAL | Q7 and Q8 are unavailable. If endpoints bypass internal resolvers, DNS tunnelling is invisible everywhere. |
| Browser fleet (Chrome, Edge, Firefox, Brave, Opera) | Clipboard-write API is the delivery vector. Cache directory is the payload store. | Browser enterprise policy state, extension inventory | HIGH | Loses the single most effective preventive control (clipboard policy). |
| Crypto-wallet and Signal Desktop users | Explicit CountLoader collection targets. | Software inventory | MEDIUM | Cannot prioritise which infections carry the highest data-loss impact. |
| Removable media | CountLoader command 9 drops .lnk files across all drives for USB spread. | Removable-device telemetry, IsOnRemovableDisk | MEDIUM | Lateral spread to air-gapped or partner systems goes unnoticed. |
| Developer and finance endpoints | Legitimate Web3 traffic here masks EtherHiding C2 resolution. | NetworkConnectIP4, DnsRequest | MEDIUM | H12 is only viable where a clean baseline of who legitimately talks to RPC nodes exists. |
| WMI subsystem | DeviceManager alternate persistence via __FilterToConsumerBinding. | Microsoft-Windows-WMI-Activity/Operational (EID 5859, 5860, 5861) | HIGH | GAP This channel is created through direct COM calls and has no clean Falcon process event. The Windows log is the only reliable source. |
ATT&CK Mapping
Mapping as published by the vendor, with the covering query or control from this pack added to each row.
| Tactic | ID | Technique | Observed behavior | Covered by |
|---|---|---|---|---|
| Execution | T1204.004 | User Execution: Malicious Copy and Paste | DOUBLECUP is injected into ClickFix pages that copy a command to the victim clipboard. | Q1, HRD-1, HRD-2 |
| Execution | T1059.001 | Command and Scripting Interpreter: PowerShell | Used to carve and run the cached PNG payload. CountLoader is pure PowerShell. DeviceManager pipes payloads into powershell.exe over STDIN. | Q2, Q4, HRD-5 |
| Execution | T1059.006 | Command and Scripting Interpreter: Python | CountLoader drops App.py for masquerading. DeviceManager is a Python RAT with an embedded runtime. | Q9, Q11 |
| Execution | T1059.003 | Command and Scripting Interpreter: Windows Command Shell | cmd.exe searches and executes the cached PNG. DeviceManager pipes commands into cmd.exe /Q /K. | Q1, Q3 |
| Execution | T1059.004 | Command and Scripting Interpreter: Unix Shell | Mach-O CountLoader shells out to native Unix commands such as ioreg. | Q15 |
| Execution | T1047 | Windows Management Instrumentation | Both loaders query Win32_Processor, Win32_ComputerSystemProduct and Win32_DiskDrive for host fingerprinting. | Native N3, HRD-4 |
| Execution | T1106 | Native API | DeviceManager uses Python ctypes to call kernel32.GetVolumeInformationW and related APIs directly. | GAP Prevention only |
| Persistence | T1053.005 | Scheduled Task/Job: Scheduled Task | DeviceManager creates MicroUpdaterV1 and PythonAppUpdater. CountLoader creates GoogleUpdateService and MSEdgeUpdateService tasks. | Q5, Q6, Native N4 |
| Persistence | T1547.009 | Boot or Logon Autostart Execution: Shortcut Modification | CountLoader can rewrite browser .lnk targets to launch the browser and the RAT together. Dead code in the analysed sample. | Native N7 |
| Persistence | T1546.003 | Event Triggered Execution: WMI Event Subscription | DeviceManager can provision PythonAppUpdateFilter and PythonAppUpdateConsumer in root\subscription through COM. | Native N3, HRD-4 GAP in EDR |
| Persistence | T1543.001 | Create or Modify System Process: Launch Agent | Mach-O CountLoader writes a .plist into ~/Library/LaunchAgents and calls launchctl load. | Q15, Native N6 |
| Defense Evasion | T1620 | Reflective Code Loading | Stage 2 reflectively loads the decrypted .NET assembly directly into process memory. | GAP Detect surrounding behavior |
| Defense Evasion | T1027 | Obfuscated Files or Information | PowerShell execution is obfuscated with wildcards (pow?r?hell.exe). Stage 2 uses XOR string obfuscation with key 210. | Q2, HRD-6 |
| Defense Evasion | T1480.001 | Execution Guardrails: Environmental Keying | The victim public IPv4 is the PBKDF2 seed for the payload decryption key, so the payload will not unpack elsewhere. | GAP Anti-analysis, not detectable on-host |
| Defense Evasion | T1140 | Deobfuscate/Decode Files or Information | CountLoader hex-decodes and XOR-decrypts the JSON task payload from its C2. | Q4 |
| Defense Evasion | T1027.003 | Obfuscated Files or Information: Steganography | Malicious code is hidden inside a PNG staged in the browser cache. | Q1, Native N5 |
| Defense Evasion | T1036.003 | Masquerading: Rename Legitimate Utilities | CountLoader copies, renames and PE-header-patches conhost.exe, powershell.exe and mshta.exe. | Q3, HRD-3 |
| Defense Evasion | T1218.005 | System Binary Proxy Execution: Mshta | CountLoader command 10 runs mshta.exe against an operator-supplied remote URL. | Q12, HRD-6 |
| Discovery | T1082 | System Information Discovery | Both loaders collect OS version, architecture and machine GUID. | Q10, Q15 |
| Discovery | T1033 | System Owner/User Discovery | DeviceManager retrieves the active username through getpass or %USERNAME%. | Partial |
| Discovery | T1012 | Query Registry | DeviceManager reads the Cryptography MachineGuid value. | Partial |
| Discovery | T1016 | System Network Configuration Discovery | Public IP is resolved through actor-controlled echo hosts or third-party APIs such as ip-api.com. | Proxy hunt |
| Discovery | T1083 | File and Directory Discovery | Browser cache directories are searched for a PNG of an exact byte size. CountLoader enumerates wallet and application paths. | Q1, Q10 |
| Discovery | T1069.001 | Permission Groups Discovery: Local Groups | CountLoader tests for admin rights through a WMI StdRegProv read and flags the result with an asterisk. | Partial |
| Discovery | T1518.001 | Software Discovery: Security Software Discovery | Both loaders enumerate installed AV through root\SecurityCenter2. | Q10 |
| Command and Control | T1573.001 | Encrypted Channel: Symmetric Cryptography | CountLoader XOR-encrypts and hex-encodes its C2 traffic with a random six-digit key prepended to the payload. | Q13 |
| Command and Control | T1105 | Ingress Tool Transfer | All three components can pull further payloads. | Q4, Q11, Q12 |
| Command and Control | T1102.001 | Web Service: Dead Drop Resolver | DeviceManager resolves its C2 from an Ethereum/Polygon smart contract (EtherHiding). | H12, HRD-8 Partial |
| Command and Control | T1071.004 | Application Layer Protocol: DNS | DeviceManager tunnels over raw UDP DNS using A and TXT records with 63-character label chunking. | Q7, Q8, HRD-7 |
| Command and Control | T1071.001 | Application Layer Protocol: Web Protocols | DOUBLECUP session endpoints over HTTP GET. CountLoader and DeviceManager both implement HTTP POST C2. | Q13, Q14 |
Native Audit-Log Hunts
These cover the parts of the chain that Falcon telemetry sees poorly or not at all. Run them alongside the CQL section, not instead of it.
N1. Run dialog history (the ClickFix paste itself)
The Run dialog records what the user typed. This is the single highest-value forensic artifact for confirming a ClickFix infection, and it survives the malware self-deleting.
Registry: HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU
Look for values containing any of:
findstr certutil %~z
-NoP -W Hidden -EP B -C - (the DOUBLECUP stage-1 PowerShell switch cluster)
"User Data" AppData\Local f_
Collect fleet-wide:
Get-ChildItem 'HKU:\' | ForEach-Object {
$p = "$($_.PSPath)\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU"
if (Test-Path $p) { Get-ItemProperty $p }
}
N2. PowerShell script-block logging (EID 4104)
Stage 2 and CountLoader are fileless. Script-block logging is the only place their decrypted bodies are ever written down. If 4104 is not enabled, see HRD-5 in Hardening, then re-run this hunt once logs accumulate.
Log: Microsoft-Windows-PowerShell/Operational, Event ID 4104 Search decoded ScriptBlockText for: FromBase64String System.Reflection.Assembly -bxor PBKDF2 / Rfc2898DeriveBytes Schedule.Service GoogleUpdateService MSEdgeUpdateService approveUpdate getUpdates Ledger Live BitBox02 KeepKey irm iex Note: CountLoader 4.5p deliberately avoids ConvertFrom-Json and uses a regex JSON parser to stay under AMSI heuristics, so do NOT rely on ConvertFrom-Json as a marker.
N3. WMI Event Subscription persistence (the EDR gap)
DeviceManager builds this through direct ole32 and oleaut32 COM calls rather than wmic.exe or PowerShell, specifically so that process-lineage detections do not fire. The WMI operational log and a direct namespace query are the reliable checks.
Log: Microsoft-Windows-WMI-Activity/Operational, Event ID 5861
(also 5859 and 5860 for consumer and filter registration)
Direct namespace audit, run fleet-wide and diff against a known-good baseline:
Get-WmiObject -Namespace root\subscription -Class __EventFilter
Get-WmiObject -Namespace root\subscription -Class CommandLineEventConsumer
Get-WmiObject -Namespace root\subscription -Class __FilterToConsumerBinding
Get-WmiObject -Namespace root\subscription -Class __IntervalTimerInstruction
DOUBLECUP-specific names to alert on:
__EventFilter PythonAppUpdateFilter
CommandLineEventConsumer PythonAppUpdateConsumer
__IntervalTimerInstruction PythonAppTimer_600 (600000 ms interval)
Any CommandLineEventConsumer whose CommandLineTemplate references pythonw.exe or a
path under %LOCALAPPDATA% warrants investigation regardless of its name.
N4. Scheduled task audit (EID 4698 and on-disk XML)
Log: Security, Event ID 4698 (task created), 4702 (task updated)
Requires "Audit Other Object Access Events" to be enabled. See HRD-9.
On-disk task definitions:
C:\Windows\System32\Tasks\
Alert on task names matching:
GoogleUpdateService* MSEdgeUpdateService* MicroUpdaterV1 PythonAppUpdater
These are impostors. The genuine vendor tasks are named:
GoogleUpdateTaskMachineCore / GoogleUpdateTaskMachineUA
MicrosoftEdgeUpdateTaskMachineCore / MicrosoftEdgeUpdateTaskMachineUA
so a substring match on "GoogleUpdate" alone will produce noise. Match the full prefix.
Also flag any task whose action runs a binary from %USERPROFILE% or %LOCALAPPDATA%,
or whose settings combine WakeToRun with a repetition interval under 30 minutes.
N5. Browser cache carve artifacts
Cache locations (per browser profile): Chrome %LOCALAPPDATA%\Google\Chrome\User Data\Default\Cache\Cache_Data\ Edge %LOCALAPPDATA%\Microsoft\Edge\User Data\Default\Cache\Cache_Data\ Brave %LOCALAPPDATA%\BraveSoftware\Brave-Browser\User Data\Default\Cache\Cache_Data\ Opera %APPDATA%\Opera Software\Opera Stable\Cache\ Firefox %LOCALAPPDATA%\Mozilla\Firefox\Profiles\<profile>\cache2\entries\ Chromium cache entries are named f_XXXXXX. The DOUBLECUP command locates the payload by EXACT byte size, so the hunt is: any f_* entry whose size matches across multiple unrelated hosts is a staged payload, not organic browsing. Triage: carve any f_* entry written within 120 seconds of a cmd.exe or powershell.exe start on the same host, and check for a PNG header followed by a large ASCII region. The reference sample used a marker string of ZZ1984 as the findstr needle.
N6. macOS LaunchAgent audit
Persistence path: ~/Library/LaunchAgents/*.plist Audit: ls -la ~/Library/LaunchAgents/ /Library/LaunchAgents/ launchctl list Flag any plist whose ProgramArguments reference a binary in ~/Library, /tmp, /var/folders or the user Downloads directory, or any plist with no matching installed application. Cross-check against your MDM's approved LaunchAgent inventory. Supporting reconnaissance commands used by the Mach-O build: /usr/bin/sw_vers -productVersion system_profiler SPHardwareDataType ioreg -rd1 -c IOPlatformExpertDevice /usr/bin/curl (HTTP POST and binary retrieval)
N7. Browser shortcut integrity
The .lnk rewrite capability is present but never invoked in the analysed sample, so treat this as a low-yield check that costs almost nothing to run. It becomes important if the operator ships a build where the function is wired up.
Scan the desktop and Start Menu for browser shortcuts whose target is not the
browser executable:
Get-ChildItem "$env:USERPROFILE\Desktop","$env:APPDATA\Microsoft\Windows\Start Menu" `
-Filter *.lnk -Recurse | ForEach-Object {
$sc = (New-Object -ComObject WScript.Shell).CreateShortcut($_.FullName)
[pscustomobject]@{ Link = $_.FullName; Target = $sc.TargetPath; Args = $sc.Arguments }
} | Where-Object { $_.Target -match 'conhost|cmd\.exe' -or $_.Arguments -match 'start ' }
The documented hijack rewrites the target to conhost.exe --headless cmd.exe /c start,
launching the real browser and the payload together.
N8. Web gateway hunt for the DOUBLECUP session protocol
The loader's server-side protocol is consistent across campaigns regardless of the lure domain, which makes it a durable proxy-log hunt: URI path ends with /api/config (campaign configuration fetch) URI path contains /session/reg (session registration) URI path contains /session/check (readiness and completion polling, 1.2 to 3s) URI path contains /session/signal (infection confirmation) URI path contains /stego-image.png?sid= Highest-fidelity composite: the same client hitting /api/config and then polling a /session/check endpoint on the same host more than 10 times inside 60 seconds. That polling cadence is the loader waiting for the stego image to be ready and has no benign equivalent.
CrowdStrike LogScale CQL Hunt Queries
On time windows. None of these queries carry an in-query timeframe filter. In CQL the right side of a comparison must be a literal, so @timestamp >= (now() - 7d) does not parse and silently breaks every query it leads. Set the window in the Falcon console instead. Last 7 days is a sensible default for the behavioral queries and Last 30 days for the infrastructure ones.
Looks for: the pasted ClickFix command itself. A shell walking a browser profile directory, comparing files by exact byte size, and carving the match with findstr or certutil. This is the single highest-fidelity detection in the pack and it does not depend on any rotatable indicator.
// HUNT: DOUBLECUP ClickFix, shell carving a payload out of the browser cache // MITRE: T1204.004, T1027.003, T1083 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: none expected. A size-matched cache-file loop piped into an interpreter has no benign analogue. // NOTE: set the search window in the console. Last 7 days is a good starting point. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/%~z/i | CommandLine=/(findstr|certutil)/i | CommandLine=/(AppData|User Data|Cache)/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: command lines that reach PowerShell through a glob such as pow?r?hell.exe rather than by name. The exclusion drops the literal spelling, so only obfuscated forms survive. This catches the DOUBLECUP stage-1 launcher and a wide range of unrelated evasion tooling as a bonus.
// HUNT: Wildcard-obfuscated PowerShell resolution (DOUBLECUP stage 1 uses pow?r?hell.exe) // MITRE: T1027, T1059.001 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: rare. The exclusion below removes the literal spelling so only obfuscated forms remain. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/pow[-a-z?*]{0,3}r[-a-z?*]{0,3}hell/i | CommandLine!=/powershell/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: CountLoader's PE-patched LOLBin copies. The --headless switch is specific to conhost.exe, so a process carrying it whose filename is not conhost.exe is by definition a renamed copy. This defeats the masquerade without needing to know which autostart name the malware stole on that host.
// HUNT: conhost --headless launched from a RENAMED copy (CountLoader 4.5p PE-patched LOLBin) // MITRE: T1036.003, T1059.003 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: Windows Terminal uses --headless, but always as conhost.exe, which the exclusion removes. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/--headless/i | FileName!=/^conhost(\.exe)?$/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, ImageFileName, SHA256HashData, CommandLine])
Looks for: the CountLoader re-fetch cradle. Both scheduled tasks call back with irm <C2> | iex under an execution-policy bypass every 25 minutes, so an infected host produces a steady, regular signal rather than a single event. FP: package managers and vendor bootstrap installers use the same three ingredients. Tune before alerting.
// HUNT: PowerShell download cradle with execution-policy bypass (CountLoader task re-fetch) // MITRE: T1059.001, T1105 | CONF: high FP: medium COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: Chocolatey and Scoop bootstraps, some vendor installers, CI agents. // TUNING: exclude your build and deployment service accounts by UserName, and exclude the // TUNING: ParentBaseFileName of your approved software-distribution agent. Do NOT exclude on a // TUNING: CommandLine substring alone, since that is the field the attacker controls. // TUNING: an infected host repeats this roughly every 25 minutes. Sort by aid and look for cadence. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/-e[a-z]*p[a-z]*\s+bypass/i | CommandLine=/(\birm\b|Invoke-RestMethod|\biwr\b|Invoke-WebRequest)/i | CommandLine=/(\biex\b|Invoke-Expression)/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: the four persistence task names used across both payloads. These imitate vendor updater tasks but do not match the real naming convention, which is GoogleUpdateTaskMachine* and MicrosoftEdgeUpdateTaskMachine*. Anchoring the regex at the start of the name is what keeps this clean.
// HUNT: Impostor update tasks (CountLoader GoogleUpdateService / MSEdgeUpdateService, // DeviceManager MicroUpdaterV1 / PythonAppUpdater) // MITRE: T1053.005 | CONF: high FP: low COST: low // REQUIRES: ScheduledTaskRegistered (Windows) // FALSE POSITIVES: none. Genuine vendor tasks are GoogleUpdateTaskMachine* and // MicrosoftEdgeUpdateTaskMachine*, neither of which matches this start-anchored pattern. #event_simpleName=/^ScheduledTaskRegistered$/ | TaskName=/^(GoogleUpdateService|MSEdgeUpdateService|MicroUpdaterV1|PythonAppUpdater|DOUBLECUP)/i | table([@timestamp, aid, ComputerName, UserName, TaskName, TaskExecutable, TaskAuthor])
Looks for: DeviceManager's persistence call, which writes an XML task definition to %TEMP%\t.xml, registers it, then deletes the XML inside a finally block. Catching the registration is the only chance, because the file is gone within milliseconds. FP: installers and MDM agents legitimately register tasks from XML templates.
// HUNT: schtasks registering a task from an XML file staged in a user-writable path // MITRE: T1053.005 | CONF: medium FP: medium COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: vendor installers and MDM/RMM agents register tasks from an XML template. // TUNING: exclude the ParentBaseFileName of your MDM/RMM agent and msiexec.exe where the parent // TUNING: chain is signed. Anything left whose parent is a script interpreter is worth reading. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^schtasks(\.exe)?$/i | CommandLine=/\bXML\b/i | CommandLine=/(Temp|AppData|Users)/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, CommandLine])
Looks for: the exact wire format of DeviceManager's DNS C2. Its operations encode as a single leading letter (i for system-info exfil, t for task polling, r for status), then a hyphen, then the 16-character MD5-derived device hash, then the payload label. Because the malware appends microsoft.com to blend into DNS logs, matching on the apex is useless. Matching on this label shape is not.
// HUNT: DeviceManager DNS-tunnel query structure (op prefix + device_hash + payload label) // MITRE: T1071.004, T1041 | CONF: high FP: low COST: medium // REQUIRES: DnsRequest (Windows/macOS) // FALSE POSITIVES: very low. A single op letter, then a 16+ character hex hash, then an encoded label. // NOTE: the malware appends a microsoft.com apex on purpose. Do not filter on the apex, filter on shape. #event_simpleName=/^DnsRequest$/ | DomainName=/^[itr]-[0-9a-f]{16,64}-/i | table([@timestamp, aid, ComputerName, DomainName, RequestType, ContextBaseFileName, ContextProcessId])
Looks for: the generic version of Q7, for when the operator changes the label prefixes. DeviceManager chunks payloads into 63-character labels, which is the DNS maximum, so a host pushing data out this way emits an abnormal volume of near-maximum-length first labels. Run this as a weekly outlier review rather than an alert. FP: CDNs, EDR cloud lookups and telemetry SDKs also use long hashed labels.
// HUNT: DNS tunnelling volumetrics, hosts emitting many maximum-length labels // MITRE: T1071.004 | CONF: medium FP: medium COST: high // REQUIRES: DnsRequest (Windows/macOS) // FALSE POSITIVES: CDN, EDR and AV cloud-lookup traffic, and some telemetry SDKs, use long hashed labels. // TUNING: exclude ContextBaseFileName for your AV/EDR agent and for browser processes FIRST, then // TUNING: baseline the remaining top talkers for a week before you alert on anything. // TUNING: raise the Lookups threshold to fit your estate. 100 suits a quiet corporate endpoint. #event_simpleName=/^DnsRequest$/ | DomainName=/^[-a-z0-9]{45,63}\./i | groupBy([aid, ComputerName, ContextBaseFileName], function=count(as=Lookups), limit=2000) | Lookups > 100 | sort(Lookups, order=desc, limit=200)
Looks for: the named script artifacts of the DeviceManager RAT. run.pyw is the unpacked core, agent_main.pyw is the installed entry point, and the _dm_ prefixed temp files are how it stages CMD, PowerShell and Python tasks on disk before deleting them. These names are family-specific, so a hit is effectively a confirmation.
// HUNT: DeviceManager Python entry points (run.pyw, agent_main.pyw, _dm_ temp task files) // MITRE: T1059.006, T1620 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: none expected. These script names are specific to DeviceManager. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/(run\.pyw|agent_main\.pyw|_dm_task\.py|_dm_[a-z0-9]{4,}\.(ps1|bat))/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, ImageFileName, CommandLine])
Looks for: the CountLoader victim-profiling pass. It probes %APPDATA% for a fixed list of wallet directories and checks the Ledger install paths, then reports each as a boolean in its C2 beacon. A hit tells you not just that the host is infected but that the operator has already decided it is worth monetising.
// HUNT: CountLoader wallet, browser-extension and Signal Desktop profiling strings // MITRE: T1518.001, T1083, T1082 | CONF: medium FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: low. Genuine wallet use does not pass these directory names as arguments. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/(Ledger Live|Ledger Wallet|BitBox02|KeepKey|@trezor|Exodus|Guarda)/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: CountLoader's taskType 11 staging step, which downloads the official embeddable Python package into the user profile so it can run App.py from a scheduled task. The version pattern is generalised rather than pinned to 3.13.13, because the operator can bump it trivially.
// HUNT: Portable embeddable Python package pulled into a user profile (CountLoader taskType 11) // MITRE: T1105, T1059.006 | CONF: medium FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: developer workstations legitimately fetch embeddable Python. Scope to // non-developer OUs first, or join against your developer host group and invert. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/python-3\.[0-9]{1,2}\.[0-9]{1,2}-embed-(amd64|win32)/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: CountLoader command 10, which proxies script execution through mshta against an operator-supplied URL, and the .lnk files it drops for USB spread, which also launch mshta. Local .hta files are occasionally legitimate in older line-of-business apps. A remote URL essentially never is.
// HUNT: mshta.exe executing a remote URL (CountLoader command 10, proxied script execution) // MITRE: T1218.005, T1105 | CONF: high FP: low COST: low // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: rare in a managed estate. Legacy apps use LOCAL .hta files, not remote URLs. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^mshta(\.exe)?$/i | CommandLine=/http[s]?:/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, CommandLine])
Looks for: direct callbacks to the eight published IPs. Treat any hit as an incident, not a hunt result. Run this over the longest window your retention allows, since it is the retro-hunt that tells you whether you were already hit before this pack existed.
// HUNT: Outbound connection to published DOUBLECUP / DeviceManager infrastructure // MITRE: T1071.001, T1102.001 | CONF: high FP: low COST: low // REQUIRES: NetworkConnectIP4 (Windows/macOS) // FALSE POSITIVES: none. Any hit is a confirmed infrastructure callback. Escalate, do not triage. // NOTE: set the console window as wide as retention allows. This is the retro-hunt. #event_simpleName=/^NetworkConnectIP4$/ | RemoteAddressIP4=/^(213\.139\.77\.109|91\.92\.240\.100|67\.219\.107\.181|80\.96\.109\.229|167\.148\.201\.131|89\.124\.117\.12|103\.22\.137\.227|146\.70\.124\.154)$/ | table([@timestamp, aid, ComputerName, ContextBaseFileName, LocalAddressIP4, RemoteAddressIP4, RemotePort])
Looks for: every published DOUBLECUP domain, including the fake CRM login pages. A hit on one of the CRM lure domains means a user reached the page. Whether they pasted the command is what Q1 tells you. Run both together when triaging.
// HUNT: DNS resolution of DOUBLECUP lure, staging and CountLoader C2 domains // MITRE: T1071.001, T1583.001 | CONF: high FP: low COST: low // REQUIRES: DnsRequest (Windows/macOS) // FALSE POSITIVES: none. These are dedicated actor domains, not compromised legitimate sites. // NOTE: pair a hit here with Q1 on the same aid to establish whether the user actually executed. #event_simpleName=/^DnsRequest$/ | DomainName=/(^|\.)(login-netsuite\.com|login-odoo\.com|login-salesforce\.com|verification-salesforce\.com|login-hubspot\.com|pending-verification\.com|doublecap\.ltd|doublecap\.live|canva-arts\.com|cloudscraft\.com|examcanvas\.com|storagepioneer\.com|supercloudsaver\.com|ticgo-cloud\.com|roqqcloud\.com|cloud-electronic\.com|nxtdrcliam\.site|alphastore\.vg|appleid-customertelemetry\.gl|spec-connectweb3\.tv|srv641398444\.host\.ultaserver\.net)$/i | table([@timestamp, aid, ComputerName, DomainName, ContextBaseFileName, ContextProcessId])
Looks for: the Mach-O build's profiling pass. Rather than calling native APIs it shells out through popen and system, so it produces a tight burst of sw_vers, system_profiler, ioreg and launchctl under one parent. Grouping by parent is what separates that burst from a normal single call. FP: MDM, inventory and patch agents do exactly the same thing on a schedule.
// HUNT: macOS CountLoader reconnaissance burst (sw_vers, system_profiler, ioreg, launchctl) // MITRE: T1082, T1543.001, T1059.004 | CONF: medium FP: medium COST: medium // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (macOS sensor coverage required) // FALSE POSITIVES: MDM, inventory and patch agents call the same utilities on a schedule. // TUNING: exclude the ParentBaseFileName of your MDM and inventory agents first, for example // TUNING: jamf, munki or osqueryd, then review any remaining parent that is not a signed managed // TUNING: binary. A parent living in a user home directory or in Downloads is the finding. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^(sw_vers|system_profiler|ioreg|launchctl)$/i | groupBy([aid, ComputerName, ParentBaseFileName], function=count(as=Hits), limit=2000) | Hits >= 3 | sort(Hits, order=desc, limit=200)
Looks for: the DeviceManager delivery shape, an Inno Setup installer re-launching itself through the /SL5= IPC handoff from a Downloads or Temp path. FP: high by design. Every Inno Setup installer on earth does this, so it is a triage lens for a host you already suspect, never a standalone alert. Pair it with Q9 or Q13.
// HUNT: Inno Setup stager unpacking with the /SL5 IPC flag from a download or temp path // MITRE: T1204.002, T1027 | CONF: medium FP: high COST: medium // REQUIRES: ProcessRollup2 / SyntheticProcessRollup2 (Windows) // FALSE POSITIVES: HIGH BY DESIGN. Every Inno Setup installer uses this flag. Not an alert. // TUNING: run this ONLY scoped to an aid already flagged by Q9 or Q13, or restricted to hosts // TUNING: with no software-install change ticket for the period. // TUNING: exclude the SHA256HashData values of the Inno-packaged software you deploy, then review // TUNING: whatever remains. Do not promote this query to a scheduled search. #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/SL5=/i | CommandLine=/(Downloads|Temp|AppData)/i | table([@timestamp, aid, ComputerName, UserName, ParentBaseFileName, FileName, SHA256HashData, CommandLine])
CrowdStrike Custom IOA Recommendations
Four of the sixteen queries are clean enough to promote to Custom IOAs. The rest stay as Investigate-only hunts. Deploy every IOA in Detect for two weeks before considering Prevent, and note that Q3 is the only one where an immediate Prevent action is genuinely low-risk.
| IOA name | From | Pattern | Action | Exclusions |
|---|---|---|---|---|
| DOUBLECUP ClickFix Cache Carve | Q1 | Process creation. Image cmd.exe or powershell.exe. Command line matches a size-comparison token together with findstr or certutil and a browser profile directory. | Detect then Prevent Critical | None recommended. If a hit is a true positive the host is already executing attacker code. |
| Renamed Console Host Execution | Q3 | Process creation. Command line contains --headless. Image filename is not conhost.exe. | Prevent Critical | Add an exclusion only if a signed vendor product is confirmed to ship a renamed conhost, which is unusual enough to be worth investigating first. |
| Impostor Updater Task Registration | Q5 | Scheduled task registration. Task name starts with GoogleUpdateService, MSEdgeUpdateService, MicroUpdaterV1 or PythonAppUpdater. | Detect High | None. The genuine vendor tasks use different prefixes and will not match. |
| DeviceManager DNS Tunnel | Q7 | DNS request. Query name leading label matches an operation prefix followed by a hex device hash. | Detect High | None expected. If your estate produces noise, restrict to TXT record types first. |
Investigate-only (do not promote)
- Q4, Q6, Q8, Q15, Q16. All carry FP medium or higher. Each has a
// TUNING:block inside the query card. Baseline them in your own estate before they earn an alert. - Q13 and Q14 are better served by Falcon IOC Management using the CSV in section 10 than by a Custom IOA, because IOC Management handles expiry and bulk revocation for you.
- Q16 specifically must not become a scheduled search. Every Inno Setup installer matches it.
Deployment path: Falcon console, Endpoint security, Custom IOA rule groups. Create one Windows rule group named for this campaign and one macOS group, assign to a pilot host group of roughly 50 endpoints, then review for a week before widening. Custom IOAs evaluate on every matching event, so keep the regex anchored as written rather than loosening it.
Machine-Readable IOC Appendix
Four one-click blocks. The CSV imports directly into Falcon IOC Management. The behavioral block is what still works after the operator rotates infrastructure, which for DeviceManager takes one blockchain transaction.
type,value,action,severity,expiration,description,tags sha256,882914f9014f14e89123e835f103ac8f9d4b2e358c1f21c1cbc7f1054e6afed6,prevent,critical,2027-02-05,DOUBLECUP Go operator client,campaign:DOUBLECUP sha256,8585721cbc46780903bd727e37a9ed07a33463852046ff65bc718ded4c80dfb1,prevent,critical,2027-02-05,DOUBLECUP Go operator client,campaign:DOUBLECUP sha256,28cbbca8099bb1b27668d135314842c69ceb478a7d6b4b08f063d106a06c8f9d,detect,high,2027-02-05,DOUBLECUP stage 2 steganographic PNG,campaign:DOUBLECUP sha256,6e08cb5602f63bee2b40739167b4aef77763bc8fb47b4839ca2fc1607ad35cba,prevent,critical,2027-02-05,MicroUpdaterV1.exe DeviceManager Inno Setup stager,malware:DeviceManager sha256,ea70895620f955b0712b85c3fee41de7437d5068267966f0b4fb6fa2704c3a50,prevent,critical,2027-02-05,run.pyw DeviceManager RAT core,malware:DeviceManager sha256,bdf28e611d77362c40a0445655a35943c03accf21bb9a5af755da7eac5ea5e40,prevent,critical,2027-02-05,CountLoader 4.5p,malware:CountLoader sha256,afe273533d6f9d0b8852988f6a4b34571dd52af4c690e54723a86257aa8a015d,prevent,critical,2027-02-05,setup.sh macOS CountLoader stager,malware:CountLoader sha256,08730fda7366104b1461b12834f55723381bf34a234947689c708b1ee431af69,prevent,critical,2027-02-05,AppleIDVerificationService macOS CountLoader,malware:CountLoader ipv4,213.139.77.109,detect,high,2026-11-05,DOUBLECUP license panel and open directory port 9090,campaign:DOUBLECUP ipv4,91.92.240.100,detect,critical,2026-11-05,DeviceManager C2 resolved via EtherHiding,malware:DeviceManager ipv4,67.219.107.181,detect,high,2026-11-05,DOUBLECUP payload builder callback host,campaign:DOUBLECUP ipv4,80.96.109.229,detect,medium,2026-11-05,DOUBLECUP license panel activity,campaign:DOUBLECUP ipv4,167.148.201.131,detect,medium,2026-11-05,DOUBLECUP license panel activity,campaign:DOUBLECUP ipv4,89.124.117.12,detect,medium,2026-11-05,DOUBLECUP license panel activity,campaign:DOUBLECUP ipv4,103.22.137.227,detect,medium,2026-11-05,DOUBLECUP server activity,campaign:DOUBLECUP ipv4,146.70.124.154,detect,medium,2026-11-05,DOUBLECUP server activity,campaign:DOUBLECUP domain,login-netsuite.com,prevent,high,2026-11-05,CRM lure page injecting DOUBLECUP,campaign:DOUBLECUP domain,login-odoo.com,prevent,high,2026-11-05,CRM lure page injecting DOUBLECUP,campaign:DOUBLECUP domain,login-salesforce.com,prevent,high,2026-11-05,CRM lure page injecting DOUBLECUP,campaign:DOUBLECUP domain,verification-salesforce.com,prevent,high,2026-11-05,CRM lure page injecting DOUBLECUP,campaign:DOUBLECUP domain,login-hubspot.com,prevent,high,2026-11-05,CRM lure page injecting DOUBLECUP,campaign:DOUBLECUP domain,pending-verification.com,prevent,high,2026-11-05,CRM lure page injecting DOUBLECUP,campaign:DOUBLECUP domain,doublecap.ltd,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,doublecap.live,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,canva-arts.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,cloudscraft.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,examcanvas.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,storagepioneer.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,supercloudsaver.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,ticgo-cloud.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,roqqcloud.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,cloud-electronic.com,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,cap.spec-connectweb3.tv,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,cap-t1.spec-connectweb3.tv,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,cap-t2.spec-connectweb3.tv,prevent,high,2026-11-05,Delivers DOUBLECUP,campaign:DOUBLECUP domain,nxtdrcliam.site,prevent,high,2026-11-05,Hosts DOUBLECUP server component,campaign:DOUBLECUP domain,srv641398444.host.ultaserver.net,prevent,high,2026-11-05,Hosts DOUBLECUP server. FQDN only. Do not block the provider apex,campaign:DOUBLECUP domain,alphastore.vg,prevent,high,2026-11-05,Delivers DOUBLECUP and CountLoader C2,malware:CountLoader domain,appleid-customertelemetry.gl,prevent,high,2026-11-05,macOS CountLoader C2 and stager host,malware:CountLoader url,http://67.219.107.181/hgflssvslvidfugvbldiuv,detect,high,2026-11-05,DOUBLECUP payload builder callback URL,campaign:DOUBLECUP url,https://appleid-customertelemetry.gl/setup.sh,prevent,high,2026-11-05,macOS CountLoader stager,malware:CountLoader url,https://appleid-customertelemetry.gl/AppleIDVerificationService,prevent,high,2026-11-05,macOS CountLoader Mach-O,malware:CountLoader url,https://s3.us2.lyve.seagate.com/fullstack09/MicroUpdaterV1.exe,detect,high,2026-11-05,DeviceManager staged on abused Seagate Lyve storage. Full object path only. NEVER block the seagate apex,malware:DeviceManager # Not importable into Falcon IOC Management. Monitor externally, see the Web3 block. # smart contract 0xc027490AF56a9d7050fc259Ecd03DA1580b84aae # operator address 0xCE17b1EF00d47105Bc127BbE6fC45dE47BC22fb8
These do not expire and cannot be rotated by the operator. Prefer them over the CSV.
DELIVERY
shell reads a browser cache file selected by EXACT byte size, then carves it
markers: %~z size comparison, findstr or certutil, a browser User Data path
PowerShell reached through a glob rather than by name (pow?r?hell.exe)
clipboard write immediately followed by a Run-dialog process launch
COUNTLOADER 4.5p
a process invoked with --headless whose filename is NOT conhost.exe
copies of conhost.exe / powershell.exe / mshta.exe outside System32 whose PE
OriginalFilename or InternalName does not match the on-disk filename
single-letter-prefixed system binary names in a user-writable path
pattern: c* for conhost, p* for powershell, m* for mshta (e.g. csvchost.exe)
scheduled task with WakeToRun enabled AND a repetition interval under 30 minutes
HTTP GET to /connect? where the query string is hex with a 6-digit prefix
process alive for only a few seconds, repeating on a fixed 25-minute cadence
DEVICEMANAGER
pythonw.exe running from a user-writable path with no installed Python product
DNS query whose first label is <op-letter>-<16-char hex>-<payload>
sustained DNS TXT queries with 63-character labels from a single host
WMI __FilterToConsumerBinding created with NO wmic.exe or powershell.exe ancestor
cmd.exe /Q /K or powershell.exe -Command - fed entirely over STDIN
eth_call traffic to public Web3 RPC nodes from a host with no blockchain workload
MACOS COUNTLOADER
LaunchAgent plist referencing a binary in ~/Library, /tmp or Downloads
burst of sw_vers + system_profiler + ioreg under one non-managed parent
SCHEDULED TASK NAMES GoogleUpdateService<GUID> CountLoader primary, 25 min, WakeToRun MSEdgeUpdateService<GUID> CountLoader fallback, 25 min MicroUpdaterV1 DeviceManager primary, 10 min PythonAppUpdater DeviceManager fallback DOUBLECUP operator-side client tooling (genuine vendor tasks are GoogleUpdateTaskMachine* and MicrosoftEdgeUpdateTaskMachine*, so match the full prefix) WMI SUBSCRIPTION OBJECTS (root\subscription) __EventFilter PythonAppUpdateFilter CommandLineEventConsumer PythonAppUpdateConsumer __IntervalTimerInstruction PythonAppTimer_600 (600000 ms) FILE PATHS %LOCALAPPDATA%\DeviceManager\config.json AgentConfig, contract + key %LOCALAPPDATA%\DeviceManager\agent.log rotating log, best forensic source %LOCALAPPDATA%\DeviceManager\agent_main.pyw hidden entry point %LOCALAPPDATA%\DeviceManager\agent\ full package copy %TEMP%\t.xml task XML, deleted immediately %TEMP%\_dm_task.py in-memory python task wrapper %TEMP%\_dm_<random>.ps1 on-disk powershell task %TEMP%\_dm_<random>.bat on-disk cmd task %USERPROFILE%\App_<GUID>.py CountLoader masquerading helper %USERPROFILE%\Python313\ embeddable Python 3.13 staging ~/Library/LaunchAgents/*.plist macOS CountLoader persistence FILE NAMES AND STRINGS MicroUpdaterV1.exe run.pyw agent_main.pyw App.py is-*.tmp python-3.13.13-embed-amd64.zip AppleIDVerificationService setup.sh K94DGQ99VYCCH52TKOT2 hardcoded CountLoader campaign token ZZ1984 findstr needle in the reference stego PNG C2 URI PATTERNS /api/config /session/reg /session/check /session/signal /stego-image.png?sid= /connect? approveUpdate?id= getUpdates (POST body, XOR+hex encoded, Bearer JWT) ACTOR HANDLES (pivot only, not detection) Telegram bot @harrypoterlohBOT Actor Rognar / @johnysilverhe (primary source spelling, single n) Also seen as johnnysilverhe (double n, as VS Code publisher) VS Code ext Agent IDE
DeviceManager reads its live C2 from a smart contract, so the operator re-points the
entire botnet with ONE transaction and no implant redeployment. That makes contract
monitoring the only way to get the next C2 BEFORE it is used against you.
CONTRACT
0xc027490AF56a9d7050fc259Ecd03DA1580b84aae C2 resolver contract
0xCE17b1EF00d47105Bc127BbE6fC45dE47BC22fb8 operator address writing updates
networks: Ethereum / Polygon. The analysed sample pointed at Sepolia testnet RPCs.
FUNCTION SELECTORS
0x1dcf296b read. Called with the victim device_hash. Returns a per-victim C2.
0xc474520d write. GLOBAL C2 update. A call here re-points the whole botnet.
0x71c28139 write. Targeted C2 assignment to one specific infected device.
WHAT TO DO WITH IT
1. Set a block-explorer alert on any transaction to the contract address above.
2. On a 0xc474520d call, pull the calldata, strip the 0x prefix, read the ABI
offset and length, then ChaCha20-decrypt the payload. The key is the SHA-256 of
the campaign blockchain_key and the nonce is derived from the contract address.
3. First decrypted byte 0x00 means the new C2 is HTTP POST, anything else means
DNS tunnelling. The remainder is UTF-8 and is the IP or hostname. If no port is
present the malware appends :53 for DNS or :80 for HTTP.
4. Push the recovered address into the CSV block above as a new detect entry.
The known-good decryption of the most recent global-update transaction at the time of
the source report resolved to: dns://91.92.240[.]100
ENDPOINT-SIDE SIGNAL (no contract access needed)
Alert on eth_call JSON-RPC traffic, or DNS/TLS to public Web3 RPC providers, from
any host outside your developer and treasury groups. Build that allowlist first,
because the exclusion list is the detection here.
Detection Validation Gates
Work these four gates in order. Do not promote anything to Prevent until gate 4 passes, and record the date each gate cleared so the coverage claim in section 15 is evidenced rather than assumed.
Gate 1 — Telemetry ready
- Confirm
ProcessRollup2volume is non-zero per host per day across the Windows estate. If command lines are truncated or suppressed by policy, Q1 through Q6 and Q9 through Q12 are all degraded and you must fix that before continuing. - Confirm
ScheduledTaskRegisteredevents exist at all. Several tenants have this event class disabled or filtered, which silently kills Q5. - Confirm
DnsRequestis present and that endpoints actually use the internal resolver. If a host talks to an external resolver directly, Q7 and Q8 will never see its tunnel traffic. - Confirm macOS sensor coverage separately. Q15 assumes macOS process telemetry, which is commonly a lower deployment percentage than Windows.
Gate 2 — Benign baseline
- Run Q4, Q6, Q8, Q15 and Q16 over 14 days with no exclusions. Record the hit count and the top ten parents or accounts for each.
- Write the exclusions named in each card's
// TUNING:block against what you actually saw, not against what the card guessed. The tuning lines are a starting hypothesis about your estate, not a fact about it. - Expected steady state after tuning: Q4 in the low tens per week in an estate that uses package managers, and near zero in one that does not. Q8 should settle to a stable set of the same few agent processes, which you then exclude.
- Q1, Q3, Q5, Q7, Q9 and Q13 should all baseline at zero. Any non-zero result during baselining is a finding, not noise. Investigate before excluding anything.
Gate 3 — Positive tests
Run these on an isolated, instrumented test host. They exercise the detection logic without executing anything malicious and without reproducing any part of the attack chain.
Q3 copy conhost.exe to a user path under a different name and launch it with
--headless and a trivial argument. Confirm the query fires on the renamed image.
This is the highest-value test because it validates the masquerade logic itself.
Q5 register a scheduled task literally named MSEdgeUpdateServiceTEST pointing at
a harmless executable. Confirm Q5 fires, then delete the task.
Q7 from the test host, resolve a hostname of the shape
i-0123456789abcdef-test.example.com against your internal resolver.
Confirm the DnsRequest event appears and Q7 matches the label shape.
Q9 create an empty file named run.pyw and invoke it through a python interpreter.
Confirm the command line is captured.
Q12 run mshta.exe https://example.com/ and confirm it fires. Kill it immediately.
Q13 no safe positive test exists. Validate by confirming the query parses and by
checking it returns rows when you temporarily substitute a benign IP you control.
Detection latency target: all of the above should surface within 5 minutes.
If they do not, the problem is telemetry ingestion, not the query.
Gate 4 — Promotion
- Promote Q1, Q3, Q5 and Q7 to Custom IOAs in Detect only. Hold for 14 days.
- Move Q3 to Prevent first. It has the cleanest logic and the least plausible benign match.
- Move Q1 to Prevent once you are satisfied gate 2 held at zero. A true positive on Q1 means the host is already running attacker-supplied code, so blocking is the correct outcome.
- Leave Q5 and Q7 in Detect indefinitely. Both are worth alerting on and neither is worth blocking, because by the time they fire the payload has already run.
- Import the section 10 CSV into Falcon IOC Management with the expiry dates as written, then diary a review for 2026-11-05 when the network indicators lapse.
Hardening — Tiered
DOUBLECUP is unusually vulnerable to prevention because its delivery depends on two things a managed estate does not actually need: an interactive Run dialog and a web page's ability to write to the clipboard. Take those away and the loader has no route from a lure page to a shell. Everything else here is depth behind that.
| ID | Control | Why it matters here | Authority |
|---|---|---|---|
| HRD-1 | Remove the Run menu from the Start Menu for standard users. GPO User Configuration, Administrative Templates, Start Menu and Taskbar, "Remove Run menu from Start Menu". | The ClickFix prompt instructs the victim to press Win+R and paste. This removes the paste target entirely and is the single highest-leverage control against the whole ClickFix technique class, not just DOUBLECUP. | MITRE M1038 Execution Prevention. CIS Microsoft Windows Benchmark, user-rights and Explorer policy section. |
| HRD-2 | Block the browser clipboard-write permission. Set DefaultClipboardSetting to 2 in Chrome and Edge enterprise policy, with narrow exceptions via ClipboardAllowedForUrls. | The lure page silently copies the browser-matched command to the clipboard through the async Clipboard API. Value 2 removes that capability estate-wide. It does not stop a user manually selecting and copying visible text, so treat it as friction, not a wall. | CIS Google Chrome Benchmark v3.0.0 item 4.2.5. Chrome Enterprise policy list. |
| HRD-3 | Enable ASR rule "Block use of copied or impersonated system tools" c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb. | This is the direct counter to CountLoader 4.5p's core evasion. It copies conhost.exe, powershell.exe and mshta.exe out of System32, renames them and patches the PE metadata. This rule blocks exactly that class of impersonated system binary. | MITRE M1042. Microsoft Defender ASR rules reference. |
| HRD-4 | Enable ASR rule "Block persistence through WMI event subscription" e6db77e5-3df2-4cf1-b95a-636979351e5b. | DeviceManager's alternate persistence builds a __FilterToConsumerBinding through direct COM calls specifically to dodge process-lineage detection. This rule closes the channel rather than trying to see it, which matters because Falcon has no clean event for it. | MITRE M1040. Microsoft Defender ASR rules reference. |
| HRD-5 | Enable PowerShell script-block logging (EID 4104), module logging and transcription. | Stage 2 and all of CountLoader are fileless. Script-block logs are the only place their decrypted bodies are ever recorded. Without this, a post-incident investigation has almost nothing to work with because the malware self-deletes. | MITRE M1047. CIS Microsoft Windows Benchmark, PowerShell section. Microsoft Security Baseline. |
| HRD-6 | Enable ASR rules "Block execution of potentially obfuscated scripts" 5beb7efe-fd9a-4556-801d-275e5ffc04cc and "Block JavaScript or VBScript from launching downloaded executable content" d3e037e1-3eb8-44c8-a917-57927947596d. | Stage 1 is JScript, VBScript or PowerShell carved out of a PNG, and stage 2 is heavily obfuscated with an XOR routine. Both rules target that shape. Note the obfuscated-script rule requires cloud-delivered protection to be on. | MITRE M1038, M1042. Microsoft Defender ASR rules reference. |
| HRD-9 | Enable "Audit Other Object Access Events" so scheduled task creation logs as Security EID 4698. | Both payloads persist through scheduled tasks. This event is off by default in most estates, which is why native hunt N4 so often returns nothing on the first run. | MITRE M1047. CIS Microsoft Windows Benchmark, advanced audit policy. |
| ID | Control | Why it matters here | Authority |
|---|---|---|---|
| HRD-7 | Force all endpoint DNS through internal resolvers and block outbound UDP/TCP 53 to anything else. Enable per-client query logging including record type. Alert on sustained TXT volume per host. | DeviceManager tunnels over raw UDP sockets to its own authoritative server. If an endpoint can reach an arbitrary resolver, the tunnel never touches infrastructure you can see. This control is what makes Q7 and Q8 meaningful rather than theoretical. | MITRE M1037 Filter Network Traffic. NIST SP 800-81 secure DNS deployment guidance. |
| HRD-10 | Block execution from user-writable paths with AppLocker or App Control for Business. Start in Audit, deny %LOCALAPPDATA%, %TEMP% and %USERPROFILE% for executables and scripts, with an allowlist for genuine per-user apps. | Every persistence and execution artifact in this chain lives in a user-writable path: the renamed LOLBins, the embedded Python runtime, pythonw.exe, run.pyw, the _dm_ temp scripts. This one control breaks CountLoader and DeviceManager simultaneously. | MITRE M1038. Microsoft App Control for Business design guide. CIS Microsoft Windows Benchmark. |
| HRD-11 | Restrict or block mshta.exe via AppLocker or WDAC, and enable ASR "Block process creations originating from PSExec and WMI commands" d1e49aac-8f56-4280-b9ba-993a6d77406c. | CountLoader command 10 proxies script execution through mshta, and its USB .lnk drops launch mshta too. Almost no modern estate has a real need for mshta. Test the PSExec/WMI rule carefully if you run Configuration Manager, which depends heavily on WMI. | MITRE M1042. Microsoft Defender ASR rules reference. LOLBAS project. |
| HRD-12 | Enable ASR "Block untrusted and unsigned processes that run from USB" b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4 and disable autorun for removable media. | CountLoader command 9 scans every logical and physical drive and drops .lnk files designed to pull the loader through mshta. That is how this reaches segmented or partner systems. | MITRE M1034. Microsoft Defender ASR rules reference. |
| HRD-13 | Constrained Language Mode for PowerShell for non-administrative users, enforced through App Control rather than an environment variable. | CountLoader relies on .NET reflection and D/Invoke to bypass AMSI. Constrained Language Mode removes access to the reflection APIs that technique needs. Setting it via environment variable alone is trivially bypassed, so it must be App Control enforced. | MITRE M1042, M1026. Microsoft PowerShell security documentation. |
| HRD-14 | macOS: restrict LaunchAgent creation to MDM-managed paths and enforce Gatekeeper plus notarisation. Remove standard-user admin rights. | The Mach-O build persists by dropping a plist into ~/Library/LaunchAgents and calling launchctl load. That path needs no elevation, so this is purely a policy and monitoring problem. | MITRE M1038, M1026. CIS Apple macOS Benchmark. Apple Platform Security guide. |
| HRD-15 | Block the published indicators at the web proxy and DNS firewall using the section 10 CSV, and add a proxy rule for the DOUBLECUP session URI pattern. | Indicator blocking is the shallowest layer here and it expires, but the URI pattern (/api/config plus /session/check polling) is campaign-structural rather than domain-specific and will survive infrastructure rotation. | MITRE M1037. |
| ID | Control | Why it matters here | Authority |
|---|---|---|---|
| HRD-8 | Egress policy for Web3 RPC endpoints. Build an allowlist of hosts with a genuine blockchain need, then alert on eth_call traffic or RPC-provider DNS from everything else. | EtherHiding is the reason the C2 indicators in this pack are perishable. You cannot take down a smart contract, so the practical control is noticing that a marketing laptop is talking to an Ethereum RPC node. The allowlist is the hard part and is why this is strategic rather than immediate. | MITRE M1037. best practice, no formal benchmark |
| HRD-16 | App Control for Business in enforced mode with a managed publisher allowlist, replacing the audit-mode AppLocker baseline from HRD-10. | This is the durable version of HRD-10. Once enforced, an unsigned Python runtime unpacked into a user directory simply does not run, regardless of how the operator repackages the loader next. | MITRE M1038. Microsoft App Control for Business deployment guide. DISA STIG application allowlisting requirements. |
| HRD-17 | Phishing-resistant MFA and conditional access on the impersonated SaaS platforms (NetSuite, Odoo, HubSpot, Salesforce), plus a brand-impersonation domain monitoring feed. | The lure cluster impersonates CRM login pages. Users who reach those pages may also be typing credentials into them. Detecting the loader without addressing the credential half of the same page leaves the more valuable outcome for the attacker unaddressed. | MITRE M1032, M1017. NIST SP 800-63B. |
| HRD-18 | Targeted user awareness on the ClickFix pattern specifically. Teach the shape: any web page that asks you to press Win+R, or to open Terminal and paste something, to "verify you are human" or "fix a display error", is an attack. | The chain has exactly one human decision point and it is a very teachable one. Generic phishing training does not cover it, because there is no attachment and no credential prompt. Include macOS Terminal in the message, since the same service delivers a Mach-O payload. | MITRE M1017 User Training. |
Deployable Playbooks
Raw configuration for the four highest-leverage controls. Every step carries its prerequisites, whether a reboot is needed, and how to undo it. Test each on a pilot ring before estate-wide rollout.
Playbook 1 — Remove the ClickFix paste target (HRD-1, HRD-2)
STEP 1.1 Remove the Run dialog for standard users
Prerequisites: GPO edit rights. A pilot OU. Confirm no line-of-business process
instructs users to launch anything via Win+R, and confirm your
help-desk scripts do not rely on it for standard users.
Reboot required: No. Applies at next Group Policy refresh or user logon.
GPO path: User Configuration \ Policies \ Administrative Templates \
Start Menu and Taskbar \ "Remove Run menu from Start Menu" = Enabled
Registry equivalent (per user hive):
Key: HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer
Value: NoRun Type: REG_DWORD Data: 1
Verify:
gpresult /h report.html then search the report for "Remove Run menu"
reg query "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" /v NoRun
Note: this removes the Start Menu entry and disables the Win+R shortcut. It does not
block cmd.exe or PowerShell themselves, which remain available to administrators.
Rollback: Set the GPO setting to "Not Configured" (do NOT set it to Disabled, which
writes NoRun=0 and pins the behaviour on). Then delete the value:
reg delete "HKCU\Software\Microsoft\Windows\CurrentVersion\Policies\Explorer" /v NoRun /f
Effective at next policy refresh. No reboot.
STEP 1.2 Block the browser clipboard-write permission
Prerequisites: Chrome or Edge enterprise policy management (ADMX ingested, or
Intune / Workspace policy). Inventory any internal web app that
legitimately uses a "copy to clipboard" button, because those need
an allowlist entry BEFORE this goes on.
Reboot required: No. Browser restart required.
Chrome:
Key: HKLM\SOFTWARE\Policies\Google\Chrome
Value: DefaultClipboardSetting Type: REG_DWORD Data: 2
Edge:
Key: HKLM\SOFTWARE\Policies\Microsoft\Edge
Value: DefaultClipboardSetting Type: REG_DWORD Data: 2
Value meanings: 2 = do not allow any site to use the clipboard site permission
3 = ask the user (this is the default when the policy is unset)
Allowlist for internal apps that genuinely need it:
Chrome: HKLM\SOFTWARE\Policies\Google\Chrome\ClipboardAllowedForUrls\1 = "https://intranet.example.com"
Verify: browse to chrome://policy or edge://policy and confirm the value is applied
and shows no conflict.
IMPORTANT: confirm the exact registry path in your own browser-management console
before mass deployment. The policy NAME and its value semantics are vendor-confirmed;
the registry path in this playbook was not read from a rendered vendor page in the
research for this pack, so treat it as needing a one-host verification first.
Limitation: this blocks programmatic clipboard writes. It does not prevent a user
manually selecting text on the page and copying it, so pair it with HRD-1 and HRD-18.
Rollback: Delete the DefaultClipboardSetting value (or set it to 3) and restart the
browser. Effect is immediate on restart.
reg delete "HKLM\SOFTWARE\Policies\Google\Chrome" /v DefaultClipboardSetting /f
Playbook 2 — ASR rules that break both payloads (HRD-3, HRD-4, HRD-6, HRD-11, HRD-12)
STEP 2.1 Enable in AUDIT mode first
Prerequisites: Microsoft Defender Antivirus active (not passive). Cloud-delivered
protection ON, which the obfuscated-script rule requires. If you run
Configuration Manager, read the warning in step 2.3 before enabling
the PSExec/WMI rule anywhere.
Reboot required: No.
Add-MpPreference -AttackSurfaceReductionRules_Ids c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb `
-AttackSurfaceReductionRules_Actions AuditMode # copied/impersonated system tools
Add-MpPreference -AttackSurfaceReductionRules_Ids e6db77e5-3df2-4cf1-b95a-636979351e5b `
-AttackSurfaceReductionRules_Actions AuditMode # WMI event subscription persistence
Add-MpPreference -AttackSurfaceReductionRules_Ids 5beb7efe-fd9a-4556-801d-275e5ffc04cc `
-AttackSurfaceReductionRules_Actions AuditMode # obfuscated scripts
Add-MpPreference -AttackSurfaceReductionRules_Ids d3e037e1-3eb8-44c8-a917-57927947596d `
-AttackSurfaceReductionRules_Actions AuditMode # JS/VBS launching downloaded content
Add-MpPreference -AttackSurfaceReductionRules_Ids b2b3f03d-6a65-4f7b-a9c7-1c7ef74a9ba4 `
-AttackSurfaceReductionRules_Actions AuditMode # untrusted processes from USB
Verify:
(Get-MpPreference).AttackSurfaceReductionRules_Ids
(Get-MpPreference).AttackSurfaceReductionRules_Actions
Audit events: Microsoft-Windows-Windows Defender/Operational, EID 1121 and 1122
Rollback: Remove-MpPreference -AttackSurfaceReductionRules_Ids <guid>
Immediate, no reboot.
STEP 2.2 Review audit output, then move to Block
Prerequisites: At least 7 days of audit data covering a full business cycle,
including a patch window and a month-end if you have one.
Reboot required: No.
Review EID 1121/1122 per rule. Expect near-zero for the copied-system-tools and
WMI-subscription rules in a healthy estate. If either is noisy, that noise IS the
finding and needs investigating before you exclude it.
Then flip each reviewed rule:
Set-MpPreference -AttackSurfaceReductionRules_Ids c0033c00-d16d-4114-a5a0-dc9b3a7d2ceb `
-AttackSurfaceReductionRules_Actions Enabled
Exclusions, only where a business case is documented:
Add-MpPreference -AttackSurfaceReductionOnlyExclusions "C:\Program Files\Vendor\app.exe"
Note these rules have LIMITED exclusion support per Microsoft, so a path exclusion
may not behave as you expect. Verify each one.
Rollback: Set the rule action back to AuditMode, or remove the rule ID entirely.
Immediate, no reboot.
STEP 2.3 mshta and the PSExec/WMI rule
Prerequisites: Confirm no line-of-business application depends on mshta.exe. Search
ProcessRollup2 for mshta parents over 30 days before deciding.
CRITICAL: if you use Microsoft Configuration Manager, Microsoft
advises against enabling the PSExec/WMI rule through any other
deployment method, because the ConfigMgr client depends heavily on
WMI. Test extensively in Audit first.
Reboot required: No.
Add-MpPreference -AttackSurfaceReductionRules_Ids d1e49aac-8f56-4280-b9ba-993a6d77406c `
-AttackSurfaceReductionRules_Actions AuditMode
Rollback: Remove-MpPreference -AttackSurfaceReductionRules_Ids d1e49aac-8f56-4280-b9ba-993a6d77406c
Immediate, no reboot. If ConfigMgr breaks, this is the first thing to undo.
Playbook 3 — PowerShell visibility and scheduled-task auditing (HRD-5, HRD-9)
STEP 3.1 Script-block logging, module logging, transcription
Prerequisites: Log storage sized for the increase. Script-block logging is verbose,
typically the largest single Windows log volume increase you will
make. Confirm your SIEM licence covers it before enabling fleet-wide.
Reboot required: No. Applies to new PowerShell sessions.
GPO path: Computer Configuration \ Policies \ Administrative Templates \
Windows Components \ Windows PowerShell
"Turn on PowerShell Script Block Logging" = Enabled
(leave "Log script block invocation start/stop" OFF, it multiplies volume
for very little investigative gain)
"Turn on Module Logging" = Enabled, module names = *
"Turn on PowerShell Transcription" = Enabled
OutputDirectory = a write-only share the user cannot read or delete from,
otherwise the malware simply removes its own transcript.
Registry equivalent:
HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging
EnableScriptBlockLogging REG_DWORD 1
HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\Transcription
EnableTranscripting REG_DWORD 1
Verify: run a trivial command, then confirm EID 4104 appears in
Microsoft-Windows-PowerShell/Operational.
Rollback: Set each policy to "Not Configured" and delete the registry values.
Applies to new sessions. No reboot.
reg delete "HKLM\SOFTWARE\Policies\Microsoft\Windows\PowerShell\ScriptBlockLogging" /f
STEP 3.2 Scheduled task creation auditing
Prerequisites: Advanced audit policy in use (not legacy audit policy). Log storage
headroom, though this event is low volume.
Reboot required: No.
auditpol /set /subcategory:"Other Object Access Events" /success:enable /failure:enable
GPO equivalent: Computer Configuration \ Policies \ Windows Settings \ Security Settings \
Advanced Audit Policy Configuration \ Object Access \
"Audit Other Object Access Events" = Success and Failure
Verify:
auditpol /get /subcategory:"Other Object Access Events"
Create a test task and confirm Security EID 4698 is written.
Rollback: auditpol /set /subcategory:"Other Object Access Events" /success:disable /failure:disable
Immediate, no reboot.
Playbook 4 — DNS containment for the tunnel (HRD-7)
STEP 4.1 Force internal resolvers and block external DNS
Prerequisites: Internal resolvers sized for full estate query load with logging on.
Inventory anything that hardcodes an external resolver: some IoT,
some VPN clients, some container runtimes. Those break first.
Reboot required: No, but endpoints may need a DHCP lease renewal or a network
profile refresh to pick up the resolver change.
Firewall rule (egress, applied at the perimeter and on the host firewall):
DENY any internal source -> any external destination, UDP 53
DENY any internal source -> any external destination, TCP 53
DENY any internal source -> any external destination, TCP 853 (DoT)
ALLOW approved resolvers -> upstream, UDP/TCP 53
Also block DNS-over-HTTPS bypass in browser policy, otherwise the browser routes
around your resolver and the endpoint DNS logs go quiet:
Chrome / Edge: DnsOverHttpsMode = "off"
HKLM\SOFTWARE\Policies\Google\Chrome\DnsOverHttpsMode REG_SZ off
HKLM\SOFTWARE\Policies\Microsoft\Edge\DnsOverHttpsMode REG_SZ off
Verify:
From a test endpoint, query any EXTERNAL resolver directly, for example
nslookup example.com 192.0.2.53 (this must FAIL once the rule is live)
Confirm queries appear in the internal resolver log with the client IP attributed.
Rollback: Remove the egress deny rules and set DnsOverHttpsMode back to
"automatic" or delete the value. Immediate. No reboot.
Keep resolver logging on even if you roll back the blocks, since the
logging alone is what Q7 and Q8 depend on.
STEP 4.2 Alert on tunnelling shape
Prerequisites: Step 4.1 complete and resolver logs flowing to the SIEM with
per-client attribution and record type.
Reboot required: No.
Resolver or SIEM rules:
- any single client exceeding a per-hour TXT query threshold you baseline first
- first label length at or near 63 characters, sustained
- a client querying a microsoft.com subdomain that resolves to non-Microsoft space
(this is the specific DeviceManager blend-in trick)
- NXDOMAIN ratio per client above your baseline
Rollback: Disable or tune the alert rules. Detection only, no endpoint state changed,
so there is nothing to undo on the fleet.
Rollback discipline. Every step above changes endpoint or network state and every one has a documented undo. The two with the widest blast radius are the PSExec/WMI ASR rule where Configuration Manager is in use, and the external-DNS block, which will surface every device that hardcodes a public resolver. Stage both on a pilot ring and keep the rollback command to hand during the change window.
Containment Runbook
Before you isolate, capture memory. CountLoader 4.5p deletes itself from disk on first execution and lives only in the scheduled task that re-fetches it. DeviceManager deletes its task XML and its temp task files immediately after use. If you isolate and reboot before acquiring memory, most of what you needed is gone. The scheduled task definitions and agent.log are the artifacts that survive.
| Phase | Actions | Owner | Evidence to preserve |
|---|---|---|---|
| 0. Triage (0 to 30 min) |
Confirm the hit is real. Q1 or Q3 firing means execution already happened. Q14 alone means the user only reached a lure page. Establish which by running Q1 and Q14 scoped to the same aid. Identify whether the payload was CountLoader (Q4, Q10 hits), DeviceManager (Q9, Q7 hits) or both. Check whether the user has crypto-wallet or Signal Desktop installed, since Q10 tells you the operator already knows. |
SOC L1 | Query results with timestamps. The full CommandLine from the Q1 hit, which is the pasted ClickFix command verbatim. |
| 1. Isolate (30 to 60 min) |
Falcon network-contain the host. Do not power it off. Capture a memory image and a triage collection first if your process allows it. Preserve %LOCALAPPDATA%\DeviceManager\agent.log before anything else, then the scheduled task XML from C:\Windows\System32\Tasks\, then the browser cache directory. Collect the RunMRU key per native hunt N1. |
SOC L2 / IR | Memory image. agent.log. Task XML files. Browser cache f_* entries. RunMRU values. Full process tree from the Falcon console. |
| 2. Scope (1 to 4 h) |
Run Q13 and Q14 across the whole estate over the longest available retention window. Every host in the same OU or department as the victim is a candidate, because ClickFix lures usually arrive through the same ad, search result or email to a group. Run Q5 estate-wide to find persistence on hosts that never triggered a delivery detection. Check for USB spread via CountLoader command 9 by looking for recently written .lnk files on removable media. | Threat hunt | List of every host with a hit, and the first-seen timestamp for each. |
| 3. Eradicate (4 to 24 h) |
Remove both persistence classes. Delete scheduled tasks matching the four impostor names. Audit and remove WMI subscription objects per native hunt N3, since ASR blocking a new one does not remove an existing one. Delete the DeviceManager directory tree and the staged Python runtime. Find and remove the renamed system-binary copies, which will be in a user-writable path with a single-letter prefix. Do not simply delete the malware and return the host: if the renamed LOLBins remain, an operator with a live session can restart the chain. | IR / Endpoint | Before and after listing of tasks, WMI subscriptions and the user-writable paths. |
| 4. Credential response (4 to 24 h) |
Treat every credential entered on the lure page as compromised, because the CRM impersonation pages harvest as well as deliver. Force password reset and revoke active sessions for the affected user on NetSuite, Odoo, HubSpot and Salesforce as applicable. If Q10 fired, engage the user about wallet seed phrases and treat any wallet on that host as compromised. If Signal Desktop was present, the operator profiled for it deliberately. | IAM / IR | Reset and session-revocation records. SaaS sign-in logs for the affected account over the exposure window. |
| 5. Block (24 h) |
Import the section 10 CSV into Falcon IOC Management. Push the domain and IP list to the proxy and DNS firewall. Add the DOUBLECUP session URI pattern as a proxy rule so the block survives infrastructure rotation. Set up the smart-contract watch described in the Web3 block, because that is what tells you when the DeviceManager C2 moves. | SOC / Network | Change tickets. Import confirmation with the expiry dates recorded. |
| 6. Recover (24 to 72 h) |
Rebuild rather than clean where DeviceManager was present. It has an in-memory command channel that ran arbitrary CMD, PowerShell and Python, so the compromise scope is unbounded and cleaning is a guess. For a CountLoader-only infection with no evidence of secondary payload execution, cleaning plus a monitored return is defensible. Release from containment only after 48 hours of clean telemetry on Q4, Q5, Q7 and Q13. | Endpoint / IR | Rebuild record or the clean-telemetry evidence supporting a decision not to rebuild. |
| 7. Close (1 week) |
Deploy the Immediate tier from section 12 if it is not already in place, since this incident is the business case. Brief the affected team on the ClickFix pattern per HRD-18. Feed the Q1 CommandLine from step 0 back into the detection as a real-world validation sample. Diary the 2026-11-05 indicator expiry review. | SOC lead | Post-incident review. Updated detection baseline. |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1204.004 | Clipboard command pasted into the Run dialog | Q1 | Yes | GOOD |
| T1027.003 | Payload hidden in a cached PNG, carved by size | Q1 | Yes | GOOD |
| T1027 | Wildcard-obfuscated interpreter resolution | Q2 | No | GOOD |
| T1036.003 | Renamed and PE-patched system binaries | Q3 | Yes | GOOD |
| T1059.001 / T1105 | PowerShell download cradle with policy bypass | Q4 | No | PARTIAL FP medium, needs local baselining |
| T1053.005 | Scheduled-task persistence, named | Q5 | Yes | GOOD |
| T1053.005 | Scheduled-task persistence, XML registration | Q6 | No | PARTIAL FP medium |
| T1071.004 | DNS tunnelling, known label structure | Q7 | Yes | GOOD |
| T1071.004 | DNS tunnelling, generic volumetrics | Q8 | No | PARTIAL outlier review only |
| T1059.006 | Python RAT entry points | Q9 | No | GOOD |
| T1518.001 / T1083 | Wallet, extension and Signal profiling | Q10 | No | GOOD |
| T1105 / T1059.006 | Embedded Python runtime staging | Q11 | No | GOOD |
| T1218.005 | mshta proxied remote script execution | Q12 | No | GOOD |
| T1071.001 | Known infrastructure callback | Q13, Q14 | IOC Mgmt | PARTIAL perishable by design |
| T1543.001 / T1082 | macOS LaunchAgent and recon burst | Q15 | No | PARTIAL depends on macOS sensor coverage |
| T1204.002 | Inno Setup stager unpack | Q16 | No | PARTIAL triage lens only, FP high |
| T1546.003 | WMI Event Subscription persistence | None | No | GAP Native N3 + ASR HRD-4 |
| T1620 | Reflective .NET assembly loading | None | No | GAP No distinct sensor event. Detect surrounding behavior. |
| T1480.001 | Environmental keying on the public IP | None | No | GAP Anti-analysis technique, not host-observable |
| T1102.001 | EtherHiding C2 resolution via smart contract | None | No | GAP HRD-8 egress policy + external contract monitoring |
| T1106 | Native API calls through Python ctypes | None | No | GAP Prevention only, via HRD-10 and HRD-16 |
| T1547.009 | Browser .lnk shortcut hijacking | None | No | GAP Native N7. Dead code in the analysed sample. |
Coverage summary. Sixteen queries cover sixteen of the twenty-two mapped behaviors, ten of them at good confidence with four promoted to Custom IOAs. Six behaviors are gaps. Five of those six are gaps by nature rather than by omission: reflective loading, environmental keying and ctypes API calls produce no distinct endpoint event in any EDR, and EtherHiding happens on a public blockchain rather than on your network. Each is addressed by a preventive control or a native audit-log hunt instead, and each is named as such rather than being quietly dropped. The one gap that is genuinely worth closing with better telemetry is WMI Event Subscription persistence, where the Windows WMI-Activity operational log carries the signal that the EDR does not.
Validation status. All four gates in section 11 are open at v0.1. Nothing in this pack has been baselined in a live estate, so the FP ratings are informed estimates, not measurements. Work gate 2 before you alert on Q4, Q6, Q8, Q15 or Q16, and note that Q1, Q3, Q5, Q7, Q9 and Q13 are all expected to baseline at zero, which makes any non-zero result during gate 2 a finding rather than noise.
Hunt Summary Ticket
TITLE: DOUBLECUP ClickFix Loader-as-a-Service, CountLoader 4.5p and DeviceManager RAT
SEVERITY: High. Active commodity loader service, user-executed, no admin rights required.
SCOPE: All Windows endpoints. All macOS endpoints. Web proxy and DNS resolver logs.
Any user of NetSuite, Odoo, HubSpot or Salesforce is in the lure target set.
HYPOTHESIS: A user reached a fake CRM login page, pasted a clipboard-staged command into
the Run dialog, and that command carved a payload out of the browser cache.
The resulting infection persists as an impostor updater scheduled task and
beacons out over HTTP or DNS tunnelling.
QUERIES: Q1 ClickFix browser-cache carve CONF high FP low
Q2 Wildcard-obfuscated PowerShell CONF high FP low
Q3 Renamed conhost with --headless CONF high FP low
Q4 PowerShell download cradle + policy bypass CONF high FP med
Q5 Impostor updater task names CONF high FP low
Q6 schtasks XML registration from a user path CONF med FP med
Q7 DeviceManager DNS-tunnel label structure CONF high FP low
Q8 DNS tunnelling volumetrics CONF med FP med
Q9 DeviceManager Python entry points CONF high FP low
Q10 Wallet / extension / Signal profiling CONF med FP low
Q11 Embeddable Python staged to user profile CONF med FP low
Q12 mshta executing a remote URL CONF high FP low
Q13 Callback to published infrastructure CONF high FP low
Q14 DNS to lure, staging and C2 domains CONF high FP low
Q15 macOS CountLoader recon burst CONF med FP med
Q16 Inno Setup /SL5 stager (triage lens only) CONF med FP high
DO FIRST: 1. Run Q13 and Q14 over maximum retention. This is the retro-hunt and it
answers "were we already hit" before anything else matters.
2. Run Q5 estate-wide. Persistence outlives the delivery event, so this
finds hosts whose infection predates your detection coverage.
3. Run Q1 and Q3. Both should return zero. Non-zero is an incident.
4. Deploy HRD-1 and HRD-2. They remove the delivery path rather than
detecting it, and neither carries compatibility risk.
FINDINGS: [ ] Q13/Q14 retro-hunt result and window covered
[ ] Q5 estate-wide persistence sweep result
[ ] Hosts with a confirmed execution (Q1 or Q3 hit)
[ ] Payload identified per host: CountLoader / DeviceManager / both
[ ] Wallet or Signal Desktop present on any affected host
[ ] Credentials entered on a lure domain, and reset status
GAPS: Reflective .NET loading, environmental keying and ctypes API calls have no
endpoint event in any EDR. EtherHiding C2 resolution happens on a public
blockchain, not on your network. WMI Event Subscription persistence needs
the Windows WMI-Activity log because Falcon has no clean event for it.
macOS coverage depends on sensor deployment percentage, which is usually
lower than Windows. Confirm it rather than assuming it.
ACTIONS: [ ] Promote Q1, Q3, Q5, Q7 to Custom IOAs in Detect
[ ] Import the section 10 CSV into Falcon IOC Management
[ ] Deploy Immediate hardening tier HRD-1 through HRD-6 and HRD-9
[ ] Enable EID 4104 script-block logging and EID 4698 task auditing
[ ] Baseline Q4, Q6, Q8, Q15, Q16 for 14 days before alerting
[ ] Set the smart-contract watch for a new global C2 write
[ ] Diary indicator expiry review for 2026-11-05
OWNER: HuntPack
VERSION: v0.1 · 2026-08-05
Changelog
Perishability note for the next revision. The DeviceManager C2 is resolved from a smart contract, so 91.92.240[.]100 can be replaced by the operator with a single blockchain transaction and no implant update. Re-check the contract before relying on that indicator. The network indicators are set to expire 2026-11-05. The behavioral queries Q1 through Q3, Q5, Q7 and Q9 carry no expiry because they describe technique, not infrastructure.
References
| Tier | Source | Used for | Accessed |
|---|---|---|---|
| TIER 1 | SOCRadar Threat Research Unit — Introducing DOUBLECUP, a ClickFix Loader Delivering CountLoader and DeviceManager RATs | Primary source. Execution chain, CountLoader 4.5p and DeviceManager internals, all indicators, vendor ATT&CK mapping. | 2026-08-05 |
| TIER 2 | The Hacker News — DOUBLECUP Uses ClickFix and Cached PNGs to Deliver CountLoader and DeviceManager RAT | Corroboration of the C2, the Telegram bot and the VS Code extension link. | 2026-08-05 |
| TIER 2 | BleepingComputer — New DOUBLECUP ClickFix service hides malware in browser cache images | Corroboration of the findstr/certutil carve, macOS LaunchAgent persistence, DNS A and TXT transport, dual-architecture macOS build. | 2026-08-05 |
| TIER 1 | Microsoft Learn — Attack surface reduction rules reference | Authoritative ASR rule GUIDs, dependencies and deployment caveats for HRD-3, HRD-4, HRD-6, HRD-11, HRD-12. | 2026-08-05 |
| TIER 2 | Chrome Enterprise policy list — DefaultClipboardSetting, ClipboardAllowedForUrls, ClipboardBlockedForUrls | Browser clipboard-write policy semantics for HRD-2. Policy name and values confirmed. Registry path not confirmed from a rendered page, and flagged as such in Playbook 1. | 2026-08-05 |
| FRAMEWORK | MITRE ATT&CK | Technique identifiers in section 6 and mitigation M-numbers in section 12. | 2026-08-05 |
Source snapshots
Every source above was saved verbatim at research time so that each atomic indicator in this pack can be mechanically traced back to the text it came from. The snapshots ship alongside this file in DOUBLECUP-ClickFix-LaaS-Hunt-sources/:
01-socradar-doublecup-primary.txt02-thehackernews-doublecup.txt03-bleepingcomputer-doublecup.txt04-microsoft-asr-rules-reference.txt05-chrome-clipboard-policy.txt
Integrity note. All five fetched sources were screened for text addressed to an automated agent, such as instructions to run commands, to fetch a further URL because "the real indicators are there", or claims of prior authorisation. None was found and no source was dropped. The SOCRadar page initially returned HTTP 403 and then a bot-check interstitial. It was retrieved on a later attempt once the interstitial cleared on its own. No bot protection was solved or bypassed.