我之前写过一个有关于对象管理的读书笔记。但是这篇文章与前面的不同,这是我个人对对象管理器到底是什么的一个分析,而且也是直接对WRK代码进行的阅读。

执行体对象即我们通常所言的内核对象,我们知道Windows内核中有许多“管理器”,然而管理器并不是一个实体的存在而是一个抽象的概念。它更像是一系列相关函数和数据结构的集合。

《Windows Internals》中如此定义对象管理器:“本节将介绍Windows的对象管理器,即执行体内部负责创建、删除、保护和跟踪对象的组件”。

我们先从创建对象开始。依次是:创建对象、删除对象、引用对象、解除引用对象、控制对象访问、查找对象、

一.创建对象

对象创建操作肯定从r3传来。

针对每个对象类型都有各自的创建内核对象的函数。举个例子,

NtCreateFile()

NtCreateEvent()

NtCreateTimer()

NtCreateKey()

NtCreateProcess()

NtCreateThread()

这些函数都是由相应的Zw版本对应而来的。

这些函数内部都是用了ObCreateObject()这个函数来创建对象。

ObCreateObject()函数主要做了两件事

1.解析传入的OBJECT_ATTRIBUTES结构到对象的OBJECT_CREATE_INFORMATION结构以及其他结构中。

2.调用ObpAllocateObject()函数创建对象。

我们主要关注ObpAllocateObject()函数怎么创建的对象。

 NTSTATUS
