Deep Dive: The ZiChatBot Supply Chain Attack via PyPI and Zulip C2
In a sophisticated display of supply chain subversion, a new cross-platform malware family known as ZiChatBot has emerged. This campaign leverages the widespread trust in the Python Package Index (PyPI) and the ubiquitous Zulip team chat platform to establish a highly stealthy, legitimate-looking command-and-control (C2) infrastructure.
During proactive threat hunting, security analysts identified a series of malicious wheel packages masquerading as benign developer utilities. The three primary fraudulent projects—uuid32-utils, colorinal, and termncolor—were engineered to blend seamlessly into the Python ecosystem. While they successfully implemented their advertised functionalities (such as UUID generation and terminal color formatting), they functioned as Trojan horses to deliver the ZiChatBot payload.
The campaign, which has been active since July 2025, demonstrates a meticulously planned supply chain attack targeting both Windows and Linux development environments through poisoned wheel packages.
To evade detection, the attackers employed a multi-layered dependency strategy. For instance, termncolor acted as a benign wrapper that merely imported colorinal as a dependency. This technique ensures that a developer installing termncolor might see no immediate red flags, while the malicious colorinal library is silently pulled into their downstream projects during the installation process.

The malware’s reach was intentionally broad, shipping platform-specific wheels for Windows (x86 and x64) and Linux (x86_64), allowing it to compromise diverse development workflows.
Technical Breakdown: The Infection Chain
The infection vector differs slightly by OS, but the objective remains the same: achieving persistence and remote code execution.
Windows Execution Flow
Upon the installation of colorinal-0.1.7-py3-none-win_amd64.whl or uuid32-utils, a DLL dropper named terminate.dll is extracted to the local disk. The execution is triggered through a clever masquerade: the package’s __init__.py script loads unicode.py, which contains a function titled is_color_supported(). While this name suggests a harmless terminal capability check, its actual role is to load terminate.dll directly into the active Python process.

The dropper’s exported function, envir, is called with a hard-coded UTF-8 string that serves as the decryption key. Using AES-CBC for decryption and LZMA for decompression, the dropper recovers the core ZiChatBot components: vcpktsvr.exe and libcef.dll. These are dropped into a vcpacket directory under %LOCALAPPDATA%. Persistence is then secured by creating a “pkt-update” entry in the Windows Registry’s “Run” key.
In a final act of anti-forensics, the malware executes shellcode to locate and delete terminate.dll and the original malicious Python scripts, effectively scrubbing its initial presence from the library folder. This cleanup phase makes post-infection analysis significantly harder.
Linux Execution Flow
The Linux variant follows a similar logic, though the dropper is packaged as terminate.so. The payload is deployed as a single ELF executable located at /tmp/obsHub/obs-check-update. Rather than using systemd, the malware ensures persistence by creating a crontab job that triggers every five minutes, ensuring the bot remains active even after reboots.
Zulip REST APIs: A Novel C2 Strategy
What sets ZiChatBot apart is its Command-and-Control (C2) architecture. Instead of communicating with a suspicious, newly registered domain or a known malicious IP, it utilizes Zulip’s public REST APIs. This “living off the cloud” approach allows C2 traffic to blend in with legitimate enterprise chat automation.
On Windows, the vcpktsvr.exe binary sideloads libcef.dll, which contains the cef_api_mash export—the engine for C2 communication. The bot authenticates to a specific Zulip organization (under the “helper” workspace) using an embedded API token passed via HTTP headers.
The command structure is highly efficient:
- Data Exfiltration: The bot posts system metadata to specific Zulip topics.
- Command Retrieval: The bot polls specific topics for new shellcode payloads.
- Acknowledgment: Upon successful execution of a command, the bot replies to the message with a “heart” emoji, providing a non-obvious signal to the attacker that the task was completed.
Attribution: The Shadow of OceanLotus
Technical analysis via Kaspersky’s Threat Attribution Engine (KTAE) has revealed a 64% code similarity between the ZiChatBot dropper and previously documented tools used by OceanLotus (APT32). This includes nearly identical logic for AES-CBC decryption and LZMA decompression.
OceanLotus is a Vietnam-aligned advanced persistent threat (APT) group with a history of targeting organizations across the Asia-Pacific region and, more recently, the Middle East. Their toolkit has a long history of abusing developer platforms like GitHub to facilitate their operations. While formal attribution is complex, the technical overlaps strongly suggest ZiChatBot is a new evolution in OceanLotus’s supply chain offensive capabilities.
Defensive Roadmap
While the malicious PyPI packages have been purged and the “helper” Zulip organization has been deactivated, the threat remains active on previously compromised systems.
Recommended Actions for Security Teams:
- Network Layer: Implement egress filtering to block traffic to
helper.zulipchat.comif not required for business operations. - Endpoint Detection (EDR): Scan for the following artifacts:
- Windows:
%LOCALAPPDATA%\vcpacket\,vcpktsvr.exe, orterminate.dll. - Linux:
/tmp/obsHub/obs-check-update.
- Windows:
- Supply Chain Hygiene: Enforce strict dependency pinning (using
requirements.txtwith hashes) and utilize tools likepip-auditto scan for known vulnerabilities and malicious packages in your Python environments.