In app request for privilege escalation C#.NET - c#

I have an application that under rare circumstances needs to change its registry setting. Also during it's first execution it needs to create a new key. I'm developing this in Windows 7. I get ThrowUnauthorizedAccessException. How do I force Windows to give me a UAC prompt to temporarily elevate my permissions?
Thanks in advance.

Should all users be allowed to modify this setting? If so, the simplest solution is to modify your installation program to give Users Full Control of the registry key.
If only administrators should be able to modify this setting, then you will need to launch another copy of your program, asking Windows to elevate it:
ProcessStartInfo startInfo = new ProcessStartInfo("C:\Path\To\MyApplication.exe");
startInfo.Verb = "runas"; //trigger a UAC prompt (if UAC is enabled)
System.Diagnostics.Process.Start(startInfo);
If you were smart you would include some command line arguments, so you can tell "yourself" that it should jump straight to the part of the software that the user needs to deal with. Or your command line arguments could just say what you want done:
ProcessStartInfo startInfo = new ProcessStartInfo(
"C:\Path\To\MyApplication.exe",
"/setLoggingEnabled yes");
startInfo.Verb = "runas"; //trigger a UAC prompt (if UAC is enabled)
System.Diagnostics.Process.Start(startInfo);
Have your application check for the setLoggingEnabled switch, make the change, and then exit.
Update: A common situation is players of World of Warcraft. Since the game is allowed to update itself while running, all users must be allowed to modify the game data sitting in Program Files. The correct and valid action is to modify the ACLs on the
C:\Program Files\Blizzard\World of Warcraft
folder so that all users have full control. In fact, before Blizzard got their act together, Microsoft released an application compatibility update that gives all users full control to the WoW folder next time it run as an administrator.
Another common case is when the Blizzard Launcher is launched with administrative privelages, it updates a registry key in HKLM, recording where the game is. This happens when, for example, i move WoW from a hard drive to an SSD drive
run the launcher once as an administator so that the updaters work correctly.

Related

Why is my mapped network drive not appearing in Network Locations?

I'm using Windows 10. Here is my code to map the network drive.
System.Diagnostics.Process p = new System.Diagnostics.Process();
p.StartInfo.UseShellExecute = true;
p.StartInfo.Verb = "runas";
p.StartInfo.FileName = "net.exe";
p.StartInfo.Arguments = "use Z: " + dPath; //dPath has escaped characters
p.Start();
What I was trying to do was trying to run the command net.exe use Z: DPATH as administrator but the Z drive does not appear in File Explorer but when I run the exact same command using cmd with Admin rights, the Z drive appears correctly.
Proof of mapped drive
My Network drive is mapped as evidenced below (Encountered this error when trying to re-map it manually) just that it wasn't appearing under Network Locations in File Explorer > This PC.
This behaviour is caused by UAC (User Account Control). When logging on to Windows as an admin, there are two sessions created. One with admin rights and one without. When you map the drives programmatically, you are doing it with the session with admin rights.
However, when you use File Explorer to view the Network Locations, you are using standard rights. For mapped drives, the admin and standard rights are not shared. Hence, the admin is not able to view the mapped drive eventhough it was created with admin rights.
Solution 1
Click Start, type regedit in the Start programs and files box, and
then press ENTER.
Locate and then right-click the registry subkey
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\Windows\CurrentVersion\Policies\System.
Point to New, and then click DWORD Value.
Type EnableLinkedConnections, and then press ENTER.
Right-click EnableLinkedConnections, and then click Modify.
In the Value data box, type 1, and then click OK.
Exit Registry Editor, and then restart the computer.
Solution 2
Run File Explorer as administrator
When making a right click on the Explorer and select "Run as
administrator" it doesn't start the Windows Explorer with admin
rights. The Windows Vista/7/8/10 Explorer includes a special function to
block such requests.
To disable it, start regedit.exe and go to the following key:
HKEY_CLASSES_ROOT\AppID{CDCBCFCA-3CDC-436f-A4E2-0E02075250C2}
make a right click on Permissions and set your user as owner of the key and
give your current user writing permissions.
Next, delete or rename the value RunAs. Now the Elevated-Unelevated
Explorer Factory is disabled and you can start the Explorer with admin
rights.
Solution 3
If the above can't work, disable your UAC (User Account Control) by going into User Account Control Settings and moving the slider to Never notify
Also, if you have Professional, Enterprise, or Ultimate version of windows installed, you need to look into a program in Administrative tools called Local Security Policy and disable all the policies related to UAC in Security Settings > Local Policies > Security Options (Located in the bottom 15 policies of the list)
It helped me restarting explorer.exe with admin rights via Task Manager.

Shortcut in a System Startup is not starting up for other users but only for administrator

