New Abuse of the ClickOnce Technology, Part 2: Stop Threat Actors from Clicking Once and Staying Forever

Following our deep dive into the internals of ClickOnce application deployment in Part 1 of this two-part blog series, let’s focus on the security implications of this technology. In this blog, we examine how threat actors can weaponize ClickOnce features, and we reveal what we believe to be a new abuse that security teams need to be aware of. We conclude by outlining detection strategies and demonstrating how the CrowdStrike Falcon® sensor identifies and responds to these threats in real-world scenarios.

Now, let’s stop adversaries from clicking once and staying forever.

How Threat Actors Can Take Advantage of ClickOnce apps

Before diving into how threat actors can exploit the ClickOnce technology, let’s examine why they would choose to do so. 

One factor is the user-friendliness aspect of the deployment process, which requires minimal user interaction. To deploy a ClickOnce application, threat actors only need to convince their target to click once or twice to potentially get their malware executed and persist on the target system. This option significantly simplifies the delivery phase of the kill chain as it bypasses common protection mechanisms such as mailbox filtering systems. Alternatively, ClickOnce applications can be deployed from .application files, which requires equally minimal user input and provides threat actors additional options to execute their payload.

This ease of delivering the payload is tied to a second motive: Threat actors are taking advantage of the general lack of awareness around ClickOnce apps, CrowdStrike observations show. While .exe files are heavily scrutinized and controlled in most environments, .application files can sometimes fly under the radar of security tools, creating an opportunity for threat actors to slip through traditional defenses. On the other hand, users rarely realize that clicking a webpage button can trigger software installation, typically expecting to see an executable installer in their downloads folder first. This lack of knowledge of the ClickOnce technology allows threat actors to use misleading buttons and fool users who don’t realize that clicking on it can trigger an application’s deployment.

Another advantage of ClickOnce applications for adversaries lies in the fact that they don’t require elevated privileges to be deployed. While installing a .msi package requires administrator rights, any user can install a ClickOnce app. This lowers the barrier to entry for attacks, as threat actors can target standard user accounts, which comprise the majority of enterprise endpoints.

ClickOnce applications also provide threat actors with a built-in updating mechanism. When configured to be available offline, an application reference file (.appref-ms) is dropped at the installation of the application in the Start Menu (under %Users \AppData\Roaming\Microsoft\Windows\Start Menu\Programs\). This means that every time a user starts the ClickOnce application from the Start Menu, whoever controls the server can update the app. This gives threat actors a reliable method for maintaining remote access and updating their malware as needed to change command and control (C2) addresses, move laterally, or take other actions.

Finally, threat actors benefit from the legitimacy of the ClickOnce deployment process itself. The malicious payload executes within legitimate Microsoft process trees (with rundll32.exe and dfsvc.exe), increasing the stealthiness of the execution. Further,  the UI displayed to the user is a legitimate one from Microsoft.

These characteristics altogether create a powerful attack vector that security teams must actively monitor and defend against. Now that we have highlighted the reasons behind the use of ClickOnce apps to spread malware, let’s summarize previous research that uncovered ways threat actors can weaponize ClickOnce mechanisms, before revealing a new abuse.

Previous Research Introducing ClickOnce Weaponization Vectors

“ClickOnce and you’re in: When .appref-ms abuse is operating as intended” by William Burke

At Black Hat USA 2019, William Joseph Burke, CISA Red Team Lead, presented new methods to weaponize .appref-ms files. As a reminder, the .appref-ms files are dropped in the Windows’s Start Menu folder at the end of a deployment to provide users a shortcut to execute ClickOnce apps that have been configured to be available offline. When opened, the .appref-ms gets the ClickOnce components to fetch available updates from the deployment server, download any potential new components, and run the application.

Stealthy Delivering of the Payload Through Updates

As the update triggered by the .appref-ms is considered to be impacting an application that has already been approved by the user, users aren't prompted to authorize the update. This creates an opportunity for threat actors that can either compromise legitimate ClickOnce application servers or convince users to install a harmless app, to later on transform the benign application into a malicious one. All they have to do is push a malicious update into the deployment server, and the next time the user opens the .appref-ms file of the app, the malicious payload will be downloaded and run without the user realizing the application has changed. 

Leveraging .appref-ms for Persistence

By definition, .appref-ms files trigger the execution of a ClickOnce application upon opening. When placed strategically, adversaries can automate their opening to use them as intermediaries, rather than directly running malicious payloads. For instance, by placing a .appref-ms file in the Startup folder or creating a scheduled task to process the file regularly, they can ensure persistence, with the added bonus of having the payload executed by Windows components. 

