0

I have written a small program in c# that helps with switching between licenses for my company. It's a tray icon with a menu with the different choices.

It changes an environment variable and needs to have elevated rights in its manifest.

This means that the UAC warning shows up every time the program starts, which is not ideal because it would be really nice to have the program on autostart when Windows starts, without the warning showing up all the time.

Are there a good way to do this?

Is it possible to:

  • Run the program without elevated privileges and only get the UAC warning when I call the function to change the variables.
  • Change the environment variables without admin rights.
  • Add the program to a "white list" programmatically (although more realistic, add it manually)

I know the UAC is there to protect from malicious software, but it would be really nice to solve this in a way that enables me to start the program at Windows start.

I haven't been able to fine any silver bullet on this problem.

Any advise?

mottosson
  • 3,283
  • 4
  • 35
  • 73
  • 7
    Wouldnt every virus, trojan and malware exploit this? – Ňɏssa Pøngjǣrdenlarp Sep 14 '16 at 21:03
  • 2
    The normal way around this is you have a windows service that runs with system privileges that your program talks to that gets set up during the installation phase. – Scott Chamberlain Sep 14 '16 at 21:04
  • Yes I know the UAC is there for that reason. But there must be software out there that has admin rights without the warning, right?? – mottosson Sep 14 '16 at 21:05
  • Use a security certificate, and optionally put the program in Program Files folder. – InfZero Sep 14 '16 at 21:07
  • Try to find a similar solution which implements StrokesPlus to enable UAC: http://www.strokesplus.com/forum/topic/814/version-276 – InfZero Sep 14 '16 at 21:08
  • @InfZero [Actually](https://technet.microsoft.com/en-us/magazine/2009.07.uac.aspx#id0560031), it has to be a security certificate signed by the "Windows publisher" and it must be in a "Secure directory" like `%SystemRoot%\System32`. – Scott Chamberlain Sep 14 '16 at 21:09
  • @InfZero isn't it really complicated to implement, and possibly expensive to buy a certificate? – mottosson Sep 14 '16 at 21:14
  • @mottosson No, it is impossible to implement. The only things signed with the "Windows publisher" certificate are pieces of software that ships with windows. – Scott Chamberlain Sep 14 '16 at 21:19
  • I thought of something. Is it possible to start the application without privileges and only get the UAC when I run the function the actually needs it. That way I could autostart it without the warning. – mottosson Sep 14 '16 at 22:02
  • 3
    A program starts elevated or not, it can not be "upgraded" while running. However what you can do is launch a 2nd copy of the program as administrator with some command line arguments that tell it to do the work then exit. – Scott Chamberlain Sep 15 '16 at 13:04
  • Yep, this is probably the way to go. I have to think about it a bit. Thanks! – mottosson Sep 15 '16 at 13:07
  • The problem is that any application is a potential backdoor to a system. If you have just one "totally safe admin application" that can avoid UAC, all you need to do is add your own `user32.dll` (or such) to that application's directory, and yay! You have full access to the computer. You need to be able to verify the application and all its dependencies, and ensure that none of those have been changed by an attacker. That's why you want to install applications in Program Files, by the way, and why installers should always be administrator-level applications. – Luaan Sep 15 '16 at 13:16

3 Answers3

0

The normal way around this is you have a windows service that runs with system privileges that will set the environment variables for you.

You will need to have your installer install the service and set it to auto start. Then your tray application will need to communicate with the service with some kind of Inter-Process Communication (like WCF), the tray program can then send the requests to change the variable and the service can execute those changes.


Another way to handle this is start your program un-elevated then when you need to do something that requires UAC privileges you launch a new copy of your program as an administrator and pass in command line arguments that tell it to do the work you need done then exit. You also could have your program check to see if it is an admin, and if it already is elevated it could skip the step of starting the new copy.

Community
  • 1
  • 1
Scott Chamberlain
  • 124,994
  • 33
  • 282
  • 431
0

What you need to do is move the license information to a location that all users can write to:

  • user's own environment variable
  • %CSIDL_COMMON_APPDATA% (e.g. C:\ProgramData, which all users can write to)
  • HKEY_CURRENT_USER

The ideal solution involves writing to a common machine-wide location:

  • %CSIDL_COMMON_APPDATA% (e.g. C:\ProgramData)
  • HKEY_LOCAL_MACHINE/Software/Contoso/License
  • C:\Program Files\Contoso\License\license.txt

Legacy software can't be changed

But assuming there are many existing unchangeable applications that cannot be altered to look anywhere else but an environment variable for license information you can (after you smack that guy who designed that):

  • write the license information to the user's own environment variable

Your switching tool will call:

SetEnvironmentVariable("ContosoLicenseInfo", "V2h5IGFyZSB5b3UgZGVjb2RpbmcgdGhpbmdzIHRoYXQgZG9uJ3QgYmVsb25nIHRvIHlvdT8=");

What would you have done under Windows XP

All this hand-wringing about UAC. You have to ask yourself:

What would I have done under Windows XP?

Without UAC, and the user running as a standard user, what will your license switching tool have done?

  • would have it crashed horribly on startup?
  • would it have crashed as soon as the user tried to use it?
  • would it have failed in a polite way?
  • would it show a message on startup saying: "Sorry, no."?

What would you have done under Windows 7?

Even better, you have to ask what you would have done for a user running under Windows 7? A standard user logs in, and you have a program in their startup group that claims to require administrative privileges.

The user needs to go get an administrator during login to run your tool? That's not going to fly.

  • If you're dead set against using a per-user location.
  • If you're dead set against using a common location that all users can write to

Then change your tool to run without needing user privileges.

Only when the user goes to do something do you need admin privileges.

Check if the user is an admin:

Boolean IsUserAnAdmin()
{
    PSID administratorsGroup;
    administratorsGroup = AllocateAndInitializeSid(SECURITY_NT_AUTHORITY, 2, SECURITY_BUILTIN_DOMAIN_RID, DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0);

    Boolean result = CheckTokenMembership(0, administratorsGroup);
    FreeSid(administratorsGroup);
}

If they are an admin, you can perform the action as in.

If the user is not an admin, then you put the UAC shield on the Yellow-Blue Windows Security Icon Apply button.

You then re-launch your tool as an admin:

ShellExecute("runas", "C:\Program Files\Contoso\LicenseSwitcher.exe", ...); //the "runas" verb triggers elevation

But what would you do under Windows 7

None of the UAC stuff works if UAC is disabled. In that case: you are a standard user, and that's it.

In that case, it really is best to convert to:

  • machine wide location for the default license
  • per-user location if you want to choose your own
Ian Boyd
  • 246,734
  • 253
  • 869
  • 1,219
-2

UAC is there to protect the Windows User by alerting them (and requiring an explicit action) that a particular application is requesting elevated permissions. If it was possible to bypass it from with the application itself them it would leave it a little pointless :)

I would assume that you are looking to change environment variables globally because I believe that you can change them for the current process without being elevated.

Scott Perham
  • 2,410
  • 1
  • 10
  • 20
  • Yes I need to set the environment "System variables" because the licens management software we're using is reading from there. – mottosson Sep 14 '16 at 21:13
  • @mottosson System variables seems like an odd place for licensing information. Wouldn't the registry or some kind of config file be more appropriate? Then you wouldn't even have to worry about UAC. – itsme86 Sep 14 '16 at 22:30
  • The problem is that we are using a third party license manager, that's reading information from env-vars. We can't do anything about this. – mottosson Sep 15 '16 at 06:35