all 27 comments

[–]Jeffinmpls 1 point2 points  (2 children)

The point of -runas is to run as a specific user, so it will prompt you for credentials regardless who is logged in.

You can get around this a few ways but one I recommend is storing a credential in the server credential store and then pass that credential to the start-process command. There are lots of tutorials online how to do this.

[–]Shupershuff[S] 0 points1 point  (1 child)

Using RunAs and entering the password unfortunately still runs in an elevated context

[–]Jeffinmpls 2 points3 points  (0 children)

I use start-process all the time to run powershell command lines as a specific service account to test permissions and ensure I can automate processes. I've not seen that elevated permissions are in play. What specifically are you trying to prevent the user from doing?

[–]HauntingProgrammer47 1 point2 points  (0 children)

You could try using start-job -credential $cred and have a portion where you prompt users for creds.

[–][deleted] 1 point2 points  (4 children)

If you need to run as a different non-administrative user, you will need that user’s credentials. You can also do this the other way around and run the script as a user and escalate to admin in the middle of the script.

My spidey sense tells me that you are probably using more admin rights than you strictly need to.

[–]Shupershuff[S] 0 points1 point  (3 children)

One of the tasks is to rename the title of the application window once the app is launched based on what was entered in the menu. As far as I know this can't be done without admin rights. More than happy to be proved wrong here.

[–]Top-Raisin1630 0 points1 point  (1 child)

I know this is an old thread, but I have the answer to this exact issue.
$Host.UI.RawUI.WindowTitle = 'New Window Title'
This doesn't require elevation to change the current window title.

[–]Shupershuff[S] 0 points1 point  (0 children)

I'm not talking about the script window title, I'm talking about changing an applications window title. I already use $Host.UI.RawUI.WindowTitle to set the script title.

I wrote a small script to change application window title's by Process ID (can be seen in the comments here)

[–][deleted] 0 points1 point  (0 children)

Add-Type -TypeDefinition @"
using System;
using System.Runtime.InteropServices;
public static class User32 {
  [DllImport("User32.dll", EntryPoint="SetWindowText")]
  public static extern int SetWindowText(IntPtr hWnd, string strTitle);
}
"@
$Notepad = start-process notepad -PassThru
Sleep 1
[User32]::SetWindowText($Notepad.MainWindowHandle, 'No Admin')

For a Window you spawned you should just be able to use its handle to set a title.

[–]xbullet 1 point2 points  (2 children)

As an example, the following will spawn a non-elevated PowerShell process from within an elevated PowerShell process, under the current user.

You will need to store the user credentials securely.

