0

I'm facing quite weird error while trying to run a proccess with elevated privileges. I wrote a PS function that gets a command and user credentials and it should execute the command under those credentials. It's like Start-Process cmdlet but I wrote the function because I need to capture the output of the executed command. The point is that is supposed that when I set the property Verb of the ProcessStartInfo to "runas" that is supposed to launch the UAC.

My function is here:

Function Grant-ElevatedPrivileges {
    [cmdletBinding()]
    param(
        [Parameter(Mandatory=$true)]
        [String]$command
        ,
        [Parameter(Mandatory=$true)]
        [System.Management.Automation.PSCredential]$credential
    )
    Write-Verbose -msg "EXECUTING COMMAND WITH ELEVATED PRIVILEGES: $command"
#   Write-Host "$command"
    $result = @{'result' = $false; 'output' = $false; 'error' = $false};
    $psi = New-object System.Diagnostics.ProcessStartInfo
    #$psi.CreateNoWindow = $true 
    $psi.UseShellExecute = $false 
    $psi.RedirectStandardOutput = $true 
    $psi.RedirectStandardError = $true 
    $psi.FileName = 'C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe' 
    $psi.Arguments = @"
-ExecutionPolicy Bypass -noprofile $command
"@
    $psi.UserName = $credential.GetNetworkCredential().UserName
    if ($credential.GetNetworkCredential().Domain -ne "") { $psi.Domain = $credential.GetNetworkCredential().Domain }
    $psi.Password = $credential.Password
    $psi.Verb = "runas"
    $process = New-Object System.Diagnostics.Process 
    $process.StartInfo = $psi
    try {
        $result['result'] = $process.Start()
        $process.WaitForExit()
        $result['output'] = $process.StandardOutput.ReadToEnd()   
        $result['error'] = $process.StandardError.ReadToEnd()
    } catch [System.ComponentModel.Win32Exception] {
        if (($_.Exeption.NativeErrorCode) -eq 1326) {
            Write-Verbose "USUARIO O CONTRASEÑA INCORRECTA"
            $result['error'] = "BADUSER"
        } else {
            $result['error'] = $_.Exception.Message
        }

        $result['result'] = $false
    } catch {
        $result['result'] = $false
        $result['error'] = Write-Error $_.Exception.Message
    }

    if ($result['error'] -ne '') {
        Write-Verbose $result['error']
        $result['result'] = $false
    }
    $result
}

I check the behaviour I mention by invoking the function:

Grant-ElevatedPrivileges -command "([Security.Principal.WindowsPrincipal] [Security.Principal.WindowsIdentity]::GetCurrent()).IsInRole([Security.Principal.WindowsBuiltInRole] 'Administrator')" -credential $creds -Verbose

That should return True if the command where executed under admin privileges...

Any ideas about what I'm missing?

Thanks for your advices or ideas ;)

SantiFdezMunoz
  • 501
  • 1
  • 6
  • 18
  • For what it's worth, I tested out your code, and was able to find that it did not request elevation from a non-elevated prompt. Did you get your code idea from here? http://www.codeproject.com/Articles/105506/Getting-Elevated-Privileges-on-Demand-using-C –  Jan 03 '14 at 15:23
  • And what is your problem? Does it not return true? Does it return an error? – Lars Truijens Jan 03 '14 at 15:24
  • @TrevorSullivan, I wrote the function about 3 months algo, so I cannot remember the exact sources, but may be one of my sources. Nevertheless, as far as I remember from doc on MSDN if I set the verb to "runas" it should rise the UAC window, shouldn't it? – SantiFdezMunoz Jan 03 '14 at 16:54
  • @LarsTruijens, my problem is that if I test my function with the code I mention it always returns false, when it's supposed to return true since the code it's supposed to be executed on an administrator context. – SantiFdezMunoz Jan 03 '14 at 16:56
  • @SantiFdezMunoz The MSDN documentation does not explicitly call out the "runas" verb. It states that the `Verb` property should match one of the values output from the read-only `Verbs` property. Looking at the docs for `Verbs`, it says that the returned values are based on the extension of the value specified for the `FileName` property. http://msdn.microsoft.com/en-us/library/system.diagnostics.processstartinfo.verbs(v=vs.110).aspx –  Jan 03 '14 at 17:04
  • You are right @TrevorSullivan, I saw that information in other forums and wrongly assumed that I read it on MSDN. – SantiFdezMunoz Jan 03 '14 at 19:54

1 Answers1

0

It seems it is not possible to run as a different user AND elevated (as administrator) in one go. So either:

  • Run as a different user, but not elevated by supplying credentials, no runas verb and UseShellExecute = false. You already have that code
  • Run elevated as the current user by using the runas verb, no credentials and UseShellExecute = true. See here for an example.
  • Run as a different user AND elevated by doing it in two steps by combining the two options above. See here for an example.
    1. Start a process as a different user
    2. Start a process from that process and elevate it
Community
  • 1
  • 1
Lars Truijens
  • 42,837
  • 6
  • 126
  • 143
  • @LarsTrujiens, your approach seems logical, let me rewrite the function, test it and I'll let you know the results. Thanks! – SantiFdezMunoz Jan 03 '14 at 19:57
  • Bah, I had a feeling it had something to do with `ShellExecute` ... but yeah, it wouldn't let you use `ShellExecute` unless you didn't specify credentials. –  Jan 03 '14 at 19:59
  • @LarsTrujies, I've just tested your approach and I realized that it has a drawback, I cannot redirect StandardOutput or StandardError if I set UseShellExecute = false. So it seems that is not posible in a feasible way to execute a command with elevated privileges, current credentials AND redirected output (which is actually as important as running the command with elevated privileges) – SantiFdezMunoz Jan 07 '14 at 09:19