Собственный API Windows: когда и почему используются вызовы API с префиксом Zw vs Nt?

В Native API Microsoft экспортирует две версии каждого вызова API, одну с префиксом Zw и одну с Nt, например. ZwCreateThread и NtCreateThread.

Мой вопрос: в чем разница между этими двумя версиями вызовов и когда и почему следует использовать исключительно Zw или Nt? Насколько я понимаю, версия Zw гарантирует, что вызывающая сторона находится в режиме ядра, а Nt - нет.

Меня также интересует конкретное значение префиксов / сокращений Zw и Nt? Можно предположить, что Nt, вероятно, относится к семейству Windows NT(Новая технология) или к Native(возможно, нет)? Что касается Zw, это означает что-то?

3 ответа

Решение

Обновить:

Помимо ответа Ларри Остермана (который вы обязательно должны прочитать), я должен упомянуть еще одну вещь:

Поскольку варианты NtXxx выполняют проверки, как будто вызов поступает из пользовательского режима, это означает, что любые буферы, передаваемые в функцию NtXxs, должны находиться в адресных пространствах пользовательского режима, а не в режиме ядра. Так что если вы вызываете функцию, такую ​​как NtCreateFile в вашем драйвере и передать его указатели в буферы режима ядра, вы получите обратно STATUS_ACCESS_VIOLATION из-за этого.


См. Использование версий Nt и Zw подпрограмм собственных системных служб.

Драйвер режима ядра вызывает версию Zw собственной подпрограммы системных служб, чтобы сообщить подпрограмме, что параметры поступают из надежного источника режима ядра. В этом случае подпрограмма предполагает, что она может безопасно использовать параметры без предварительной их проверки. Однако, если параметры могут быть из источника пользовательского режима или источника режима ядра, драйвер вместо этого вызывает версию подпрограммы Nt, которая на основе истории вызывающего потока определяет, были ли параметры созданы пользователем режим или режим ядра.

Собственные процедуры системных служб делают дополнительные предположения о параметрах, которые они получают. Если подпрограмма получает указатель на буфер, который был выделен драйвером режима ядра, подпрограмма предполагает, что буфер был выделен в системной памяти, а не в памяти пользовательского режима. Если подпрограмма получает дескриптор, открытый приложением пользовательского режима, она ищет дескриптор в таблице дескрипторов пользовательского режима, а не в таблице дескрипторов режима ядра.

Также, Zw не стоит ни за что. Посмотрите, что означает префикс Zw?:

Подпрограммы системных служб Windows имеют имена, которые начинаются с префиксов Nt и Zw. Префикс Nt является аббревиатурой от Windows NT, но префикс Zw не имеет смысла. Zw был выбран частично, чтобы избежать потенциальных конфликтов имен с другими API, и частично, чтобы избежать использования любых потенциально полезных двухбуквенных префиксов, которые могут понадобиться в будущем.

Я собирался оставить это как комментарий к ответу Мерхдада, но это слишком долго...

Ответ Мердада на 100% точен. Это также немного вводит в заблуждение. Статья " PreviousMode", на которую ссылается статья "Использование Nt и Zw...", Мехрдад, более детально описывает ее. Перефразируя: основное различие между вызовами API Nt и Zw состоит в том, что вызовы Zw проходят через диспетчер системных вызовов, но для драйверов вызовы Nt являются прямыми вызовами API.

Когда драйвер вызывает Zw API, единственным реальным эффектом работы диспетчера системных вызовов является то, что он устанавливает KeGetPreviousMode() в KernelMode вместо UserMode (очевидно, для кода режима пользователя формы Zw и Nt идентичны). Когда различные системные вызовы видят, что ExGetPreviousMode является KernelMode, они обходят проверку доступа (поскольку драйверы могут делать все что угодно).

Если драйвер вызывает NT-форму API, возможно, он потерпит неудачу из-за проверок доступа.

Конкретный пример: если драйвер вызывает NtCreateFile, NtCreateFile вызовет SeAccessCheck(), чтобы проверить, есть ли у приложения, вызвавшего драйвер, разрешения на создание файла. Если этот же драйвер называется ZwCreateFile, вызов API NtCreateFile не будет вызывать SeAccessCheck, поскольку ExGetPreviousMode вернул KernelMode и, следовательно, предполагается, что драйвер имеет доступ к файлу.

Для авторов драйверов важно понимать разницу между ними, поскольку это может иметь серьезные последствия для безопасности...

Zw означает нулевое ожидание (без потери времени на проверку параметров).

Другие вопросы по тегам