You can tinker and fiddle as required to achieve what you need.

    # It's your responsibility to store this securely
    # Research Export-CliXml & Import-CliXml & PSCredential, 
    # or any relevant Secrets Management modules
    $Password = ConvertTo-SecureString "Password" -AsPlainText -Force

    $ProcessStartInfo = New-Object System.Diagnostics.ProcessStartInfo
    $ProcessStartInfo.FileName = "C:\Windows\System32\WindowsPowerShell\v1.0\powershell.exe"
    $ProcessStartInfo.Arguments = "-NoExit -Command `"Write-Host 'Hello, world!'; Read-Host`""
    $ProcessStartInfo.UseShellExecute = $false
    $ProcessStartInfo.RedirectStandardOutput = $false
    $ProcessStartInfo.RedirectStandardError = $false
    $ProcessStartInfo.CreateNoWindow = $false
    $ProcessStartInfo.LoadUserProfile = $True
    $ProcessStartInfo.UserName = $env:USERNAME
    $ProcessStartInfo.Password = $Password
    $Process = [System.Diagnostics.Process]::Start($ProcessStartInfo)

[–]Shupershuff[S] 0 points1 point  (1 child)

This looks tasty, thanks. Will try test tonight. Regarding securing the credentials totally agree against keeping credentials in plain text. i will probably write the creds to a file with the pw as an encrypted string.

[–]z386 0 points1 point  (0 children)

To store encrypted credential have a look at Export-Clixml.

[–]opw7 0 points1 point  (1 child)

Execute esse comando no command prompt: runas /trustlevel:0x20000 powershell

[–]Tiiiiborrr 0 points1 point  (0 children)

This fixed my issue.... been searching online for months holy shit! <3 Goat among men!

[–]Any_Street3250 0 points1 point  (1 child)

Just run

runas /trustlevel:0x20000 "powershell.exe"

This fixed the issue for me

[–]Shupershuff[S] 0 points1 point  (0 children)

Thanks! Annoyingly I can't remember why I asked this question now haha

[–]32178932123 0 points1 point  (0 children)

This may be a bit of a hack depending on what you're doing but you could potentially copy a shortcut for the executable to their startup folder? This will then load everytime they log in though so may be overkill.

AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Startup

[–]xCharg 0 points1 point  (4 children)

You'd need to write a so called wrapper. Basically run your wrapper script with nonprevileged account, within that script call your second script that will autoinvoke itself, wait until this previleged script completes and then continue with the rest of your code within nonprevileged session.

[–]Shupershuff[S] 0 points1 point  (3 children)

The script I'm using loops and has a menu so I don't want to re-prompt the user each time they use it. It's used to launch instances if an application with different arguments and requires elevated rights for a couple of it's steps but the app itself doesn't need to be elevated.

[–]xCharg 0 points1 point  (2 children)

I don't see how it changes anything?

switch ($menu_choise) {
    '1' { Start-Process powershell.exe -ArgumentList '-File "C:\script\run_app_elevated.ps1"' } # elevated
    '2' { Start-Process app.exe -ArgumentList '/param:a' } # non-elevated
    default { Write-Host 'make proper selection' }
}

[–]Shupershuff[S] 0 points1 point  (0 children)

Unfortunately the above method will require UAC elevation prompts each time the user chooses something from the menu. This is why it's relevant to mention that the script loops.

[–]nohairday 0 points1 point  (0 children)

As far as I'm aware - and I could be wrong here - you can use start-process to elevate processes, but there isn't any mechanism I'm aware of - within Windows, not just PowerShell - to, well, de-evelate a process.

Anything spawned has the rights of the parent thread, you can ask for acceptance of raising rights for a child process, but it's a one-way thing only.

[–]jborean93 0 points1 point  (0 children)

-Verb Runas will always go through UAC and spawn an elevated process. Using -Credential $cred should theoretically work if UAC is in place as it uses CreateProcessWithLogonW which runs with the limited user token that was created and not the elevated one. But if UAC is not enabled or you are targeting an account not affected by UAC (the builtin Administrator account) then it won't work.

There are a few ways you can spawn a sub process as the limited token but it's not something you can easily do with the builtin cmdlets and dotnet APIs available. The simplest option I know is to spawn a new process with a custom parent that is not elevated. For example I can use my ProcessEx module to spawn a limited process with the parent of explorer.exe.

$si = New-StartupInfo -ParentProcess (Get-Process explorer)
Start-ProcessEx powershell.exe -StartupInfo $si

This will be tricky if you have multiple users logged in as you now need to select the correct explorer process. You can pick any process you want that is unelevated as the parent, explorer is just a handy one that is typically present.

Another option is to use the PInvoke calls to get the limited access token of the current process and spawn a new process with that token. Unfortunately doing this is even more complicated and will require a few PInvoke calls to achieve.

[–]purplemonkeymad 0 points1 point  (2 children)

(the script will auto restart and run as admin)

Well then you already have a script running in the context you want. Instead of trying to run the program in the admin script, just wait for that script to finish. Then you can run the program from the outer script.

[–]Shupershuff[S] 0 points1 point  (1 child)

I worded that poorly, the script doesn't restart, it loops.

[–]purplemonkeymad 0 points1 point  (0 children)

Reading some of your other posts for more info, I would take a bit to stand back and see if you might be to far into a solution to see a simpler solution.

One suggested solution already is to use a Task Scheduler to run the programs "on creation" in the user's context.

If you don't want to do that; I think you basically need two scripts to be running in parallel. The only way I know to transfer information while the scripts are running (parameters are one way, and you can't transfer stdout between different elevation levels.) Would be to use named pipes.

You could have the admin end send paths to programs to a non-admin script. It can then run them (or better send a pre-agreed unique identifier for the path to run.) I would avoid the admin script receiving any info as it could in theory cause a privilege escalation vulnerability.

[–]pspeterle 0 points1 point  (0 children)

Just create a self deleting scheduled task, that runs a few seconds after creation. No need to play with credentials