内核中根据进程Pid获取卷的全目录

  • 2019 年 10 月 8 日
  • 笔记

目录

一丶简介

在内核中有时候想通过PID 获取进程的全路径以达到监控的作用 比如我们设置了进程回调.则可以根据PID看下进程的全路径.

二丶原理

原理就是在内核中 通过 ZwQueryInformationProcess 这个未公开的函数 进行查询. 查询好是 ** ProcessImageFileName ** 也就是27号功能.

但是查询出来的路径是Dos路径.还需要进行转化.

1.传入PID 使用 ZwOpenProcess打开PID获取Handle 2.使用ZwQueryInfomationProcess*的27号功能(ProcessImageFileName) 传入 Process的Handle来获取路径.

3.代码实现.

1.首先是未公开的函数获取.

结构定义:

typedef NTSTATUS(*PfnZwQueryInformationProcess) (      __in HANDLE ProcessHandle,      __in PROCESSINFOCLASS ProcessInformationClass,      __out_bcount(ProcessInformationLength) PVOID ProcessInformation,      __in ULONG ProcessInformationLength,      __out_opt PULONG ReturnLength      );    PfnZwQueryInformationProcess ZwQueryInformationProcess;

单独函数实现

//初始化未公开的导出函数  NTSTATUS InitGloableFunction()  {      UNICODE_STRING UtrZwQueryInformationProcessName =          RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");      ZwQueryInformationProcess =          (PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);      return STATUS_SUCCESS;  }

2.获取NT路径

NTSTATUS GetDosPathByProcessId(ULONG pid)  {      /*      1.根据PID获取进程句柄      2.使用ZwQueryInformationProcess 传入HANDLE 使用27号功能获取路径      */      HANDLE hProcess = 0;      CLIENT_ID cid;      OBJECT_ATTRIBUTES obj;      NTSTATUS ntStatus;      ULONG RetLength = 0;      PVOID pBuffer = NULL;      UNICODE_STRING uRetStrNtPath;        if (ZwQueryInformationProcess == NULL)          return STATUS_UNSUCCESSFUL;        cid.UniqueProcess =(HANDLE)pid;      cid.UniqueThread = 0;      InitializeObjectAttributes(&obj, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);      ntStatus = ZwOpenProcess(&hProcess, PROCESS_ALL_ACCESS, &obj, &cid);      if (!NT_SUCCESS(ntStatus))          return STATUS_UNSUCCESSFUL;      //使用27 号功能遍历        ntStatus = ZwQueryInformationProcess(hProcess, ProcessImageFileName, NULL, 0, &RetLength);      if (STATUS_INFO_LENGTH_MISMATCH != ntStatus)          return STATUS_UNSUCCESSFUL;        //申请内存继续获取.      pBuffer = ExAllocatePoolWithTag(PagedPool, RetLength, 'niBI');      if (NULL == pBuffer)          return STATUS_UNSUCCESSFUL;      //重新调用获取.        ntStatus = ZwQueryInformationProcess(hProcess, ProcessImageFileName, pBuffer, RetLength, &RetLength);      if (!NT_SUCCESS(ntStatus))          return STATUS_UNSUCCESSFUL;      //此时Puffer就已经是我们的路径了    进行该有的操作即可.      return STATUS_SUCCESS;  }

因为暂时是做测试,所以并没有返回Buffer的值.

windbg查看.

可以看到已经获取了 calc的 卷的全路径.

至于转化为我们常用的路径.看下一讲.