Solved

Question for JKR, ImpersonateInteractiveUser() does not work after SP4...

Posted on 2004-03-31
11
669 Views
Last Modified: 2008-02-01
JKR or to whom anyone who has an answer,

About 1 week ago I posted a question asking how to impersonate the interactive user so I could launch a process that wrote to the users desktop.  Well during testing I was getting some inconsistent results, after an extremely long amount of testing I figured out it was Windows 2000 SP4 breaks it, most likely its something microsoft has tightened down on to make the system more secure, I believe my weakness relies in how I am obtaining the Process ID of the interactive user, however I have not done enough testing to verify this.  The below code is the ENTIRE snippet I am using to Impersonate the interactive user.  Do you have any information regarding any new methods of doing this after SP4?

NOTE: Works fine in WindowsXP with all SP/Patches...

DWORD ImpersonateInteractiveUser()  //Impersonates the logged in user to create an instance in the users context...
{
      HANDLE hToken = NULL;                
      HANDLE hProcess = NULL;

      DWORD processID = GetExplorerProcessID();
      if( processID)
      {
            hProcess =
                  OpenProcess(  
                  PROCESS_ALL_ACCESS,
                  TRUE,
                  processID );

            if( hProcess)
            {
                  if( OpenProcessToken(
                        hProcess,
                        TOKEN_EXECUTE |
                        TOKEN_READ |
                        TOKEN_QUERY |
                        TOKEN_ASSIGN_PRIMARY |
                        TOKEN_QUERY_SOURCE |
                        TOKEN_WRITE |
                        TOKEN_DUPLICATE,
                        &hToken))
                  {
                        ImpersonateLoggedOnUser( hToken);
                        CloseHandle( hToken );
                  }
                  CloseHandle( hProcess );
            }
      }
      return processID;
}

DWORD GetExplorerProcessID()  //Needed to impersonate the logged in user...
{
      HANDLE hSnapshot;
      PROCESSENTRY32 pe32;
      ZeroMemory(&pe32,sizeof(pe32));
      DWORD temp = NULL;

      try
      {
            hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS,NULL);

            pe32.dwSize = sizeof(PROCESSENTRY32);

            if(Process32First(hSnapshot,&pe32))
            {
                  do
                  {
                        if(!strcmp(pe32.szExeFile,"explorer.exe"))
                        {
                              temp = pe32.th32ProcessID;
                              break;
                        }

                  }while(Process32Next(hSnapshot,&pe32));
            }
      }
      catch(...)
      {
            StopService();
      }
      return temp;
}
0
Comment
Question by:Magadass
  • 7
  • 3
11 Comments
 

Author Comment

by:Magadass
Comment Utility
I believe I answered my own question:

http://support.microsoft.com/default.aspx?kbid=821546

But have yet to get this to make it work, but it does appear there are changes...
0
 

Author Comment

by:Magadass
Comment Utility
OK I cannot get these changes to make this work, perhaps this is only part of the solution maybe something has to be changed in the code as well?
0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
The article lists only a new privilege - have you tried to grant that to the account your application is running under?
0
 

Author Comment

by:Magadass
Comment Utility
Yes it does not fix it...  I have tested the code also, everything is returning successful... Have no idea why its not working....According to the article it should work if I change the policy...

0
 

Author Comment

by:Magadass
Comment Utility
JKR have you been able to duplicate this?  This is a serious issue for me and all of the microsoft documentation I find says that changing this policy should correct the proble.  However it does not!!  
0
Maximize Your Threat Intelligence Reporting

Reporting is one of the most important and least talked about aspects of a world-class threat intelligence program. Here’s how to do it right.

 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>JKR have you been able to duplicate this?

Just me and a laptop with XP here at the moment, sorry :o)
0
 

Author Comment

by:Magadass
Comment Utility
Microsoft VirtualPC is your friend :)
0
 

Author Comment

by:Magadass
Comment Utility
I have opened a ticker with microsoft premier support, I will post the resolution as soon as I get one...
0
 

Accepted Solution

by:
Magadass earned 0 total points
Comment Utility
I have resolved this issue with the support from Microsoft Premier Support, JKR please take notice to the gotchas at the bottom.  The method for obtaining the PID of explorer.exe will not work within terminal services, also the impersonation code you provided to me is still functioning after SP4, it was part of my code that needed to be resolved, you have to use CreateProcessAsUser now due to security restrictions microsoft is implementing to make windows more secure in nature.

Hi Eric,

I have been in discussions with #### in regards to your issue with SHAppBarMessage().  Based on the information, I have reviewed, Are you doing the following:


1. The AppBarUI Application is being launched by the service with CreateProcess().  

2. Before calling CreateProcess(), you obtain the token of explorer and impersonate the Explorer (the "Interactive User").  

3. The assumption is that the AppBarUI will run in the security context of the "Interactive User".

 

The assumption is not correct, the AppBarUI will run under the context of the calling process which in this case is the service running in the LocalSystem security context.

 

You will need to launch the process with CreateProcessAsUser() using the token obtained from ImpersonateInteractiveUser().  You won't have to worry about security to winsta0\default since the security has already been granted for the "Interactive User".

 

The code will look like:

 

si.cb = sizeof(si);
si.lpDesktop = "winsta0\\default";

 

CreateProcessAsUser(hToken, ....);

 

This code will make AppBarUI run in the same security context as the "Interactive User".  

 

I'm assuming you are not running on Terminal Server and you have found the correct explorer.exe for the "Interactive User".  

 

I would also like to mention that we don't recommend launching interactive processes from a service.  The preferable solution would be to have a background process launched by the "interactive user" which would communicate with the service and the background process would launch processes on behalf of the service.

 

Another alternative would be to use the CreateProcessWithLogonW() API but this requires the password of the "Interactive User".  On Windows Server 2003, we do have the API CreateProcessWithTokenW which does accept a token. [but there is an issue with calling this API from the LocalSystem Security Context, this also applies to CreateProcessWithLogonW()]  The only reason I recommend these APIs is that they properly deal with the issues of launching processes interactively.

GOTCHAS:

1. The technique for obtaining the PID for explorer.exe is NOT robust.  The code doesn't take into account the possiblity of multiple instances of explorer.exe running on the system under different security contexts.  A simple example of this scenario is terminal server.

2. Services should not be launching interactive processes in general.  This will not be supported in the future.  If it is necessary to launch a process from a service, CreateProcessWithLogonW() or CreateProcessWithTokenW() would be better.



0
 
LVL 86

Expert Comment

by:jkr
Comment Utility
>>JKR please take notice to the gotchas at the bottom

Thank you *very* much for sharing this insight!
0

Featured Post

How to improve team productivity

Quip adds documents, spreadsheets, and tasklists to your Slack experience
- Elevate ideas to Quip docs
- Share Quip docs in Slack
- Get notified of changes to your docs
- Available on iOS/Android/Desktop/Web
- Online/Offline

Join & Write a Comment

Written by John Humphreys C++ Threading and the POSIX Library This article will cover the basic information that you need to know in order to make use of the POSIX threading library available for C and C++ on UNIX and most Linux systems.   [s…
C++ Properties One feature missing from standard C++ that you will find in many other Object Oriented Programming languages is something called a Property (http://www.experts-exchange.com/Programming/Languages/CPP/A_3912-Object-Properties-in-C.ht…
The viewer will learn how to user default arguments when defining functions. This method of defining functions will be contrasted with the non-default-argument of defining functions.
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.

762 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

6 Experts available now in Live!

Get 1:1 Help Now