7
votes

I've seen several questions that are the opposite of this; "How do I disable virtualization?" That is not my question. I want to force an application to run with virtualization enabled.

I have an application that ran just fine under Windows XP, but, because it writes its configuration to its working directory (a subfolder of "C:\Program Files (x86)"), it does not work completely under Windows 7. If I use task manager to turn on UAC Virtualization, it saves its config just fine, but of course it then can't load that config.

I do not want to set it to run as administrator, as it does not need those privileges. I want to set it to run with UAC Virtualization enabled.

I found a suggestion that I put some magic in the registry at HKLM\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags. For completeness I also put it in Wow6432Node, but neither had any effect.

5
why can't you just change the app to keep the config file in AppData?Kate Gregory
@KateGregory 's suggestion, or modify the ACL on the folder so that everyone has full control. Problem is that no every kind of write will always be virtualized. It's a stop-gap feature, there to stop buggy programs from crashing. It really isn't something you should be relying on. In fact, virtualization can be disabled through group policy - nevermind if you want it or not.Ian Boyd
@KateGregory: I don't have the source. If I had the source, I'd be using that, rather than bad workarounds that rely on stop-gap features.DaleStan
@IanBoyd Modify the ACL to defeat the security I get by running with UAC on? I don't think so. Group Policy does not prohibit virtualization on my machine ("User Account Control: Virtualize file and registry ..." is Enabled), so that doesn't apply to me, though it may apply to others. (I eventually gave up and modified the ACL on the config file only. This does solve the original problem, and without opening any security holes, but it doesn't answer the original question.)DaleStan

5 Answers

5
votes

File system is virtualized in certain scenarios, so is your question how to still turn it on when your application does not qualify? It is unlikely possible, MSDN:

Virtualization is not in option in the following scenarios:

  • Virtualization does not apply to applications that are elevated and run with a full administrative access token.

  • Virtualization supports only 32-bit applications. Non-elevated 64-bit applications simply receive an access denied message when they attempt to acquire a handle (a unique identifier) to a Windows object. Native Windows 64-bit applications are required to be compatible with UAC and to write data into the correct locations.

  • Virtualization is disabled for an application if the application includes an application manifest with a requested execution level attribute.

4
votes

this may come way too late now, but I am the author of the suggestion you found to activate UAC virtualization, and there was a mistake in my post. The registry keys to modify are the following:

HKLM\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\ 
HKCU\Software\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers\

(notice the "Layers" appended)

so a full example would be:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"C:\\Program Files (x86)\\Some Company\\someprogram.exe"="RUNASINVOKER"

note that multiple parameters must be separated with space character.

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows NT\CurrentVersion\AppCompatFlags\Layers]
"C:\\Program Files (x86)\\Some Company\\someprogram.exe"="WINXPSP3 RUNASINVOKER"

--

I'm sincerely sorry that you lost a fair amount of time because of my mistake.

And by the way, let me express my disagreement with Ian Boyd's post. There are places where write privileges should not be granted to everyone, such as this one, since it breaks the base security rule of "System-wide writes should be authorised to privileged principals only". Program Files is a system-wide place, not a per-user one.

All rules have exceptions of course, but in the present case, one could imagine a maliciously crafted configuration file making the program exec an arbitrary command as the user running it. On a lighter side, one could imagine a "mistake delete" by another user, which would make the app fail. Back on the heavier side, application executables in Program Files are often run by the admin, sooner or later. Even if you don't want to, uninstalling programs very often run uninstall executables that are in Program Files. Maybe the uninstall procedure will use that config file which could have consequences if it's maliciously crafted.

Of course you may say, this sounds paranoid somehow, agreed. I did modify some NTFS ACLs in Program Files at the times of Win XP and was able to sleep after that, but why take the slightest risk when the tools are available ?

2
votes

I found one not very well cited condition where UAC Virtualization does NOT work: when the file in Program Files is maked as read-only.

That is, suppose the file C:\Program Files\<whatever>\config.ini is marked as read-only. When the application try to change it, UAC Virtualization will return an access denied error instead of reparsing it to %LOCALAPPDATA%\VirtualStore\<whatever>\config.ini.

Although I did not found this documented, this behavior is probably done by design, since it makes some sense.

The solution is simple: assure that all files that are supposed to be modified by the application are not read-only (or just unflag all files, since the user will not be able to change them anyway).

1
votes

You have an application, and you want users to be able to modify registry keys or files in locations that by default only Administrators can modify.

