zoukankan      html  css  js  c++  java
  • 句柄的创建

     创建对象的三大步骤:

      1.通过ObCreateObject函数创建目标对象。

      2.目标对象本身的初始化

      3.通过ObInsertObject将目标对象插入对象目录和句柄表,并返回句柄。

     ObCreateObject函数用来创建一个指定类型的内核对象。

    NTSTATUS
    ObCreateObject(IN POBJECT_TYPE Type,
                   IN POBJECT_ATTRIBUTES ObjectAttributes OPTIONAL,
                   IN KPROCESSOR_MODE AccessMode,
                   IN ULONG ObjectSize,
                   IN ULONG PagedPoolCharge OPTIONAL,
                   IN ULONG NonPagedPoolCharge OPTIONAL,
                   OUT PVOID *Object)
    {
       ObjectCreateInfo = ObpAllocateObjectCreateInfoBuffer(LookasideCreateInfoList);
       Status = ObpCaptureObjectCreateInformation(ObjectAttributes,FALSE,ObjectCreateInfo,
    &ObjectName);//提取ObjectAttributes中的字段
       if (!PagedPoolCharge)
            PagedPoolCharge = Type->TypeInfo.DefaultPagedPoolCharge;
       if (!NonPagedPoolCharge)
            NonPagedPoolCharge = Type->TypeInfo.DefaultNonPagedPoolCharge;
       ObjectCreateInfo->PagedPoolCharge = PagedPoolCharge;
            ObjectCreateInfo->NonPagedPoolCharge = NonPagedPoolCharge;
       //从对应池中分配内存,创建对应的对象
       Status = ObpAllocateObject(ObjectCreateInfo,&ObjectName,Type,ObjectSize,AccessMode,
    &Header);
       return Status;
    }
    

      

      其实真正的工作函数是ObpAllocateObject,它内部调用ExAllocatePoolWithTag(ObjectType->PoolType, 可选头总大小+ ObjectSize, Tag)分配对象内存,然后初始化设置头部中的Flags等其他工作。(绝大多数内核对象都分配在非分页池中)

      ObCreateObject函数的第二个参数指向一个_OBJECT_ATTRIBUTES结构,这是一个非常重要的结构。

      

    typedef struct _OBJECT_ATTRIBUTES
    {
       ULONG Length;//本结构体的长度
       HANDLE RootDirectory;//相对目录(不一定是父目录)
       PUNICODE_STRING ObjectName;//相对RootDirectory这个目录的剩余路径 或者 全路径
       //上面两个字段一起间接构成对象的全路径
       ULONG Attributes;//打开属性,对象属性与句柄属性的混合
       PVOID SecurityDescriptor;// SD安全描述符
       PVOID SecurityQualityOfService;
    } OBJECT_ATTRIBUTES, *POBJECT_ATTRIBUTES;
    typedef CONST OBJECT_ATTRIBUTES *PCOBJECT_ATTRIBUTES;
    

      创建对象、打开对象时都会用到这个结构。

      

    OBJECT_ATTRIBUTES结构体中的Attributes字段是个混合成员,由句柄属性、对象属性、打开属性复合而成,可以取下面的组合

    OBJ_INHERIT://句柄属性,表示句柄是否可继承给子进程

    OBJ_PERMANENT://指该对象是否永久存在于对象目录中直到对象销毁.(目录符号链接设备文件 都是)

    OBJ_EXLUSIVE://对象属性,指该对象同一时刻只能被一个进程独占打开

    OBJ_CASE_INSENSITIVE://打开属性,表示本次打开操作查找比较对象名时大小写不敏感

    OBJ_OPENIF://打开属性,表示if对象存在就打开

    OBJ_OPENLINK://打开属性,表示本次打开是否可以直接打开符号链接

    OBJ_KERNEL_HANDLE://句柄属性,表示要求得到一个内核句柄

     

    而对象头中的Flags字段则完全表示对象的一些属性标志

    OB_FLAG_CREATE_INFO;//表示头部中含有创建时的属性信息

    OB_FLAG_CREATOR_INFO;//表示含有创建者进程信息

    OB_FLAG_KERNEL_MODE://表示PreviousMode是内核模式的代码创建的本对象

    OB_FLAG_EXCLUSIVE://表示同一时刻只能被一个进程独占打开

    OB_FLAG_PERMANET://永久性对象,直到对象完全销毁时才脱离对象目录

    OB_FLAG_SINGLE_PROCESS://表示含有每进程的句柄统计信息

    OB_FLAG_DEFER_DELETE;//标记本对象被延迟删除了

     

      创建的对象,如果有名字,就需要插入到对象目录和句柄表中。即使没有名字,也需要插入到句柄表中,这样才能让应用程序得以找到该对象以进行访问。这就是ObInsertObject函数的功能:

    NTSTATUS
    ObInsertObject(IN PVOID Object,
                   IN PACCESS_STATE AccessState OPTIONAL,
                   IN ACCESS_MASK DesiredAccess,
                   OUT PHANDLE Handle)//返回得到的句柄
    {
        ObjectHeader = OBJECT_TO_OBJECT_HEADER(Object);
        ObjectCreateInfo = ObjectHeader->ObjectCreateInfo;
        ObjectNameInfo = ObpReferenceNameInfo(ObjectHeader);
        ObjectType = ObjectHeader->Type;
        ObjectName = NULL;
        if ((ObjectNameInfo) && (ObjectNameInfo->Name.Buffer))
            ObjectName = &ObjectNameInfo->Name;
    PreviousMode = KeGetPreviousMode();
    //无名对象(并且不需要安全控制)就不挂入对象目录,仅仅插入句柄表中
        if ( (ObjectName==NULL) && !(ObjectType->TypeInfo.SecurityRequired))
        {
            ObjectHeader->ObjectCreateInfo = NULL;
            Status = ObpCreateUnnamedHandle(Object,DesiredAccess,ObjectCreateInfo->Attributes,
                                            PreviousMode,Handle);
            return Status;
        }
    
        InsertObject = Object;
        if (ObjectName)//若是一个有名对象
    {
        //这个函数有两种用途。
    //当Object不为NULL表示将Object插入到对象目录中的指定位置
        //当Object为NULL表示查找指定的对象目录位置处的对象
        //两种用途都将指定目录位置处的对象返回到InsertObject中
            Status = ObpLookupObjectName(ObjectCreateInfo->RootDirectory,
                                         ObjectName,
                                         ObjectCreateInfo->Attributes,
                                         ObjectType,
                                         ObjectCreateInfo->ParseContext,
                                         Object,//要插入的对象
                                         &InsertObject);//返回最终那个位置处的对象
            //如果原位置处已有同名对象,插入失败
            if ((NT_SUCCESS(Status)) && (InsertObject) && (Object != InsertObject))
            {
                OpenReason = ObOpenHandle;//既然插入失败了,那就是要打开对象,获得句柄
                if (ObjectCreateInfo->Attributes & OBJ_OPENIF)//检查本次打开操作的要求
                {
                    if (ObjectType != OBJECT_TO_OBJECT_HEADER(InsertObject)->Type)
                        Status = STATUS_OBJECT_TYPE_MISMATCH;
                    else
                        Status = STATUS_OBJECT_NAME_EXISTS;//看到没,应用层经常返回这个出错值        
                }
                else
                {
                    Status = STATUS_OBJECT_NAME_COLLISION;
                }
                return Status;
            }
        }
        if (InsertObject == Object)//if 插入成功
            OpenReason = ObCreateHandle;//只有第一次创建对象的时候才会插入对象目录中
        ObjectHeader->ObjectCreateInfo = NULL;//不再需要了
        if (Handle)//如果用户要求插入句柄表,就插入句柄表,得到一个句柄
        {
            Status = ObpCreateHandle(OpenReason,InsertObject,AccessState,
                                     ObjectCreateInfo->Attributes, PreviousMode,Handle);
        }
        return  Status;
    }
    

      

  • 相关阅读:
    右下角老弹出盗版提示,以及登录界面出现正版验证对话框
    动态TSQL语句常見問題與解決方案
    验证码
    远程调用存储过程
    windows powershell
    屏蔽IE浏览器的刷新(不包括单个刷新按钮)
    获取数据库中的数据库有多少个
    网页刷新方法集合
    Win7中IIS7安装配置
    sql 根据字段查表名
  • 原文地址:https://www.cnblogs.com/lsh123/p/8331058.html
Copyright © 2011-2022 走看看