XWorm is not a new strain of malware, but in this case it appears in an unusual phishing campaign. Booking confirmations specifically tailored to businesses in the tourism sector are sent via WhatsApp Web to trick recipients into opening a JavaScript file.
As a Remote Access Trojan (RAT), XWorm gives attackers extensive access to infected systems. This can allow them to steal passwords and payment information, record screen contents, or install additional malware such as ransomware. For a general overview of XWorm’s capabilities, see ANY.RUN’s XWorm Malware Analysis. XWorm is particularly dangerous because the malware is offered as Malware-as-a-Service. This means that even attackers with limited technical expertise can use the Trojan for a fee. As a result, threat actors can focus more heavily on selecting their victims and optimizing their distribution methods—as demonstrated in this case.

Attack Summary

Instead of a traditional phishing email, the attackers use WhatsApp Web and tailor their lures specifically to businesses in the tourism industry in Latin America. Many tourism businesses use WhatsApp Business as a convenient communication channel between employees and guests. However, when accessed through the web application, documents and links can be just as dangerous as attachments in a phishing email.
Phishing WhatsApp The message “Hello, I would like to confirm the reservation. I have made the payment; the receipt is attached below” is used to trick victims into opening what appears to be a payment receipt or booking confirmation. The lure is specifically tailored to the day-to-day operations of a hotel. A potentially overlooked reservation creates an immediate sense of urgency, increasing the likelihood that the attached file will be opened without further verification.

However, the supposed receipt is not a regular PDF document but a JavaScript file. When opened, it first executes an initial loader. This loader sets up additional components on the system before downloading the actual XWorm Trojan. The malware stores its files in an inconspicuous-looking, nested directory and configures automatic execution to ensure it remains active even after the system is restarted. A very similar infection chain was analyzed in February 2026 in a post by Moises Cerqueira.
Once the system has been successfully infected, the Trojan regularly connects to a Command-and-Control server, or C2 server, operated by the attackers. Through this connection, commands can be received and executed on the compromised machine. This allows the attackers to install additional malware, extract booking data and guest contact information, or attack other systems within the network.

The following sections provide a technical look at the JavaScript-based initial loader, the additional tools it downloads, and the Remote Access Trojan itself. The recovered components are analyzed statically, following an approach similar to that described in a post published in September 2025.

Analysis of the JavaScript Loader

File: NU_Comprovante_47266772__82173625_72735278_Pdf.js
SHA-256: B8AFB6B8731DB787BAF5CF62EE6CA33D73D186CB8277C505940D35DDD3B60D33
MD5: B3B41B1A1DD2ED3E9047EFA4013D9AF1

This file is the initial loader that was received and distributed via WhatsApp. The JavaScript file was statically analyzed using Visual Studio Code and deobfuscated step by step. (Junk functions and Base64 encoding).

if condition in kapMb
If the script is launched from Temp or Downloads, it copies itself to the Public directory, launches the copy, and then terminates the original instance. This moves execution away from the typical download directories and into the public user directory.

Copy from Downloads

Function wZtRoyXEvX()
This function constructs a PowerShell command. The two obfuscated Base64 blocks PoQct and HwdxE are combined, cleaned up, and decoded. The decoded PowerShell code is then written to the following file: C:\Users\Public\fprnk.ps1. The file is then executed. fprnk.ps1

PowerShell code from PoQct += HwdxE
The decoded PowerShell code first tests the internet connection and checks for common analysis or sandbox environments. To do so, it searches for running processes frequently associated with malware analysis or sandbox environments. If an analysis environment is detected, the script triggers a system restart. This behavior can interrupt dynamic analysis and make investigating the malware more difficult.

Copy from Downloads

Subsequent Payload
A URL is written to the file C:\Users\Public\lnzvp.txt: hxxps://andrefelipedon.../ArquivosDeTexto/03[.]txt. An additional payload is then downloaded from this URL and saved to C:\Users\Public\fcthg.txt.

Reflection / Assembly Loading
Further sections of the code contain identifiers and method calls such as Load, Assembly, and Invoke, indicating the dynamic loading of a .NET assembly. An additional URL was also identified: hxxps://andrefelipedona.../PeYes. Its exact purpose has not yet been fully reconstructed.

PowerShell Persistence and Process Hollowing