ObpAllocateObject (
IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
IN KPROCESSOR_MODE OwnershipMode,
IN POBJECT_TYPE ObjectType OPTIONAL,
IN PUNICODE_STRING ObjectName,
IN ULONG ObjectBodySize,
OUT POBJECT_HEADER *ReturnedObjectHeader
) /*++ Routine Description: This routine allocates a new object including the object header
and body from pool and fill in the appropriate fields. Arguments: ObjectCreateInfo - Supplies the create information for the new object OwnershipMode - Supplies the processor mode of who is going to own
the object ObjectType - Optionally supplies the object type of the object being
created. If the object create info not null then this field must
be supplied. ObjectName - Supplies the name of the object being created ObjectBodySize - Specifies the size, in bytes, of the body of the object
being created ReturnedObjectHeader - Receives a pointer to the object header for the
newly created objet. Return Value: An appropriate status value. --*/ {
ULONG HeaderSize;
POBJECT_HEADER ObjectHeader;
ULONG QuotaInfoSize;
ULONG HandleInfoSize;
ULONG NameInfoSize;
ULONG CreatorInfoSize;
POBJECT_HEADER_QUOTA_INFO QuotaInfo;
POBJECT_HEADER_HANDLE_INFO HandleInfo;
POBJECT_HEADER_NAME_INFO NameInfo;
POBJECT_HEADER_CREATOR_INFO CreatorInfo;
POOL_TYPE PoolType; PAGED_CODE(); //
// Compute the sizes of the optional object header components.
// if (ObjectCreateInfo == NULL) { QuotaInfoSize = ;
HandleInfoSize = ;
NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );//OBJECT_HEADER_CREATOR_INFO一定存在 } else { //
// The caller specified some additional object create info
//
// First check to see if we need to set the quota
// if (((ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge ||
ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge ||
ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA) &&
PsGetCurrentProcess() != PsInitialSystemProcess) ||
(ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
//这时,配额头才是存在的
QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO ); } else { QuotaInfoSize = ;
} //
// Check if we are to allocate space to maintain handle counts
// if (ObjectType->TypeInfo.MaintainHandleCount) {
//这时,句柄头才是存在的
HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO ); } else { HandleInfoSize = ;
} //
// Check if we are to allocate space for the name
// if (ObjectName->Buffer != NULL) {
//这时,名字头才是存在的
NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO ); } else { NameInfoSize = ;
} //
// Finally check if we are to maintain the creator info
// if (ObjectType->TypeInfo.MaintainTypeList) { CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO ); } else { CreatorInfoSize = ;
}
} //
// Now compute the total header size
//
//计算整个头的大小
HeaderSize = QuotaInfoSize +
HandleInfoSize +
NameInfoSize +
CreatorInfoSize +
FIELD_OFFSET( OBJECT_HEADER, Body ); //
// Allocate and initialize the object.
//
// If the object type is not specified or specifies nonpaged pool,
// then allocate the object from nonpaged pool.
// Otherwise, allocate the object from paged pool.
// if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) {
//为啥等于空时要用非分页池?
PoolType = NonPagedPool; } else { PoolType = PagedPool;
} ObjectHeader = ExAllocatePoolWithTag( PoolType,
HeaderSize + ObjectBodySize,
(ObjectType == NULL ? 'TjbO' : ObjectType->Key) |//这里体现了对象类型中国Key字段的作用
PROTECTED_POOL ); if (ObjectHeader == NULL) { return STATUS_INSUFFICIENT_RESOURCES;
} //
// Now based on if we are to put in the quota, handle, name, or creator info we
// will do the extra work. This order is very important because we rely on
// it to free the object.
// if (QuotaInfoSize != ) {
//设置配额头OBJECT_HEADER_QUOTA_INFO
QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)ObjectHeader;
QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge;
QuotaInfo->ExclusiveProcess = NULL;
ObjectHeader = (POBJECT_HEADER)(QuotaInfo + );
} if (HandleInfoSize != ) {
//设置Handle头OBJECT_HEADER_HANDLE_INFO
HandleInfo = (POBJECT_HEADER_HANDLE_INFO)ObjectHeader;
HandleInfo->SingleEntry.HandleCount = ;
ObjectHeader = (POBJECT_HEADER)(HandleInfo + );
} if (NameInfoSize != ) {
//设置Name头OBJECT_HEADER_NAME_INFO
NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader;
NameInfo->Name = *ObjectName;
NameInfo->Directory = NULL;
NameInfo->QueryReferences = ; if ( (OwnershipMode == KernelMode)
&&
(ObjectCreateInfo != NULL)
&&
(ObjectCreateInfo->Attributes & OBJ_KERNEL_EXCLUSIVE) ) { NameInfo->QueryReferences |= OBP_NAME_KERNEL_PROTECTED;
} ObjectHeader = (POBJECT_HEADER)(NameInfo + );
} if (CreatorInfoSize != ) {
//设置创建信息头OBJECT_HEADER_CREATOR_INFO
CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader;
CreatorInfo->CreatorBackTraceIndex = ;
CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId;//把创建对象的进程的信息存在创建信息头中
InitializeListHead( &CreatorInfo->TypeList );//加入到同一类型的内核对象的列表 PERFINFO_ADD_OBJECT_TO_ALLOCATED_TYPE_LIST(CreatorInfo, ObjectType); ObjectHeader = (POBJECT_HEADER)(CreatorInfo + );
} //
// Compute the proper offsets based on what we have
// //设置OBJECT_HEADER中几个可选头的偏移值
if (QuotaInfoSize != ) { ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize); } else { ObjectHeader->QuotaInfoOffset = ;
} if (HandleInfoSize != ) { ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize); } else { ObjectHeader->HandleInfoOffset = ;
} if (NameInfoSize != ) { ObjectHeader->NameInfoOffset = (UCHAR)(NameInfoSize + CreatorInfoSize); } else { ObjectHeader->NameInfoOffset = ;
} //
// Say that this is a new object, and conditionally set the other flags
//
//添加标志位
ObjectHeader->Flags = OB_FLAG_NEW_OBJECT; if (CreatorInfoSize != ) { ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO;
} if (HandleInfoSize != ) { ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY;
} //
// Set the counters and its type
// ObjectHeader->PointerCount = ;//引用数
ObjectHeader->HandleCount = ;//句柄引用数
ObjectHeader->Type = ObjectType; //
// Initialize the object header.
//
// N.B. The initialization of the object header is done field by
// field rather than zeroing the memory and then initializing
// the pertinent fields.
//
// N.B. It is assumed that the caller will initialize the object
// attributes, object ownership, and parse context.
// //根据用户传入的参数设置OBJECT_HEADER的Flags值
if (OwnershipMode == KernelMode) { ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT;
} if (ObjectCreateInfo != NULL &&
ObjectCreateInfo->Attributes & OBJ_PERMANENT ) { ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT;
} if ((ObjectCreateInfo != NULL) &&
(ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) { ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT;
} ObjectHeader->ObjectCreateInfo = ObjectCreateInfo;
ObjectHeader->SecurityDescriptor = NULL; if (ObjectType != NULL) { InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfObjects); if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) { ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects;
}
} //返回的值
*ReturnedObjectHeader = ObjectHeader; return STATUS_SUCCESS;
}

