Ответ 1
Друг передал меня Программирование безопасности Windows от Keith Brown, который точно отвечает на этот вопрос.
Первичные жетоны можно и нужно называть токенами процесса, а токены олицетворения могут и должны называться токеновыми маркерами. Первичные жетоны могут быть прикреплены только к процессу, а токены олицетворения могут быть прикреплены только к потокам. Все это. Они действительно могут быть свободно преобразованы с использованием DuplicateTokenEx
(если у вас есть необходимые права доступа к дескриптору, который вы хотите преобразовать, очевидно).
Со страницы 115 в книге:
BOOL DuplicateTokenEx( HANDLE ExistingToken, // in DWORD DesiredAccess, // in LPSECURITY_ATTRIBUTES Attributes, // in, optional SECURITY_IMPERSONATION_LEVEL ImpLevel, // in TOKEN_TYPE Type, // in PHANDLE NewToken); // out
...
Параметр
Type
является историческим артефактом. Если вы посмотрите на определение перечисленияTOKEN_TYPE
, вы обнаружите, что токены были таксономизированы на две категории: олицетворение против первичных токенов. Не подвешивайте эту номенклатуру; смысл на самом деле намного проще, чем кажется. Листы олицетворения могут быть прикреплены только к потокам, а первичные маркеры могут присоединяться только к процессам. Что все это значит. Таким образом, токен процесса, полученный ранее через OpenProcessToken, был основным маркером.В ранних версиях Windows NT (3.x) было гораздо более жесткое ограничение на то, что вы могли бы сделать с токеном, в зависимости от того, откуда вы его взяли, и, следовательно, был введен тип токена для отслеживания предполагаемое использование токена. Поскольку в этом тексте предполагается, что вы используете Windows NT 4.0 или выше, просто подумайте о токенах олицетворения как "токена токена" и первичного токена как "токен процесса" и используйте
DuplicateTokenEx
для преобразования между ними, когда это необходимо, Windows NT 4.0 разорвала границы между ними, введяDuplicateTokenEx
; версия этой версии Windows NT 3.x,DuplicateToken
, была жестко запрограммирована только для создания токенов олицетворения. Фактически, теперь вы должны увидеть глупую ошибку, из-за которой первый вызовSetThreadToken
терпит неудачу: код пытается привязать первичный токен (тот, который получен от процесса) к потоку (который требует олицетворения маркер). Это не-нет. Чтобы исправить как логическую проблему, так и глупую историческую проблему, здесь скорректированный код:
Другие вещи, которые не являются строго ответом на вопрос, но были упомянуты в вопросе:
- По-видимому,
ImpersonateLoggedOnUser
переходит на лишнюю милю и преобразует основные токены в маркеры олицетворения, аSetThreadToken
не беспокоит. Зачем? кто знает? Вероятно, по той же причине некоторые API-интерфейсы разрешают привилегии на время вызова, в то время как другие требуют, чтобы вызывающие абоненты сами включали эти привилегии. -
LogonUser
(иLsaLogonUser
), вероятно, возвращают токены олицетворения для сетевых входов из-за предположения о том, кто обычно выполняет сетевые входы в систему (например, стр. 83). - Вы можете создавать токены из пользовательского режима, используя недокументированную функцию NTDLL
ZwCreateToken
, для которой требуются довольно необычные привилегии (в частности, уникальныйSE_CREATE_TOKEN_NAME
). Вы, вероятно, не должны...