深入理解句柄表

2023-05-16

涉及到句柄表的有以下这些概念:

  • HANDLE_TABLE
  • HANDLE_TABLE结构体中的TableCode变量

实际上啊,TableCode是指向句柄表项第一个句柄表项的指针(NULL句柄表项),TableCode就是HANDLE_TABLE_ENTRY的指针。

但是,当有两级以上表时,这个时候就不是了,先来搞定最简单的。

HANDLE_TABLE_ENTRY:句柄表项

对象头_OBJECT_HANDLE

EXHANDLE:这个就是提供给用户使用的句柄值

HANDLE_TABLE_ENTRY是一个8个字节的结构体。它包括:

  • 指向对象头的指针
  • 32位的访问掩码

因为对象头_OBJECT_HANDLE的大小是0x18h,是8的倍数,因为对象头总是按照8个字节对齐。所以对象头的地址低3位肯定是0。所以HANDLE_TABLE_ENTRY的对象头的指针的低3位为0,低三位被用作一些访问标志。

句柄值:通过查看句柄值可以发现,句柄值总是4的倍数。例如:

0x0004

0x0008

0x000C

0x0010

所以,句柄值低2位总是0,所以低2位可以被用作标志位。

句柄值的结构类型是EXHANDLE,在EXHANDLE中低2位为标志位。

0x0000这一个句柄值被用来做位NULL无效句柄。提供给用户使用:

if(Handle == NULL/ *0x0000*/ )

return;

typedef struct _EXHANDLE

{

// 注意啦,这里是个联合。

// 实际上该结构体就占4个字节

union

{

struct

{

ULONG TagBits:2;

ULONG Index:30;

}

HANDLE GenericHandleOverlay; //呵呵,这是用来提供给用户使用的句柄。

#define HANLE_VALUE_INC 4

ULONG_PTR Value; //这个表示什么意思呢?

}

}EXHANDLE,*PEXHANDLE;

*******************************************************************************

如何知道HANDLE_TABLE和HANDLE_TABLE_ENTRY的关系,可以参考ExpAllocateHandleTable。

ExpAllocateHandleTable用来为每个进程分配句柄表,并初始化句柄表。第一次只分配0级的句柄(保存真正句柄项)。

*******************************************************************************

我不知道该怎么写才顺,我就按照我的分析流程写吧。

!Process 查看当前进程

PROCESS 87ca7cf8   SessionId: 0   Cid: 0cb0     Peb: 7ffd8000   ParentCid: 03c4

     DirBase: 3f13d000   ObjectTable: e2d11b78   HandleCount:   76.

     Image: windbg.exe

其中EPROCESS的地址在87ca7cf8,ObjectTable的地址在e2d11b78

ObjectTable是HANDLE_TABLE结构变量,它保存在EPROCESS中。

dt _EPROCESS 87ca7cf8   来查看EPROCESS结构体的值。

.....

    +0x0c4 ObjectTable       : 0xe2d11b78_HANDLE_TABLE

......

ObjectTable在EPROCESS偏移0x0c4处。

ObjectTable保存着关于句柄表的信息。

我们使用下面的命令来查看HANDLE_TABLE内容:

dt _HANDLE_TABLE 0xe2d11b78     

    +0x000 TableCode         : 0xe4702000

   ......

其中偏移0为TableCode,它实际上是句柄项(_HANDLE_TABLE_ENTRY)的指针。

句柄项(_HANDLE_TABLE_ENTRY)是用来保存真正的句柄信息的结构体。

(注意,当TableCode低2位为0时,TableCode才指向_HANDLE_TABLE_ENTRY,至于如何给TableCode分配值,还是需要分析一下源码。)

_HANDLE_TABLE_ENTRY是两个32位的结构体:一个指向对象头的指针;一个是32位的标志。

注意,这个32位的对象头的指针并不是全部有效。因为对象头为0x18个字节,所以windows能保证对象头的分配地址总是8的倍数。所以这32位的对象头的指针低3位肯定都为0,windows将这低3位用作其他用途。因此,当我们使用对象头指针时,一定要记得,低3位值不是我们需要的,应该置0 。即:value & 0xFFFFFFF8。

我们使用dt _HANDLE_TABLE_ENTRY 0xe4702000 来查看其值。

lkd> dt _HANDLE_TABLE_ENTRY 0xe4702000

