对象句柄
驱动程序和用户模式组件通过 句柄访问大多数系统定义的对象。 句柄由 "句柄不透明" 数据类型表示。 (请注意,句柄不用于访问设备对象或驱动程序对象。 )
对于大多数对象类型,创建或打开对象的内核模式例程提供调用方的句柄。 然后,调用方在对象的后续操作中使用该句柄。
下面是驱动程序通常使用的对象类型的列表,以及提供该类型的对象的句柄的例程。
对象类型 | 对应的创建/打开例程 |
---|---|
文件 |
|
注册表项 |
IoOpenDeviceInterfaceRegistryKey、 IoOpenDeviceRegistryKey、 ZwCreateKey、 ZwOpenKey |
线程数 |
|
事件 |
|
符号链接 |
|
目录对象 |
|
节对象 |
当驱动程序不再需要访问该对象时,它将调用 ZwClose 例程来关闭该句柄。 这适用于上表中列出的所有对象类型。
提供句柄的大多数例程采用 OBJECT_ATTRIBUTES 结构作为参数。 此结构可用于为句柄指定属性。
驱动程序可以指定下列句柄属性:
OBJ_KERNEL_HANDLE
只能从内核模式访问句柄。
OBJ_INHERIT
当创建句柄时,当前进程的所有子级都将接收该句柄的副本。
OBJ_FORCE_ACCESS_CHECK
此属性指定系统对句柄执行所有访问检查。 默认情况下,系统会绕过在内核模式下创建的句柄的所有访问检查。
使用 InitializeObjectAttributes 例程在 OBJECT_ATTRIBUTES 结构中设置这些属性。
有关验证对象句柄的信息,请参阅 验证对象句柄失败。
专用对象句柄
每当驱动程序为其专用使用创建对象句柄时,驱动程序必须指定 OBJ_KERNEL_HANDLE 特性。 这可确保用户模式应用程序无法访问句柄。
共享对象句柄
必须仔细编写在内核模式和用户模式之间共享对象句柄的驱动程序,以避免意外创建安全漏洞。 下面是一些指导原则:
在内核模式下创建句柄并将其传递给用户模式,而不是其他方法。 用户模式组件创建并传递给驱动程序的句柄不应受信任。
如果驱动程序必须代表用户模式应用程序操作句柄,请使用 OBJ_FORCE_ACCESS_CHECK 特性来验证应用程序是否具有所需的访问权限。
使用 ObReferenceObjectByPointer 将内核模式引用保留在共享句柄上。 否则,如果用户模式组件关闭了句柄,则引用计数将变为零,并且如果驱动程序尝试使用或关闭句柄,系统会崩溃。
如果用户模式应用程序创建一个事件对象,则驱动程序可以安全等待该事件发出信号,但前提是该应用程序通过 IOCTL 将事件对象的句柄传递给驱动程序。 驱动程序必须在创建事件的进程的上下文中处理 IOCTL,并必须通过调用 ObReferenceObjectByHandle来验证该句柄是否为事件句柄。