I want to run an application under another user account's (non-elevated) credentials while that user is already logged-in. Specifically, I want my application's installer (which runs under any administrator account) to spawn processes into each logged-in user's desktop session. These processes communicate with a service and display windows on the desktop for the user to interact with.
Ordinarily, from a service running as LocalSystem
, the approach is WTSQueryUserToken
-> CreateProcessAsUser
. However, WTSQueryUserToken
won't run outside of the LocalSystem
account (with SE_TCB_NAME
privilege), which makes that approach fail here.
If the user weren't logged in already, I could just register the application to run under HKLM\...\Run
, so that any logged-in user will get a copy of the application when they log in. But if the user's already logged-in, that doesn't work either (at least, not until they log out and log back in again).
I can see two possible answers:
You can't do this. Sorry.
You can get a token from somewhere else (maybe enumerate explorer.exe processes and pull the access token from each one?), call
DuplicateTokenEx
, then pass toCreateProcessAsUser
. I tried this approach and consistently received "access denied" when trying toOpenProcessToken
on a process running under another user session, even with the debug privilege enabled and the process opened withPROCESS_ALL_ACCESS
.
What do you think?
If the answer is #1 ("you can't do this"), then what is the recommended best practice for spawning non-elevated processes to mediate between a service and the user? Is it best practice for the service to spawn these processes into each session via CreateProcessAsUser? Or is it best practice for the non-elevated processes to be run separately (e.g. via HKLM\...\Run
or HKCU\...\Run
)?