.NET: Microsoft Technologies based on the .NET software framework. Runtime: An environment required to run apps that aren't compiled to machine language.
Because the DLL executes before Program.Main(), the only supported in-place mitigation to test is Windows Exploit Protection’s PreferSystem32 policy on the executable that performs ClickOnce activation; application code cannot retroactively secure that startup load.
Test the in-place mitigation
Microsoft introduced PreferSystem32 specifically for application-directory planting of system DLL names: it searches System32 before the application directory. Microsoft classifies application-directory planting as defense in depth rather than generally servicing it with a down-level security update.^1^
- Identify the process that loads the planted DLL.
- Capture another
.appref-mslaunch in Process Monitor. - Filter for:
-
Operation is Load Image -
Path ends with dfshim.dll
-
- Record the Process Name and full executable path on the successful malicious load.
- Do not assume that your application executable is the correct policy target; the load occurs before its entry point.
- Capture another
- Apply PreferSystem32 to that executable in a test system.
- Open Windows Security → App & browser control → Exploit protection → Program settings.
- Select Add program to customize.
- Prefer Choose exact file path and select the executable identified above.
- Locate Prefer system32 images/PreferSystem32, override the system setting, and enable it.
- Apply the change and restart the affected process or Windows when prompted. Windows supports per-program Exploit Protection configuration through this interface.^2^
- Retest the proof of concept.
- Leave the test
dfshim.dllin the ClickOnce application directory. - Launch through the same
.appref-msshortcut. - Expected result: the applicable system DLL is loaded from the Windows system directory instead of the application directory, and the proof-of-concept file is not created.
- Confirm the successful
Load Imagepath in Process Monitor.
- Leave the test
- Verify the stored policy from elevated PowerShell:
$process = "actual-loader.exe"
Get-ProcessMitigation -Name $process
# Start the ClickOnce application, then inspect the running instance.
Get-ProcessMitigation -Name $process -RunningProcesses
Get-ProcessMitigation and Set-ProcessMitigation require an elevated PowerShell session.^3^
PreferSystem32 is a compensating control, not a general prohibition on loading DLLs from the application directory. It is relevant to system DLL names such as those in your list, must be applied to the process performing the vulnerable load, and requires compatibility testing. It does not establish that every listed name is exploitable.
Why Program.Main() cannot fix this case
For unpackaged desktop applications, the normal DLL search process considers redirection, API sets, already loaded modules, Known DLLs, and then the application directory before the system directory. The precise result therefore varies by DLL, Windows version, architecture, process, and loading method.^4^
Calling SetDefaultDllDirectories or SetDllDirectory("") at the beginning of Main() can harden subsequent loads performed by your process, but cannot affect dfshim.dll or another component already loaded during .appref-ms activation. For DLLs loaded later by code you control:
- Use fully qualified paths.
- Prefer
LoadLibraryExsearch flags orSetDefaultDllDirectories. - Test process-wide changes against plug-ins and native dependencies.^5^
Stronger permanent remediation
If PreferSystem32 cannot be applied to the actual activation process, fails testing, or does not cover all observed loads, retaining the same per-user ClickOnce execution model does not provide the requested guarantee.
ClickOnce deliberately stores and executes application files from a per-user, versioned cache, and manages replacement directories during updates.^6^ Avoid changing ACLs inside that cache: ClickOnce manages those directories, making such changes operationally fragile across updates.
The stronger remediation is:
- Deploy the executable and native dependencies with MSI or another managed installer.
- Install code under an administrator-protected location writable only by administrators, such as Program Files.
- Store user-writable settings and data outside the executable directory.
- Sign the installer and application binaries.
- Retire the
.appref-msshortcut and launch the installed executable. - As a standard user, verify that creating or replacing DLLs in the installation directory is denied.
- Repeat the Process Monitor test and confirm system DLLs load from the expected Windows directory.
ClickOnce is intentionally per-user and does not install files under Program Files, whereas Windows Installer commonly requires administrative installation.^7^
Signing the ClickOnce manifests remains recommended, but it is not a substitute for controlling the DLL search path. Manifest signing proves publisher identity and protects manifested content against tampering.^8^ ClickOnce hashes likewise validate files declared in the application manifest; an omitted, externally planted DLL is a different loading-path issue.^9^
Validate each additional DLL separately
Do not classify all listed DLLs from NAME NOT FOUND events alone. For each name, record:
- Process performing the lookup.
-
Load Imagesuccess path. - Whether the planted DLL actually loads and executes.
- Process architecture—particularly System32 versus SysWOW64.
- Whether PreferSystem32 changes the successful load path.
If a Microsoft-supplied activation process still loads a planted system DLL after PreferSystem32 is correctly applied, submit the Process Monitor trace, Windows build, architecture, exact reproduction steps, and harmless proof of concept through the Microsoft Security Response Center submission portal.
References
- Triaging a DLL planting vulnerability - microsoft.com
- Evaluate exploit protection
- Enable exploit protection
- Dynamic-link library search order
- Dynamic-Link Library Security
- ClickOnce cache overview
- ClickOnce Deployment and Security - Visual Studio (Windows)
- Secure ClickOnce applications
- <file> element (ClickOnce application)