win32内核程序中进程的pid,handle,eprocess之间相互转换的方法
在内核程序开发中,我们常常需要取得某进程的pid或句柄,或者需要检索进程的eprocess结构,很多API函数需要的参数也不同,所以掌握pid<->handle<->eprocess相互转换的方法会大大提高我们的开发效率。
以下就是我自己在实际开发中总结出来的转换方法,在此记录下来,以供需要的朋友参考。
1、pid->handle
OBJECT_ATTRIBUTES ObjectAttributes;
CLIENT_ID clientid;
InitializeObjectAttributes(&ObjectAttributes, 0 ,OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 0, 0);
clientid.UniqueProcess = (HANDLE)pid;
clientid.UniqueThread=0;
ZwOpenProcess(&handle, PROCESS_ALL_ACCESS, &ObjectAttributes, &clientid);
handle即为所求。
2、handle->pid
PROCESS_BASIC_INFORMATION pbi;
ns = ZwQueryInformationProcess(ProcessHandle, ProcessBasicInformation, (PVOID)&pbi, sizeof(ProcessBasicInformation), NULL);
pid = pbi.UniqueProcessId;
pid即为所求。
3、pid->eprocess
PEPROCESS pEProc;
PsLookupProcessByProcessId((HANDLE)pid, &pEProc);
ObDereferenceObject(pEProc);
pEProc即为所求eprocess的指针。
PsLookupProcessByProcessId第一个参数虽命名为handle,但实际为进程ID.
另外还有函数PsGetCurrentProcessId,虽返回的类型为HANDLE,实际为进程ID。
同例对于线程ID也使用的是HANDLE来标识的,这其实与EPROCESS和ETHREAD中对进程和线程的ID标识类型相关,因其都为Ptr64 Void类型,故为HANDLE类型即void*
4、handle->eprocess
st = ObReferenceObjectByHandle (ProcessHandle,
PROCESS_TERMINATE,
PsProcessType,
KeGetPreviousModeByThread(&Self->Tcb),
&Process,
NULL);
5、eprocess->pid
_EPROCESS.UniqueProcessId即为所求,虽然声明类型为HANDLE,但实际上是pid。
6、eprocess->handle
Status = ObOpenObjectByPointer(
Process,
Attributes,
&AccessState,
0,
PsProcessType,
PreviousMode,
&Handle
);
总结:
这是句柄、句柄表、对象三者间的关系。
PspCidTable是全局的句柄表,用来存放进程、线程对象体,通过进、线程的pid作为索引可以在PspCidTable句柄表中找到pid所属进、线程的对象体(既EPROCESS或ETHREAD)。
其次,在进程内部,以handle作为索引,可以在进程的句柄表(ObjectTable)中找到handle代表的对象头,对象头+0x18就可得到对象体。以上内容全部可以通过在windbg下验证。