Solved

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

Posted on 2004-03-31
11
679 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
ID: 10723960
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
ID: 10724297
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
ID: 10725700
The article lists only a new privilege - have you tried to grant that to the account your application is running under?
0
Independent Software Vendors: We Want Your Opinion

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 

Author Comment

by:Magadass
ID: 10726934
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
ID: 10733625
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
 
LVL 86

Expert Comment

by:jkr
ID: 10734670
>>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
ID: 10735629
Microsoft VirtualPC is your friend :)
0
 

Author Comment

by:Magadass
ID: 10735632
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
ID: 10847331
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
ID: 10847351
>>JKR please take notice to the gotchas at the bottom

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

Featured Post

Free Tool: Path Explorer

An intuitive utility to help find the CSS path to UI elements on a webpage. These paths are used frequently in a variety of front-end development and QA automation tasks.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Errors will happen. It is a fact of life for the programmer. How and when errors are detected have a great impact on quality and cost of a product. It is better to detect errors at compile time, when possible and practical. Errors that make their wa…
This article shows you how to optimize memory allocations in C++ using placement new. Applicable especially to usecases dealing with creation of large number of objects. A brief on problem: Lets take example problem for simplicity: - I have a G…
The viewer will learn how to clear a vector as well as how to detect empty vectors in C++.
The viewer will be introduced to the member functions push_back and pop_back of the vector class. The video will teach the difference between the two as well as how to use each one along with its functionality.

733 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