nt!_HANDLE_TABLE_ENTRY

    +0x000 Object            : (null)

    +0x000 ObAttributes      : 0

    +0x000 InfoTable         : (null)

    +0x000 Value             : 0

    +0x004 GrantedAccess     : 0xfffffffe

    +0x004 GrantedAccessIndex : 0xfffe

    +0x006 CreatorBackTraceIndex : 0xffff

    +0x004 NextFreeTableEntry : -2

但是得到的值好像是无效的。

这就对了,因为句柄表的第一个值不被使用,做为一个无效值,用来提供给程序员做错误处理使用。

下面该怎么办呢?句柄表,句柄表肯定是一个连续的数组,连续的保存一些句柄表项。

我们使用dd 0x4702000来查看这块地址的一些值

lkd> dd 0xe4702000

e4702000   00000000 fffffffe e1008719 000f0003

e4702010   e1858019 00000003 87d68f13 00100020

......

看,值出来了,因为一个句柄表项_HANDLE_TABLE_ENTRY占8个字节。所以,前两个值看似一个无效的值。但是红色标示的却象个有用的句柄项。

注意了,_HANDLE_TABLE_ENTRY是2个32位组成的64位结构体。前面说过了,低32位是对象头的指针。但是要得到对象头的指针,我们必须将值&0xFFFFFFF8,将低3位置0。

e1008719 & 0xFFFFFFF8 = e1008718

我们还必须加上0x18才能得到真正的内核对象。因为内核对象在对象头的后面,对象头的大小是0x18

dt _object_header

lkd> dt _object_header

nt!_OBJECT_HEADER

    +0x000 PointerCount      : Int4B

...

    +0x018 Body              : _QUAD

用刚才的 e1008718 + 0x018 = e1008730 ,然后我们使用!Object e1008730查看。

lkd> !object e1008730

Object: e1008730    Type: (89bddad0) KeyedEvent

     ObjectHeader: e1008718 (old version)

     HandleCount: 48   PointerCount: 49

     Directory Object: e1000270   Name: CritSecOutOfMemoryEvent

哈哈,挺像的 。使用!Handle列出当前句柄来测试一把。

lkd> !handle

processor number 0, process 87ca7cf8

PROCESS 87ca7cf8   SessionId: 0   Cid: 0cb0     Peb: 7ffd8000   ParentCid: 03c4

     DirBase: 3f13d000   ObjectTable: e2d11b78   HandleCount:   99.

     Image: windbg.exe

Handle table at e4702000 with 99 Entries in use

0004: Object: e1008730   GrantedAccess: 000f0003 Entry: e4702008

Object: e1008730   Type: (89bddad0) KeyedEvent

     ObjectHeader: e1008718 (old version)

         HandleCount: 48   PointerCount: 49

         Directory Object: e1000270   Name: CritSecOutOfMemoryEvent

0008: Object: e1858030   GrantedAccess: 00000003 Entry: e4702010

Object: e1858030   Type: (89c153b0) Directory

......

对比一下,成功,我们已经找到了句柄值为0004的内核对象。

OK,冒出了句柄值,那么句柄值是如何被关联起来呢?想下0004,它对应_HANDLE_TABLE_ENTRY表项的低几个啊?

句柄值为0x0000代表是NULL,刚好_HANDLE_TABLE_ENTRY的第0个表项为无效值

句柄值为0x0004有效,刚好指的是_HANDLE_TABLE_ENTRY的第1个表项。

那句柄值为0x0008了?

原来句柄值总是4的倍数。值/4就代表句柄表项数组_HANDLE_TABLE_ENTRY的索引啊。

这时,句柄值的低两位永远是0啦,为啥呢?是4的倍数,第2为不就为0?自己算算。

0x00,0x04,0x08,0x10,0x14等等的二进制

既然第2位永远为0,那么微软就利用了这两位做一个标志位,用来指示当前句柄值所代表的内核对象到那个表项数组中找到?

什么意思呢?

句柄表实际上是分级的,分3级,我们可以像理解分页一样。

分页分为:页目录、页表、物理页。

每个页目录保存1024个页表,每个页表保存着1024个物理页,每个页为4k。

句柄表可以这样分:

4K的目录,保存1K个表指针(指针为一项,占4个字节吗,总共是1024个项)。

每个4K的表,保存着1K个_HANDLE_TABLE_ENTRY数组指针。

