- LockWorkStation and ExitWindowsEx from a service
- Posted by Igor.Jovanovski@gmail.com on May 9th, 2007
We have a Credential Provider that allows a proprietery logon to
Vista. We would like to have monitoring on the smart card so that when
the user removes the card, the system could lock, log off, go to stand
by, hibernate or shut down.
Microsoft is doing that (for locking and log off only) with a service
that needs to be started on each client system.
For the purpose of that we developed a service of our own that will
monitor the smart card for removal and will get the reader name to be
monitored from the credential provider.
Now it is possible to put the system to stand by, hibernate or to shut
it down but the calls for locking:
bLocked = LockWorkStation();
and for log off:
bLogOff = ExitWindowsEx(EWX_LOGOFF | EWX_FORCE, 0);
are failing.
The reason why the locking fails is probably because of the following
as stated in the description:
"The LockWorkStation function is callable only by processes running on
the interactive desktop."
- So the question for this would be how could I make the service to
"run on the interactive desktop", or propagete the call from the
service to process that has this property?
and the reason why the logoff call fails is probably because of the
EWX_LOGOFF flag which requires:
"This flag can be used only by processes running in an interactive
user's logon session."
- So is there a way to make the service make this call in "interactive
user's logon session"?
- How can this two problems be solved?
Microsoft service can cause the system to lock or log off somehow. Is
this service sending some events to the winlogon process to perform
this, or?
- I was thinking of making a COM local server and see if I can start
it from the service but make it run in the user context. I know that
if I manage to call the two functions above from a process that runs
in user context they will do their job.
I would appreciate any hint on this.
I.
- Posted by Stefan Kuhr on May 9th, 2007
Hello Igor,
Igor.Jovanovski@gmail.com wrote:
I assume it uses WTSShutdownSystem. Have you already tried this API?
--
Stefan Kuhr
- Posted by Norman Diamond on May 10th, 2007
CreateProcessAsUser
<Igor.Jovanovski@gmail.com> wrote in message
news:1178722326.533553.112180@w5g2000hsg.googlegro ups.com...
- Posted by Uwe Sieber on May 10th, 2007
Igor.Jovanovski@gmail.com wrote:
See
http://www.microsoft.com/whdc/system..._Services.mspx
Under 'Session 0 Isolation' they suggest to use CreateProcessAsUser
as Norman did.
Under XP you get the required access token of the active user by
DWORD dwSessionId = WTSGetActiveConsoleSessionId(); // 0, 1, 2...
if ( dwSessionId == 0xFFFFFFFF ) {
// no active user
return;
}
HANDLE hToken = NULL;
WTSQueryUserToken(dwSessionId, &hToken);
HANDLE hDupToken = NULL;
DuplicateToken(hToken, SecurityImpersonation, &hDupToken);
Under W2K you have to steal the token from a process that is running
in the user's context, usually the Explorer.exe...
Greetings from Germany
Uwe
- Posted by Norman Diamond on May 10th, 2007
In Vista I did not need to call DuplicateToken.
In either XP or Vista, my understanding is that if I called DuplicateToken
then I would get an impersonation token and CreateProcessAsUser would fail.
In XP I tried calling DuplicateTokenEx to get a duplicate primary token but
CreateProcessAsUser failed anyway. So I gave up with some experiments in
XP. Anyway the original poster is dealing with Credential Providers so I
assumed he only targets Vista, and CreateProcessAsUser worked perfectly for
me in Vista.
"Uwe Sieber" <mail@uwe-sieber.de> wrote in message
news:5afvb0F2odrc6U1@mid.individual.net...
- Posted by Uwe Sieber on May 10th, 2007
Oops, you are right. DuplicateToken isn't good enough here. We
need DuplicateTokenEx with TokenPrimary for TokenType:
DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityIdentification,
TokenPrimary, &hDupToken);
I had taken the code from the wrong place, I dealed there
with impersonation only...
With DuplicateTokenEx I had no problems with CreateProcessAsUser
under W2K, XP and Vista.
Greetings from Germany
Uwe
Norman Diamond wrote:
- Posted by Igor.Jovanovski@gmail.com on May 11th, 2007
thanks all of you for your input.
How ever I still have a problem with this.
In my service I call LogonUser to get the user token and then use
CreateProcessAsUser as following:
......
bFunc =
LogonUser(user,domain,lppwdin,LOGON32_LOGON_NETWOR K,LOGON32_PROVIDER_DEFAULT,
&hToken1);
.....
STARTUPINFO sturtupInfo;
ZeroMemory(&sturtupInfo, sizeof(sturtupInfo));
sturtupInfo.cb = sizeof(sturtupInfo);
sturtupInfo.lpDesktop = TEXT("WinSta0\\default");
sturtupInfo.wShowWindow = SW_SHOW;
sturtupInfo.dwFlags = STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES;
PROCESS_INFORMATION pInfo;
BOOL bSet = CreateProcessAsUser(hToken1, L"C:\\LockWorkstation.exe",
L"", NULL, NULL, FALSE, NORMAL_PRIORITY_CLASS, NULL, NULL,
&sturtupInfo, &pInfo);
and the function suceeds and also the LockWorkstation.exe gets called.
The LockWorkstation.exe is a console app with the following code:
#include "stdafx.h"
#include "windows.h"
int _tmain(int argc, _TCHAR* argv[])
{
BOOL bSet = LockWorkStation();
if(bSet == TRUE)
MessageBox(NULL, L"Locked", L"Locked", MB_OK);
else
MessageBox(NULL, L"failed", L"failed", MB_OK);
return 0;
}
I have put the two message boxes to trace why it does not locks and
then a popup message box from windows comes stating that a interactive
service dialog has been deteced and if I want to see it. If I confirm
I see a new desktop with the cmd promt and my "Locked" message box
there. But ror some reason LockWorkstation function does not locks the
workstation despite the correct return code. Was LockWorkstation.exe
run in the user context just as if I have double cliked it? If not was
is different and how can I change that in order to get the workstation
to lock (some parameters for CreateProcessAsUser, impersonation?)? And
why do I get the message box in this new desktop?
As for the logoff scenario I will try the WTSLogoffSession function
directly from the service.
I.
- Posted by Stefan Kuhr on May 11th, 2007
Hello Igor,
Igor.Jovanovski@gmail.com wrote:
You are creating a network logon session. You cannot create UI that is
noticeable by a user unless you create an interactive logon session.
Using LogonUser will not get you anywhere in your scenario, because even
if you manage to change the session ID of the token you create via
LogonUser to one of your terminal sessions and even if you happen to use
the same user as the one logged on to that particular terminal session,
UI will not be displayed because the DACLs of the winsta and desktop
(winsta0\\default of that terminal session) have entries for the logon
session LUIDs of the interactive logon session, not for the principal
who is logged on (the logon session luids you get with LogonUser are
different than those of the logged in interactive users). The only thing
you could do is grab the token of the interactive logon session of each
teminal session via WTSQueryUserToken or to use token stealing, as
others have explained before, and use these tokens to start your process
via CPAU. Another possibility might be to duplicate your processes token
(I assume this runs as SYSTEM) and change the session ID in that
duplicate to that of your terminal session. If you use this token with
CPAU, you will get a process running as SYSTEM on your terminal session.
In the past, such processes were targets of shatter attacks, with Vista,
things should be different, however, because of UIPI.
--
Stefan Kuhr