谈windows中的句柄

 
每当一个进程打开一个对象,系统就返回一个句柄作为凭证,由此可以想到,句柄是依赖于具体的进程的,换句话说,句柄一定属于某个进程,以后在访问这个对象时就要使用这个凭证!
    所以句柄还可以认为是一个进程和一个对象之间建立的一种连接,一座桥梁,一个上下文,就像一个门一样,已经打开。这种连接就持续存在,直到关闭。
一个进程可打开对个对象,就会拥有多个句柄,所以每个进程都拥有一个句柄表,在进程控制块EPROCESS中有个指针ObjectTable是_HANDLE_TABLE类型,指向本进程的句柄表!
看下_HANDLE_TABLE结构:
 kd> dt _handle_table
nt!_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 , Bit
+0x028 FirstFreeHandle : Uint4B
+0x02c LastFreeHandleEntry : Ptr32 _HANDLE_TABLE_ENTRY
+0x030 HandleCount : Uint4B
+0x034 NextHandleNeedingPool : Uint4B
+0x038 HandleCountHighWatermark : Uint4B
TableCode的低两位被用作标志位,用于表示当前句柄表的级数,0,1,2分别表示一级表,二级表,三级表。
一级表实际上是一个_HANDLE_TABLE_ENTRY 数组,每个_HANDLE_TABLE_ENTRY 8个字节,而一级表是一个page的大小,所以一级表可以容纳2^9个_HANDLE_TABLE_ENTRY 
 lkd> dt _HANDLE_TABLE_ENTRY
nt!_HANDLE_TABLE_ENTRY
+0x000 Object : Ptr32 Void//指向对象的一个指针
+0x000 ObAttributes : Uint4B
+0x000 InfoTable : Ptr32 _HANDLE_TABLE_ENTRY_INFO
+0x000 Value : Uint4B
+0x004 GrantedAccess : Uint4B
+0x004 GrantedAccessIndex : Uint2B
+0x006 CreatorBackTraceIndex : Uint2B
+0x004 NextFreeTableEntry : Uint4B
而句柄以4为步进(注0),因此最大句柄为0x200*4=0x800.其中可存放的最大句柄不超过0x800(最大为0x800-4),而每个一级表的第一个HANDLE_TABLE_ENTRY的Object总是为0,因为我们都知道0是一个无效的句柄,它不指向一个有效的对象。因此,每个一级表实际存放的句柄数为511个!
 
_HANDLE_TABLE结构中有个TableCode字段,该字段有32位,低2位作为标记是几级表,0为一级,1为2级,2为3级。当为0时,TableCode值就指向一个Page,此页就是句柄表,每个表项8个字节为一个entry,低4个字节是对象地址,注意第一个entry不代表任何对象。
若TableCode前两位为1或者2,那么TableCode&0xfffffffd就指向二级或者三级表,每个表项四个字节,指向一个一级或者二级表,以此类推!!
注意:由于对象体都是8字节对齐的,所以对象地址的低3位总是0,可用于标记对象的某些属性,所以在一级句柄表中的对象地址要&0xfffffff8才表示对象头的地址,加上0x18后得到对象体(这里涉及到windows内核中对象的管理,参见另一篇关于对象的文章)!
句柄表架构如图所示:

至于为什么句柄表的号都是4的倍数呢?

一个进程的句柄表包含了所有已被该进程打开的那些对象的指针。对象句柄是用来检索句柄表的一个“伪索引”。对于句柄表机制,achillis <<Windows句柄表>>系列文章已经分析得很透彻了,只是对“句柄以4为步进”来源不明。经查,根源如下:

typedef struct _EXHANDLE
{
 union
 {
  struct
  {
   ULONG TagBits:2;
   ULONG Index:30;
  }
  HANDLE GenericHandleOverlay;
  #define HANLE_VALUE_INC 4
  ULONG_PTR Value;
 }

}EXHANDLE,*PEXHANDLE;
此结构正是用来定义句柄类型。低2位TagBits为标志位Windows用于其它用途,故句柄值低2位对其作为句柄表索引本身无意义,所以等于4的倍数。有了以上分析,自然,在用句柄值为索引取句柄表项时,句柄值必须/4。因此程序中用到的句柄值并不能直接用来索引句柄表,也就有了“伪索引”说法。

 
在windows系统中,主要分为两种句柄表:
1、单个进程的句柄表
2、系统全局句柄表pspCidTable
前者主要用于进程打开的各种对象,而后者用于分配全局进程PID。以任务管理器关闭某个进程为例,如果其要关闭一个进程,首先根据进程PID打开其进程并获取访问这个进程的句柄,这时,PID对应在PspHandleTable中的索引,而获得的句柄对应任务管理器的句柄表中的索引,仅仅在任务管理器的进程空间中有效,一个全局、一个局部。而解析句柄和PID的过程完全一致。
主要区别在于全局句柄表的表项指向的是对象体而不是对象头。
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