If you were running Windows 2000, or Windows XP, or Windows Vista, or Windows 7, or Windows 8, the solution is the same:

  • grant appropriate permissions to those locations

For example, if your program needs to modify files in:

C:\Program Files\Blizzard\World of Warcraft

Then the correct action is to change permissions on the World of Warcraft folder. This is, in fact, a shim that Microsoft applied to World of Warcraft. (On next run it granted Everyone Full Control to the folder - how else can WoW update itself no matter what user is logged in.)

If you want users to be able to modify files in a location: you have to grant them permission. If you were a standard user trying to run WoW on Windows XP you will get the same problem - and need to apply the same solution.


Your application is writing its configuration to:

C:\Program Files (x86)\Hyperion Pro\preferences.ini

then you, in fact do want to grant Users Full Control to that file:

enter image description here

So your:

  • application is not set to run as an Administrator
  • users cannot modify the executable
  • users can modify Configuration.ini

Granting permissions is not a bad thing; it's how you administer your server.


There are two solutions:

  • Install to C:\ProgramData\Contoso\Preferences.ini and ACL it at install time
  • Install to C:\Program Files\Contoso\Preferences.ini and ACL it at install time

And if you look at the guidance of the AppCompat guy at Microsoft:

Where Should I Write Program Data Instead of Program Files?

A common application code update is this: “my application used to write files to program files. It felt like as good a place to put it as any other. It had my application’s name on it already, and because my users were admins, it worked fine. But now I see that this may not be as great a place to stick things as I once thought, because with UAC even Administrators run with standard user-like privileges most of the time. So, where should I put my files instead?”

FOLDERID_ProgramData

The user would never want to browse here in Explorer, and settings changed here should affect every user on the machine. The default location is %systemdrive%ProgramData, which is a hidden folder, on an installation of Windows Vista. You’ll want to create your directory and set the ACLs you need at install time.

So you have two solutions:

  • create your file at install time, and ACL it so that all users can modify it at runtime
  • create your file at install time, and ACL it so that all users can modify it at runtime

The only difference is semantic. The Program Files folder is mean for program files. You don't want to store data here.

  • And it's not because Diego Queiroz has any insight about security.
  • It's because it's where just the programs go.

Sometimes machines are imaged with the same Program Files over and over. You don't want per-machine data in your image. That data belongs in ProgramData.

And it's not a security issue.

Some people have to learn where the security boundary is.

0
votes

there are quite some good points in those other answers.
actually i have upvoted all of those.
so let's all combine them together and add some more aspect ...

the OP mentions some "legacy application from the old days".
so we can assume it is x86 (32bit) and also does not include any manifest (and in particular does not specify any "requestedExecutionLevel").

--

Roman R. has good points in his answer regarding x64 and manifest file:
https://stackoverflow.com/a/8853363/1468842
but all those conditions don't seem to apply in this case.

NovHak outlines some AppCompatFlags with RUNASIVOKER in his answer:
https://stackoverflow.com/a/25903006/1468842

Diego Queiroz adds intersting aspect regarding the read-only flag in his answer:
https://stackoverflow.com/a/42934048/1468842

Ian Boyd states that probably you don't even should go for that "virtualization", but instead set according ACL on those files of interest (such as "config.ini"):
https://stackoverflow.com/a/12940213/1468842

and here comes the addtional / new aspect:
one can set a policy to disable all virtualization - system-wide:

[HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System]
"EnableVirtualization"=dword:00000000

actually i'm enforcing this policy on each and every system that i own.
because otherwise it will lead to confusing behaviour on multi-user environments.
where UserA applies some changes and everything goes fine.
but then UnserB does not get the changes done by UserA.

in case some old crappy software fails then it should "fail"!
and not claim that everything went "fine".
IMHO this "Virtualization" thing was the worst design decision by microsoft, ever.

so maybe the system has this policy enabled and that's why virtualization doesn't work for you?

--

so probably the ultimate checklist would be:

  • is the application x86 or x64?
  • does the exe have a manifest (including the requestedExecutionLevel)?
  • have you checked the read-only attribute (e.g. of those INI files)?
  • is there a policy to force the EnableVirtualization to 0?
  • have you tried the AppCompatFlags with RUNASIVOKER?
  • or simply go for ACL instead of virtualization

--

in the end we are discussing how to get on old legacy application to run.
by using whatever workarounds and hacks we can think of.
this should probably better discussed on either superuser or serverfault.

at stackoverflow (targeted for programmers) we all know: it's about time to get all of our own programs compatible with UAC concept and how to implement things the "right" way - the "microsoft" way :)