проблема здесь в вызове
// Impersonate
ImpersonateLoggedOnUser(hTok2); // Returns true
несмотря на ImpersonateLoggedOnUser
верните true, действительно функция может делать не то, что вы ожидаете
Все олицетворяющие функции, включая ImpersonateLoggedOnUser разрешают
запрашиваемое олицетворение, если выполняется одно из следующих условий:
- Запрашиваемый уровень олицетворения токена меньше SecurityImpersonation , например SecurityIdentification или SecurityAnonymous .
- Вызывающий имеет привилегию SeImpersonatePrivilege .
...
так что даже для действительного hToken api может завершиться с ошибкой, но не обычным способом - вместо возврата false и установки кода ошибки - api в любом случае возвращает true, но беззвучно сбрасывает уровень олицетворения токена потока на SecurityIdentification
, после этого все вызовы, которые выполняют проверки безопасности, завершаются с ERROR_BAD_IMPERSONATION_LEVEL
или ERROR_ACCESS_DENIED
.
в общем случае процесс без повышенных прав не имеет привилегии SeImpersonatePrivilege
, в результате чего, когда мы пытаемся подменить себя с маркером с повышенными правами, вызов формально не завершится неудачно, но вместо этого мы получим SecurityIdentification
уровень олицетворения SecurityImpersonation
. даже если он повышен (или LocalSystem , или даже в режиме ядра), попробуйте установить токен с повышенными правами для потока в процессе, который не имеет привилегии SeImpersonatePrivilege
- эта попытка задает только уровень SecurityIdentification
.
мы можем легко проверить это, позвонив по OpenThreadToken
и запросив TokenImpersonationLevel
.
полный код теста:
inline ULONG BOOL_TO_ERROR(BOOL f)
{
return f ? NOERROR : GetLastError();
}
void WINAPI entry(void*)
{
HANDLE hToken, hThread, hDupToken;
ULONG dwError;
// for attach debugger
MessageBoxW(0, 0, GetCommandLineW(), 0);
if (PWSTR c = wcschr(GetCommandLineW(), '*'))
{
ULONG dwThreadId = wcstoul(c + 1, &c, 16);
dwError = ERROR_INVALID_PARAMETER;
if (!*c && dwThreadId)
{
dwError = BOOL_TO_ERROR(OpenProcessToken(GetCurrentProcess(), TOKEN_DUPLICATE|TOKEN_IMPERSONATE, &hToken));
if (dwError == NOERROR)
{
dwError = BOOL_TO_ERROR(DuplicateToken(hToken, ::SecurityImpersonation, &hDupToken));
CloseHandle(hToken);
if (dwError == NOERROR)
{
if (hThread = OpenThread(THREAD_SET_THREAD_TOKEN, FALSE, dwThreadId))
{
dwError = RtlNtStatusToDosError(
ZwSetInformationThread(hThread, ThreadImpersonationToken, &hDupToken, sizeof(hDupToken))
);
CloseHandle(hThread);
}
else
{
dwError = GetLastError();
}
CloseHandle(hDupToken);
}
}
}
ExitProcess(dwError);
}
WCHAR file[MAX_PATH], params[32];
if (GetModuleFileNameW(0, file, RTL_NUMBER_OF(file)))
{
SHELLEXECUTEINFOW sei = {
sizeof(sei), SEE_MASK_NOCLOSEPROCESS, 0, L"runas", file, params
};
swprintf(params, L"*%x", GetCurrentThreadId());
dwError = BOOL_TO_ERROR(ShellExecuteExW(&sei));
if (dwError == NOERROR)
{
switch (WaitForSingleObject(sei.hProcess, INFINITE))
{
case WAIT_OBJECT_0:
if (GetExitCodeProcess(sei.hProcess, &dwError))
{
break;
}
case WAIT_FAILED:
dwError = GetLastError();
break;
default:
__debugbreak();
dwError = ERROR_GEN_FAILURE;
}
CloseHandle(sei.hProcess);
if (dwError == NOERROR)
{
if (OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, TRUE, &hToken))
{
ULONG cb;
SECURITY_IMPERSONATION_LEVEL sil;
if (GetTokenInformation(hToken, ::TokenImpersonationLevel, &sil, sizeof(sil), &cb))
{
DbgPrint("ImpersonationLevel = %x\n", sil);
}
CloseHandle(hThread);
}
union {
HANDLE hFile;
HKEY hKey;
};
hFile = CreateFileW(file, 0, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if (hFile == INVALID_HANDLE_VALUE)
{
DbgPrint("CreateFile=%u\n", GetLastError());
}
else
{
CloseHandle(hFile);
}
dwError = RegOpenKeyExW(HKEY_CURRENT_USER, 0, 0, KEY_READ, &hKey);
if (dwError)
{
DbgPrint("OpenKey=%u\n", dwError);
}
else
{
RegCloseKey(hKey);
}
}
}
}
ExitProcess(dwError);
}
, так что это специально - отключите не повышенные (менее Высокий уровень целостности ) процессы, олицетворяющие повышенные токены, удалив SeImpersonatePrivilege
из токена процесса. это эффективно устраняет все попытки выдать себя за высокий или более высокий уровень целостности