内核中通过进程PID获取进程的全部路径

  • 2019 年 10 月 8 日
  • 筆記

目录

一丶简介

我们遇到的Dos路径.如果想转化为NT路径(也就是 C:xxxx)类似的格式 需要自己实现. 具体原理如下:

二丶原理

1.原理

1.使用** ZwOpenProcess ** 通过进程PID获取HANDLE 2.使用** ZwQueryInformationProcess ** 查询Handle,使用27号(ProcessFileNmae)得到NT路径. 3.使用** ZwOpenFile 打开路径得到Handle 4.使用 ObReferenceObjectByHandle ** 获得 内核对象(FileObject) 5.从FileObject的成员FileName得到其路径 6.使用 RtlVolumeDeviceToDosName 将FileObject设备对象传入.获得Dos路径.也就是盘符 7.拼接路径进行传出

2.代码实现.

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;  }  NTSTATUS GetDosPathByProcessId(IN ULONG pid,OUT PANSI_STRING pAnsiNtPath)  {      /*      1.根据PID获取进程句柄      2.使用ZwQueryInformationProcess 传入HANDLE 使用27号功能获取路径      */      HANDLE hProcess = 0;      CLIENT_ID cid;      OBJECT_ATTRIBUTES obj;      NTSTATUS ntStatus;      ULONG RetLength = 0;      PVOID pBuffer = NULL;      HANDLE hFile;      IO_STATUS_BLOCK iostu;      PVOID FileObject = NULL;      PFILE_OBJECT pMyFileObject = NULL;      UNICODE_STRING DosName;      UNICODE_STRING FunllPath;        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))      {          if (NULL != pBuffer)          {              ExFreePoolWithTag(pBuffer, 'niBI');          }          return STATUS_UNSUCCESSFUL;      }        //开始转化路径      InitializeObjectAttributes(&obj, pBuffer, OBJ_KERNEL_HANDLE, 0, 0);      ntStatus = ZwOpenFile(          &hFile,          GENERIC_READ,          &obj,          &iostu,          FILE_SHARE_READ| FILE_SHARE_WRITE ,          0);      if (!NT_SUCCESS(ntStatus))      {          if (NULL != pBuffer)          {              ExFreePoolWithTag(pBuffer, 'niBI');          }          ZwClose(hFile);          return STATUS_UNSUCCESSFUL;      }        //获得文件对象      ntStatus = ObReferenceObjectByHandle(          hFile,          GENERIC_ALL,          *IoFileObjectType,          KernelMode,          &FileObject,          NULL);        if (!NT_SUCCESS(ntStatus))      {          if (NULL != pBuffer)          {              ExFreePoolWithTag(pBuffer, 'niBI');          }          ntStatus = ObDereferenceObject(FileObject);          ZwClose(hFile);          return STATUS_UNSUCCESSFUL;      }      pMyFileObject = (PFILE_OBJECT)FileObject;      if (NULL == pMyFileObject)      {          if (NULL != pBuffer)          {              ExFreePoolWithTag(pBuffer, 'niBI');          }          ntStatus = ObDereferenceObject(FileObject);          ZwClose(hFile);          return STATUS_UNSUCCESSFUL;        }      //通过 RtlVolumeDeviceToDosName 获取Dos路径 也即是C: D: 等盘符      RtlVolumeDeviceToDosName(pMyFileObject->DeviceObject,&DosName);        //获得路径直接直接拼接即可.        FunllPath.MaximumLength = pMyFileObject->FileName.MaximumLength + DosName.MaximumLength;      FunllPath.Length = pMyFileObject->FileName.Length + DosName.Length;      FunllPath.Buffer = ExAllocatePoolWithTag(NonPagedPool, FunllPath.MaximumLength, 0);        //拼接路径      RtlCopyUnicodeString(&FunllPath, &DosName);//得到C:      RtlAppendUnicodeStringToString(&FunllPath, &pMyFileObject->FileName);//得到C:\xxx路径,转为Asii      RtlUnicodeStringToAnsiString(pAnsiNtPath, &FunllPath,TRUE); //RtlFreeAnsiString  要释放空间.          ExFreePool(FunllPath.Buffer); //因为传出自动为其分配了内存所以这个进行谁放      if (NULL != pBuffer)      {          ExFreePoolWithTag(pBuffer, 'niBI');      }        ntStatus = ObDereferenceObject(FileObject);      ZwClose(hFile);      return STATUS_SUCCESS;  }  NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObj, PUNICODE_STRING pRegPath)  {            ANSI_STRING AnsiNtPath;      pDriverObj->DriverUnload = DriverUnLoad;      InitGloableFunction();      KdBreakPoint();      GetDosPathByProcessId(3356,&AnsiNtPath);        return STATUS_SUCCESS;  }

以下为调试的时候的代码截图. 1.得到FileName

2.使用RtlVolumeDeviceToDosName 得到盘符

3.拼接路径为UNICODE_STRING类型

4.为传入的ANSI_STRING 分配空间转换.得到ANSI_STRING路径.