At CYFIRMA, we are committed to delivering timely insights into active cyber threats and the techniques used by malicious actors to target individuals and enterprises. This report examines PupkinStealer, a malware developed in C# using the .NET framework, designed to harvest sensitive user data and exfiltrate it via Telegram’s Bot API. This analysis outlines its internal structure, operational workflow, and data theft mechanisms, along with guidance on mitigating the risks associated with such threats.
PupkinStealer represents a straightforward but effective example of .NET-based information-stealing malware. This strain targets a specific range of sensitive data, including stored credentials, personal documents, and user messages. Upon infection, it executes several background tasks—harvesting login data from popular web browsers, copying select files from the victim’s desktop, stealing session information from messaging platforms such as Telegram and Discord, and capturing a screenshot of the desktop. All collected data is then compressed into a ZIP archive and exfiltrated to a remote server via the Telegram Bot API, minimizing traceability and enhancing stealth.
PupkinStealer, first observed in April 2025, is a simple, straightforward information stealer malware. Unlike the other information stealers who target a wide range of data, PupkinStealer only targets a specific set of data. With no specific anti-analysis defenses or persistence mechanisms, PupkinStealer depends on straightforward execution and low-profile behavior to avoid detection during its operation.
PupkinStealer uses a telegram bot to exfiltrate data. The bot ‘botKanal’, and its username, ‘botkanalchik_bot’, appear to derive from the Russian word канал (kanal), meaning “channel,” with kanalchik likely serving as a diminutive or colloquial form.
Additionally, chat metadata identified a user whose bio contains Russian-language text (“куплю рамоны за 2 к”), further suggesting a possible Russian origin.
Based on available evidence, PupkinStealer is attributed to a developer operating under the alias “Ardent.” This attribution stems from embedded strings within the malware’s code, notably the phrase “Coded by Ardent.”
Threat Landscape:
PupkinStealer emerges within a broader threat landscape dominated by low-complexity, high-impact infostealers that are widely available and easily customizable. As cybercriminals increasingly favor Telegram for command-and-control operations due to its anonymity and ease of use, tools like PupkinStealer represent a growing trend in malware-as-a-service offerings. These lightweight, modular stealers require minimal technical skill to deploy and are particularly attractive to less-sophisticated threat actors seeking rapid monetization through credential theft, session hijacking, and data resale on illicit marketplaces. The simplicity and efficiency of PupkinStealer underscores the continued evolution of information-stealing malware in the hands of opportunistic attackers.
File Analysis | |
File Name | PupkinStealer.exe |
File Size | 6.21 MB (6510592 bytes) |
Signed | Not signed |
MD5 | fc99a7ef8d7a2028ce73bf42d3a95bce |
SHA-256 | 9309003c245f94ba4ee52098dadbaa0d0a4d83b423d76c1bfc082a1c29e0b95f |
Last Modified | 27-04-2025 |
This version of PupkinStealer is a 32-bit GUI-based Windows executable written in .NET, with dependencies embedded using Costura. The architecture is set to ‘AnyCPU’, making it compatible with both x86 and x64 environments.
The executable is not packed, but the ‘.text’ section contains the executable code, with an entropy value of 7.998, indicating a high level of randomness or complexity in the code.
As Costura modifies the .NET executable by embedding compressed external DLLs within the assembly, this likely contributes to the elevated entropy, despite the absence of traditional packing.
Upon execution, the operating system loads the .NET executable. The control is then transferred to the .NET runtime (via mscoree.dll), which initializes the Common Language Runtime (CLR). The CLR loads the necessary assemblies and begins executing the managed entry point defined in the assembly metadata — specifically, the Main() method of the malware.
The Main() method serves as the central execution point for the malware’s activities. It is responsible for coordinating the malware’s operations, starting by launching multiple asynchronous tasks. Each task is dedicated to harvesting different types of sensitive data from the victim’s system. These operations can include capturing screenshots, gathering system information, accessing stored credentials, and exfiltrating files, among other malicious activities.
The first background task executed by the malware invokes the DecryptingBrowsersPasswords() function, defined under the Browsers.Chromium.ChromiumPasswords class. This function is responsible for extracting saved login credentials from Chromium-based web browsers, specifically targeting Chrome, Edge, Opera, Opera GX, and Vivaldi.
Before performing any extraction, the malware creates a directory under a temporary path specific to the current user (e.g., %TEMP%\[username]\Passwords) to store the stolen browser data in separate text files, one per targeted browser (e.g., Chrome.txt, Edge.txt, Opera.txt, OperaGX.txt, and Vivaldi.txt).
Once the storage directory is created, the malware proceeds to extract saved credentials from Chromium-based browsers. The process is similar for each browser. First, it checks whether the browser’s Login Data file exists on the system — a SQLite database that contains saved usernames and encrypted passwords. If the file is found, the malware then retrieves the corresponding decryption key by reading the browser’s Local State file, located at: %LOCALAPPDATA%\[BrowserName]\User Data\Local State.
FunctionsForStealer Class
The FunctionsForStealer class plays a crucial role in retrieving these decryption keys. It contains several methods specifically designed to extract the decryption key for different Chromium-based browsers. These keys are required to decrypt the encrypted passwords stored in the Login Data database. The FunctionsForStealer.LocalStateKeys nested class is responsible for fetching the encrypted key from each browser’s Local State file, then decrypting it using the Windows Data Protection API.
Each browser’s decryption key is stored in the Local State file under the os_crypt -> encrypted_key field. The malware accesses this field, decodes the encrypted key, and uses the ProtectedData.Unprotect method to decrypt the key based on the system’s data protection settings. The methods in this class are as follows:
Each of these methods follows a similar pattern:
2. The encrypted_key field is extracted, which is base64-encoded.
3. The base64 string is decoded, and the malware decrypts it using the system’s data protection scope.
These decryption keys are then used to access and decrypt the stored passwords from the browser’s Login Data SQLite database.
FunctionsForDecrypt Class
Once the decryption key is retrieved by the FunctionsForStealer class, the next step is to decrypt the actual saved passwords. This is handled by the FunctionsForDecrypt class, which contains methods to handle the decryption of the browser’s passwords.
Key functionalities in this class include:
The decryption process follows these steps:
By leveraging these two classes — FunctionsForStealer and FunctionsForDecrypt — the malware is able to automate the process of obtaining, decrypting, and extracting saved passwords from various browsers. This enables the attacker to obtain sensitive login credentials without the need for direct user interaction.
The GrabberDesktop method is part of the Desktop class and is used to collect specific types of files from the user’s desktop, and copy them to a designated folder.
Directory Creation:
The method first ensures that a directory named DesktopFiles is created under a specific directory path defined in Variables.workdir. If the directory already exists, it is not recreated. The purpose of this directory is to temporarily store the files that are being collected from the user’s desktop.
File Retrieval from Desktop:
The method retrieves a list of files from the user’s desktop directory (as defined by Variables.desktop) using Directory.GetFiles. This allows the malware to scan the user’s desktop for potentially valuable files.
File Type Filtering:
The method filters the files by their extensions, selecting only those with the following types: .pdf, .txt, .sql, .jpg, and .png. These file types are often associated with important data, such as:
File Storage:
After filtering, the selected files are copied to the DesktopFiles directory within the specified work directory (Variables.workdir). The method checks if a file with the same name already exists in the target directory. If it does, the existing file is deleted before the new one is copied, ensuring there are no duplicates.
The method includes a try-catch block that silently ignores any exceptions that might occur during the file collection process. This prevents the malware from crashing or raising any errors, allowing it to continue its operation without alerting the user or security systems. The lack of error reporting indicates that the malware is designed to operate silently and persistently. It will continue its file collection process regardless of any issues, minimizing the chances of detection.
Simultaneously with other data theft routines, the malware targets messaging applications such as Telegram to extract session data. It uses a dedicated method to locate and exfiltrate the contents of Telegram’s tdata directory, which stores session files that allow continued access to the user’s account without requiring login credentials.
The malware first attempts to locate the tdata folder by checking the default path at %APPDATA%\Telegram Desktop\tdata. If this path does not exist, it falls back to parsing the Telegram.lnk shortcut file found on the desktop. This is done by reading the binary structure of the .lnk file to determine the actual installation directory of the Telegram client.
Once the path is resolved, the malware checks whether the Telegram process is running. If so, it terminates the process to prevent any file locks or interference during the copying operation. It then recursively copies all files and subdirectories from the tdata folder into a subdirectory under its working directory, labeled Grabbers\TelegramSession.
By stealing the entire tdata directory, the malware enables an attacker to potentially restore the victim’s Telegram session on another system, gaining full access to messages, contacts, and any media without triggering new authentication.
The malware in this task targets the Discord application in order to steal authentication tokens from the victim’s machine. Discord tokens are sensitive pieces of data that allow unauthorized access to user accounts without requiring a password or multi-factor authentication. By extracting these tokens, the attacker can impersonate the victim and potentially perform malicious activities on their behalf.
The malware checks the following paths to locate Discord’s leveldb directories:
The routine first checks if these directories exist. If they do, it copies them to a temporary location for further analysis. The malware then scans the .log and .ldb files in these directories using three different regular expressions that match Discord’s authentication token formats, including:
When any tokens are found, they are saved to a file named Tokens.txt in the created temporary directory (workdir), specifically in the Grabbers\Discord subfolder. This allows the malware to store and exfiltrate the stolen data easily.
Additionally, the malware attempts to copy the entire leveldb directory, which may contain other sensitive data such as chat logs, user preferences, or session information. This exfiltration increases the risk to the victim, as the attacker may gain further insights into the victim’s Discord usage and interactions.
The malware in this task is designed to capture a screenshot of the victim’s desktop and save it to a specific location on the infected machine. This functionality can be used to exfiltrate sensitive information displayed on the victim’s screen.
The malware begins by creating a directory to store the captured screenshot in the “%APPDATA%\Temp\[Username]\Grabbers\Screenshot” path.
Once the directory is created, the malware initializes a Bitmap object with a resolution of 1920×1080 pixels—commonly matching standard desktop dimensions. It then uses the Graphics.CopyFromScreen method to capture the contents of the primary screen, copying the entire visible desktop area into the bitmap image. After the screenshot is captured, it is saved as a .jpg file named Screen.jpg in the Grabbers\Screenshot subdirectory.
The malware then updates a status variable to reflect the outcome of the screenshot operation—recording “Success!” if the capture and save were successful or storing the corresponding error message if an exception was encountered, which is also printed to the console.
After harvesting data in the Temp directory under %APPDATA%, the malware compresses the entire contents of this directory into a single ZIP archive to consolidate all collected information—such as browser passwords, Telegram sessions, Discord tokens, desktop files, and screenshots, into one file to facilitate easier exfiltration.
The compression routine begins by initializing a ZIP archive using the CP866 character encoding, which supports Cyrillic characters and ensures compatibility across systems. The malware sets the compression level to maximum (level 9) to reduce the archive size as much as possible.
Before saving the archive, the malware embeds identifying metadata into the ZIP file’s comment section. This comment includes the victim’s username, public IP address, and Windows Security Identifier (SID), allowing the attacker to distinguish between victims without needing to open the archive. Once the archive metadata is configured, the malware adds the full contents of the %APPDATA%\Temp\[Username] directory into the archive. The resulting ZIP file is then saved in the same location with the filename format [Username]@ardent.zip.
Upon completion, the malware updates an internal status variable to reflect the success of the compression operation. If an error occurs during the process, the exception is logged, and the error message is stored instead.
Following successful data harvesting and compression, the malware proceeds to exfiltrate the stolen information to a remote attacker-controlled server. In this case, the attacker uses the Telegram Bot API as the exfiltration channel.
It first verifies the existence of the archive file. If the file is present, the malware reads its contents into memory as a byte array. To construct the exfiltration request, the malware concatenates several components to build a full Telegram Bot API URL. This includes:
The caption includes the following data points:
Analyzing PupkinStealer offers important insights into its operational features. Based on this analysis, the following points highlight the capabilities of this information-stealing malware:
PupkinStealer exemplifies a simple yet effective form of data-stealing malware that leverages common system behaviors and widely used platforms to exfiltrate sensitive information. Its lack of complex obfuscation or persistence mechanisms suggests it was designed for rapid deployment and data harvesting rather than long-term compromise. By targeting a specific range of data—browser credentials, desktop files, messaging sessions, and screenshots—and using Telegram as an exfiltration channel, it highlights the continued trend of using legitimate services for malicious purposes.
As threats like PupkinStealer continue to evolve, it is crucial for organizations to implement robust cybersecurity measures and proactive defense strategies to mitigate the associated risks. To reduce the threat of PupkinStealer, users should exercise caution when opening files from untrusted sources or clicking on unfamiliar links, especially those promoting dubious software or content. Additionally, deploying strong cybersecurity practices, such as using reputable antivirus software, regularly updating all software, and remaining vigilant against social engineering attacks, can significantly enhance protection against such sophisticated malware. Educating users about potential threats and promoting a security-conscious culture within organizations are also essential steps in minimizing the risk posed by PupkinStealer and similar malware.
S/N | Indicators | Type | Context |
1 | fc99a7ef8d7a2028ce73bf42d3a95bce | MD5 | PupkinStealer.exe |
2 | 9309003c245f94ba4ee52098dadbaa0d0a4d83b423d76c1bfc082a1c29e0b95f | SHA-256 | PupkinStealer.exe |
3 | https[:]//api[.]telegram[.]org/bot[BotToken]/sendDocument?chat_id=7613862165&caption | URL | Telegram Bot/Exfiltration URL |
4 | 8013735771:AAE_UrTgQsAmiAsXeDN6mehD_fo3vEg-kCM | Telegram Bot Token | Telegram Bot Token used for exfiltration |
5 | %APPDATA%\Temp\[Username]\Grabbers\Browser\passwords.txt | File Path | Collected browser credentials |
6 | %APPDATA%\Temp\[Username]\Grabbers\TelegramSession\* | File Path | Collected Telegram session data |
7 | %APPDATA%\Temp\[Username]\Grabbers\Discord\Tokens.txt | File Path | Collected Discord data |
8 | %APPDATA%\Temp\[Username]\Grabbers\Screenshot\Screen.jpg | File Path | Captured screenshot |
9 | %APPDATA%\Temp\[Username]\DesktopFiles\* | File Path | Collected desktop file |
10 | %APPDATA%\Temp\[Username]\[Username]@ardent.zip | File Path | Exfiltration payload |
No. | Tactic | Technique |
1 | Execution (TA0002) | T1059: Command and Scripting Interpreter T1204.002: Malicious File |
2 | Defense Evasion (TA0005) | T1027.015: Compression |
3 | Persistence (TA0003) | T1547.001: Registry Run Keys / Startup Folder |
4 | Credential Access (TA0006) | T1555.003: Credentials from Web Browsers T1528: Steal Application Access Token |
5 | Discovery (TA0007) | T1082: System Information Discovery |
6 | Collection (TA0009) | T1005: Data from Local System T1113: Screen Capture T1074.001: Local Data Staging |
7 | Exfiltration (TA0010) | T1041: Exfiltration Over C2 Channel T1567.002: Exfiltration to Cloud Storage |
rule PupkinStealer_Malware
{
meta:
description = “Detects PupkinStealer malware based on known IoCs and file hashes”
author = “NA”
date = “2025-05-09”
malware_family = “PupkinStealer”
strings:
// File path indicators
$f1 = “%APPDATA%\\Temp\\*\\Grabbers\\Browser\\passwords.txt” nocase
$f2 = “%APPDATA%\\Temp\\*\\Grabbers\\TelegramSession\\” nocase
$f3 = “%APPDATA%\\Temp\\*\\Grabbers\\Discord\\Tokens.txt” nocase
$f4 = “%APPDATA%\\Temp\\*\\Grabbers\\Screenshot\\Screen.jpg” nocase
$f5 = “%APPDATA%\\Temp\\*\\DesktopFiles\\” nocase
$f6 = “%APPDATA%\\Temp\\*\\*@ardent.zip” nocase
// Telegram exfiltration URL
$url1 = “https://api.telegram.org/bot” ascii wide
$url2 = “/sendDocument?chat_id=7613862165&caption” ascii wide
$token = “8013735771:AAE_UrTgQsAmiAsXeDN6mehD_fo3vEg-kCM” ascii wide
// File hashes as strings
$md5_hash = “fc99a7ef8d7a2028ce73bf42d3a95bce”
$sha256_hash = “9309003c245f94ba4ee52098dadbaa0d0a4d83b423d76c1bfc082a1c29e0b95f”
condition:
// Match the file hash (MD5 or SHA256) or check for IoCs related to file paths
($md5_hash or $sha256_hash) or
// All Telegram-related strings (url1, url2, token) must be present together
($url1 and $url2 and $token) or
// Match based on specific IoC strings (file paths)
(4 of ($f1, $f2, $f3, $f4, $f5, $f6))
}