Get our latest research in your inbox

New threat intelligence, detection engineering, and red team write-ups, delivered when we publish.

EtherHiding: When Malware Hides Its C2 on the Blockchain

August 10, 2026Crimson7 Threat Intelligence
threat intelligenceEtherHidingEthereumsmart contractscommand and controldead drop resolverShai-Huludsupply chaindetection engineeringT1102.001
  • Classification: TLP:WHITE
  • Threat type: Command and Control / Dead Drop Resolver
  • MITRE ATT&CK: T1102.001 (Web Service: Dead Drop Resolver)

Threat actors are storing C2 domains inside Ethereum smart contracts. The contract address is stable, the retrieval is anonymous, and there is no registrar or hosting provider to send a takedown request to. We observed this technique live in the Shai-Hulud supply chain campaign, queried the contract on mainnet, and decoded the C2 domain directly from the chain.


What is EtherHiding?

Traditional malware C2 infrastructure has a shelf life. Defenders register sinkhole domains, hosting providers pull servers, and law enforcement seizes infrastructure. The attacker loses the channel and has to rebuild.

EtherHiding sidesteps all of that.

The concept is simple. Instead of hardcoding a C2 domain in the payload, or relying on a DGA that defenders can predict, the malware calls an Ethereum smart contract to retrieve its current C2 address. The smart contract acts as a dead drop resolver, a lookup service that only the attacker can update, hosted on infrastructure that nobody can take down.

From the EVM's perspective this is a read-only call. No gas is spent, no transaction is recorded for the read, and the request blends in with millions of other eth_call RPCs hitting public endpoints every day. The malware needs no wallet and no ETH. The deployment and any domain rotation calls do leave on-chain traces, but the read path the malware uses does not.


How it works

The attacker deploys a minimal Solidity contract with a getter function that returns a string: the C2 domain, a payload URL, or any other configuration data.

// SPDX-License-Identifier: MIT
pragma solidity >=0.6.12 <0.9.0;

contract EtherHiding {
    function getPayload() public pure returns (string memory) {
        return "awqhnjewqjkl.icu";
    }
}

Figure 1: EtherHiding.sol open in Remix IDE, the Crimson7 proof-of-concept contract before deployment to Sepolia. Our deployed version returns a benign contact string rather than a live C2 domain.

That is the whole thing. A single function, a single string. The real Shai-Hulud variant stores the domain in a state variable behind an onlyOwner setter, so the attacker can update the C2 domain whenever they want by sending a transaction. The contract address stays the same, the malware never needs updating, and the domain it resolves can change at any time.

The contract's ABI is equally minimal, a single pure function returning a string.

[
    {
        "inputs": [],
        "name": "getPayload",
        "outputs": [
            {
                "internalType": "string",
                "name": "",
                "type": "string"
            }
        ],
        "stateMutability": "pure",
        "type": "function"
    }
]

We deployed a proof of concept on the Sepolia testnet so you do not have to take our word for any of this. Open the EtherHiding C2 Demo, pick the Crimson7 Demo (testnet) preset, and hit Query Contract. The tool sends the same eth_call a piece of malware would send and shows you both the raw hex and the decoded string.

Figure 2: The Crimson7 proof-of-concept contract on Sepolia, queried through the demo page. The raw hex response is ABI decoded back into the stored string.

The malware payload makes a JSON-RPC eth_call to any public Ethereum RPC endpoint. No authentication is required.

{
  "jsonrpc": "2.0",
  "method": "eth_call",
  "params": [{
    "to": "0xE1f2395ee43e45A1556EC6438a88c31B83493103",
    "data": "0x53ed5143"
  }, "latest"],
  "id": 1
}

The data field is just the 4-byte keccak256 function selector for getAll(). The response comes back ABI encoded, the malware decodes it, and it has its current C2 domain.

Figure 3: Live query of the Shai-Hulud C2 resolver on Ethereum mainnet. The decoded string is awqhnjewqjkl[.]icu.


Why defenders cannot kill it

  • No takedown path. There is no registrar to contact, no hosting provider to abuse report, no DNS to sinkhole. The contract is replicated across the Ethereum network, no single party can remove or freeze it, and the attacker can update the stored domain at will.
  • Domain rotation without payload updates. The attacker calls a setter function on the contract to change the C2 domain. Every infected host picks up the new address on its next check-in, with no payload update needed.
  • Traffic blends in. RPC calls to endpoints like publicnode.com, getblock.io, or infura.io are legitimate traffic. At the network layer the malware's requests are indistinguishable from ordinary DeFi activity.
  • No on-chain footprint for readers. The eth_call method is a local simulation, it does not create a transaction. There is nothing to find in block explorers unless you already know the contract address.

What we observed

