For responders · macOS
Technical analysis & indicators of compromise
Drawn from analysis of one real macOS case — a packed, Go-based infostealer with an integrated cryptocurrency clipper, delivered by a ClickFix lure. Indicators are specific to that sample; the patterns generalise.
If you’re here to recover rather than analyse, the recovery protocol and the clean & rebuild guide are the practical paths. Windows analysis →
How it works
The attack chain
A pasted one-liner prints a decoy “verification” message, then decodes a hidden payload and executes it in the background with output suppressed. The payload fetches a second-stage loader from a remote host and runs it. The loader writes the stealer binary into a cache folder disguised as a system-update directory and installs a LaunchAgent impersonating an Apple service for persistence. The fake password prompt that follows collects the admin password, giving the second stage root.
What the malicious command looks like (defanged — not runnable)
Shown only so the pattern is recognisable. The payload is redacted and this will not run. The universal tell: any instruction that ends by piping text into your shell is an attack.
echo 'I am not a robot — Verification ID: «random»' && \
echo '«long base64 blob — REDACTED»' | base64 «decode» | «shell»
The decoded blob fetched a remote script (saved as a hidden, “system-update”-themed file) and executed it. Network addresses are listed as indicators below, never as runnable commands.
Persistence
Where it persists
The sample installed a single user-level LaunchAgent. macOS runs launch items via launchd, which reads .plist files from the launch directories — so the malware simply registered with the system’s own launcher.
| Artifact | Location / value |
|---|---|
| LaunchAgent | ~/Library/LaunchAgents/com.apple.softwareupdated.plist |
| Payload | ~/Library/Caches/com.apple.softwareupdate/SoftwareUpdate |
| Run flags | RunAtLoad + KeepAlive · launched with --clipper |
Audit note: all three launch directories should be checked — user ~/Library/LaunchAgents/, and system /Library/LaunchAgents/ and /Library/LaunchDaemons/. In this case only the user agent was malicious; both system locations were clean, despite the malware holding root. A clipper needs the logged-in GUI session, which is why it lives as a user agent rather than a root daemon — so a clean system folder does not lower the data-theft assumption.
Read-only verification (responder)
# label collides with Apple's real service — match on the unique cache path instead
ps aux | grep "Caches/com.apple.softwareupdate/SoftwareUpdate" | grep -v grep
launchctl list | grep -i softwareupdate
sudo sfltool dumpbtm
A - in the PID column of launchctl list means not currently running; the second column there is the last exit status, not a PID.
Binary analysis
What it steals
The payload is a 64 MB Mach-O universal binary (x86-64 + arm64) written in Go. Go embeds config field names and target lists in plaintext, so capabilities are readable by static analysis (no execution). It is a full-spectrum stealer plus clipper:
- Crypto wallets — Atomic, Trust, Electrum, Exodus, Wasabi, Guarda, Coinomi, Armory, Phantom; wallet files and stored keys.
- Seed phrases — the binary embeds the full BIP-39 wordlist, indicating it scans for and harvests recovery phrases stored as text.
- Clipboard hijacking — substitutes copied crypto addresses with attacker-controlled ones (addresses below).
- Credentials & secrets — macOS Keychain, browser passwords/cookies/autofill/cards, password-manager vaults (KeePass
.kdbx, 1Password.1pux/.1pif, Enpass), GPG keys, SSH keys, API keys. - Browsers — Firefox, Chrome, Brave, Vivaldi, Safari. Messaging — Signal. Plus a general file-grabber and victim geolocation.
Clipper substitution addresses
Hard-coded in a JSON table in the binary — the addresses it swaps a victim’s copied address for. Published as a warning: if you are about to send to one of these, stop.
| Asset | Attacker address |
|---|---|
| EVM | 0x326516e60696fb6d249f7e3315c756d488951127 |
| Bitcoin | bc1qhvu30h6qk0e8yv2erqt6sf4e4nyetlfvn7vgx9 |
| Monero | 42PETqm6navFRWXC2VPKMWSbiLR1pMvCmFakQTFBrGB3XMmcnFDAv5og3w6NSAUvGjPzmfTE1BWTPUCZQwd5cw7zM3rFdRX |
Indicators of compromise
IoC summary
| Type | Indicator |
|---|---|
| Classification | Packed/obfuscated Go macOS infostealer + clipper (family not resolved by AV consensus) |
| SHA-256 | 12f8431b39828129088a87dc2a399a54ab7acc844e1dac85ad0467b8b12ea8b4 |
| Payload path | ~/Library/Caches/com.apple.softwareupdate/SoftwareUpdate |
| Persistence | ~/Library/LaunchAgents/com.apple.softwareupdated.plist |
| Loader host | 192.144.57.152 (HTTP) |
| C2 (embedded) | 91.84.125.223:8133 (HTTP) |
| Clipper · EVM | 0x326516e60696fb6d249f7e3315c756d488951127 |
| Clipper · BTC | bc1qhvu30h6qk0e8yv2erqt6sf4e4nyetlfvn7vgx9 |
| Clipper · XMR | 42PETqm6navFRWXC2VPKMWSbiLR1pMvCmFakQTFBrGB3XMmcnFDAv5og3w6NSAUvGjPzmfTE1BWTPUCZQwd5cw7zM3rFdRX |
Notes & caveats
The whole multi-arch binary scored low on VirusTotal (9/52), but that understates it: many engines can’t parse a large universal Mach-O. Scanned per-architecture, detection roughly doubled (x86-64 20/64, arm64 12/63). Engine consensus is a macOS stealer trojan; no clean family name is agreed, so none is asserted here.
The C2 is embedded in the binary but was not observed contacted during sandbox analysis — expected for stealers (time-limited runs, gated callbacks, or a dead server). Treat it as a static indicator, not a confirmed live callback.