私有句柄表

一、什么是句柄

句柄(HANDLE)并不是一个指针,也不是对象地址。

它本质上是:

👉 当前进程句柄表中的一个索引值

示例代码:

cpp 复制代码
HANDLE hProcess = OpenProcess(PROCESS_ALL_ACCESS, FALSE, pid);

解释:

  • hProcess ≠ EPROCESS*

  • hProcess ≠ 内核地址

  • hProcess = 句柄表中的一个编号

二、什么是句柄表

句柄表是 Windows 用来管理"对象引用关系"的一张表:用户态拿到的 HANDLE 本质上只是这张表里的一个索引。

cpp 复制代码
EPROCESS
 └── ObjectTable (HANDLE_TABLE)
        ├── Entry[0]
        ├── Entry[1] → OBJECT_HEADER
        ├── Entry[2] → OBJECT_HEADER
        └── Entry[n]
  • 每个进程都有自己的句柄表
  • HANDLE 只是索引
  • 不同进程中相同数值的 HANDLE 含义完全不同
  • 句柄是"进程私有"的

三、_HANDLE_TABLE

_HANDLE_TABLE 是 进程句柄表的实体结构

它负责:

  • 管理所有 HANDLE

  • 分配 / 回收句柄

  • 查找 HANDLE → OBJECT

  • 维护并发与安全

bash 复制代码
kd> dt _handle_table
ntdll!_HANDLE_TABLE
   +0x000 TableCode        : Uint4B
   +0x004 QuotaProcess     : Ptr32 _EPROCESS
   +0x008 UniqueProcessId  : Ptr32 Void
   +0x00c HandleLock       : _EX_PUSH_LOCK
   +0x010 HandleTableList  : _LIST_ENTRY
   +0x018 HandleContentionEvent : _EX_PUSH_LOCK
   +0x01c DebugInfo        : Ptr32 _HANDLE_TRACE_DEBUG_INFO
   +0x020 ExtraInfoPages   : Int4B
   +0x024 Flags            : Uint4B
   +0x024 StrictFIFO       : Pos 0, 1 Bit
   +0x028 FirstFreeHandle  : Uint4B
   +0x02c LastFreeHandleEntry : Ptr32 _HANDLE_TABLE_ENTRY
   +0x030 HandleCount      : Uint4B
   +0x034 NextHandleNeedingPool : Uint4B
   +0x038 HandleCountHighWatermark : Uint4B

TableCode ------【句柄表的核心】

bash 复制代码
含义:
句柄表的"入口指针 + 层级编码"

高位:句柄表地址
低2位:表层级

QuotaProcess

bash 复制代码
该句柄表所属进程的 EPROCESS

UniqueProcessId

bash 复制代码
该句柄表所属进程的 PID

HandleLock

bash 复制代码
句柄表的自旋锁

HandleTableList

bash 复制代码
所有进程的句柄表挂到一个全局链表中
也就是拿到任意一个进程的句柄表,可以遍历所有进程的句柄表

HandleContentionEvent

bash 复制代码
当多个线程争抢句柄表锁时
线程在这里等待
避免自旋浪费 CPU

HandleCount

bash 复制代码
当前进程中 有效句柄数量
会随 CloseHandle 变化

四、句柄表的三级结构

句柄表 是一个**可变层级**的结构:

它可以是 1 层、2 层,或者 3 层。

由 TableCode 的低 2 位决定。

TableCode & 3 含义
0 一级表
1 二级表
2 三级表
3 保留

在 Windows 7 x86 中,有几个关键事实:

项目 数值
页大小 0x1000(4KB)
指针大小 4 字节
HANDLE_TABLE_ENTRY 8 字节
HANDLE 低 2 位 标志位
真实索引 Handle >> 2

4.1 一级句柄表

bash 复制代码
一页 = 0x1000 字节
每个 Entry = 8 字节
Index = Handle >> 2;
base = TableCode(低2位清零)

容量计算:
0x1000 / 8 = 512 = 0x200
寻址方式
base + Index * 8;

4.2 二级句柄表

当句柄数超过 512,系统会自动升级为二级表。

bash 复制代码
Index = Handle >> 2;
base = TableCode(低2位清零)

一级索引= Index / 0x200;
二级索引= Index % 0x200;

容量计算:
1024 × 512 = 524288 = 0x80000

4.3 三级句柄表

bash 复制代码
Index = Handle >> 2;
base = TableCode(低2位清零)

一级索引 = Index / (1024 * 512);
R1 = Index % (1024 * 512);
二级索引 = R1 / 512;
三级索引 = R1 % 512;

容量计算:
1024 × 1024 × 512 = 0x20000000

五、句柄表项(HANDLE_TABLE_ENTRY) ------ 句柄真正的实体

HANDLE_TABLE_ENTRY 是"句柄的本体"

它描述了:

  • 这个句柄指向哪个对象

  • 拥有什么访问权限

  • 是否可继承 / 是否关闭

  • 对象是否还有效

  • 而 HANDLE 本身,只是访问它的钥匙。

相关推荐
笨鸟先飞,勤能补拙2 小时前
从预测到决策:人工智能与机器学习的系统方法、工程闭环与现实边界
大数据·人工智能·windows·python·机器学习·密码学
程序员-李俞2 小时前
Mistral OCR 4真正改变的不是“识字”:文档AI正在变成Agent的数据入口
人工智能·windows·ai作画·aigc·ocr·ai编程·ai写作
C++ 老炮儿的技术栈3 小时前
Qt5.9.1 Windows 完整开发环境搭建流程
开发语言·c++·windows·qt·编辑器·代码化
bkspiderx4 小时前
从零开始:VS Code搭建C/C++开发环境全指南(Windows/macOS/Linux)
c语言·c++·windows·vs code·c/c++开发环境
Rudon滨海渔村6 小时前
镜像转换esd转iso - VMware虚拟机如何安装或恢复(.esd)的Windows系统
windows·vmware·iso·esd
西安景驰电子7 小时前
《PTP精确时间协议系列》第二篇:工程部署、调试与性能优化
运维·服务器·网络·数据库·windows·性能优化
问天_观心7 小时前
零基础在windows环境下的WSL使用llamafactory(一)
人工智能·windows·python·神经网络·语言模型·github·模型蒸馏
xrkhy7 小时前
redis-shake的使用windows版本
数据库·windows·redis
我一定会有钱8 小时前
打造完美工作流:Git 配置”一次推送,三端同步”(Gitee/GitCode/GitHub)
开发语言·windows·vscode·搜索引擎·gitlab·github·visual studio code
一技安身8 小时前
【Git】零基础入门实战教程(Windows 完整版,适配竞赛仓库)
windows·git