Stanislav Pyzhov, Lead Threat Intelligence Specialist of the Positive Technologies Expert Security Center Sophisticated Threat Research Group
Vladislav Lunin, Senior Threat Intelligence Specialist of the Positive Technologies Expert Security Center Sophisticated Threat Research Group
Introduction
In March 2025, the Threat Intelligence Department of the Positive Technologies Expert Security Center (PT ESC) analyzed an attack that exploited a Google Chrome zero-day vulnerability (sandbox escape), which was registered around the same time and has since been tracked as CVE-2025-2783. Researchers from Kaspersky described the exploitation of this vulnerability and the attack itself, but the subsequent infection chain remained unattributed.
In this report, we argue that the attack can be attributed to the TaxOff group, which we covered in our earlier study. This report also provides data that suggests that TaxOff is actually the same group as Team46, another group we had previously identified.
Team46?
The attack that caught the attention of experts occurred in mid-March 2025. The initial attack vector was a phishing email containing a malicious link. When the victim clicked the link, it triggered a one-click exploit (CVE-2025-2783), leading to the installation of the Trinper backdoor employed by TaxOff. The phishing email was disguised as an invitation to the Primakov Readings forum and the link led to a fake website hosting the exploit. The text of the email can be found in the Kaspersky report.
During the investigation of that attack, another attack, dating back to October 2024, was discovered, which also began with a phishing campaign. The malicious emails contained an invitation to participate in an international conference called "Security of the Union State in the modern world."
Figure 1. Decoy document used in the October 2024 attack
The email structure and style are very similar to those observed in the March 2025 attack.
The October 2024 email contains the following link: https://mil-by[.]info/#/i?id=[REDACTED]. Clicking the link downloads an archive with a shortcut that launches powershell.exe with this command:
The PowerShell script downloaded after the execution of the command is also similar to one of the scripts used by Team46. Here is how the downloaded script looks like:
As you can see, the same pattern is used to name the decoy document on the victim's computer (umawbfez-bkw5-f85a-3idl-3z4ql69v8it0.pdf and 399ha122-tt9d-6f14-s9li-lqw7di42c792.pdf). In both cases, the Edge User-Agent is used when downloading the decoy document, and the Yandex Browser User-Agent is used when downloading the payload. Moreover, in both cases, the computer name is passed via the query parameter.
The only real difference between those two cases is payload. The earlier attack, as described by Dr.Web, exploited a DLL hijacking vulnerability in Yandex Browser (CVE-2024-6473), with the adversaries replacing the legitimate Wldp.dll library to launch the malicious payload. In the October 2024 attack, the adversaries exploited the rdpclip.exe system component, which is also vulnerable to DLL hijacking, and replaced the winsta.dll system library.
Interestingly, winsta.dll serves as a loader for the Trinper backdoor employed by the TaxOff group, which we described earlier. The backdoor used the common-rdp-front.global.ssl.fastly.net C2 server.
This could be dismissed as a coincidence if it weren't for a similar attack recorded in September 2024. The phishing emails sent out by the attackers contained an archive called Корпоративного Центра ПАО «Ростелеком».zip, which included a shortcut called Ростелеком.pdf.lnk that launched powershell.exe with a command typical for Team46:
The decoy document used in the attack was disguised as a message from Rostelecom, Russia's largest digital service provider, notifying of upcoming maintenance outages.
Figure 2. Decoy document used in the September 2024 attack
The phone number at the end of the message is in the Team46 style (which we discussed in our earlier article): it is incorrect and consists of a random sequence of digits.
The payload in this attack was the AdobeARM.exe file, which happens to be a loader for the backdoor used in the first known Team46 attack described by Dr.Web. In fact, when analyzing one of the incidents, we discovered this backdoor, also dubbed AdobeARM.exe, on a system with the Trinper backdoor.
Trinper loader
In the DllMain function, the loader initializes a structure containing the encrypted final payload, a list of hashes for further checks, and auxiliary fields such as the size of the final payload. After initializing the structure, the loader starts a thread that contains logic for decrypting and launching the final payload.
Figure 3. Initialization of the structure and start of the thread
To describe the decryption process, we created a diagram showing the encryption layers and their sequence as well as corresponding decryption algorithms and keys.
Figure 4. Layers of encryption
Within the thread, the loader operates in a loop to decrypt the first layer of encryption, which is then used as a decryptor for the second layer.
Figure 5. Decryption of the first and second layers
Once the second layer is decrypted, control is transferred to it. This layer is obfuscated with a custom control flow flattening technique. It dynamically resolves all the necessary WinAPI functions and then transfers control to the main functionality.
Figure 6. Obfuscated control flow
At this stage, the loader checks for the presence of debuggers and ensures that its execution is performed in the right environment. The loader first verifies that it is being executed in the context of a specific process. For this, it uses a modified BLAKE2b hashing algorithm to compute the hash of the current process's name. The hash is matched against one of the embedded hashes; if the loader is not being executed in the right process, its execution is terminated.
Figure 7. Check for execution within the right process
Next, the loader obtains the firmware UUID by calling the GetSystemFirmwareTable function. (The UUID is then used in the payload decryption process, which means the malicious payload can only be decrypted on the target system. So far, we cannot say for sure how the attackers identified the machine UUIDs for malware generation.) After that, a debugging check through the heap is performed. If the check fails, it diverts the intended control flow, randomizing the UUID values and transferring control to an infinite decryption loop.
Figure 8. Debugging check
If all checks are successfully passed, the UUID is transferred to the function implementing the first round of the ChaCha20 algorithm to generate a key. Using this key, the loader decrypts the third layer of encryption with the ChaCha20 algorithm and performs an integrity check on the decrypted data. Next, the loader decrypts the fourth layer using ImagePathName from the PEB structure as a key. Data from the fourth layer is used to generate the final decryption key for the fifth layer (as in the case with the UUID). This stage also includes an integrity check of the decrypted bytes.
Figure 9. Use of ImagePathName
If the key is decrypted successfully, the loader uses it to decrypt the final layer of encryption, which happens to be the donut loader.
We also encountered variations where Cobalt Strike was used instead of donut. If the final loader is donut, the payload is Trinper; otherwise, the payload is Cobalt Strike. Trinper has functionally remained the same.
Auxiliary tools
The investigation found that the attackers also used self-written tools to conduct reconnaissance on the victim's system. All tools are written in .NET and transmit the obtained data through a named pipe. They include the following:
dirlist.exe to search for files on the system.
ProcessList.exe to obtain a list of running processes.
ScreenShot.exe to capture screenshots.
Comparison of Team46 and TaxOff
Let's consider the facts suggesting that Team46 and TaxOff are likely to be the same group.
PowerShell commands and URL patterns
As described at the beginning of the report, both groups used similar PowerShell commands and scripts, including similar URL patterns.
Overall, the loader used by TaxOff is functionally identical to the Trojan.Siggen27.11306 loader used by Team46. The key similarities are as follows:
Use of a thread to decrypt the payload.
Use of the firmware UUID as a key.
Use of ImagePathName as a key.
Use of a modified ChaCha20 encryption algorithm.
Use of a modified BLAKE2 hashing algorithm.
Use of the donut loader.
Infrastructure
Both groups used syntactically similar domain names with hyphens, mimicking legitimate services. For example:
Team46: ms-appdata-fonts.global.ssl.fastly.net
TaxOff: fast-telemetry-api.global.ssl.fastly.net
Conclusion
Our study strongly suggests that Team46 and TaxOff are in fact the same APT group, which we will continue to refer to as Team46. This group leverages zero-day exploits, which enables it to penetrate secure infrastructures more effectively. The group also creates and uses sophisticated malware, implying that it has a long-term strategy and intends to maintain persistence on the compromised systems for an extended period.
Team46 used a CVE-2025-2783 exploit for system compromise
Initial Access
T1566.002
Phishing: Spearphishing Link
Team46 used phishing emails containing a link to a website with CVE-2025-2783 and an archive with a malicious shortcut loader
Execution
T1059.001
Command and Scripting Interpreter: PowerShell
Team46 uses PowerShell to download intermediate payloads and the main payload
T1106
Native API
Team46 uses donut shellcode to download and inject code
T1204.001
User Execution: Malicious Link
Team46 sends out phishing emails with a link to trick users into clicking it and downloading an archive with a malicious shortcut
T1204.002
User Execution: Malicious File
Team46 used decoy files to run the Trinper and Dante backdoors
Privilege Escalation
T1055
Process Injection
Team46 used Cobalt Strike to inject various malicious payloads into processes
Defense Evasion
T1027
Obfuscated Files or Information
Team46's loader used control flow flattening
T1055.012
Process Injection: Process Hollowing
Team46 used the Trinper backdoor to inject code into processes
T1070.004
Indicator Removal: File Deletion
The Dante backdoor has a self-deletion feature: it is triggered when a specific value is set for the "deadline" registry key, which determines the lifespan of the backdoor in the system without C2 communication
T1070.009
Indicator Removal: Clear Persistence
The self-deletion feature of the Dante backdoor removes registry keys responsible for persistence on the system
T1480.001
Execution Guardrails: Environmental Keying
Team46's loader used the system UUID as a decryption key for the payload
T1497.001
Virtualization/Sandbox Evasion: System Checks
To prevent execution in a virtual environment, the Dante backdoor loader scans various OS logs for strings related to virtual machines and malware analysis tools
T1562.001
Impair Defenses: Disable or Modify Tools
Team46 uses donut shellcode to patch Antimalware Scan Interface (AMSI), Windows LockDown Policy (WLDP), and Native API exit functions to avoid process termination
T1622
Debugger Evasion
The Dante backdoor loader can detect debuggers by checking the debug registers and other parameters indicating the presence of connected debuggers, as well as by scanning for debugger drivers
Credential Access
T1056.001
Input Capture: Keylogging
Team46 used the Trinper backdoor to intercept keystrokes
Discovery
T1057
Process Discovery
Team46 used ProcessList.exe to obtain a list of processes running in the system
T1083
File and Directory Discovery
Team46 used the Trinper backdoor to collect file system information
Collection
T1056.001
Input Capture: Keylogging
Team46 used the Trinper backdoor to intercept keystrokes
T1115
Clipboard Data
Team46 used the Trinper backdoor to access the clipboard
Command and Control
T1071
Application Layer Protocol
Team46's Trinper and Dante backdoors use HTTP and HTTPS for C2 communication
T1090.004
Proxy: Domain Fronting
Team46 used domain fronting to communicate with the Trinper backdoor
T1132.001
Data Encoding: Standard Encoding
Team46 used the Trinper backdoor to encode received information using Base64
T1572
Protocol Tunneling
Team46 used Cobalt Strike for its own C2 protocol encapsulated in HTTPS
T1573.001
Encrypted Channel: Symmetric Cryptography
Team46's Trinper backdoor uses AES-256 to encrypt transmitted data
T1573.002
Encrypted Channel: Asymmetric Cryptography
Team46's Trinper and Dante backdoors use RSA to encrypt transmitted data
Exfiltration
T1041
Exfiltration Over C2 Channel
Team46 used the Trinper backdoor to exfiltrate data to C2