查看: 420|回复: 0

[其他] WIN32简单的办法获取父进程信息PID进程名

[复制链接]

211

主题

211

帖子

654

积分

高级会员

Rank: 4

积分
654
发表于 2019-2-9 19:25:09 | 显示全部楼层 |阅读模式
下面是例子用到的相关的函数:
。NtQueryInformationProcess
。QueryFullProcessImageName
。GetProcessImageFileName
。OpenProcess
。GetCurrentProcessId
。PathStripPath
这些函数以及参数的解释在MSDN上都可以查到,虽然有一个“NtQueryInformationProcess”是“未公开函数”,但是在头文件"winternl.h"中提供了它的声明。
NtQueryInformationProcess 函数用到了一个重要的结构:
  1. typedef struct _PROCESS_BASIC_INFORMATION {
  2.     PVOID Reserved1;
  3.     PPEB PebBaseAddress;
  4.     PVOID Reserved2[2];
  5.     ULONG_PTR UniqueProcessId;
  6.     PVOID Reserved3;
  7. } PROCESS_BASIC_INFORMATION;
  8. typedef PROCESS_BASIC_INFORMATION *PPROCESS_BASIC_INFORMATION;
复制代码

经过前辈的探索,得知结构体中的"Reserved3"字段就是父进程的PID
得到父进程PID后我们再打开这个进程就可以获取到这个进程的相关信息了。
在使用QueryFullProcessImageName、NtQueryInformationProcess或者GetProcessImageFileName时,要求用PROCESS_QUERY_INFORMATION的方式打开
因为这只是获取信息,我们不希望去打扰人家。。。
但是“QueryFullProcessImageName”和“GetProcessImageFileName”这两个函数的要求时必须用PROCESS_QUERY_INFORMATION 或 PROCESS_QUERY_LIMITED_INFORMATION的方式打开的进程句柄。
  1. #ifndef UNICODE
  2. #define UNICODE
  3. #endif // UNICODE
  4. #ifndef _UNICODE
  5. #define _UNICODE
  6. #endif // _UNICODE
  7.  
  8. #include <stdio.h>
  9. #include <tchar.h>
  10. #include <Windows.h>
  11. #include <winternl.h>
  12. #include <Shlwapi.h>
  13.  
  14. /*
  15. /// GetProcessImageFileName 函数
  16. //windows7: kernel32.dll|.lib
  17. // windows r8+: psapi.dll|.lib
  18. #include <psapi.h>
  19. */
  20.  
  21. #pragma comment(lib, "shlwapi.lib")
  22.  
  23. #define SETVALUEFROMPOINTER(p, v) (*p=v)
  24. #if defined(UNICODE) || defined(_UNICODE)
  25. #define OutPutStr(f, v) wprintf_s(L##f, v)
  26. #else
  27. #define OutPutStr(f, v) printf_s(f, v)
  28. #endif
  29.  
  30.  
  31. DWORD GetParentPIDAndName( DWORD ProcessID, LPTSTR lpszBuffer_Parent_Name, PDWORD ErrCodeForBuffer );
  32.  
  33. int main(int argc, const char* argv[]) {
  34.     DWORD pid;
  35.     TCHAR buf[BUFSIZ] = {0};
  36.     DWORD err_code;
  37.  
  38.     pid = GetParentPIDAndName(GetCurrentProcessId(), buf, &err_code);
  39.  
  40.     if ( err_code ) {
  41.         fprintf(stderr, "GetProcessName--> err code: %lu\n", err_code);
  42.     }
  43.  
  44.     OutPutStr("ParentProcessPID: %lu\n", pid);
  45.     OutPutStr("ParentProcessFullName: %s\n", buf);
  46.     PathStripPath(buf);
  47.     OutPutStr("ParentProcessName: %s\n", buf);
  48.  
  49.     return 0;
  50. }
  51.  
  52. typedef
  53. __kernel_entry NTSTATUS
  54. (NTAPI*NQIP)(
  55.     IN HANDLE ProcessHandle,
  56.     IN PROCESSINFOCLASS ProcessInformationClass,
  57.     OUT PVOID ProcessInformation,
  58.     IN ULONG ProcessInformationLength,
  59.     OUT PULONG ReturnLength OPTIONAL
  60.     );
  61.  
  62. DWORD GetParentPIDAndName( DWORD ProcessID, LPTSTR lpszBuffer_Parent_Name, PDWORD ErrCodeForBuffer ) {
  63.     /// 打开给定进程PID
  64.     HANDLE hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, ProcessID);
  65.     if ( !ProcessID ) {
  66.         DWORD err_code = GetLastError();
  67.         fprintf_s(stderr, "[OpenProcess]err code: %lu\n", err_code);
  68.         return 0;
  69.     }
  70.  
  71.     /// 下面是获取函数 NtQueryInformationProcess 的函数指针
  72.     HMODULE hNtdll = GetModuleHandle(_T("ntdll.dll"));
  73.     if ( !hNtdll ) {
  74.         DWORD err_code = GetLastError();
  75.         fprintf_s(stderr, "[GetModuleHandle]err code: %lu\n", err_code);
  76.         CloseHandle(hProcess);
  77.         return 0;
  78.     }
  79.  
  80.     NQIP _NtQueryInformationProcess = (NQIP)GetProcAddress(hNtdll, "NtQueryInformationProcess");
  81.     if ( !_NtQueryInformationProcess ) {
  82.         DWORD err_code = GetLastError();
  83.         fprintf_s(stderr, "[GetProcAddress]err code: %lu\n", err_code);
  84.         CloseHandle(hProcess);
  85.         return 0;
  86.     }
  87.     //***
  88.  
  89.     /// 获取打开的进程的进程进程信息
  90.     PROCESS_BASIC_INFORMATION pbi;
  91.     NTSTATUS status = _NtQueryInformationProcess(
  92.                             hProcess,
  93.                             ProcessBasicInformation,
  94.                             (LPVOID)&pbi, sizeof(PROCESS_BASIC_INFORMATION),
  95.                             NULL);
  96.  
  97.     DWORD dwParentID = 0;
  98.     if ( NT_SUCCESS(status) ) {
  99.         /// 结构体 PROCESS_BASIC_INFORMATION 的 "Reserved3"字段 是父进程的PID
  100.         dwParentID = (LONG_PTR)pbi.Reserved3;
  101.  
  102.         if ( NULL != lpszBuffer_Parent_Name ) {
  103.             HANDLE hParentProcess = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, dwParentID);
  104.             if ( hParentProcess ) {
  105.                 /// 用来接收进程文件名和路径的长度(必须!)
  106.                 DWORD bufs;
  107.                 /// 获取进程路径
  108.                 BOOL ret = QueryFullProcessImageName(hParentProcess, 0, lpszBuffer_Parent_Name, &bufs);
  109.                 if ( TRUE == ret )
  110.                     SETVALUEFROMPOINTER(ErrCodeForBuffer, 0);
  111.                 else
  112.                     SETVALUEFROMPOINTER(ErrCodeForBuffer, GetLastError());
  113.  
  114.                 /*
  115.                 /// 结果是DOS路径+文件名
  116.                 TCHAR buf[BUFSIZ];
  117.                 GetProcessImageFileName(hParentProcess, buf, BUFSIZ);
  118.                 cout << "[GetProcessImageFileName]: " << buf << endl;
  119.                 */
  120.             }
  121.             else {
  122.                 SETVALUEFROMPOINTER(ErrCodeForBuffer, GetLastError());
  123.             }
  124.             if ( hParentProcess )
  125.                 CloseHandle(hParentProcess);
  126.         }
  127.     }
  128.     else {
  129.         DWORD err_code = GetLastError();
  130.         fprintf_s(stderr, "[NtQueryInformationProcess]err code: %lu\n", err_code);
  131.     }
  132.  
  133.     CloseHandle(hProcess);
  134.     return dwParentID;
  135. }
复制代码

“QueryFullProcessImageName”和“GetProcessImageFileName”的区别是,前者反回的是我们平常常见且使用的win32路径,后者返回的是完整的设备路径。
“GetProcessImageFileName”的介绍点击这儿

我编译运行的工具是codebocks+vs2010附带的编译工具(msvc)(cl-16.00.30319.01和link-10.00.30319.01)
codeblocks 运行一个程序是使用“cb_console_runner.exe”来启动的,所以它就是父进程。

WIN32简单的办法获取父进程信息PID进程名

WIN32简单的办法获取父进程信息PID进程名
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

快速回复 返回顶部 返回列表