內核中通過進程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路徑.