Create a process with ordinary rights from an administrator process
There is any way to run another process with ordinary rights from a process running as administrator? From a process with elevated rights I want to start a proc开发者_Go百科ess with ordinary rights like it were started from explorer. I tried impersonation but I didn't work.
Use CreateProcessAsUser(). Details are in the linked SDK docs.
No this is not possible (There are several hacky ways to do this (Inject into explorer, task scheduler, SaferAPI+MediumIL etc) but none of them work in all scenarios)
This seems like a nice way to do it, provided you don't care about situations where the Shell is not running (e.g. possibly some Terminal Services application-only setups, perhaps, though I'm not sure):
http://brandonlive.com/2008/04/27/getting-the-shell-to-run-an-application-for-you-part-2-how/
It gets an interface to Explorer.exe, which should be running in the user's normal context, and asks Explorer to execute a command in its behalf. This is done just using simple, documented COM interfaces and without having to mess around with process tokens or code/DLL injection.
The technique I've used with success is to use IShellDispatch2::ShellExecute to ask Explorer to launch the process. Since Explorer typically runs as normal integrity, this is effective. The trick is that it's a bit of work to get the IShellDispatch2 object. I followed the process outlined in this blog.
on linux you can use setuid to change the program user id
for windows you can look at his: https://serverfault.com/questions/16886/is-there-an-equivalent-of-su-for-windows
If at all possible, use Larry Osterman's solution (in the comments to Anders' answer) instead, i.e., have a parent process that runs without elevation, and launch both the elevated process and the non-elevated process from there.
If that isn't possible, there is an approach that should work in almost all cases, though it is usually more trouble than it's worth:
Install and start a system service, configured to run as local system. Give it your Remote Desktop session ID, e.g., via a command-line argument or a registry setting, as well as your process ID and the command line you want to run.
From the system service, use GetTokenInformation with TokenLinkedToken to get the linked token from the target process. You have to do this from a system service because you need SE_TCB_NAME to get a usable token. (This limitation does not appear to be documented but is consistent with the behaviour of tokens in Windows.)
Or, if there is no linked token, use WTSQueryUserToken to get a copy of the user's token. I believe this always gives you the limited token (if there is one) but if you want to be safe you can check whether it is an elevated or limited token using GetTokenInformation and TokenElevationType; if it is an elevated token, you can use TokenLinkedToken to get the limited one.
If there is no linked token (TokenElevationTypeDefault) you should use the token as-is. This may happen either because the user is not an administrator, or because UAC is disabled, either globally or because the user logged in using the built-in Administrator account. If the user is not an administrator then the token is already suitable. If UAC is disabled, you should respect the user's intent and use the administrative token.
You can then use CreateProcessAsUser or CreateProcessWithTokenW from the system service to launch the new process.
Finally, the service should delete itself and stop.
There is at least one edge case: if your elevated process is launched from a command window (or other process) which was launched using runas and non-administrative credentials. There is no split token in this case, and the original token may have already been deleted, so unless you captured a copy before elevation took place (Larry's solution, or variants thereof) there is no general way to run the child process in the same user context that the elevated process was originally launched from. The best you can do is the context of the logged on user (via WTSQueryUserToken as described above) which may not be the behaviour the end user would expect. (This may, however, be an acceptable limitation, depending on the scenario.)
When Explorer needs to de-elevate, it uses a scheduled task. This is probably a good solution in most cases, and much easier than my earlier answer.
A simple example in Powershell:
$action = New-ScheduledTaskAction -Execute 'notepad.exe'
Register-ScheduledTask -TaskName 'Launch Notepad' -Action $action -User $env:username
Start-ScheduledTask -TaskName 'Launch Notepad'
精彩评论