Summary

Scenario Something is wrong at Maromalix. On February 10th, 2026, credentials that should never have left the network were suddenly used from an unauthorized 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. Initial Access Q1: What is the IP address of the attacker that exploited the web application? By reading the scenario above carefully, we have a public-facing web application asset that got attacked, so let’s start investigation. We are provided here with a pcap file with ssl keys log file: At first, filtered for http traffic, and took a look at conversations, found the IP for the web-server (arguably172.31.44.238 is the web-server IP) Narrowing down a little with this query: http.request.methodPOST and ip.dst172.31.44.238 for less packets and better inspection (~300 packets). After following someTLS streams, found this communication: a weird POST requests generated by a script maybe (User-Agent: python-requests/2.31.0\r\n ) and have the same length (339 ). so, i guess this needs further investigation by adding the source IP address http.request.methodPOST and ip.dst172.31.44.238 and ip.src==63.180.69.24 Actually i couldn’t stop myself from inspecting the fisrtPOST request with a different length, so i followed the TLS stream for this hovered packet: so it’s a payload that abuses a JavaScript weakness (prototype pollution + constructor escape) to escape normal restrictions, then executes the system command id on the server. After that, it tries to sneak the result back to the attacker by embedding it inside an error response. Also, By investigating the second packets with the length > 339: we can find this payload also: So it makes sense now!! 63.180.69.24 Q2: What is the CVE identifier for the vulnerability exploited in this attack? from the Lab Name, we can search and get the CVE easily: Or by searching for the CVE from the payloads we’ve already identified in the previous question: CVE-2025–55182 Execution Q3: What is the filename of the script downloaded by the exploit payload to install the malware? based on paloalto report (link) we did identified this so, we can filter for the user-agent curl , and GET requests:http.request.method==GET and http.user_agent contains “curl” s.sh Q4: What is the filename of the decrypted implant that serves as the main RAT? By investigating the bash script file, we can get the correct answer directly: .7vfgycfd01.js Defense Evasion Q5: What is the hidden directory path used by the malware to store its components? Investigating the same Bash script file, it’s obvious at the beginning of the file: ~/.local/share/.05bf0e9b Q6: The malware checks system locale to avoid execution in certain regions. What is the first locale code in the blocklist? since we have the full script, the script contains a Base64 encoded Blob That is AES Encrypted, with a clear Key and IV as you can see, So, Let’s decrypt it properly on cyberchef (link), and get the answer: ru Command and Control Q7: What are the two smart contract addresses used for C2 resolution? (Format: in the order they are queried) from the same previous decrypted Code, we can get the addresses directly: 0x22f96d61cf118efabc7c5bf3384734fad2f6ead4,0xb0cbaA51b3D1D36e8E95F4F68dfBd47ED2eaA7a4 Q8: When was the primary smart contract deployed on the Ethereum network (UTC)? from the previous image, we can determine that the first contract is the primary one, so let’s check it online (link) from etherscan, we can can go to the full contract and get the timestamp: 2025–12–05 19:13:47 Q9: Since the smart contract is deployed on a public blockchain, its source code can be obtained. What function name is used to retrieve the stored C2 URL? in my case i used the Dedaub (LINK), Now, we can put the input data we found in the contract into Dedaub: just like this: and now it’s decompiled successfully: it’s basically a minimal storage contract that lets an address store and retrieve a string mapped to its address, so let’s take that full string and decompile it again into Dedaub: getString Q10: What is the transaction hash of the first C2 URL published to the primary contract? investigating the first transaction hash as shown: investigating the Input data: Decode Input so yeah, it contains the C2 URL, so hit the transaction hash for the answer 0xe4efe4d2b118229161f7023e13ab98b54180fbfb1756d11959e4f19238b9655d Q11: When did the implant retrieve the C2 URL from the blockchain (UTC)? falling back to our pcap file, we can use this filter: http contains “eth” or search for eth_call since it is the JSON-RPC method used to read data from smart contracts: 2026–02–10 18:37 Q12: What C2 URL did the implant retrieve from the blockchain during execution? we can see here the traffic direction: https://63.176.62.199:443 Q13: What is the Bot ID assigned to the compromised host? Get Loay Salah’s stories in your inbox Join Medium for free to get updates from this writer. the same previous packet, we can get the BotID from it 4ebfbc8aedf60511 Credential Access Q14: Once connected to the C2, the implant started executing multi-stage payloads. What is the endpoint path used for exfiltrating harvested credentials? checking all visited URLs, until you’ll find this: /crypto/keys Persistence Q15: What is the filename of the systemd user service created for persistence? Since we are looking for Linux persistence via a systemd user service, so the goal is to find where the attacker creates or references a .service file. c16a536e1a9cb42d.service Q16: What is the comment field in the attacker’s injected SSH public key? we need to know first that the structure is like this:ssh-rsa , so by the filter : http contains “ssh-rsa” single lonely packet, let’s check its TLS stream, and get the answer: maromalix@ether_dev Execution Q17: When was the first remote command executed through the C2 channel (UTC)? this question and the next one Q18, have the same idea. from reading the full decrypted AES js file (Link), we can determine that It generates a fake-looking URL, which is used for Beaconing: https://<C2_DOMAIN>/api//<BOT_ID>/.?=<BOT_ID> https://63.176.62.199:443/api//4ebfbc8aedf60511/.?=4ebfbc8aedf60511 So, by searching with this query: http.request.methodGET and ip.src172.31.44.238 and ip.dst63.176.62.199 , we can see this: All commands by the C2 Beaconing server (with some jitter intervals) SO, we can determine the command by following the TLS Stream for each packet, (the command will be seen in the GET response packet) like this: or another way, with searching for the POST requests, from the web-server to the C2 server with query: http.request.methodPOST and ip.src172.31.44.238 and ip.dst63.176.62.199 and get the precious commands “whoami ” with the timestamp: 2026–02–10 18:40 Q18: 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? investigating all commands by this amazing query: http.request.methodPOST and ip.src63.180.69.24 and http.request.uri contains “/login” and http.content_length>339 we now have all the 8 executed commands, this one is the one we need so by investigating each packet (Follow TLS ) we can find this 15.3.9 Q19: Based on the observed IOCs and TTPs, which nation-state is most likely behind this activity? from the CVE number (CVE-2025–55182 ), we identified that it’s origin from North Korea (DPRK) DPRK

By Loay Salah

Original Article