views:

35

answers:

2

When using CreateProcessAsUser we pass STARTUPINFO and with lpDesktop NULL, the target is winsta0/default, the interactive desktop of the interactive user.

I wish to target a window station in another session of a second, non-interactive user, say a remote desktop user.

I assume that it can't be winsta0 because that's reserved for the single interactive user.

I am looking at the function list here: http://msdn.microsoft.com/en-us/library/ms687107(v=VS.85).aspx

I can enumerate window stations on the machine, but how do I identify which window station is connected to which user/process/session?

Each window station is connected to a session Each process has a target window station

But how, for example if I have a process, or a session ID, do I determine which Window Station it is associated with?

A: 

You can use GetUserObjectinformation to get the SID of the user associated with that window station.

As for finding the Window Station from a process: - Get the top-level window handle for the process
- Enumerate the window stations (EnumWindowStations)
- Enumerate the desktops for each window station (EnumDesktops)
- Enumerate the windows for each desktop (EnumDesktopWindows) until you find a match.

Yeah, it's not a straightforward, but it should solve your problem.

Note: On Vista and Win7, the interactive user is not in winsta0. Winsta0 is reserved for the system and services only, the interactive user gets a new windows station and is treated the (mostly) same way as a TS users.

Franci Penov
That works fine and gives me the names of the Winstation and Desktop. I can extract the pid from the Hwnd of EnumWindows viaGetWindowThreadProcessId. I have an issue obtaining a handle to the WindowStation. The callback from EnumWindowStations only returns a name, no handle
BillyG
On Win7, EnumWindowStations run from a service, after I have switched user (multiple user switching) only seems to enumerate Winsta0 which is obviously not an interactive or non-interactive user. According to http://msdn.microsoft.com/en-us/library/ms682644(VS.85).aspx and http://msdn.microsoft.com/en-us/library/ms687391(v=VS.85).aspx the service should be able to enumerate all window stations on the box?
BillyG
Further to above, from EnumWindowStations, I can only Enumerate WinSta0 and various service and mswindowstations. No user windowstations. Plus, According to the docs for OpenWindowStation, it only works for the current session. This seems to mean it is technically unable to open anything other than the first station. I seem to be unable to open any other stations than WinSta 0. http://msdn.microsoft.com/en-us/library/ms684339(v=VS.85).aspx.
BillyG
If you look at the documentation for EnumWindowsStation and OpenWindowStation, the account that attempts to use these two APIs, needs to have specific rights (WINSTA_ENUMERATE for enum and proper rights in the station ACL for open).
Franci Penov
Note that enumerating window stations works for the current session only. You need to CreateProcessAsUser (http://msdn.microsoft.com/en-us/library/ms682429(VS.85).aspx) to inject your process in another session for a particular user. note that you have to explicitly specify `""` (empty string) as desktop name in your call, otherwise the process will be launched in the context of the window station of the launching process.
Franci Penov
It is possible to GetThreadDesktop(threadOfTargetProcess) to obtain a handle to the desktop for the process, and then GetUserObjectInformation to obtain desktop handle. However, the corresponding GetProcessWindowStation accepts no arguments. How would it be possible to trace the window station for the specified desktop handle (or name?)
BillyG
I note that Sysinternals Process Explorer (ran elevated) displays the windowstation for the process, in the format: \\Windows\WindowStations\\WinSta0 (for xp) or on Win7 \Sessions\1\Windows\WindowStations\\WinSta0. Even with multiple users logged-in, they all seem to have Explorer.exe in WinSta0. The question is how to obtain the same information from the process, that ProxExp finds?
BillyG
A: 

On WinXP/Win2K3 or higher, you could do the following:

  1. Call WTSEnumerateSessions to get a list of active session information (which will also give you the window station name associated to each session).
  2. Pass the session id to WTSQueryUserToken.
  3. Pass the token to GetTokenInformation to get the user's SID.
  4. Pass the user's SID to LsaLookupSids to get the user and domain names.

Also, if you want to identify which session is the active console session, you can compare the session id to the return value of WTSGetActiveConsoleSessionId.

However, I would recommend using the token returned from WTSQueryUserToken to launch a process on the target desktop via CreateProcessAsUser, as Franci mentioned. You'll have to pass it through DuplicateTokenEx to convert it from an impersonation token to a primary token, but it works on WinXP or higher, and Microsoft documents it as the "preferred" way to launch interactive applications from the services desktop on Vista and higher.

Javert93