Skip to content

Back to the catalog

Malicious Crypto Shell Packages Target RubyGems
opensourcemalware.comwriteup

Malicious Crypto Shell Packages Target RubyGems

OpenSourceMalware's analysis of over 40 typosquatted RubyGems packages (e.g. rubygems-btc-shell) published by a user calling themselves "Ghost Dev," targeting crypto/web3 developers. The packages ship a delayed-execution payload hidden in extconf.rb that evades sandboxes before either opening a reverse shell to 45.138.12.177:8090 or deploying a full theft kit (inject_proxy.py, _grab.py, a browser extension, and a rogue root CA) that MITMs TLS traffic to 28+ crypto exchanges, swaps withdrawal addresses, hijacks the clipboard, and harvests wallet files, seed phrases, and private keys. The writeup includes full IOCs, SHA-256 hashes, attacker wallet addresses, and C2 endpoints.

TL;DR 42 typosquatted RubyGems packages from "Ghost Dev" install a reverse shell or a TLS-MITM crypto-theft kit that swaps wallet addresses and harvests seed phrases.
Document

What it is

rubygems-btc-shell and its 40+ typosquat siblings, all published by RubyGems user reqthrottle_3474 ("Ghost Dev"). The malicious logic sits in ext/req_throttle_mini/extconf.rb, disguised as a native-extension build script.

How it works

Before activating, the script checks for CI/sandbox/analysis-directory markers and generated test usernames, and confirms signs of a real dev workstation (SSH keys, Git config, npm/RubyGems credentials, Bundler data). If those checks pass, it forks to background, detaches from the terminal, and sleeps 20–40 minutes before decoding a base64 payload.

Two variants exist:

  • Reverse shell (11 of the 40+ packages): repeatedly connects to 45.138.12.177:8090, attaches to /bin/sh, retries every 30 seconds on failure.
  • Downloader: sleeps 1200 + rand(1200) seconds (or 2s if env var WG_FAST is set), then fetches http://45.138.12.177:8092/wgkit.tar.gz. The target URL is XOR-decoded from a hex string at runtime, and can be overridden via WG_KIT_URL env var.

The downloaded kit (wgkit.tar.gz) installs via wg_install.sh into $HOME/.cache/.wg, trusts a bundled root CA ("Wallet Guard Root CA", valid 2026-10-05 to 2036-10-02), writes proxy env vars into .bashrc/.zshrc, and creates autostart entries wg.desktop and wg-grab.desktop. A local MITM proxy (inject_proxy.py) listens on 127.0.0.1:8899, intercepting HTTPS to 28 named exchanges using pre-signed per-domain certs, and injects ext/content.js before </head>/<head>/<body>. The injected script detects BTC/ETH/TRX/SOL/TON withdrawal addresses in form fields and fetch/XHR/FormData submissions, swaps them for attacker wallets, then spoofs the displayed value for up to 12 seconds. _grab.py polls the clipboard every ~800ms (via Win32 API or xclip/xsel) to swap copied addresses, scans for MetaMask/TronLink/Phantom/Coinbase/Trust Wallet/Exodus/Electrum data, and greps user files for seed/keystore/WIF/xprv material, XOR-obfuscates and base64-encodes it, then POSTs to /grab.

flowchart TD
    A[gem install] --> B{extconf.rb: sandbox/CI check}
    B -- fails: sandbox --> X[dormant, no action]
    B -- passes: real workstation --> C[sleep 20-40min]
    C --> D{variant}
    D -- 11 pkgs --> E[reverse shell to .177:8090]
    D -- other pkgs --> F[sleep ~20-40min, fetch wgkit.tar.gz from .177:8092]
    F --> G[trust rogue root CA]
    G --> H[MITM proxy 127.0.0.1:8899]
    H --> I[rewrite withdrawal address in page]
    F --> J[_grab.py: clipboard + file/wallet harvest]

Preconditions / Affected

Any system where one of the 40+ typosquat gems was installed and run outside a sandbox/CI environment, with a real developer profile (SSH keys, git config, npm/gem credentials) present — this is required to trigger the delayed payload.

What to do

  • Inspect endpoints for: the "Wallet Guard Root CA" in the trust store, $HOME/.cache/.wg, autostart entries $HOME/.config/autostart/wg.desktop and wg-grab.desktop, and a listener on 127.0.0.1:8899.
  • Check for proxy environment variables added to .bashrc/.zshrc.
  • Treat any wallet/exchange secrets present on an affected host as compromised; rotate them from a clean device.
  • Query for outbound connections to 45.138.12.177 (ports 8080, 8090, 8092) and HTTP requests to /wi/grab, /w, or /grab.

Caveats

The proxy's --c2 option and the grabber's WG_C2 env-variable override allow operator-supplied exfil URLs that the researchers could not resolve, since those values are external to the analyzed sample — the listed C2 IOCs reflect only the default/observed configuration.

Organisations named here

  • 45.138.12.177
  • reqthrottle_3474
  • rubygems-btc-shell
  • Wallet Guard Root CA

Technologies named here

  • RubyGems registry
  • OpenSourceMalware automatic detection engine
  • inject_proxy.py
  • rubygems-btc-shell
  • TronLink
  • _grab.py
  • ext/content.js
  • MetaMask
  • Phantom
  • wg_install.sh
  • wg-ca.crt
  • Binance
  • xclip / xsel
  • Coinbase
  • Trust Wallet
  • Exodus
  • Electrum
  • Chrome, Brave, Edge browsers
  • Targeted cryptocurrency exchanges
  • RubyGems
  • Python
  • Bitcoin
  • Ethereum
  • Solana

Techniques named here

  • Typosquatting
  • Sandbox/analysis evasion
  • Delayed execution
  • Reverse shell
  • Second-stage payload download
  • Adversary-in-the-middle TLS interception
  • Browser injection / HTML content injection
  • Withdrawal address replacement
  • Clipboard hijacking
  • Wallet-vault and secret harvesting
  • Data obfuscation and exfiltration
  • Persistence via autostart entries
  • Rogue trusted root CA installation

Threat actors named here

  • Ghost Dev
  • rubygems-btc-shell
  • Wallet Guard kit