I have Programatically created a shortcut of my tray application in C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Startup.
But my tray application is not launching when i login for any user. It is only starting for the administrator.
Can someone please tell me, i have spend a complete day to solve this issue but unable to fix it..
var startupFolderPath = Environment.GetFolderPath(Environment.SpecialFolder.CommonStartup);
var shell = new WshShell();
var shortCutLinkFilePath = string.Format("{0}\\{1}", startupFolderPath, "MyShortcut.lnk");
var windowsApplicationShortcut = (IWshShortcut)shell.CreateShortcut(shortCutLinkFilePath);
windowsApplicationShortcut.Description = "Shortcut for My Tray application.";
windowsApplicationShortcut.WorkingDirectory = assemblyPath;
windowsApplicationShortcut.TargetPath = executablePath;
windowsApplicationShortcut.Save();
I think there are a couple of ways to deal with this:
A program won't start with elevated permissions from the Startup folder (or similar "start at logon" locations), as Harry Johnston points out. But if it has an elevation manifest you should be able to relaunch it with a shell execute, then it will prompt for elevation because it's no longer directly from Startup. The Startup shortcut could have a command line option as a quick way to knows it's from Startup, then run the path to your executable with ShellExecute() or a Process.Start with a ProcessStartInfo.UseShellExecute set true. This should get the porompt for elevation which is required for elevated code to run. Caveat: I've not tried this but I've heard reports that it works.
A service can run elevated and start when the system starts. Your startup program can be non-admin and have a message protocol to ask the service to do things. This is overkill for an app you just want to run for a short time, but not for a system monitor type of app.

C# admin rights issues

I trying to make a program which connect to a game ("quick connect").
When i start the application as an administrator and connect to the game, it have weird issues (e.g. shortkeys doesn't respond for the ingame keys and the game doesn't load some model files), but when i start without admin rights it works fine, however i need the admin rights for other purposes (file operations).
I tried to rerun the program with the runas commandline command, the app had no admin rights, but the game still doesn't work right.
// OnClick event
ProcessStartInfo proc = new ProcessStartInfo("cmd.exe", "/c runas /trustlevel:0x20000 \"myapp.exe rerun\"");
proc.WorkingDirectory = Application.StartupPath;
proc.CreateNoWindow = true;
proc.UseShellExecute = false;
Process.Start(proc);
// Program.cs
if(!admin && args[0].Equals("rerun"))
{
ProcessStartInfo proc = new ProcessStartInfo("cmd.exe", "/c game.exe ipAndPortToConnect");
proc.WorkingDirectory = Application.StartupPath;
proc.CreateNoWindow = true;
proc.UseShellExecute = false;
Process.Start(proc);
}
I tried many combinations but none of them worked.
I can't figure out what the hell causing it...
If you check the Task Manager, you'll see the game still runs as a different user, namely Administrator. This most likely means the game saves some information in the user profile, for example under AppSettings (like hotkeys in configuration files), or game modifications that are stored in AppData, which could cause the issues you mentioned.
The user who 'reruns' your program is still the elevated user, albeit with less permissions, and that user launches the game. You cannot "unimpersonate" a process properly to the point the OS thinks it runs as the logged in user, so you'll have to do something else.
You can either see if you can move the user-specific resources to a path relative to the game, not the user, or start the process by any other means but directly from yours, for example using a Scheduled Task.
But why didn't you update your existing question?

ApplicationPool user vs StartInfo.Username?