我们可以看到实质上内核对象就是用ExAllocatePoolWithTag分配的一块内存。

这个是OBJECT_HEADER,大量的操作都针对这个位进行。

看以看到对象头和所有可选头的填充都在这个函数中完成。

      typedef struct _OBJECT_HEADER
{
LONG PointerCount;//引用计数
union
{
LONG HandleCount;//句柄计数
PVOID NextToFree;
};
POBJECT_TYPE Type;//对象类型
UCHAR NameInfoOffset;//OBJECT_HEADER_NAME_INFO偏移
UCHAR HandleInfoOffset;//OBJECT_HEADER_HANDLE_INFO偏移
UCHAR QuotaInfoOffset;//OBJECT_HEADER_QUOTA_INFO偏移
UCHAR Flags;//标明此对象各种的属性的标识符
union
{
POBJECT_CREATE_INFORMATION ObjectCreateInfo;//OBJECT_CREATE_INFORMATION结构地址
PVOID QuotaBlockCharged;
};
PVOID SecurityDescriptor;//安全描述符结构地址
QUAD Body;//对象体地址
} OBJECT_HEADER, *POBJECT_HEADER;

前面说ObCreateObject()函数“解析传入的OBJECT_ATTRIBUTES结构到对象的OBJECT_CREATE_INFORMATION结构以及其他结构中。”

在ObCreateObject()中的解析,在ObpAllocateObject()中派上了用途。ObpAllocateObject()不再有OBJECT_ATTRIBUTES结构作为参数。

二.删除对象

在ObDereferenceObject()中,会判断OBJECT_HEADER中的PointerCount值,如果为0就调用ObpDeleteObject()函数来进行删除。

ObpDeleteObject函数先把对象从OBJECT_HEADER_CREATOR_INFO.TypeList列表中删除,然后释放名字UNICODE_STRING的缓冲区,最后调用OBJECT_TYPE中定义的DeleteProcedure函数。

三.引用对象和解除引用对象

比如函数ObReferenceObjectByPointer()

引用和解除引用对象是在获取了OBJECT指针后,用OBJECT_TO_OBJECT_HEADER宏转换成OBJECT_HEADER指针,然后用InterlockedIncrement()加锁修改这个值。

四.控制对象访问

在打开一个对象时,参数中要填写预期的操作以申请权限。

