我能够找到的关于升级到满足我需要的适当权限的所有内容都与我当前的方法一致,但问题仍然存在。我希望也许有人有一些 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 对所有人如此有用的人!