Run process from different credentials? Simple with DevxExec.exe!
We've released updated version of our command-line tool that allows to run Windows processes under different user credentials.
Devxexec is licensed under a Creative Commons Attribution-NonCommercial-NoDerivs 3.0 Unported License.
Based on work at developex.com. Permissions beyond the scope of this license may be available.
21.1.14: DevxExec is updated! Download a new version 1.16.
+ Possibility of specifying desktop for running processes. Command-line parameter: "devxexec.exe desktop:winsta0\winlogon".
1.2.13: DevxExec is updated! Download a new version 1.15. This is a minor bug fix.
+ Now Devxexec is trying to fetch target user environment block. If it's not possible, it uses environment block of a mother process.
For compatibility purposes, a new option "/upp" was added. If it’s specified, Devexec isn't trying to fetch target user environment block.
Following article reviews several scenarios of process creating from Windows service like: creating a process win GUI from the non-interactive service, creating a process under another user account and in the different session. The article doesn’t contain code examples, however, it explains how to achieve the result with a free command line tool DevxExec. This text requires basic level of familiarity of Windows API.
How to run a process from the Windows service
There are different situations, when you need to create an additional process from your main process. One of those situations is, when you need to isolate some code of your service, because that code could be a reason of resource leak or can damage your common process somehow. Another case is, when your application needs to perform an action that requires changing primary process token. Finally, you just may need to run a 3rd party application.
At first glance, creating a new process is a very simple operation. That is actually true. There are 3 different functions CreateProcess, CreateProcessAsUser and CreateProcessWithLogon in Windows API that you can use to create a new process. However, there are situations, when they don’t work in the way you expect.
To allow several users working with the same computer at the same time Windows isolates processes of each user with a special object called session. During system startup it creates a session with ID=0. OS uses this session to isolate windows services processes from users’ processes. Also Windows creates another session (ID=1) during startup and run the first instance of winlogon.exe under that session. Therefore, first logged in (via console) user will work under session with ID=1. When another user wants to login to the computer, system creates a new session for him.
Window always creates a new session before the user logs in. In another words, it happens, when a new remote desktop connection is established or when a user connected via console uses the "switch user" function. Once the session is created, Windows runs a new instance of winlogon.exe. So, the login screen, where a user types his credentials, always relates to its own session.
Every session has it own windows station. Windows station is an another isolation object that came to us from older version of the system. Every window station contains a dedicated clipboard and a number of desktops.
Here is the typical hierarchy of sessions, window stations and desktops in Windows Vista and Seven (Windows 7).
In older systems, like XP or 2003, it is different. The user logged in via console and the services are running in the same session and interactive services even use the same windows station and the same desktop.
When you run a process from the windows service under the user account, that process may not have (usually it doesn’t) access to the window station and to the desktop related to session 0. Of course, if your process doesn’t create any window then, you are just lucky. However, it’s actually not easy to write an application that doesn’t create any window at all. Typical Windows application infrastructure is based on a window even if this window is newer shown. The console application written on the most of languages (like Visual C++ or C#) creates a window too. Therefore in 99% of cases our application needs the access to the window station and to the desktop.
When you run a console application and the user, under which the process is running, doesn’t have an access to the window station, on some versions of OS you may see the error message like this:
To solve this problem, you can add permissions to the window station and the desktop. Usually, services run under the separate window station "Service-0×0-3e7$". However, if the option "Allow interact with Desktop" is on for the service, then it runs under "WinSta0". The difference between those windows stations is that "Service-0×0-3e7$" can’t be ever interactive, a user will not be able to see the GUI of applications running there. In case of "WinSta0" a user can see the GUI but remember that in Windows Vista/Seven/2008 interactive services and the logged in user have different window stations with the same name but in different sessions.
In Windows Vista/Seven/2008, once a window is created into the Session0Winsta0Default, operation system will show a dialog like this. This dialog allows switching active user desktop to Session0Winsta0Default.
It’s actually not really important, if your service runs in interactive mode or not. You always can specify a window station and a desktop while creating a new process. There is a special parameter in StartupInfo structure for this.
You can also use the Developex free tool DevxExec to run a process from the windows service under another user.
DevxExec.exe /user:Administrator /password:qwerty "cmd.exe"
This command automatically grants permissions to user "Administrator" on the appropriate window station and the desktop and runs a command shell.
How to run an application under another user account credentials from the Windows service
Let’s see the following scenario. You have a Windows service running. User Marcus has logged to the computer. And you want your service to start the application that will be shown to Marcus on his current desktop. In other words, you need to run a new process in another session.
It sounds like an easy task. Yes, you can change a window station and a desktop, but unfortunately, there is no option to specify a session ID to CreateProcess functions. However, Windows security token is always related to one session and, fortunately, we can change the session for the security token. Therefore, if we create a new token for our user (for example, using LogonUser), then change a session for this token using SetTokenInformation function and finally, call CreateProcessAsUser, the new process will be created in the appropriate session.
Again you can use DevxExec. It has a special parameter /sessionid to specify the session you want to run a new process in. For example, this command could start a command shell for a logged in user under Administrator.
DevxExec.exe /user:Marcus /password:qwerty /sessionid:1 "cmd.exe"
How to run an application for a user from the Windows service
Here is an another scenario. User Marcus has logged to the computer. And you want your service to start an application as Annette that Marcus can work with on his current desktop. The solution above will work in that scenario too, but only, if Annette is a member of the local "Administrators" group. Otherwise, she will not have access to the Marcus desktop and windows station.
So, our service (that runs in session = 0) needs to give permissions to Annette to Marcus desktop (session ≠ 0). The problem is how to get a handle of thedesktop that lives in another session. If you find out how to do it, please, let us know. Unfortunately, we haven’t found how to do it, but here is a workaround solution:
Get a primary process (OpenProcessToken).
Create a primary copy of this token (DuplicateTokenEx)
Modify session id of the replica (SetTokenInformation).
Create a new temporary process using that taken with CreateProcessAsUser.
This process will be run into the Marcus session, therefore, it could access his window station and his desktop and give permissions to Annette.
DevxExec works approximately that way so, you can create a process for either user in either session.