• Windows内核执行体对象管理器的操作过程与分析


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

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

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

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

    一.创建对象

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

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

    NtCreateFile()

    NtCreateEvent()

    NtCreateTimer()

    NtCreateKey()

    NtCreateProcess()

    NtCreateThread()

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

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

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

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

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

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

      1 NTSTATUS
      2 ObpAllocateObject (
      3     IN POBJECT_CREATE_INFORMATION ObjectCreateInfo,
      4     IN KPROCESSOR_MODE OwnershipMode,
      5     IN POBJECT_TYPE ObjectType OPTIONAL,
      6     IN PUNICODE_STRING ObjectName,
      7     IN ULONG ObjectBodySize,
      8     OUT POBJECT_HEADER *ReturnedObjectHeader
      9     )
     10 
     11 /*++
     12 
     13 Routine Description:
     14 
     15     This routine allocates a new object including the object header
     16     and body from pool and fill in the appropriate fields.
     17 
     18 Arguments:
     19 
     20     ObjectCreateInfo - Supplies the create information for the new object
     21 
     22     OwnershipMode - Supplies the processor mode of who is going to own
     23         the object
     24 
     25     ObjectType - Optionally supplies the object type of the object being
     26         created. If the object create info not null then this field must
     27         be supplied.
     28 
     29     ObjectName - Supplies the name of the object being created
     30 
     31     ObjectBodySize - Specifies the size, in bytes, of the body of the object
     32         being created
     33 
     34     ReturnedObjectHeader - Receives a pointer to the object header for the
     35         newly created objet.
     36 
     37 Return Value:
     38 
     39     An appropriate status value.
     40 
     41 --*/
     42 
     43 {
     44     ULONG HeaderSize;
     45     POBJECT_HEADER ObjectHeader;
     46     ULONG QuotaInfoSize;
     47     ULONG HandleInfoSize;
     48     ULONG NameInfoSize;
     49     ULONG CreatorInfoSize;
     50     POBJECT_HEADER_QUOTA_INFO QuotaInfo;
     51     POBJECT_HEADER_HANDLE_INFO HandleInfo;
     52     POBJECT_HEADER_NAME_INFO NameInfo;
     53     POBJECT_HEADER_CREATOR_INFO CreatorInfo;
     54     POOL_TYPE PoolType;
     55 
     56     PAGED_CODE();
     57 
     58     //
     59     //  Compute the sizes of the optional object header components.
     60     //
     61 
     62     if (ObjectCreateInfo == NULL) {
     63 
     64         QuotaInfoSize = 0;
     65         HandleInfoSize = 0;
     66         NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
     67         CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );//OBJECT_HEADER_CREATOR_INFO一定存在
     68 
     69     } else {
     70 
     71         //
     72         //  The caller specified some additional object create info
     73         //
     74         //  First check to see if we need to set the quota
     75         //
     76 
     77         if (((ObjectCreateInfo->PagedPoolCharge != ObjectType->TypeInfo.DefaultPagedPoolCharge ||
     78               ObjectCreateInfo->NonPagedPoolCharge != ObjectType->TypeInfo.DefaultNonPagedPoolCharge ||
     79               ObjectCreateInfo->SecurityDescriptorCharge > SE_DEFAULT_SECURITY_QUOTA) &&
     80                  PsGetCurrentProcess() != PsInitialSystemProcess) ||
     81             (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
     82             //这时,配额头才是存在的
     83             QuotaInfoSize = sizeof( OBJECT_HEADER_QUOTA_INFO );
     84 
     85 
     86         } else {
     87 
     88             QuotaInfoSize = 0;
     89         }
     90 
     91         //
     92         //  Check if we are to allocate space to maintain handle counts
     93         //
     94 
     95         if (ObjectType->TypeInfo.MaintainHandleCount) {
     96             //这时,句柄头才是存在的
     97             HandleInfoSize = sizeof( OBJECT_HEADER_HANDLE_INFO );
     98 
     99 
    100         } else {
    101 
    102             HandleInfoSize = 0;
    103         }
    104 
    105         //
    106         //  Check if we are to allocate space for the name
    107         //
    108 
    109         if (ObjectName->Buffer != NULL) {
    110             //这时,名字头才是存在的
    111             NameInfoSize = sizeof( OBJECT_HEADER_NAME_INFO );
    112 
    113 
    114         } else {
    115 
    116             NameInfoSize = 0;
    117         }
    118 
    119         //
    120         //  Finally check if we are to maintain the creator info
    121         //
    122 
    123         if (ObjectType->TypeInfo.MaintainTypeList) {
    124 
    125             CreatorInfoSize = sizeof( OBJECT_HEADER_CREATOR_INFO );
    126 
    127         } else {
    128 
    129             CreatorInfoSize = 0;
    130         }
    131     }
    132 
    133     //
    134     //  Now compute the total header size
    135     //
    136     //计算整个头的大小
    137     HeaderSize = QuotaInfoSize +
    138                  HandleInfoSize +
    139                  NameInfoSize +
    140                  CreatorInfoSize +
    141                  FIELD_OFFSET( OBJECT_HEADER, Body );
    142 
    143     //
    144     //  Allocate and initialize the object.
    145     //
    146     //  If the object type is not specified or specifies nonpaged pool,
    147     //  then allocate the object from nonpaged pool.
    148     //  Otherwise, allocate the object from paged pool.
    149     //
    150 
    151     if ((ObjectType == NULL) || (ObjectType->TypeInfo.PoolType == NonPagedPool)) {
    152         //为啥等于空时要用非分页池?
    153         PoolType = NonPagedPool;
    154 
    155     } else {
    156 
    157         PoolType = PagedPool;
    158     }
    159 
    160     ObjectHeader = ExAllocatePoolWithTag( PoolType,
    161                                           HeaderSize + ObjectBodySize,
    162                                           (ObjectType == NULL ? 'TjbO' : ObjectType->Key) |//这里体现了对象类型中国Key字段的作用
    163                                             PROTECTED_POOL );
    164 
    165     if (ObjectHeader == NULL) {
    166 
    167         return STATUS_INSUFFICIENT_RESOURCES;
    168     }
    169 
    170     //
    171     //  Now based on if we are to put in the quota, handle, name, or creator info we
    172     //  will do the extra work.  This order is very important because we rely on
    173     //  it to free the object.
    174     //
    175 
    176     if (QuotaInfoSize != 0) {
    177         //设置配额头OBJECT_HEADER_QUOTA_INFO
    178         QuotaInfo = (POBJECT_HEADER_QUOTA_INFO)ObjectHeader;
    179         QuotaInfo->PagedPoolCharge = ObjectCreateInfo->PagedPoolCharge;
    180         QuotaInfo->NonPagedPoolCharge = ObjectCreateInfo->NonPagedPoolCharge;
    181         QuotaInfo->SecurityDescriptorCharge = ObjectCreateInfo->SecurityDescriptorCharge;
    182         QuotaInfo->ExclusiveProcess = NULL;
    183         ObjectHeader = (POBJECT_HEADER)(QuotaInfo + 1);
    184     }
    185 
    186     if (HandleInfoSize != 0) {
    187         //设置Handle头OBJECT_HEADER_HANDLE_INFO
    188         HandleInfo = (POBJECT_HEADER_HANDLE_INFO)ObjectHeader;
    189         HandleInfo->SingleEntry.HandleCount = 0;
    190         ObjectHeader = (POBJECT_HEADER)(HandleInfo + 1);
    191     }
    192 
    193     if (NameInfoSize != 0) {
    194         //设置Name头OBJECT_HEADER_NAME_INFO
    195         NameInfo = (POBJECT_HEADER_NAME_INFO)ObjectHeader;
    196         NameInfo->Name = *ObjectName;
    197         NameInfo->Directory = NULL;
    198         NameInfo->QueryReferences = 1;
    199 
    200         if ( (OwnershipMode == KernelMode) 
    201                 && 
    202              (ObjectCreateInfo != NULL)
    203                 &&
    204              (ObjectCreateInfo->Attributes & OBJ_KERNEL_EXCLUSIVE) ) {
    205 
    206             NameInfo->QueryReferences |= OBP_NAME_KERNEL_PROTECTED;
    207         }
    208        
    209         ObjectHeader = (POBJECT_HEADER)(NameInfo + 1);
    210     }
    211 
    212     if (CreatorInfoSize != 0) {
    213         //设置创建信息头OBJECT_HEADER_CREATOR_INFO
    214         CreatorInfo = (POBJECT_HEADER_CREATOR_INFO)ObjectHeader;
    215         CreatorInfo->CreatorBackTraceIndex = 0;
    216         CreatorInfo->CreatorUniqueProcess = PsGetCurrentProcess()->UniqueProcessId;//把创建对象的进程的信息存在创建信息头中
    217         InitializeListHead( &CreatorInfo->TypeList );//加入到同一类型的内核对象的列表
    218 
    219         PERFINFO_ADD_OBJECT_TO_ALLOCATED_TYPE_LIST(CreatorInfo, ObjectType);
    220 
    221         ObjectHeader = (POBJECT_HEADER)(CreatorInfo + 1);
    222     }
    223 
    224     //
    225     //  Compute the proper offsets based on what we have
    226     //
    227     
    228     //设置OBJECT_HEADER中几个可选头的偏移值
    229     if (QuotaInfoSize != 0) {
    230 
    231         ObjectHeader->QuotaInfoOffset = (UCHAR)(QuotaInfoSize + HandleInfoSize + NameInfoSize + CreatorInfoSize);
    232 
    233     } else {
    234 
    235         ObjectHeader->QuotaInfoOffset = 0;
    236     }
    237 
    238     if (HandleInfoSize != 0) {
    239 
    240         ObjectHeader->HandleInfoOffset = (UCHAR)(HandleInfoSize + NameInfoSize + CreatorInfoSize);
    241 
    242     } else {
    243 
    244         ObjectHeader->HandleInfoOffset = 0;
    245     }
    246 
    247     if (NameInfoSize != 0) {
    248 
    249         ObjectHeader->NameInfoOffset =  (UCHAR)(NameInfoSize + CreatorInfoSize);
    250 
    251     } else {
    252 
    253         ObjectHeader->NameInfoOffset = 0;
    254     }
    255 
    256     //
    257     //  Say that this is a new object, and conditionally set the other flags
    258     //
    259     //添加标志位
    260     ObjectHeader->Flags = OB_FLAG_NEW_OBJECT;
    261 
    262     if (CreatorInfoSize != 0) {
    263 
    264         ObjectHeader->Flags |= OB_FLAG_CREATOR_INFO;
    265     }
    266 
    267     if (HandleInfoSize != 0) {
    268 
    269         ObjectHeader->Flags |= OB_FLAG_SINGLE_HANDLE_ENTRY;
    270     }
    271 
    272     //
    273     //  Set the counters and its type
    274     //
    275 
    276     ObjectHeader->PointerCount = 1;//引用数
    277     ObjectHeader->HandleCount = 0;//句柄引用数
    278     ObjectHeader->Type = ObjectType;
    279 
    280     //
    281     //  Initialize the object header.
    282     //
    283     //  N.B. The initialization of the object header is done field by
    284     //       field rather than zeroing the memory and then initializing
    285     //       the pertinent fields.
    286     //
    287     //  N.B. It is assumed that the caller will initialize the object
    288     //       attributes, object ownership, and parse context.
    289     //
    290 
    291     //根据用户传入的参数设置OBJECT_HEADER的Flags值
    292     if (OwnershipMode == KernelMode) {
    293 
    294         ObjectHeader->Flags |= OB_FLAG_KERNEL_OBJECT;
    295     }
    296 
    297     if (ObjectCreateInfo != NULL &&
    298         ObjectCreateInfo->Attributes & OBJ_PERMANENT ) {
    299 
    300         ObjectHeader->Flags |= OB_FLAG_PERMANENT_OBJECT;
    301     }
    302 
    303     if ((ObjectCreateInfo != NULL) &&
    304         (ObjectCreateInfo->Attributes & OBJ_EXCLUSIVE)) {
    305 
    306         ObjectHeader->Flags |= OB_FLAG_EXCLUSIVE_OBJECT;
    307     }
    308 
    309     ObjectHeader->ObjectCreateInfo = ObjectCreateInfo;
    310     ObjectHeader->SecurityDescriptor = NULL;
    311 
    312     if (ObjectType != NULL) {
    313 
    314         InterlockedIncrement((PLONG)&ObjectType->TotalNumberOfObjects);
    315 
    316         if (ObjectType->TotalNumberOfObjects > ObjectType->HighWaterNumberOfObjects) {
    317 
    318             ObjectType->HighWaterNumberOfObjects = ObjectType->TotalNumberOfObjects;
    319         }
    320     }
    321 
    322 
    323     //返回的值
    324     *ReturnedObjectHeader = ObjectHeader;
    325 
    326     return STATUS_SUCCESS;
    327 }
    View Code

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

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

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

     1      typedef struct _OBJECT_HEADER
     2 {
     3      LONG PointerCount;//引用计数
     4      union
     5      {
     6           LONG HandleCount;//句柄计数
     7           PVOID NextToFree;
     8      };
     9      POBJECT_TYPE Type;//对象类型
    10      UCHAR NameInfoOffset;//OBJECT_HEADER_NAME_INFO偏移
    11      UCHAR HandleInfoOffset;//OBJECT_HEADER_HANDLE_INFO偏移
    12      UCHAR QuotaInfoOffset;//OBJECT_HEADER_QUOTA_INFO偏移
    13      UCHAR Flags;//标明此对象各种的属性的标识符
    14      union
    15      {
    16           POBJECT_CREATE_INFORMATION ObjectCreateInfo;//OBJECT_CREATE_INFORMATION结构地址
    17           PVOID QuotaBlockCharged;
    18      };
    19      PVOID SecurityDescriptor;//安全描述符结构地址
    20      QUAD Body;//对象体地址
    21 } 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()加锁修改这个值。

    四.控制对象访问

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

  • 相关阅读:
    获取Spring项目配置文件元素
    MyEclipse安装插件的几种方法
    排序-->桶排序
    排序-->冒泡排序
    排序-->选择排序
    排序-->插入排序
    约瑟夫问题----(数组+list)实现
    约瑟夫问题--->环形链表
    py---pycharm快捷键
    双向链表--简单的增删改查
  • 原文地址:https://www.cnblogs.com/Ox9A82/p/5420345.html
Copyright © 2020-2023  润新知