【问题标题】:Windows Vista/Windows 7 privilege: SeDebugPrivilege & OpenProcessWindows Vista/Windows 7 权限:SeDebugPrivilege & OpenProcess
【发布时间】:2011-02-25 07:45:59
【问题描述】:

我所能找到的关于升级到满足我需要的适当权限的所有内容都与我当前的方法一致,但问题仍然存在。我希望也许有人有一些 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 错误。这在以受限用户身份运行(如预期的那样)和以管理员身份显式运行(右键单击 → 以管理员身份运行 以及从管理员级别命令提示符运行时)都会发生。 p>

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

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

踢球者

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

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

注意事项

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

如果调用者启用了 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 下正确打开另一个进程(假设可执行文件已正确“以管理员身份运行”编辑)可能缺少的可能权限、特权、权限等有一些了解以上条件,不胜感激。

如果我不是完全被难住了,我就不会在这里,但我希望该团队的经验和知识再次闪耀。我感谢您花时间阅读这堵文字墙。感谢您的善意,感谢您是让 StackOverflow 对所有人如此有用的人!

【问题讨论】:

  • 好的,现在那是个问题。
  • 如果你想要的只是从进程内存中读取,你可能会要求一个特定的权利,而不仅仅是 PROCESS_ALL_ACCESS(我知道这不是问题的重点)
  • @Anders 根据 MSDN,如果基本进程启用了SeDebugPrivilege,则无论请求的访问权限如何,OpenProcess 都应该工作。要将其减少到必要的访问权限PROCESS_VM_READ 仍然需要SeDebugPrivilege 才能工作,所以我不确定结果是否会有所不同(除非 MSDN 文档有误,这并非不可能)。
  • 哪些进程无法打开?许多安全软件使用内核模式挂钩来阻止对其进程的访问。如果不是这样,那么问题进程的令牌中的 SID 可能有问题。您将不得不在有问题的机器上运行 Process Explorer 以获得一些答案。
  • AdjustTokenPrivileges 成功了吗?如果是这样,您仍然需要检查 GetLastError,因为它可以返回 ERROR_NOT_ALL_ASSIGNED。如果发生这种情况,则出于某种原因,进程令牌中不存在 SeDebugPrivilege。您是否在此代码中进行任何模拟?确保管理员组在本地安全策略中被授予调试权限(这是默认设置)。

标签: c++ windows uac privileges openprocess


【解决方案1】:

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

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


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

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

编辑: Impersonate SYSTEM (or equivalent) from Administrator Account



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

【讨论】:

  • 您说您不知道如何将特权添加到现有令牌:AdjustTokenPrivileges 不应该这样做吗?显然,这仅在启用特权并且现有令牌根本没有它时才有效。
  • @romkyns: AdjustTokenPrivileges,据我所知,仅允许启用、禁用或删除访问令牌中的权限。但是,如果权限本身完全从访问令牌中丢失(或已被删除),AdjustTokenPrivileges 将无法添加丢失的权限。
  • 你能给我一份 RunWithDebugEnabled 的副本吗?来源是否可用?这听起来很酷,可以节省我一些时间。
  • 可能我的问题和你的一样。尽管我设置了SeDebugPrivilege 并正确使用了PROCESS_ALL_ACCESS,但在以管理员身份运行应用程序的读取内存时,我总是收到Access is denied. 错误。你说的我不熟悉。什么是RunWithDebugEnabled 应用程序?我搜索了一下,什么也没找到。我同意@test。可以和我们分享一下吗?
  • 我意识到我参加这个聚会迟到了。如果您正在寻找与 RunWithDebugEnabled 大致等效但希望将新进程作为原始进程的子进程(即不是系统服务的子进程)启动的方法,现在有一种方法可以做到这一点:github.com/cubiclesoft/createprocess-windows跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2011-07-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-01-11
  • 1970-01-01
  • 2011-01-04
相关资源
最近更新 更多