Question

ZWOpenFile and NtOpenFile are both the functions of nt dll..ZwOpenFile is implemented as same as NtopenFile..but I dont understand why ZWopenFile is included in nt dll function.Can anyone please explain me the difference?

Was it helpful?

Solution

This is documented in MSDN:

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. For more information about how the routine distinguishes user-mode parameters from kernel-mode parameters, see PreviousMode.

Basically it relates to how the parameters are validated.

OTHER TIPS

Generally, kernel drivers should only use the ZwXxx() functions.

When called from user mode, the ZwXxx() and NtXxx() functions are exactly the same - they resolve to the same bits of code in ntdll.dll.

When called from a kernel-mode driver, the Zwxxx() variant ensures that a flag used by the kernel is set to indicate that the requestor mode (what's supposed to indicate the caller's mode) is kernel mode. If a kernel driver calls the NtXxx() variant the requestor mode isn't explicitly set so it's left alone and might indicate user or kernel mode, depending on what has occurred in the call stack up to this point.

If the requestor mode flag is set to user mode, the kernel will validate parameters, which might not be the right thing to do (especially if the kernel driver is passing in kernel mode buffers, as the validation will fail in that case), if it's set to kernel mode, the kernel implicitly trusts parameters.

So the rules for using these API names generally boils down to: if you're writing a kernel driver, call the ZwXxx() version (unless you're dealing with special situations, and you know what you're doing and why). If you're writing a user mode component, it doesn't matter which set you call.

As far as I know, Microsoft only documents the NtXxx() for use in user-mode (where it indicates that they are the user-mode equivalent to the corresponding ZwXxx() function).

Giving an example to what has already been said to ensure OP or anyone else gets a complete picture.

  1. NtXxx calls from user mode are resulting in passing less trusted data(from user mode) to a more privileged layer (kernel mode). So it expects the buffer has valid user mode address, the Handles being passed are valid user mode handles, etc.

  2. If a driver calls NtXxx api instead of its equivalent ZwXxx it has to ensure that valid user mode arguments are being passed i.e. it cannot pass a kernel mode address (even if it is valid) and a kernel mode handle (see OBJ_KERNEL_HANDLE).

  3. As already said the ZwXxx equivalent of the API explicitly indicates (through requestor level) that such parameter validation needs to be skipped as the callee is at the same privilege level as the caller.

Here is link to a good starting point for anyone who wants to go beyond the obvious, https://www.osronline.com/article.cfm?id=257.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top