Windows本机API:何时以及为什么使用Zw vs Nt前缀API调用?

Windows本机API:何时以及为什么使用Zw vs Nt前缀API调用?,windows,winapi,nt-native-api,Windows,Winapi,Nt Native Api,在本机API中,Microsoft导出每个API调用的两个版本,一个前缀为Zw,另一个前缀为Nt,例如ZwCreateThread和NtCreateThread 我的问题是,这两个版本的调用之间有什么区别,何时以及为什么应该只使用Zw或Nt? 据我所知,Zw版本确保调用者驻留在内核模式,而Nt则没有 我还想知道Zw和Nt前缀/缩写的具体含义? 可以猜测Nt可能指Nt(新技术)Windows系列或本机(可能不是)? 至于Zw,它代表什么吗 更新: 除了拉里·奥斯特曼(Larry Osterman)

在本机API中,Microsoft导出每个API调用的两个版本,一个前缀为Zw,另一个前缀为Nt,例如ZwCreateThread和NtCreateThread

我的问题是,这两个版本的调用之间有什么区别,何时以及为什么应该只使用Zw或Nt? 据我所知,Zw版本确保调用者驻留在内核模式,而Nt则没有

我还想知道Zw和Nt前缀/缩写的具体含义? 可以猜测Nt可能指Nt(新技术)Windows系列或本机(可能不是)? 至于Zw,它代表什么吗

更新: 除了拉里·奥斯特曼(Larry Osterman)的回答(你肯定应该读一下),还有一件事我应该提到:

由于NtXxx变体执行检查时好像调用来自用户模式,这意味着传递给NtXxs函数的任何缓冲区都必须驻留在用户模式地址空间中,而不是内核模式中。因此,如果在驱动程序中调用像
NtCreateFile
这样的函数,并将其指针传递到内核模式缓冲区,则会因此返回
状态\u访问\u冲突


内核模式驱动程序调用本机系统服务例程的Zw版本,通知例程参数来自可信的内核模式源。在这种情况下,例程假定它可以安全地使用参数,而无需首先验证它们。但是,如果参数可能来自用户模式源或内核模式源,则驱动程序将调用例程的Nt版本,该例程根据调用线程的历史确定参数是源自用户模式还是内核模式

本机系统服务例程对其接收的参数进行附加假设。如果例程接收到指向内核模式驱动程序分配的缓冲区的指针,则例程假定缓冲区是在系统内存中分配的,而不是在用户模式内存中分配的。如果例程接收到由用户模式应用程序打开的句柄,则例程将在用户模式句柄表中查找该句柄,而不是在内核模式句柄表中

而且,
Zw
并不代表任何东西。见:

Windows本机系统服务例程的名称以前缀Nt和Zw开头。Nt前缀是Windows Nt的缩写,但Zw前缀没有任何含义。选择Zw部分是为了避免与其他API的命名冲突,部分是为了避免使用将来可能需要的任何可能有用的两个字母前缀


我本想把这作为对默哈德答案的评论,但时间太长了

Mehrdad的答案100%准确。这也有点误导。Mehrdad在“使用Nt和Zw…”链接的“文章”中对此进行了更详细的介绍。释义: Nt和ZWAPI调用之间的主要区别在于,Zw调用通过系统调用调度程序,但是对于驱动程序,Nt调用是对API的直接调用

当驱动程序调用ZWAPI时,通过系统调用调度程序运行的唯一实际效果是它将KeGetPreviousMode()设置为KernelMode而不是UserMode(显然对于用户模式代码,Zw和Nt表单是相同的)。当各种系统调用看到ExGetPreviousMode是KernelMode时,它们会绕过访问检查(因为驱动程序可以做任何事情)

如果驱动程序调用API的NT形式,它可能会因为访问检查而失败

一个具体示例:如果驱动程序调用NtCreateFile,NtCreateFile将调用SeAccessCheck(),以查看调用驱动程序的应用程序是否具有创建该文件的权限。如果同一个驱动程序调用了ZwCreateFile,则NtCreateFile API调用将不会调用SeAccessCheck,因为ExGetPreviousMode返回了KernelMode,因此假定驱动程序可以访问该文件


驱动程序作者必须理解两者之间的区别,因为这对安全性有着深远的影响…

有趣-我们为一个重要的API选择了API前缀,因为我们不想使用一个将来可能用于重要事情的前缀。@Blank:好吧,这很有趣,但话说回来,我想不出更好的选择了\