Search code examples
powershelladminuac

How to run exe with/without elevated privileges from PowerShell


I would like an easy way to run a process with different privileges from the same user without asking or knowing his/her password. A dialog is okay if necessary. I would prefer not to launch a PowerShell sub-process to accomplish this.

Scenario 1: PowerShell script is running in admin-mode. I want to launch a script or an .exe without admin privileges but on the same user.

Scenario 2: PowerShell script is running in normal mode. I want to launch a script or an .exe with admin privileges on the same user.


Solution

  • Let's split this into three parts.

    First determine if current session is running with admin privileges:

    $CurrentID = [System.Security.Principal.WindowsIdentity]::GetCurrent()
    $CurrentPrincipal = new-object System.Security.Principal.WindowsPrincipal($CurrentID)
    $adminRole = [System.Security.Principal.WindowsBuiltInRole]::Administrator
    
    # Check to see if session is currently with admin privileges
    
    if ($CurrentPrincipal.IsInRole($adminRole)) {
        write-host "Yes we are running elevated."
    }else{
        write-host "No this is a normal user session."
    }
    

    Now, if we are running with or without elevation, you can start a new process with elevated privileges like this:

    $newProc = new-object System.Diagnostics.ProcessStartInfo "PowerShell"
    # Specify what to run
    $newProc.Arguments = "powershell.exe"
    # If you set this, process will be elevated
    $newProc.Verb = "runas"
    [System.Diagnostics.Process]::Start($newProc)
    

    And lastly, if we have elevated privileges, but would like to start a new process without...

    I have no idea. Will have to try to find the answer to this, but as it is not a common scenario, I had no luck so far.

    EDIT: I have now seen a couple of “solutions” for this scenario. There is no native way to do this in .NET/PowerShell. Some are quite complicated (Calls to some 12 COM objects). This vista-7-uac-how-to-lower-process-privileges is a good reference.

    The one that seems most elegant to me, is exploiting a “bug” in explorer.exe. Just launch you .exe using explorer.exe and the resulting process runs without privilege elevation again.

    $newProc = new-object System.Diagnostics.ProcessStartInfo "PowerShell"
    # Specify what to run, you need the full path after explorer.exe
    $newProc.Arguments = "explorer.exe C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
    [System.Diagnostics.Process]::Start($newProc)
    

    EDIT #2: Another way I have just found to start a new non-elevated process from an already elevated environment is to use the runas.exe with the 0x20000 (Basic User) trust level:

    C:\> runas /showtrustlevels The following trust levels are available on your system: 0x20000 (Basic User) C:\> runas /trustlevel:0x20000 devenv

    enter image description here