內核中PID_HANDLE_OBJECT等互相轉換

  • 2019 年 10 月 8 日
  • 筆記

目錄

一丶簡介

在內核中我們一般會使用各種 HANDLE Object 以及 ID等等. 那麼有時候就需要互相轉換.這裡記錄一下.

下面以進程為例進行說明.

1.進程pid 轉化為 HANDLE

原理就是 跟ring3一樣. 使用打開進程的函數來獲取HANDLE

核心原理就是在內核中使用 ZwOpenProcess 傳入PID 傳出一個HANDLE.

程式碼如下:

    ULONG pid;      HANDLE hProcessHandle;      OBJECT_ATTRIBUTES obj;      CLIENT_ID clientid;      //必須初始化      pid = 2378;      clientid.UniqueProcess = (HANDLE)pid;      clientid.UniqueThread = 0;      InitializeObjectAttributes(&obj, 0, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);      ZwOpenProcess(&hProcessHandle, PROCESS_ALL_ACCESS, &obj, &clientid);

此時ProcessHandle就是我們所要的Handle 關於文件你就可以使用 ZwOpenFile or ZwCreateFile 註冊表類似.

2.Handle ——–> 轉化為 PID

Handle轉化為PID就要使用跟進程相關的特有API.

如進程則使用 ** ZwQueryInformationProcess ** 遍歷進程的基礎資訊即可得到PID

但是注意,此函數在內核中不能直接使用.因為是未公開的函數.所以我們必須進行聲明.並且使用 內核API來動態獲取此函數的地址才可以

程式碼如下: 聲明與定義:

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

核心實現,ProcessHandle就是你所獲得的句柄.

PROCESS_BASIC_INFORMATION ProcessBasicInfor;      //動態獲取.      UNICODE_STRING UtrZwQueryInformationProcessName =          RTL_CONSTANT_STRING(L"ZwQueryInformationProcess");      ZwQueryInformationProcess =          (PfnZwQueryInformationProcess)MmGetSystemRoutineAddress(&UtrZwQueryInformationProcessName);      //check...      //核心程式碼      /*      1.利用PID      */      PROCESS_BASIC_INFORMATION ProcessBasicInfor;      ZwQueryInformationProcess(          ProcessHndle,          ProcessBasicInformation,          (PVOID)&ProcessBasicInfor,          sizeof(ProcessBasicInfor),          NULL);      /*      ProcessBasicInfor.UniqueProcessId; 則為你所求      */

3.Pid ——> Object(EPROCESS)

pid轉化為EPROCESS說下原理.

原理就是通過 PsLookUpProcessByProcessId 傳入PID.傳出EPROCESS.

但是內核中你使用了這個函數. 那麼獲得的EPROCESS就會引用計數+1根據內核面向對象的設計.你要進行解引用.所以還需要一個API 進行解引用

核心程式碼如下:

PEPROCESS pEpro;  PsLookUpProcessByProcessId((HANDLE)pid,&pEpro);  ObDereferenceObject(pEpro);  PEpro即為你所求.

4. HANDLE ————-> EPROCESS

這個也是很常用的.在內核編程中.當你獲得一個HANDLE 首先就要把其轉化為對應的OBJECT對象.

而內核函數也為我們提供了.

如下:

ObReferenceObjectByHandle(ProcessHandle, GENERIC_ALL,*PsProcessType,KernelMode,&pEprocess,NULL);

5.EPROCESS ———> pid

在EPROCESS中本身就記錄著PID. 直接獲取PID即可. EPROCESS.UniqueProcessId;

6.EPROCESS ———>HANDLE

這個倒是沒有常用.但是內核也提供了API給我們使用

ObOpenObjectByPoint(Process,attributes,&AccessState,0,*PsProcessType,PreviousMode,&Handle);