为什么 Windows 拒绝访问某些进程的名称?

Why does Windows deny access to some processes' names?

我想尝试构建一个小程序,它可以读取其他程序的内存并将其转储到文本文件中(如果它显然具有访问权限)。但对我来说,访问似乎是一个问题。我首先尝试了一下,想打印当前 运行 所有进程的列表,但显然我什至无法打开某些进程。但是,如果我在像 Cheat Engine 这样的程序中打开列表,它会显示所有进程名称(如果我没看错的话,系统进程例如主要是 PID 4)。现在我是不是在打开进程时弄乱了所需的访问级别,或者 Cheat Engine 只是使用了一些技巧或从其他地方读取了名称?我尝试了 QueryFullProcessImageNameGetBaseModuleName,后者需要 PROCESS_VM_READ 访问权限,这就是我使用 QueryFullProcessImageName 的原因,因为我试图将访问级别降至最低。

main.cpp

#include <cstring>
#include <iostream>
#include <iomanip>
#ifdef _WIN32_WINNT
#undef _WIN32_WINNT
#endif
#define _WIN32_WINNT 0x0600 /* Define so QueryFullProcessImageName can be used */
#include <windows.h>
#include <psapi.h>


using namespace std;


WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR cmdLine, int cmdShow) {
    DWORD processIds[256];  /* Buffer for the process IDs */
    DWORD cbNeeded; /* Space needed from EnumProcesses() to store all IDs */
    /* 
     * I will not check if the space was sufficient or not because this is just a local experiment 
     * and i can insure it is enough space
     */
    if (EnumProcesses(processIds, sizeof(processIds), &cbNeeded) == 0) {
        cout << "Error while enumerating processes(" << GetLastError() << ")" << endl;
        return 0;
    }
    for (unsigned int i = 0; i < cbNeeded / sizeof(DWORD); i++) {
        DWORD nameBufferSize = 128;
        LPSTR processBaseName = new CHAR[128];
        /* Open the process; here is where i get access denied */
        HANDLE openProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, processIds[i]);
        if (openProcess == NULL) {
            if(GetLastError() == 5) strcpy(processBaseName, "<denied>");
            else strcpy(processBaseName, "<unknown>");
        } else if (QueryFullProcessImageName(openProcess, NULL, processBaseName, nameBufferSize) == 0) {
            if(GetLastError() == 5) strcpy(processBaseName, "<denied>");
            else strcpy(processBaseName, "<unknown>");
        }
        cout << "PID: " << setw(6) << left << processIds[i] << "\t" << processBaseName << endl;
        delete processBaseName;
        CloseHandle(openProcess);
    }
    return 0;
}

受保护的进程是您的主要原因。例如,您不能打开 csrss.exe、smss.exe 或 System.其次,尝试启用调试权限 SeDebugPriviledge。然后还 运行 以管理员身份查看是否有更多进程。但是你不能访问受保护的进程,即使有调试权限。为此,您需要一个使用 SeLocateProcessImageFileNamePsGetProcessFileName.

的内核模式驱动程序

这里评论了很多有用的信息,所以我可以自己回答这个问题。如前所述,问题是我永远不会有足够的权限打开受保护的系统进程。解决方案是以另一种方式收集信息。正如所评论的那样,使用 CreateToolhelp32Snapshot 可以更轻松地获取所有当前 运行 进程的快照。然后我可以通过 Process32First 遍历它们,然后使用 Process32Next 遍历它们,然后只读取结构的 PROCESSENTRY32::szExeFile 以获取进程的名称。

我现在使用的代码:

HANDLE processSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (processSnapshot == INVALID_HANDLE_VALUE) {
      std::cout << "Error while taking process snapshot(" << GetLastError() << ")" << std::endl;
      return 0
}
PROCESSENTRY32 process;
process.dwSize = sizeof(PROCESSENTRY32); /* This is neccessary as the Process32First/Next function expects the size of the class in this member before the first call */
if ( ! Process32First(processSnapshot, &process) ) {
      std::cout << "Error while accessing first entry of snapshot(" << GetLastError() << ")" << std::endl;
      return 0;
}
do {
      std::cout << "PID: " << process.th32ProcessID << "\t" << process.szExeFile << std::endl;
} while( Process32Next(processSnapshot, &process) );
if (GetLastError() != ERROR_NO_MORE_FILES) { /*  The Process32Next function throws the ERROR_NO_MORE_FILES error code when there is no more entry to read. If this is not the last error message something went wrong. */
        std::cout << "Error while enumerating processes(" << GetLastError() << ")" << std::endl;
}

注意快照是当前状态的快照,如果有任何进程打开或关闭,需要重新拍摄快照以获取新状态和新进程的信息。