Windows Vista/Windows 7 权限:SeDebugPrivilege 和 OpenProcess
-
05-10-2019 - |
题
我所能找到的有关升级到适合我的需要的权限的所有内容都与我当前的方法一致,但问题仍然存在。我希望也许有人有一些 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 上正确打开另一个进程(假设可执行文件已正确“以管理员身份运行”),我们将不胜感激。
如果我不是完全被难住了,我就不会在这里,但我希望该团队的经验和知识再次闪耀光芒。我感谢您花时间阅读这面文字墙。良好的意愿是值得赞赏的,感谢您让 Stack Overflow 对所有人如此有用!
解决方案
因此,经过大量调试并麻烦了很多人获取信息后,我终于找到了编写该代码的人 RunWithDebugEnabled
应用程序并了解其运作方式的概要。
在这种情况下,问题在于 Debug programs
域管理员的本地策略中的特权已被删除,因此 SeDebugPrivilege
进程的访问令牌中不存在令牌。如果它根本不存在,则无法启用它,而且我仍然不知道如何将权限添加到现有的访问令牌。
目前的魔法是如何运作的:
所以 RunWithDebugEnabled
magic 应用程序将使用其管理员权限将自身安装为服务并自行启动,从而在 SYSTEM
用户帐户而不是域管理员。和 SYSTEM
权限,然后应用程序创建一个与管理员令牌相同的新访问令牌,仅具有 SeDebugPrivilege
存在令牌。这个新令牌用于 CreateProcessAsUser()
并使用新启用的运行程序 SeDebugPrivilege
以前失踪了。
我实际上不喜欢这里的“解决方案”,并且一直在继续寻找一种“更干净”的方式来获得此特权。我将把这个问题作为另一个问题发布在这里,我会尽量记住链接到这里,以帮助其他人跟进并供将来参考。
我感谢大家花费时间和精力来帮助调试和解决这个问题。真的非常感谢!