Windows句柄与对象类型关联机制及内核结构成员作用咨询
Windows句柄与对象类型的关联机制及关键结构解析
背景说明
现有两个程序文件:拼写有误的LearnHanle.exe(正确应为LearnHandle.exe)和pop.exe,源码如下:
LearnHanle.cpp 源码
// LearnHanle.cpp #include <windows.h> #include <stdlib.h> #include <stdio.h> int main() { STARTUPINFOW startup = { 0 }; startup.cb = sizeof startup; PROCESS_INFORMATION pi = { 0 }; BOOL createProcResult = FALSE; // 修正路径的转义字符,原代码单斜杠会导致路径解析错误 if (!CreateProcessW(L"C:\\pop.exe", NULL, NULL, NULL, TRUE, 0, NULL, NULL, &startup, &pi)) MessageBoxA(NULL, "Create Process Failed", "Alert", MB_OK); char handle[80] = { 0 }; sprintf_s(handle, "Process Handle: %llu ProcessId: %llu", pi.hProcess, pi.dwProcessId); MessageBoxA(NULL, handle, "Process", MB_OK); sprintf_s(handle, "Thread Handle: %llu ThreadId: %llu", pi.hThread, pi.dwThreadId); MessageBoxA(NULL, handle, "Thread", MB_OK); system("pause"); CloseHandle(pi.hThread); CloseHandle(pi.hProcess); }
pop.cpp 源码
// pop.cpp #include <windows.h> #include <stdlib.h> #include <stdio.h> int main() { MessageBox(0, 0, 0, 0); // 长时间休眠,保持进程存活 Sleep(6000000); }
LearnHanle.exe的功能是创建pop.exe进程后暂停自身。通过Process Explorer查看LearnHanle.exe进程详情,可找到关联pop.exe进程的句柄及内核地址0xFFFFE786E04AF080;使用WinDbg调试Windows 11内核时,执行!object命令查看该地址可得到pop.exe进程的对象信息,但不清楚该地址存储内容及!object命令的获取原理。
结合查看LearnHanle.exe的_HANDLE_TABLE结构,以下是相关问题的解析:
1. 进程句柄表中的表项如何关联到对应的对象类型?
Windows进程的句柄表(_HANDLE_TABLE)中每个表项对应_HANDLE_TABLE_ENTRY结构,关联逻辑如下:
- 用户态调用
CreateProcess等API创建对象时,内核会为目标对象(如pop.exe的进程对象)分配内存,并生成对应的句柄表项。 - 句柄表项的
ObjectPointerBits字段存储了指向内核对象头部(_OBJECT_HEADER)的指针(低几位被用作权限标志,需通过位运算剔除后得到完整指针)。 - 通过
_OBJECT_HEADER的TypeIndex成员,可索引到内核全局对象类型表ObTypeIndexTable,每个索引对应唯一的对象类型(如进程、线程、文件)。 - 最终通过该索引定位到
_OBJECT_TYPE结构,明确句柄对应的对象类型。
完整关联路径:句柄表项 → ObjectPointerBits → _OBJECT_HEADER → TypeIndex → ObTypeIndexTable → 对象类型
2. 三个关键结构成员的作用
struct _HANDLE_TABLE_ENTRY::ObjectPointerBits
这是句柄表项的核心字段:
- 存储内核对象头部
_OBJECT_HEADER的指针,但低几位被复用为权限标志(如是否允许继承、是否只读),需通过位运算(如与0xFFFFFFFFFFFFFFF0按位与)剔除标志位,才能得到真实的指针地址。 - 是用户态句柄到内核对象的直接桥梁,内核通过解析该字段找到对应的对象实例。
struct _OBJECT_HEADER::TypeIndex
这是一个8位索引值:
- 内核维护全局对象类型数组
ObTypeIndexTable,每个索引对应唯一的对象类型(如进程类型索引为PROCESS_OBJECT_TYPE,线程为THREAD_OBJECT_TYPE)。 - 通过该索引可快速定位对象的类型结构,获取该类型的默认权限、销毁回调等属性,同时区分不同类型的内核对象。
struct _KPROCESS::Header(_DISPATCHER_HEADER)
_KPROCESS是内核态进程对象的核心结构,其Header成员为_DISPATCHER_HEADER类型:
_DISPATCHER_HEADER是所有调度器对象(进程、线程、事件、互斥体等)的通用头部,包含对象状态标志、信号状态、等待链表等调度相关核心信息。- 对于进程对象,该头部负责管理进程的调度状态(如就绪、等待),同时作为
_OBJECT_HEADER之后的第一个结构,衔接对象通用属性与进程特有属性。
补充:!object命令的原理
WinDbg的!object命令本质是内核调试器直接读取指定地址的内存:
- 输入的
0xFFFFE786E04AF080是_OBJECT_HEADER的起始地址(或对象体地址,命令会自动识别头部)。 - 命令先解析
_OBJECT_HEADER的TypeIndex找到对象类型,再读取对象体内容(如进程对象的_KPROCESS结构),最后格式化输出所有信息。
内容的提问来源于stack exchange,提问作者shichengv
相关产品推荐
相关产品推荐

