25

我能够找到的关于升级到满足我需要的适当权限的所有内容都与我当前的方法一致,但问题仍然存在。我希望也许有人有一些 Windows Vista/Windows 7 内部经验,可能会在只有黑暗的地方发光。我相信这会很长,但请耐心等待。

语境

我正在开发一个需要访问当前机器上其他进程的内存的应用程序。这显然需要管理员权限。它还需要SeDebugPrivilege(不,这不是 的拼写错误SetDebugPrivilege),我相信自己正确地获得了它,尽管我质疑是否不需要更多特权,从而导致我的问题。到目前为止,代码已在所有版本的 Windows XP 以及我的测试 Vista 32 位和 Windows 7 64 位环境中成功运行。

过程

  • 程序将始终以管理员权限运行。在这篇文章中可以假设这一点。
  • 升级当前流程Access Token以包含SeDebugPrivilege权利。
  • 用于EnumProcesses创建系统上当前 PID 的列表
  • OpenProcess使用PROCESS_ALL_ACCESS访问权限打开句柄
  • 用于ReadProcessMemory读取其他进程的内存。

问题:

在开发和我的个人测试期间一切正常(包括 Windows XP 32 和 64、Windows Vista 32 和 Windows 7 x64)。但是,在同事的 Windows Vista(32 位)和 Windows 7(64 位)计算机上进行测试部署期间,似乎存在特权/权限问题,OpenProcess并因一般Access Denied错误而失败。这在以受限用户身份运行(如预期的那样)和以管理员身份显式运行时(右键单击 →以管理员身份运行以及从管理员级别命令提示符运行时)都会发生。

但是,在我的测试环境中,这个问题对于我自己来说是无法重现的。我亲眼目睹了这个问题,所以我相信问题存在。我可以辨别实际环境和我的测试环境之间的唯一区别是,在 UAC 提示符下使用域管理员帐户时会发生实际错误,而我的测试(没有错误)使用本地管理员帐户UAC 提示。

看来,尽管使用的凭据允许 UAC“以管理员身份运行”,但该进程仍未获得能够OpenProcess在另一个进程上运行的正确权限。我对 Vista/Windows 7 的内部结构不够熟悉,不知道这可能是什么,我希望有人知道可能是什么原因。

踢球者

报告这个错误的人,并且他的环境可以定期重现这个错误,有一个小应用程序,它的名字RunWithDebugEnabled是一个小引导程序,它似乎提升自己的权限,然后启动传递给它的可执行文件(因此继承升级的权限)。当使用该程序运行时,在 UAC 提示符下使用相同的域管理员凭据,该程序可以正常工作,并且能够成功调用OpenProcess并按预期运行。

所以这肯定是获取正确权限的问题,众所周知,域管理员帐户一个管理员帐户,应该能够访问正确的权限。(显然获得这个源代码会很棒,但如果可能的话,我不会在这里)。

笔记

如前所述,失败OpenProcess尝试报告的错误是Access Denied. 根据 MSDN 文档OpenProcess

如果调用者启用了 SeDebugPrivilege 权限,则无论安全描述符的内容如何,​​都会授予所请求的访问权限。

这使我相信,在这些条件下,可能存在问题(1)获取SeDebugPrivileges或(2)需要任何 MSDN 文档中未提及的其他权限,并且域管理员帐户和本地管理员之间可能有所不同帐户

示例代码:

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
   /////////////////////////////////////////////////////////
}



谢谢!

如果有人对在上述条件下在 Windows Vista 和 Windows 7 上正确打开另一个进程(假设可执行文件已正确“以管理员身份运行”ed)可能缺少哪些可能的权限、特权、权利等有所了解,将不胜感激。

如果我不是完全被难住了,我就不会在这里,但我希望该小组的经验和知识再次闪耀。我感谢您花时间阅读这堵文字墙。感谢您成为使 Stack Overflow 对所有人如此有用的人!

4

1 回答 1

13

因此,经过大量调试和麻烦很多人的信息后,我终于能够找到编写RunWithDebugEnabled应用程序的人并大致了解它的运行方式。

在这种情况下,问题是Debug programs域管理员的本地策略中的特权已被删除,因此该SeDebugPrivilege令牌不存在于进程的访问令牌中。如果它根本不存在,则无法启用它,而且我仍然知道无法将权限添加到现有访问令牌。


当前魔术如何工作:
因此RunWithDebugEnabled魔术应用程序将使用其管理员权限将自己安装为服务并启动自己,从而在SYSTEM用户帐户而不是域管理员下运行。使用SYSTEM权限后,应用程序会创建一个与管理员令牌相同的新访问令牌,只是该SeDebugPrivilege令牌存在。这个新令牌用于CreateProcessAsUser()和运行SeDebugPrivilege之前缺少的新启用的程序。

我实际上不喜欢这里的这种“解决方案”,并且一直在继续寻找一种“更清洁”的方式来获得这种特权。我将在 SO 上将此作为另一个问题发布,我会尽量记住在此处链接,以帮助其他人跟进并供将来参考。

编辑: 从管理员帐户模拟系统(或等效)



我感谢大家花费时间和精力帮助调试和解决这个问题。真的非常感谢!

于 2010-06-07T16:27:31.120 回答