內核中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);