Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Windows Native API: When and why use Zw vs Nt prefixed api calls?

In Native API Microsoft exports two versions of each api call, one prefixed with Zw and one with Nt, for eg. ZwCreateThread and 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.

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?

like image 720
Shinnok Avatar asked Jan 22 '11 21:01

Shinnok


People also ask

What is the Native API why is it used?

The Native API is a lower-level interface for interacting with Windows that is rarely used by nonmalicious programs but is popular among malware writers. Calling functions in the Native API bypasses the normal Windows API.

What is NT API?

The Native API is a lightweight application programming interface (API) used by Windows NT and user mode applications. This API is used in the early stages of Windows NT startup process, when other components and APIs are still unavailable.


2 Answers

Update:

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.

like image 127
user541686 Avatar answered Sep 28 '22 22:09

user541686


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

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.

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

like image 34
ReinstateMonica Larry Osterman Avatar answered Sep 28 '22 23:09

ReinstateMonica Larry Osterman