“ClickOnce (Ab)Use for Trusted Code Execution” by Nick Powers and Steven Flores 

Trojanizing Legitimate Software with Malicious Dependencies 

Because malicious ClickOnce applications are usually not signed, their deployment often triggers additional security checks like SmartScreen, which increases the chances for the payload to be detected. At DEF CON 30 in 2022, Nick Powers and Steven Flores of SpecterOps presented a method to reduce this friction by trojanizing the dependencies of legitimate applications. They realized that adding a malicious dependency does not impact the application’s signature, so threat actors can embed malicious payloads in the dependencies instead of creating the application from scratch, to benefit from a valid signature. 

More specifically, this abuse can be executed in two ways:

  • Dependency Hijacking: Intercepting an existing ClickOnce deployment and modifying one or more dependencies while preserving the host application's signature
  • New Deployment Creation: Identifying signed .NET applications without existing ClickOnce deployments and creating new deployments with trojanized dependencies

Both approaches result in threat actors having a malicious ClickOnce application with a trusted signature at their disposal, increasing the chances of the deployment going unnoticed.

Uncovering a New Abuse Using COM Hijacking 

Identifying a New Attack Surface

During our deep dive into the ClickOnce deployment process, we stumbled upon something interesting at the start of the server,  in the function dfdll!BindToServer().

Figure 1. Decompiled dfdll!BindToServer() Figure 1. Decompiled dfdll!BindToServer()
Before starting the server by launching “dfsvc.exe,” we observed that BindToServer() first attempts to initialize the COM server using CoCreateInstance(), which, according to the documentation, “creates and default initializes a single object of the class associated with a specified CLSID” (Class Identifier GUID), given in the first argument through the rcx register. But when we stepped through the function call, we realized that the function was unable to instantiate the COM object and was returning through the rax register a “Class not registered” error (0x80040154 - REGDB_E_CLASSNOTREG).
Figure 2. Windbg screenshot showing the return value of CoCreateInstance() Figure 2. Windbg screenshot showing the return value of CoCreateInstance()

So we looked a bit closer. Under the hood, this API fetches the definition of any COM object defined in the registry with the CLSID provided in the first argument. A COM object can be defined under different registry keys, with the first location checked out by Windows being under “HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\{%CLSID%},” where most of the current user’s COM object definitions can be found.

Example with a COM server of OneDrive:

Figure 3. Example of COM object definition in the registry Figure 3. Example of COM object definition in the registry
This means the determining factor in the initialization of the COM server is the CLSID provided to CoCreateInstance(). In the InvokeServer() function, the CLSID is defined by a hardcoded global variable named “CLSID_DeploymentServiceCom,” passed as the first argument to BindToServer():
Figure 4. Decompiled dfdll!InvokeServer(),  decompiled in IDA Figure 4. Decompiled dfdll!InvokeServer(), decompiled in IDA
Looking at the global variable CLSID_DeploymentServiceCom, we can observe that it is defined as the following hardcoded value:
Figure 5. Definition of the CLSID_DeploymentServiceCom variable in IDA Figure 5. Definition of the CLSID_DeploymentServiceCom variable in IDA
Which we can display in the Python console with the following script as a GUID, to confirm it matches the value we’ve seen with Windbg:
Figure 6. CLSID_DeploymentServiceCom displayed as a GUID Figure 6. CLSID_DeploymentServiceCom displayed as a GUID
Online, we can also find references of this CLSID associated with the class “DeploymentServiceCom,” for which Microsoft’s documentation indicates that the class provides “internal services for the ClickOnce deployment API.” We can also verify directly on the “DeploymentServiceCom” implemented in the System.Deployment.dll:
Figure 7. DeploymentServiceCom class implementation from System.Deployement.dll Figure 7. DeploymentServiceCom class implementation from System.Deployement.dll

We could therefore expect the global variable “CLSID_DeploymentServiceCom” to hold the CLSID of a COM object defining “dfsvc.exe,” as we’ve seen dfsvc.exe performing ClickOnce deployments. However, when we looked up on the registry to confirm our theory, we were surprised to find that the registry held no such key. 

Looking at the registry key accessed with Process Monitor, we could confirm that the RPC client (rundll32.exe) indeed attempts to find a COM object defined for the CLSID {20FD4E26-8E0F-4F73-A0E0-F27B8C57BE6F}, but is unsuccessful at finding it. The system first searches under the HKCU hive to identify any “per user” definition, then under HKCR to search within the merged view of per user (HKCU) and per machine (HKLM) definitions, but both result in a “NAME NOT FOUND” error. 