每个4K的_HANDLE_TABLE_ENTRY数组保存着512个_HANDLE_TABLE_ENTRY,咋是512个?因为每一个_HANDLE_TABLE_ENTRY是8个字节。

每个_HANDLE_TABLE_ENTRY指向真正的内核对象前的对象头。(第1个表项除外,代表空。)

哈哈,句柄表就这么简单,就是太多繁琐的东西。记不住。

记下笔记备忘之。

这两天试着写写访问句柄表信息的小驱动。写完后配合代码和WRK再整理。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

深入理解句柄表 的相关文章

  • ROS机器人操作系统底层原理及代码剖析

    0 目的 本文介绍ROS机器人操作系统 xff08 Robot Operating System xff09 的实现原理 xff0c 从最底层分析ROS代码是如何实现的 1 序列化 把通信的内容 xff08 也就是消息message xff
  • RS232,RS485波形分析

    通过观察波形可以确定以下情况 xff1a 是否有数据接收或发送 xff1b 数据是否正确 xff1b 波特率是否正确 xff1b 一 串行数据的格式 异步串行数据的一般格式是 xff1a 起始位 43 数据位 43 停止位 xff0c 其中
  • GPU渲染管线之旅|05 图元处理、Clip/Cull, 投影和视图变换

    上一篇中我们讨论了关于 纹理和采样 xff0c 这一篇我们回到3D管线的前端 在执行完顶点着色之后 xff0c 就可以实际的渲染东西了 xff0c 对吗 xff1f 暂时还不行 xff0c 因为在我们实际开始光栅化图元之前 xff0c 仍然
  • 谈谈OpenCV中的四边形

    首先抛出一个问题 xff0c 给定一系列二维平面上的的点 xff0c 这些点是可以组成一个封闭的二维图形 因为这些点是矩形区域拍摄图像后识别得到的图形的边界点 xff0c 所以我们要抽象出来这个矩形 xff0c 也就是我们要反映出这个矩形
  • GPU渲染管线之旅|07 深度处理、模板处理

    在这一篇中 xff0c 我们来讨论Z pipline的前端部分 简称它为early Z 以及它是在光栅化中怎么起作用的 和上一篇一样 xff0c 本篇也不会按实际的管道顺序进行讨论 xff1b 我将首先描述基础算法 xff0c 然后再补充管
  • GPU渲染管线之旅|08 Pixel Shader

    在这一部分中 xff0c 我们来谈谈像素处理的前半部分 dispatch和实际的像素着色 事实上 xff0c 这部分是大多数图形开发者在谈到PS stage时所关心的内容 有关alpha blend和Late Z的内容则会下一篇文章中去探讨
  • MFC基于CSplitterWnd类的多窗口分割

    使用平台 xff1a win7 64bit 使用环境 xff1a VS2012 1 CSplitterWnd介绍 上图是从MSDN中截取的类的继承图表 xff0c CSplitterWnd类继承自CWnd类 这个类主要就是提供窗口分割的功能
  • OpenCV - 区域生长算法

    1 理论基础 区域生长算法的基本思想是将有相似性质的像素点合并到一起 对每一个区域要先指定一个种子点作为生长的起点 xff0c 然后将种子点周围领域的像素点和种子点进行对比 xff0c 将具有相似性质的点合并起来继续向外生长 xff0c 直
  • 不规则Contours内部像素的操作

    在findContours函数使用了之后 xff0c 有时候就会面临对Contours内部区域的访问 由于contours不一定是凸图形 xff0c 所以使用循环操作的时候总感觉不那么方便 比如在下图中 xff0c 已经使用findCont
  • ros代码中添加使用opencv库,cv::Mat和ros image之间的相互转换

    https blog csdn net sunyoop article details 78630024 ros中很多时候要用到图形处理 xff0c 这时就需要使用opencv库 xff0c 本篇主要将怎么在ros现成node上使用open
  • Ubuntu 16.04 使用

    这篇博客用来专门记录尝试搬迁工作环境到Linux下的使用笔记 xff0c 主要包含有常用软件的安装 xff0c 配置 1 安装输入法 ubuntu 16 04中支持ibus输入系统 1 系统 gt 首选项 gt IBus设置 在弹出的IBu
  • 牛顿迭代法求解方程

    说明 xff1a 该篇博客源于博主的早些时候的一个csdn博客中的一篇 xff0c 由于近期使用到了 xff0c 所以再次作一总结 原文地址 概述 牛顿迭代法 xff08 Newton s method xff09 又称为牛顿 拉夫逊 xf
  • OpenCV - 均值迭代分割

    题外话 之前在博客中写过一篇 区域生长 的博客 xff0c 区域生长在平时经常用到 xff0c 也比较容易理解和代码实现 xff0c 所以在很多情况下大家会选择这种方法 但是区域生长有一个最致命的点就是需要选取一个生长的种子点 为了交流学习
  • IMU原理及姿态融合算法详解

    IMU原理及姿态融合算法详解 一 组成 IMU全称是惯性导航系统 xff0c 主要元件有陀螺仪 加速度计和磁力计 其中陀螺仪可以得到各个轴的加速度 xff0c 而加速度计能得到x xff0c y xff0c z方向的加速度 xff0c 而磁
  • FrankMocap win10安装指导

    本文是相当于将github上frankmocap的安装指导进行了翻译 xff0c 增加了一下windows下安装遇到的坑以及注意事项 如果是linux系统应该安装官方的安装指导安装就可以 xff0c 可以直接参考官方安装指导 安装所有模块
  • ADRC学习(1)系统在调节过程中安排过渡过程的作用

    1 二阶系统的调节过程 考虑对于如下所示的二阶系统 x
  • 笔记本更换SSD后卡顿、假死、失去响应问题探究

    某些笔记本电脑将HDD更换为SSD后 xff0c 系统运行过程中会随机产生半分钟到一分钟的卡顿 xff08 假死 xff09 期间鼠标指针可以运动 xff0c 但所有程序均失去响应 xff0c 也无法打开新的程序 HDD硬盘指示灯常亮 xf
  • 机器人 齐次变换矩阵 位姿变换矩阵(RT矩阵) Matlab参数公式计算

    对于齐次位姿变换 xff08 RT矩阵 xff09 xff0c 有的时候手动计算公式参数太多比较麻烦 xff0c 因此利用matlab参量syms xff0c 可以方便一些 xff0c 可以用于计算机器人正运动学位姿矩阵的参数表示 xff0
  • UART串口校验方式(无校验、奇偶校验、固定校验)

    UART串口校验方式 xff08 奇偶校验 固定校验 无校验 xff09 串口通信校验方式奇偶校验位固定校验位 Stick 无校验位 校验位 xff1a 串口通信中的检错方式 串口在接收数据时 xff0c 如果无检验位 xff0c 则只要检

