Add winstd::system_impersonator
Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
parent
539828dd2c
commit
28b70eedb8
@ -37,5 +37,21 @@ namespace UnitTests
|
|||||||
if (!lib_shell32)
|
if (!lib_shell32)
|
||||||
Assert::Fail(L"LoadLibraryEx failed");
|
Assert::Fail(L"LoadLibraryEx failed");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST_METHOD(system_impersonator)
|
||||||
|
{
|
||||||
|
winstd::win_handle<NULL> processToken;
|
||||||
|
if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_DUPLICATE, processToken))
|
||||||
|
Assert::Fail(L"OpenProcessToken failed");
|
||||||
|
DWORD isElevated, dwLength;
|
||||||
|
if (!GetTokenInformation(processToken, TokenElevation, &isElevated, sizeof(isElevated), &dwLength))
|
||||||
|
Assert::Fail(L"GetTokenInformation failed");
|
||||||
|
winstd::system_impersonator system_impersonator;
|
||||||
|
// SYSTEM impersonation works in elevated processes only.
|
||||||
|
if (dwLength == sizeof(isElevated) && isElevated)
|
||||||
|
Assert::IsTrue(system_impersonator);
|
||||||
|
else
|
||||||
|
Assert::IsTrue(!system_impersonator && GetLastError() == ERROR_ACCESS_DENIED);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "Common.h"
|
#include "Common.h"
|
||||||
|
#include <tlhelp32.h>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
@ -1814,10 +1815,41 @@ namespace winstd
|
|||||||
ULONG_PTR m_cookie; ///< Cookie for context deactivation
|
ULONG_PTR m_cookie; ///< Cookie for context deactivation
|
||||||
};
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Base class for thread impersonation of another security context
|
||||||
|
///
|
||||||
|
class impersonator
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
///
|
||||||
|
/// Construct the impersonator
|
||||||
|
///
|
||||||
|
impersonator() noexcept : m_cookie(FALSE) {}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Reverts to current user and destructs the impersonator
|
||||||
|
///
|
||||||
|
/// \sa [RevertToSelf function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379317.aspx)
|
||||||
|
///
|
||||||
|
virtual ~impersonator()
|
||||||
|
{
|
||||||
|
if (m_cookie)
|
||||||
|
RevertToSelf();
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Did impersonation succeed?
|
||||||
|
///
|
||||||
|
operator bool () const { return m_cookie; }
|
||||||
|
|
||||||
|
protected:
|
||||||
|
BOOL m_cookie; ///< Did impersonation succeed?
|
||||||
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
/// Lets the calling thread impersonate the security context of a logged-on user
|
/// Lets the calling thread impersonate the security context of a logged-on user
|
||||||
///
|
///
|
||||||
class user_impersonator
|
class user_impersonator : public impersonator
|
||||||
{
|
{
|
||||||
WINSTD_NONCOPYABLE(user_impersonator)
|
WINSTD_NONCOPYABLE(user_impersonator)
|
||||||
WINSTD_NONMOVABLE(user_impersonator)
|
WINSTD_NONMOVABLE(user_impersonator)
|
||||||
@ -1834,20 +1866,64 @@ namespace winstd
|
|||||||
{
|
{
|
||||||
m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
|
m_cookie = hToken && ImpersonateLoggedOnUser(hToken);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Lets the calling thread impersonate the security context of the SYSTEM user
|
||||||
|
///
|
||||||
|
class system_impersonator : public impersonator
|
||||||
|
{
|
||||||
|
WINSTD_NONCOPYABLE(system_impersonator)
|
||||||
|
WINSTD_NONMOVABLE(system_impersonator)
|
||||||
|
|
||||||
|
public:
|
||||||
///
|
///
|
||||||
/// Reverts to current user and destructs the impersonator
|
/// Construct the impersonator and impersonates the SYSTEM user
|
||||||
///
|
///
|
||||||
/// \sa [RevertToSelf function](https://msdn.microsoft.com/en-us/library/windows/desktop/aa379317.aspx)
|
system_impersonator() noexcept
|
||||||
///
|
|
||||||
virtual ~user_impersonator()
|
|
||||||
{
|
{
|
||||||
if (m_cookie)
|
TOKEN_PRIVILEGES privileges = { 1, {{{ 0, 0 }, SE_PRIVILEGE_ENABLED }} };
|
||||||
RevertToSelf();
|
if (!LookupPrivilegeValue(NULL, SE_DEBUG_NAME, &privileges.Privileges[0].Luid) ||
|
||||||
}
|
!ImpersonateSelf(SecurityImpersonation))
|
||||||
|
return;
|
||||||
|
|
||||||
protected:
|
{
|
||||||
BOOL m_cookie; ///< Did impersonation succeed?
|
HANDLE h;
|
||||||
|
if (!OpenThreadToken(GetCurrentThread(), TOKEN_ADJUST_PRIVILEGES, FALSE, &h))
|
||||||
|
goto revert;
|
||||||
|
win_handle<INVALID_HANDLE_VALUE> thread_token(h);
|
||||||
|
if (!AdjustTokenPrivileges(thread_token, FALSE, &privileges, sizeof(privileges), NULL, NULL))
|
||||||
|
goto revert;
|
||||||
|
process_snapshot process_snapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
|
||||||
|
if (!process_snapshot)
|
||||||
|
goto revert;
|
||||||
|
PROCESSENTRY32 entry = { sizeof(PROCESSENTRY32) };
|
||||||
|
if (!Process32First(process_snapshot, &entry))
|
||||||
|
goto revert;
|
||||||
|
while (_tcsicmp(entry.szExeFile, TEXT("winlogon.exe")) != 0)
|
||||||
|
if (!Process32Next(process_snapshot, &entry))
|
||||||
|
goto revert;
|
||||||
|
process winlogon_process = OpenProcess(PROCESS_QUERY_INFORMATION, FALSE, entry.th32ProcessID);
|
||||||
|
if (!winlogon_process)
|
||||||
|
goto revert;
|
||||||
|
if (!OpenProcessToken(winlogon_process, TOKEN_IMPERSONATE | TOKEN_DUPLICATE, &h))
|
||||||
|
goto revert;
|
||||||
|
win_handle<INVALID_HANDLE_VALUE> winlogon_token(h);
|
||||||
|
if (!DuplicateToken(winlogon_token, SecurityImpersonation, &h))
|
||||||
|
goto revert;
|
||||||
|
win_handle<INVALID_HANDLE_VALUE> duplicated_token(h);
|
||||||
|
if (!SetThreadToken(NULL, duplicated_token))
|
||||||
|
goto revert;
|
||||||
|
}
|
||||||
|
|
||||||
|
m_cookie = TRUE;
|
||||||
|
return;
|
||||||
|
|
||||||
|
revert:
|
||||||
|
DWORD dwResult = GetLastError();
|
||||||
|
RevertToSelf();
|
||||||
|
SetLastError(dwResult);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
///
|
///
|
||||||
@ -2308,6 +2384,21 @@ static LSTATUS RegOpenKeyExW(
|
|||||||
return s;
|
return s;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
/// Opens the access token associated with a process
|
||||||
|
///
|
||||||
|
/// \sa [OpenProcessToken function](https://learn.microsoft.com/en-us/windows/win32/api/processthreadsapi/nf-processthreadsapi-openprocesstoken)
|
||||||
|
///
|
||||||
|
static BOOL OpenProcessToken(_In_ HANDLE ProcessHandle, _In_ DWORD DesiredAccess, _Inout_ winstd::win_handle<NULL> &TokenHandle)
|
||||||
|
{
|
||||||
|
HANDLE h;
|
||||||
|
if (OpenProcessToken(ProcessHandle, DesiredAccess, &h)) {
|
||||||
|
TokenHandle.attach(h);
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma warning(pop)
|
#pragma warning(pop)
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user