Kaspersky’s GReAT team has uncovered a sophisticated PyPI supply chain attack attributed with moderate confidence to the OceanLotus APT group (APT32), involving three malicious Python wheel packages that silently delivered a previously unknown malware family called ZiChatBot targeting both Windows and Linux systems using Zulip’s public REST APIs as command-and-control infrastructure.
During routine threat hunting, Kaspersky researchers detected a cluster of malicious Python wheel packages uploaded to the Python Package Index (PyPI) beginning July 16, 2025.
Rather than relying on traditional attack vectors, the threat actor behind the campaign exploited PyPI, the world’s most widely used Python library repository, to silently infect developers and Python users worldwide.
After Kaspersky shared the intelligence with the public security community, the malicious packages were promptly removed from PyPI, and the attacker’s Zulip organization was officially deactivated.
The campaign is consistent with OceanLotus’s documented trend of escalating supply chain attacks, following a similar GitHub-based phishing operation that targeted cybersecurity researchers and enterprises in early 2025, where poisoned repositories mimicked legitimate red-teaming tools.
Three Malicious PyPI Packages
The threat actor created three carefully crafted PyPI projects designed to impersonate popular Python utility libraries:
- uuid32-utils – Posed as a library for generating 32-character UUID strings; first uploaded July 16, 2025
- colorinal – Masqueraded as a cross-platform color terminal text library; uploaded July 22, 2025
- termncolor – Appeared as an ANSI terminal color formatter; uploaded July 22, 2025, and deliberately listed colorinal as a dependency to conceal the malicious chain
The termncolor package itself contained no directly malicious code, functioning purely as a trojan horse that pulled the weaponized colorinal library as a dependency, a sophisticated layering technique designed to evade static package analysis and trick even cautious developers.
Each package provided the exact functional features described on its PyPI page, making detection significantly harder for end users and automated scanners.
Once a user installs the colorinal package, a dropper file named terminate.dll (Windows) or terminate. So (Linux) was silently extracted from the wheel archive and placed on the victim’s filesystem.
When the library is imported into any Python project, the __init__.py script triggered a secondary script unicode.py, which loaded the dropper into the host Python process and invoked an exported function named envir passing xterminalunicode as a decryption key.
The dropper decrypted embedded strings and payload data using AES in CBC mode, then decompressed them with LZMA to recover ZiChatBot’s core components: vcpktsvr.exe and libcef.dll.
These files were deposited into %LOCALAPPDATA%\vcpacket\ on Windows, with persistence established via the registry run key HKCU\Software\Microsoft\Windows\CurrentVersion\Run under the entry name pkt-update.
Following deployment, the dropper used XOR-decrypted shellcode (three-byte key 3a7) to self-delete both the DLL and the malicious Python script, erasing all forensic artifacts from the installed library folder.
On Linux, the dropper placed ZiChatBot as a single ELF executable at /tmp/obsHub/obs-check-update and registered a crontab persistence job running every five minutes, a lightweight but effective persistence mechanism for Unix environments.
ZiChatBot represents a novel approach to C2 evasion. Rather than registering domains or leasing VPS servers, security teams routinely block and monitor the malware that exclusively used Zulip’s public REST APIs as its command-and-control channel.
The malware included a hardcoded Base64-encoded authentication token corresponding to a bot account (Morian-bot@helper.zulipchat.com) registered under an attacker-controlled Zulip organization named “helper.”
ZiChatBot operated through two dedicated channel-topic pairs: one to transmit current system reconnaissance data, and another to receive shellcode payloads from the attacker.
The malware supported only a single control command, keeping its network footprint minimal and its behavior difficult to classify as malicious using behavioral heuristics alone.
Zulip has since officially deactivated the “helper” organization, but security teams should add helper.zulipchat.com to their denylist, as infected endpoints may still attempt connections.
Kaspersky’s Threat Attribution Engine (KTAE) returned a 64% code similarity between ZiChatBot’s dropper and a dropper previously linked to OceanLotus (APT32) in an earlier threat intelligence report.
Reverse engineering confirmed that the decryption and decompression algorithms in both samples were nearly identical, strongly suggesting shared developer infrastructure or tooling.
OceanLotus (APT32) is a Vietnam-linked advanced persistent threat group historically focused on government agencies, NGOs, and technology firms across the Asia-Pacific region.
However, this PyPI campaign targeting Python developers globally demonstrates a clear strategic expansion of the group’s operational scope.
In early 2025, APT32 similarly abused GitHub by distributing trojanized red team tools to target Chinese cybersecurity researchers, using GitHub’s Issues and Discussions features to fabricate legitimacy. No confirmed infections have been identified to date based on Kaspersky’s telemetry.
Indicators of Compromise (IOCs)
Security teams should hunt for the following artifacts across their environments:
- Registry key:
HKCU\Software\Microsoft\Windows\CurrentVersion\Run→pkt-updatepointing tovcpktsvr.exe - File paths:
%LOCALAPPDATA%\vcpacket\vcpktsvr.exe,%LOCALAPPDATA%\vcpacket\libcef.dll - Linux path:
/tmp/obsHub/obs-check-update - C2 domain to denylist:
helper.zulipchat.com - Zulip bot token (decoded):
Morian-bot@helper.zulipchat.com:U8REXlI6Kf8qXB9rQzOPBiIA4brJ58qG - vcpktsvr.exe SHA256:
48be833b0b0ca1ad3cf99c66dc89c3f4
FAQ
Q1: What is ZiChatBot malware?
ZiChatBot is a previously unknown malware family discovered by Kaspersky that uses Zulip’s public REST APIs as its command-and-control infrastructure, rather than a traditional dedicated C2 server, targeting both Windows and Linux systems.
Q2: Which PyPI packages delivered ZiChatBot?
The three malicious packages were uuid32-utils, colorinal, and termncolor, all uploaded to PyPI between July 16 and 22, 2025, and designed to impersonate legitimate Python utility libraries.
Q3: Who is behind the ZiChatBot PyPI supply chain attack?
Kaspersky’s KTAE system found a 64% code similarity between ZiChatBot’s dropper and malware previously linked to OceanLotus (APT32), a Vietnam-linked APT group known for targeting Asia-Pacific governments and enterprises.
Q4: How can organizations protect themselves from this attack?
Organizations should immediately add helper.zulipchat.com to their denylist, audit Python environments for the identified file paths and registry keys, and enforce software supply chain security controls such as package integrity verification and dependency scanning.
Site: thecybrdef.com
For more insights and updates, follow us on Google News, Twitter, and LinkedIn.