Windows 内核对象
2018-03-19 本文已影响0人
szn好色仙人
-
每个内核对象都只是一个内存块,由操作系统分配,并只能由操作内核访问。这个内存块是一个数据结构,其成员维护着与对象有关的信息。少数成员如:安全描述符和使用计数等是所有对象共有的。但其他大多数成员都是不同类型的对象特有的
-
为了增强操作系统的可靠性,内核对象句柄值是与进程相关的。所以,如果将句柄值传给另一个进程,那么另一个进程用此句柄值来进行调用时,会发生失败,更糟糕的是,他们会根据该句柄在我们进程的句柄表的索引来引用一个可能完全不同类型的内核对象
-
内核对象的拥有者是操作系统内核,而非进程。内核对象的生命期可能会长于创建他的那个线程。操作系统通过内核对象的使用计数,来确定内核对象的销毁时间
-
内核对象可以用一个安全描述符来保护。安全描述符描述了谁拥有对象、谁被允许使用和访问对象。用于创建内核对象的所有函数几乎都有一个指向SECURITY_ATTRIBUTES结构的指针作为参数,大多数情况下应传入NULL,这样创建的内核对象具有默认安全属性
-
一个进程在初始化时,系统将为其分配一个句柄表。这个句柄表仅供内核对象使用,一个进程初始化时候,其句柄表为空,当进程调用创建内核对象的 API 时,内核扫描进程的句柄表,查找一个空白的记录项并对其进行初始化
-
创建内核对象的 API 调用失败,返回值可能是 NULL 也可能是INVALID_HANDLE_VALUE
-
在不需要使用内核对象的时候,记得使用 CloseHandle 来释放资源
跨进程共享内核对象
-
使用对象句柄继承
- 只有在进程之间具有父子关系时,才可以使用对象句柄继承。
- 父进程若想子进程继承其某个对象句柄,必须使此对象句柄的安全属性中的 SECURITY_ATTRIBUTES::bInheritHandle 设为 TRUE,然后在调用 CreateProcess 中指定第五个参数为 TRUE,系统会遍历父进程的句柄表,将所有可继承的句柄都完全复制到子进程的句柄表中,且复制后的位置是一样的,这就意味着:在父进程与子进程之间的句柄值是完全一样的。随后系统会递增相应内核对象的使用计数
- 父进程通过命令行的形式或者其他方法将对应句柄值通知到子进程中,则子进程就可以正常使用继承的句柄了
- 进程可以通过SetHandleInformation来改变句柄的标志位,每个句柄目前有2个标志位:
HANDLE_FLAG_INHERIT //指明可继承性
HANDLE_FLAG_PROTECT_FROM_CLOSE //指明不可关闭句柄, 调用 CloseHandle 将会出错
SetHandleInformation(h, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT); //打开继承
SetHandleInformation(h, HANDLE_FLAG_INHERIT, 0); //关闭继承
- 进程可以通过GetHandleInformation来查询句柄的标志位
-
通过为内核对象命名(大部分内核对象都可以命名)
- 命名的名称长度为 260
- 所有的内核对象都共享一个命名空间,即使其类型不同
- Create* Open* 系列函数都可以用于打开已有的句柄。 Create* 系列的函数在指定名称的内核对象不存在的情况下,还会进行创建
-
利用 DuplicateHandle 来复制内核对象
https://msdn.microsoft.com/en-us/library/ms724251(VS.85).aspx