Table of Contents
I recently had a request to create a small applet/windows form that would allow regular end users to perform an administrative task. For example, restart the Print Spooler service. We did not want to grant the user any elevated rights, only to give them a program that would allow them to perform the single task and nothing more. PowerShell to the rescue –
Beginning with Windows Vista, the administrator security token split with the standard user token. This means that to perform administrative tasks you must elevate (UAC). Each app that requires the administrator access token must prompt for consent. Using PowerShell Studio I can create my Winform and use an administrator manifest to prompt for elevation, and input either a RunAs account or specify an account to Impersonate as.
The problem however, is Windows evaluates manifests prior to RunAs or Impersonation. It will load the manifest before any code is executed, and if our user is a standard user, they will be prompted for administrative credentials. So to make this all work we need to first launch with RunAs or Impersonation and then launch a shell or form that has an admin manifest. Sapien has a great article that details the inner workings of this a bit better.
Below is the back-end code of a simple Windows form I am creating in Sapien PowerShell Studio. It will allow my end users, that have no admin rights on their machines, to reset the Print Spooler Service.
If I were to compile this as is and run it on a machine where the user is only a standard user, I can see that it will fail because Restart-Service requires an admin Shell to run. Restarting the print spooler is an administrative task.
So, In PowerShell studio I will go to the Packager Settings, and in Output settings, select the Run Mode to be Impersonate or RunAs and then enter the credentials. These credentials I specified are a service account that has enough local rights to perform the task I specified. (ex: If I want the form the reset the network stack it can be a member of the local network operators group instead of the local administrators). The credentials you specify in here are encrypted within the compiled executable.
But wait, if you were to compile this now and run it. It will still fail. This is because while we are running as our service account or impersonating our service account, we only have the service account’s standard user token. We do not yet have the administrator token. Also, the executable must live somewhere that the specified Impersonation or RunAs account has access to! If you place this on your users desktop and your service account does not have permission to that users desktop without requesting the admin token, you will get the error, “The Directory Name is Invalid”
Using the cmdlet Start-Process we can launch a administrative PowerShell instance in the background and slipstream our command to reset the spooler in there. Since we are running our program as an administrator, when it prompts us with UAC to get the admin security token, we can simply approve it.
The end user will see the UAC prompt when they run the program because the it is requesting the administrator security token to run our single command.
All together our new back-end code now looks like the following
When we go to our end user machine who has no admin rights at all, we can see it launches and resets the spooler without any issues.
One of the benefits to this method is that it is all compiled in a single executable.