谈windows中的句柄的更多相关文章

  1. [转]Windows中的句柄(handle)

    1.句柄是什么?   在windows中,句柄是和对象一一对应的32位无符号整数值.对象可以映射到唯一的句柄,句柄也可以映射到唯一的对象.2.为什么我们需要句柄?   更准确地说,是windows需要 ...

  2. Windows中的句柄

    (一)句柄 在程序设计中,句柄(handle)是一种特殊的智能指针.当一个应用程序要引用其他系统(如数据库.操作系统)所管理的内存块或对象时,就要使用句柄. 句柄与普通指针的区别在于,指针包含的是引用 ...

  3. Windows中句柄和ID的区别

    写在前面:这里介绍句柄 对于“句柄”,在下一直停留在一知半解的认识层面,近日在下学习Windows编程,决定趁此机会将句柄彻底搞清楚.查阅了一些网络上的资料,发现网络上的讲解大概可以分为两类:一种是以 ...

  4. Linux与Windows中动态链接库的分析与对比

    摘要:动态链接库技术实现和设计程序常用的技术,在Windows和Linux系统中都有动态库的概念,采用动态库可以有效的减少程序大小,节省空间,提高效率,增加程序的可扩展性,便于模块化管理.但不同操作系 ...

  5. 【Windows】Windows中的数据类型以及命名

    一.大写标示符 Windows中的很多标识符都是以两个或者三个大写字母作为前缀的,且其后紧跟一个下划线.这些标识符都是常量数值,前缀表明该常量的一般类别.如下 前缀 常量 CS(Class Style ...

  6. windows内核对象句柄

    内核对象用于管理进程.线程和文件等诸多种类的大量资源,每一个内核对象都只是一个句内存快,它由操作系统内核分配,并只能右操作系统内核访问.这个内存块是一个数据结构,其维护着与对象相关的信息,其中少数成员 ...

  7. [转载]解析WINDOWS中的DLL文件---经典DLL解读

    [转载]解析WINDOWS中的DLL文件---经典DLL解读 在Windows世界中,有无数块活动的大陆,它们都有一个共同的名字——动态链接库.现在就走进这些神奇的活动大陆,找出它们隐藏已久的秘密吧! ...

  8. Windows中的对象

    来源  http://www.0xaa55.com/forum.php?mod=viewthread&tid=1401&extra=page%3D1  windows里常用句柄操作资源 ...

  9. 浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍

    浅谈Windows环境下DOS及MS-DOS以及常见一些命令的介绍 前记 自己是搞编程的,首先我是一个菜鸟,接触计算机这么久了,感觉很多计算机方面的技术和知识朦朦胧胧.模模糊糊,貌似有些贻笑大方了:所 ...

随机推荐

  1. js设计模式-观察者模式

    定义: 观察者模式又叫发布订阅模式,它定义了对象间的一种一对多的依赖关系.观察者模式让两个对象松耦合地联系在一起,虽然不太清楚彼此的细节,但这不影响他们之间的互相通信. 思路 定义一个对象,在对象中实 ...

  2. linux create a process

    When the system starts up it is running in kernel mode and there is, in a sense, only one process, t ...

  3. Webserivce简单安全验证

    最近新接了一个需要调用第三方WebService的项目,看到这个第三方WebService被调用的时候,需要授权用户名和密码,于是自己也想对WebService的安全授权这个方面进行了一下研究,以前调 ...

  4. Beta 冲刺(7/7)

    前言 队名:拖鞋旅游队 组长博客:https://www.cnblogs.com/Sulumer/p/10129067.html 作业博客:https://edu.cnblogs.com/campus ...

  5. 逆向路由器固件之解包 Part1

    这个系列的文章以逆向路由器固件的方式来挖掘路由器中存在的漏洞. 本篇文章主要以介绍解包固件工具为主.文中演示用的固件可以在这里下载.由于针对设备的攻击越来越多,很多厂商把不提供固件下载作为一种安全策略 ...

  6. 解压Ubuntu的initrd.img的方法

    Ubuntu的initrd.img可以在/boot中找到,通常文件名后面还跟有很长的一串版本号. 为了保险起见,不直接操作原文件,而是把它复制到自己的家目(home)录中.如果你是用root帐号登录的 ...

  7. exit和return

    函数名: exit() 所在头文件:stdlib.h(如果是”VC6.0“的话头文件为:windows.h) 功 能: 关闭所有文件,终止正在执行的进程. exit(1)表示异常退出.这个1是返回给操 ...

  8. 电脑技巧合集 - imsoft.cnblogs

    ● 如何制作网页● 教你建一个别人打不开的文件夹 ● 只改一个值!马上加快宽带上网速度 ● 在电脑右下角显示你的名字● XP系统如何加快开机速度● 连接宽带时出错表示的意思 ● 恢复丢失数据的方法● ...

  9. CF1096:D. Easy Problem(DP)

    Vasya is preparing a contest, and now he has written a statement for an easy problem. The statement ...

  10. bind() 函数兼容

    为了搞清这个陌生又熟悉的bind,google一下,发现javascript1.8.5版本中原生实现了此方法,目前IE9+,ff4+,chrome7+支持此方法,opera和safari不支持(MDN ...