Runas verb not elevating on specific Windows 10 machines - c#

I have a really odd issue, where some code that we have been running for years has stopped working on certain machines. There is no obvious pattern to the machines (in terms of Win10 build number or patch level).
The code is designed to run an application as the local administrator, and is as follows:
string strPwd = "MySecretPassword";
SecureString securePassword = new SecureString();
foreach (char ch in strPwd)
{
securePassword.AppendChar(ch);
}
ProcessStartInfo processInfo = new ProcessStartInfo();
processInfo.UserName = "Administrator";
processInfo.Password = securePassword;
processInfo.Verb = "runas";
processInfo.FileName = "cmd.exe";
processInfo.WorkingDirectory = #"c:\windows\system32";
processInfo.UseShellExecute = false;
Process.Start(processInfo);
If I run this on a "working" machine, I see the following (note, the echo test > c:\test.txt is how I am testing whether it can perform a restricted task):
Note the "Administrator" on the CMD window. Also, note that creating a file at the root of c: is allowed.
In comparison, if I run the same on another machine I get the following:
Note that in this case (running exactly the same code) the window is not running elevated. Oddly, if I look at the process in Task Manager, the owner is Administrator.
On both machines:
I am using the default Administrator account
The password is correct
The account is in the Administrators group
The account is not disabled
Furthermore, on the "bad" machine, if I right-click and choose RunAs and enter the Administrator credentials - it works perfectly. (Same result as in the first picture above.)
As an additional test I've tried using the DOS runas command and this doesn't work on the "bad" machines either. The result is slightly different though:
Note in this case the "Running as Administrator" in the title bar. (The same test on a "good" machine gives the same result as in the first picture above, i.e.: Administrator: C:\windows\system32\cmd.exe)

Related

Starting a process

As part of SharePoint automation testing, I am trying to open Internet Explorer as another user by using the System.Diagnostics.Process . Here is the following C# code
System.Diagnostics.Process p = new System.Diagnostics.Process();
// Domain and User Name:
p.StartInfo.Domain = "MYDOMAIN";
p.StartInfo.UserName = "myusername";
// Command to execute and arguments:
p.StartInfo.FileName = "C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe";
p.StartInfo.Arguments = "http://url/AllItems.aspx";
// Build the SecureString password...
System.String rawPassword = "thepassword";
System.Security.SecureString encPassword = new System.Security.SecureString();
foreach (System.Char c in rawPassword)
{
encPassword.AppendChar(c);
}
p.StartInfo.Password = encPassword;
// The UseShellExecute flag must be turned off in order to supply a password:
p.StartInfo.UseShellExecute = false;
p.StartInfo.CreateNoWindow = false;
p.Start();
When I run this automated test Visual Studio returns informing me that the test was successful, however Internet Explorer does not open.
Is there something in my code I am missing in order for a window to appear? There is no iexplore process running prior to the test being run.
putting double quotes around the file path (since it contains spaces) may help:
p.StartInfo.FileName = "\"C:\\Program Files (x86)\\Internet Explorer\\iexplore.exe\""
^^ ^^
In addition, if your intention is to start this from a service process or dll running in a service such as "SharePoint", then this code will probably not launch the process in the desktop desired. You'll need to set the desktop to "winsta0\\default" in the startup info.
To run a process the worker process should have high privileges and this is not an ideal case in any web application. If your purpose is to use IE for unit testing then I would consider using something like WaitIN. If your purpose is for application logic to access a URL and do something then consider using HttpWebRequest. If you still need a process to be started then create a Windows Service and then expose a web call so in Share Point you can just make a call and your Windows Service can run on local account or some other high privilege account.
Hope this helps and please provide the scenario why you want to start the IE and that can give you a better answer in the forum.

Why is my application failing when launched remotely?