During analysis of the Shai-Hulud malware, the weaponized keyv@6.0.0 npm package, we identified an EtherHiding contract deployed at:

0xE1f2395ee43e45A1556EC6438a88c31B83493103

The malware rotates through a list of public Ethereum RPC endpoints so it never depends on a single gateway:

  • go.getblock.io
  • securerpc.com
  • runonflux.io
  • chain49.com
  • tenderly.co
  • diamondswap.org
  • lokibuilder.xyz

At time of query (2026-08-06) the contract returned a single domain: awqhnjewqjkl[.]icu

Check this contract for yourself, right nowThe Shai-Hulud C2 preset in our demo queries this exact address on mainnet. If the operator has rotated the domain since we published, you will see the new one.Query mainnet

The contract bytecode is 2,597 bytes and remained deployed as of 2026-08-06. The attacker retains the ability to rotate C2 at any time by calling the setter function, and that setter transaction would be visible on-chain, which gives defenders a monitoring opportunity.

For the full analysis of the campaign this contract belongs to, see our companion report, Shai-Hulud's Ethereum C2: Inside a Blockchain-Backed npm Supply-Chain Attack.


The selector problem

One thing worth noting for defenders doing static analysis: the malware does not contain the function name getAll() anywhere. It only contains the 4-byte selector 0x53ed5143.

If you are reverse engineering a sample and you see a hex constant like this in an eth_call, you can reverse it using public signature databases.

0x53ed5143 → getAll()
0x2cae8ae4 → getPayload()
0xa9059cbb → transfer(address,uint256)

The selector is keccak256("functionName(argTypes)") truncated to 4 bytes. Public databases that let you reverse the lookup:

Paste a selector like 0x53ed5143 and you get back getAll(). The Selector Toolkit in our EtherHiding demo does both directions in one place: type a function name to get its selector, or paste a selector to look up the name. These databases have indexed millions of function signatures from verified contracts across every EVM chain. If the attacker used a common function name you will find it. If they used something obfuscated such as function x7f2a() it will not be in any database, but that absence is itself a red flag during analysis.

Figure 4: Selector Toolkit. Hashing getPayload() to its selector, and reverse looking up 0x53ed5143 to getAll() via OpenChain.


Detection opportunities

EtherHiding is hard to block, but it is not invisible.

  1. Monitor for unusual Ethereum RPC traffic. If node.exe or bun.exe is making POST requests to Ethereum RPC endpoints, that is anomalous in most enterprise environments. Nobody is running DeFi from a CI server.
  2. Watch the contract. The address is public. You can set up monitoring to alert when the stored domain changes, giving you early warning of C2 rotation.
  3. Detect the RPC endpoints. The malware needs some gateway to reach Ethereum. If you block or alert on the known RPC domains it cycles through, you force the attacker to find new endpoints.
  4. Hunt for the pattern, not the IOC. Any process making eth_call requests with a small, fixed data payload and then immediately connecting to the decoded domain is the behavioral pattern, regardless of which contract or RPC is involved.

Key takeaways

  • EtherHiding gives attackers censorship-resistant, dynamically updatable C2 infrastructure at near-zero ongoing cost. This is not a theoretical technique, it is in active use in the Shai-Hulud campaign.
  • You cannot neutralize this infrastructure. There is no takedown, no sinkhole, no seizure. The attacker can change the stored domain at any time, or deploy a new contract entirely. Accept that and focus on detection.
  • Detect the behavior, not the IOC. The durable signal is non-DeFi processes such as node and bun making eth_call requests to Ethereum RPC endpoints. That pattern survives domain rotation, contract changes, and RPC endpoint swaps.
  • The barrier to entry is low. One Solidity contract and a few dollars in deployment gas. Other actors are likely to adopt this pattern.

IOC summary

TypeIndicatorContext
Contract0xE1f2395ee43e45A1556EC6438a88c31B83493103EtherHiding C2 resolver (mainnet), stored domain may change
Selector0x53ed5143Function selector for getAll()
Domainawqhnjewqjkl[.]icuActive C2 domain from the contract, as of 2026-08-06
RPCgo.getblock.ioEthereum RPC endpoint used by malware
RPCsecurerpc.comEthereum RPC endpoint used by malware
RPCrunonflux.ioEthereum RPC endpoint used by malware
RPCchain49.comEthereum RPC endpoint used by malware
RPCtenderly.coEthereum RPC endpoint used by malware
RPCdiamondswap.orgEthereum RPC endpoint used by malware
RPClokibuilder.xyzEthereum RPC endpoint used by malware

Research conducted through passive, read-only interaction with public blockchain data. No attacker infrastructure was modified, disrupted, or otherwise interfered with. Domains are defanged per standard practice.