views:

805

answers:

3

Everything I've been able to find about escalating to the appropriate privileges for my needs has agreed with my current methods, but the problem exists. I'm hoping maybe someone has some Windows Vista/Win7 internals experience that might shine some light where there is only darkness. I'm sure this will get long, but please bare with me.

Context:
I'm working on an app that requires accessing the memory of other processes on the current machine. This, obviously, requires administrator rights. It also requires SeDebugPrivilege, which I believe myself to be acquiring correctly, although I question if more privileges aren't necessary and thus the cause of my problems. Code has so far worked successfully on all versions of Windows XP, and on my test Vista32 and Win7x64 environments.

Process:

  • Program will Always be run with Administrator Rights. This can be assumed throughout this post.
  • Escalating the current process's Access Token to include SeDebugPrivilege rights.
  • Using EnumProcesses to create a list of current PIDs on the system
  • Opening a handle using OpenProcess with PROCESS_ALL_ACCESS access rights
  • Using ReadProcessMemory to read the memory of the other process.

Problem:
Everything has been working fine during development and my personal testing (including Windows XP 32 & 64, Windows Vista 32, and Windows 7 x64). However, during a test deployment onto both Windows Vista(32-bit) and Windows 7(64-bit) machines of a colleague, there seems to be a privilege/rights problem with OpenProcess failing with a generic Access Denied error. This occurs both when running as a limited User (as would be expected) and also when run explicitly as Administrator (Right-click > Run as Administrator and when run from an Administrator level command prompt).

However, this problem has been unreproducible for myself in my test environment. I have witnessed the problem first hand, so I trust that the problem exists. The only difference that I can discern between the actual environment and my test environment is that the actual error is occurring when using a Domain Administrator account at the UAC prompt, whereas my tests (which work with no errors) use a local administrator account at the UAC prompt.

It appears that although the credentials being used allow UAC to 'run as administrator', the process is still not obtaining the correct rights to be able to OpenProcess on another process. I am not familiar enough with the internals of Vista/Win7 to know what this might be, and I am hoping someone has an idea of what could be the cause.

The Kicker:
The person who has reported this error, and who's environment can regularly reproduce this bug, has a small application named along the lines of RunWithDebugEnabled which is a small bootstrap program which appears to escalate its own privileges and then launch the executable passed to it (thus inheriting the escalated privileges). When run with this program, using the same Domain Administrator credentials at UAC prompt, the program works correctly and is able to successfully call OpenProcess and operates as intended. So this is definitely a problem with acquiring the correct privileges, and it is known that the Domain Administrator account is an administrator account that should be able to access the correct rights. (Obviously obtaining this source code would be great, but I wouldn't be here if that were possible).

Notes:
As noted, the errors reported by the failed OpenProcess attempts are Access Denied. According to MSDN documentation of OpenProcess:

If the caller has enabled the SeDebugPrivilege privilege, the requested access is granted regardless of the contents of the security descriptor.

This leads me to believe that perhaps there is a problem under these conditions either with (1) Obtaining SeDebugPrivileges or (2) Requiring other privileges which have not been mentioned in any MSDN documentation, and which might differ between a Domain Administrator account and a Local Administrator account

Sample Code:

void sample()
{
   /////////////////////////////////////////////////////////
   //   Note: Enabling SeDebugPrivilege adapted from sample
   //     MSDN @ http://msdn.microsoft.com/en-us/library/aa446619%28VS.85%29.aspx
   // Enable SeDebugPrivilege
   HANDLE hToken = NULL;
   TOKEN_PRIVILEGES tokenPriv;
   LUID luidDebug;
   if(OpenProcessToken(GetCurrentProcess(), TOKEN_ADJUST_PRIVILEGES, &hToken) != FALSE) 
   {
      if(LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &luidDebug) != FALSE)
      {
         tokenPriv.PrivilegeCount           = 1;
         tokenPriv.Privileges[0].Luid       = luidDebug;
         tokenPriv.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
         if(AdjustTokenPrivileges(hToken, FALSE, &tokenPriv, 0, NULL, NULL) != FALSE)
         {
            // Always successful, even in the cases which lead to OpenProcess failure
            cout << "SUCCESSFULLY CHANGED TOKEN PRIVILEGES" << endl;
         }
         else
         {
            cout << "FAILED TO CHANGE TOKEN PRIVILEGES, CODE: " << GetLastError() << endl;
         }
      }
   }
   CloseHandle(hToken);
   // Enable SeDebugPrivilege
   /////////////////////////////////////////////////////////

   vector<DWORD> pidList = getPIDs();  // Method that simply enumerates all current process IDs

   /////////////////////////////////////////////////////////
   // Attempt to open processes
   for(int i = 0; i < pidList.size(); ++i)
   {
      HANDLE hProcess = NULL;
      hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pidList[i]);
      if(hProcess == NULL)
      {
         // Error is occurring here under the given conditions
         cout << "Error opening process PID(" << pidList[i] << "): " << GetLastError() << endl;
      }
      CloseHandle(hProcess);
   }
   // Attempt to open processes
   /////////////////////////////////////////////////////////
}




