Fortinet Threat Research: QuickFox Supply Chain Attack Used to Deploy FDMTP Implant
FortiGuard Labs uncovers a long-running campaign that used process-based guardrails to select Windows targets
Affected Platforms: Windows Endpoints Impact Parties: QuickFox Users Impact: Supply chain attack resulting in the installation of an implant for persistent access. Severity Level: Medium
FortiGuard Labs is tracking a campaign associated with a long-standing supply chain attack on the QuickFox application. QuickFox is a VPN proxy and game accelerator typically employed by Chinese users to speed up access to Chinese-based resources, often to improve video game user experience.
Active since at least August 2025, the supply chain attack involves a trojanized version of the QuickFox application. The attack is delivered via a modified Electron renderer HTML file used to download and execute a JavaScript-based loader. Upon execution, the JavaScript loader fingerprints the victim endpoint to determine if it’s a valid target before downloading and installing an FDMTP implant. Analysis of infrastructure related to this campaign indicates active development, and infrastructure continues to be active at the time of publishing.
Fortinet has contacted QuickFox as part of our responsible disclosure process. QuickFox has removed the described malicious components from their Windows installer from v3.59.6, and the malicious components that were later transferred to MacOS components do not result in the progression of the infection.
The infection chain associated with this supply chain attack is outlined in Figure 1 below. Note that two different ‘generations’ of the .NET loader employed at different stages of the intrusion were observed, with the deviations of each noted in Figure 1.
The installer executable was trojanized by adding two lines of JavaScript to a single HTML file. This HTML file is executed by the Electron renderer, which is part of the main QuickFox application during initialization. The modified HTML file can be found nested within the archive embedded within the executable file at path ‘ \ .7z\resources\app.asar\candy\core\service\index.html ’. The two lines of JavaScript added to the file are shown in the screenshot in Figure 3, below, and a comparison of the original and the modified version is shown in Figure 2.
These two added lines of JavaScript download and execute two JavaScript files from two URLs referencing the ‘ cdns3[.]51quickfox[.]cn ’ domain. Analysis of the domain identifies it was registered on 09 Jun 2025 by ‘林天俊 (Lin Tianjun)’. The domain appears to be an implementation of typosquatting that swaps the ‘ .com ’ TLD in the legitimate ‘ cdns3[.]51quickfox[.]com ’ with the ‘ .cn ’ TLD. To confirm, the ‘ 51quickfox[.]cn ’ domain is not an official QuickFox domain. A comparison of the details related to the masquerading domain and the legitimate QuickFox domain is shown in Table 1.
Table 1: Comparison of domain details for the legitimate QuickFox infrastructure and the malicious masquerading domain.
Analysis of versions of the QuickFox installer indicates the trojanized components were introduced sometime between 2025-07-25 and 2025-08-13. The earliest affected version that FortiGuard Labs obtained was v3.0.51.0 for the Windows application. Analysis of available QuickFox application versions for Mac identified that the supply chain attack had resulted in the modified ‘index.html’ file being included in some builds. However, execution guardrails in the initial downloaded JavaScript restricted execution to Windows endpoints. Behavior indicative of these initial infection stages was not observed in iOS and Android versions of the application, indicating the campaign was likely specifically targeting Windows users. Details of the compromised status of available versions are outlined in Table 2.
Table 2: Details of the affected version of the QuickFox installer. Note. QuickFox does not maintain a publicly accessible version release timeline or historic installers for their Windows applications, so these represent the versions publicly available at the time of this reporting and should not be considered an exhaustive list.
Analysis of the files served by the two URLs identified that ‘ firebase-analytics-compat.js ’ contains legitimate Google Firebase code. The ‘ firebase-app-compat.js ’ file is a heavily obfuscated JavaScript file masquerading as the legitimate Firebase SDK code. Obfuscation of JavaScript and HTML components within an Electron application like QuickFox is not anomalous, so the presence of obfuscated JavaScript is not itself anomalous. However, in this case, the downloaded JavaScript leverages a custom algorithm outlined below:
A screenshot of some of the obfuscation is shown below in Figure 4.
Analysis of the deobfuscated script identifies several key functions; the first is a check to validate the affected endpoint is running Windows. The second is a check with C2 to ensure an endpoint is not re-infected. The third is to generate a list of processes using the tasklist command via a cmd.exe child process. This tasklist is then analyzed for specific process names. The script will stop and exit if a process named ‘ steam.exe ’ is in the tasklist output. Steam is a popular gaming platform, and FortiGuard Labs assesses that this guardrail is likely to restrict deployment of later-stage payloads to corporate computers. The check is for 26 other process names related to a broad range of personal and business functions. A complete list of the process names, the assumed associated applications, and their function is shown below in Table 3.
Table 3: Process names and likely associated application and application function.
Once the script has confirmed that Steam is not running and that at least one of the applications in the above list are running the script will then download the stage payload. Pseudocode for this section of the deobfuscated JavaScript is shown below in Figure 5.
Note that, because QuickFox is an Electron application, JavaScript files are executed in the context of a dedicated child process spawned under the main QuickFox application process. This alters the process lineage for the infection process outlined above and should be considered when assessing protections from EDR and other technologies. The process tree associated with guardrail validation is very noisy, with a significant number of cmd.exe processes spawning from the child QuickFox process. A screenshot of the infection process lineage is shown in Figure 6 along with annotations for key infection stages.
The stage of the JavaScript involves downloading the zip file ‘ update.zip ’ from the C2 via a web request to ‘ hxxp://cdns3[.]51quickfox[.]cn/2025090411/update.zip ’ and saving it to ‘ %TEMP%\quickfox\update.zip’ . FortiGuard Labs has identified at least two generations of the stage of the intrusion, both of which execute an FDMTP payload:
In both generations, the prior JavaScript extracts the contents of the downloaded ‘ update.zip ’ to the ‘ %APPDATA%\Local\Temp\quickfox\updated\ ’ directory. Following extraction, the script creates a 1-byte file ‘ data.dat ’ in the updated directory. This file serves as a file-based mutex, and the script will exit if the file already exists to prevent re-infection. The script then executes ‘ csmonitor.exe’, which sideloads the malicious ‘ Microsoft.ServiceHosting.Tools.dll ’ DLL.
The behavior of this ‘ Microsoft.ServiceHosting.Tools.dll ’ loader changes between generations, indicating ongoing development to improve the campaign’s survivability.
Analysis of the generation 1 version of the ‘ Microsoft.ServiceHosting.Tools.dll ’ file (SHA256:2B6CDAFDFE427A3DE1A94A8A2CA1F09FC4C8F90E4F59089FD9B35B73185ED01C) identifies it as a .NET loader containing an embedded .NET module payload ‘ Client.dll ’ stored as a byte array. When executed through the csmonitor.exe application, the .NET loader instantiates an instance of the ‘ DevStore ’ class, which loads and executes the embedded ‘ Client.dll ’ as a new thread within the context of the csmonitor.exe process. A code snippet of key components of the DevStore class from the ‘ Microsoft.ServiceHosting.Tools.dll ’ file is shown below, in Figure 7.
The generation 2 sample of ‘ Microsoft.ServiceHosting.Tools.dll ’ (SHA256:795594AD5E6F2868CC4D8ED12DABF4F3999A1477C6B250527C5EDE9A98528FB9) functions differently from the generation 1 sample. The generation 2 sample is obfuscated using the JieJie .NET Protector tool 1 and functions as a loader to decrypt and load the contents of ‘ update.bin ’. The ‘ update.bin ’ file is encrypted using AES-128-ECB encryption with a common, hardcoded key ‘ POt_L[Bsh0=+@0a. ’ Note that this is the same decryption key observed in the FDMTP campaign reported by Darktrace. The decrypted contents of this file are a copy of the final FDMTP payload ‘ Client.dll ’ and functionally match those loaded in generation 1.
The Client.dll payload contains 15 compressed modules within its resources section, as shown in Figure 8 below.
On execution, it registers a ‘ ResolveEventHandler ’ object that points to the ‘ Costura.AssemblyLoader.ResolveAssembly()’ method as shown above in Figure 8. This method is called when the .NET Framework can’t find a module that the client module is trying to load (i.e., when an ‘Assembly Resolve’ event is triggered). When called, this method decompresses and loads the corresponding module from the module resource section. This functionality obfuscates code within the compressed modules, reducing the effectiveness of static analysis methods.
Each of these 15 modules contains specific functionality used during the operation of the FDMTP payload, but the main module that orchestrates the payload execution is ‘ Client.FDMTPFrame.dll ’.
Following the registration of this handler, the FDMTP implant attempts to obtain a C2 connection via the ‘Client.Program.InitConnect() method, as shown in Figure 9 below.
This method defines two RPC servers (CommonService and PluginService) and three plugins (FileTransferPlugin, SystemEventsPlugin, and ActiveWindowPlugin) for retrieving information from a hardcoded staging C2 via an API request ‘ GET /GetCluster?protocol=DotNet-TcpFDMTP&tag= ’ to a staging domain, which in the analyzed sample here was ‘ www[.]icloud-cdn[.]net ’. This request registers the affected endpoint with the C2 using a country code ( ) and retrieves an array of nodes (IP addresses and ports) used for subsequent DTMP C2 communications.
The staging domain used to provide the IP and ports of FDMTP clusters is hardcoded within each sample. The FortiGuard Labs team identified several domains being used as staging domains associated with the QuickFox supply chain compromise, with at least three still active when QuickFox was notified of the compromise. The infrastructure related to this campaign continues to evolve the contents of ‘ update.zip’, changing along with subsequent malware file names. Internal names within tooling appear consistent. The API function names also appear to be changing over time, with ‘ GetSlaver ’, ‘ GetGateways ’, ‘ GetEndpoints ’ ‘ GetServers ’, ‘ GetHosts ’, and ‘ GetNodes ’ all observed performing similar functions. These C2 staging domains, along with some of their associated URLs, are shown in Table 4.
Table 4: Domains and associated URLs used as staging domains for the FDMTP implants associated with this QuickFox campaign infrastructure.
The FortiGuard Labs team observed that staging domains responded to this request with a base64-encoded and gzip-compressed list of two IP:Port entries per request, with port ranges observed between 20800 and 20816. An example of web traffic associated with this target registration is shown in Figure 10.
Once the implant has received the C2 connection information, it establishes a connection to the C2 clusters through a FDMTP socket, as shown in Figure 9 above. The FortiGuard Labs team identified the following clusters/nodes (see Table 5) associated with some of the staging domains outlined in Table 4.
Table 5: FDMTP cluster nodes associated with identified staging C2 domains.
Once the running implant is connected to the C2 cluster, it conducts an FDMTP handshake by sending ‘ 00 01 ’ and ‘ 00 04 ’ flag packets with negotiation types, IDs, and status. Afterward, the C2 server sends a ‘ GetInfo ’ RPC request within a ‘ 00 14 ’ flag packet to the implant to collect basic information from the victim’s device. The malware serializes and compresses the basic information and sends it as a response in a ‘ 00 15 ’ packet. An example of the two packets collected during analysis is shown in Figure 11.
When the implant receives this ‘ GetInfo ’ RPC request, the Client.CommonService.GetInfo() method is called based on the RPC server’s registry information. It sends the basic information stored in the Common.HostInfo variable, which contains the data as shown in Figure 12 below.
The malware compresses the data list above and sends it to the C2 server over a ‘ 00 15 ’ flag packet, as illustrated at the bottom of Figure 11. The C2 server then sends an ‘ EnumProcessByJson ’ RPC request to collect all running process information from the compromised endpoint, including the PIDs and process names. This is likely to perform additional server-side filtering of compromised endpoints and to support adversary targeting.
The implant continued to periodically connect to FDMTP infrastructure. The implant appears to operate largely through plugins (DLLs) that are pushed from the FDMTP server to the implant during check-ins. When the adversary needs to execute a remote plugin on the compromised device, the C2 server sends ‘ IsRegistryPlugin ’, ‘ RegistryPlugin’ and ‘ RunPlugin’ RCP requests within packets marked with the ‘ 00 14 ’ flag.
The C2 server sends a plugin’s hash code to the operating implant as the parameter to the IsRegistryPlugin() method, which invokes the corresponding ‘ Client.FDMTPFrame.Connection.PluginService.IsRegistryPlugin() ’ with the DLL file hash code as its parameter. The operating implant then checks whether the corresponding plugin has already been stored in the compromised device’s registry.
It then reports the result (‘ 00 ’ indicates not found; ‘ 01 ’ indicates found) back to the C2 server within a ‘ 00 15 ’ flag packet, as shown in Figure 13.
If the C2 server receives a ‘ 00 ’ response to the ‘ IsRegistryPlugin’ request, it sends a ‘ RegistryPlugin ’ RPC request to the FDMTP server. The corresponding RPC request response contains a compressed executable file embedded within the packet, as shown below in Figure 14.
On receipt of this response, the ‘ Client.FDMTPFrame.Connection.PluginService.RunPlugin()’ method is invoked to save the compressed executable file into the system registry under the specific sub-key ‘ HKCU\SOFTWARE\Microsoft\IME\{Common.HostInfo.HWID} ’.
If the server receives a ‘ 01 ’ in response to the ‘ IsRegistryPlugin’ request, or once the response to the ‘ RegistryPlugin ’ request has been saved to the registry, the C2 server proceeds directly with a ‘ RunPlugin’ RPC request.
When the implant receives a ‘ RunPlugin’ RPC request, the ‘ Client.FDMTPFrame.Connection.PluginService.RunPlugin() ’ method is invoked. The corresponding packet contains a hash of the target plugin’s compressed file code corresponding to the target plugin that is passed to the ‘ Client.FDMTPFrame.Connection.PluginService.RunPlugin() ’ method. Within the method, the implant first retrieves the plugin file from the system registry using its hash, then decompresses and loads it. Finally, the plugin’s ‘ Plugin.Room.run() ’ method is invoked. In the sample analyzed during testing, the loaded plugin file is named ‘ Assist.dll ’. When its ‘ Plugin.Room.run() ’ method is invoked, it calls the ‘ Handle() ’ method to process the decompressed parameter stored in the ‘ pluginMethod’ variable, as shown in Figure 15.
In the case of the plugin sample analyzed during our investigation, the ‘ Assist.dll ’ plugin downloads two files and saves them to the ‘ %LocalAppData%\Microsoft\WindowsApps ’ folder. Once downloaded, the C2 server can issue a ‘ StartProcess ’ RPC request to execute the downloaded files. It should be noted that these URLs used to retrieve subsequent executable components are embedded within the server-provided plugin and are configurable between campaigns, allowing some additional survivability for running implants.
FortiGuard Labs did not observe significant post-exploitation behavior from the FDMTP implant on affected victims following initial installation beyond basic enumeration performed through the previously described plugin functionality. The FortiGuard Labs team did not observe any additional plugins beyond those reported by Darktrace in FDMTP reporting.
FortiGuard Incident Response has engaged with the affected vendor, per our responsible disclosure program. QuickFox responded quickly to identify the trojanized components of their software, has since removed the reported components, and begun an internal investigation into the associated supply chain attack. Currently identified affected versions apply to the Windows applications only at this stage, and versions >v3.0.35 (the earliest known non-compromised version) and <v3.55.6, the most recent version in which QuickFox has removed malicious components.
FortiGuard Labs does not confidently attribute this campaign to a particular actor. However, there is significant technical crossover with open-source reporting that is externally attributed to Twill Typhoon. Details of this technical crossover are outlined below.
Reporting by Darktrace highlights the recent use of an FDMTP implant matching the final payload deployed in the campaign related to the QuickFox supply chain compromise. Matches were based on side-loading techniques ( T1574.001 – Hijack Execution Flow: DLL ), code structure, and key loader components. In this previously reported campaign, the adversary leveraged the legitimate ‘biz_render.exe’ binary, a legitimate component of Sogou Pinyin IME, as the sideloading target, with their loader replacing ‘browser_host.dll’, whereas in our case, the adversary leveraged the ‘csmonitor.exe’ application as a target for sideloading.
In addition to this technique implementation crossover, there is shared infrastructure between the two campaigns, as C2 ‘cluster’ IPs provided by staging domains observed in this previously reported campaign were also registered as C2 ‘cluster’ IPs linked to staging domains observed in the campaign we highlighted above. Linkages here are entirely related to technical factors, indicating with high confidence that the same infrastructure and tooling were employed across the two reported campaigns.
An additional consideration regarding attribution is the inclusion of partial victim filtering at the client level. The JavaScript executed through the trojanized HTML code responsible for the initial C2 connection includes execution guardrails that kill the infection if an executable named ‘ steam.exe ’ is running. FortiGuard Labs assesses that this is likely intended to avoid deployment on endpoints used for personal use, increasing the likelihood of the second-stage payload only being deployed in corporate environments. Additionally, the initial JavaScript installs the payload only if one of a list of processes (see Table 3) is present. The list includes several processes associated with administrator tooling, translator applications focused on Chinese-native translators, developer tools, and crypto-related applications. This collection of applications does not provide definitive validation of targeting, as a broad range of motivations can be supported by targeting the processes in the targeted list. However, the list does contain a large percentage of Chinese translation applications
QuickFox’s user base is primarily Chinese international students and expats who use the application to more efficiently interact with Chinese-based services. Given this user base, a hypothesis around targeting is that primary targeting was generically for Chinese citizens operating outside China. A competing hypothesis is that this campaign aimed to target professionals required to interact with Chinese native speakers, potentially for trade or diplomatic engagement purposes. Neither hypothesis can be confirmed without understanding the victim context for second-stage intrusions, which would identify true targets of the campaign.
This campaign highlights the need for organizations to adequately prepare against supply chain attacks, especially those targeting specific user bases that may not sit within an organization’s typical threat profile. Additionally, the TTP and indicator crossover related to this campaign and the campaign reported by Darktrace earlier in 2026 highlight how the application of timely, high-confidence open-source threat intelligence can, in some cases, provide detection opportunities across adversary campaigns.
The lack of confidence in attribution beyond technical clustering is largely due to limited visibility into second-stage post-exploitation activity. Despite identifying several victims of this initial infection, this initial part of the campaign (up to and including FDMTP implant installation) appears opportunistic, with the information gathered centralized, likely for second-stage target validation.
FortiGuard Labs is continuing to investigate infrastructure associated with this larger campaign to fill some of these intelligence gaps and identify other potentially related supply chain attacks. If you believe this or any other cybersecurity threat has impacted your organization, please our Global FortiGuard Incident Response Team 2
FortiGuard Antivirus signatures associated with indicators related to this investigation are provided in the IOC section below. FortiGate, FortiMail, FortiClient, and FortiEDR support ingestion of signatures from the FortiGuard AntiVirus service. As a result, customers who have these products with up-to-date protections are protected.
The URLs are rated as “Malicious Websites” and “Malicious Activities Found” by the FortiGuard Web Filtering service.
FortiGuard IP Reputation and Anti-Botnet Security Service proactively block these intrusions by aggregating malicious source IP data from the Fortinet distributed network of threat sensors, CERTs, MITRE, cooperative competitors, and other global sources that collaborate to provide up-to-date threat intelligence hostile sources.
TA0001: Initial Access
TA0011: Command & Control
The following lists of indicators are associated with the campaign outline in this article.
%APPDATA%\Local\Temp\quickfox\updated\ Microsoft.ServiceHosting.Tools.dll
Microsoft.ServiceHosting.Tools.dll
Generation 1 FDMTP loader. Self-contained FDMTP payload stored as byte array
3B79D95F7F7B58C401A3BC79F94EBB52
173DD4190740B96F6F733C801B6428ED4B52B607
2B6CDAFDFE427A3DE1A94A8A2CA1F09FC4C8F90E4F59089FD9B35B73185ED01C
%APPDATA%\Local\Temp\quickfox\updated\ Microsoft.ServiceHosting.Tools.dll
Microsoft.ServiceHosting.Tools.dll
Generation 2 FDMTP loader. Obfuscated .NET module that decrypts and reflectively loads the FDMTP payload stored in collocated ‘ update.bin ’ file.
03FD832B81DD54D2BF5F610A8FF27856
7AB7FFE4C233A4F2440F0FDEB2E117C788792281
795594AD5E6F2868CC4D8ED12DABF4F3999A1477C6B250527C5EDE9A98528FB9
%APPDATA%\Local\Temp\quickfox\updated\ Microsoft.ServiceHosting.Tools.dll
Microsoft.ServiceHosting.Tools.dll
Generation 2 FDMTP loader. Obfuscated .NET module that decrypts and reflectively loads the FDMTP payload stored in collocated ‘ config.bin ’ file.
2DD8681DCD218C88D1C78DFE939EC92B
C41B4E11E6A9E3B53DA1F92B213DE9F65A825C92
6634339B813E6105B5138DE6AB67B016B8DFBF49233C29DE9BAB3207E8B50D24
%APPDATA%\Local\Temp\quickfox\updated\ csmonitor.exe
Legitimate Windows binary used to sideload both generations of FDMTP loader. Not malicious.
2FFDCFB7157511789228988E26D06FD6
39504CEAD410056878962053F8D027E9F299CD10
A5D36EDC34FE54B2092349F877DAF560A98F5FEA635D1AC4A110B3518102EF96
Legitimate executable (not malicious)
%APPDATA%\Local\Temp\quickfox\updated\ update.bin
Encrypted FDMTP payload. Decrypted and loaded by generation 2 FDMTP loader.
5E4ED6ABBF555E5A542E3D4308CCD7BF
B370B674CE877B9C0A7708C7834AEB7EDA983564
DC666E9C148BBCA5E21D8C9A97143575C075F53360F135E0191AED9E8278D396
%APPDATA%\Local\Temp\quickfox\updated\ update.bin
Encrypted FDMTP payload. Decrypted and loaded by generation 2 FDMTP loader.
19E760EE849EB7C1F100F2B7010A763D
3449A349B6C8045B16DF4F88D58C65C2BDF891BB
5CBB64375636E83B5F17D6083633CECC02E2A5F4168CD7CCA5CDEE36CCCA9B38
%APPDATA%\Local\Temp\quickfox\updated\ config.bin
Encrypted FDMTP payload. Decrypted and loaded by generation 2 FDMTP loader.
1F3031167F94B166CC7B69376A01C124
B194A997C9A653134BDB1F2D0C3137DCDACB54D5
A53D756F28457B1C4A239C91CDEC8ED7B7DA67A93E332E6DF9621CBEF8417474
Zip containing generation 1 FDMTP loader and ‘ csmonitor.exe ’.
30D59C3D4916AA5FB24050C6AAE7F8E4
A195810C41F401C4B48CB557CF8CE60C2D807025
D9DB5CBC193DDAF4C0A265804FDEF70C32451DAAF2974FA9ADF52CE1DEFAC5F7
Zip containing generation 2 FDMTP loader, payload and ‘ csmonitor.exe ’.
E0A92209DD62DAE8460D934DC6B7DDD7
2CC0425A90A39AC4EEDADD59CAAAFAD5B50F8420
7462CE2595119C928CF516EC33148DC2A39DD9F71636A5C849C7ED93B7C5CA06
Zip containing generation 2 FDMTP loader, payload and ‘ csmonitor.exe ’.
B1D344C9A1525373BE6A3980FA85A603
11A6DF1E15663AE89F59A9E598AE8987F42A632B
3BD3B300F3278520819A06D0CB1F0EADBF946DBBC11352538246FF075EB427F1
Zip containing generation 2 FDMTP loader, payload and ‘ csmonitor.exe ’.
5F3DAF7417DD666213168EB6C7453CC7
E90D2730F3354FF1ADF334B03C95EAC3207D47B9
6932A20AC61FD3F93D7CFEE414F6F46834068AC7C9CA011B054A6A10DC56B3D1
1 2
The full story
This article is one source in a clustered incident — the cluster page carries the summary, timeline and every other outlet covering it.
