Я пытаюсь создать токен с повышенными правами SYSTEM
, но приведенный ниже код не работает:
#include <windows.h>
#include <stdio.h>
BOOL Elevate()
{
PSID pSID = NULL;
HANDLE hToken = NULL, hToken2 = NULL;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
fprintf(stderr, "OpenProcessToken(): %d\n", GetLastError());
goto done;
}
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hToken2))
{
fprintf(stderr, "DuplicateTokenEx(): %d\n", GetLastError());
goto done;
}
if (!AllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_MANDATORY_SYSTEM_RID,
0,
0, 0, 0, 0, 0, 0,
&pSID))
{
fprintf(stderr, "AllocateAndInitializeSid(): %d\n", GetLastError());
goto done;
}
if (!SetTokenInformation(hToken2, TokenIntegrityLevel, &pSID, sizeof(pSID)))
{
fprintf(stderr, "SetTokenInformation(): %d\n", GetLastError());
goto done;
}
done:
if (pSID)
{
FreeSid(pSID);
pSID = NULL;
}
CloseHandle(hToken);
CloseHandle(hToken2);
return TRUE;
}
int main(int argc, char** argv)
{
Elevate();
}
Сбой на SetTokenInformation
, код ошибки 24: ERROR_BAD_LENGTH
. Кто-нибудь знает, что случилось?
РЕДАКТИРОВАТЬ
Реми Лебо был прав, и я нашел пример здесь: https://wiki.sei.cmu.edu/confluence/display/c/WIN02-C.+Ограничение+привилегий+при+порождении+дочерних+процессов
Следуйте комментарию выше, попробуйте передать sizeof(SID)
вместо sizeof(pSID)
. Я на Mac, поэтому не проверял
Спасибо @Asesh, я пробовал sizeof(SID) и GetLastError() по-прежнему возвращает 24
@Asesh Независимо от основной проблемы с показанным кодом (передача неверных данных в SetTokenInformation()
), мне это кажется проблема XY. Для чего именно вы планируете использовать этот «повышенный» токен? Вероятно, есть лучшее решение. Предоставление любому произвольному процессу доступа с повышенными правами SYSTEM представляет серьезную угрозу безопасности.
в примере тоже была ошибка sizeof(tml) + GetLengthSid(psd)
когда должно быть ровно sizeof(tml)
Согласно документации TOKEN_INFORMATION_CLASS
TokenIntegrityLevel
The buffer receives aTOKEN_MANDATORY_LABEL
structure that specifies the token's integrity level.
Где TOKEN_MANDATORY_LABEL
определяется как:
typedef struct _SID_AND_ATTRIBUTES {
#if ...
PISID Sid;
#else
PSID Sid;
#endif
DWORD Attributes;
} SID_AND_ATTRIBUTES, *PSID_AND_ATTRIBUTES;
typedef struct _TOKEN_MANDATORY_LABEL {
SID_AND_ATTRIBUTES Label;
} TOKEN_MANDATORY_LABEL, *PTOKEN_MANDATORY_LABEL;
Итак, вам нужно указать SetTokenInformation()
указатель на TOKEN_MANDATORY_LABEL
, а не указатель на SID
, например:
#include <windows.h>
#include <stdio.h>
BOOL Elevate()
{
TOKEN_MANDATORY_LABEL tml = {};
HANDLE hToken = NULL, hToken2 = NULL;
SID_IDENTIFIER_AUTHORITY NtAuthority = SECURITY_NT_AUTHORITY;
BOOL result = FALSE;
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &hToken))
{
fprintf(stderr, "OpenProcessToken(): %ul\n", GetLastError());
goto done;
}
if (!DuplicateTokenEx(hToken, MAXIMUM_ALLOWED, NULL, SecurityImpersonation, TokenPrimary, &hToken2))
{
fprintf(stderr, "DuplicateTokenEx(): %ul\n", GetLastError());
goto done;
}
if (!AllocateAndInitializeSid(
&NtAuthority,
1,
SECURITY_MANDATORY_SYSTEM_RID,
0,
0, 0, 0, 0, 0, 0,
&(tml.Label.SID)))
{
fprintf(stderr, "AllocateAndInitializeSid(): %ul\n", GetLastError());
goto done;
}
tml.Label.Attributes = ...; // desired integrity level
if (!SetTokenInformation(hToken2, TokenIntegrityLevel, &tml, sizeof(tml)))
{
fprintf(stderr, "SetTokenInformation(): %ul\n", GetLastError());
goto done;
}
result = TRUE;
done:
if (tml.Label.SID) FreeSid(tml.Label.SID);
if (hToken) CloseHandle(hToken);
if (hToken2) CloseHandle(hToken2);
return result;
}
int main(int argc, char** argv)
{
Elevate();
}
pSID
— это указатель, поэтомуsizeof(pSID)
всегда будет возвращать размер указателя (32-битный или 64-битный). Ожидаемое значение последнего аргумента отличается: docs.microsoft.com/en-us/windows/win32/api/securitybaseapi/…