You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.02 13:53:24