Feed
HighPublished 8 May 20263 packages · 7 versions

OceanLotus-attributed ZiChatBot PyPI droppers: uuid32-utils, colorinal, termncolor with Zulip-API C2

Summary

Kaspersky GReAT (2026-05-08) re-attributed three PyPI wheels uploaded by an attacker between 2025-07-16 and 2025-07-22 - uuid32-utils, colorinal, and termncolor - to the Vietnam-aligned OceanLotus (APT32) group. The droppers fetch a Windows DLL or Linux .so, persist via Run-key or crontab, and load ZiChatBot, a Python backdoor that uses public Zulip REST APIs as its C2 channel to blend with normal developer traffic.

typosquatinfostealercredential-theftobfuscationdormant-domain
Threat actor
OceanLotus / APT32 (Kaspersky moderate-confidence attribution)
Detected by
Kaspersky GReAT · Zscaler ThreatLabz
Also known as
ZiChatBot · APT32 PyPI wheel campaign · Zulip-API C2 backdoor
Ecosystems
PyPI
Packages tracked
3

What happened

On 2026-05-08 Kaspersky's Global Research and Analysis Team published a re-attribution write-up linking three previously-disclosed malicious PyPI wheels to the Vietnam-aligned OceanLotus (APT32) group. The packages - uuid32-utils, colorinal, and termncolor - were first flagged in August 2025 by Zscaler ThreatLabz as generic supply-chain malware; Kaspersky's KTAE code-similarity engine matched the dropper logic at 64% against known APT32 implants, upgrading the incident from opportunistic crime to suspected state-sponsored espionage.

Campaign

All three wheels were uploaded between 2025-07-16 and 2025-07-22 from a fresh attacker account. uuid32-utils impersonates a 32-character UUID generator, colorinal impersonates a cross-platform terminal-colour utility, and termncolor is a benign-looking wrapper that lists colorinal as a transitive dependency - installing the latter pulls and detonates the former. Recorded download totals before PyPI takedown: uuid32-utils 1,479, colorinal 614, termncolor 387 (Kaspersky tally; Zscaler observed 529 / 355 for colorinal / termncolor in an earlier snapshot).

Payload - DLL sideload + crontab + Zulip C2

The bdist wheels carry a platform-matched dropper: a Windows DLL or a Linux .so. On Windows the dropper sideloads into a benign Python loader, drops a payload into %APPDATA%, and persists via HKCU\Software\Microsoft\Windows\CurrentVersion\Run. On Linux the equivalent path uses a crontab entry to respawn the backdoor on reboot. The implant - Kaspersky-named ZiChatBot - is a Python backdoor whose distinguishing feature is that it has no dedicated C2 server: every command, exfiltration, and heartbeat is funnelled through the public Zulip team-chat REST API (*.zulipchat.com). The attacker created Zulip organisations and channels under throwaway accounts, then used Zulip's OAuth tokens as authenticated C2 - outbound looks like ordinary developer traffic to a Slack-style chat service. Kaspersky reports the Zulip organisations were deactivated after disclosure.

Attribution

Kaspersky's KTAE clustering matched the dropper to OceanLotus / APT32 with moderate confidence at 64% code similarity. OceanLotus has been active since at least 2014 and historically targets Asia-Pacific governments, dissidents, automotive companies, and infrastructure operators with custom backdoors (KerrDown, Ratsnif, Cobalt Strike variants). The 2025-07 PyPI campaign represents a deliberate pivot to the open-source supply chain - APT32 had previously been observed using compromised websites and Skype/Telegram lures, not registry uploads.

Timeline

  • 2025-07-10 - earliest attacker activity observed (first malicious commit to staging repos, per ThreatLabz reconstruction)
  • 2025-07-16 → 2025-07-22 - uuid32-utils, colorinal, termncolor uploaded to PyPI in three separate bursts
  • 2025-08 - Zscaler ThreatLabz publishes the original detection; PyPI removes the packages, Zulip deactivates the C2 organisations
  • 2026-05-08 - Kaspersky GReAT publishes the OceanLotus / APT32 re-attribution write-up with KTAE similarity analysis
  • 2026-05 → 2026-06 - re-attribution amplified by The Hacker News, GBHackers, GridinSoft, daily.dev, MalwareTips, and others

No CVE / GHSA covers the wave - PyPI security removed the packages but no advisory was created at the time. The Kaspersky write-up and the original Zscaler post are the only structured references; we record the Kaspersky attribution date as published because that is when the campaign became a named, attributed disclosure. Exact published version numbers per package are not enumerated in the public sources beyond Safety DB's record of uuid32-utils reaching 1.0.4; we list inferred initial-publish versions only, and a lockfile match on any version of these three names should be treated as compromise.

Affected packages (3)

These are usually pulled in as transitive dependencies rather than installed directly. Check your whole tree at once - it runs in your browser and nothing is uploaded.

Impact

  • Cross-platform persistence: Windows persistence via HKCU\Software\Microsoft\Windows\CurrentVersion\Run, Linux persistence via a crontab entry that respawns the backdoor on every reboot
  • DLL sideloading on Windows (uuid32-utils / colorinal) and ELF .so loading on Linux - both wheel families carry platform-matched droppers inside the bdist
  • ZiChatBot Python backdoor connects to public Zulip REST APIs for command-and-control - perimeter detection that flags rare C2 hostnames will miss this because Zulip is allow-listed in many engineering environments
  • Sleeper window: ~10 months between PyPI publication (2025-07) and public re-attribution (2026-05-08); any environment that pinned these names in a lockfile during the window has run the backdoor
  • Termncolor is a benign wrapper that imports colorinal as a transitive dependency - a lockfile that only mentions termncolor still pulls and executes the malicious payload
  • OceanLotus / APT32 targeting profile is Asia-Pacific governments, dissidents, and enterprises; Kaspersky scored the dropper at 64% similarity to known APT32 implants in their KTAE engine

What to do

  1. 1Grep every requirements.txt, Pipfile.lock, poetry.lock, and pdm.lock in scope for uuid32-utils, colorinal, or termncolor - all three were removed from PyPI but pinned lockfiles will still attempt to install them from caches / mirrors
  2. 2Quarantine any developer workstation or CI runner that ran pip install against one of the three names between 2025-07-16 and 2026-05-08; assume full host compromise and re-image
  3. 3On Windows, audit HKCU\Software\Microsoft\Windows\CurrentVersion\Run for unexpected entries pointing into %APPDATA% or %LOCALAPPDATA%
  4. 4On Linux, audit crontab -l (per-user) and /etc/cron.d/, /etc/crontab for unexpected jobs added during the dwell window
  5. 5Egress hunt: outbound to *.zulipchat.com REST APIs from Python interpreters that should not be using Zulip - ZiChatBot is the only published example of Zulip-as-C2 to date
  6. 6Rotate any credential reachable from a compromised host: SSH keys, cloud tokens (AWS / Azure / GCP), Git tokens, npm/PyPI publish tokens, and browser-stored session cookies

References

pypi-2026-05-08-oceanlotus-zichatbot-zulip-c2