为什么OpenProcess给了我一个非现有pid的非NULL HANDLE?

时间:2016-02-09 16:22:30

标签: c++ winapi

我尽可能地减少了代码sscce 这段代码的作用是什么:

  • 使用CreateProcess
  • 启动Windows记事本
  • 暂停。所以windows有一些时间来初始化记事本
  • 使用TerminateProcessCreateProcess获取的句柄上使用TerminateProcess取消记事本。
  • 等待进程句柄终止,因为OpenProcess是异步
  • 致电#include "stdafx.h" #include <windows.h> #include "Psapi.h" #include <TlHelp32.h> #include <iostream> #include <cassert> typedef unsigned long PID; typedef const std::string& P_PATH; // Launch an executable given by a path and set a few infomatives stuffs passed as ref parameters bool launch_process(P_PATH path, STARTUPINFO& info, PROCESS_INFORMATION& processInfo, HANDLE& hProcess, PID& pid) { setlocale(LC_ALL, "en_US.utf8"); std::wstring widestr = std::wstring(path.begin(), path.end()); const wchar_t* widecstr = widestr.c_str(); LPTSTR szCmdline = _tcsdup(widecstr); if (CreateProcess(szCmdline, NULL, NULL, NULL, false, NULL, NULL, NULL, &info, &processInfo)) { hProcess = processInfo.hProcess; pid = processInfo.dwProcessId; return true; } return false; } int main(int argc, char* argv[]) { // Setup // ----- bool OK = false; STARTUPINFO info = { sizeof(info) }; PROCESS_INFORMATION processInfo; HANDLE hProcess; PID pid = 0; // launch notepad // -------------- OK = launch_process("C:\\WINDOWS\\System32\\notepad.exe", info, processInfo, hProcess, pid); assert(OK); // wait a bit // ---------- system("PAUSE"); SetLastError(0); // get Handle on notepad // --------------------- hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, false, static_cast<DWORD>(pid)); std::cout << "Error: " << GetLastError() << std::endl; // Kill notepad // ------------ UINT exitCode = 0; DWORD dwWaitResult = 0; SetLastError(0); OK = TerminateProcess(hProcess, exitCode); std::cout << "Error: " << GetLastError() << std::endl; // ensure everything went well ( we need to wait because TerminateProcess is asynchronous ) if (!OK || (dwWaitResult != WaitForSingleObject(hProcess, INFINITE))) return -1; // Cleanup CloseHandle(hProcess); CloseHandle(processInfo.hProcess); CloseHandle(processInfo.hThread); hProcess = nullptr; processInfo.hProcess = nullptr; // Ya know what let's reopen the pid I just killed // ( you can see that notepad was started then killed, you can check the pid does not exist in either the task manager or processExplorer ) SetLastError(0); hProcess = OpenProcess(PROCESS_TERMINATE | SYNCHRONIZE, false, static_cast<DWORD>(pid)); std::cout << "Error: " << GetLastError() << std::endl; // Yeah I can speak to the deads! if (hProcess != nullptr) { LPWSTR szProcessName = L""; GetModuleFileNameEx(hProcess, NULL, szProcessName, sizeof szProcessName); char c_szText[MAX_PATH]; wcstombs(c_szText, szProcessName, wcslen(szProcessName) + 1); // But the deads have no names std::cout << "Error: " << GetLastError() << std::endl; std::cout << "Zombie Name: " << c_szText << std::endl; } return 0; } on dead pid
  • 和我的僵尸一起玩......

您可以在调试中轻松检查(在OpenProcess之前),在任务管理器或processExplorer中找不到给定的Pid。但是没有其他Windows API函数似乎接受这个Pid

vec4 ArrayTextureBlend(in vec3 texCoord)
{
  float frac = fract(texCoord.z);
  texCoord.z = floor(texCoord.z);
  vec4 top = texture(arrayTex, texCoord);
  vec4 bottom = texture(arrayTex, texCoord + vec3(0, 0, 1));
  return mix(top, bottom, frac); //Linearly interpolate top and bottom.
}

1 个答案:

答案 0 :(得分:9)

  1. 它没有出现在任务管理器的进程列表中,因为它已终止。任务管理器不显示僵尸(此行为不同于例如显示僵尸的Linux ps -Af f)。

  2. 它仍然存在并且OpenProcess可以访问,因为进程对象尚未被破坏,即它处于僵尸状态。这将是因为另一个进程有一个开放的句柄。例如,

    • 一个防病毒软件,它可以调用OpenProcess获取信息以评估该应用程序是否是恶意的,或者
    • Process Monitor,它可以获取各种信息,可能是其中一些信息称为OpenProcess,或者
    • DWM,我想,但不知道,调用OpenProcess来获取有关应用程序是否支持的信息,例如高DPI模式等等,或
    • 任何数量的其他应用程序可能先前调用过OpenProcess并且仍然处于打开状态。
  3. 道德:

    • 不要指望一旦关闭手柄就会销毁过程对象,因为你的手柄不是唯一的手柄。

    • 僵尸状态对于进程来说是一个完全合法的状态。如果进程终止,所有进程都将处于僵尸状态,有人正在等待用GetExitCodeProcess读取退出代码,或者对该过程的状态有任何其他兴趣。通常,一旦读取退出代码,对流程的兴趣就会减弱,句柄将被关闭,最后流程将被销毁。

    • 一旦进程被销毁,就可以重用PID。 (相反,在关闭所有句柄之前,不能重复使用PID)。在Windows中,内核更喜欢低编号的PID,并且可以非常快速地重用它们。这种行为不同于Linux,它更喜欢递增PID,并且在达到最大值之前不会重复使用它们。

    • 如果您想要进程的句柄,请不要关闭它。