MSDN说OpenProcess()
必须返回有效的句柄,或者错误时返回NULL。
然而,我在Win7 x64(以及Win 8.1 x86,Win XP x64,Win Vista x64)上遇到了罕见的情况,其中OpenProcess()
为当前进程返回-1,即伪句柄,而我枚举过程。它很少偶尔发生(当我在不同的平台上运行我的测试套件时)。我无法在Win 10上重现它。
然后CloseHandle()
在此句柄上失败并出现ERROR_INVALID_HANDLE
错误。但另一方面,MSDN表示
不再需要时,不需要关闭伪句柄。 使用伪句柄调用CloseHandle函数无效。
为什么会这样?这是OpenProcess()
的正确行为吗?
以下是我的代码示例:
HANDLE snap = CreateToolhelp32Snapshot (TH32CS_SNAPPROCESS, 0);
PROCESSENTRY32 prEntry = {};
prEntry.dwSize = sizeof (PROCESSENTRY32);
if (Process32First (snap, &prEntry))
{
do
{
if (prEntry.th32ProcessID)
{
HANDLE h = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, prEntry.th32ProcessID);
// <<<< from time to time h is (-1) here when meets the current process
if (h)
{
wchar_t imageFilename[MAX_PATH + 1] = {};
if (GetProcessImageFileName(hProc, imageFilename, MAX_PATH))
{
// do something
}
if (!CloseHandle(h))
{
// CLoseHandle returns FALSE on pseudo handle (at least on Win 7)
DWORD err = ::GetLastError();
// err == 0x6, i.e. ERROR_INVALID_HANDLE, for the pseudo handle
// << create a memory dump here for further analysis
}
}
}
}
while (Process32Next (snap, &prEntry));
}
UPD:我发现为什么我的测试在Win 10平台上永远不会失败 - CloseHandle(HANDLE(-1))
总是在Win 10上返回TRUE
,而在Win 7上它返回FALSE
并出现0x6错误。但我仍然没有解释OpenProcess()
行为。
解决方案:正如Ben Voigt所说(参见接受的答案),测试环境中有一个钩子,在之前的测试套件运行后没有清除。经过几天的调试,找到并定位了钩子,修复了测试套件以清理钩子。现在OpenProcess调用正常工作。
答案 0 :(得分:2)
最可能的解释是写得不好的OpenProcess
钩子,例如反恶意软件和恶意软件都使用这种钩子。
这个钩子的作者没有仔细阅读OpenProcess
文档,当真正的Windows OpenProcess
成功但钩子想要阻止你的访问时,它正在做
return INVALID_HANDLE_VALUE;
(这也可能是写CreateFile
挂钩的复制/粘贴错误)
由于这样的钩子主要用于rootkit - 这两个&#34; evil&#34;和"good" (but accidentally evil anyway)种类,你可能无法从系统内部确认钩子。另一方面,内核调试器连接应该表明在实际的Windows OpenProcess执行期间,返回地址是钩子代码,而不是内核转换存根。