内核程序中进程的pid,handle,eprocess之间相互转换的方法

本文介绍了在内核程序开发中,如何实现进程标识符(PID)、句柄与 eprocess 结构之间的相互转换。通过具体代码示例展示了五种转换方式,并解释了句柄、句柄表及对象三者之间的关系。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在内核程序开发中,我们常常需要取得某进程的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的指针。


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下验证。 


转载自:http://bbs.pediy.com/showthread.php?t=119193
<think>好的,我现在要回答用户关于EPROCESS结构体定义和使用方法的问题。首先,用户是Windows内核开发的初学者,可能需要基础的解释。我需要参考提供的引用资料,尤其是引用3和4,其中提到了EPROCESS与链表、VAD结构的关系。 首先,EPROCESS结构体是Windows内核中表示进程的关键数据结构,包含进程的各种信息。根据引用4,EPROCESS结构中有VAD结构的偏移,所以需要说明其存储进程的虚拟地址信息。同时,引用3提到内核使用LIST_ENTRY链表,可能EPROCESS中的ActiveProcessLinks就是这种链表结构,用于连接所有进程。 接下来,结构体定义部分,用户可能需要知道主要成员,如进程ID、句柄表、PEB地址等。由于EPROCESS在不同系统版本中定义不同,应提醒用户使用调试工具查看具体版本的定义。 关于使用方法,需要说明如何通过PsGetCurrentProcess获取当前进程EPROCESS,如何遍历进程链表,以及如何访问VAD等成员。这里要结合引用4中的例子,比如使用!process指令和偏移量来定位VAD结构。 最后,生成相关问题时要围绕EPROCESS的应用场景、遍历方法、与线程结构体的关系等,帮助用户深入理解。同时确保使用正确的LaTeX格式,行内公式用$,独立公式用$$,并检查语法正确性。</think>### EPROCESS结构体的定义与使用方法 #### 一、EPROCESS结构体定义 `EPROCESS`是Windows内核中描述进程的核心数据结构,包含进程的所有元数据。其定义因Windows版本不同而有所差异,但核心成员包括: $$ \begin{aligned} &\text{+0x2e8 UniqueProcessId : Ptr64 Void} \quad \text{(进程PID)} \\ &\text{+0x448 ObjectTable : Ptr64 _HANDLE_TABLE} \quad \text{(句柄表)} \\ &\text{+0x5c8 Peb : Ptr64 _PEB} \quad \text{(用户态进程环境块)} \\ &\text{+0x658 VadRoot : Ptr64 _MM_AVL_TABLE} \quad \text{(VAD树根节点)} \\ &\text{+0x5f0 ActiveProcessLinks : _LIST_ENTRY} \quad \text{(进程链表节点)} \end{aligned} $$ 该结构体长度通常超过0x1000字节[^4],实际定义需通过WinDbg查看: ```bash 0: kd> dt nt!_EPROCESS ``` #### 二、主要成员解析 1. **进程标识** - `UniqueProcessId`:进程PID,通过`PsGetProcessId`函数获取 - `ImageFileName`:进程映像文件名(如x64.exe) 2. **内存管理** - `VadRoot`指向进程的虚拟地址描述符树(VAD Tree),可通过`!vad`命令查看: ```bash 0: kd> !process ffffe28fbb0860c0 7 ``` 3. **链表结构** - `ActiveProcessLinks`是`LIST_ENTRY`类型的内核链表节点,用于连接所有活动进程: $$ \text{遍历公式:NextProcess = CONTAINING_RECORD(ListEntry.Flink, EPROCESS, ActiveProcessLinks)} $$ #### 三、使用方法示例 1. **获取当前进程** ```c PEPROCESS CurrentProcess = PsGetCurrentProcess(); ``` 2. **遍历进程链表** ```c PLIST_ENTRY ListHead = PsGetProcessListHead(); PLIST_ENTRY CurrentEntry = ListHead->Flink; while (CurrentEntry != ListHead) { PEPROCESS Process = CONTAINING_RECORD(CurrentEntry, EPROCESS, ActiveProcessLinks); DbgPrint("Process Name: %s\n", Process->ImageFileName); CurrentEntry = CurrentEntry->Flink; } ``` 3. **访问VAD树** ```c PMM_AVL_TABLE VadRoot = Process->VadRoot; if (VadRoot->NumberGenericTableElements > 0) { // 遍历VAD树分析内存布局 } ``` #### 四、开发注意事项 1. **版本兼容性** EPROCESS结构偏移量随系统版本变化(如Win10与Win7不同),应使用`FIELD_OFFSET`宏动态获取偏移[^3]。 2. **内存访问** 访问用户空间地址需使用`ProbeForRead`验证,或通过MDL映射物理内存[^2]。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值