Windows Vista / Win7权限问题:SeDebugPrivilege&OpenProcess

我所能find的关于升级到适合我需要的特权的一切都与我目前的方法一致,但存在问题。 我希望也许有人有一些Windows Vista / Win7的内部经验,可能会发光的地方,只有黑暗的光线。 我相信这会很久,但请和我一起裸露。

背景
我正在开发一个应用程序,需要访问当前机器上其他进程的内存。 显然,这需要pipe理员权限。 这也需要SeDebugPrivilege ,我相信自己正确地获得,虽然我质疑是否有更多的特权是不必要的,因此我的问题的原因。 代码至今在所有版本的Windows XP,以及我的testingVista32和Win7x64环境中都能够成功运行。

处理:

  • 程序将始终以pipe理员权限运行。 这可以假设贯穿这篇文章。
  • 升级当前进程的Access Token以包含SeDebugPrivilege权限。
  • 使用EnumProcesses在系统上创build当前PID的列表
  • 使用OpenProcessPROCESS_ALL_ACCESS访问权限打开一个句柄
  • 使用ReadProcessMemory读取另一个进程的内存。

问题:
在开发和个人testing(包括Windows XP 32&64,Windows Vista 32和Windows 7 x64)期间,一切工作都正常。 但是,在同事的Windows Vista(32位)和Windows 7(64位)机器的testing部署过程中, OpenProcess出现通用Access Denied错误似乎存在特权/权限问题。 在以有限的用户身份运行时(如预期的那样)以及以pipe理员身份(右键单击>以pipe理员身份运行以及从pipe理员级别的命令提示符运行时)时,都会发生这种情况。

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

看起来,虽然使用的凭据允许UAC以“pipe理员身份运行”,但进程仍然没有获得能够在另一个进程上进行OpenProcess的正确权限。 我对Vista / Win7的内部知识不是很了解,所以我希望有人知道可能是什么原因。

踢球者:
报告这个错误和谁的环境的人可以定期地重现这个错误,有一个小的应用程序,名为RunWithDebugEnabled ,它是一个小的引导程序,看起来会提升自己的权限,然后启动传递给它的可执行文件inheritance升级的权限)。 在使用此程序运行时,在UAC提示符下使用相同的域pipe理员凭据,程序将正常工作,并能够成功调用OpenProcess并按预期运行。 因此,获得正确权限肯定是个问题,而且已知域pipe理员帐户一个pipe理员帐户,应该能够访问正确的权限。 (显然获得这个源代码会很好,但如果可能的话,我不会在这里)。

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

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

这使我相信,在这些情况下,(1)获取SeDebugPrivileges或(2)需要在MSDN文档中没有提到的其他特权,并且可能在域pipe理员帐户和本地pipe理员帐户

示例代码:

 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上正确打开另一个进程(假设可执行文件已经正确“以pipe理员身份运行”编辑)可能缺less的可能的权限/特权/权限等有一些了解,这将是非常感激的。 如果我不是绝对难倒,我不会在这里,但是我希望这个团队的经验和知识再次闪耀。 我感谢你花时间阅读这篇文章。 只有善意才会感激,谢谢你是那种让所有人都这么有用的人!

所以在经过大量的调试和困扰了很多人的信息后,我终于能够找到编写RunWithDebugEnabled应用程序的人,并RunWithDebugEnabled了解它的运行方式。

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

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

我其实不喜欢这个“解决方案”,而且一直在继续寻求一种“更清洁”的方式来获得这个特权。 我将在这里发布这个问题作为另一个问题,我将尽力记住在这里链接,以帮助其他人跟随和为将来的参考。

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

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