Почему вызов ZwCreateKey в режиме ядра обходит безопасность Windows?
Команда, с которой я работаю, недавно столкнулась с проблемой обеспечения совместимости нашего программного обеспечения со сторонним программным обеспечением для виртуализации. Это программное обеспечение использует драйвер ядра для выполнения перехвата API-интерфейса реестра Windows (ZwCreateKey
, так далее). Это работает путем перехвата вызовов в Ntdll. Наше программное обеспечение также довольно низкого уровня, и в некоторых контекстах требуется доступ к реальному реестру без перехвата.
Мы изучаем возможность использования нашего собственного драйвера ядра для вызова ZwCreateKey
и т. д., от нашего имени обходя их зацепками. По сути это означало создание драйвера NT Legacy и библиотеки пользовательского режима, которая обеспечивает собственные функции реестра. Библиотека и драйвер очень просты, мы просто используем IOCTL для передачи всех параметров для ZwCreateKey
и т. д. в наш драйвер, затем мы вызываем версию вызова ядра и возвращаем результаты.
Подход сработал хорошо, и у нас теперь есть система чтения / записи в реальном реестре при виртуализации. Единственная проблема заключается в том, что наша новая система, по-видимому, обеспечивает безопасность Windows для объектов реестра.
ZwCreateKey
принимает маску доступа примерно так:
NTSTATUS ZwCreateKey(
__out PHANDLE KeyHandle,
__in ACCESS_MASK DesiredAccess,
__in POBJECT_ATTRIBUTES ObjectAttributes,
__reserved ULONG TitleIndex,
__in_opt PUNICODE_STRING Class,
__in ULONG CreateOptions,
__out_opt PULONG Disposition
);
Насколько я понимаю, хотя мы теперь работали в режиме ядра, у нас все еще был контекст токена пользователя. Это должно означать, что версия ядра ZwCreateKey
потерпит неудачу точно так же, как пользователь, если бы не получился тест маски доступа. На самом деле происходит то, что даже с ограниченным токеном, когда вызывается наш драйвер, он может создавать ключи в ограниченных частях HKLM при вызове ограниченным пользователем. Что дает? Должны ли мы сами выполнять проверки ACL? Нужно ли что-то делать, чтобы ограничить наши собственные привилегии в режиме ядра? Любая помощь высоко ценится.
1 ответ
Проверьте это для объяснения. В основном, Nt/Zw в пользовательском режиме (ntdll) - это одно и то же - они сначала выполняют обширные проверки перед тем, как выполнять действие. Где, например, при вызове функций Zw из режима ядра (как в случае с драйвером устройства) эти проверки пропускаются, поскольку предполагается, что информация, поступающая из компонента режима ядра (например, из драйвера), должна быть доверенной по умолчанию