XCSSET v40 — Xcode Supply-Chain Malware Targeting macOS Developers
Executive Summary
XCSSET is a modular macOS malware family first documented by Trend Micro in August 2020, historically distributed by injecting malicious code into Apple Xcode projects. After months of dormancy, Palo Alto Networks Unit 42 identified a resurgence beginning in mid-April 2026, with a second wave in early May 2026 that expanded the module set. Unit 42 published the full technical analysis as v40 on 2026-07-31, and it was independently corroborated by BleepingComputer, GBHackers and Cyber Security News in the first week of August 2026.
The infection vector is unchanged from XCSSET's original design and remains its most dangerous property: the actor compromises vulnerable Git repositories and injects a downloader script into benign files inside legitimate Xcode projects — dozens of applications with active user bases have been affected. When a developer clones and builds the tainted project, the loader executes under the developer's own user context, inheriting broad access without triggering conventional permission prompts. From there XCSSET infects every other local Xcode project on the machine and propagates further through shared source code — ordinary git commit and push activity becomes the worm's transport layer.
v40's architectural advance is hiding as much of its logic as possible in memory. A four-stage chain (loader → host fingerprint → staging applet → in-memory "boot" module) loads 17 specialized modules without writing a stable binary to disk. The loader is recompiled on the C2 server every few hours — Unit 42 observed roughly 8 distinct file hashes in 24 hours for functionally identical code — which is why no usable file hash IOC exists for this campaign and why this pack leans on network and behavioral detection instead. Two modules are new in v40: a Chrome hijacker that wraps the legitimate Chrome binary and abuses the Chrome DevTools Protocol (CDP) to inject JavaScript, intercept fetch/XMLHttpRequest calls, tamper with cryptocurrency wallet transactions, and open a fileless reverse shell through the browser's own console channel; and a Telegram Desktop trojanizer that downloads a malicious Telegram.app archive, wipes the legitimate install, drops an ad hoc-signed C2-controlled replacement, and kills the original process so the user transparently relaunches the trojanized client. v40 also actively impairs macOS defenses: it disables the SoftwareUpdate configuration channel, terminates CloudTelemetryService, locks the XProtect signature database with an exclusive Perl file lock, and resets the TCC database to re-trigger (and desensitize users to) permission prompts.
Defender priority: Because hashes are worthless against this loader, prioritize the network and behavioral signals in this pack over file-based detection. The three highest-value, lowest-noise hunts are: (1) DNS/network traffic to the 62 published C2 domains and 7 C2 IPs (Q1, Q2) — attacker-owned infrastructure with zero legitimate use; (2) any process retrieving the CDP helper binary via the string zw_sfp64 (Q4) — a unique attacker-chosen token; and (3) Chrome launched with --remote-debugging-port by a non-test-automation parent (Q3), which is the enablement step for the browser hijack. The shared SSL certificate thumbprint 6e480d648fa1b70612f5d198a66875e28847547d is a durable pivot across the four operator IPs even as they rotate.
Source Review & Web Hunter Notes
Six sources were fetched and snapshotted to XCSSET-v40-Hunt-sources/. Every atomic indicator shipped in section 4/10 traces to the Unit 42 primary snapshot and is cross-validated against the two independent press write-ups below.
| Tier | Source | Key finding | Carry forward |
|---|---|---|---|
| 1 · Vendor | Palo Alto Networks Unit 42 — "The Xcode Assassin Returns" (2026-07-31) | Full infection chain, 17-module list, C2 endpoint taxonomy, 62 domains, 7 IPs, SSL thumbprint, CDP helper URLs, defense-impairment behavior | Yes — primary basis for all queries and IOCs |
| 2 · Press | BleepingComputer (2026-08-04, Bill Toulas) | Confirms two-wave timeline (mid-April / early May 2026), 17-module count, XProtect/MRT/TCC/RSR impairment | Partial — corroboration only |
| 2 · Press | GBHackers (2026-08-03, Mayura Kathir) | Confirms CDP helper URLs, notes reused SSL/SSH/RDP fingerprints across campaigns, Google notified re: cross-platform protections | Partial — corroboration only |
| 2 · Press | Cyber Security News (2026-08-03, Tushar Subhra Dutta) | Confirms IP set, SSL thumbprint, "60+ domains" framing, second-wave module expansion | Partial — corroboration only |
| 1 · Catalog | MITRE ATT&CK — XCSSET (S0658) | 30 legacy technique mappings for pre-v40 XCSSET | Yes — base ATT&CK mapping in section 6 |
| 1 · Catalog | Malpedia — osx.xcsset family page | Historical reference list (2020–2022); no v40 content yet indexed | Context only |
Research notes and deliberate exclusions
- No file hashes are shipped, and none were invented. Unit 42 explicitly attributes this to per-build server-side recompilation (~8 distinct hashes per 24 hours for the loader alone). A live MalwareBazaar query for
tag:XCSSETwas attempted during this research and was blocked by a bot-check interstitial — recorded as a research gap, not a negative finding. The IOC appendix ships a labelledREPLACE_WITH_SHA256placeholder rather than a fabricated value. - Domain count discrepancy, disclosed rather than papered over: Unit 42's prose states "70+" C2 domains; the domain list explicitly enumerated in the fetched extract contains 62 distinct entries. This pack ships the 62 that are individually named and verifiable in the saved snapshot — it does not round up to "70+" or invent the remainder.
- Cross-validation: the starter IOC set supplied for this hunt (sample domains, all 7 IPs, the SSL thumbprint, and the 6 CDP helper URLs) matches the Unit 42 primary source exactly and is independently corroborated by GBHackers and Cyber Security News. No indicator in this pack came from a single uncorroborated source.
- MITRE ATT&CK S0658 reflects only legacy (pre-2026) XCSSET. The v40-specific capabilities — CDP browser hijacking, Telegram Desktop trojanization,
defaults-based fileless persistence, and the XProtect/MRT/TCC/SoftwareUpdate impairment — are not yet cataloged under S0658 as of this fetch. Section 6 flags every v40-specific mapping as analyst-inferred from the Unit 42/press write-ups rather than pulled from the ATT&CK catalog. - No prompt-injection or suspicious embedded instructions were observed in any fetched source during this research. All six pages returned ordinary threat-intelligence prose; nothing resembling an attempt to redirect this pipeline's behavior was present.
Hunt Brief & Attack Chain
Hunt hypotheses (ordered by fidelity)
| # | Hypothesis | MITRE | Telemetry | Conf |
|---|---|---|---|---|
| H1 | A host resolves one of the 62 published XCSSET v40 C2 domains | T1071.001 | DnsRequest | HIGH |
| H2 | A host connects to one of the 7 published XCSSET v40 C2 IPv4 addresses | T1071.001, T1573.001 | NetworkConnectIP4 | HIGH |
| H3 | Google Chrome is launched with --remote-debugging-port by a non-automation parent (CDP hijack enablement) | T1554, T1539 | ProcessRollup2 | MED |
| H4 | A process retrieves the CDP helper binary via the unique token zw_sfp64 | T1105 | ProcessRollup2 | HIGH |
| H5 | Xcode/xcodebuild spawns a shell that downloads and executes remote content (poisoned build-phase script) | T1195.001, T1059.004 | ProcessRollup2 | MED |
| H6 | defaults write stores a long base64-style blob in a newly created preference domain (fileless staging) | T1027.013, T1564.001 | ProcessRollup2 | MED |
| H7 | tccutil reset runs outside a normal admin/QA workflow | T1548.006 | ProcessRollup2 | MED |
| H8 | A process disables SoftwareUpdate scheduling or kills CloudTelemetryService | T1562.001 | ProcessRollup2 | MED |
| H9 | Telegram Desktop is re-signed ad hoc after a kill/relaunch sequence (trojanizer replacement) | T1554, T1036 | ProcessRollup2 | MED |
Attack chain
| Step | Behavior | Telemetry | Hunt angle |
|---|---|---|---|
| 1 · Supply-chain injection | Downloader script injected into an Xcode project file on a compromised/poisoned Git repository | — | Native hunt (repo/commit review) |
| 2 · Build-time execution | Developer clones and builds the tainted project; loader runs under the developer's own user context | ProcessRollup2 | Q5 |
| 3 · C2 registration | Loader curls the C2 /a endpoint for the next stage | ProcessRollup2, DnsRequest, NetworkConnectIP4 | Q1, Q2 |
| 4 · Host fingerprint | uname -s, whoami chained from the loader | ProcessRollup2 | Folds into Q5 |
| 5 · Staging applet | Temporary ad hoc-signed applet loads the final stage into volatile memory | ProcessRollup2 | GAP — largely in-memory |
| 6 · Boot module | Core "boot" module loads 17 specialized modules in memory | — | GAP — no discrete event |
| 7 · Defense impairment | Disables SoftwareUpdate, kills CloudTelemetryService, locks XProtect DB, resets TCC DB | ProcessRollup2 | Q7, Q8 |
| 8 · Fileless persistence | Base64-encoded staging payload written into a per-host defaults preference domain | ProcessRollup2 | Q6 |
| 9 · Chrome hijack | chrome_remote wraps Chrome, enables CDP, injects JS, intercepts fetch/XHR and wallet transactions, opens a fileless reverse shell via console.log | ProcessRollup2, NetworkConnectIP4 | Q3, Q4 |
| 10 · Telegram trojanization | Downloads a malicious Telegram.app archive, wipes the legitimate install, drops an ad hoc-signed replacement, relaunches | ProcessRollup2 | Q9 |
| 11 · Propagation | Infects other local Xcode projects (git_finder/replicator_finder) and spreads to shared repos via git commit | — | GAP — native hunt (repo review) |
| 12 · Ongoing C2 | Heartbeat (/p), exfiltration (/u), dynamic config (/w?cmd), browser-hijack events (/e) | NetworkConnectIP4, DnsRequest | Q1, Q2 |
Consolidated IOC Table
76 atomic indicators — 62 domains, 7 IPv4, 6 CDP helper URLs, 1 SSL certificate thumbprint. All published by Unit 42 (2026-07-31) and cross-validated against GBHackers and Cyber Security News. No file hashes are published for this campaign (see section 2) — that row is included with (none published) per the pipeline convention rather than omitted.
| Type | Value | Conf | Action | Context |
|---|---|---|---|---|
| SHA256 / MD5 | (none published) | — | — | Loader recompiled server-side every few hours (~8 hashes/24h); no stable hash IOC exists for this campaign |
| IPv4 | 91.108.106.229 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| IPv4 | 95.142.35.34 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| IPv4 | 95.142.35.206 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| IPv4 | 95.142.37.159 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| IPv4 | 151.243.109.188 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| IPv4 | 178.208.92.129 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| IPv4 | 178.208.92.168 | MEDIUM | detect | C2 operator IP; shares SSL thumbprint below |
| TLS cert thumbprint | 6e480d648fa1b70612f5d198a66875e28847547d | HIGH | pivot | Shared across all 4 operator IPs above; durable pivot across IP rotation (not a native Falcon IOC-Management type) |
| URL | hxxps://amzndev[.]in/d/zw_sfp64 | HIGH | detect | Chrome CDP helper binary download |
| URL | hxxps://amzndev[.]ru/d/zw_sfp64 | HIGH | detect | Chrome CDP helper binary download |
| URL | hxxps://googlenets[.]ru/d/zw_sfp64 | HIGH | detect | Chrome CDP helper binary download |
| URL | hxxps://netcdndev[.]in/d/zw_sfp64 | HIGH | detect | Chrome CDP helper binary download |
| URL | hxxps://whitead[.]in/d/zw_sfp64 | HIGH | detect | Chrome CDP helper binary download |
| URL | hxxps://whiteads[.]ru/d/zw_sfp64 | HIGH | detect | Chrome CDP helper binary download |
| Domain | accapple.ru, adschecks.ru, adsmobi.ru, adsmorein.in, amdcdn.ru, amzndev.in, amzndev.ru, amznprod.in, applecdn.ru, appledisk.ru, appledns.ru, applehosts.ru, appletime.in, bulksec.ru, cdnamz.in, cdnamz.ru, cdnapple.in, cdnatapple.ru, cdnroute.ru, checkcdn.ru, chromeads.ru, cnmag.ru, devnetaps.ru, dnsapple.ru, dnsrelays.ru, explorecdn.ru, fiddlejoy.ru, figmacat.ru, figmanets.in, funchats.ru, gironetcdn.ru, goalmate.ru, googlenets.ru, greencn.ru, icloudsnet.ru, imails.ru, legalads.in, littleads.in, littledns.ru, maganet.ru, mindelgate.ru, netapsdev.ru, netcdnads.in, netcdnamz.ru, netcdndev.in, netcorps.ru, netsprot.in, netsproto.in, networkads.in, rigacdn.in, rigmajoys.in, rigmanet.ru, rigmanets.in, sahusuzuki.in, stuffdns.in, testjoys.ru, timewebnet.in, vigmanet.ru, whitead.in, whiteads.ru, wincdn.ru, windsecure.ru — all 62: HIGH confidence, detect action, campaign C2 infrastructure (Unit 42, cross-validated) | |||
Perishability: the 7 IPv4 addresses are rated medium confidence and carry the shortest expiry in this pack (30 days) — commodity/bulletproof hosting reassigns fast. The SSL thumbprint is the more durable pivot if the IPs rotate but the operators reuse certificate material, as GBHackers independently observed across campaign waves.
Affected Surface & Telemetry Matrix
| Surface | Required telemetry | Priority | Gap risk |
|---|---|---|---|
| macOS developer workstations running Xcode | ProcessRollup2, SyntheticProcessRollup2 | CRITICAL | Low — standard Falcon macOS sensor coverage |
| Google Chrome browser processes | ProcessRollup2, NetworkConnectIP4 | CRITICAL | Medium — CDP is a local-loopback interface; confirm your sensor captures the initiating process's full command line |
| Telegram Desktop installations | ProcessRollup2 | HIGH | Medium — file-write telemetry for macOS app-bundle replacement is not confirmed in the standard Falcon macOS event set; see gap note in section 15 |
| Shared Git repositories the developer has push access to | — | CRITICAL | High — propagation vector has no Falcon telemetry; requires source-control hygiene controls (section 7) |
| DNS and outbound network (fleet-wide) | DnsRequest, SuspiciousDnsRequest, NetworkConnectIP4 | HIGH | Low |
| macOS security stack (XProtect, MRT, TCC, SoftwareUpdate) | ProcessRollup2 (command-line based) | HIGH | Medium — no discrete "security tool disabled" event on macOS; inferred from command-line patterns only |
ATT&CK Mapping
Legacy techniques are from the MITRE ATT&CK S0658 catalog. Rows marked (v40 — analyst-mapped) describe v40-specific capabilities documented by Unit 42/press but not yet reflected in the S0658 catalog as of this pack's research date.
| Tactic | Technique | Observed behavior | Query / control |
|---|---|---|---|
| Initial Access | T1195.001 — Compromise Software Dependencies and Development Tools | Downloader script injected into Xcode project files on poisoned Git repositories | Q5 · dependency/repo scanning |
| Execution | T1059.004 — Unix Shell | Loader script runs shell commands under the developer's context at build time | Q5 |
| Execution | T1204.002 — Malicious File | Developer unknowingly builds the tainted Xcode project, triggering execution | Q5 |
| Persistence | T1543.004 — Launch Daemon | Legacy XCSSET persistence mechanism, retained per S0658 | GAP |
| Persistence | T1546.004 — Unix Shell Configuration Modification | Modified project.pbxproj build-phase scripts | Q5 |
| Persistence | T1027.013 / T1564.001 (v40 — analyst-mapped) | Base64-encoded staging payload written into a per-host defaults preference domain | Q6 |
| Defense Evasion | T1548.006 — TCC Manipulation | TCC database reset to re-trigger and desensitize permission prompts | Q7 |
| Defense Evasion | T1553.001 — Gatekeeper Bypass | Ad hoc-signed staging applet and trojanized Telegram.app | Native hunt (codesign audit, section 7) |
| Defense Evasion | T1562.001 (v40 — analyst-mapped, not in S0658) | Disables SoftwareUpdate, kills CloudTelemetryService, locks XProtect DB, resets MRT-relevant state | Q8 |
| Defense Evasion | T1036 — Masquerading | chrome_remote wraps the legitimate Chrome binary; trojanized Telegram keeps the original name/icon | Q3, Q9 |
| Defense Evasion | T1497.003 — Time Based Checks | Stats module performs CPU/hardware checks for VM evasion | GAP |
| Discovery | T1082 — System Information Discovery | uname -s host fingerprinting | Folds into Q5 |
| Discovery | T1518.001 — Security Software Discovery | Checks XProtect/MRT presence prior to impairment | Q8 (context) |
| Discovery | T1614.001 — System Language Discovery | Legacy XCSSET capability, retained per S0658 | GAP |
| Collection | T1113 — Screen Capture | Legacy XCSSET screenshot capability | GAP — no discrete macOS screen-capture event |
| Collection | T1056.002 — GUI Input Capture | Legacy keylogging capability | GAP |
| Collection | T1005 / T1560 — Data from Local System / Archive Collected Data | clipboard_v2, data_folders_finder, notes_app modules stage local data for exfil | GAP — no confirmed discrete file-read event |
| Credential Access / Collection | T1539 — Steal Web Session Cookie (v40 CDP context) | chrome_remote harvests cookies, autofill data and crypto-wallet transactions via CDP | Q3, Q4 |
| Command and Control | T1071.001 — Web Protocols | HTTPS beaconing to /a /s /l /u /p /w /e C2 endpoints | Q1, Q2 |
| Command and Control | T1573.001 — Symmetric Cryptography | AES-256-CBC dual-key (inbound/outbound) communications | Behavioral context for Q1/Q2 |
| Command and Control | T1105 — Ingress Tool Transfer | CDP helper binary and module downloads | Q4 |
| Command and Control | (v40 — analyst-mapped, no formal sub-technique) | Fileless reverse shell via Chrome DevTools console.log channel | Q3 |
| Impact | T1486 — Data Encrypted for Impact | Legacy XCSSET ransomware capability per S0658; not confirmed active in v40 press coverage | GAP |
| Lateral Movement | T1195.001 (repeat) | Propagation to other local Xcode projects and shared repos via git commit | GAP — native hunt only |
Native Audit-Log Hunts
Checks that do not require Falcon telemetry — run these in parallel, especially for the propagation vector and in-memory stages Falcon cannot see directly.
- Git repository review — diff-review recently pushed commits to Xcode projects for unexpected changes to
project.pbxprojRun Script build phases; treat any unfamiliar build-phase script as hostile until proven otherwise, especially in forked or third-party-contributed projects. - macOS unified log (
log show --predicate) — search fordefaults writeevents creating unfamiliar preference domains,tccutil resetinvocations, and Perl processes touching paths under/Library/Apple/System/Library/CoreServices/XProtect.bundle. - Dependency/supply-chain scanning — scan cloned or forked Xcode projects for hidden or unfamiliar build phases before opening them in Xcode; treat this as mandatory for any project pulled from outside your own org.
- Chrome integrity audit — compare the installed Chrome binary's hash against Google's published release hash; review LaunchAgents/LaunchDaemons and any wrapper scripts around
/Applications/Google Chrome.appfor tampering. - Telegram Desktop integrity audit — compare the installed
Telegram.appbundle's code signature against the official Telegram Team ID. An ad hoc signature (codesign -dvshowing noAuthority=chain to a real Team ID) is a strong indicator of the trojanizer. - MDM/Jamf fleet sweep — inventory ad hoc-signed applications bypassing Gatekeeper across the managed developer fleet; cross-reference against your approved-software baseline.
CrowdStrike LogScale CQL Hunt Queries
The Falcon macOS sensor emits the same core event taxonomy used below (ProcessRollup2/SyntheticProcessRollup2, NetworkConnectIP4, DnsRequest) as Windows/Linux. macOS has no registry, so persistence is hunted via CommandLine patterns (defaults, tccutil) rather than RegGenericValueUpdate.
Looks for: resolution of any of the 62 published C2 domains. FP: none expected — attacker-registered infrastructure with no legitimate use.
// HUNT: DNS resolution of published XCSSET v40 C2 domains // MITRE: T1071.001 (Web Protocols), T1568 (Dynamic Resolution) // CONF: high | FP: low | COST: low // REQUIRES: DnsRequest // FALSE POSITIVES: none expected — domains are attacker-registered infrastructure with no legitimate use #event_simpleName=/^(DnsRequest|SuspiciousDnsRequest)$/ | in(field=DomainName, values=["accapple.ru","adschecks.ru","adsmobi.ru","adsmorein.in","amdcdn.ru","amzndev.in","amzndev.ru","amznprod.in","applecdn.ru","appledisk.ru","appledns.ru","applehosts.ru","appletime.in","bulksec.ru","cdnamz.in","cdnamz.ru","cdnapple.in","cdnatapple.ru","cdnroute.ru","checkcdn.ru","chromeads.ru","cnmag.ru","devnetaps.ru","dnsapple.ru","dnsrelays.ru","explorecdn.ru","fiddlejoy.ru","figmacat.ru","figmanets.in","funchats.ru","gironetcdn.ru","goalmate.ru","googlenets.ru","greencn.ru","icloudsnet.ru","imails.ru","legalads.in","littleads.in","littledns.ru","maganet.ru","mindelgate.ru","netapsdev.ru","netcdnads.in","netcdnamz.ru","netcdndev.in","netcorps.ru","netsprot.in","netsproto.in","networkads.in","rigacdn.in","rigmajoys.in","rigmanet.ru","rigmanets.in","sahusuzuki.in","stuffdns.in","testjoys.ru","timewebnet.in","vigmanet.ru","whitead.in","whiteads.ru","wincdn.ru","windsecure.ru"]) | table([ComputerName, UserName, DomainName, ContextBaseFileName, ContextProcessId])
Looks for: outbound connections to the 7 published operator IPs sharing SSL thumbprint 6e480d648fa1b70612f5d198a66875e28847547d. FP: none expected — dedicated campaign hosting.
// HUNT: Outbound connection to published XCSSET v40 C2 IPv4 infrastructure // MITRE: T1071.001, T1573.001 (Symmetric Cryptography) // CONF: high | FP: low | COST: low // REQUIRES: NetworkConnectIP4 // FALSE POSITIVES: none expected — hosting is dedicated to this campaign's operators #event_simpleName=/^NetworkConnectIP4$/ | in(field=RemoteAddressIP4, values=["91.108.106.229","95.142.35.34","95.142.35.206","95.142.37.159","151.243.109.188","178.208.92.129","178.208.92.168"]) | table([ComputerName, UserName, ContextBaseFileName, RemoteAddressIP4, RemotePort])
Looks for: the enablement step for the Chrome CDP hijack. FP: QA/automation engineers and Selenium/Puppeteer/Playwright test harnesses legitimately launch Chrome this way — exclude your CI/test-runner parents before alerting.
// HUNT: Google Chrome launched with the remote-debugging-port flag (CDP hijack enablement) // MITRE: T1554 (Compromise Host Software Binary), T1539 (Steal Web Session Cookie) — v40 analyst-mapped, CDP abuse has no discrete ATT&CK sub-technique yet // CONF: medium | FP: medium | COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: QA/automation engineers and Selenium/Puppeteer/Playwright test harnesses legitimately launch Chrome with --remote-debugging-port // TUNING: exclude known CI/test-runner parent processes (e.g. node, python running pytest/selenium) by ParentBaseFileName before alerting #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^Google Chrome$/i | CommandLine=/--remote-debugging-port/i | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: the unique attacker-chosen download token zw_sfp64, published across 6 domains. FP: none expected.
// HUNT: Process retrieving the XCSSET v40 Chrome CDP helper binary (zw_sfp64) // MITRE: T1105 (Ingress Tool Transfer) // CONF: high | FP: low | COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: none expected — zw_sfp64 is a unique attacker-chosen filename with no legitimate use #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/zw_sfp64/i | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: the poisoned Xcode build-phase step itself. FP: legitimate CocoaPods/Carthage/SPM build-phase scripts and CI pipelines (fastlane, GitHub Actions runners) also invoke curl/bash from Xcode build steps — prioritize hits whose downloaded URL matches Q1/Q2 infrastructure.
// HUNT: Xcode or xcodebuild spawning a shell that downloads and executes content (poisoned build-phase script) // MITRE: T1195.001 (Compromise Software Dependencies and Development Tools), T1059.004 (Unix Shell) // CONF: medium | FP: medium | COST: medium // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: legitimate CocoaPods/Carthage/SPM build-phase scripts and CI pipelines (fastlane, GitHub Actions runners) also invoke curl/bash from Xcode build steps // TUNING: exclude your known CI runner identities and pinned dependency-manager scripts by ParentBaseFileName/CommandLine before alerting; prioritize hits where the downloaded URL matches Q1/Q2 infrastructure #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ParentBaseFileName=/^(xcodebuild|Xcode)$/i | CommandLine=/(curl|wget)\s/i | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
defaults write fileless staging
Looks for: a long base64-style value written via defaults write — the v40 fileless persistence mechanism. FP: legitimate software (browsers, Office apps, MDM agents) routinely write long base64/plist blobs to preference domains — treat this as a lead requiring correlation, never a standalone alert.
// HUNT: defaults(1) writing a base64-style payload into a newly created preference domain // MITRE: T1027.013 (Encrypted/Encoded File), T1564.001 (Hidden Files and Directories) // CONF: medium | FP: high | COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: legitimate software (browsers, Office apps, MDM agents) write long base64/plist blobs to defaults domains routinely // TUNING: scope to defaults invocations whose parent is NOT a known Apple/MDM/browser process, and whose value argument exceeds ~200 chars; treat as a lead requiring correlation with Q1/Q2/Q4, never a standalone alert #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^defaults$/i | CommandLine=/write/i | CommandLine=/[A-Za-z0-9+\/=]{200,}/ | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
tccutil reset outside normal admin/QA workflow
Looks for: resetting the TCC permission database, which v40 abuses to re-trigger and desensitize permission prompts. FP: developers/QA legitimately run tccutil reset when testing permission prompts; MDM remediation scripts may also invoke it.
// HUNT: tccutil reset invoked outside of normal user/admin workflow // MITRE: T1548.006 (TCC Manipulation) // CONF: medium | FP: medium | COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: developers/QA legitimately run tccutil reset when testing permission prompts; MDM remediation scripts may also invoke it // TUNING: exclude your MDM/Jamf remediation script identity and known developer/QA host groups; prioritize hits with no interactive UserName session at the time #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | FileName=/^tccutil$/i | CommandLine=/reset/i | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: commands that disable macOS security telemetry, update checks, or XProtect. FP: MDM/Jamf policies and Apple's own installer occasionally toggle SoftwareUpdate scheduling; rare legitimate admin scripts kill telemetry daemons during troubleshooting.
// HUNT: Commands disabling macOS security telemetry, update checks, or XProtect (v40 defense impairment) // MITRE: T1562.001 (Disable or Modify Tools) — v40 analyst-mapped; not in the legacy S0658 catalog // CONF: medium | FP: medium | COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: MDM/Jamf policies and Apple's own installer occasionally toggle SoftwareUpdate scheduling; rare legitimate admin scripts kill telemetry daemons during troubleshooting // TUNING: exclude your MDM remediation identity and scope to processes with no code-signing chain to Apple or your MDM vendor #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/(CloudTelemetryService|softwareupdate --schedule off|com\.apple\.SoftwareUpdate)/i | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
Looks for: the ad hoc codesign step v40 performs on the replacement Telegram.app. FP: legitimate Telegram auto-update also kills and relaunches the app; developers ad hoc-sign their own builds during testing — correlate with Q1/Q2/Q4 infrastructure before escalating.
// HUNT: Telegram Desktop replaced or re-signed with an ad hoc signature after a kill/relaunch sequence // MITRE: T1554 (Compromise Host Software Binary), T1036 (Masquerading) // CONF: medium | FP: medium | COST: low // REQUIRES: ProcessRollup2, SyntheticProcessRollup2 // FALSE POSITIVES: legitimate Telegram auto-update also kills and relaunches the app; developers ad hoc-sign their own builds during testing // TUNING: correlate with a preceding download from Q1/Q2/Q4 infrastructure; flag only when codesign shows no valid Telegram FZ LLC Team ID #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/codesign/i | CommandLine=/Telegram/i | table([ComputerName, UserName, ParentBaseFileName, FileName, CommandLine])
CrowdStrike Custom IOA Recommendations
Five queries are strong enough to promote from hunt to Custom IOA. Q5, Q6, Q7 and Q9 carry tunable false-positive surface and stay investigate-only until baselined in your environment.
| IOA name | Type | Pattern | Action | Exclusions |
|---|---|---|---|---|
| XCSSET v40 — C2 domain resolution | DNS Request | Domain in the published 62-entry list | Block & alert | None recommended |
| XCSSET v40 — C2 IPv4 connection | Network Connection | RemoteAddressIP4 in the published 7-entry list | Alert (detect) | Re-validate before Block — IPs are volatile |
| XCSSET v40 — Chrome CDP hijack enablement | Process Creation | Image Google Chrome · CommandLine contains --remote-debugging-port | Alert (detect) | CI/test-automation parent processes (Selenium/Puppeteer/Playwright) |
| XCSSET v40 — CDP helper binary download | Process Creation | CommandLine contains zw_sfp64 | Block & alert | None — unique attacker-chosen token |
| XCSSET v40 — Defense impairment command | Process Creation | CommandLine matches CloudTelemetryService kill / SoftwareUpdate disable / XProtect path reference | Alert (detect) | MDM/Jamf remediation service identity |
Deployment path: Endpoint security → Custom IOA rule groups → create a macOS Process Creation / DNS / Network group, add the five rules above in Monitor mode first. The C2 domain and CDP helper rules are safe to promote directly to Block; the Chrome CDP and defense-impairment rules need at least one week of baseline against your developer and MDM populations before enforcement.
Alert Triage Package — C2 Communication (Q1 + Q2)
Scheduled Search name: HUNT: XCSSET v40 - C2 Domain/IP Communication
Scheduled Search description: Detects DNS resolution or outbound connection to infrastructure published for the XCSSET v40 macOS supply-chain campaign (62 domains, 7 IPv4 addresses sharing SSL thumbprint 6e480d648fa1b70612f5d198a66875e28847547d). A hit indicates an infected Xcode-built host has established or is attempting C2 communication.
MITRE: T1071.001 (Web Protocols), T1573.001 (Symmetric Cryptography) · Tactics: Command and Control · Priority: HIGH (escalate immediately if the resolving/connecting process is Xcode, xcodebuild, a staging applet, or Chrome) · FP Sources: none expected — dedicated attacker infrastructure.
Subject: 🚨 HUNT ALERT 🚨 — XCSSET v40 C2 Communication Detected (Possible Supply-Chain Compromise)
Body: A host resolved or connected to published XCSSET v40 C2 infrastructure. This campaign spreads via poisoned Xcode projects — the initiating process and any recent Xcode/xcodebuild build activity on this host are the first things to check. Note: DNS resolution alone does not confirm compromise, but any correlated NetworkConnectIP4 hit does. Check ContextBaseFileName for the initiating process, then pivot to Q4/Q6 on the same host.
Investigation checklist:
- Identify the initiating process — check
ContextBaseFileName/ContextProcessIdon the DNS or network event. - Check whether the host has Xcode installed and whether a build occurred in the last 24 hours (correlate with Q5 hits).
- Run Q4 (CDP helper download) and Q6 (defaults staging) on the same host and timeframe.
- Check for Chrome processes with
--remote-debugging-port(Q3) on the same host. - Identify which local Xcode projects exist on the host and whether any were recently cloned from an external/forked source.
- Isolate if: a NetworkConnectIP4 hit is confirmed (not just DNS) and any of Q3/Q4/Q6 also fire on the same host.
Pivot queries:
>> YOU NEED: ComputerName (from the alert) >> FILL IN: ComputerName="REPLACE_WITH_HOSTNAME"
// Host-scoped: all XCSSET v40-related activity on the affected host, last 7d #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2|DnsRequest|NetworkConnectIP4)$/ | ComputerName="REPLACE_WITH_HOSTNAME" | (CommandLine=/zw_sfp64/i or CommandLine=/(CloudTelemetryService|softwareupdate --schedule off)/i or FileName=/^defaults$/i or FileName=/^Google Chrome$/i) | table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine]) // Environment-wide: hosts touching XCSSET v40 infrastructure, ranked by hit count #event_simpleName=/^(DnsRequest|NetworkConnectIP4)$/ | in(field=DomainName, values=["accapple.ru","googlenets.ru","whitead.in"]) or in(field=RemoteAddressIP4, values=["91.108.106.229","95.142.35.34"]) | groupBy([ComputerName], function=count(as=Hits), limit=500) | sort(Hits, order=desc)
Alert Triage Package — Chrome CDP Hijack (Q3 + Q4)
Scheduled Search name: HUNT: XCSSET v40 - Chrome CDP Hijack Enablement
Scheduled Search description: Detects the browser-hijack enablement sequence introduced in XCSSET v40 — Chrome launched with a remote-debugging flag, or a process retrieving the campaign's CDP helper binary via the unique token zw_sfp64. Used to catch credential, cookie and crypto-wallet-transaction interception before it reaches the exfiltration stage.
MITRE: T1554 (Compromise Host Software Binary), T1539 (Steal Web Session Cookie), T1105 (Ingress Tool Transfer) · Tactics: Credential Access, Command and Control · Priority: HIGH (escalate immediately if the zw_sfp64 download is confirmed — that variant has no legitimate explanation) · FP Sources: Selenium/Puppeteer/Playwright test automation, CI browser-testing pipelines.
Subject: ⚠️ HUNT ALERT ⚠️ — Chrome CDP Hijack Enablement Detected (Possible Browser Session Theft)
Body: Chrome was launched with debugging enabled, or a process downloaded the XCSSET v40 CDP helper binary. If the CDP helper download is confirmed, treat this as active compromise — the helper connects to the exposed CDP port and can harvest cookies, autofill data and crypto-wallet transactions in real time. Check the parent process first: a test-automation framework (Selenium/Puppeteer/pytest) is likely benign; anything else, especially a process also seen in the C2 alert above, is high priority.
Investigation checklist:
- Check
ParentBaseFileNamefor the Chrome launch — CI/test-runner parent = likely benign; anything else = escalate. - Check whether
zw_sfp64appears anywhere in the same host's recent CommandLine history (Q4). - Check for a concurrent or preceding hit on Q1/Q2 (C2 infrastructure) on the same host.
- If confirmed, treat all credentials and session cookies stored in that Chrome profile as compromised.
- Check for crypto-wallet browser extensions on the host — CDP hijack specifically targets wallet transaction data.
- Isolate if: zw_sfp64 download is confirmed, or the CDP flag hit correlates with a Q1/Q2 C2 hit on the same host.
Pivot queries:
>> YOU NEED: ComputerName (from the alert) Alert timestamp (from Step 1 — set LogScale window to ±30 min) >> FILL IN: ComputerName="REPLACE_WITH_HOSTNAME"
// Host-scoped: Chrome process tree and CDP helper activity around the alert #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | ComputerName="REPLACE_WITH_HOSTNAME" | (FileName=/^Google Chrome$/i or CommandLine=/zw_sfp64/i) | table([@timestamp, ComputerName, UserName, ParentBaseFileName, FileName, CommandLine]) // Environment-wide: frequency of zw_sfp64 helper retrieval across the fleet #event_simpleName=/^(ProcessRollup2|SyntheticProcessRollup2)$/ | CommandLine=/zw_sfp64/i | groupBy([ComputerName], function=count(as=Hits), limit=500) | sort(Hits, order=desc)
Investigate-only — Defense Impairment (Q8)
No full alert email; treat as an escalation lead. If Q8 fires, immediately cross-check the same host against Q1/Q2/Q4 — a lone defense-impairment hit with no corroborating C2 activity is more likely a legitimate MDM remediation script and should be triaged, not escalated, until corroborated.
Machine-Readable IOC Appendix
type,value,action,severity,expiration,description,tags domain,accapple.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,adschecks.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,adsmobi.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,adsmorein.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,amdcdn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,amzndev.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure and CDP helper host,campaign:XCSSET-v40 domain,amzndev.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure and CDP helper host,campaign:XCSSET-v40 domain,amznprod.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,applecdn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,appledisk.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,appledns.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,applehosts.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,appletime.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,bulksec.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,cdnamz.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,cdnamz.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,cdnapple.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,cdnatapple.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,cdnroute.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,checkcdn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,chromeads.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,cnmag.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,devnetaps.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,dnsapple.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,dnsrelays.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,explorecdn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,fiddlejoy.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,figmacat.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,figmanets.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,funchats.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,gironetcdn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,goalmate.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,googlenets.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure and CDP helper host,campaign:XCSSET-v40 domain,greencn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,icloudsnet.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,imails.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,legalads.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,littleads.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,littledns.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,maganet.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,mindelgate.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,netapsdev.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,netcdnads.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,netcdnamz.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,netcdndev.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure and CDP helper host,campaign:XCSSET-v40 domain,netcorps.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,netsprot.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,netsproto.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,networkads.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,rigacdn.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,rigmajoys.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,rigmanet.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,rigmanets.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,sahusuzuki.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,stuffdns.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,testjoys.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,timewebnet.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,vigmanet.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,whitead.in,detect,high,2026-11-07,XCSSET v40 C2 infrastructure and CDP helper host,campaign:XCSSET-v40 domain,whiteads.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure and CDP helper host,campaign:XCSSET-v40 domain,wincdn.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 domain,windsecure.ru,detect,high,2026-11-07,XCSSET v40 C2 infrastructure,campaign:XCSSET-v40 ipv4,91.108.106.229,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40 ipv4,95.142.35.34,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40 ipv4,95.142.35.206,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40 ipv4,95.142.37.159,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40 ipv4,151.243.109.188,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40 ipv4,178.208.92.129,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40 ipv4,178.208.92.168,detect,high,2026-09-08,XCSSET v40 C2 operator IP,campaign:XCSSET-v40
# XCSSET v40 behavioral signatures (no atomic IOC form) # C2 endpoint taxonomy (Unit 42) GET /d/<name> binary download GET /a loader retrieval GET /s/<module> module retrieval POST /l status/log reporting POST /u file exfiltration POST /p heartbeat GET /w?cmd dynamic configuration POST /e browser-hijack events # Chrome CDP hijack Unique download token: zw_sfp64 Helper binary: chrome_remote Chrome launched with --remote-debugging-port by a non-automation parent Fileless reverse shell channel: marked console.log events over the CDP WebSocket # Fileless persistence defaults write into a per-host-generated preference domain, base64-encoded payload # Defense impairment Perl process taking an exclusive file lock on the XProtect signature database killall / pkill targeting CloudTelemetryService softwareupdate --schedule off / com.apple.SoftwareUpdate preference writes tccutil reset invoked outside interactive admin context # Telegram trojanizer Download of a Telegram.app replacement archive, followed by kill + ad hoc codesign + relaunch # TLS pivot (durable across IP rotation) SSL certificate thumbprint: 6e480d648fa1b70612f5d198a66875e28847547d # 17 named modules (Unit 42) boot, stats, clipboard_v2, payloader, replicator_finder, git_finder, zip_infect_finder, data_folders_finder, firefox_data, notes_app, settings_app, finder_app, persist, browser_remote, safari_remote, chrome_remote, tdesktop
https://amzndev.in/d/zw_sfp64 https://amzndev.ru/d/zw_sfp64 https://googlenets.ru/d/zw_sfp64 https://netcdndev.in/d/zw_sfp64 https://whitead.in/d/zw_sfp64 https://whiteads.ru/d/zw_sfp64
Family: XCSSET (first documented Trend Micro, August 2020) Version: v40 (mid-April 2026 wave, expanded early May 2026 wave) Primary vector: Poisoned/compromised Xcode projects on GitHub New modules: Chrome hijacker (chrome_remote, via CDP), Telegram Desktop trojanizer (tdesktop) Vendor source: Palo Alto Networks Unit 42 (2026-07-31) MITRE ATT&CK: S0658 (legacy catalog entry; v40 capabilities not yet indexed)
# No SHA256/MD5/SHA1 file hashes have been published for XCSSET v40 by any # vendor as of this pack's research date (2026-08-09). Unit 42 explicitly # attributes this to server-side recompilation of the loader every few # hours (~8 distinct hashes per 24 hours for functionally identical code). # A live MalwareBazaar tag:XCSSET query was attempted and blocked by a # bot-check interstitial (research gap, not a negative result). sha256,REPLACE_WITH_SHA256,detect,high,2027-08-09,XCSSET v40 sample — populate only from your own detonation/VT lookup,campaign:XCSSET-v40 # Do not invent or derive a hash value. An unsourced hash is not an indicator.
# Before building any Xcode project pulled from outside your own org:
[ ] Diff project.pbxproj against the last known-good commit for new/modified
Run Script build phases
[ ] Confirm ENABLE_USER_SCRIPT_SANDBOXING is set for all build-phase scripts
(Xcode 15+)
[ ] Review any curl/wget/base64/eval usage inside build-phase shell scripts
[ ] Confirm the repo's recent commit history has no unexplained force-pushes
or unsigned commits from unfamiliar authors
[ ] Cross-reference any embedded download URL against the domain/IP list in
the Falcon IOC Management CSV above
[ ] Run the endpoint sweep script in Playbook 3 (section 13) after any build
from an unfamiliar or forked repository
Import note: Falcon IOC Management natively accepts sha256, md5, sha1, domain, ipv4 and ipv6. The CDP helper URLs are routed to your proxy/SWG rather than the Falcon IOC importer. The SSL certificate thumbprint is not a native Falcon IOC type — use it as a manual pivot/enrichment value against any TLS-inspection or JA3-capable network tooling you operate.
Detection Validation Gates
Gate 1 — Telemetry ready
- Confirm the macOS Falcon sensor is deployed and reporting
ProcessRollup2/SyntheticProcessRollup2for your Xcode developer population — this population is frequently under-sampled in fleet-wide sensor policy audits. - Confirm
DnsRequestandNetworkConnectIP4are populated for macOS endpoints in your tenant; some macOS sensor policies reduce network telemetry by default. - Confirm your sensor policy captures full
CommandLinefor macOS process events — Q6, Q7, Q8 and Q9 depend entirely on command-line visibility since macOS has no registry-equivalent event.
Gate 2 — Benign baseline
- Run Q3, Q5, Q6, Q7, Q8 and Q9 over 7 days with no exclusions and record hit counts against your developer and MDM populations before promoting any to alert.
- Q1, Q2 and Q4 should return zero in a clean environment. A non-zero baseline is itself a finding — investigate before assuming false positives.
Gate 3 — Positive tests
- In an isolated VM, launch Chrome with
--remote-debugging-port=9222and confirm Q3 fires; close it afterward. - Run
defaults write com.example.test.$(uuidgen) TestKey "$(head -c 300 /dev/urandom | base64)"and confirm Q6 fires; rundefaults deleteto clean up. - Run
tccutil reset All com.example.testagainst a harmless bundle ID and confirm Q7 fires.
Gate 4 — Promotion criteria
- Promote Q1, Q2 and Q4 to Custom IOA Block immediately — zero expected legitimate traffic.
- Promote Q3 and Q8 to Block only after 7 days at a confirmed, explainable FP rate against your CI/automation and MDM populations.
- Re-validate the 7 IPv4 indicators before any network block — they carry the shortest expiry and the highest reassignment risk in this pack.
Hardening — Tiered
- Enable Xcode User Script Sandboxing fleet-wide (MITRE M1038 · Apple Xcode 15+ built-in mitigation). This confines Run Script build phases to their declared inputs/outputs, directly blocking the class of attack this campaign uses to inject a downloader at build time.
- Import the section 10 CSV into Falcon IOC Management — domains and IPs at detect. Route the CDP helper URLs to your proxy/SWG instead.
- Hunt Q1, Q2 and Q4 across your full retention window immediately. All three are zero-false-positive and retrospective; run them before any hardening lands.
- Brief your Xcode developer population on the poisoned-project pattern: never build an unfamiliar or forked Xcode project without first running the provenance checklist in section 10.
- Enforce Gatekeeper and disable "Allow apps from Anywhere" via MDM (MITRE M1038 · Apple Platform Security Guide, System Settings > Privacy & Security > Security policy). Blocks the ad hoc-signed staging applet and trojanized Telegram replacement from launching without an explicit override.
- Reconcile installed Chrome and Telegram Desktop copies against vendor-notarized releases (MITRE M1045 · code-signing verification). Flag any install whose
codesign -dvoutput shows no valid Team ID chain. - Lock TCC.db from user-level reset via MDM configuration profile (MITRE M1047 · Apple Platform Security Guide, TCC section). Reduces v40's ability to silently re-arm permission prompts as a persistence/evasion signal.
- Restrict outbound access for developer endpoints to a proxy with TLS inspection and category-based blocking (MITRE M1037). The campaign relies on direct HTTPS to freshly registered .ru/.in domains; an authenticated egress proxy denies the unproxied direct-connect path.
- Stand up automated Xcode-project dependency/build-phase scanning in CI before any external or forked project is opened locally. ⚠ best-practice, no formal benchmark — cite NIST SP 800-218 (Secure Software Development Framework) as the closest formal authority.
- Require signed Git commits and mandatory code review for changes to
project.pbxprojbuild phases across your development org. ⚠ best-practice, no formal benchmark — this directly targets XCSSET's shared-source propagation vector. - Remove local administrator rights from developer endpoints where feasible (MITRE M1026). Developers are this campaign's highest-value target and typically hold the broadest local privileges.
- Establish an org-wide software provenance policy for Chrome, Telegram and any Electron/browser-adjacent app, with hash-pinned or notarization-verified distribution channels.
Deployable Playbooks
1 — Enable Xcode User Script Sandboxing fleet-wide
Prerequisites: Xcode 15 or later on managed developer endpoints. Reboot required: No — takes effect on next Xcode build.
#!/bin/bash # Enforces sandboxed Run Script build phases at the Xcode application level. defaults write com.apple.dt.Xcode IDEBuildOperationDefaultBuildSetting_ENABLE_USER_SCRIPT_SANDBOXING -bool YES # Verify defaults read com.apple.dt.Xcode IDEBuildOperationDefaultBuildSetting_ENABLE_USER_SCRIPT_SANDBOXING
Rollback: defaults delete com.apple.dt.Xcode IDEBuildOperationDefaultBuildSetting_ENABLE_USER_SCRIPT_SANDBOXING
Some legacy build-phase scripts that reach outside their declared inputs/outputs (uncommon but not unheard of) will fail under sandboxing. Pilot on one developer ring before fleet-wide deployment.
2 — MDM configuration profile: enforce Gatekeeper + notarization
Prerequisites: MDM (Jamf Pro or equivalent) managing the target fleet. Reboot required: No — a re-login may be needed for the policy to take effect in already-running sessions.
<!-- Deploy via Jamf Pro (or your MDM) as a Custom Configuration Profile,
PayloadType com.apple.systempolicy.control -->
<dict>
<key>PayloadType</key>
<string>com.apple.systempolicy.control</string>
<key>EnableAssessment</key>
<true/>
<key>AllowIdentifiedDevelopers</key>
<true/>
<key>DisableOverride</key>
<true/>
</dict>
# Verify (on target endpoint)
spctl --status
Rollback: Remove/unassign the configuration profile via MDM; Gatekeeper returns to its prior local-override state.
3 — Endpoint sweep for XCSSET v40 artifacts (read-only audit)
Prerequisites: None — read-only, safe on production endpoints. Reboot required: No.
#!/bin/bash # READ-ONLY audit. Does not remediate. Review output before acting. echo "--- Ad hoc-signed apps in /Applications ---" for app in /Applications/*.app; do codesign -dv "$app" 2>&1 | grep -q "Authority=" || echo "UNSIGNED/AD-HOC: $app" done echo "--- Chrome launches with the CDP flag in the last hour ---" log show --predicate 'eventMessage CONTAINS "remote-debugging-port"' --last 1h echo "--- Preference domains modified in the last 24h (heuristic) ---" find "$HOME/Library/Preferences" -name "*.plist" -mtime -1 echo "--- Telegram.app signature check ---" if [ -d "/Applications/Telegram.app" ]; then codesign -dv "/Applications/Telegram.app" 2>&1 fi
Rollback: None required — this script performs no changes.
4 — Block known XCSSET v40 C2 infrastructure at the network layer
Prerequisites: Admin access to the macOS packet filter (pf) or equivalent network appliance. Reboot required: No.
# /etc/pf.anchors/xcsset-v40-block
block drop out quick on en0 to { 91.108.106.229 95.142.35.34 95.142.35.206 \
95.142.37.159 151.243.109.188 178.208.92.129 178.208.92.168 }
# Load the anchor (add a matching anchor line in /etc/pf.conf first)
sudo pfctl -f /etc/pf.conf
# Verify
sudo pfctl -sr | grep -A2 xcsset
Rollback: Remove the anchor reference from /etc/pf.conf and the xcsset-v40-block file, then reload with sudo pfctl -f /etc/pf.conf.
This is host-level and does not scale past a handful of endpoints — for fleet enforcement, push the same block list to your perimeter firewall or DNS sinkhole instead.
Containment Runbook
| Phase | Actions | Owner | Evidence to capture |
|---|---|---|---|
| 1 · Triage 0–1 h | Confirm the hit is genuine (Q1/Q2/Q4 are confirmatory; Q3/Q6/Q7/Q8/Q9 need corroboration). Identify which local Xcode project was recently built and its source repository. | SOC L1 | Process tree, full command lines, repository URL, last commit hash |
| 2 · Isolate 0–1 h | Network-contain the host in Falcon. Preserve rather than reboot where possible — the in-memory boot module and staging state are the best forensic evidence, and v40's defaults-based persistence survives a reboot regardless. | SOC L2 | Falcon containment timestamp; memory image if your process supports it |
| 3 · Scope 1–4 h | Run Q1, Q2 and Q4 fleet-wide. Enumerate every local Xcode project on the host and check whether the infected developer has push access to shared repositories — XCSSET propagates through exactly that path. | Threat hunting | Host list, affected repository list, first-seen timestamps |
| 4 · Browser/session response 1–8 h | If Q3 or Q4 fired, treat every credential, session cookie and crypto-wallet transaction in that Chrome profile as compromised. Force session revocation and password resets for the affected user. | IAM | Chrome profile inventory, session revocation log, wallet extension list |
| 5 · Telegram response 1–8 h | If Q9 fired, advise the user to log out all Telegram sessions from a clean device via Settings > Devices and re-verify two-factor authentication. | IR lead + user | Session list, 2FA re-verification confirmation |
| 6 · Eradicate 4–24 h | Rebuild rather than clean. The fileless, per-host defaults-domain persistence and XProtect/TCC tampering make manual remediation unreliable; a missed preference domain re-arms the implant. | Endpoint eng. | Rebuild ticket, or full removal evidence for every persistence artifact found |
| 7 · Repository remediation 4–24 h | Audit and, if necessary, force-push a clean history for any shared repository the infected developer pushed to during the compromise window. Notify every other developer who may have pulled the tainted commits. | Dev/security eng. | Commit audit log, list of affected downstream clones |
| 8 · Recover 1–3 d | Reissue Chrome and Telegram from vendor-verified sources. Return the host to production only after 48 h of clean telemetry against the full query set. | Endpoint eng. | Clean-telemetry attestation, software provenance record |
| 9 · Harden 1–4 w | Execute the section 12 Immediate and Near-term tiers fleet-wide. Brief the affected developer population on the poisoned-project pattern specifically. | Security eng. | Change records, sandboxing/Gatekeeper deployment confirmation, awareness comms |
Detection Coverage Map
| Technique | Behavior | CQL | IOA | Coverage |
|---|---|---|---|---|
| T1071.001 / T1568 | C2 domain resolution | Q1 | Yes | GOOD |
| T1071.001 / T1573.001 | C2 IPv4 connection | Q2 | Yes | GOOD — but perishable |
| T1554 / T1539 | Chrome CDP hijack enablement | Q3 | Yes | PARTIAL — CI/test-automation noise |
| T1105 | CDP helper binary download | Q4 | Yes | GOOD |
| T1195.001 / T1059.004 | Poisoned Xcode build-phase execution | Q5 | — | PARTIAL — CI tooling creates noise |
| T1027.013 / T1564.001 | Fileless defaults-based staging | Q6 | — | PARTIAL — high FP, correlation-dependent |
| T1548.006 | TCC database reset | Q7 | — | PARTIAL — legitimate admin/QA use overlaps |
| T1562.001 (v40) | SoftwareUpdate/CloudTelemetryService/XProtect impairment | Q8 | Yes | PARTIAL — MDM remediation overlaps |
| T1554 / T1036 | Telegram Desktop trojanization | Q9 | — | PARTIAL — needs codesign correlation |
| T1543.004 | Launch Daemon persistence (legacy) | — | — | GAP — no query written; low observed v40 usage per sources |
| T1553.001 | Gatekeeper bypass (ad hoc signing) | — | — | GAP — covered only by native codesign audit, section 7 |
| T1497.003 | VM/sandbox evasion checks | — | — | GAP — malware-internal decision logic, no discrete telemetry |
| T1113 / T1056.002 | Screen capture / GUI input capture (legacy) | — | — | GAP — no discrete macOS Falcon event confirmed |
| T1005 / T1560 | Local data collection and archiving | — | — | GAP — no confirmed discrete file-read event |
| T1486 | Data encrypted for impact (legacy, not confirmed active in v40) | — | — | GAP — not observed in v40 press coverage |
| T1195.001 (propagation) | Spread to other local/shared Xcode projects via git | — | — | GAP — no Falcon telemetry; native repo-review only |
Nine of sixteen mapped behaviors have good or partial CQL coverage and five are promoted to Custom IOAs. The residual gaps cluster in three places: in-memory tradecraft (boot module, VM evasion, screen/input capture — none produce discrete process telemetry by design), legacy capabilities not confirmed active in the v40 press coverage (Launch Daemon persistence, ransomware impact), and the propagation vector itself (git-based spread has no Falcon telemetry and is addressed only through source-control hygiene in section 7). Validation gates for every query are in section 11; clear Gate 1 before treating any zero-hit result as clean.
Hunt Summary Ticket
TITLE: Hunt — XCSSET v40 macOS supply-chain malware (poisoned Xcode projects)
SEVERITY: High — active campaign, no usable file-hash IOC, credential/wallet/chat
hijacking capability, published network infrastructure
SCOPE: All macOS endpoints running Xcode; secondary scope is any macOS host
running Google Chrome or Telegram Desktop.
HYPOTHESIS: A developer built an Xcode project poisoned via a compromised Git
repository. The injected loader executed under the developer's own
context, registered with C2, loaded 17 modules in memory, impaired
XProtect/MRT/TCC/SoftwareUpdate, established fileless persistence via
a per-host defaults preference domain, and deployed the Chrome CDP
hijacker and/or Telegram trojanizer. It then attempted to infect other
local Xcode projects and propagate via shared git commits.
QUERIES: Q1 DNS resolution of published C2 domains <-- RUN THIS FIRST
Q2 Network connections to published C2 IPv4s <-- RUN THIS FIRST
Q3 Chrome launched with CDP remote-debugging-port
Q4 Retrieval of the CDP helper binary (zw_sfp64) <-- RUN THIS FIRST
Q5 Xcode/xcodebuild spawning a download-and-execute shell
Q6 Suspicious defaults write fileless staging
Q7 tccutil reset outside normal workflow
Q8 Defense-impairment commands
Q9 Telegram Desktop ad hoc re-signing (trojanizer)
DO FIRST: 1. Run Q1, Q2 and Q4 across your full retention window. All three are
zero-false-positive and retrospective; any hit is a confirmed lead.
2. Import the section 10 CSV into Falcon IOC Management.
3. Confirm macOS ProcessRollup2/NetworkConnectIP4/DnsRequest telemetry
is populated for your Xcode developer population (Validation Gate 1)
before treating a zero-hit result as clean.
FINDINGS: [ ] Hosts with Q1/Q2 hits (confirmed C2 contact) .............. ____
[ ] Hosts with Q4 hits (CDP helper download) ................. ____
[ ] Hosts with Q3 hits requiring corroboration ............... ____
[ ] Infected Xcode project(s) identified ..................... ____
[ ] Shared repositories requiring commit-history remediation .. ____
GAPS: No file hashes exist for this campaign (per-build recompilation defeats
hash IOCs). In-memory boot-module execution, VM evasion, screen/input
capture and the git-based propagation vector produce no discrete Falcon
telemetry — covered only by the native audit-log hunts in section 7.
ACTIONS: [ ] Enable Xcode User Script Sandboxing fleet-wide (playbook 1)
[ ] Enforce Gatekeeper via MDM configuration profile (playbook 2)
[ ] Run the endpoint sweep script on any suspect host (playbook 3)
[ ] Block known C2 IPs at the network layer (playbook 4)
[ ] Force credential/session reset for any user with a confirmed hit
[ ] Audit and remediate shared repositories the affected developer
pushed to during the compromise window
OWNER: ____________________
VERSION: v0.1 (2026-08-09)
Changelog
References
| Tier | Source | Used for | Published | Accessed |
|---|---|---|---|---|
| 1 | Palo Alto Networks Unit 42 — The Xcode Assassin Returns: A Deep Dive Into the Latest XCSSET Version | Infection chain, module list, C2 endpoint taxonomy, all published atomic indicators | 2026-07-31 | 2026-08-09 |
| 2 | BleepingComputer — New XCSSET variant targets macOS devs via compromised Xcode projects | Independent corroboration of timeline, module count, defense-impairment scope | 2026-08-04 | 2026-08-09 |
| 2 | GBHackers — XCSSET v40 Infects Xcode Projects to Hijack Chrome and Trojanize Telegram on Macs | Independent corroboration of CDP helper URLs, infrastructure reuse across waves | 2026-08-03 | 2026-08-09 |
| 2 | Cyber Security News — XCSSET v40 Abuses Chrome DevTools Protocol to Steal Cookies and Run Commands | Independent corroboration of IP set, SSL thumbprint, CDP mechanics | 2026-08-03 | 2026-08-09 |
| Ref | MITRE ATT&CK — XCSSET (S0658) | Legacy technique catalog for pre-v40 XCSSET | — | 2026-08-09 |
| Ref | Malpedia — XCSSET (osx.xcsset) | Historical reference list; confirmed no v40 hash/sample data indexed yet | — | 2026-08-09 |
Provenance: the fetched text of all six sources is saved alongside this pack in XCSSET-v40-Hunt-sources/. Every atomic indicator in section 4/10 traces to the Unit 42 snapshot (01) and is cross-validated in snapshots 03 and 04.