Windows内核执行体对象管理器的操作过程与分析的更多相关文章

  1. Linux内核笔记——进程管理之执行体

    内核版本:linux-2.6.11 在Linux中,有多种执行体(指令流.执行单位),它们是CPU调度和分配资源的基本单位,它们是内核态可见的,即内核态下,每一种执行体都有对应的唯一数据结构task_ ...

  2. [Windows内核分析]KPCR结构体介绍 (CPU控制区 Processor Control Region)

    Windows内核分析索引目录:https://www.cnblogs.com/onetrainee/p/11675224.html 逆向分析操作系统内核代码至少需要具备两项技能: 段页汇编代码非常懂 ...

  3. windows内核窥探

    windows是一个非常优秀的OS,从今天开始,我要和大家共同分享windows给我们带来的快乐!本人只所以将自己的学习笔记与大家分享,一是让自己更深入的理解windows,再就是有什么疏漏之处,望大 ...

  4. Windows 内核(WRK)编译

    引子 WRK 是微软于 2006 年针对教育和学术界开放的 Windows 内核的部分源码, WRK(Windows Research Kernel)也就是 Windows 研究内核, 在 WRK 中 ...

  5. Windows内核驱动中操作文件

    本页主题:如何在windows内核驱动中对文件操作,实现对文件的拷贝.粘贴.删除.查询信息等,这是很常用也是很简单的方法. 部分内容参考:http://www.cppblog.com/aurain/a ...

  6. Windows 内核(WRK)简介

    引子 WRK 是微软于 2006 年针对教育和学术界开放的 Windows 内核的部分源码,WRK(Windows Research Kernel)也就是 Windows 研究内核,在 WRK 中不仅 ...

  7. 第一章 Windows内核概述

    第一章 Windows内核概述 这一章节描述了Windows内核知识中最重要的几个概念,这些话题在这本书之后会有更详细的描述,那些会与当前的主题密切相关.要确保你理解这个章节的概念,因为这些概念构成了 ...

  8. Windows内核开发-Windows内部概述-2-

    Windows内部概述-2- 线程: 执行代码的实体是线程.一个线程的包含在进程里面的,线程使用进程提供的资源来运行代码. 一个线程拥有以下的内容: 1:明确的运行模式,用户态或者内核态. 2:执行的 ...

  9. Windows内核开发-4-内核编程基础

    Windows内核开发-4-内核编程基础 这里会构建一个简单但是完整的驱动程序和一个客户端,部署内核执行一些平时user下无法执行的操作. 将通过以下内容进行讲解: 1 介绍 2 驱动初始化 3 Cr ...

随机推荐

  1. windows下载执行命令大全

      1.bitsadmin命令(只能命令下载到指定路径上,win7以上): bitsadmin /transfer myDownLoadJob /download /priority normal & ...

  2. python基础----封装、封装与扩展性

    从封装本身的意思去理解,封装就好像是拿来一个麻袋,把小猫,小狗,小王八,还有egon和alex一起装进麻袋,然后把麻袋封上口子.但其实这种理解相当片面 首先我们要了解 要封装什么 你钱包的有多少钱(数 ...

  3. C++堆和栈详解(转)

    一.预备知识—程序的内存分配    一个由C/C++编译的程序占用的内存分为以下几个部分    1.栈区(stack)—   由编译器自动分配释放   ,存放函数的参数值,局部变量的值等.其    操 ...

  4. move_base的 局部路径规划代码研究

    base_local_planner teb_local_planner parameter code g2o base_local_planner ROS wiki Given a plan to ...

  5. Selective Search for Object Recognition

    http://blog.csdn.net/charwing/article/details/27180421 Selective Search for Object Recognition 是J.R. ...

  6. jQuery中deferred的对象使用

    什么是deferred对象 开发网站的过程中,我们经常遇到某些耗时很长的javascript操作.其中,既有异步的操作(比如ajax读取服务器数据),也有同步的操作(比如遍历一个大型数组),它们都不是 ...

  7. 原生JS实现省市区(县)三级联动选择

    原文地址→看过来 写在前面 前段时间写一个关于天气的东西,里面的省市区(县)城市选择让我很头疼,在网上搜索出来大都是借助插件或者第三方库,感觉这样做代码会很重,所以索性就把几种城市选择的方式实现一遍, ...

  8. jQuery各版本CDN

    jquery-2.1.1 注:jquery-2.0以上版本不再支持IE 6/7/8)百度引用地址 (推荐目前最稳定的,不会出现延时打不开情况) 百度压缩版引用地址:<script src=”ht ...

  9. 使用inline-block,使前面img,后面空div居中显示在一行后,导致当div中有内容时,div下移问题

    .pro_li img,.pro_sm{display: inline-block; *display:inline;*zoom:1;vertical-align: middle ;} 解决方法:使用 ...

  10. Django之kindeditor

    1.什么是kindeditor? KindEditor是一套开源的HTML可视化编辑器,主要用于让用户在网站上获得所见即所得编辑效果,兼容IE.Firefox.Chrome.Safari.Opera等 ...