這個函數的功能很強大,可以用來查找進程的很多相關信息。 先看一下定義: NTSTATUS WINAPI NtQueryInformationProcess( _In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength ); 該函數並沒有被微軟公開,它在Ntdll.dll 里導出的,所以要想調用此函數,得用LoadLibrary和GetProcAddress來加載。 用的時候要#include <winternl.h>頭文件 這里說一下參數介紹: processHandle:查詢進程的句柄 ProcessInformationClass:想要查找的信息,他是一個 PROCESSINFOCLASS 的枚舉類型;可以取值: ProcessBasicInformation 0 ProcessDebugPort 7 ProcessWow64Information 26 ProcessImageFileName 27 ProcessBreakOnTermination 29 ProcessInformation:要存放查詢結果的緩沖區,這個結構要根據第二個參數來決定, ProcessInformationLength:緩沖區大小 ReturnLength:實際返回的寫入緩沖區的字節數 我們看一下 ProcessBasicInformation 這個結構: typedef struct _PROCESS_BASIC_INFORMATION { PVOID Reserved1; PPEB PebBaseAddress; PVOID Reserved2[2]; ULONG_PTR UniqueProcessId; PVOID Reserved3; } PROCESS_BASIC_INFORMATION; 這是官方的定義,它其實就是下面的結構: typedef struct { DWORD ExitStatus; // 接收進程終止狀態 DWORD PebBaseAddress; // 接收進程環境塊地址 DWORD AffinityMask; // 接收進程關聯掩碼 DWORD BasePriority; // 接收進程的優先級類 ULONG UniqueProcessId; // 接收進程ID ULONG InheritedFromUniqueProcessId; //接收父進程ID } PROCESS_BASIC_INFORMATION; 這個結構里面有父進程的ID,對應的官方的 Reserved3字段, 還有進程的PEB,看一下進程環境塊兒的定義: typedef struct _PEB { BYTE Reserved1[2]; BYTE BeingDebugged; //該進程是否正在被調試, BYTE Reserved2[1]; PVOID Reserved3[2]; PPEB_LDR_DATA Ldr; PRTL_USER_PROCESS_PARAMETERS ProcessParameters; BYTE Reserved4[104]; PVOID Reserved5[52]; PPS_POST_PROCESS_INIT_ROUTINE PostProcessInitRoutine; BYTE Reserved6[128]; PVOID Reserved7[1]; ULONG SessionId; //會話ID } PEB, *PPEB; 下面寫一段程序來看一下:
#include <windows.h> #include <winternl.h> //先定義函數指針 typedef NTSTATUS (WINAPI *PFUN_NtQueryInformationProcess)( _In_ HANDLE ProcessHandle, _In_ PROCESSINFOCLASS ProcessInformationClass, _Out_ PVOID ProcessInformation, _In_ ULONG ProcessInformationLength, _Out_opt_ PULONG ReturnLength ); void main() { DWORD dwCurrentProcessID; HANDLE hProcessThis; DWORD dwParentID; //如果隨意申請一塊兒內存的話,不管內存多大,調用結果死活不成功,比如:UCHAR pbi[3000] = {0};這樣會導致失敗,還有待繼續探究 PROCESS_BASIC_INFORMATION pbi = {0}; ULONG dwReturnLen; ULONG dwData = sizeof(PROCESS_BASIC_INFORMATION); dwCurrentProcessID = GetCurrentProcessId(); //打開進程一定要有 PROCESS_QUERY_INFORMATION 權限 hProcessThis = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwCurrentProcessID); HMODULE hModule = LoadLibraryA("Ntdll.dll"); PFUN_NtQueryInformationProcess pfun = (PFUNNtQueryInformationProcess)GetProcAddress(hModule, "NtQueryInformationProcess"); NTSTATUS status = pfun(hProcessThis, ProcessBasicInformation, (PVOID)&pbi, dwData, &dwReturnLen); dwParentID = (DWORD)pbi.Reserved3; //dwParentID的值為devenv.exe 進程的句柄,即父進程的句柄 PPEB peb = pbi.PebBaseAddress; }
執行完這些語句后可以查看內存,下面是我的環境下的內存:

//說明:把Reserved3轉化為DWORD后一定會得到devenv.exe 進程的ID,dwParentID也可以說明問題

//說明:這是peb字段,我們看到BeingDebugged字段已經被置為1,說明正在被調試,
SessionId:字段也顯示出了該進程的會話ID
其它字段可以在深入的研究,現在自己也不太熟悉。