Figure 8. Process Monitor logs showing the unsuccessful attempt to access the COM object definition in the registry Figure 8. Process Monitor logs showing the unsuccessful attempt to access the COM object definition in the registry

This observation led us to wonder: Could we hijack the deployment process by defining our own COM object with the hardcoded CLSID used by rundll32?

Spoiler: Yes we can.

Testing and Validating the Abuse

First, let’s note that adding a key under the hive “HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID\” does not require any elevated privilege. This means there are no requirements to add the registry keys fetched by rundll32.exe within a deployment, and any user can go ahead and define the COM object associated with the hardcoded CLSID that dfdll.dll uses.

Let’s set up an entry in the registry that would define a COM object with that CLSID:

Figure 9. Registry entries set up as part of the COM hijacking Figure 9. Registry entries set up as part of the COM hijacking

Let’s then deploy a  ClickOnce application to confirm that, when the function CoCreateInstance() will be called with the hardcoded CLSID, our masqueraded registry entry will be correctly processed. We click on our application’s deployment manifest, and we observe successively:

1. The API CoCreateInstance() call from the rundll32 COM client successfully accesses the registry key we set up, initiating the request to create the COM server:

Figure 10. Process Monitor logs highlighting Step 1 Figure 10. Process Monitor logs highlighting Step 1
2. The COM object initialization’s request is processed by the dedicated svchost.exe process responsible for “DCOM Server Process Launcher” (PID 1020 in our test session):
Figure 11. Description of the svchost.exe process performing the initialization of our COM server Figure 11. Description of the svchost.exe process performing the initialization of our COM server
Figure 12. Process Monitor logs highlighting Step 2 Figure 12. Process Monitor logs highlighting Step 2
3. svchost.exe starts calc.exe thinking the binary implements the COM server rundll32.exe expects:
Figure 13. Process Monitor logs highlighting Step 3 Figure 13. Process Monitor logs highlighting Step 3

4. calc.exe being executed!

After calc.exe has started, CoCreateInstance() realizes the executable is not implementing the expected COM object and returns a “CO_E_SERVER_EXEC_FAILURE” (0x80080005):

Figure 14. Windbg’s capture showing the return error code from CoCreateInstance Figure 14. Windbg’s capture showing the return error code from CoCreateInstance

Similarly to what happens in the default case where the CLSID is not being defined, dfdll.dll moves on to manually start dfsvc.exe, which implements the expected COM server and pursues the deployment.  

Tactical Analysis: Breaking Down This New Attack Surface

The abuse we’ve identified is a variant of COM hijacking, which introduces a new abuse of ClickOnce technology. Let’s walk through what an attack chain using this hijack would look like and discuss what this discovery entails.

Wrapping It All Together 

During a traditional ClickOnce deployment, rundll32.exe makes an attempt to initialize the COM server by calling CoCreateInstance() with a hardcoded CLSID. In an up-to-date Windows environment, this CLSID doesn't have a corresponding COM object defined in the registry, so CoCreateInstance gracefully fails and the COM server gets initialized later on, when dfsvc.exe registers it using CoRegisterClassObject(). 

By defining in the registry a COM object with the hardcoded CLSID that rundll32.exe uses, a threat actor can impersonate the ClickOnce’s COM server and trick the OS into executing the binary setup in the registry entry. At the next ClickOnce deployment, when rundll32.exe will attempt to instantiate the ClickOnce COM server, CoCreateInstance will resolve the binary added by the adversary and start it. Let’s note that this abuse only works when dfsvc.exe is not already running, in which case dfsvc.exe already exposes an instance of the COM server for rundll32.exe to use, and CoCreateInstance() does not need to look up the COM object's definition in the registry.

This creates the following attack chain:

Figure 15. Summary of the attack chain using COM hijacking to abuse a ClickOnce deployment Figure 15. Summary of the attack chain using COM hijacking to abuse a ClickOnce deployment

Fundamentals of the Technique: COM Hijacking

This new abuse of the ClickOnce technology relies on impersonating a COM server in the registry, which belongs to the category of COM hijacking techniques. The MITRE ATT&CK® framework defines them as the use of “the COM system to insert malicious code that can be executed in place of legitimate software through hijacking the COM references.” It typically refers to the following set of techniques:

  • Overwriting a defined .dll or .exe associated with an existing COM object to get the legitimate component to use the malicious binary instead of the legitimate one
  • Abusing COM object registry keys pointing to a non-existing binary by introducing a malicious binary at the expected location
  • Taking advantage of the registry search order by defining in the user registry hive (HKCU) a COM server already defined in HKLM — with HKCU taking precedence over HKLM, the freshly added entry in HKCU will be used first 

