在Native API中,Microsoft导出每个api调用的两个版本,一个以Zw为前缀,另一个以Nt为前缀,例如。 ZwCreateThread和NtCreateThread。
我的问题是这两个版本的调用之间有什么区别,以及何时以及为什么应该只使用Zw或Nt? 据我所知,Zw版本确保调用者驻留在内核模式,而Nt则不然。
我也想知道Zw和Nt前缀/缩写的具体含义? 可以猜测Nt可能是指NT(新技术)Windows系列或Native(可能不是)? 至于Zw,它代表什么?
答案 0 :(得分:12)
除了Larry Osterman的答案(你应该明确阅读),我还应该提到另一件事:
由于NtXxx变体执行检查就像调用来自用户模式一样,这意味着传递给NtXxs函数的任何缓冲区必须驻留在用户模式地址空间中,而不是内核模式 。因此,如果在驱动程序中调用类似NtCreateFile
的函数并将其传递给内核模式缓冲区,则会因此而返回STATUS_ACCESS_VIOLATION
。
请参阅Using Nt and Zw Versions of the Native System Services Routines。
内核模式驱动程序调用本机系统服务例程的Zw版本,以通知例程该参数来自可信的内核模式源。在这种情况下,例程假定它可以安全地使用参数而无需先验证它们。但是,如果参数可能来自用户模式源或内核模式源,则驱动程序会调用例程的Nt版本,该例程根据调用线程的历史记录确定参数是否源自用户模式或内核模式。
本机系统服务例程对它们收到的参数做出了额外的假设。如果例程接收到指向由内核模式驱动程序分配的缓冲区的指针,则例程假定缓冲区是在系统内存中分配的,而不是在用户模式内存中。如果例程接收到由用户模式应用程序打开的句柄,则例程在用户模式句柄表中查找句柄,而不是在内核模式句柄表中。
此外,Zw
不代表任何事情。见What Does the Zw Prefix Mean?:
Windows本机系统服务例程的名称以前缀Nt和Zw开头。 Nt前缀是Windows NT的缩写,但Zw前缀没有任何意义。部分选择Zw是为了避免与其他API发生潜在的命名冲突,部分原因是为了避免使用将来可能需要的任何可能有用的双字母前缀。
答案 1 :(得分:11)
我打算将此作为对Merhdad答案的评论,但它太长了......
Mehrdad的回答是100%准确的。这也有点误导。由“使用Nt和Zw ......”文章链接的“PreviousMode”文章更详细地介绍了Mehrdad。复述: Nt和Zw API调用之间的主要区别在于Zw调用通过系统调用调度程序,但用于驱动程序,Nt调用是直接调用API。
当驱动程序调用Zw API时,通过系统调用调度程序运行的唯一真正效果是它将KeGetPreviousMode()设置为KernelMode而不是UserMode(显然是用户模式代码,Zw和Nt形式相同)。当各种系统调用看到ExGetPreviousMode是KernelMode时,它们会绕过访问检查(因为驱动程序可以执行任何操作)。
如果驱动程序调用了API的NT形式,则可能由于访问检查而失败。
一个具体示例:如果驱动程序调用NtCreateFile,NtCreateFile将调用SeAccessCheck()以查看调用驱动程序的应用程序是否有权创建该文件。如果该驱动程序名为ZwCreateFile,则NtCreateFile API调用将不会调用SeAccessCheck,因为ExGetPreviousMode返回KernelMode,因此假定驱动程序可以访问该文件。
对于驾驶员作者而言,了解两者之间的区别非常重要,因为它可能会对安全产生深远的影响...