Run the process under different user credentials

I want to run the process under different user credentials. This is what I have now:

/// <summary> /// Do actions under another username credentials /// </summary> /// <param name="username">Username to inpersonate</param> /// <param name="domain">Domain/Machine</param> /// <param name="password">Password </param> public static void Action(string username,string domain, string password ) { try { if (LogonUser(username, domain, password, LOGON32_LOGON_INTERACTIVE, LOGON32_PROVIDER_DEFAULT, ref hToken)) { if (DuplicateToken(hToken, 2, ref hTokenDuplicate)) { WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate); WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate(); // Check the identity but it could do any other action under given username credentials try { ProcessStartInfo info = new ProcessStartInfo("cmd.exe"); info.UseShellExecute = false; info.RedirectStandardInput = true; info.RedirectStandardError = true; info.RedirectStandardOutput = true; info.UserName = "dummy"; // see the link mentioned at the top // Define the string value to assign to a new secure string. char[] chars = { 'p', 'a', 's', 's','1','2','3','4','/' }; // Instantiate the secure string. SecureString testString = new SecureString(); // Assign the character array to the secure string. foreach (char ch in chars) testString.AppendChar(ch); info.Password = testString; Process.Start(info); } catch (Exception ex) { Console.WriteLine("Exception Occurred :{0},{1}",ex.Message, ex.StackTrace.ToString()); } // Stop impersonating the user impersonationContext.Undo(); } } // Free the tokens if (hToken != IntPtr.Zero) CloseHandle(hToken); if (hTokenDuplicate != IntPtr.Zero) CloseHandle(hTokenDuplicate); }catch(Exception ex) { Console.WriteLine("Exception occurred. " + ex); } 

This does not seem to work, and I get "Access denied." Any ideas on how to do this? If we ask for credentials, we will get the correct ones, so he must execute any program under these credentials. i.e:

  if (DuplicateToken(hToken, 2, ref hTokenDuplicate)) { WindowsIdentity windowsIdentity = new WindowsIdentity(hTokenDuplicate); WindowsImpersonationContext impersonationContext = windowsIdentity.Impersonate(); // Check the identity but it could do any other action under given username credentials Console.WriteLine("After impersonation: {0}", WindowsIdentity.GetCurrent().Name); // Stop impersonating the user impersonationContext.Undo(); } 

And the answer is correct, we get "dummy".

We could make it even easier:

  public static void Run() { try { const string file = "cmd.exe"; var sspw = new SecureString(); foreach (var c in "pass1234/") sspw.AppendChar(c); var proc = new Process(); proc.StartInfo.UseShellExecute = false; proc.StartInfo.WorkingDirectory = Path.GetDirectoryName(file); proc.StartInfo.FileName = Path.GetFileName(file); proc.StartInfo.Domain = "WIN08"; proc.StartInfo.Arguments = ""; proc.StartInfo.UserName = "dummy"; proc.StartInfo.Password = sspw; proc.StartInfo.LoadUserProfile = false; proc.Start(); }catch(Exception e) { Console.WriteLine(e); } 

However, I still have exceptions ...

+4
source share
3 answers

I do not think you need to log in and duplicate the descriptor. All you have to do is set the username, domain and password in the ProcessStartInfo object. This has been available since .NET 3.0, if I remember correctly.

EDIT:

Also for more information, this is what really happens when you specify the username / domain / password for ProcessStartInfo: http://support.microsoft.com/kb/165194 . The reason for the denial of access is probably because you do not have access to the user desktop or window station. It is not enough just to call LoginUser.

+5
source

This may be strange for some people, my apologies, I'm a Linux developer ... Checked:

  /// <summary> /// Class that deals with another username credentials /// </summary> class Credentials { /// <summary> /// Constructor of SecureString password, to be used by RunAs /// </summary> /// <param name="text">Plain password</param> /// <returns>SecureString password</returns> private static SecureString MakeSecureString(string text) { SecureString secure = new SecureString(); foreach (char c in text) { secure.AppendChar(c); } return secure; } /// <summary> /// Run an application under another user credentials. /// Working directory set to C:\Windows\System32 /// </summary> /// <param name="path">Full path to the executable file</param> /// <param name="username">Username of desired credentials</param> /// <param name="password">Password of desired credentials</param> public static void RunAs(string path, string username, string password) { try { ProcessStartInfo myProcess = new ProcessStartInfo(path); myProcess.UserName = username; myProcess.Password = MakeSecureString(password); myProcess.WorkingDirectory = @"C:\Windows\System32"; myProcess.UseShellExecute = false; Process.Start(myProcess); } catch (Win32Exception w32E) { // The process didn't start. Console.WriteLine(w32E); } } } 
+4
source

Maybe you forgot to make only a safe line? My method works fine for me:

 Process proc = new Process { StartInfo = { CreateNoWindow = true, UseShellExecute = false, RedirectStandardOutput = true, RedirectStandardInput = true, FileName = "cmd.exe", UserName = "user", Domain = "myDomain", Password = GetSecureString("Password"), Arguments = "/c ipconfig" } }; proc.Start(); 

GetSecureString () function:

 public static SecureString GetSecureString(string str) { SecureString secureString = new SecureString(); foreach (char ch in str) { secureString.AppendChar(ch); } secureString.MakeReadOnly(); return secureString; } 
+2
source

Source: https://habr.com/ru/post/986847/


All Articles