I have a Windows application that sits on four different servers, its purpose is to look through a directory, find .wav files and copy them to a remote location. It works perfectly when ran from directory it's in on the server, but I don't like going to four different servers to execute the application. So below, I have a console app that is really just telling the user to store the IDs for the wav files in the right location so the four applications can see them, then executes the various programs. The problem is all four apps crash immediately after launch, I think it has something to do with how I'm executing the command, but I can't figure it out. Any ideas?
class Program
{
static void Main()
{
Console.SetWindowSize(90, 35);
Console.WriteLine(#"Place the ID of the interaction(s) you wish to recover in \\SERVER\c$\IDKeys.txt." + Environment.NewLine);
Console.WriteLine("Press Enter to find interactions.");
Console.ReadLine();
exeCmd();
}
static void exeCmd()
{
string[] executable =
{
#"\\Server1\C$\App\findwavs.exe",
#"\\Server2\C$\App\findwavs.exe",
#"\\Server3\C$\App\findwavs.exe",
#"\\Server4\C$\App\findwavs.exe"
};
foreach (string exe in executable)
{
Process proc = new Process();
proc.StartInfo.FileName = exe;
proc.Start();
}
}
}
The code you have executes the executable on the local machine.
Using #"\\Server1\C$\App\findwavs.exe does not mean that the executable will run on Server1, it just means that your local machine will look in this network path to obtain the executable file, but will run it locally.
You can use PsExec to execute an application on a remote machine.
Consider the following code that uses PsExec to run an executable on a remote machine:
string application = "c:\\app\\findwavs.exe";
string arguments = ""; //use this if you want to pass any command line arguments to the findwavs.exe executable
string location_of_psexec = "c:\\pstools\\psexec.exe"; //location of Psexec.exe on local machine
string remote_machine = "Server1"; //name of remote machine
Process process = new Process();
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.FileName = location_of_psexec;
process.StartInfo.Arguments = string.Format("\\\\{0} -c \"{1}\" \"{2}\"", remote_machine, application, arguments);
This code assumes that the application path (e.g. "c:\app\findwavs.exe") is relative to your local machine, not the remote machine.
If you want to use a path relative to the remote machine, simply remove the -c from the value of process.StartInfo.Arguments
UPDATE:
Quoting from the above reference:
If you omit a user name, the process will run in the context of your account on the remote system, but will not have access to network resources (because it is impersonating). Specify a valid user name in the Domain\User syntax if the remote process requires access to network resources or to run in a different account. Note that the password and command are encrypted in transit to the remote system.
To make you application able to access network resources, use the -u and -p switches to supply a username and a password.
Running your code would be equivalent to navigating to \\Server1\C$\App\findwavs.exe in Explorer and double clicking on the exe. What I mean by this is that it will run the program on the machine that told it to run, not where the exe is stored.
The easiest way I can see to accomplish the task you want to perform would be to use PsExec.

Non-Admin user shown in UAC prompt

The following code checks for an admin user:
Text = new WindowsPrincipal(WindowsIdentity.GetCurrent()).IsInRole(WindowsBuiltInRole.Administrator).ToString();
Process p = new Process
{
StartInfo = new ProcessStartInfo
{
Verb = "runas",
FileName = "notepad",
}
};
p.Start();
When executed by my non-admin user, the first part shows "false" as expected. But in the UAC prompt - one of the "administrators" is my own account. How can that be?
(This only happens with one non-admin account. Not others on this computer. And is not offered as an option to them when executed from other accounts - they only see the real admins.)
Using a Windows 7 (x64) PC that is not connected to any other computer or domain (besides a wireless connection to the router). This was not the case until recently. Might it be that during installation of VS 2013 + Team Foundation Server somehow the account got partial Admin rights? Do partial admin rights even exist? (And yes. I've rebooted.)

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?

run shell command (manage-bde) as administrator from C#

I need to run "manage-bde" shell command from C# code.
The main application process is already running as administrator and is Elevated.
I used code from : UAC self-elevation example on MS website for confirming the app process is elevated.
(http://code.msdn.microsoft.com/windowsdesktop/CSUACSelfElevation-644673d3)
However, when I try to run manage-bde from the C# code, I get "System can't find file specified".
Process p = new Process();
p.StartInfo.FileName = "C:\\Windows\\System32\\manage-bde.exe";
p.StartInfo.UseShellExecute = true;
p.Start();
As a workaround, I tried to create a batch file that runs the command.
string batchFileName = DateTime.Now.Ticks + ".bat";
StreamWriter writer = new StreamWriter(batchFileName);
writer.WriteLine("manage-bde");
writer.Flush();
writer.Close();
Process p = new Process();
p.StartInfo.FileName = batchFileName;
p.StartInfo.UseShellExecute = true;
p.Start();
The batch file is written , and executed successfully; However, the command "manage-bde" is not recognized.
I changed the code to use the verb "runas" and use admin password and that works, but I want the batch file to work without the need for providing the admin password. The current logged in user is already administrator on the computer but the batch file is not getting executed with the existing admin privileges . I need the batch file to execute and manage-bde to run successfully.
Your help or advice will be very highly appreciated :)
ps: some commands other than manage-bde work fine without need for admin runas.
The reason of the behavior I encountered was the Windows File System Redirector.
In most cases, whenever a 32-bit application attempts to access %windir%\System32, the access is redirected to %windir%\SysWOW64
https://msdn.microsoft.com/en-us/library/windows/desktop/aa384187%28v=vs.85%29.aspx
My application build was 32 bits. Whenever it tried to access System32 windows automatically redirected it to SysWow64 which does not contain "manage-bde.exe". I changed the build to 64 bits and then the application could access manage-bde.exe from System32
Even if you're running as the Administrator user, you're not fully elevated if UAC is running. Meaning that you'll have either the UAC prompt come up or you'll be prompted for a password.
The only real way you could get around that is to run your application elevated first, or to write a service that runs with elevated permissions to start your new process.
The alternative of course is to disable UAC, but that is undesirable in most situations.

Categories