[原创][分享]冷饭热炒 - 再读Windows对象管理
- 关于Windows内核对象管理
- 摘要
都是已经被人研究烂了的技术了……我还在默默学习中-_-! 看过很多书(《Windows核心编程》、《Windows内核原理与实现》等)中对Windows内核对象管理的知识,但一直不是那么理解,文字描述的再详细也不能让人脑中有一个具体的概念。最近在认真阅读《Windows内核情景分析》一书,该书从源代码去讲述内核对象及其管理手段。本人再结合WRK-1.2中的实现代码,进而回想以往其他书中对Windows内核对象管理的知识,读完对象管理一章,顿时有融会贯通、醍醐灌顶之感,源码才是真相所在之处。对于码农来说理解代码也许比理解中文、英文等语言表达的内容来的更容易,可以将抽象的概念具体化。
- 有码才有真相
NOTE: 本文所涉及到的数据结构出自WRK-1.2,对于其他版本的Windows,可能略有不同,请参考WinDBG。
- 相关补充
2.1 对象目录的根节点名
一般情况下根节点名为是把斜杠(\),在C/C++中写法则是双斜杠(\\)。但于历史原因,对象路径的绝对路径名可能是DOS路径名,其根节点名是\??\或\??表示。
2.2 对象及其相关属性
对象属性、对象头和对象体在内存中按照从低地址到高地址的顺序排列,对象属性是可选的。在OBJECT_HEADER中:NameInfoOffset若非0,则对象头向低地址偏移NameInfoOffset处是OBJECT_HEADER_NAME_INFO,HandleInfoOffset和QuotaInfoOffset同理。

图 1
而是否存在OBJECT_HEADER_CREATOR_INFO,则由Flags中是否存在OB_FLAG_CREATOR_INFO来决定,因为其结构如果存在则和对象头相邻,所以其偏移为sizeof(OBJECT_HEADER)。

如图2、3,这两个结构体,在创建对象的过程中将频繁涉及这两个结构体,具体流程请参考下一节的关于ObCreateObject函数的解析。
这里只稍微介绍下,OBJECT_ATTRIBUTES是创建对象时传入的关于对象的属性信息,在创建对象过程中会逐步填入OBJECT_HEADER和OBJECT_CREATE_INFORMATION结构中,进而在调用ObpAllocateObject时将属性转移到对象几个可选头中。虽然OBJECT_CREATE_INFORMATION是可选的,但通常情况下都是存在的。
2.3 对象类型
如图1、4所示,对象头中有一个指针指向对象类型OBJECT_TYPE,对象类型中TypeInfo字段指向OBJECT_TYPE_INITIALIZER结构体,这个结构体主要是在创建对象类型时初始化一些信息(注意TypeInfo不是指针),在OBJECT_TYPE_INITIALIZER中几个函数指针比较关键,这些函数主要是限定在对象在收到某些指令时,如何去执行,比如:打开使用OpenProcedure、关闭使用CloseProcedure、路径解析使用ParseProcedure等。一般的ParseProcedure都比较简单,但是文件对象的ParseProcedure是个特例,文件对象涉及文件系统,需要转入文件目录中寻找。

图 4
2.4 ObpRootDirectoryObject和ObpTypeDirectoryObject
ObpRootDirectoryObject和ObpTypeDirectoryObject是内核中的两个全局变量,前者用来存放整个Windows内核中所有命名对象(Object),后者用来存放内核中所有对象的类型。ObpRootDirectoryObject在对象目录中的路径为反斜杠(\),也即为根目录名;ObpTypeDirectoryObject在对象目录中的路径为\ObjectTypes,其为ObpRootDirectoryObject的子目录,节点名为ObjectTypes。如图5所示:

图5
2.5 句柄表
内核中有三个不同用处的句柄表,在不同Context下的使用时要注意。
详细说明如图6:

图 6
句柄表描述中两个关键结构体HANDLE_TABLE和HANDLE_TABLE_ENTRY,如下图7、8。
在使用过程中要注意HANDLE_TABLE_ENTRY中的Object字段,这个字段虽然名为Object,但这个指针却指向的是对象头(OBJECT_HEADER)。

2.6 对象目录

图9
前面提到过,有名对象会存在一个全局的对象目录里,所有有名对象以开链哈希表(Separate Chaining)的方式存储,在OBJECT_DIRECTORY中HashBuckets就是一个有37个元素的哈希表。
存储形式如图 10所示。这里要注意:
? 符号链接节点可能指向同目录中的另一个节点。
? 节点名就是对象名。
? 中间节点必须是目录对象或“符号链接”对象(OBJECT_SYMBOLIC_LINK)。
? 普通的对象只能是叶节点。
? 节点路径以反斜杠(\)分隔。

图 10
- 相关函数
3.1 ObCreateObject

- Summary
当然,以上所有内容均来自《Windows内核情景分析》,我只是加以总结,以我的理解来讲述。
如有错误敬请批评指正!!!


- 参考
1. 毛德操. Windows内核情景分析
2. 潘爱民. Windows内核原理与实现
3. WRK-1.2