Thanks!
If anyone has some insight into what possible permissions/privileges/rights/etc that I may be missing to correctly open another process (Assuming the executable has been properly "Run as Administrator"ed) on Windows Vista and Windows 7 under the above conditions, it would be most greatly appreciated. I wouldn't be here if I weren't absolutely stumped, but I'm hopeful that once again the experience and knowledge of the group shines bright. I thank you for taking the time to read this wall of text. The good intentions alone are appreciated, thanks for being the type of person that makes SO so useful to all!

A: 

Run Process Explorer and compare the security tabs for your app started with and without the RunWithDebugEnabled loader. Are they the same or is it using more than just debug privs?

Anders
Thanks for the response! I've wanted to check this myself, too, but unfortunately I do not have ready access to the environment which produces this error. Yes, this is very frustrating, especially since I can't exactly reproduce the environment in my test structure :( This is part of the reason I'm hoping someone with a deeper understanding of access/privilege tokens on Windows Vista / Win7 might already have an explanation...debugging this one is definitely under less-than-ideal circumstances.
KevenK
+1  A: 

Could the Debug programs local policy be modified on the "problem" machine?

Aaron Klotz
While it is definitely *possible*, I'm not sure that that would explain this issue fully. The privileged administrator account **is** capable of enabling the proper rights, as can be seen by the utility application used to "RunWithDebugEnabled" as mentioned in the OP. If the user is capable of doing this correctly, the solution seems to be in figuring out what's missing from the implementation of the code itself. I am fairly sure that the "RunWithDebugEnabled" code does not make modifications to the system policies, although I cannot claim it to be impossible (without source).
KevenK
You were right, the `RunWithDebugEnabled` just did some very klugey work in the background to get around this
KevenK
Is your program now able to run successfully on the problem machine, then?
Aaron Klotz
@Aaron Unfortunately, no. Please see my answer to this question, or my follow up pursuit of a better solution at http://stackoverflow.com/questions/2991957. I suppose technically I know of one solution (basically copying the 'RunWithDebugEnabled' program into my own), but I am not especially satisfied with the way it works. And I expect to get a few "well if the network administrator turned off the privilege, you shouldn't try to use it!" answers, which won't help much either :-P
KevenK
+1  A: 

So after a lot of debugging and bothering a lot of people for information, I was finally able to track down the guy who wrote the RunWithDebugEnabled application and get a rundown of how it operates.

The problem, in this case, is that Debug programs privilege in the local policy for the domain administrator had been removed, and thus the SeDebugPrivilege token was not present in the process's access token. It can't be enabled if it's not present at all, and I still know of no way to add the privilege to an existing access token.


How the current magic works:
So the RunWithDebugEnabled magic application would use its Administrator rights to install itself as a service and start itself, thus running under the SYSTEM user account rather than the Domain Administrator. With SYSTEM privileges, the app then creates a new access token that is identical to the Administrator token, only with the SeDebugPrivilege token present. This new token is used to CreateProcessAsUser() and run the program with the newly enabled SeDebugPrivilege that was missing before.

I actually do not like this "solution" here, and have been continuing my search for a 'cleaner' way to obtain this privilege. I will be posting this as another question here on SO, which I will try to remember to link here as well to help others follow along and for future reference.

EDIT: http://stackoverflow.com/questions/2991957



I thank you all for your time and energies in helping to debug and solve this problem. It really is much appreciated!

KevenK