(转)WINDOWS内核对象
WINDOWS内核对象
原文地址:http://blog.csdn.net/misterliwei/article/details/976988 支持原创
一.前言
Windows中有很多像进程对象、线程对象、文件对象等等这样的对象,我们称之为Windows内核对象。内核对象是系统地址空间中的一个内存块,由系统创建并维护。内核对象为内核所拥有,而不为进程所拥有,所以不同进程可以访问同一个内核对象。
二.内核对象结构
每个对象都有对象头和对象体组成。所有类型的对象头结构都是相同的,而结构体部分却各不相同的。下面是内核对象的结构图:

内核对象结构图
图中灰色部分是可能出现的。每个对象中是否存在这些部分主要由OBJECT_HEADER结构中的相关标志来指定。上面的5个结构的格式是固定的;而OBJECT结构体部分却是各个对象各不同的。需要注意的是:指向对象的指针POBJECT是指向对象体部分,而不是指向对象头的。所以,若需要访问OBJECT_HEADER,需要将POBJCECT减去0x18而获得。
下面是OBJECT_HEADER的结构
|
typedef struct _OBJECT_HEADER { DWORD PointerCount; // 指针引用的数目 DWORD HandleCount; // 打开句柄的数目 POBJECT_TYPE ObjectType; //指向类型对象的指针 BYTE NameOffset; //对象名的偏移 BYTE HandleDBOffset; // HANDLE DB的偏移 BYTE QuotaChargesOffset; //QUOTA CHARGES的偏移 BYTE ObjectFlags; // 对象标志 union { // 对象标志中OB_FLAG_CREATE_INFO ? ObjectCreateInfo : QuotaBlock PQUOTA_BLOCK QuotaBlock; POBJECT_CREATE_INFO ObjectCreateInfo; }; PSECURITY_DESCRIPTOR SecurityDescriptor; }OBJECT_HEADER, *POBJECT_HEADER; |
三.目录对象
WINDOWS中有20几类无数的内核对象,它们都独立地存在于系统地址空间中。系统利用目录对象将所有的这些对象组织起来。目录对象是一个有37个数组元素组成的哈希(HASH)树。数据结构如下:
|
Typedef struct _OBJECT_DIRECTORY_ENTY { Struct _OBJECT_DIRECTORY_ENTRY *NextEntry; POBJECT Object }OBJECT_DIRECTORY_ENTRY, *POBJECT_DIRECTORY_ENTRY,**PPOBJECT_DIRECTORY_ENTRY; Typedef struct _OBJECT_DIRECTORY { POBJECT_DIRECTORY_ENTRY HashTable[37]; POBJECT_DIRECTORY_ENTRY CurrentEntry; BOOLEAN CurrentEntryValid; BYTE Reserved1; WORD Reserved2; DWORD Reserved3; }OBJECT_DIRECTORY, *POBJECT_DIRECTORY; |
系统将对象名称进行一定的算法得出一个HASH值,算法如下:
|
//根据名字计算HASH值。 hash = 0; p = (PSHORT)wStr; //存放名称的一个WCHAR数组 while(*p) { Symb = (CHAR)*p; hash = hash * 3 + (hash >> 1); if (Symb < 'a') //<a hash= hash + Symb; else if (Symb <= 'z') //即 a~z hash = hash + Symb - 0x20; else // > z hash = hash + (CHAR)RtlUpcaseUnicodeChar((WCHAR)*p); p ++; } hash = hash % 37; //最终的hash值。 |
系统将所有相同HASH值的对象链接到响应的数组项中,于是系统中所有元素将排列成如下的结构图:

系统根目录的对象的指针由ObpRootDirectoryObject来指定。
按理说,系统中只需要一个目录对象就够了,系统中所有的内核对象都将链接在这个目录对象上。但是不知什么原因,系统中并不是这样,系统中存在着多个目录对象,它们以根目录对象为根,组成一个“对象树”。每个目录对象中的哈希树的hash值的计算规则都是一样的。
我们可以根据系统中“对象树”的结构来遍历系统中所有的对象。

四.类型对象
内核对象中还有一种比较特殊的对象——类型对象。系统中每种类型对象只有一个类型对象,也就是说,系统中最多只有20几个类型对象。每种类型的对象都在其对象体中存在一个指向其类型对象的指针,因为一种类型对象只有一个实体,所以每种类型对象的指针都是固定的,这样我们就可以通过对象体中的类型对象指针来判断和访问对象的类型了。

各个类型对象的对象体内并没有链表结构使得它们相互链接起来。但是假如对象头部前面有OBJECT_CREATOR_INFO结构(见下表),则相同类型的对象就可以通过它的成员ObjectList相互链接起来了。但是,不幸的是:缺省情况下,只有Port和WaitPort两中类型的对象有这种结构。所以一般情况下,我们是不能通过类型对象来遍历这个系统中所有对象的。
|
typedef struct _OBJECT_CREATOR_INFO { LIST_ENTRY ObjectList; // OBJECT_CREATOR_INFO HANDLE UniqueProcessId; WORD Reserved1; WORD Reserved2; }OBJECT_CREATOR_INFO, *POBJECT_CREATOR_INFO, **PPOBJECT_CREATOR_INFO; |
五.对象的遍历
上面分析过了,下面可以目录对象的遍历,来进行系统中所有对象的遍历。
|
//写一个递归函数。用来分析树型目录。 void AnalyseDirectory(POBJECT_DIRECTORY pDirectory, ULONG DirectoryType, int Level) { POBJECT_DIRECTORY_ENTRY pDirectoryEntry; POBJECT_HEADER pObjectHeader; POBJECT_NAME pObjectName; PWCHAR wStr[200]; char Space[100]; //为生成空格用的。 int i, j; for(i = 0; i < 36; i ++) //DIR对象的对象体(BODY)是37个元素的数组。 { pDirectoryEntry = pDirectory->HashTable[i]; while(pDirectoryEntry) { pObjectHeader = (POBJECT_HEADER)((ULONG)pDirectoryEntry->pObject - sizeof(OBJECT_HEADER)); //生成空格 RtlZeroMemory(Space, 100); for(j = 0; j < 5 * Level; j ++) Space[j] = ' '; if (pObjectHeader->NameOffset) { pObjectName = (POBJECT_NAME)((ULONG)pObjectHeader - pObjectHeader->NameOffset); RtlZeroMemory(wStr, 200 * sizeof(WCHAR)); RtlCopyMemory(wStr, pObjectName->Name.Buffer, pObjectName->Name.Length); DbgPrint("%s pObject: 0x%08X Name: %S", Space, pDirectoryEntry->pObject, wStr); } else DbgPrint("%s pObject: 0x%08X Name: noname", Space, pDirectoryEntry->pObject); //pObject对象是属性对象吗 if ((ULONG)pObjectHeader->pObjectType == DirectoryType) AnalyseDirectory(pDirectoryEntry->pObject, DirectoryType, Level + 1); pDirectoryEntry = pDirectoryEntry->NextEntry; } }//end of 遍历37个记录 } |
六.对象的访问
内核中知道了内核对象的地址就可以直接访问这个内核对象了,但是在用户程序中却不能这样访问。Windows为内核对象的访问提供了一系列的函数。当调用一个用于创建内核对象的函数时,函数调用完便返回一个句柄值。句柄值是进程独立的,一个进程中的句柄值在另一个进程中是无效的。
句柄值是一个进程句柄表的索引。每个进程都有一个进程句柄表,而所有进程的句柄表串成一个句柄表链。这个链的头部地址保存在内核变量HandleTableListHead中。
下面具体看一下句柄表结构。系统将句柄表组织成和线性地址解析一样的结构。句柄表是个三层的表结构,而句柄值也被分成三部分,用来分别索引这三个部分。下面是句柄解析图:

七.总结
本文可以说是一个读书笔记。在参考了很多文章的基础上,然后作一些试验才完成本文的。内核对象是Windows内部的重要数据结构。通过本文可以大致了解Windows是如何组织众多的对象的。
八.参考
1.《Undocumented Windows 2000 Secrets》
2.Anathema《Inside Windows Nt Object Manager》
3.webcrazy《剖析Windows NT/2000内核对象组织》
4.《Inside Windows 2000》
5.《Windows核心编程》
注意:本节描述的句柄是再WIN2K下的句柄.WINXP下句柄表结构已经完全不同.
(转)WINDOWS内核对象的更多相关文章
- Windows内核对象
1. 内核对象 Windows中每个内核对象都只是一个内存块,它由操作系统内核分配,并只能由操作系统内核进行访问,应用程序不能在内存中定位这些数据结构并直接更改其内容.这个内存块是一个数据结构,其成员 ...
- windows内核对象句柄
内核对象用于管理进程.线程和文件等诸多种类的大量资源,每一个内核对象都只是一个句内存快,它由操作系统内核分配,并只能右操作系统内核访问.这个内存块是一个数据结构,其维护着与对象相关的信息,其中少数成员 ...
- windows内核对象管理学习笔记
目前正在阅读毛老师的<windows内核情景分析>一书对象管理章节,作此笔记. Win内核中是使用对象概念来描述管理内核中使用到的数据结构.此对象(Object)均是由对象头(Object ...
- windows内核对象可以等待
内核对象有两种状态 触发 与未触发. 是可以等待的.
- 内核对象&句柄&泄漏&检测
今天看到这个问题如何评价王垠的 <讨厌的 C# IDisposable 接口>? - 王垠(人物),答案被歪到windows 内核对象和句柄,答案中谈的太浅显而且有误.翻出陈年老文章(此文 ...
- windows核心编程---第八章 使用内核对象进行线程同步
使用内核对象进行线程同步. 前面我们介绍了用户模式下线程同步的几种方式.在用户模式下进行线程同步的最大好处就是速度非常快.因此当需要使用线程同步时用户模式下的线程同步是首选. 但是用户模式下的线程同步 ...
- Windows API学习---线程与内核对象的同步
前言 若干种内核对象,包括进程,线程和作业.可以将所有这些内核对象用于同步目的.对于线程同步来说,这些内核对象中的每种对象都可以说是处于已通知或未通知的状态之中.这种状态的切换是由Microsoft为 ...
- Windows核心编程学习九:利用内核对象进行线程同步
注:源码为学习<Windows核心编程>的一些尝试,非原创.若能有助于一二访客,幸甚. 1.程序框架 #include "Queue.h" #include <t ...
- 内核对象 windows操作系统
问题: 什么是内核对象? 答:内核对象实际上时由内核分配的一块内存,而且只能由内核来访问.它时一个数据结构,成员包含有关于该对象的信息.一些成员对于所有对象类型都是一样的,比如对象名称.安全描述.使用 ...
随机推荐
- e.currentTarget
e.target总是指向点击的目标 e.currentTarget会指向这个点击标的冒泡对象 <div class="wrap"> wrap <div class ...
- 修改Eclipse的WorkSpace保持数[转载]
最近用Eclipse开发特别多,我个人习惯每一个项目一个WorkSpace,这样的话代码干净.而且当项目之前编码规范不一样时,也不会彼此影响.但项目一多,Eclipse默认只保存5个WorkSpace ...
- Thml 小插件8 天气插件定制
网址:http://www.tianqi.com/plugin/
- Echoprint系列--Android编译与调用
在Echoprint系列--编译中编译了源代码,这次将Echoprint移植到Android平台并測试识别歌曲功能. 一.编译库 1.环境准备 Android NDK,我的是android-ndk-r ...
- iPhone开发之全局变量的使用
全局变量历来就是很好的东西,能够在开发中带来很多方便,下面来介绍一下iPhone中软件开发时全局变量的使用方法: 一.新建Constants.h文件(文件名根据需要自己取),用于存放全局变量: 二.在 ...
- ASP.NET WebApi 简单记录
//获取当前提交过来的Request对象 var request = System.Web.HttpContext.Current.Request;
- iOS网络开发-AFNetworking请求asp.net WebService
看到园子有位朋友需要使用AFN框架请求 WebService,所以就整理了一下,demo下载链接在底部 编写WebService可以看这篇博客 http://www.cnblogs.com/linmi ...
- Servlet之ServletContext以及文件操作
ServletContext ------------------------------------ ServletContext是什么? 与cookie,session比较. 可以把它想象成一个共 ...
- UVA 10325 lottery 容斥原理
题目链接 给出m个数, 求1-n的范围内, 无法整除这m个数之中任何一个数的数的个数. 设m个数为a[i], 对任意的i, n/a[i]是n中可以整除a[i]的数的个数, 但是这样对于有些数重复计算了 ...
- Ubuntu 12.04中文输入法的安装(转)
Ubuntu上的输入法主要有小小输入平台(支持拼音/二笔/五笔等),Fcitx,Ibus,Scim等.其中Scim和Ibus是输入法框架. 在Ubuntu的中文系统中自带了中文输入法,通过Ctrl+S ...