Examples of these techniques are well documented and can be found in many blog posts such as in pentestlab’s post “Persistence-COM Hijacking” and bohops’s post “Abusing the COM Registry Structure: CLSID, LocalServer32, & InprocServer32.”

Our variant of COM hijacking applied to the ClickOnce technology is similar to the first category of COM hijacking listed above, which overwrites in the registry the definition of a binary associated with a legitimate COM object. 

However, this new variant differentiates itself by taking advantage of a COM object that isn't defined in the first place. This gives threat actors a significant advantage: Since they’re not overwriting an existing value, they’re not disrupting any expected behavior and have a higher chance of going unnoticed and persisting after updates. 

In addition, this hijack can be completely fileless as the value for LocalServer32 can include both a binary and its arguments, letting us use cmd.exe or powershell.exe with scripts. This sets our variant apart from InProcServer32-based COM hijacking techniques, which require a malicious library to be present on the system.

Limitations of This Abuse

From an adversarial perspective, this technique offers a discreet and fileless option to deliver payloads, under a legitimate process tree, running as the current user. Once an attacker has compromised a system, all they have to do is set up a few registry keys, make sure dfsvc.exe isn’t running, and get their victim to install (or uninstall) any ClickOnce application. Their payload will then be executed by the svchost.exe process handling the “DCOM Server Process Launcher.” 

However, there are two limitations to this abuse. First, because this technique only works when there is no dfsvc.exe process running, the abuse is unlikely to work more than once upon successive deployments. After the malicious binary has started, the legitimate deployment happens, and dfsvc.exe usually keeps running afterward for some time to answer any further deployment requests. And as we’ve mentioned previously, the abuse needs to have no dfsvc.exe running. This means that after a successful execution of the abuse, the attack would not likely work again until dfsvc.exe naturally terminates or until dfsvc.exe gets manually stopped.

Second, while the abuse doesn't prevent applications from deploying, it does introduce a noticeable delay of 30 to 50 seconds. Indeed, when the call to CoCreateInstance() is performed with the hijacked CLSID, the system creates what it thinks is the process implementing the COM server and gives the process some time to provide an interface pointer to return to the caller of CoCreateInstance(). The delay is due to this allotted time to initialize the COM server, until the system eventually realizes that the server could not provide what was requested and moves on to the manual start of dfsvc.exe. As this is a considerable amount of time for a user familiar with the ClickOnce technology, this can raise suspicions.

Detection Opportunities

As with any attack, early detection is crucial. Here, the first sign of this abuse is the creation of registry keys that define the COM server used in ClickOnce deployment, associated to the CLSID {20FD4E26-8E0F-4F73-A0E0-F27B8C57BE6F}. By monitoring new entries that could define a COM object with that CLSID (e.g., "HKEY_CURRENT_USER\SOFTWARE\Classes\CLSID{20FD4E26-8E0F-4F73-A0E0-F27B8C57BE6F}"), we can better catch COM hijacking attempts using the ClickOnce technology before attackers successfully execute their malicious code.

Using the Falcon sensor, we immediately detect such abuse, block the registry operation, and terminate the process. 

Figure 16. Detection of the abuse attempt in the Falcon UI Figure 16. Detection of the abuse attempt in the Falcon UI

Conclusion

While ClickOnce offers an elegant solution for software distribution, we’ve seen that its powerful features can be weaponized by threat actors in ways Microsoft likely did not anticipate. 

Throughout this two-part series, we’ve discussed many of ClickOnce's characteristics, highlighted how ClickOnce differs from other installation methods, detailed the different deployment scenarios, and documented inner mechanisms. Moving from its legitimate deployment benefits to its potential security risks, we’ve listed some known abuses of the technology and uncovered a new one using COM hijacking.

This new abuse adds to the list of ClickOnce-related threats that security teams must be on the lookout for. As threat actors constantly seek new ways to compromise systems, understanding how little-known technologies like ClickOnce work and realizing how they can be abused is crucial for maintaining a strong security posture. By staying informed and leveraging the detection strategies we've outlined and implementing robust security solutions like the CrowdStrike Falcon platform, organizations can continue to benefit from ClickOnce's convenience while effectively mitigating its risks.

Additional Resources

  • Read other technical blogs from CrowdStrike engineers here.
  • Dive deeper into topics like this at Fal.Con 2026 with expert-led sessions, hands-on training, and real-world insights.

CrowdStrike Falcon Platform
Ready to protect your business?

Try CrowdStrike free today

Subscribe

Sign up now to receive the latest notifications and updates from CrowdStrike

See CrowdStrike Falcon in action