Self Assessment

PupkinStealer : A .NET-Based Info-Stealer

Published On : 2025-05-09
Share :
PupkinStealer : A .NET-Based Info-Stealer

Executive Summary

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.

Introduction

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.

Key Findings

  • PupkinStealer is an information-stealing malware designed to collect a specific set of data, including browser credentials, desktop files, messaging sessions (Telegram and Discord), and desktop screenshots.
  • The malware extracts and decrypts saved login credentials from Chromium-based browsers by obtaining decryption keys stored in their Local State files.
  • It copies Telegram’s tdata folder to exfiltrate session files, allowing potential access to user accounts without credentials.
  • Authentication tokens are harvested from Discord’s leveldb storage using regular expressions, enabling unauthorized account access.
  • The malware captures the screen at a fixed resolution and saves the image locally before exfiltration.
  • All stolen data is compressed into a single ZIP archive with embedded metadata (e.g., username, IP, SID) to assist attackers in victim tracking.
  • The archive is sent to an attacker-controlled Telegram bot using a crafted URL with detailed system information in the caption.

ETLM Attribution

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.

Bot details: used in exfiltration

Additionally, chat metadata identified a user whose bio contains Russian-language text (“куплю рамоны за 2 к”), further suggesting a possible Russian origin.

TA’s Telegram

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.

Analysis of Pupkin Stealer

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.

.text section

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.

Snippet: embedded compressed DLLs

Behavioral & Code Analysis

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.

Main() function

Task 1: Harvesting Credentials from Web-Browsers

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.

Code snippet: ChromiumPasswords class

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:

  • GetKeyChrome(): Extracts and decrypts the key for Google Chrome.
  • GetKeyOpera(): Extracts and decrypts the key for Opera.
  • GetKeyOperaGX(): Extracts and decrypts the key for Opera GX.
  • GetKeyEdge(): Extracts and decrypts the key for Microsoft Edge.
  • GetKeyVivaldi(): Extracts and decrypts the key for Vivaldi.

Each of these methods follows a similar pattern:

    1. The Local State file for the respective browser is read.

    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:

  • IsV10(byte[] data): This method checks if the encryption version of the saved password data is “v10”. This is important because the encryption method may vary between different versions of Chromium-based browsers, so identifying the version is a critical first step.
  • Prepare(byte[] encryptedData, out byte[] nonce, out byte[] ciphertextTag): This method prepares the encrypted password data by extracting the nonce and ciphertext tag, which are required for AES GCM decryption.
  • Decrypt(byte[] encryptedBytes, byte[] key, byte[] iv): This method handles the actual decryption of the encrypted password data using AES-GCM (Authenticated Encryption with Associated Data). It requires the encrypted bytes, the decryption key, and the initialization vector (IV) (or nonce) to decrypt the data and retrieve the original password.

The decryption process follows these steps:

  1. The encrypted Data is passed to the Prepare() method to extract the nonce and ciphertext tag.
  2. The nonce, ciphertext, and the decryption key are then passed to the Decrypt() method, which uses AES-GCM decryption to recover the original password.
  3. The decrypted password is returned as a string.

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.

Task 2: Grabbing Files from Desktop

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:

  • .pdf and .txt: Document files that may contain sensitive or confidential information.
  • .sql: Database files that could store user data or credentials.
  • .jpg and .png: Image files that could include private or personal photos.

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.

Task 3: Telegram Data Exfiltration Module

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.

Code snippet: Telegram data harvesting

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.

Task 4: Discord Token Grabber

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.

Code snippet: Discord data harvesting

The malware checks the following paths to locate Discord’s leveldb directories:

  • %APPDATA%\Discord\Local Storage\leveldb
  • %APPDATA%\Discord PTB\Local Storage\leveldb
  • %APPDATA%\Discord Canary\leveldb

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:

  1. Standard Discord tokens
  2. OAuth tokens
  3. Multi-factor authentication (MFA) tokens

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.

Task 5: Screenshot Capture

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.

Code snippet: screenshot functionality

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.

Data Compression:

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.

creating a zip archive

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.

Exfiltration:

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 base endpoint: https[:]//api[.]telegram[.]org/bot
  • The bot token, stored in Variables.Token
  • The target chat ID, provided as an argument to the function
  • A URL-encoded caption containing detailed information about the victim system and the success of each harvesting module

Code snippet: data exfiltration

The caption includes the following data points:

  • Username
  • Public IP address
  • Security Identifier (SID)
  • Total number of recovered passwords
  • Discovery status and counts of passwords for major browsers (Chrome, Edge, Opera, Vivaldi, etc.)
  • Whether files were found on the desktop
  • Status of the Telegram session theft
  • Success flags for the screenshot and ZIP compression modules
  • Attribution string: “Coded by Ardent”

Data Exfiltration to Telegram Bot

PupkinStealer Capabilities

Analyzing PupkinStealer offers important insights into its operational features. Based on this analysis, the following points highlight the capabilities of this information-stealing malware:

  1. Credential Theft from Web Browsers: Extracts and decrypts saved login credentials from Chromium-based browsers (Chrome, Edge, Opera, Opera GX, Vivaldi)
  2. Desktop File Collection: Scans the victim’s desktop for files with selected extensions (.pdf, .txt, .sql, .jpg, .png) and copies them for exfiltration.
  3. Telegram Session Hijacking: Locates and exfiltrates Telegram’s tdata folder to capture active session files, allowing account takeover without login credentials.
  4. Discord Token Grabbing: Extracts Discord authentication tokens from leveldb directories using regular expressions to enable account access and impersonation.
  5. Screenshot Capture: Takes a screenshot of the victim’s primary screen
  6. Data Packaging and Exfiltration: Compresses all stolen data into a ZIP archive embedded with system metadata (username, IP, SID), then exfiltrates the archive to an attacker-controlled Telegram bot via the Telegram Bot API.

Conclusion

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.

Indicators Of Compromise

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

MITRE ATT&CK Tactics and Techniques

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

YARA Rules

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))
}

Recommendations

  • Implement threat intelligence to proactively counter the threats associated with the PupkinStealer.
  • To protect the endpoints, use robust endpoint security solutions for real-time monitoring and threat detection such as Antimalware security suit and host-based intrusion prevention system.
  • Continuous monitoring of the network activity with NIDS/NIPS and using the web application firewall to filter/block the suspicious activity provides comprehensive protection from compromise due to encrypted payloads.
  • Configure firewalls to block outbound communication to known malicious IP addresses and domains associated with PupkinStealer command and control servers.
  • Implement behavior-based monitoring to detect unusual activity patterns, such as suspicious processes attempting to make unauthorized network connections.
  • Employ application whitelisting to allow only approved applications to run on endpoints, preventing the execution of unauthorized or malicious executables.
  • Conducting vulnerability assessment and penetration testing on the environment periodically helps in hardening the security by finding the security loopholes followed by remediation process.
  • Use of security benchmarks to create baseline security procedures and organizational security policies is also recommended.
  • Develop a comprehensive incident response plan that outlines steps to take in case of a malware infection, including isolating affected systems and notifying relevant stakeholders.
  • Security awareness and training programs help to protect from security incidents such as social engineering attacks. Organizations should remain vigilant and continuously adapt their defenses to mitigate the evolving threats posed by the PupkinStealer malware.
  • Update security patches that can reduce the risk for potential compromise.