Path: C:\Users[REDACTED]\AppData\LocalLow\Windows Sytem (x86)\Program Rules\Program Rules NVIDEO\Program Rules\Program Rules NVIDEO\

The directory contains a total of 44 PowerShell scripts. Five of these contain code for C2 communication, while twelve create registry entries. The remaining scripts are primarily used to invoke one of the other scripts via PowerShell.
The following three files are examined in more detail as representative examples:

  • accwx.ps1 – PowerShell invocation
  • jodjx.ps1 – Creation of a registry entry
  • lbtly.ps1 – C2 communication and payload execution

accwx.ps1 Launches the jodjx.ps1 script via PowerShell.

accwx.ps1

jodjx.ps1 Creates a RunOnce registry entry using New-ItemProperty. As a result, lbtly.ps1 is executed via PowerShell in hidden mode the next time the user logs on.

jodjx.ps1

lbtly.ps1 Contains two embedded Windows executables: dxxAS and litHM. Both were Base64-encoded and stored in the file as byte strings.

lbtly.ps1

The decimal byte values 77 and 90 correspond to the ASCII characters M and Z, respectively, or the byte sequence 0x4D 0x5A. This forms the MZ signature at the beginning of a PE file. The dxxAS component is loaded directly from the byte array as a .NET assembly without first being written to disk as an executable file. The path to installutil.exe is then passed to the loader. The loader launches the legitimate Windows binary as the target process and injects the payload contained in litHM using Process Hollowing.

In summary:

  • dxxAS = Loader / Injector
  • litHM = XWorm payload
  • installutil.exe = Legitimate host process used for Process Hollowing

The two embedded components were extracted, saved as separate files, and subsequently analyzed using dnSpyEx.

lbtly_dxxAS.bin
SHA-256: DA580B4DBE6FD9A90149121595797DD34A6266D0E1DAE92B5DBED7FAFE1E3C89
Structure: Class3.Run() -> Class2.wMAHY(installutil.exe, litHM_bytes, “”) -> Class2.Execute(…)

Class3

  • Run() - Accepts parameters, starts Check(), and then calls Class2.wMAHY, which launches the malicious process.
  • Check() - Implements sandbox evasion. Checks for analysis tools every three seconds, deletes the folder if necessary, and forces a system restart.
  • D9AB4194(int) - Checks whether the launched process is still running.
  • 5481E4A7() - Restarts lbtly.ps1 if necessary.
  • 6433609D() - Watchdog function that launches multiple variants of jodjx.ps1. The scripts are only launched if the check finds no indications of running processes or components associated with Avast, AVG, or QHActiveDefense.
  • 3BA1AC81(int) - Terminates the specified process.

Class2
Performs Process Hollowing using installutil.exe.
Detailed sequence:

  1. Launches installutil.exe with its main thread suspended.
  2. Checks the payload for the MZ signature and verifies 32-/64-bit compatibility.
  3. Removes the original image from the target process using ZwUnmapViewOfSection.
  4. Allocates memory in the target process using VirtualAllocEx.
  5. Writes the payload into the target process using WriteProcessMemory.
  6. Sets the entry point to the payload.
  7. Resumes the main thread using ResumeThread.
  8. Returns the PID to Class3.

C2 Communication

lbtly_litHM.bin
SHA-256: 4576C76F4B14CC339355789ED0BCE92975288E70C4580F3559ED218642C76A11
Detect It Easy (DiE) results: Malware: XWorm (3.0-5.0) and Packer: Generic [Assembly invoke]
Based on its configuration, C2 commands, and detection by Detect It Easy, the payload was identified as belonging to the XWorm malware family.

Main()
Threads are used for C2 communication. The configuration values are encrypted using AES in ECB mode. Decryption is implemented in the AlgorithmAES class. ClientSocket and Messages handle C2 communication.

Decryption Decryption of the configuration values AlgorithmAES

