Вот код, где я пытаюсь выдать себя за пользователя, а затем создать мьютекс. Мьютекс не создается. Я получаю ошибку ERROR_ACCESS_DENIED.
void Impersonate()
{
DWORD logonType = LOGON32_LOGON_INTERACTIVE;
DWORD logonProvider = LOGON32_PROVIDER_DEFAULT;
HANDLE userToken;
HANDLE hMutex;
DWORD err;
LPSTR user = "zoom"; // the user I created myself on my machine.
// It has Administrator privileges, and my account,
// from which I start the app, is Admin too
LPSTR password = "zoom";
LPSTR domain = ".";
hMutex = NULL;
LogonUserA(user, domain, password, logonType, logonProvider,&userToken);
// just to make sure that mutexes are created fine before impersonation
hMutex = CreateMutexA( NULL, FALSE, "mutex_good" );
ImpersonateLoggedOnUser(userToken);
hMutex = CreateMutexA( NULL, FALSE, "mutex_797" ); // I can set any
// random name, no difference
if( hMutex == NULL )
{
err = GetLastError();
// here err is ERROR_ACCESS_DENIED
}
CloseHandle(userToken);
}
Я нашел несколько похожих тем, но все они обсуждали создание мьютекса с тем же именем из двух разных пользовательских контекстов, то есть мьютекс «MUTEX_1» уже был создан до олицетворения и пытался вызвать CreateMutex с тем же именем, но из олицетворенного сбой пользователя из-за отсутствия привилегий.
Это не тот случай, так как я совершенно уверен, что перед этим кодом не создается мьютекс с тем же именем (или вообще каким-либо мьютексом).
Я думаю, что я должен передать что-то ненулевое в CreateMutex, но что именно?
Я не очень хорош в безопасности Windows. Я понимаю, что передача NULL в качестве первого параметра CreateMutex означает, что будут использоваться атрибуты безопасности по умолчанию. В этом случае это будут параметры безопасности, связанные с потоком, то есть с имитируемым пользователем.
Я прав с моими предположениями?
прежде всего вам нужно понять Пространства имен NT и использовать WinObj инструмент.
это как небольшая файловая система в памяти с папками и разными «файлами» (здесь под «файлами» подразумеваются разные типы объектов — Event
, Mutant
(Мьютекс), Section
, Device
…) каждый раз, когда вы создаете именованный объект — он помещается в какую-то папку в Пространства имен NT. папки здесь (например, папки в NTFS) имеют дескрипторы безопасности. В результате не каждый может создать объект в любой папке.
Перефразируя то, что вы делаете на языке файловой системы (возможно, это будет более понятно):
я (John
) попробуйте создать файл «mutex_good» под %USERPROFILE%\Documents
и это нормально. потому что это моя личная папка, и у меня есть доступ для записи в нее.
тогда я вхожу (подражаю) как zoom
и попробуйте создать файл «mutex_797» снова под %USERPROFILE%\Documents
(%USERPROFILE%
в обоих случаях расширяться по тому же пути, скажем c:\Users\John
подражание не влияет на это)
а также zoom
не удалось создать файл. Зачем ? просто у него нет прав на это. только John
, Administartors
, SYSTEM
иметь доступ к записи c:\Users\John
но нет zoom
,
теперь давай вернемся к Пространства имен NT. когда мы звоним CreateMutexA( NULL, FALSE, "mutex_797" );
где "mutex_797"
будет размещен?
если ты не appcontainer
и не запускается в системе session 0
— ты бегаешь в каком-то пользователе session <N>
и ваши именованные объекты будут помещены в \Sessions\<N>\BaseNamedObjects
каталог, где N = 1,2 ..
так зовите CreateMutexA( NULL, FALSE, "mutex_797" );
попробуйте создать мьютекс в \Sessions\<N>\BaseNamedObjects\mutex_797
Однако в \Sessions\<N>\BaseNamedObjects
существуют следующие SymbolicLinks (это как в файловой системе NTFS):
Global -> \BaseNamedObjects
Local -> \Sessions\<N>\BaseNamedObjects
Session -> \Sessions\BNOLINKS
так сказать, если вы позвоните CreateMutexA( NULL, FALSE, "Global\\mutex_797" );
Диспетчер объектов попробуйте разместить свой мьютекс под \BaseNamedObjects\mutex_797
для получения дополнительной информации об этом прочитать Пространства имен объектов ядра
и конечно надо понимать Как работает AccessCheck
Для объектов каталога определены следующие права доступа:
//
// Object Manager Directory Specific Access Rights.
//
#define DIRECTORY_QUERY (0x0001)
#define DIRECTORY_TRAVERSE (0x0002)
#define DIRECTORY_CREATE_OBJECT (0x0004)
#define DIRECTORY_CREATE_SUBDIRECTORY (0x0008)
Также можете больше прочитать об этом на DirectoryObject DesiredAccess Флаги
нам нужно DIRECTORY_CREATE_OBJECT
доступ (Доступ для создания имени к объекту каталога) для создания мьютекса (или события, или любого объекта) в каталоге
Теперь для понимания, почему вы можете создать мьютекс в \Sessions\<N>\BaseNamedObjects
но zoom
нельзя — нужно искать Security Descriptor
для этой папки. я бросаю это:
T FL AcessMsK Sid
0 00 000F000F S-1-5-90-0-1 DWM-1
0 00 000F000F S-1-5-18 SYSTEM
0 0B 10000000 S-1-5-18 SYSTEM
0 0B 10000000 S-1-3-0 CREATOR OWNER
0 00 000F000F S-1-5-21-4026734978-3280735129-2412320105-1001 John
0 0B 10000000 S-1-5-5-0-294807 LogonSessionId_0_294807
0 00 0002000F S-1-5-5-0-294807 LogonSessionId_0_294807
0 00 0002000F S-1-5-32-544 Administrators
0 02 00000003 S-1-1-0 Everyone
0 00 00000002 S-1-5-12 RESTRICTED
17 00 00000001 S-1-16-4096 Low Mandatory Level
так у кого DIRECTORY_CREATE_OBJECT
(4) здесь? DWM-1
, SYSTEM
, Administrators
, текущие пользователи сеанса входа в систему (LogonSessionId_0_294807
), текущий пользователь (John
) — и все. zoom
нет такого доступа.
например Everyone
иметь (3) — DIRECTORY_QUERY|DIRECTORY_TRAVERSE
— Name lookup
а также Query
но нет Name creation
Вы можете спросить, где в этом случае я могу создать мьютекс после подражания? нужно использовать \BaseNamedObjects
( глобальное пространство имен )ИЛИ ЖЕ \BaseNamedObjects\Restricted
каталог — я проверяю его дескриптор безопасности и результат:
за \BaseNamedObjects
T FL AcessMsK Sid
0 00 0002000F S-1-1-0 Everyone
0 00 00000002 S-1-5-12 RESTRICTED
0 00 000F000F S-1-5-90-0-0
0 00 000F000F S-1-5-18 SYSTEM
17 00 00000001 S-1-16-4096 Low Mandatory Level
за \BaseNamedObjects\Restricted
T FL AcessMsK Sid
0 00 0002000F S-1-1-0 Everyone
0 00 0002000F S-1-5-12 RESTRICTED
0 00 000F000F S-1-5-90-0-0
0 00 000F000F S-1-5-18 SYSTEM
17 00 00000001 S-1-16-4096 Low Mandatory Level
так как вы можете просматривать Everyone
здесь есть 2000F — все необходимые доступ. надежда zoom
является членом Everyone
? следующий код, я уверен, будет работать
CreateMutexA(0, 0, "Global\\mutex_797");
за \BaseNamedObjects
(глобальное пространство имен) существует одно исключение:
Создание объекта сопоставления файлов в глобальном пространстве имен
используя CreateFileMapping, из сеанса, отличного от нулевого сеанса, является
привилегированная операция. Из-за этого приложение работает в
произвольный сеанс сервера Узел сеансов удаленных рабочих столов (Узел сеансов удаленных рабочих столов)
должен быть включен SeCreateGlobalPrivilege для создания
объект сопоставления файлов в глобальном пространстве имен успешно.
проверка привилегий ограничивается созданием объектов сопоставления файлов,
и не распространяется на открытие существующих. Например, если услуга
или система создает объект сопоставления файлов, любой процесс, выполняющийся в
любой сеанс может получить доступ к этому объекту сопоставления файлов при условии, что пользователь
имеет необходимый доступ.
но для Mutex или, скажем, Event — не нужно SeCreateGlobalPrivilege включен
Вы также можете сказать, но zoom
является учетной записью администратора и Administrator
иметь доступ к \Sessions\<N>\BaseNamedObjects
— так почему это не работает? потому что с LOGON32_LOGON_INTERACTIVE
а также UAC
система присваивается zoom
фильтрованный токен Administrator
Группа (S-1-5-32-544
) существует в токене но с SE_GROUP_USE_FOR_DENY_ONLY
только атрибут — в результате он игнорирует ACE с разрешенным доступом для SID.
а также zoom
есть другой LogonSessionId_0_XXX
SID — как результат и ERROR_ACCESS_DENIED
как отметил @ Гарри Джонстон — если мы будем использовать LOGON32_LOGON_BATCH
вместо LOGON32_LOGON_INTERACTIVE
— мы получили повышенный токен — здесь Administrator
Группа будет с SE_GROUP_ENABLED
атрибут — включен для проверок доступа для разрешенных ACE доступа
или как я предложил — используйте Global\
префикс перед именем — для объекта размещения \BaseNamedObjects
где Everyone
иметь полный доступ
Я понимаю передачу NULL в качестве первого параметра
CreateMutex
средства
эти атрибуты безопасности по умолчанию будут использоваться. В этом случае это будет
быть параметрами безопасности, связанными с потоком, то есть с
выдававший себя за пользователя.
первый параметр — указатель на SECURITY_ATTRIBUTES
Позволяет переписать дескриптор безопасности по умолчанию для нового объекта. это контроль, кто будет иметь доступ к нему. но это не дает вам более или менее доступ к каталогу, где вы пытаетесь разместить объект — вы должны иметь DIRECTORY_CREATE_OBJECT
доступ предоставлен, и мы не можем повлиять на это SECURITY_ATTRIBUTES
— это влияет на новый объект но не в существующем каталоге
и, наконец, некоторая визуализация NT Namespace
Других решений пока нет …