ChainScript: Tracing a Node.js RAT Through the Blockchain
Detection stack
- AIDR
- Alert
- ETL
- Query
Summary
ChainScript is a newly discovered Node.js-based remote access trojan (RAT) that uses decentralized blockchain infrastructure for command and control (C2) discovery. The malware relies on an EtherHiding technique, querying a Polygon smart contract to dynamically resolve active WebSocket endpoints and rapidly rotate infrastructure. Its capabilities include interactive shells, file manipulation, and cryptocurrency wallet reconnaissance.
Investigation
Blackpoint’s Adversary Pursuit Group (APG) identified ChainScript while investigating ClickFix activity involving malicious Windows Installer packages. Analysts observed malware components staged across multiple Microsoft-themed directories and a Polygon smart contract used as a resolver. The investigation showed that the threat actor automates deployment of resolver contracts together with malware builds to enable seamless C2 transitions.
Mitigation
Organizations should reduce ClickFix execution paths by disabling the Windows Run dialog where it is not required and restricting MSI installation from user-writable directories. Security teams should monitor unusual process relationships, particularly msiexec.exe spawning wscript.exe or PowerShell. Users should also be trained to recognize social engineering prompts requesting manual command execution through Win+R.
Response
If ChainScript activity is detected, the affected system should be isolated immediately to prevent lateral movement or data exfiltration through the interactive shell. Responders should perform a full forensic review for secondary payloads and unauthorized persistence in scheduled tasks or registry Run keys. Potentially exposed credentials should also be rotated, especially those associated with browser extensions or local cryptocurrency wallets.
Attack Flow
We are still updating this part.
Detections
Possible Persistence Points [ASEPs – Software/NTUSER Hive] (via registry_event)
The Possibility of Execution Through Hidden PowerShell Command Lines (via cmdline)
NodeJS Binary Executing From Uncommon Location (via cmdline)
Suspicious NodeJS Child Processes [Windows] (via cmdline)
LOLBAS WScript / CScript (via process_creation)
Possible Scheduled Task Creation (via powershell)
Suspicious Scheduled Task (via audit)
IOCs (HashSha256) to detect: ChainScript: Tracing a Node.js RAT Through the Blockchain
Detect ChainScript Blockchain-Based C2 Infrastructure Discovery [Windows Network Connection]
Detection of ChainScript RAT Execution via PowerShell [Windows PowerShell]
Detection of ChainScript Node.js RAT Execution via Msiexec and Wscript [Windows Process Creation]
Simulation Execution
-
Attack Narrative & Commands: The attacker deploys a Node.js-based payload designed to mimic ChainScript. The goal is to discover the C2 infrastructure by querying a public Ethereum RPC endpoint. The script initiates a WebSocket connection and sends a JSON-RPC
eth_callrequest. Critically, the request includes the specific function selector0x4ab7874ewithin the payload. This action is intended to simulate the “discovery” phase of the malware lifecycle, where the C2 address is pulled from a smart contract on the blockchain. -
Regression Test Script:
# Simulation script to mimic ChainScript blockchain discovery via WebSocket # This requires a Node.js environment or a tool capable of sending specific WebSocket JSON-RPC payloads. # For this simulation, we use a PowerShell script to send the raw payload. $wsUri = "wss://eth-mainnet.g.alchemy.com/v2/YOUR_API_KEY" # Using a placeholder RPC endpoint $ws = New-Object System.Net.WebSockets.ClientWebSocket $ct = New-Object System.Threading.CancellationToken try { Write-Host "[+] Connecting to WebSocket RPC..." $connectTask = $ws.ConnectAsync($wsUri, $ct) $connectTask.Wait() Write-Host "[+] Connection established." # The specific payload containing the ChainScript function selector $payload = '{ "jsonrpc":"2.0", "method":"eth_call", "params":[{ "to":"0x742d35Cc6634C0532925a3b844Bc454e4438f44e", "data":"0x4ab7874e0000000000000000000000000000000000000000000000000000000000000000" }], "id":1 }' $bytes = [System.Text.Encoding]::UTF8.GetBytes($payload) $segment = New-Object ArraySegment[Byte] -ArgumentList @(,$bytes) Write-Host "[+] Sending ChainScript discovery payload (eth_call + 0x4ab7874e)..." $sendTask = $ws.SendAsync($segment, [System.Net.WebSockets.WebSocketMessageType]::Text, $true, $ct) $sendTask.Wait() Write-Host "[+] Payload sent." } catch { Write-Error "[-] Simulation failed: $($_.Exception.Message)" } finally { if ($ws.State -eq 'Open') { $ws.CloseAsync([System.Net.WebSockets.WebSocketCloseStatus]::NormalClosure, "Closing", $ct).Wait() } $ws.Dispose() Write-Host "[+] Cleanup complete." } -
Cleanup Commands:
# No persistent changes are made by the script. # Ensure any temporary Node.js processes or local listener files are removed. Stop-Process -Name "node" -ErrorAction SilentlyContinue Remove-Item -Path "$env:TEMPchainscript_sim.tmp" -ErrorAction SilentlyContinue