I've been testing ( for the last 4 days) the variety of options to start a Process under iis7 ( asp.net)
I did find a solution.
As long as we don't need to interact with desktop, and only need to run cmd ( or something like that) the solution is simple:
w3wp user-> should be high privileged user.
Process start info (StartInfo.Username)-> should be also high privileged user.
However, there is a catch ( according to my testings):
Both users have to be the same (if we want cmd to execute)! this is the only way it will work.
So here are my 2 questions:
Why they both must be the same? Can't w3wp HighPrivilegedUSerA run (via process.startInfo) cmd as HighPriviligedUSerB?
Both users are domain admins.( which are also admins in my local group). Does only domain admin/local admin can run processes on the local machine?
p.s. All folders permissions are everyone : full controll ( including c:\windows\*.* /s and including cmd.exe permissions) and both users, as mentioned, are admins on local machine with same cloned permissions.IIS7 handler mapping * [static file] is set to read+execute
Also, the full cmd command is:
cmd /c time /t >c:\1.txt. A success is if the file exists.( and I succeed, only when both account were the same).
Full code:
Process proc = new Process();
proc.StartInfo.FileName = "cmd";
proc.StartInfo.UserName = "Royin"; //<-- only if this user is the same as w3wp user , the operation succeed !
proc.StartInfo.Domain = ...;
proc.StartInfo.WorkingFolder = #"c:\windows\system32";
proc.StartInfo.Password = ...
proc.StartInfo.Arguments = #"/c time /t >c:\1.txt"
proc.Start();
Ok, first, I HIGHLY recommend using the excellent SysInternals ProcessMonitor to help troubleshoot any issue like this: Process Monitor.
This app will basically tell you every action a process is attempting to take, so in your situation, you'd see it try to call QueryOpen, ProcessCreate, etc.
Have you checked what the ExitCode of the process is under the failing scenario? I'd be willing to bet real money it's coming back as 0xC0000142 (-1073741502), which means something like "failed to load DLL" or something. Running anything under the system32 path, even with privileged user credentials, is going to run into oddball issues with permissions, again due to the initialization procedure for creating a process.
Basically, the Process.Start flow looks something like this:
(assumptions: UserA == process running w3wp, UserB == impersonation ctx, UserC == credentials specified in process start info)
First, UserB isn't going to have much impact, as we've discussed in other conversations; any process creation stuff is going to be based on the process token of the "launching entity", so the credentials of UserA are the ones we'll be looking at.
The runtime says "Hey, can UserA access the file name specified in StartInfo.FileName?"
Windows responds yes/no, but also "BUT, to use that, you also need to be able to read all these other DLLs"
Runtime responds "Ok, can UserA access those DLLs?"
If the answer to all the above is yes, then the runtime says "Ok, logon this user and try creating a new process with cmd line and arguments..."
You are most-likely running into issues with either #2 or #4, as the default app pool identity has no read-access rights to the System32 folder. This is why when you switch the identity of the w3wp process to a privileged account, it works.
You could try a couple things, but the easiest option is probably switching back to a low-privilege account (like default app pool identity), but grant read-only access to the system32 folder to that account.
I would ABSOLUTELY not run w3wp as a privileged user, though - that is just asking for massive headaches should anything nasty happen, like somebody hacking you.
Oh, last thoughts:
DON'T set UseShellExecute to true if you can help it, it does weird stuff.
DON'T set LoadUserProfile to true if you can help it, it also does weird stuff, and is really slow as well.
DO set CreateNoWindow to true if you can, otherwise you'll see lotsa windows opening/closing on the server
DO use RedirectStandardOutput / RedirectStandardError instead of piping the output, it's way more controllable and gives better feedback when things go wrong.
DO always check the ExitCode of the process if it doesn't look like it worked

Write Access to Program Files folder

my application include a self-updater executable that is used to update the application.
One of the first steps the updater is performing is to check that it does have write permission to the application folder
IPermission perm = new FileIOPermission(FileIOPermissionAccess.AllAccess, _localApplicationCodebase);
if (!SecurityManager.IsGranted(perm))
{
OnProgressChanged("Security Permission Not Granted \n The updater does not have read/write access to the application's files (" +
_localApplicationCodebase + ")",MessageTypes.Error);
return false;
}
OnProgressChanged("Updater have read/write access to local application files at " + _localApplicationCodebase);
return true;
When executing under Win7/Vista, this code pass (meaning that according to CAS, the code does have write access), however when I try to write files, I got an Access Denied (and I confirmed that the files are NOT in use)
I understand that Vista/Win7 UAC is preventing users from writing files in the program files folders. However, what I don't understand is why the permission is granted if in reality it is not
Regards,
Eric Girard
PS : If I run the same code using 'Run As Administrator', it works fine
The important thing to know about UAC is that by default, no code runs with Administrator privileges and thus cannot write to the Program Files directory. Even if you are logged in as an administrator, the apps are launched with standard user privliges.
There are two ways around this. You can have the user start the app with the Run As Administrator menu item. But this relies on the user to remember something. The better was is to embed a manifest into your executable that requests administrator privileges. In the manifest, set requestedExecutionLevel to requireAdministrator. This will cause UAC to prompt the user for admin credentials as soon as the app starts.
As Daniel said, the best solution is to put the updating functionality in a separate application. Your primary app will have an manifest that sets the requestedExecutionLevel to "asInvoker" and your updater app with request "requireAdministrator". Your primary app can run with standard privileges. But when the update needs to happen, use Process.Start to launch the updater application that requires the user to enter the admin credentials.
The best way to write an auto updater is to have a secondary application. The first program calls the second with elevated privileges, prompting UAC. Then the second application can install the patches.
I'm not sure if this is what you're trying to do, but I've found this post helpful. The included code let's you detect if you're app is running on Vista, if UAC is enabled and if user is elevated.
http://www.itwriting.com/blog/198-c-code-to-detect-uac-elevation-on-vista.html
then restart your app with runas to let user elevate permissions
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.Verb = "runas";
processInfo.FileName = Application.ExecutablePath;
Process.Start(processInfo);

Categories