Can users interact with services directly on Microsoft Vista? - winapi

From the Microsoft website (see msdn.microsoft.com/en-us/library/ms683502(VS.85).aspx) it clearly says "Services cannot directly interact with a user as of Windows Vista".
So I decided to test this by using "psexec -s cmd.exe". As far as I know, "psexec" creates a service in order to open a command prompt. Needless to say it worked. I then decided to use "EnumWinSta GUI" in combination with psexec to switch to the winlogon desktop. To my surprise, I could even start "cmd.exe" on this desktop. Does this mean a new process created from a service can be interactive?
Or is it because psexec does some kind of black magic? If so how does it do it?
I am trying to display a full screen window from a service into the winlogon desktop object in Vista as well as XP.

Code running within a service cannot directly interact with an interactive session.
However, code running as a service with sufficient privileges can create a new process running within a specific user's desktop - getting the interactive session's user's token and calling CreateProcessAsUser, for example.
You can use WTSGetActiveConsoleSessionId to get the active console session, the session of the user who is actually on the machine. WTSQueryUserToken can then be used to get the token.
Your service can also use session change notifications in its handler function to see when users logon/logoff, unlock their session, and so on.

Related

Avoiding UAC but launching an elevated process using a windows service

I have a non-interactive service running as a the privileged SYSTEM user on Windows machines, and I need it to launch a given executable as an elevated process.
I have managed to launch a child process as SYSTEM, using WTSGetActiveConsoleSessionId(), finding a system process and duplicating it's token. Similarly, I can launch a non-elevated process as a regular user. But I need to launch the process as the regular user, but with elevated privileges - so that I don't have to show UAC, but the process is running as the appropriate user.
I am not trying to bypass UAC - since the user already agreed to installing the service. I am trying to mitigate an inconvenience. I have found a similar, unanswered question - but asked again in hope of maybe getting an answer.
If you have a filtered token for the interactive user - for example, one retrieved via WTSQueryUserToken() - you can retrieve the unfiltered ("elevated") token by using the GetTokenInformation function with the TokenLinkedToken option.

How do I limit permissions using ShellExecute on remote desktop users

Delphi XE app running on Windows 2012 Server. How do I limit the user's permissions when they open Adobe Viewer using ShellExecute. As it stands now, the uses are not permitted to see the drivers on the server. However, when the user opens a pdf from the application, the permissions revert back to admin, which allows them to see and access the drives.
Are there settings within ShellExecute that can apply the proper permissions based on the user login credentials?
When you create a process using ShellExecute, the new process runs under the credentials of the parent process. So it would seem that the process with is calling ShellExecute has more rights than you wish to grant to the process that is started by ShellExecute.
One way to solve the problem would be to call ShellExecute from a process running under the desired credentials. There may be other ways to solve it, but without any knowledge of your network security configuration, it's unlikely that we can give you much more specific advice.

How to get Windows SYSTEM user token

Operating system is Windows 7 or higher with UAC enabled. Calling process has admin rights, already confirmed by the UAC box.
I want to spawn a new Console window (cmd.exe) under user SYSTEM (don't ask why). I can do this interactively by using PsExec tool from Sysinternals or something similar, but I don't have the source code and I need to understand how this works.
I understand that I have to call CreateProcessAsUser() and that works fine with the first parameter (hToken) set to NULL, but now I need to know how to get the hToken. I understand that I can get such a token by calling LogonUser() - but not for SYSTEM. How would I get the token for SYSTEM?
I thought of using DuplicateTokenEx(), but that requires an original token, that I don't have.
Would I have to query the process list, find any SYSTEM process and try to get that token duplicated or something? I don't want to reverse engineer the PsExec tool or one of the others doing exactly this.
Typically you would install and launch a service, configured to log in as SYSTEM. You can then use OpenProcessToken and DuplicateTokenEx to make a copy of the token.
You will probably need to use SetTokenInformation to change the session ID for the token to match that of the interactive user. You need Act As Part Of the Operating System privilege to do that, so you should do this from inside the service itself. Once the duplicate token is ready to use, you can use DuplicateHandle to copy the handle into the administrative process, or (with the right options) you could launch the command shell directly from the service too.
alternative open the winlogon process with maximum permitted access, try to open the process token, (also with maximum permitted) and then try to duplicate this winlogon handle with impersonate rights. On win8.1 this will succeed. On others, you will need to temporary change the token dacl, with either a null or your own admin process token

Windows API for Creating User Profile

I'm trying to find the Window API for creating user profile.
I'm creating local user in windows, and i'm trying to run process with this user using CreateProcessWithLogonW with LOGON_WITH_PROFILE flag set.
Since the profile does not exist (the user was not interactively logged on yet) the CreateProcessWithLogonW fails.
When performing interactive logon with this user and then running the program it works.
Anyone knows how can I create user profile using Win32 API?
Thanks!
Lior
Try with User Profiles API (see http://msdn.microsoft.com/en-us/library/bb776901.aspx). On Vista and later you can use CreateProfile. On old systems you can use LogonUser and LoadUserProfile, UnloadUserProfile (see http://msdn.microsoft.com/en-us/library/bb762281.aspx).

On Terminal Server, how does a service start a process in a user's session?

From a Windows Service running on a Terminal Server (in global space), we would like to be able to start up a process running a windows application in a specific user's Terminal Server sessions.
How does one go about doing this?
The Scenerio: the windows service starts at boot time. After the user has logged into a Terminal Server user session, based on some criteria known only to the windows service, the windows service wants to start a process in the user's session running a windows application.
An example: We would like to display a 'Shutdown in 5 minutes' warning to the users. The windows service would detect this condition, and start up a process in each user session that starts the windows app that displays the warning. And, yes, I know there are other ways of displaying a warning dialog, this is the example, what we want to do is much more invasive.
You can use CreateProcessAsUser to do this - but it requires a bit of effort. I believe the following steps are the basic required procedure:
Get the user's session (WTSQuerySessionInformation).
Get a token for that user (WTSQueryUserToken).
Create a duplicate token for your use (DuplicateTokenEx).
Use the token to create an environment block (CreateEnvironmentBlock).
Launch the application with CreateProcessAsUser, using the block above.
You'll also want to make sure to clean up all of the appropriate handles, tokens, etc., after you've launched the process.
Really late reply but maybe somebody will find this helpful.
You can use PsExec to launch an application on a remote (or local) server inside a specified session by using the following command:
psexec \\COMPUTER_NAME -i SESSION_ID APPLICATION_NAME
Where SESSION_ID indicates the session id in which to launch the application.
You will need to know what sessions are active on the server and which session id maps to which user login. The following thread provides a nice code sample for this exact problem: How do you retrieve a list of logged-in/connected users in .NET?
Late reply but in the answer above DuplicateToken is not necessary since WTSQueryUserToken already returns a primary token.

Resources