我所找到的有关提升权限以满足我的需求的所有信息都与我的当前方法相符,但问题仍然存在。我希望也许有人对Windows Vista / Windows 7内部有一些经验可以在黑暗中照亮一些光芒。我相信这会变得很长,请耐心等待。
我正在开发一个需要访问当前计算机上其他进程内存的应用程序。这显然需要管理员权限。它还需要SeDebugPrivilege
(不,这不是SetDebugPrivilege
的拼写错误),我认为自己正确地获取了这个权限,尽管我怀疑是否需要更多的权限,因此导致了我的问题。代码迄今为止已成功运行在所有版本的Windows XP上,并且在我的测试Vista 32位和Windows 7 64位环境中也成功运行。
在整个过程中:
- 程序将始终使用管理员权限运行。这可以在本文中假定。
- 提升当前进程的访问令牌以包括
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
似乎存在特权/权限问题,并出现通用的访问被拒绝
错误。这会在作为有限用户(预期)运行时和显式作为管理员运行(右键单击→以管理员身份运行)以及从管理员级别命令提示符中运行时发生。
但是,在我的测试环境中,这个问题是无法再现的。我亲眼目睹了这个问题,所以我相信它确实存在。我所能分辨的实际环境和我的测试环境之间唯一的区别是,实际错误是在UAC提示框内使用域管理员帐户时发生的,而我的测试(没有错误)在UAC提示框内使用本地管理员帐户。
看起来使用的凭据虽然允许UAC“以管理员身份运行”,但该进程仍未获得正确的权限,无法在另一个进程上调用OpenProcess
。我对Vista/Windows 7的内部不熟悉,不知道可能是什么问题,希望有人能想到可能的原因。
重点
报告此错误的人,并且可以定期复制此错误的环境,拥有一个名为RunWithDebugEnabled
的小应用程序,它是一个小型引导程序,似乎升级了自己的权限,然后启动传递给它的可执行文件(从而继承了提升的权限)。当使用相同的域管理员凭据在UAC提示时运行此程序时,程序可以正确工作并成功调用OpenProcess
并按预期操作。
因此,这明显是获取正确权限的问题,并且已知域管理员帐户确实是应该能够访问正确权限的管理员帐户。(显然,如果可以获取此源代码,那将很好,但如果可能的话,我就不会在这里了)。
注释
如上所述,失败的OpenProcess
尝试报告的错误为“访问被拒绝”。根据OpenProcess
的MSDN文档:
如果调用方启用了SeDebugPrivilege特权,则无论安全描述符的内容如何,都将授予请求的访问权限。
这使我相信,在这些情况下可能存在问题,或者(1)获取SeDebugPrivilege
或(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对所有人如此有用的人!
OpenProcess
应该可以工作,无论请求的访问权限如何,只要基本进程启用了SeDebugPrivilege
。为了将其减少到必要的访问权限,PROCESS_VM_READ
仍需要SeDebugPrivilege
才能工作,因此我不确定结果是否会有任何不同(除非MSDN文档是错误的,这并非不可能)。 - KevenK