为什么在内核模式下调用ZwCreateKey似乎绕过Windows安全?

Ben*_*enj 4 windows winapi kernel driver native-code

我与之合作的团队最近面临着使我们的软件与第三方虚拟化软件兼容的挑战.该软件使用内核驱动程序来执行Windows本机注册表API(ZwCreateKey等)的挂钩.它通过挂钩Ntdll中的调用来工作.我们的软件也相当低级,在某些情况下需要访问真实的注册表而不会被钩住.

我们正在探索使用我们自己的内核驱动程序来ZwCreateKey代表我们调用它们的可能性,以避免它们的挂钩.这实质上意味着创建一个NT Legacy驱动程序和一个用户模式库,它提供我们自己的本机注册表功能.库和驱动程序非常简单,我们只需使用IOCTL将所有参数传递ZwCreateKey给我们的驱动程序,然后调用内核版本的调用并返回结果.

该方法运行良好,我们现在似乎在虚拟化时具有读/写真实注册表的系统.唯一的问题是我们的新系统似乎在注册表对象上传播Windows安全性.

ZwCreateKey 采用这样的访问掩码:

NTSTATUS ZwCreateKey(
  __out       PHANDLE KeyHandle,
  __in        ACCESS_MASK DesiredAccess,
  __in        POBJECT_ATTRIBUTES ObjectAttributes,
  __reserved  ULONG TitleIndex,
  __in_opt    PUNICODE_STRING Class,
  __in        ULONG CreateOptions,
  __out_opt   PULONG Disposition
);
Run Code Online (Sandbox Code Playgroud)

我的理解是,虽然我们现在在内核模式下运行,但我们仍然拥有用户令牌的上下文.这应该意味着内核版本ZwCreateKey将失败,就像访问掩码测试失败时的用户一样.实际发生的是,即使使用有限的令牌,当我们的驱动程序被调用时,它也能够在受限用户调用时在受限制的部分HKLM中创建密钥.是什么赋予了?我们应该自己进行ACL检查吗?我们是否需要做一些事情来限制我们在内核模式下的权限?任何帮助非常感谢.

Lor*_*ias 7

检查一下以获得解释.用户模式(ntdll)中的Nt/Zw基本相同 - 它们在实际执行操作之前首先执行大量检查.从内核模式调用Zw函数时(如设备驱动程序的情况),省略这些检查,因为假设默认情况下信任来自内核模式组件(例如驱动程序)的信息