随机推荐

  • 更改LXDE的语言为中文

    之前给旧笔记本安装了Debian8 43 LXDE嘛 xff0c 运行比较流畅 安装过程中本想选择中文的 xff0c 但是安装界面中旧有中文乱码 xff0c 所以还是选了英语 等装好了系统 xff0c 把apt update 43 upgr
  • 干掉Nouveau安装Linux Nvidia显卡驱动

    https blog csdn net misiter article details 7652731 干掉Nouveau安装Linux Nvidia显卡驱动 首先说明下什么是Nouveau xff0c 为什么有些系统安装N卡驱动的时候会提
  • 【C应用】红外遥控小车程序分析(上)——四轮马达方向控制程序分析

    目录 驱动原理分析 L293D功能分析 代码分析 驱动原理分析 小车采用两片L293D芯片控制四个车轮 xff0c 原理图如下 xff1a 因为L293D可分别控制两路电机 xff0c 为了方便理解L293D芯片的工作原理 xff0c 拿L
  • 【RTOS】RTOS实时操作系统随笔(结合UCOSII相关移植)

    目录 无操作系统下的程序结构及缺陷 有操作系统下的解决方案及CPU工作原理 操作系统调度策略及时间片轮转策略 操作系统TICK及进程切换 UCOSII介绍 UCOSII进程任务切换原理 xff1a UCOS进程的堆栈 xff1a 时钟TIC
  • 【STM32CobeMX】CubeMX建立基于STM32F1VBT6的FreeRTOS

    STM32F103VBT6 内部时钟源RCC 如果使用RTOS 使用了RTOS xff0c 默认使用SysTick xff1b 所以HAL库的时基就要用其他的定时器 当用了RTOS xff0c 就要设置HAL的timebase为其他Time
  • 【QT】手把手制作一个网络调试助手(UDP设计)

    TCP和UDP网络通信类的使用 Porn hub 1 程序框架搭建 接着上一篇文章 xff0c 这里就开始设计UDP的相关功能函数了 xff0c 首先将其UDP的相关配置进行隐藏 xff1b 1 1 构造函数讲解 MainWindow Ma
  • 【PADSVX2.7】PADSVX2.7

    目录 1 文件准备 xff1a 2 解压PADSVX 2 7 ESDM到Install 3 点击Setup 4 替换文件 5 有请馒头大师 6 开始享受VX2 7带来的爽快感觉 xff01 xff01 xff01 1 文件准备 xff1a
  • STM32 CAN的ID过滤配置

    过滤器的过滤模式 STM32提供两种过滤模式供用户设置 xff1a 屏蔽位模式和标识符列表模式 STM32总共提供14个过滤器组来处理CAN接收过滤问题 xff0c 每个过滤器组包含两个32位寄存器CAN FxR0和CAN FxR1组成 x
  • 基于STM32F407时钟配置学习

    STM32F4x系列时钟树如下 xff1a 1 系统时钟SYSCLK 在STM32F407中 xff0c 除了一些特定的时钟 xff08 例如 xff0c USB OTG FS时钟 xff0c I2S时钟 xff09 外 xff0c 系统所
  • WIN10不能访问共享文件夹的一般性问题

    WIN10不能访问共享文件夹的一般性问题 访问共享文件夹要确定双方在同一网段 xff0c 且自己可以ping通自己 如果都满足还是不能访问 xff0c 试试下面两个解决办法 报错0x8000405 win 43 r xff0c 在里面输入
  • Win10磁盘占用100%解决方法

    Win10磁盘占用100 解决方法 1 按住Ctrl 43 Shift 43 ESC打开任务管理器 xff0c 点击任意进程 xff0c 右键 资源值 磁盘 百分比 xff0c 如果是一般应用进程 xff0c 可以直接关掉 2 切换到 性能
  • WIN7不能访问共享文件夹

    WIN7不能访问共享文件夹 1 确定同一网段 2 开启被访问电脑的Guest用户 windows启用guest用户一般又3种方式 xff0c 通过图形化界面或cmd命令行 xff1a 1 打开运行输入cmd回车 xff0c 输入 xff1a
  • docker 容器更新镜像发布和保存操作步骤

    1 修改容器 安装软件等修改操作 2 docker commit 提交更新并生成新的image sudo docker commit m 34 cuda 9 0 install 34 a 34 chengde 34 23ecb489cf78
  • 嵌入式linux学习----Makefile基础知识

    一 嵌入式linux学习 Makefile基础知识 1 1 Makefile作用 makefile关系到了整个工程的编译规则 一个工程中的源文件不计数 xff0c 其按类型 功能 模块分别放在若干个目录中 xff0c makefile定义了
  • Expert C Lanuage 学习笔记----1、穿越时空的迷雾(1)

    Expert C Lanuage 学习笔记 1 穿越时空的迷雾 xff08 1 xff09 1 First Mistake 几乎每个C语言编程新手都犯过下面错误 xff1a if i 61 3 正确应该是 if i 61 61 3 这种错误
  • vscode 保存代码自动格式化(vue)

    1 根据项目配置的eslint规则保存代码后 xff0c 自动格式化代码 2 需要安装prettier 和 vetur settings json 34 codestream serverUrl 34 34 https api codest
  • 理解互斥量和信号量

    互斥量 Mutex 互斥量表现互斥现象的数据结构 xff0c 也被当作二元信号灯 一个互斥基本上是一个多任务敏感的二元信号 xff0c 它能用作同步多任务的行为 xff0c 它常用作保护从中断来的临界段代码并且在共享同步使用的资源 Mute
  • 单链表逆序与排序

    xfeff xfeff xfeff xfeff xfeff xfeff include lt stdio h gt include lt stdlib h gt include lt string h gt typedef struct d
  • ubuntu apt-get update 失败解决。

    当运行apt get update后出现如下错误时 xff1a E Some index files failed to download they have been ignored or old ones used instead 可以
  • 深入理解句柄表

    涉及到句柄表的有以下这些概念 xff1a HANDLE TABLE HANDLE TABLE结构体中的TableCode变量 实际上啊 xff0c TableCode是指向句柄表项第一个句柄表项的指针 xff08 NULL句柄表项 xff0