Bypass restrictions of enabled Folder Access Control of Windows Defender - c#

I've got an application written with C# which is installed via InnoSetup.
With enabled Controlled Folder Access of Windows 10's Defender, the setup fails to create a desktop icon (showing the message PersistFile::Save failed, code 0x80070002) -- despite running with administrative privileges.
Furthermore the installed application (which is NOT run with administrative privileges) fails to write to folders of the user, e.g. Documents.
This happens even for new files or folders, which do not overwrite anything existing. For ransomware protection I'd expect that only modifying existing files is considered dangerous.
The first question that comes to my mind is: Why is my application considered to be harmful and is thus being blocked?
I've done extensive research to get an answer, but could not find anything that helps:
Web resources from Mircosoft describing which applications are considered harmful and why cannot be found -- only guesswork there.
Signing my application with an Extended Validation Certificate (which helps suppressing SmartScreen warnings) does not change Windows Defender's behavior.
I let the Windows App Certification Kit analyze the installer -- which reported several warnings and one critical error. I fixed all issues the Kit complained about (except the warning regarding /SAFESEH which is not possible with InnoSetup), but this did not change Windows Defender's behavior regarding access blocking.
So, my refined question is: How can I bypass the access blocking of Windows Defender for my setup and my application in a valid way?
To give insights to the problem and to provide a basis for experiments I've set up a small sample application in C# which
creates new (and afterwards removes) directories in the public desktop path, user's desktop path, pulic documents path and user's documents path
is bundled by an InnoSetup script to a signed installer
Using Visual Studio to build the solution and InnoSetup to package the build, it should be easy to reproduce the behavior with enabled Controlled Folder Access. (Make sure to have a look at README.md for a description of the build steps!)
Please check out the sample project.

Related

WiX v3 Setup Project, Unable to uninstall via Apps & Features

I'm having a hard time trying to figure out what is causing this odd issue.
So I've created a very basic .msi by following the WiX v3 Setup Project documentation, pretty much just the provided template, but no matter what i try, whenever i go to uninstall it via the Windows 10 Apps & Features interface, i keep getting this:
However, when i uninstall via Control Panel\Programs\Programs and Features or by right-clicking and hitting Uninstall in the .msi's Context Menu, it uninstalls fine.
What am i missing here, should i be implementing something within the installer project to support the Apps & Features uninstall?
Thanks in advance.
AVG Anti Virus: In this case it was AVG anti virus. Uninstalling this product made the uninstall run correctly when
invoked from the new settings GUI in Windows 10.
Blocking: Errors like these often mean something is blocking the uninstall. Please disable or uninstall any anti-virus and / or security software and try again.
General Check List: Please check this answer for a "deployment check list" or "mnemonic" to debug similar problems: Deployment Mnemonic (mid-page). Also see comments above. Sweep for malware with Windows Defender Offline.
Microsoft Tips: Windows cannot access the specified device, path, or file...
Make Log File: To debug, always make an MSI log file:
FireGiant: MSI log "how-to"
Installsite: MSI log "how-to"
Exact Error Message: "Error: Windows cannot access the specified device, path, or file. You may not have the appropriate permission to access the item"

How does a click-once application determine its application identity?

