Through our daily threat hunting, we noticed that, beginning in July 2025, a series of malicious wheel packages were uploaded to PyPI (the Python Package Index). We shared this information with the public security community, and the malware was removed from the repository. We submitted the samples to Kaspersky Threat Attribution Engine (KTAE) for analysis. Based on the results, we believe the packages may be linked to malware discussed in a Threat Intelligence report on OceanLotus.
While these wheel packages do implement the features described on their PyPI web pages, their true purpose is to covertly deliver malicious files. These files can be either .DLL or .SO (Linux shared library), indicating the packagesβ ability to target both Windows and Linux platforms. They function as droppers, delivering the final payload β a previously unknown malware family that we have named ZiChatBot. Unlike traditional malware, ZiChatBot does not communicate with a dedicated command and control (C2) server, but instead uses a series of REST APIs from the public team chat app Zulip as its C2 infrastructure.
To conceal the malicious package containing ZiChatBot, the attacker created another benign-looking package that included the malicious package as a dependency. Based on these facts, we confirm that this campaign is a carefully planned and executed PyPI supply chain attack.
Technical details
Spreading
The attacker created three projects on PyPI and uploaded malicious wheel packages designed to imitate popular libraries, tricking users into downloading them. This is a clear example of a supply chain attack via PyPI. See below for detailed information about the fake libraries and their corresponding wheel packages.
Malicious wheel packages
The packages added by the attacker and listed on PyPIβs download pages are:
uuid32-utils library for generating a 32-character random string as a UUID
colorinal library for implementing cross-platform color terminal text
termncolor library for ANSI color format for terminal output
The key metadata for these packages are as follows:
Pip install command
File name
First upload date
Author / Email
pip install uuid32-utils
uuid32_utils-1.x.x-py3-none-[OS platform].whl
2025-07-16
laz**** / laz****@tutamail.com
pip install colorinal
colorinal-0.1.7-py3-none-[OS platform].whl
2025-07-22
sym**** / sym****@proton.me
pip install termncolor
termncolor-3.1.0-py3-none-any.whl
2025-07-22
sym**** / sym****@proton.me
Based on the distribution information on the PyPI web page, we can see that it offers X86 and X64 versions for Windows, as well as an x86_64 version for Linux. The colorinal project, for example, provides the following download options:
Distribution information of the colorinal project
Initial infection
The uuid32-utils and colorinal libraries employ similar infection chains and malicious payloads. As a result, this analysis will focus on the colorinal library as a representative example.
A quick look at the code of the third library, termncolor, reveals no apparent malicious content. However, it imports the malicious colorinal library as a dependency. This method allows attackers to deeply conceal malware, making the termncolor library appear harmless when distributing it or luring targets.
The termncolor library imports the malicious colorinal library
During the initial infection stage, the Python code is nearly identical across both Windows and Linux platforms. Here, we analyze the Windows version as an example.
Windows version
Once a Python user downloads and installs the colorinal-0.1.7-py3-none-win_amd64.whl wheel package file, or installs it using the pip tool, the ZiChatBotβs dropper (a file named terminate.dll) will be extracted from the wheel package and placed on the victimβs hard drive.
After that, if the colorinal library is imported into the victimβs project, the Python script file at [Python library installation path]\colorinal-0.1.7-py3-none-win_amd64\colorinal\__init__.py will be executed first.
The __init__.py script imports the malicious file unicode.py
This Python script imports and executes another script located at [python library install path]\colorinal-0.1.7-py3-none-win_amd64\colorinal\unicode.py. The is_color_supported() function in unicode.py is called immediately.
The code loads the dropper into the host Python process
The comment in the is_color_supported() function states that the highlighted code checks whether the userβs terminal environment supports color. The code actually loads the terminate.dll file into the Python process and then invokes the DLLβs exported function envir, passing the UTF-8-encoded string xterminalunicod as a parameter. The DLL acts as a dropper, delivering the final payload, ZiChatBot, and then self-deleting. At the end of the is_color_supported() function, the unicode.py script file is also removed. These steps eliminate all malicious files in the library and deploy ZiChatBot.
For the Linux platform, the wheel package and the unicode.py Python script are nearly identical to the Windows version. The only difference is that the dropper file is named βterminate.soβ.
Dropper for ZiChatBot
From the previous analysis, we learned that the dropper is loaded into the host Python process by a Python script and then activated. The main logic of the dropper is implemented in the envir export function to achieve three objectives:
Deploy ZiChatBot.
Establish an auto-run mechanism.
Execute shellcode to remove the dropper file (terminate.dll) and the malicious script file from the installed library folder.
The dropper first decrypts sensitive strings using AES in CBC mode. The key is the string-type parameter βxterminalunicodeβ of the exported function. The decrypted strings are βlibcef.dllβ, βvcpacketβ, βpkt-updateβ, and βvcpktsvr.exeβ.
Next, the malware uses the same algorithm to decrypt the embedded data related to ZiChatBot. It then decompresses the decrypted data with LZMA to retrieve the files vcpktsvr.exe and libcef.dll associated with ZiChatBot. The malware creates a folder named vcpacket in the system directory %LOCALAPPDATA%, and places these files into it.
To establish persistence for ZiChatBot, the dropper creates the following auto-run entry in the registry:
Once preparations are complete, the malware uses the XOR algorithm to decrypt the embedded shellcode with the three-byte key 3a7. It then searches the decrypted shellcodeβs memory for the string Policy.dllcppage.dll and replaces it with its own file name, terminate.dll, and redirects execution to the shellcodeβs memory space.
The shellcode employs a djb2-like hash method to calculate the names of certain APIs and locate their addresses. Using these APIs, it finds the dropper file with the name terminate.dll that was previously passed by the DLL before unloading and deleting it.
Linux version
The Linux version of the dropper places ZiChatBot in the path /tmp/obsHub/obs-check-update and then creates an auto-run job using crontab. Unlike the Windows version, the Linux version of ZiChatBot only consists of one ELF executable file.
The Windows version of ZiChatBot is a DLL file (libcef.dll) that is loaded by the legitimate executable vcpktsvr.exe (hash: 48be833b0b0ca1ad3cf99c66dc89c3f4). The DLL contains several export functions, with the malicious code implemented in the cef_api_mash export. Once the DLL is loaded, this function is invoked by the EXE file. ZiChatBot uses the REST APIs from Zulip, a public team chat application, as its command and control server.
ZiChatBot is capable of executing shellcode received from the server and only supports this one control command. Once it runs, it initiates a series of sequential HTTP requests to the Zulip REST API.
In each HTTP request, an API authentication token is included as an HTTP header for server-side authentication, as shown below.
ZiChatBot utilizes two separate channel-topic pairs for its operations. One pair transmits current system information, and the other retrieves a message containing shellcode. Once the shellcode is received, a new thread is created to execute it. After executing the command, a heart emoji is sent in response to the original message to indicate the execution was successful.
Infrastructure
We did not find any traditional infrastructure, such as compromised servers or commercial VPS services and their associated IPs and domains. Instead, the malicious wheel packages were uploaded to the Python Package Index (PyPI), a public, shared Python library. The malware, ZiChatBot, leverages Zulipβs public team chat REST APIs as its command and control server.
The βhelperβ organization that the attacker had registered on the Zulip service has now been officially deactivated by Zulip. However, infected devices may still attempt to connect to the service, so to help you locate and cure them, we recommend adding the full URL helper.zulipchat.com to your denylist.
Victims
The malware was uploaded in July 2025. Upon discovering these attacks, we quickly released an update for our product to detect the relevant files and shared the necessary information with the public security community. As a result, the malicious software was swiftly removed from PyPI, and the organization registered on the Zulip service was officially deactivated. To date, we have not observed any infections based on our telemetry or public reports.
Zulip has officially deactivated the βhelperβ organization
Attribution
Based on the results from our KTAE system, the dropper used by ZiChatBot shows a 64% similarity to another dropper we analyzed in a TI report, which was linked to OceanLotus. Reverse engineering shows that both droppers use nearly identical algorithms and logic for to decrypt and decompress their embedded payloads.
Analysis results of dropper using KTAE system
Conclusions
As an active APT organization, OceanLotus primarily targets victims in the Asia-Pacific region. However, our previous reports have highlighted a growing trend of the group expanding its activities into the Middle East. Moreover, the attacks described in this report β executed through PyPI β target Python users worldwide. This demonstrates OceanLotusβs ongoing effort to broaden its attack scope.
In the first half of 2025, a public report revealed that the group launched a phishing campaign using GitHub. The recent PyPI-based supply chain attack likely continues this strategy. Although phishing emails are still a common initial infection method for OceanLotus, the group is also actively exploring new ways to compromise victims through diverse supply chain attacks.
Through our daily threat hunting, we noticed that, beginning in July 2025, a series of malicious wheel packages were uploaded to PyPI (the Python Package Index). We shared this information with the public security community, and the malware was removed from the repository. We submitted the samples to Kaspersky Threat Attribution Engine (KTAE) for analysis. Based on the results, we believe the packages may be linked to malware discussed in a Threat Intelligence report on OceanLotus.
While these wheel packages do implement the features described on their PyPI web pages, their true purpose is to covertly deliver malicious files. These files can be either .DLL or .SO (Linux shared library), indicating the packagesβ ability to target both Windows and Linux platforms. They function as droppers, delivering the final payload β a previously unknown malware family that we have named ZiChatBot. Unlike traditional malware, ZiChatBot does not communicate with a dedicated command and control (C2) server, but instead uses a series of REST APIs from the public team chat app Zulip as its C2 infrastructure.
To conceal the malicious package containing ZiChatBot, the attacker created another benign-looking package that included the malicious package as a dependency. Based on these facts, we confirm that this campaign is a carefully planned and executed PyPI supply chain attack.
Technical details
Spreading
The attacker created three projects on PyPI and uploaded malicious wheel packages designed to imitate popular libraries, tricking users into downloading them. This is a clear example of a supply chain attack via PyPI. See below for detailed information about the fake libraries and their corresponding wheel packages.
Malicious wheel packages
The packages added by the attacker and listed on PyPIβs download pages are:
uuid32-utils library for generating a 32-character random string as a UUID
colorinal library for implementing cross-platform color terminal text
termncolor library for ANSI color format for terminal output
The key metadata for these packages are as follows:
Pip install command
File name
First upload date
Author / Email
pip install uuid32-utils
uuid32_utils-1.x.x-py3-none-[OS platform].whl
2025-07-16
laz**** / laz****@tutamail.com
pip install colorinal
colorinal-0.1.7-py3-none-[OS platform].whl
2025-07-22
sym**** / sym****@proton.me
pip install termncolor
termncolor-3.1.0-py3-none-any.whl
2025-07-22
sym**** / sym****@proton.me
Based on the distribution information on the PyPI web page, we can see that it offers X86 and X64 versions for Windows, as well as an x86_64 version for Linux. The colorinal project, for example, provides the following download options:
Distribution information of the colorinal project
Initial infection
The uuid32-utils and colorinal libraries employ similar infection chains and malicious payloads. As a result, this analysis will focus on the colorinal library as a representative example.
A quick look at the code of the third library, termncolor, reveals no apparent malicious content. However, it imports the malicious colorinal library as a dependency. This method allows attackers to deeply conceal malware, making the termncolor library appear harmless when distributing it or luring targets.
The termncolor library imports the malicious colorinal library
During the initial infection stage, the Python code is nearly identical across both Windows and Linux platforms. Here, we analyze the Windows version as an example.
Windows version
Once a Python user downloads and installs the colorinal-0.1.7-py3-none-win_amd64.whl wheel package file, or installs it using the pip tool, the ZiChatBotβs dropper (a file named terminate.dll) will be extracted from the wheel package and placed on the victimβs hard drive.
After that, if the colorinal library is imported into the victimβs project, the Python script file at [Python library installation path]\colorinal-0.1.7-py3-none-win_amd64\colorinal\__init__.py will be executed first.
The __init__.py script imports the malicious file unicode.py
This Python script imports and executes another script located at [python library install path]\colorinal-0.1.7-py3-none-win_amd64\colorinal\unicode.py. The is_color_supported() function in unicode.py is called immediately.
The code loads the dropper into the host Python process
The comment in the is_color_supported() function states that the highlighted code checks whether the userβs terminal environment supports color. The code actually loads the terminate.dll file into the Python process and then invokes the DLLβs exported function envir, passing the UTF-8-encoded string xterminalunicod as a parameter. The DLL acts as a dropper, delivering the final payload, ZiChatBot, and then self-deleting. At the end of the is_color_supported() function, the unicode.py script file is also removed. These steps eliminate all malicious files in the library and deploy ZiChatBot.
For the Linux platform, the wheel package and the unicode.py Python script are nearly identical to the Windows version. The only difference is that the dropper file is named βterminate.soβ.
Dropper for ZiChatBot
From the previous analysis, we learned that the dropper is loaded into the host Python process by a Python script and then activated. The main logic of the dropper is implemented in the envir export function to achieve three objectives:
Deploy ZiChatBot.
Establish an auto-run mechanism.
Execute shellcode to remove the dropper file (terminate.dll) and the malicious script file from the installed library folder.
The dropper first decrypts sensitive strings using AES in CBC mode. The key is the string-type parameter βxterminalunicodeβ of the exported function. The decrypted strings are βlibcef.dllβ, βvcpacketβ, βpkt-updateβ, and βvcpktsvr.exeβ.
Next, the malware uses the same algorithm to decrypt the embedded data related to ZiChatBot. It then decompresses the decrypted data with LZMA to retrieve the files vcpktsvr.exe and libcef.dll associated with ZiChatBot. The malware creates a folder named vcpacket in the system directory %LOCALAPPDATA%, and places these files into it.
To establish persistence for ZiChatBot, the dropper creates the following auto-run entry in the registry:
Once preparations are complete, the malware uses the XOR algorithm to decrypt the embedded shellcode with the three-byte key 3a7. It then searches the decrypted shellcodeβs memory for the string Policy.dllcppage.dll and replaces it with its own file name, terminate.dll, and redirects execution to the shellcodeβs memory space.
The shellcode employs a djb2-like hash method to calculate the names of certain APIs and locate their addresses. Using these APIs, it finds the dropper file with the name terminate.dll that was previously passed by the DLL before unloading and deleting it.
Linux version
The Linux version of the dropper places ZiChatBot in the path /tmp/obsHub/obs-check-update and then creates an auto-run job using crontab. Unlike the Windows version, the Linux version of ZiChatBot only consists of one ELF executable file.
The Windows version of ZiChatBot is a DLL file (libcef.dll) that is loaded by the legitimate executable vcpktsvr.exe (hash: 48be833b0b0ca1ad3cf99c66dc89c3f4). The DLL contains several export functions, with the malicious code implemented in the cef_api_mash export. Once the DLL is loaded, this function is invoked by the EXE file. ZiChatBot uses the REST APIs from Zulip, a public team chat application, as its command and control server.
ZiChatBot is capable of executing shellcode received from the server and only supports this one control command. Once it runs, it initiates a series of sequential HTTP requests to the Zulip REST API.
In each HTTP request, an API authentication token is included as an HTTP header for server-side authentication, as shown below.
ZiChatBot utilizes two separate channel-topic pairs for its operations. One pair transmits current system information, and the other retrieves a message containing shellcode. Once the shellcode is received, a new thread is created to execute it. After executing the command, a heart emoji is sent in response to the original message to indicate the execution was successful.
Infrastructure
We did not find any traditional infrastructure, such as compromised servers or commercial VPS services and their associated IPs and domains. Instead, the malicious wheel packages were uploaded to the Python Package Index (PyPI), a public, shared Python library. The malware, ZiChatBot, leverages Zulipβs public team chat REST APIs as its command and control server.
The βhelperβ organization that the attacker had registered on the Zulip service has now been officially deactivated by Zulip. However, infected devices may still attempt to connect to the service, so to help you locate and cure them, we recommend adding the full URL helper.zulipchat.com to your denylist.
Victims
The malware was uploaded in July 2025. Upon discovering these attacks, we quickly released an update for our product to detect the relevant files and shared the necessary information with the public security community. As a result, the malicious software was swiftly removed from PyPI, and the organization registered on the Zulip service was officially deactivated. To date, we have not observed any infections based on our telemetry or public reports.
Zulip has officially deactivated the βhelperβ organization
Attribution
Based on the results from our KTAE system, the dropper used by ZiChatBot shows a 64% similarity to another dropper we analyzed in a TI report, which was linked to OceanLotus. Reverse engineering shows that both droppers use nearly identical algorithms and logic for to decrypt and decompress their embedded payloads.
Analysis results of dropper using KTAE system
Conclusions
As an active APT organization, OceanLotus primarily targets victims in the Asia-Pacific region. However, our previous reports have highlighted a growing trend of the group expanding its activities into the Middle East. Moreover, the attacks described in this report β executed through PyPI β target Python users worldwide. This demonstrates OceanLotusβs ongoing effort to broaden its attack scope.
In the first half of 2025, a public report revealed that the group launched a phishing campaign using GitHub. The recent PyPI-based supply chain attack likely continues this strategy. Although phishing emails are still a common initial infection method for OceanLotus, the group is also actively exploring new ways to compromise victims through diverse supply chain attacks.
A significant proportion of cyberincidents are linked to supply chain attacks, and this proportion is constantly growing. Over the past year, we have seen a wide variety of methods used in such attacks, ranging from creation of malicious but seemingly legitimate open-source libraries or delayed attacks in such seemingly legitimate libraries, to the simplest yet most effective method: compromising the accounts of popular library owners to subsequently release malicious versions of their libraries. Such libraries are used by developers everywhere and are included in many solutions and services. The consequences of an attack can vary widely, ranging from delivering malware to a developerβs device to compromising an entire infrastructure if the malicious library has made its way into the code of a service or product.
This is exactly what happened in March 2026, when attackers injected malicious code into the popular Python library LiteLLM, which serves as a multifunctional gateway for a large set of AI agents. The attackers released two trojanized versions of LiteLLM that delivered malicious scripts to the victimβs system. Both versions made their way into the PyPI repository for Python. A technical analysis revealed that the attackersβ primary targets were servers storing confidential data related to AWS, Kubernetes, NPM, etc., as well as various databases (MySQL, PostgreSQL, MongoDB, etc.). In the latter case, the attackers were primarily interested in database configurations. In addition, the malwareβs logic included functionality for stealing confidential data from crypto wallets and techniques for establishing a foothold in the Kubernetes cluster.
Repository compromise
The compromise affected the package distribution channel via PyPI: on March 24, 2026, malicious LiteLLM versions litellm==1.82.7 and litellm==1.82.8 were uploaded to the registry. It was specifically the packageβs distribution contents that were compromised: in version 1.82.7, the malicious code was embedded in proxy_server.py, and in 1.82.8, the file litellm_init.pth was added.
Technical analysis
Both versions of the library contained the same malicious code, but its execution was implemented differently. In version 1.82.7, it was executed only when the proxy functionality was imported, while in 1.82.8, a .pth file was added that was able to execute the code every time the interpreter started.
Example of the malicious code in proxy_server.py
The malicious code in the proxy_server.py and litellm_init.pth files contained Python code encoded in Base64. After execution, the infected script saved this code alongside itself as a p.py file and immediately executed it.
The p.py script launched the main payload β another script, also encoded in Base64 β without saving it to disk. At the same time, it wrote the output of this payload to a file in the directory from which it was launched. Before being written, the output was encrypted using the AES-256-CBC algorithm with a random key generated in the code, which was saved to the session.key file. The key file was also encrypted β using a pre-initialized public RSA key.
The encrypted key and the output were combined into a tpcp.tar.gz archive and sent to the attackersβ remote server.
What exactly happened within the malicious payload whose output was sent to the C2 server? After it was launched, a recursive scan of the working directories on the victimβs system (/root, /app/, /var/www, etc.) began. In each directory, the script scanned the contents of files, which it output to the stdout buffer, from where it was then saved to the aforementioned file as the result. Next, the script collected system information and also saved it to the file. After that, it proceeded to search for sensitive data. It was interested in the following data located on servers and within the infrastructures of various services:
SSH keys
GIT accounts
.env files
AWS, Kubernetes, email service, database, and WireGuard configurations
files related to Helm, Terraform, and CI
TLS keys and certificates
A notable feature of this malware is that it does not limit itself to stealing files and configurations from the disk but also attempts to extract runtime secrets from the cloud infrastructure.
The code above uses the addresses 169.254.169.254 and 169.254.170.2. The first corresponds to the AWS Instance Metadata Service (IMDS), through which an EC2 instance (a virtual server in AWS, a machine running in the cloud) can retrieve metadata and temporary IAM role credentials (an AWS account with a set of permissions that a service or application can use to obtain temporary credentials for calls to the AWS API). The second is used in Amazon ECS to issue temporary credentials to a container during execution. Thus, the malicious script targets not only static secrets but also those issued by the cloud that can grant direct access to AWS resources at the time of infection.
Additionally, the script searches for crypto wallet configurations, as well as webhooks associated with Slack and Discord messengers. The latter indicates that the attackers are interested not only in infrastructure secrets and accounts, but also in communication channels within the development team.
In the next stage, the malware moves from data collection to establishing a foothold in the Kubernetes cluster infrastructure: if it has sufficient access, it configures a privileged pod (the smallest execution unit in Kubernetes, containing one or more containers) by enabling the securityContext.privileged=true option and mounts the nodeβs root filesystem via hostPath. This allows it to escape the container and perform actions at the node level.
Next, the malware executes another stage of infection: it saves a Base64-encoded script disguised as a legitimate system component to the Kubernetes nodeβs disk at the path /root/.config/sysmon/sysmon.py, and registers it via systemd. After launching, the script waits for an initial delay of 300 seconds, then begins periodically contacting the C2 node checkmarx[.]zone/raw, retrieving a link to the next payload from there. If the received value differs from the state previously saved in /tmp/.pg_state, the script downloads a new file to /tmp/pglog, makes it executable, and runs it in the background. At this stage, the attackers gain a foothold in the system and are capable of regularly delivering updated payloads without the need for re-injection. Since the malicious payload is written not to the containerβs temporary file directory but directly to the Kubernetes cluster node, the attackers will retain access to the infrastructure even after the container has terminated.
A similar scenario is used for local persistence: in the absence of Kubernetes, the sysmon.py script is deployed in the userβs directory at ~/.config/sysmon/sysmon.py and is also registered as a service via systemd.
OpenVSX version of the malware
While analyzing files communicating with the C2 server, we discovered malicious versions of two common Checkmarx software extensions: ast-results 2.53.0 and cx-dev-assist 1.7.0. Checkmarx is used for application security assessment. These trojanized extensions contained malicious code that delivered the NodeJS version of the malware described above.
This version is downloaded from checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz using NodeJS package installation utilities and is named checkmarx-util. Its key difference from the Python version is that it does not attempt to elevate privileges to the Kubernetes node level and does not create a privileged pod for persistence. Instead, it implements local persistence within the current environment. This means that the NodeJS variant persists only where it is already running.
Additionally, the list of folders to search for and steal secrets from is significantly smaller in this version than in the Python variant.
Checkmarx extensions are used to scan code and infrastructure configurations, so their compromise is quite dangerous: an attacker gains access not only to project files but also to a significant portion of the development environment, tokens, and local configurations.
Victimology
While assessing the attackβs impact, we saw victims all over the world. Most infection attempts occurred in Russia, China, Brazil, the Netherlands, and UAE.
Conclusion
As the technical analysis shows, the malicious scripts found in the LiteLLM versions are dangerous not only because they steal files containing sensitive data, but also because they target multiple critical infrastructure components simultaneously: the local system, cloud runtime secrets, the Kubernetes cluster, and even cryptographic keys. Such a broad scope of data collection allows an attacker to quickly move from compromising a single system and Python environment to seizing service accounts, secrets, and entire infrastructures.
Prevention and protection
To protect against infections of this kind, we recommend using a specialized solution for monitoring open-source components. Kaspersky provides real-time data feeds on compromised packages and libraries, which can be used to secure the supply chain and protect development projects from such threats.
Home security solutions, such as Kaspersky Premium, help ensure the security of personal devices by providing multi-layered protection that prevents and neutralizes infection threats. Additionally, our solution can restore the deviceβs functionality in the event of a malware infection.
To protect corporate devices, we recommend using a complex solution such as Kaspersky NEXT, which allows you to build a flexible and effective security system. The products in this line provide threat visibility and real-time protection, as well as EDR and XDR capabilities for threat investigation and response.
At the time of writing, the compromised versions of LiteLLM had already been removed from PyPI and OpenVSX. If you have used them, and as a proactive response to the threat, we recommend taking the following measures on your systems and infrastructure:
Perform a full system scan using a reliable security solution.
Rotate all potentially compromised credentials: API keys, environment variables, SSH keys, Kubernetes service account tokens, and other secrets.
Check hosts and clusters for signs of compromise: the presence of ~/.config/sysmon/sysmon.py files and suspicious pods in Kubernetes.
Clear the cache and conduct an inventory of PyPI modules: check for malicious ones and roll back to clean versions.
Check for indicators of compromise (files on the system or network signs).
A significant proportion of cyberincidents are linked to supply chain attacks, and this proportion is constantly growing. Over the past year, we have seen a wide variety of methods used in such attacks, ranging from creation of malicious but seemingly legitimate open-source libraries or delayed attacks in such seemingly legitimate libraries, to the simplest yet most effective method: compromising the accounts of popular library owners to subsequently release malicious versions of their libraries. Such libraries are used by developers everywhere and are included in many solutions and services. The consequences of an attack can vary widely, ranging from delivering malware to a developerβs device to compromising an entire infrastructure if the malicious library has made its way into the code of a service or product.
This is exactly what happened in March 2026, when attackers injected malicious code into the popular Python library LiteLLM, which serves as a multifunctional gateway for a large set of AI agents. The attackers released two trojanized versions of LiteLLM that delivered malicious scripts to the victimβs system. Both versions made their way into the PyPI repository for Python. A technical analysis revealed that the attackersβ primary targets were servers storing confidential data related to AWS, Kubernetes, NPM, etc., as well as various databases (MySQL, PostgreSQL, MongoDB, etc.). In the latter case, the attackers were primarily interested in database configurations. In addition, the malwareβs logic included functionality for stealing confidential data from crypto wallets and techniques for establishing a foothold in the Kubernetes cluster.
Repository compromise
The compromise affected the package distribution channel via PyPI: on March 24, 2026, malicious LiteLLM versions litellm==1.82.7 and litellm==1.82.8 were uploaded to the registry. It was specifically the packageβs distribution contents that were compromised: in version 1.82.7, the malicious code was embedded in proxy_server.py, and in 1.82.8, the file litellm_init.pth was added.
Technical analysis
Both versions of the library contained the same malicious code, but its execution was implemented differently. In version 1.82.7, it was executed only when the proxy functionality was imported, while in 1.82.8, a .pth file was added that was able to execute the code every time the interpreter started.
Example of the malicious code in proxy_server.py
The malicious code in the proxy_server.py and litellm_init.pth files contained Python code encoded in Base64. After execution, the infected script saved this code alongside itself as a p.py file and immediately executed it.
The p.py script launched the main payload β another script, also encoded in Base64 β without saving it to disk. At the same time, it wrote the output of this payload to a file in the directory from which it was launched. Before being written, the output was encrypted using the AES-256-CBC algorithm with a random key generated in the code, which was saved to the session.key file. The key file was also encrypted β using a pre-initialized public RSA key.
The encrypted key and the output were combined into a tpcp.tar.gz archive and sent to the attackersβ remote server.
What exactly happened within the malicious payload whose output was sent to the C2 server? After it was launched, a recursive scan of the working directories on the victimβs system (/root, /app/, /var/www, etc.) began. In each directory, the script scanned the contents of files, which it output to the stdout buffer, from where it was then saved to the aforementioned file as the result. Next, the script collected system information and also saved it to the file. After that, it proceeded to search for sensitive data. It was interested in the following data located on servers and within the infrastructures of various services:
SSH keys
GIT accounts
.env files
AWS, Kubernetes, email service, database, and WireGuard configurations
files related to Helm, Terraform, and CI
TLS keys and certificates
A notable feature of this malware is that it does not limit itself to stealing files and configurations from the disk but also attempts to extract runtime secrets from the cloud infrastructure.
The code above uses the addresses 169.254.169.254 and 169.254.170.2. The first corresponds to the AWS Instance Metadata Service (IMDS), through which an EC2 instance (a virtual server in AWS, a machine running in the cloud) can retrieve metadata and temporary IAM role credentials (an AWS account with a set of permissions that a service or application can use to obtain temporary credentials for calls to the AWS API). The second is used in Amazon ECS to issue temporary credentials to a container during execution. Thus, the malicious script targets not only static secrets but also those issued by the cloud that can grant direct access to AWS resources at the time of infection.
Additionally, the script searches for crypto wallet configurations, as well as webhooks associated with Slack and Discord messengers. The latter indicates that the attackers are interested not only in infrastructure secrets and accounts, but also in communication channels within the development team.
In the next stage, the malware moves from data collection to establishing a foothold in the Kubernetes cluster infrastructure: if it has sufficient access, it configures a privileged pod (the smallest execution unit in Kubernetes, containing one or more containers) by enabling the securityContext.privileged=true option and mounts the nodeβs root filesystem via hostPath. This allows it to escape the container and perform actions at the node level.
Next, the malware executes another stage of infection: it saves a Base64-encoded script disguised as a legitimate system component to the Kubernetes nodeβs disk at the path /root/.config/sysmon/sysmon.py, and registers it via systemd. After launching, the script waits for an initial delay of 300 seconds, then begins periodically contacting the C2 node checkmarx[.]zone/raw, retrieving a link to the next payload from there. If the received value differs from the state previously saved in /tmp/.pg_state, the script downloads a new file to /tmp/pglog, makes it executable, and runs it in the background. At this stage, the attackers gain a foothold in the system and are capable of regularly delivering updated payloads without the need for re-injection. Since the malicious payload is written not to the containerβs temporary file directory but directly to the Kubernetes cluster node, the attackers will retain access to the infrastructure even after the container has terminated.
A similar scenario is used for local persistence: in the absence of Kubernetes, the sysmon.py script is deployed in the userβs directory at ~/.config/sysmon/sysmon.py and is also registered as a service via systemd.
OpenVSX version of the malware
While analyzing files communicating with the C2 server, we discovered malicious versions of two common Checkmarx software extensions: ast-results 2.53.0 and cx-dev-assist 1.7.0. Checkmarx is used for application security assessment. These trojanized extensions contained malicious code that delivered the NodeJS version of the malware described above.
This version is downloaded from checkmarx[.]zone/static/checkmarx-util-1.0.4.tgz using NodeJS package installation utilities and is named checkmarx-util. Its key difference from the Python version is that it does not attempt to elevate privileges to the Kubernetes node level and does not create a privileged pod for persistence. Instead, it implements local persistence within the current environment. This means that the NodeJS variant persists only where it is already running.
Additionally, the list of folders to search for and steal secrets from is significantly smaller in this version than in the Python variant.
Checkmarx extensions are used to scan code and infrastructure configurations, so their compromise is quite dangerous: an attacker gains access not only to project files but also to a significant portion of the development environment, tokens, and local configurations.
Victimology
While assessing the attackβs impact, we saw victims all over the world. Most infection attempts occurred in Russia, China, Brazil, the Netherlands, and UAE.
Conclusion
As the technical analysis shows, the malicious scripts found in the LiteLLM versions are dangerous not only because they steal files containing sensitive data, but also because they target multiple critical infrastructure components simultaneously: the local system, cloud runtime secrets, the Kubernetes cluster, and even cryptographic keys. Such a broad scope of data collection allows an attacker to quickly move from compromising a single system and Python environment to seizing service accounts, secrets, and entire infrastructures.
Prevention and protection
To protect against infections of this kind, we recommend using a specialized solution for monitoring open-source components. Kaspersky provides real-time data feeds on compromised packages and libraries, which can be used to secure the supply chain and protect development projects from such threats.
Home security solutions, such as Kaspersky Premium, help ensure the security of personal devices by providing multi-layered protection that prevents and neutralizes infection threats. Additionally, our solution can restore the deviceβs functionality in the event of a malware infection.
To protect corporate devices, we recommend using a complex solution such as Kaspersky NEXT, which allows you to build a flexible and effective security system. The products in this line provide threat visibility and real-time protection, as well as EDR and XDR capabilities for threat investigation and response.
At the time of writing, the compromised versions of LiteLLM had already been removed from PyPI and OpenVSX. If you have used them, and as a proactive response to the threat, we recommend taking the following measures on your systems and infrastructure:
Perform a full system scan using a reliable security solution.
Rotate all potentially compromised credentials: API keys, environment variables, SSH keys, Kubernetes service account tokens, and other secrets.
Check hosts and clusters for signs of compromise: the presence of ~/.config/sysmon/sysmon.py files and suspicious pods in Kubernetes.
Clear the cache and conduct an inventory of PyPI modules: check for malicious ones and roll back to clean versions.
Check for indicators of compromise (files on the system or network signs).
In October 2025, we discovered a series of forum posts advertising a previously unknown stealer, dubbed βArkanix Stealerβ by its authors. It operated under a MaaS (malware-as-a-service) model, providing users not only with the implant but also with access to a control panel featuring configurable payloads and statistics. The set of implants included a publicly available browser post-exploitation tool known as ChromElevator, which was delivered by a native C++ version of the stealer. This version featured a wide range of capabilities, from collecting system information to stealing cryptocurrency wallet data. Alongside that, we have also discovered Python implementation of the stealer capable of dynamically modifying its configuration. The Python version was often packed, thus giving the adversary multiple methods for distributing their malware. It is also worth noting that Arkanix was rather a one-shot malicious campaign: at the time of writing this article, the affiliate program appears to be already taken down.
Kaspersky products detect this threat as Trojan-PSW.Win64.Coins.*, HEUR:Trojan-PSW.Multi.Disco.gen, Trojan.Python.Agent.*.
Technical details
Background
In October 2025, a series of posts was discovered on various dark web forums, advertising a stealer referred to by its author as βArkanix Stealerβ. These posts detail the features of the stealer and include a link to a Discord server, which serves as the primary communication channel between the author and the users of the stealer.
Example of an Arkanix Stealer advertisement
Upon further research utilizing public resources, we identified a set of implants associated with this stealer.
Initial infection or spreading
The initial infection vector remains unknown. However, based on some of the file names (such as steam_account_checker_pro_v1.py, discord_nitro_checker.py, and TikTokAccountBotter.exe) of the loader scripts we obtained, it can be concluded with high confidence that the initial infection vector involved phishing.
Python loader
MD5
208fa7e01f72a50334f3d7607f6b82bf
File name
discord_nitro_code_validator_right_aligned.py
The Python loader is the script responsible for downloading and executing the Python-based version of the Arkanix infostealer. We have observed both plaintext Python scripts and those bundled using PyInstaller or Nuitka, all of which share a common execution vector and are slightly obfuscated. These scripts often serve as decoys, initially appearing to contain legitimate code. Some of them do have useful functionality, and others do nothing apart from loading the stealer. Additionally, we have encountered samples that employ no obfuscation at all, in which the infostealer is launched in a separate thread via Pythonβs built-in threading module.
Variants of Python loaders executing the next stage
Upon execution, the loader first installs the required packages β namely, requests, pycryptodome, and psutil β via the pip package manager, utilizing the subprocess module. On Microsoft Windows systems, the loader also installs pywin32. In some of the analyzed samples, this process is carried out twice. Since the loader does not perform any output validation of the module installation command, it proceeds to make a POST request to hxxps://arkanix[.]pw/api/session/create to register the current compromised machine on the panel with a predefined set of parameters even if the installation failed. After that, the stealer makes a GET request to hxxps://arkanix[.]pw/stealer.py and executes the downloaded payload.
Python stealer version
MD5
af8fd03c1ec81811acf16d4182f3b5e1
File name
β
During our research, we obtained a sample of the Python implementation of the Arkanix stealer, which was downloaded from the endpoint hxxps://arkanix[.]pw/stealer.py by the previous stage.
The stealerβs capabilities β or features, as referred to by the author β in this version are configurable, with the default configuration predefined within the script file. To dynamically update the feature list, the stealer makes a GET request to hxxps://arkanix[.]pw/api/features/{payload_id}, indicating that these capabilities can be modified on the panel side. The feature list is identical to the one that was described in the GDATA report.
Configurable options
Prior to executing the information retrieval-related functions, the stealer makes a request to hxxps://arkanix[.]pw/upload_dropper.py, saves the response to %TEMP%\upd_{random 8-byte name}.py, and executes it. We do not have access to the contents of this script, which is referred to as the βdropperβ by the attackers.
During its main information retrieval routine, at the end of each processing stage, the collected information is serialized into JSON format and saved to a predefined path, such as %LOCALAPPDATA\Arkanix_lol\%info_class%.json.
In the following, we will provide a more detailed description of the Python versionβs data collection features.
System info collection
Arkanix Stealer is capable of collecting a set of info about the compromised system. This info includes:
OS version
CPU and GPU info
RAM size
Screen resolution
Keyboard layout
Time zone
Installed software
Antivirus software
VPN
Information collection is performed using standard shell commands with the exception of the VPN check. The latter is implemented by querying the endpoint hxxps://ipapi[.]co/json/ and verifying whether the associated IP address belongs to a known set of VPNs, proxies, or Tor exit nodes.
Browser features
This stealer is capable of extracting various types of data from supported browsers (22 in total, ranging from the widely popular Google Chrome to the Tor Browser). The list of supported browsers is hardcoded, and unlike other parameters, it cannot be modified during execution. In addition to a separate Chrome grabber module (which weβll discuss later), the stealer itself supports the extraction of diverse information, such as:
Browser history (URLs, visit count and last visit)
Autofill information (email, phone, addresses and payment cards details)
Saved passwords
Cookies
In case of Chromium-based browsers, 0Auth2 data is also extracted
All information is decrypted using either the Windows DPAPI or AES, where applicable, and searched for relevant keywords. In the case of browser information collection, the stealer searches exclusively for keywords related to banking (e.g., βrevolutβ, βstripeβ, βbankβ) and cryptocurrencies (e.g., βbinanceβ, βmetamaskβ, βwalletβ). In addition to this, the stealer is capable of extracting extension data from a hardcoded list of extensions associated with cryptocurrencies.
Part of the extension list which the stealer utilizes to extract data from
Telegram info collection
Telegram data collection begins with terminating the Telegram.exe process using the taskkill command. Subsequently, if the telegram_optimized feature is set to False, the malware zips the entire tdata directory (typically located at %APPDATA%\Roaming\Telegram Desktop\tdata) and transmits it to the attacker. Otherwise, it selectively copies and zips only the subdirectories containing valuable info, such as message log. The generated archive is sent to the endpoint /delivery with the filename tdata_session.zip.
Discord capabilities
The stealer includes two features connected with Discord: credentials stealing and self-spreading. The first one can be utilized to acquire credentials both from the standard client and custom clients. If the client is Chromium-based, the stealer employs the same data exfiltration mechanism as during browser credentials stealing.
The self-spreading feature is configurable (meaning it can be disabled in the config). The stealer acquires the list of userβs friends and channels via the Discord API and sends a message provided by the attacker. This stealer does not support attaching files to such messages.
VPN data collection
The VPN collector is searching for a set of known VPN software to extract account credentials from the credentials file with a known path that gets parsed with a regular expression. The extraction occurs from the following set of applications:
Mullvad VPN
NordVPN
ExpressVPN
ProtonVPN
File retrieval
File retrieval is performed regardless of the configuration. The script relies on a predefined set of paths associated with the current user (such as Desktop, Download, etc.) and file extensions mainly connected with documents and media. The script also has a predefined list of filenames to exfiltrate. The extracted files are packed into a ZIP archive which is later sent to the C2 asynchronously. An interesting aspect is that the filename list includes several French words, such as βmotdepasseβ (French for βpasswordβ), βbanqueβ (French for βbankβ), βsecretβ (French for βsecretβ), and βcompteβ (French for βaccountβ).
Other payloads
We were able to identify additional modules that are downloaded from the C2 rather than embedded into the stealer script; however, we werenβt able to obtain them. These modules can be described by the following table, with the βDetailsβ column referring to the information that could be extracted from the main stealer code.
Module name
Endpoint to download
Details
Chrome grabber
/api/chrome-grabber-template/{payload_id}
β
Wallet patcher
/api/wallet-patcher/{payload_id}
Checks whether βExodusβ and βAtomicβ cryptocurrency wallets are installed
Extra collector
/api/extra-collector/{payload_id}
Uses a set of options from the config, such as collect_filezilla, collect_vpn_data, collect_steam, and collect_screenshots
HVNC
/hvnc
Is saved to the Startup directory (%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\hvnc.py) to execute upon system boot
The Wallet patcher and Extra collector scripts are received in an encrypted form from the C2 server. To decrypt them, the attackers utilize the AES-GCM algorithm in conjunction with PBKDF2 (HMAC and SHA256). After decryption, the additional payload has its template placeholders replaced and is stored under a partially randomized name within a temporary folder.
Decryption routine and template substitution
Once all operations are completed, the stealer removes itself from the drive, along with the artifacts folder (Arkanix_lol in this case).
Native version of stealer
MD5
a3fc46332dcd0a95e336f6927bae8bb7
File name
ArkanixStealer.exe
During our analysis, we were able to obtain both the release and debug versions of the native implementation, as both were uploaded to publicly available resources. The following are the key differences between the two:
The release version employs VMProtect, but does not utilize code virtualization.
The debug version communicates with a Discord bot for command and control (C2), whereas the release version uses the previously mentioned C2 domain arkanix[.]pw.
The debug version includes extensive logging, presumably for the authorsβ debugging purposes.
Notably, the native implementation explicitly references the name of the stealer in the VersionInfo resources. This naming convention is consistent across both the debug version and certain samples containing the release version of the implant.
Version info
After launching, the stealer implements a series of analysis countermeasures to verify that the application is not being executed within a sandboxed environment or run under a debugger. Following these checks, the sample patches AmsiScanBuffer and EtwEventWrite to prevent the triggering of any unwanted events by the system.
Once the preliminary checks are completed, the sample proceeds to gather information about the system. The list of capabilities is hardcoded and cannot be modified from the server side, in contrast to the Python version. What is more, the feature list is quite similar to the Python version except a few ones.
RDP connections
The stealer is capable of collecting information about known RDP connections that the compromised user has. To achieve this, it searches for .rdp files in %USERPROFILE%\Documents and extracts the full server address, password, username and server port.
Gaming files
The stealer also targets gamers and is capable to steal credentials from the popular gaming platform clients, including:
Steam
Epic Games Launcher
net
Riot
Origin
Unreal Engine
Ubisoft Connect
GOG
Screenshots
The native version, unlike its Python counterpart, is capable of capturing screenshots for each monitor via capCreateCaptureWindowA WinAPI.
In conclusion, this sample communicates with the C2 server through the same endpoints as the Python version. However, in this instance, all data is encrypted using the same AES-GCM + PBKDF2 (HMAC and SHA256) scheme as partially employed in the Python variant. In some observed samples, the key used was arkanix_secret_key_v20_2024. Alongside that, the C++ sample explicitly sets the User-Agent to ArkanixStealer/1.0.
Post-exploitation browser data extractor
MD5
3283f8c54a3ddf0bc0d4111cc1f950c0
File name
β
This is an implant embedded within the resources of the C++ implementation. The author incorporated it into the resource section without applying any obfuscation or encryption. Subsequently, the stealer extracts the payload to a temporary folder with a randomly generated name composed of hexadecimal digits (0-9 and A-F) and executes it using the CreateProcess WinAPI. The payload itself is the unaltered publicly available project known as βChromElevatorβ. To summarize, this tool consists of two components: an injector and the main payload. The injector initializes a direct syscall engine, spawns a suspended target browser process, and injects the decrypted code into it via Nt syscalls. The injected payload then decrypts the browser master key and exfiltrates data such as cookies, login information, web data, and so on.
Infrastructure
During the Arkanix campaign, two domains used in the attacks were identified. Although these domains were routed through Cloudflare, a real IP address was successfully discovered for one of them, namely, arkanix[.]pw. For the second one we only obtained a Cloudflare IP address.
Domain
IP
First seen
ASN
arkanix[.]pw
195.246.231[.]60
Oct 09, 2025
β
arkanix[.]ru
172.67.186[.]193
Oct 19, 2025
β
Both servers were also utilized to host the stealer panel, which allows attackers to monitor their victims. The contents of the panel are secured behind a sign-in page. Closer to the end of our research, the panel was seemingly taken down with no message or notice.
Stealer panel sign-in page
Stealer promotion
During the research of this campaign, we noticed that the forum posts advertising the stealer contained a link leading to a Discord server dubbed βArkanixβ by the authors. The server posed as a forum where authors posted various content and clients could ask various questions regarding this malicious software. While users mainly thank and ask about when the feature promised by the authors will be released and added into the stealer, the content made by the authors is broader. The adversary builds up the communication with potential buyers using the same marketing and communication methods real companies employ. To begin with, they warm up the audience by posting surveys about whether they should implement specific features, such as Discord injection and binding with a legitimate application (sic!).
Feature votes
Additionally, the author promised to release a crypter as a side project in four to six weeks, at the end of October. As of now, the stealer seems to have been taken down without any notice while the crypter was never released.
Arkanix Crypter
Furthermore, the Arkanix Stealer authors decided to implement a referral program to attract new customers. Referrers were promised an additional free hour to their premium license, while invited customers received seven days of free βpremiumβ trial use. As stated in forum posts, the premium plan included the following features:
C++ native stealer
Exodus and Atomic cryptocurrency wallets injection
Increased payload generation, up to 10 payloads
Priority support
Referral program ad and corresponding panel interface
Speaking of technical details, based on the screenshot of the Visual Studio stealer project that was sent to the Discord server, we can conclude that the author is German-speaking.
This same screenshot also serves as a probable indicator of AI-assisted development as it shares the common patterns of such assistants, e.g. the presence of the utils.cpp file. What provides even more confidence is the overall code structure, the presence of comments and extensive debugging log output.
Example of LLM-specific patterns
Conclusions
Information stealers have always posed as a serious threat to usersβ data. Arkanix is no exception as it targets a wide range of users, from those interested in cryptocurrencies and gaming to those using online banking. It collects a vast amount of information including highly sensitive personal data. While being quite functional, it contains probable traces of LLM-assisted development which suggests that such assistance might have drastically reduced development time and costs. Hence it follows that this campaign tends to be more of a one-shot campaign for quick financial gains rather than a long-running infection. The panel and the Discord chat were taken down around December 2025, leaving no message or traces of further development or a resurgence.
In addition, the developers behind the Arkanix Stealer decided to address the public, implementing a forum where they posted development insights, conducted surveys and even ran a referral program where you could get bonuses for βbringing a friendβ. This behavior makes Arkanix more of a public software product than a shady stealer.
In October 2025, we discovered a series of forum posts advertising a previously unknown stealer, dubbed βArkanix Stealerβ by its authors. It operated under a MaaS (malware-as-a-service) model, providing users not only with the implant but also with access to a control panel featuring configurable payloads and statistics. The set of implants included a publicly available browser post-exploitation tool known as ChromElevator, which was delivered by a native C++ version of the stealer. This version featured a wide range of capabilities, from collecting system information to stealing cryptocurrency wallet data. Alongside that, we have also discovered Python implementation of the stealer capable of dynamically modifying its configuration. The Python version was often packed, thus giving the adversary multiple methods for distributing their malware. It is also worth noting that Arkanix was rather a one-shot malicious campaign: at the time of writing this article, the affiliate program appears to be already taken down.
Kaspersky products detect this threat as Trojan-PSW.Win64.Coins.*, HEUR:Trojan-PSW.Multi.Disco.gen, Trojan.Python.Agent.*.
Technical details
Background
In October 2025, a series of posts was discovered on various dark web forums, advertising a stealer referred to by its author as βArkanix Stealerβ. These posts detail the features of the stealer and include a link to a Discord server, which serves as the primary communication channel between the author and the users of the stealer.
Example of an Arkanix Stealer advertisement
Upon further research utilizing public resources, we identified a set of implants associated with this stealer.
Initial infection or spreading
The initial infection vector remains unknown. However, based on some of the file names (such as steam_account_checker_pro_v1.py, discord_nitro_checker.py, and TikTokAccountBotter.exe) of the loader scripts we obtained, it can be concluded with high confidence that the initial infection vector involved phishing.
Python loader
MD5
208fa7e01f72a50334f3d7607f6b82bf
File name
discord_nitro_code_validator_right_aligned.py
The Python loader is the script responsible for downloading and executing the Python-based version of the Arkanix infostealer. We have observed both plaintext Python scripts and those bundled using PyInstaller or Nuitka, all of which share a common execution vector and are slightly obfuscated. These scripts often serve as decoys, initially appearing to contain legitimate code. Some of them do have useful functionality, and others do nothing apart from loading the stealer. Additionally, we have encountered samples that employ no obfuscation at all, in which the infostealer is launched in a separate thread via Pythonβs built-in threading module.
Variants of Python loaders executing the next stage
Upon execution, the loader first installs the required packages β namely, requests, pycryptodome, and psutil β via the pip package manager, utilizing the subprocess module. On Microsoft Windows systems, the loader also installs pywin32. In some of the analyzed samples, this process is carried out twice. Since the loader does not perform any output validation of the module installation command, it proceeds to make a POST request to hxxps://arkanix[.]pw/api/session/create to register the current compromised machine on the panel with a predefined set of parameters even if the installation failed. After that, the stealer makes a GET request to hxxps://arkanix[.]pw/stealer.py and executes the downloaded payload.
Python stealer version
MD5
af8fd03c1ec81811acf16d4182f3b5e1
File name
β
During our research, we obtained a sample of the Python implementation of the Arkanix stealer, which was downloaded from the endpoint hxxps://arkanix[.]pw/stealer.py by the previous stage.
The stealerβs capabilities β or features, as referred to by the author β in this version are configurable, with the default configuration predefined within the script file. To dynamically update the feature list, the stealer makes a GET request to hxxps://arkanix[.]pw/api/features/{payload_id}, indicating that these capabilities can be modified on the panel side. The feature list is identical to the one that was described in the GDATA report.
Configurable options
Prior to executing the information retrieval-related functions, the stealer makes a request to hxxps://arkanix[.]pw/upload_dropper.py, saves the response to %TEMP%\upd_{random 8-byte name}.py, and executes it. We do not have access to the contents of this script, which is referred to as the βdropperβ by the attackers.
During its main information retrieval routine, at the end of each processing stage, the collected information is serialized into JSON format and saved to a predefined path, such as %LOCALAPPDATA\Arkanix_lol\%info_class%.json.
In the following, we will provide a more detailed description of the Python versionβs data collection features.
System info collection
Arkanix Stealer is capable of collecting a set of info about the compromised system. This info includes:
OS version
CPU and GPU info
RAM size
Screen resolution
Keyboard layout
Time zone
Installed software
Antivirus software
VPN
Information collection is performed using standard shell commands with the exception of the VPN check. The latter is implemented by querying the endpoint hxxps://ipapi[.]co/json/ and verifying whether the associated IP address belongs to a known set of VPNs, proxies, or Tor exit nodes.
Browser features
This stealer is capable of extracting various types of data from supported browsers (22 in total, ranging from the widely popular Google Chrome to the Tor Browser). The list of supported browsers is hardcoded, and unlike other parameters, it cannot be modified during execution. In addition to a separate Chrome grabber module (which weβll discuss later), the stealer itself supports the extraction of diverse information, such as:
Browser history (URLs, visit count and last visit)
Autofill information (email, phone, addresses and payment cards details)
Saved passwords
Cookies
In case of Chromium-based browsers, 0Auth2 data is also extracted
All information is decrypted using either the Windows DPAPI or AES, where applicable, and searched for relevant keywords. In the case of browser information collection, the stealer searches exclusively for keywords related to banking (e.g., βrevolutβ, βstripeβ, βbankβ) and cryptocurrencies (e.g., βbinanceβ, βmetamaskβ, βwalletβ). In addition to this, the stealer is capable of extracting extension data from a hardcoded list of extensions associated with cryptocurrencies.
Part of the extension list which the stealer utilizes to extract data from
Telegram info collection
Telegram data collection begins with terminating the Telegram.exe process using the taskkill command. Subsequently, if the telegram_optimized feature is set to False, the malware zips the entire tdata directory (typically located at %APPDATA%\Roaming\Telegram Desktop\tdata) and transmits it to the attacker. Otherwise, it selectively copies and zips only the subdirectories containing valuable info, such as message log. The generated archive is sent to the endpoint /delivery with the filename tdata_session.zip.
Discord capabilities
The stealer includes two features connected with Discord: credentials stealing and self-spreading. The first one can be utilized to acquire credentials both from the standard client and custom clients. If the client is Chromium-based, the stealer employs the same data exfiltration mechanism as during browser credentials stealing.
The self-spreading feature is configurable (meaning it can be disabled in the config). The stealer acquires the list of userβs friends and channels via the Discord API and sends a message provided by the attacker. This stealer does not support attaching files to such messages.
VPN data collection
The VPN collector is searching for a set of known VPN software to extract account credentials from the credentials file with a known path that gets parsed with a regular expression. The extraction occurs from the following set of applications:
Mullvad VPN
NordVPN
ExpressVPN
ProtonVPN
File retrieval
File retrieval is performed regardless of the configuration. The script relies on a predefined set of paths associated with the current user (such as Desktop, Download, etc.) and file extensions mainly connected with documents and media. The script also has a predefined list of filenames to exfiltrate. The extracted files are packed into a ZIP archive which is later sent to the C2 asynchronously. An interesting aspect is that the filename list includes several French words, such as βmotdepasseβ (French for βpasswordβ), βbanqueβ (French for βbankβ), βsecretβ (French for βsecretβ), and βcompteβ (French for βaccountβ).
Other payloads
We were able to identify additional modules that are downloaded from the C2 rather than embedded into the stealer script; however, we werenβt able to obtain them. These modules can be described by the following table, with the βDetailsβ column referring to the information that could be extracted from the main stealer code.
Module name
Endpoint to download
Details
Chrome grabber
/api/chrome-grabber-template/{payload_id}
β
Wallet patcher
/api/wallet-patcher/{payload_id}
Checks whether βExodusβ and βAtomicβ cryptocurrency wallets are installed
Extra collector
/api/extra-collector/{payload_id}
Uses a set of options from the config, such as collect_filezilla, collect_vpn_data, collect_steam, and collect_screenshots
HVNC
/hvnc
Is saved to the Startup directory (%APPDATA%\Microsoft\Windows\Start Menu\Programs\Startup\hvnc.py) to execute upon system boot
The Wallet patcher and Extra collector scripts are received in an encrypted form from the C2 server. To decrypt them, the attackers utilize the AES-GCM algorithm in conjunction with PBKDF2 (HMAC and SHA256). After decryption, the additional payload has its template placeholders replaced and is stored under a partially randomized name within a temporary folder.
Decryption routine and template substitution
Once all operations are completed, the stealer removes itself from the drive, along with the artifacts folder (Arkanix_lol in this case).
Native version of stealer
MD5
a3fc46332dcd0a95e336f6927bae8bb7
File name
ArkanixStealer.exe
During our analysis, we were able to obtain both the release and debug versions of the native implementation, as both were uploaded to publicly available resources. The following are the key differences between the two:
The release version employs VMProtect, but does not utilize code virtualization.
The debug version communicates with a Discord bot for command and control (C2), whereas the release version uses the previously mentioned C2 domain arkanix[.]pw.
The debug version includes extensive logging, presumably for the authorsβ debugging purposes.
Notably, the native implementation explicitly references the name of the stealer in the VersionInfo resources. This naming convention is consistent across both the debug version and certain samples containing the release version of the implant.
Version info
After launching, the stealer implements a series of analysis countermeasures to verify that the application is not being executed within a sandboxed environment or run under a debugger. Following these checks, the sample patches AmsiScanBuffer and EtwEventWrite to prevent the triggering of any unwanted events by the system.
Once the preliminary checks are completed, the sample proceeds to gather information about the system. The list of capabilities is hardcoded and cannot be modified from the server side, in contrast to the Python version. What is more, the feature list is quite similar to the Python version except a few ones.
RDP connections
The stealer is capable of collecting information about known RDP connections that the compromised user has. To achieve this, it searches for .rdp files in %USERPROFILE%\Documents and extracts the full server address, password, username and server port.
Gaming files
The stealer also targets gamers and is capable to steal credentials from the popular gaming platform clients, including:
Steam
Epic Games Launcher
net
Riot
Origin
Unreal Engine
Ubisoft Connect
GOG
Screenshots
The native version, unlike its Python counterpart, is capable of capturing screenshots for each monitor via capCreateCaptureWindowA WinAPI.
In conclusion, this sample communicates with the C2 server through the same endpoints as the Python version. However, in this instance, all data is encrypted using the same AES-GCM + PBKDF2 (HMAC and SHA256) scheme as partially employed in the Python variant. In some observed samples, the key used was arkanix_secret_key_v20_2024. Alongside that, the C++ sample explicitly sets the User-Agent to ArkanixStealer/1.0.
Post-exploitation browser data extractor
MD5
3283f8c54a3ddf0bc0d4111cc1f950c0
File name
β
This is an implant embedded within the resources of the C++ implementation. The author incorporated it into the resource section without applying any obfuscation or encryption. Subsequently, the stealer extracts the payload to a temporary folder with a randomly generated name composed of hexadecimal digits (0-9 and A-F) and executes it using the CreateProcess WinAPI. The payload itself is the unaltered publicly available project known as βChromElevatorβ. To summarize, this tool consists of two components: an injector and the main payload. The injector initializes a direct syscall engine, spawns a suspended target browser process, and injects the decrypted code into it via Nt syscalls. The injected payload then decrypts the browser master key and exfiltrates data such as cookies, login information, web data, and so on.
Infrastructure
During the Arkanix campaign, two domains used in the attacks were identified. Although these domains were routed through Cloudflare, a real IP address was successfully discovered for one of them, namely, arkanix[.]pw. For the second one we only obtained a Cloudflare IP address.
Domain
IP
First seen
ASN
arkanix[.]pw
195.246.231[.]60
Oct 09, 2025
β
arkanix[.]ru
172.67.186[.]193
Oct 19, 2025
β
Both servers were also utilized to host the stealer panel, which allows attackers to monitor their victims. The contents of the panel are secured behind a sign-in page. Closer to the end of our research, the panel was seemingly taken down with no message or notice.
Stealer panel sign-in page
Stealer promotion
During the research of this campaign, we noticed that the forum posts advertising the stealer contained a link leading to a Discord server dubbed βArkanixβ by the authors. The server posed as a forum where authors posted various content and clients could ask various questions regarding this malicious software. While users mainly thank and ask about when the feature promised by the authors will be released and added into the stealer, the content made by the authors is broader. The adversary builds up the communication with potential buyers using the same marketing and communication methods real companies employ. To begin with, they warm up the audience by posting surveys about whether they should implement specific features, such as Discord injection and binding with a legitimate application (sic!).
Feature votes
Additionally, the author promised to release a crypter as a side project in four to six weeks, at the end of October. As of now, the stealer seems to have been taken down without any notice while the crypter was never released.
Arkanix Crypter
Furthermore, the Arkanix Stealer authors decided to implement a referral program to attract new customers. Referrers were promised an additional free hour to their premium license, while invited customers received seven days of free βpremiumβ trial use. As stated in forum posts, the premium plan included the following features:
C++ native stealer
Exodus and Atomic cryptocurrency wallets injection
Increased payload generation, up to 10 payloads
Priority support
Referral program ad and corresponding panel interface
Speaking of technical details, based on the screenshot of the Visual Studio stealer project that was sent to the Discord server, we can conclude that the author is German-speaking.
This same screenshot also serves as a probable indicator of AI-assisted development as it shares the common patterns of such assistants, e.g. the presence of the utils.cpp file. What provides even more confidence is the overall code structure, the presence of comments and extensive debugging log output.
Example of LLM-specific patterns
Conclusions
Information stealers have always posed as a serious threat to usersβ data. Arkanix is no exception as it targets a wide range of users, from those interested in cryptocurrencies and gaming to those using online banking. It collects a vast amount of information including highly sensitive personal data. While being quite functional, it contains probable traces of LLM-assisted development which suggests that such assistance might have drastically reduced development time and costs. Hence it follows that this campaign tends to be more of a one-shot campaign for quick financial gains rather than a long-running infection. The panel and the Discord chat were taken down around December 2025, leaving no message or traces of further development or a resurgence.
In addition, the developers behind the Arkanix Stealer decided to address the public, implementing a forum where they posted development insights, conducted surveys and even ran a referral program where you could get bonuses for βbringing a friendβ. This behavior makes Arkanix more of a public software product than a shady stealer.
by Austin Kaiser // Intern Hacking a satellite is not a new thing. Satellites have been around since 1957. The first satellite launched was called Sputnik 1 and was launched [β¦]
moth // Recently, BHIS penetration tester Dale Hobbs was on an Internal Network Penetration Test and came across an RPC-based arbitrary command execution vulnerability in his vulnerability scan results.Β I [β¦]
Have you ever installed a Python tool / library only to then find out other Python based tools youβve installed previously are now completely broken? Running Kali? Ever try installing [β¦]
Do your PowerShell scripts keep getting caught? Tired of dealing with EDRs & Windows Defender every time you need to pop a box?Β In this one-hour podcast, originally recorded as [β¦]
Yes.. Ethical Hacker Kids. The holidays are coming up! Here John & Jordan cover the different games, tools and gifts we can give kids that help teach them the trade. [β¦]
John Strand & Jordan Drysdale// Yes.. Ethical Hacker Kids. The holidays are coming up! Here John & Jordan cover the different games, tools and gifts we can give kids that [β¦]
Jordan Drysdale// With Wild West Hackinβ Fest 2018 coming up (!!!), hereβs a preview of some things you might see in the wireless labs. First, s0lst1c3βs eaphammer. @relkci and I [β¦]
Dakota Nelson// The modern internetβs got a lot of places to hide. In this webcast, join Dakota as he shows how you can establish C2 channels and issue commands to [β¦]
Joff Thyer // Information Security professionals often have reason to analyze logs. Whether Red Team or Blue Team, there are countless times that you find yourself using βgrepβ, βtailβ, βcutβ, [β¦]
Carrie Roberts // OS Command Injection is fun. I recently found this vulnerability on a web application I was testing (thanks to Burp Suite scanner). I was excited because I [β¦]