Windows Native API: When and why use Zw vs Nt prefixed API calls?
Asked Answered
B

3

20

In Native API, Microsoft exports two versions of each API call, one prefixed with Zw and one with Nt, for example. ZwCreateThread and NtCreateThread.

What is the difference between those two versions of the calls and when and why should one use Zw or Nt exclusively?

To my understanding, the Zw version ensures that the caller resides in kernel mode, whereas Nt doesn't.

What is 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?

Bastard answered 22/1, 2011 at 21:1 Comment(0)
P
17

Aside from Larry Osterman's answer (which you should definitely read), 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.


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.

Also, Zw doesn't stand for anything. See What Does the Zw Prefix Mean?:

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.

Putman answered 22/1, 2011 at 21:6 Comment(2)
Funny - we chose the API prefix for an important API on the basis that we didn't want to use a prefix which could be used for something important in the future.Marianelamariani
@Blank: Well, it is funny, but then again, I can't think of any better alternatives. :\Putman
S
14

I was going to leave this as a comment on user541686's answer, but it got too long...

user541686's answer is 100% accurate. It is also slightly misleading. The "PreviousMode" article linked to by the "Using Nt and Zw..." article user541686 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.

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).

If a driver calls the NT form of the APIs, it's possible that it will fail because of the access checks.

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.

It's important for driver authors to understand the difference between the two since it can have profound implications for security...

Stormi answered 23/1, 2011 at 16:55 Comment(0)
H
-1

Zw stands for Zero Wait (no time waste for parameters validation).

Hartz answered 3/2, 2023 at 8:18 Comment(1)
We really need some authoritative citation for this claim - especially considering the opposing statement in the citation given in another answer.Stokehold

© 2022 - 2024 — McMap. All rights reserved.