How to start process in session before user logs on?

I have a need to start a process in a session before the user logons on. On XP I used a Windows Logon Notification Package to do this. When a new session was created, Winlogon.exe in that new session called my WLNP and it was able to start the process before the user logged on. The process is used to support smart card logons for that session.

I'm trying to find out how to do something similar on Vista. I know logon notification packages are no longer supported. I know how to write a service to get session creation notification, but I don't know how to start a process in the new session before the user logs on.

Is there a function I can use to start a process in another session? If so, I could have my session tracking sevice start the process in the new session. I haven't found such a function.

I could write a credentials provider to start the process when the user hits CTRL-ALT-DEL, but I want the process started before the user takes any action because the process takes a few seconds to initialize and only starting it after the user hits CTRL-ALT-DEL would insert an undersirable delay into smart card logon.

Is there any mechanism that I can use to get code executed in a new session soon after that new session is created, before the user logs on or hits CTRL-ALT-DEL?

Thanks,

Jim Miller

[1354 byte] By [JamesPMiller] at [2007-12-27]
# 1

Couple questions first, if you don't mind:
How do you get session creation notification?
Why do you need a process in that session for smartcard logon?

EricPerlin at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 2

>How do you get session creation notification?

Well, I don't really. I just loop calling WTSEnumerateSessions to see if a new session has been created. It's crude, but it works. It would be better if the SERVICE_CONTROL_SESSIONCHANGE mechanism would tell you when new sessions are created, but it doesn't.

>Why do you need a process in that session for smartcard logon?

It not required, just something I'm trying to do.

I'm going to see if I can achieve my goal using a combination of OpenProcessToken, SetTokenInformation, and CreateProcessWithTokenW. I'll post here if it works.

JamesPMiller at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 3

I was curious, just in case of something "creative".
With real scenarios, it could be considered in a future release.

You'll need TCB for this, but OpenProcessToken, DuplicateTokenEx, SetTokenInformation and CreateProcessAsUser should get you going.

EricPerlin at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 4

>You'll need TCB for this, but OpenProcessToken, DuplicateTokenEx, SetTokenInformation

> and CreateProcessAsUser should get you going.

I got it working! Here's what I did in a nutshell:

When I detect that a new session has been created I

  1. Use WTSEnumerateProcesses to find the process id of winlogon.exe in the new session.
  2. Use AdjustTokenPrivileges to give my session monitoring service SE_TCB_NAME privilage
  3. Call OpenProcess to get a handle to winlogon.exe process in new session
  4. Call OpenProcessToken to get winlogon.exe's access token.
  5. Call DuplicateTokenEx to make a new access token
  6. Call CreateProcessAsUser to start my process in the new session before user logs on.

RIght now my process runs as SYSTEM and it doesn't need to. I'm going to play around with the above a bit to see if I can get it to run as something else.

Jim

JamesPMiller at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 5

I guess that works too but it's not quite what I meant.
Since you duplicate winlogon's token (which is already running in that session), you don't need to set the session id.
You may not even need TCB with your procedure, but probably require SYSTEM for the OpenProcess* calls anyway.

You could have duplicated your own process token, set the session id in the duped token and proceeded to step 6.
It's probably fairly equivalent.

EricPerlin at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 6

When I Use WTSEnumerateProcesses API in my service, an error occurs. The error code is 1702 (The binding handle is invalid).

My code is like

WTSEnumerateProcesses(WTS_CURRENT_SERVER_HANDLE, ... ...

what's wrong?

virtualice at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 7

I have found that, after a reboot, the terminal services sub-system takes a while to finish initializing. You will get the 'binding handle is invalid' error until the TS sub-system is done initializing. I think there is a global event handle you can wait on to learn when TS is done initializing, but I don't remember what it is.

Anyone out there remember what it is?

JamesPMiller at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 8

This procedure is pretty inefficient in the first place. You have to wait for TS to be up, enumerate processes, find the right one, ...
The one I outlined (duplicate your own service process token, set the session id using SetTokenInformation with TokenSessionId) has none of these drawbacks.

What am I missing?

EricPerlin at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 9
You're right. Your way is better and I plan to switch over to it went I get back to working on this.
JamesPMiller at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 10

Hi Eric, I have read your posts here and tried to recreate some of the suggestions on XP in anticipation of going to Vista soon. My problem is that whenever I use CreateProcessAsUser to start a process in another session I get error 2 - "The system cannot find the file specified". I think my use of CPAU is OK as it works fine if I use it based on a handle extracted from a process owned by the user of the console session. I can get processes owned by system and any other user working in Session 0 but I can't get a process to start in another FUS session.

If I use the SYSTEM process token, duplicate it, add the different session ID then use CPAU then I get error 2. Also, if I use the handle from the Explorer.exe process in the other session I also get error 2. Do you know if there is some kind of permissions that need to be set even though all the code is running as a SYSTEM user (either via a service or using PSEXEC from sysinternals).

Thanks,

Jeremy

JeremyPWood at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 11

Prior to Vista, there's a known limitation of CPAU (CreateProcessAsUser):
It doesn't work cross-session (typically from 0 to non 0) until a user logs on to that non 0 session...
If I remember correctly, the "expected" error code in that case is 2.

EricPerlin at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 12

Eric, thanks for your reply.

I have now tried my code on vista and have no problem whatsover starting processes in other sessions. CPAU certainly seems to work more as expected on Vista than it does on XP when going across sessions.

JeremyPWood at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 13
Hi, James.

You said,

" It would be better if the SERVICE_CONTROL_SESSIONCHANGE mechanism would tell you when new sessions are created, but it doesn't."

See http://forums.microsoft.com/MSDN/ShowPost.aspx?PageIndex=2&SiteID=1&PostID=1057473

Per this thread, I would expect you could register your service for session

change notifications by calling SetServiceStatus() with the SERVICE_ACCEPT_SESSIONCHANGE flag. In that way, I would expect that your service would be notified of all SERVICE_CONTROL_SESSIONCHANGE notifications, and you would know a new session was starting if the event

type was set to WTS_CONSOLE_CONNECT or WTS_REMOTE_CONNECT.

Did you happen to try this? Very soon I will have need of implementing the same functionality you did, whereby I launch a process in a newly-created session prior to user logon. Like you said, a scheme for handling this other than polling would be nice. :-)

Thanks,

-IAmHe

iamhe at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...
# 14

The connect messages are actually reconnect messages.
They occur after user authentication when a user is reconnected to an existing session.
If the user didn't have one, a logon would occur instead.

If you're only interested in the creation of a new session at the physical console, then you can monitor logoffs and disconnects.
Shortly after either of these, a new session will be created.

I'm a little curious about the scenario requiring the creation of a per-session process prior to logon.
Can you share some more details?

EricPerlin-MSFT at 2007-9-3 > top of Msdn Tech,Software Development for Windows Vista,Security for Applications in Windows Vista...

Software Development for Windows Vista

Site Classified