I have a click-once application, which is correctly signed, correctly configured and installs itself without any problem.
It is set to run offline, but install from a specific URL, and if I download and run the setup.exe, it installs updates.
So, it's basically all working... except I cannot print out the version number, or trigger an update from in code. If I try, I get the dreaded: 'Application identity is not set.'
2017-01-10 13:43:14.8367 ERROR System.Deployment.Application.InvalidDeploymentException: Application identity is not set.
at System.Deployment.Application.ApplicationDeployment.get_CurrentDeployment()
at LibDataAgent.Internal.Services.UpdateService.Deployment() System.Deployment.Application.InvalidDeploymentException: Application identity is not set.
at System.Deployment.Application.ApplicationDeployment.get_CurrentDeployment()
at LibDataAgent.Internal.Services.UpdateService.Deployment()
I am not running in debug mode, or using a debug build.
So here's my actual question:
How, does the click-once code in System.Deployment.Application, at runtime, determine what the application identity is?
So, there are whole lot other questions around this, but please don't close this as a duplicate, as far as I can tell it is not one.
Here's a list of things I do not want answers for:
How to sign a click-one application.
How to set the application identity as you build.
How to find where the click-once application is installed.
How to make a click-once application work while debugging.
How to check for updates using ApplicationDeployment.
Just very plainly, exactly what does a click-once application do, at runtime that lets it determine the application identity.
Help!
Notes
My (thus far fruitless) attempts to solve this have yielded these notes:
I'm certain this has something to do with how the application is launched, because executing applications from the command line has never worked with click-once; but executing the same application from the start menu will correctly return IsNetworkDeployed as true.
However, I've not been able to determine what the technical difference is, or why one detects the install correctly and one doesn't. (or indeed, why this specific application doesn't work from the start menu, when others with no obvious difference do).
Things I've tried that make no difference include:
the working directory for the application.
launching the application .exe directly or via a shell
launching the application from a new shortcut
There is some kind magic to the 'MyApplication.appref-ms' that goes into the start menu; the appref-ms is just a url to the install path:
http://s3-ap-southeast-1.amazonaws.com/blahblah/Dev/MyApplication.application#MyApplication.application, Culture=neutral, PublicKeyToken=fdasdfsafads, processorArchitecture=x86
...which somehow launches a 'click once aware' instance of the application. But how?
I'll still happily accept an answer that explains how the guts of launching the application actually sets the application context up with an identity, but for now here's my best stab at what's going on for anyone else who finds this question later:
ClickOnce applications are launched by hitting the install url, or by using the .appref-ms file on the start menu, which contains the url.
The application/x-ms-application MIME type handler is invoked for the downloaded file, which launches the 'ClickOnce aware' instance of the application.
At runtime, the ApplicationContext.Identity is used to determine what the ClickOnce details are, and setup the CurrentDeployment object.
As far as anyone knows, directly launching the deployed executable for a ClickOnce application (in C:\Users\Administrator\AppData\Local\Apps\2.0\b107ee1... or whatever the install folder is) will always return IsNetworkDeployed as false, and will not be able to self update.
Practically speaking, this means:
You're looking for the install folder and path to your .exe? Don't bother. Even when you know where it is, it won't have the correct ApplicationContext when you run it.
To spawn a new 'ClickOnce aware' instance of your application launch internet explorer at its install url. You cannot pass command line arguments to it.
eg.
var url = "http://s3-ap-southeast-1.amazonaws.com/blahblah/Dev/MyApplication.application#MyApplication.application, Culture=neutral, PublicKeyToken=fdasdfsafads, processorArchitecture=x86";
var psi = new ProcessStartInfo
{
FileName = #"iexplore",
Arguments = $"\"{url}\"",
};
Process.Start(psi);
(if you want to find the URL, hunt through the start menu for the appref-ms file for the application; the url is contained in it)
...and how does the executable get launched with an identity?
No idea; but this is as far as anyone seems to ever have got with understanding it:
(tldr; magic. Probably something to do with how CreateProcess is invoked to spawn the appliciation using the ApplicationContext api, in some combination of DFsvc.exe. DFshim.dll and DFdll.dll)
(The rest of this information is taken from this old blog post by Ian Picknel: http://ianpicknell.blogspot.com.au/2010/03/launching-clickonce-application.html)
Once the deployment manifest has been
stored in the Temporary Internet Files folder, Internet Explorer then
attempts to establish how it should handle the file with the (assumed
and actual) .application extension. It checks the user-specific file
types at HKCU\Software\Classes and, if it fails to find an
.application sub-key there, checks for machine-specific file types at
HKCR. Via this means it establishes that the .application extension
denotes an Application.Manifest file. It then uses this information to
check the user-specific HKCU\Software\Classes\Application.Manifest and
machine-specific HKCR\Application.Manifest keys to establish the CLSID
of a library which handles Application.Manifest files and yields the
result {98af66e4-aa41-4226-b80f-0b1a8f34eeb4}. Finally, it looks up
this CLSID in the user-specific
HKCU\Software\Classes\CLSID{98af66e4-aa41-4226-b80f-0b1a8f34eeb4} and
machine-specific HKCR\CLSID{98af66e4-aa41-4226-b80f-0b1a8f34eeb4}
paths to establish that .application files are handled by
C:\WINDOWS\system32\DFshim.dll.
This is where things start to get a little complicated. I said earlier
that no 'magic' was happening behind the scenes. Well, whilst that was
true for the process of retrieving the deployment manifest it most
certainly is not true of the process of actually launching the
ClickOnce application once the deployment manifest has been retrieved
and the handler, DFshim.dll, has been identified.
DFshim.dll is described in the registry as the 'Manifest mime handler'
although its file properties describe it as the 'Application
Deployment Support Library'. It implements the Internet Explorer MIME
handler COM interface. It is a native 32-bit DLL, written in Microsoft
Visual C++ 2005, and was installed into C:\Windows\system32 when the
.NET Framework 2.0 was installed.
DFshim.dll has a hard-coded reference to DFdll.dll, which it locates
by checking the values of
HKLM\SOFTWARE\Microsoft.NETFramework\InstallRoot (typically
C:\Windows\Microsoft.NET\Framework) and the keys beneath
HKLM\SOFTWARE\Microsoft.NETFramework\Policy\AppPatch (typically
v2.0.50727, even if a later version of the Framework is installed).
DFdll.dll too is a native 32-bit DLL written in Microsoft Visual C++
2005.
DFdll.dll uses COM services exposed by DFsvc.exe, which is also
located in the .NET Framework folder. DFsvc.exe is a standard .NET
MSIL assembly. DFsvc contains a single Main method (within the
System.Deployment.Application namespace) which simply calls the
internal System.Deployment.Application.DFServiceEntryPoint.Initialize
method within System.Deployment.dll. The Initialize method registers
System.Deployment.Application.DeploymentServiceCom with COM via
System.Runtime.InteropServices.RegistrationServices (i.e. it performs
the equivalent of CoRegisterClassObject in COM) using the CLSID
{33246f92-d56f-4e34-837a-9a49bfc91df3}. This is the means by which its
services are made available to DFdll.dll.
The COM service exposed by
System.Deployment.Application.DeploymentServiceCom delegates the
majority of its methods to other non-ComVisible classes within the
System.Deployment.Application namespace. For example, the public
ActivateDeployment method calls ActivateDeployment on a new
System.Deployment.Application.ApplicationActivator instance, the
public CheckForDeploymentUpdate method calls CheckForDeploymentUpdate
on System.Deployment.Application.SubscriptionStore, etc.
It is clear that the vast majority of the work surrounding the actual
installation and launch of the ClickOnce application is undertaken by
classes within the System.Deployment namespace, hosted within
DFsvc.exe. DFshim.dll and DFdll.dll appear to primarily be responsible
for arbitrating between the COM-based world of Internet Explorer and
the .NET-based world of ClickOnce.

How to remove write permission of file using msi installer?

Iam using visual studio setup project (msi installer) for my winforms application. How to remove write permission to c drive programefiles? How to implement file permission step by step in msi installer?
I tried cacls to remove file permission. But it is not works.
The Program Files folder can be written to only with administrator privilege. That means you are asking how to prevent code that is running elevated (with admin privilege) from writing to files in the Program Files folder. It's not clear to me what access restrictions you need that to prevent elevated code from doing what elevated code is supposed to do because that's a security related issue, not an installer question.
The short answer to the design issue is that you should try to run your app with limited user privilege instead of administrator privilege, because limited users cannot write to files in the Program Files folder. However you haven't described the underlying problem you're trying to solve, you've just asked how to implement your proposed solution.
If cacls didn't work, it's impossible to say if it will never work (because you are doing a Just me install, as an example) or if you had an implementation error (because you wrote some kind of custom action to do it and your code is incorrect). The general answer to all these types of question is "write a custom action", but without details of exactly what you tried it's impossible to know why it didn't work, but that's the answer, and if a custom action doesn't work then it's a design or coding problem that requires showing the code and saying if it's an Everyone or Just me install.

CS0016: Could not write to output file - 'The directory name is invalid. ' [duplicate]

In Brief
When I attempt to browse my website, I get the following error message:
CS0016: Could not write to output file 'c:\Windows\Microsoft.NET\Framework64\v2.0.50727\Temporary ASP.NET Files\www\xxx\yyy\zzz\a.b.dll' - 'The directory name is invalid'
In Detail
I have two web-sites on my Development PC (fictitious names):
Web2 - this is written in ASP.NET using .NET 3.5 and runs in an AppPool that addresses the v2.0 .NET framework and runs in an Integrated mode. This is developed using Visual Studio 2010
Web4 - this is written in ASP.NET using .NET 4.5 and runs in an AppPool that addresses the v4.0 .NET framework and runs in an Integrated mode. This is developed using Visual Studio 2012.
Recently, I've been working in VS2012 on Web4 almost constantly and it works fine, however the other day I tried to run Web2 and got the exception displayed above.
Bizarrely, part of the path (which I replaced above with letters "zzz") appear to point to a German language path, since it's "\de-DE\" - I'm not operating in German, so I've no idea where it got this idea from.
One thing that is almost certainly un-related, but for some unknown reason I feel it's important to mention: I was using the Performance Analysis tool in Visual Studio 2012 the day before this problem first appeared and I don't know if this might have made some changes to my computer...??
Attempted fixes
There are quite a few threads regarding this on the internet; some threads end in success where file access permissions have been altered whilst others finish on a somewhat desperate sounding note... I have gone through the process of comparing the NTFS permissions on all relevant sounding directories on my PC with that of a colleagues on whose machine this is still working. Unfortunately, no joy to be had there.
I have also un-installed asp.net 2.0 and re-installed it using:
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis.exe -u
C:\Windows\Microsoft.NET\Framework64\v2.0.50727\aspnet_regiis.exe -ir
and again, no joy to be had there either.
My Web4 continues to run unaffected.
Also FYI: using IIS 7.5 on Win7 x64.
I'm now turning to the this wider audience in the hope of turning my current state of despair into one of success.
Thanks everyone
Griff
In IIS Manager, in the advanced settings of the Application Pool, make sure "Process Model > Load User Profile" is set to "True".
I had this exact same problem. I tried changing permissions, disabling anti-virus, creating a new app pool, and reinstalling .NET. I even created a new site with just a "Default.aspx" page and tried to view that site. Even that site had the compilation error. Finally, I noticed that my app pools (clean test site and main site) had the non-default value "False" for the Load User Profile setting. I set that back to true and the issue went away.
The answer was found using ProcMon:
http://technet.microsoft.com/en-us/sysinternals/bb896645
The temporary asp.net files are first created in the user's temp folder and then moved into this folder. For some as yet unknown reason, the compilation for my Web2 site (.NET 2 AppPool) now uses the same folders as my Web4 (.NET 4 AppPool) site.
I used ProcMon to identify all results for "access denied" and gave the IIS_IUSRS group write permissions (and in one case - C:\Users\ASP.NET V4.0 Integrated - modify permissions).
I have no idea why the compilation is using the "wrong" folders and I suspect I may have over-elevated the permissions in some cases, but for now it's working.
In case the above answers didn't fix it for you, check your environment variables (right-click on Computer -> Properties -> Advanced System Settings -> Advanced tab -> Environment Variables
Make sure the temp variables are pointing to a folder with all the necessary permissions. (full access for Network Service, IIS_IUSRS)
Note: don't check just the two variables at the top, look inside the scroll menu under System Variables. You might find the variables configured there too.
It may not be the cause, but this error started occurring for me after trying to run VS 2010 Performance Wizard with the Instrumentation method.
A quick fix in my DEV environment: changed the Identity of the Application Pool of the app to LocalSystem.

How does the InstallAllUsers option work?

I have a C# application, and a Visual Studio (2010) Setup Project with it. In my Setup Project, I am using InstallAllUsers = True. Additionally, my application needs to launch at Startup, so a shortcut is being added to the User's Startup Folder.
So I install my application as user Bob (from a share), and then I log off and log on as user Alice. Alice gets a dialogue that says:
The feature you are trying to use is on a network resource that is unavailable.
It provides the network path from which the MSI was installed. So, basically, it's looking for the MSI on a share that Alice doesn't have access to. This is repeatedly reproducible if Alice tries to manually launch the Startup link. However, Alice can directly launch the exe from the installation location, which works fine.
I don't fully understand why it is looking for an MSI, but I guess it makes sense that an application can not be completely installed by one user for another user, so the MSI is needed to complete the installation.
But if that is the case, then I don't understand why the MSI only seems to be required when launching from the Startup link, and not from the exe directly.
My question has several parts:
Is what I am experiencing expected behaviour for the InstallAllUsers option?
If so, how can I ensure that my application is fully installed for all users?
Is it necessary to copy the msi locally, and ensure that it does not get deleted before each user has had a chance to log on?
This is happening because the shortcuts are "advertised shortcuts" hence the greyed out target box.
More info here...
http://www.advancedinstaller.com/user-guide/advertised-shortcuts.html
When an advertised shortcut is launched it validates the checks
associated with the key resources. If any is missing it will fix it by
running the installation package and installing again all information
from the .msi file.
This is why its trying to run the msi.
You can turn off advertised shortcuts by reading this article...
DISABLEADVTSHORTCUTS=1 disables all shortcuts
If its an all users install, then the shortcut will probably want to reside in the all users start menu. Win 7: C:\ProgramData\Microsoft\Windows\Start Menu.
Eric, I would recommend taking a look at the shortcut file contents. You can do this by using Powershell, and there is a SO link to help you on your way:
Editing shortcut (.lnk) properties with Powershell

Categories