在第1阶段, ObInitSystem首先对每个处理器的PRCB结构的lookaside链表进行初始化。
在全局名字空间中创建根目录\
来看一下NtCreateDirectoryObject这个函数实际上是ObCreateObject和ObInsertDirectory的封装。其内部执行的操作很简单,一个是创建一个目录对象, 接着将该目录对象插入到全局名字空间中。
而函数ObCreateObject之前分析过,内部主要调用ObpAllocateObject, 初始化一个对象头部。
接着就是ObInsertObject在当前进程中的句柄表中插入该目录的句柄,并获该句柄的值, 其内部主要的工作流程如下:
调用ObpLookupObjectName确认在全局名字空间中是否存在该名称的目录。
如果存在但是并非是我们需要定位的对象类型,就不能重复插入,确认具体的原因后返回。这里有3种
如果说我们都没有找到该对象,就直接进行收尾工作后返回
如果定位到了该对象, 并且是我们需要插入的对象类型,首先需要做一些安全方面的工作。
为该对象在进程中创建句柄表项,并获取该句柄。
接着做了一些释放工作后ObInsertObject返回,并获取对象句柄。
句柄获取后NtCreateDirectoryObject便返回了。所以其内部创建了对应类型的对象后,返回指代该对象的句柄。接着调用了ObReferenceObjectByHandle来通过句柄引用了这个对象, 获取指向该对象的指针。
成功创建了该对象后, 为其制定DACL并再其中加入了ACE规则。
可以清晰的看到安全描述符身份为World时DACL规定其拥有查询遍历和读取权限。安全描述符身份为Admin或者System权限时DACL规定其拥有所有权限。
接着用同样的套路创建了KernelObjects和ObjectTypes目录
接着就把这几种新创建的目录类型插入全局名字空间里, 但要确保不能重复插入。调用ObpLookupDirectoryEntry检查全局名字空间中是否存在该目录,如果不存在就调用ObpInsertDirectoryEntry插入
最后调用了ObpCreateDosDevicesDirectory为驱动器盘符和Win32设备名创建了\DosDevices 目录对象
下面进入ObpCreateDosDevicesDirectory内看看里面到底做了什么:
为\DosDevices设定访问的DACL规则,即创建安全描述符。
创建全局\??目录对象
为刚刚的\??目录对象创建一个符号链接名, 即\??\GLOBALROOT
进入NtCreateSymbolicLinkObject内部查看一下是如何创建符号链接名的:
内部首先创建了符号链接名对象:
将目标对象的一些信息保存到符号链接对象的结构体内:
最后把符号链接对象插入到当前进程的句柄表内并获取代表该对象的句柄。这样就结束了。
用同样的方法创建了\??\Global符号链接, 在用户层如果想要访问这些内核对象只能通过这些符号链接来访问。
最后创建了\??\DosDevices符号链接对象
所以 ObpCreateDosDevicesDirectory 最终创建了一个\??目录对象并创建了3个指向它的符号链接。到这里对象管理器的阶段1初始化工作已经完成了。
(完)