Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Launch a process under another user's credentials

Tags:

c#

windows

I want to launch a process under another username's credentials. This is what I have now:

        /// <summary>
        /// Do actions under another username's 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);
          }

It does not seem to work and I get an "Access denied". Any ideas of how to do it? If we ask for the credentials, we get the right ones, so it should execute any program under that 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 right, we get "dummy".

We could make it even simpler:

 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 get exceptions...

like image 449
Manolete Avatar asked Jun 20 '11 15:06

Manolete


People also ask

How do I Run a program as another user?

To Run a program as a different user, simply press the Shift key and right-click on the shortcut or executable you wish to Run as different user. From the right-click context menu, select Run as different user.

How do I Run a program from a different user in PowerShell?

Then you can right-click on the PowerShell icon, which shows you an option as Windows PowerShell. Hovering over that options, Click Shift and right-click together to open another menu. You can choose Run as Different User from the new menu. Then a different popup would be opened, as shown in the below image.

How do I Run a Command Prompt as another user?

You could do the following: Open a Command Prompt window. Click Start, click Run, type cmd and press ENTER. In the Command Prompt window you just opened, type runas /user:<domain\username> cmd and press ENTER to open another Command Prompt using alternate credentials.


1 Answers

It might be weird for some people, my apologies, I am Linux developer... Tested:

    /// <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);
            }
        }

    }
like image 89
Manolete Avatar answered Sep 21 '22 00:09

Manolete