Windows Native API:何时以及为何使用 Zw 与 Nt 前缀的 api 调用?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4770553/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Windows Native API: When and why use Zw vs Nt prefixed api calls?
提问by Shinnok
In Native API Microsoft exports two versions of each api call, one prefixed with Zw and one with Nt, for eg. ZwCreateThread and NtCreateThread.
在 Native API 中,Microsoft 导出每个 api 调用的两个版本,一个以 Zw 为前缀,一个以 Nt 为前缀,例如。ZwCreateThread 和 NtCreateThread。
My question is what is the difference between those two versions of the calls and when and why one should use Zw or Nt exclusively? To my understanding Zw version ensures that the caller resides in kernel mode, whereas Nt doesn't.
我的问题是这两个版本的调用之间有什么区别,何时以及为什么应该专门使用 Zw 或 Nt?据我了解,Zw 版本确保调用者驻留在内核模式中,而 Nt 则不会。
I am also wondering about the specific meaning for Zw and Nt prefixes/abbreviations? One can guess Nt probably refers to NT(New Technology) Windows family or Native(probably not)? As for Zw, does it stand for something?
我还想知道 Zw 和 Nt 前缀/缩写的具体含义?可以猜到 Nt 可能是指 NT(New Technology) Windows 系列还是 Native(可能不是)?至于Zw,它代表什么吗?
回答by user541686
Update:
更新:
Aside from Larry Osterman's answer (which you should definitelyread), there's another thing I should mention:
除了拉里·奥斯特曼的回答(你绝对应该阅读),还有一件事我应该提到:
Since the NtXxx variants perform checks as though the call is coming from user-mode, this means that any buffers passed to the NtXxs function must reside in user-mode address spaces, not kernel-mode. So if you call a function like NtCreateFile
in your driver and pass it pointers to kernel-mode buffers, you will get back a STATUS_ACCESS_VIOLATION
because of this.
由于 NtXxx 变体执行检查就好像调用来自用户模式一样,这意味着传递给 NtXxs 函数的任何缓冲区必须驻留在用户模式地址空间中,而不是内核模式。因此,如果您NtCreateFile
在驱动程序中调用一个函数并将其传递给内核模式缓冲区的指针,您将因此返回 a STATUS_ACCESS_VIOLATION
。
See Using Nt and Zw Versions of the Native System Services Routines.
A kernel-mode driver calls the Zw version of a native system services routine to inform the routine that the parameters come from a trusted, kernel-mode source. In this case, the routine assumes that it can safely use the parameters without first validating them. However, if the parameters might be from either a user-mode source or a kernel-mode source, the driver instead calls the Nt version of the routine, which determines, based on the history of the calling thread, whether the parameters originated in user mode or kernel mode.
Native system services routines make additional assumptions about the parameters that they receive. If a routine receives a pointer to a buffer that was allocated by a kernel-mode driver, the routine assumes that the buffer was allocated in system memory, not in user-mode memory. If the routine receives a handle that was opened by a user-mode application, the routine looks for the handle in the user-mode handle table, not in the kernel-mode handle table.
内核模式驱动程序调用本机系统服务例程的 Zw 版本,以通知例程参数来自受信任的内核模式源。在这种情况下,例程假定它可以安全地使用参数而无需首先验证它们。但是,如果参数可能来自用户模式源或内核模式源,驱动程序会调用 Nt 版本的例程,它根据调用线程的历史记录确定参数是否来自用户模式或内核模式。
本机系统服务例程对它们接收的参数做出额外的假设。如果例程接收到指向由内核模式驱动程序分配的缓冲区的指针,则例程假定缓冲区是在系统内存中分配的,而不是在用户模式内存中。如果例程接收到由用户模式应用程序打开的句柄,则例程会在用户模式句柄表中查找该句柄,而不是在内核模式句柄表中。
Also, Zw
doesn't stand for anything. See What Does the Zw Prefix Mean?:
此外,Zw
不代表任何东西。请参阅Zw 前缀是什么意思?:
The Windows native system services routines have names that begin with the prefixes Nt and Zw. The Nt prefix is an abbreviation of Windows NT, but the Zw prefix has no meaning. Zw was selected partly to avoid potential naming conflicts with other APIs, and partly to avoid using any potentially useful two-letter prefixes that might be needed in the future.
Windows 本机系统服务例程的名称以前缀 Nt 和 Zw 开头。Nt 前缀是 Windows NT 的缩写,但 Zw 前缀没有任何意义。选择 Zw 部分是为了避免与其他 API 的潜在命名冲突,部分是为了避免使用将来可能需要的任何潜在有用的两字母前缀。
回答by ReinstateMonica Larry Osterman
I was going to leave this as a comment on Merhdad's answer but it got too long...
我打算把它作为对 Merhdad 回答的评论,但它太长了......
Mehrdad's answer is 100% accurate. It is also slightly misleading. The "PreviousMode" article linked to by the "Using Nt and Zw..." article Mehrdad goes into it in more detail. Paraphrasing: The primary difference between the Nt and Zw API calls is that the Zw calls go through the system call dispatcher, but for drivers, Nt calls are direct calls to the API.
Mehrdad 的回答是 100% 准确的。这也有点误导。“使用 Nt 和 Zw...”文章链接到的“ PreviousMode”文章 Mehrdad 更详细地介绍了它。释义:Nt 和 Zw API 调用之间的主要区别在于 Zw 调用通过系统调用调度程序,但对于驱动程序,Nt 调用是对 API 的直接调用。
When a driver calls a Zw API, the only real effect of running through the system call dispatcher is that it sets KeGetPreviousMode() to KernelMode instead of UserMode (obviously to user mode code, the Zw and Nt forms are identical). When the various system calls see that ExGetPreviousMode is KernelMode, they bypass access checking (since drivers can do anything).
当驱动程序调用 Zw API 时,通过系统调用调度程序运行的唯一实际效果是它将 KeGetPreviousMode() 设置为 KernelMode 而不是 UserMode(显然对于用户模式代码,Zw 和 Nt 形式是相同的)。当各种系统调用看到 ExGetPreviousMode 是 KernelMode 时,它们会绕过访问检查(因为驱动程序可以做任何事情)。
If a driver calls the NT form of the APIs, it's possible that it will fail because of the access checks.
如果驱动程序调用 API 的 NT 形式,它可能会因为访问检查而失败。
A concrete example: if a driver calls NtCreateFile, the NtCreateFile will call SeAccessCheck() to see if the application which called into the driver has permissions to create the file. If that same driver called ZwCreateFile, the NtCreateFile API call won't call SeAccessCheck because ExGetPreviousMode returned KernelMode and thus the driver is assumed to have access to the file.
一个具体的例子:如果驱动程序调用 NtCreateFile,NtCreateFile 将调用 SeAccessCheck() 以查看调用驱动程序的应用程序是否具有创建文件的权限。如果同一个驱动程序调用 ZwCreateFile,则 NtCreateFile API 调用将不会调用 SeAccessCheck,因为 ExGetPreviousMode 返回 KernelMode,因此假定驱动程序有权访问该文件。
It's important for driver authors to understand the difference between the two since it can have profound implications for security...
驱动程序作者了解两者之间的区别很重要,因为它可能对安全性产生深远的影响......