An MD5 hash is calculated from Settings.Mutex and copied twice into the 32-byte array array. Due to the overlapping copy operations, array[15] is written twice, while array[31] remains unchanged with a value of 0x00. Values from Settings must first be Base64-decoded before they can be decrypted. This results in the following C2 communication data:

  • Hosts   porshe911[.]shop   “ki2k5Ddc/7ybrdG0Es2Wdg==”
  • Port   1337         “BLA3RVoDqeO8BLMOLHB/8Q==”
  • Key    [REDACTED]     “e[REDACTED]=”
  • SPL    Xwormmm       “+4k3B+7s0rFHbhtNugXN9g==”
  • Group   SPAM01       “hSsToL6YAfXgCZyFcwViJg==”
  • USBNM   USB.exe      “Bstd7UGdFarWK+1gGl+LCw==”

VirusTotal also associates the hostname with the JavaScript file analyzed in this report.

ClientSocket.BeginConnect()
Reads the host address from Settings.Hosts and then initiates the connection to the C2 server.

Messages.Read(byte[] b)
AlgorithmAES Processes incoming commands from the C2 server. The received data is encrypted and, after decryption, split into individual components using the SPL separator (Xwormmm). The commands are then evaluated through a chain of conditional statements. Examples include:

  • uninstall - Uninstall the malware
  • Update - New payload
  • FM - Execute the supplied payload in memory
  • PCLogoff - Log off the user
  • $Cap - Capture and send a screenshot

Additional Files

In addition to lbtly.ps1, four other scripts with an almost identical structure were identified.

The dxxAS.bin components extracted from the respective scripts all have the same SHA-256 hash, meaning that they contain identical loader code.

In contrast, the extracted litHM.bin components differ between the individual scripts and each have different hash values. Further analysis with dnSpyEx revealed differences in the Mutex values in particular. However, the overall structure and implemented functionality appear to be largely identical. The following table provides an overview of the five files analyzed, their corresponding program names, and the configured domain addresses.

ScriptProgram Name  Domain (Port:1337) 
gpcrr.ps1costarica.exeporshe911[.]shop
kadxn.ps1costarica.exeporshe911[.]shop
kphwh.ps1  TESTEE.exeporshe911[.]shop
lbtly.ps1SPAM01.exeporshe911[.]shop
xmlad.ps1XClient9.exeporshe911[.]shop /
34.228.244.82

Indicators of Compromise

Files / Folders

NU_Comprovante_47266772__82173625_72735278_Pdf.jsJavaScript-based initial loader
(SHA-256) B8AFB6B8731DB787BAF5CF62EE6CA33D73D186CB8277C505940D35DDD3B60D33
(MD5) B3B41B1A1DD2ED3E9047EFA4013D9AF1
hotel fazenda.txtText file containing contacted phone numbers
(SHA-256) CE394D023290A90763BB5CCFA53578527AECC8780292CD0A51E8CE60E7CFE9C1
(MD5) 7608F302A916AAAC5C633D6A2246C2F5
ss.txtText file containing the message that was sent
(SHA-256) 2A39BC707184A735F84A9DD7F2A27ADCF7CC5783FEDC205143F4878A8EF28666
(MD5) B653BDCC36ACD1BAE130FB8C9E66C43F
C:\Users[REDACTED]\AppData\LocalLow\Windows Sytem (x86)\Program Rules\Program Rules NVIDEO\Program Rules\Program Rules NVIDEO\Disguised directory containing the PowerShell components

C:\Users\Public\vvksx.jsCopied version of the JavaScript initial loader
C:\Users\Public\fprnk.ps1 Decoded PowerShell code from the initial loader
C:\Users\Public\lnzvp.txtFile used to store a subsequent URL
C:\Users\Public\fcthg.txtFile used to store downloaded payload data

Registry Values

HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\RunOnce – Update Drivers NVIDEO_*Persistence via RunOnce
HKCU:\SOFTWARE\Microsoft\Windows\CurrentVersion\Run – Update Drivers NVIDEO_*Persistence via Run

C2 and Download Infrastructure

hxxps://andrefelipedonascime1775471117328.2082219.meusitehostgator[.]com.br/FVTwhWzaQj_06_04_Meus_ArquivosDeTexto/03[.]txtSubsequent payload/configuration source
hxxps://andrefelipedona…/PeYesAdditional URL referenced in the code
andrefelipedonascime1775471117328.2082219.meusitehostgator[.]com[.]brSubsequent download/C2 infrastructure
porshe911[.]shopC2 domain
porshe9111[.]shop C2 domain from another payload variant
34.228.244.82Additional C2 address
1337C2 communication port
installutil.exeHost process used for Process Hollowing