AuroraRuntime/Source/Processes/AuProcessElevation.NT.cpp

1014 lines
36 KiB
C++

/***
Copyright (C) 2023 J Reece Wilson (a/k/a "Reece"). All rights reserved.
File: AuProcessElevation.NT.cpp
Date: 2023-12-23
Author: Reece
***/
#include <Source/RuntimeInternal.hpp>
#include "AuProcessElevation.NT.hpp"
#include <tlhelp32.h>
enum _SE_OBJECT_TYPE
{
SE_KERNEL_OBJECT = 6
};
#if !defined(POLICY_ALL_ACCESS)
#define POLICY_ALL_ACCESS 0xf0fff
#endif
namespace Aurora::Processes
{
struct SecureRunAs
{
RunAsDescriptor desc;
AuList<int> pids {};
bool bRepeat {};
SECURITY_DESCRIPTOR sd {};
void BlankMemory()
{
if (this->desc.password)
{
AuMemset(this->desc.password.value().data(),
0,
this->desc.password.value().size());
}
}
static HANDLE GetProcessTokenHandle()
{
static HANDLE gHandle = INVALID_HANDLE_VALUE;
static AuInitOnce gInitOnce;
if (pOpenProcessToken)
{
gInitOnce.Call([&]()
{
pOpenProcessToken(OpenProcess(PROCESS_ALL_ACCESS, FALSE, GetCurrentProcessId()),
TOKEN_ALL_ACCESS, &gHandle);
});
}
return gHandle;
}
static DWORD GetTokenIntegrityLevel()
{
char buffer[1000];
TOKEN_MANDATORY_LABEL &info = *(TOKEN_MANDATORY_LABEL *)buffer;
DWORD dwLength { 1000 };
if (!pGetTokenInformation ||
!pGetSidSubAuthority ||
!pGetSidSubAuthorityCount)
{
return -1;
}
if (!pGetTokenInformation(GetProcessTokenHandle(), TokenIntegrityLevel, &info, 1000, &dwLength))
{
return -1;
}
auto pSid = info.Label.Sid;
auto dwIntegrityLevel = *(pGetSidSubAuthority(pSid, (*(pGetSidSubAuthorityCount(pSid)) - 1U)));
if (dwIntegrityLevel == SECURITY_MANDATORY_LOW_RID)
{
return dwIntegrityLevel;
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_MEDIUM_RID && dwIntegrityLevel < SECURITY_MANDATORY_HIGH_RID)
{
return SECURITY_MANDATORY_MEDIUM_RID;
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_HIGH_RID)
{
return SECURITY_MANDATORY_HIGH_RID;
}
else if (dwIntegrityLevel >= SECURITY_MANDATORY_SYSTEM_RID)
{
return SECURITY_MANDATORY_SYSTEM_RID;
}
return -1;
}
static bool SetTokenIntegrityLevel(HANDLE hToken,
DWORD dwIntegrity)
{
static const BYTE kSidPattern[6] { 0, 0, 0, 0, 0, 16 };
TOKEN_MANDATORY_LABEL tokenLabel {};
SID_IDENTIFIER_AUTHORITY sidAuth;
AuMemcpy(sidAuth.Value, kSidPattern, sizeof(sidAuth.Value));
if (!pSetTokenInformation ||
!pAllocateAndInitializeSid)
{
return false;
}
PSID sid;
if (!pAllocateAndInitializeSid(&sidAuth,
1,
dwIntegrity, 0, 0, 0, 0, 0, 0, 0,
&sid))
{
return false;
}
tokenLabel.Label.Sid = sid;
tokenLabel.Label.Attributes = SE_GROUP_INTEGRITY;
return pSetTokenInformation(hToken,
TokenIntegrityLevel,
&tokenLabel,
sizeof(TOKEN_MANDATORY_LABEL));
}
static bool IsAdmn()
{
return false;
}
enum class EPrompt
{
eError,
eCancel,
eOK
};
static EPrompt PromptForCreds(std::wstring &wideusername,
std::wstring &widepassword,
SecureRunAs *pRunAs,
const std::wstring &wideserver)
{
LPVOID pAuthBuffer;
ULONG ulPackageLen {};
ULONG ulAuthLen {};
bool bSecond {};
CREDUI_INFOW info {};
if (!pCredUnPackAuthenticationBufferW ||
!pCredUIPromptForWindowsCredentialsW ||
!pCoTaskMemFree)
{
return EPrompt::eError;
}
info.cbSize = sizeof(info);
info.pszCaptionText = L"User Account Control";
info.pszMessageText = L"";
AuString a { "Please log in to elevate the process to " };
if (pRunAs->desc.runAs == ERunAsUser::eSpecifiedImpersonation)
{
if (pRunAs->desc.impersonate)
{
a += pRunAs->desc.impersonate.value();
}
}
else if (pRunAs->desc.runAs == ERunAsUser::eRegularUser)
{
if (wideusername.size())
{
a = fmt::format("Please log in to your account ({})", AuLocale::ConvertFromWChar(wideusername.data()));
}
else
{
a = "Please log in to your account";
}
}
else if (pRunAs->desc.runAs == ERunAsUser::eSuperUser)
{
a += "Administrator status";
}
else
{
switch (pRunAs->desc.runAs)
{
case ERunAsUser::eNTAS:
{
a += "NT Authority\\SYSTEM";
break;
}
case ERunAsUser::eNTTI:
{
a += "Trusted Installer";
break;
}
}
}
auto tempMessageBuffer = AuLocale::ConvertFromUTF8(a);
info.pszMessageText = tempMessageBuffer.data();
HRESULT result = pCredUIPromptForWindowsCredentialsW(&info,
0,
&ulPackageLen,
{}, 0,
&pAuthBuffer, &ulAuthLen,
nullptr,
0x1);
if (result != ERROR_SUCCESS)
{
if (result == ERROR_CANCELLED)
{
return EPrompt::eCancel;
}
else
{
return EPrompt::eError;
}
}
wideusername.resize(512);
widepassword.resize(512);
DWORD dwUsernameLen = wideusername.size();
DWORD dwPasswordLen = widepassword.size();
bSecond = pCredUnPackAuthenticationBufferW(0,
pAuthBuffer, ulAuthLen,
wideusername.data(), &dwUsernameLen,
nullptr /*TODO: server*/, 0,
widepassword.data(), &dwPasswordLen);
wideusername.resize(dwUsernameLen - 1);
widepassword.resize(dwPasswordLen - 1);
AuMemset(pAuthBuffer, 0, ulAuthLen);
pCoTaskMemFree(pAuthBuffer);
if (result == ERROR_SUCCESS &&
bSecond)
{
return EPrompt::eOK;
}
else
{
return EPrompt::eError;
}
}
static std::wstring GetUsername()
{
wchar_t buffer[512];
DWORD dwLength = AuArraySize(buffer);
if (!pGetUserNameW)
{
return {};
}
if (!pGetUserNameW(buffer, &dwLength))
{
return {};
}
return { buffer, dwLength };
}
static bool GetSidOfUser(const std::wstring &username,
AuList<AuUInt8> buffer,
PSID *ppSid)
{
static const auto kDefaultSize = 32;
buffer.resize(kDefaultSize);
bool bOk {};
if (!pLookupAccountNameW)
{
return false;
}
while (!bOk)
{
SID_NAME_USE eSidType;
AuList<wchar_t> dmain;
dmain.resize(2024);
DWORD dw = dmain.size();
DWORD cbSid = buffer.size();
if (pLookupAccountNameW(NULL,
username.c_str(),
(PSID)buffer.data(),
&cbSid,
dmain.data(),
&dw,
&eSidType))
{
bOk = true;
break;
}
auto dwErrorCode = GetLastError();
if (dwErrorCode == ERROR_INSUFFICIENT_BUFFER)
{
buffer.resize(cbSid);
}
else
{
break;
}
}
if (bOk)
{
*ppSid = (PSID)buffer.data();
}
return bOk;
}
static HANDLE GetToken(DWORD pid)
{
HANDLE hToken;
auto hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (!hProcess)
{
return {};
}
if (!pOpenProcessToken)
{
return {};
}
if (!pOpenProcessToken(hProcess, MAXIMUM_ALLOWED, &hToken))
{
hToken = {};
}
CloseHandle(hProcess);
return hToken;
}
static void GetSelfSID(std::function<void(PSID)> callback)
{
auto hToken = GetProcessTokenHandle();
if (!pGetTokenInformation)
{
return;
}
DWORD dwSize {};
if (!pGetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
return;
}
AuList<AuInt8> buf(dwSize, '\x00');
auto pTokenUser = (PTOKEN_USER)buf.data();
if (!pGetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
{
return;
}
callback(pTokenUser->User.Sid);
}
void SetRight(HANDLE hAdmin)
{
if (!pLsaOpenPolicy ||
!pLsaAddAccountRights ||
!pLsaClose ||
!pRevertToSelf)
{
return;
}
pRevertToSelf();
GetSelfSID([=](PSID pSelf)
{
if (pSetThreadToken)
{
pSetThreadToken(NULL, hAdmin);
}
LSA_OBJECT_ATTRIBUTES attr {};
LSA_HANDLE hHandle;
if (pLsaOpenPolicy(NULL, &attr, POLICY_ALL_ACCESS, &hHandle) == 0)
{
LSA_UNICODE_STRING unistr;
unistr.Buffer = (PWSTR)L"SeAssignPrimaryTokenPrivilege";
unistr.Length = 29 * 2;
unistr.MaximumLength = 29 * 2;
if (pLsaAddAccountRights(hHandle,
pSelf,
&unistr,
1) == 0)
{
this->bRepeat = true;
}
}
pLsaClose(hHandle);
});
}
static AuString GetProcessUserName(DWORD pid)
{
AuString username;
wchar_t lpName[MAX_PATH];
wchar_t lpDomain[MAX_PATH];
DWORD dwNameSize { MAX_PATH };
DWORD dwDomainSize { MAX_PATH };
SID_NAME_USE SidType;
if (!pLookupAccountSidW ||
!pOpenProcessToken ||
!pGetTokenInformation)
{
return {};
}
HANDLE hProcess = OpenProcess(PROCESS_QUERY_LIMITED_INFORMATION, FALSE, pid);
if (!hProcess)
{
return {};
}
HANDLE hToken {};
if (!pOpenProcessToken(hProcess, TOKEN_QUERY, &hToken))
{
CloseHandle(hProcess);
return {};
}
DWORD dwSize {};
if (!pGetTokenInformation(hToken, TokenUser, NULL, 0, &dwSize) &&
GetLastError() != ERROR_INSUFFICIENT_BUFFER)
{
CloseHandle(hToken);
CloseHandle(hProcess);
return {};
}
AuList<AuInt8> buf(dwSize, '\x00');
auto pTokenUser = (PTOKEN_USER)buf.data();
if (!pGetTokenInformation(hToken, TokenUser, pTokenUser, dwSize, &dwSize))
{
CloseHandle(hToken);
CloseHandle(hProcess);
return {};
}
if (!pLookupAccountSidW(NULL, pTokenUser->User.Sid, lpName, &dwNameSize, lpDomain, &dwDomainSize, &SidType))
{
CloseHandle(hToken);
CloseHandle(hProcess);
return {};
}
username = AuLocale::ConvertFromWChar(lpDomain);
username += "/";
username += AuLocale::ConvertFromWChar(lpName);
CloseHandle(hToken);
CloseHandle(hProcess);
return username;
}
void CachePids()
{
HANDLE hProcSnap;
PROCESSENTRY32 pe32;
if (this->pids.size())
{
return;
}
hProcSnap = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
pe32.dwSize = sizeof(PROCESSENTRY32);
if (!Process32First(hProcSnap, &pe32))
{
CloseHandle(hProcSnap);
return;
}
while (Process32Next(hProcSnap, &pe32))
{
if (AuToLower(GetProcessUserName(pe32.th32ProcessID)) == "nt authority/system")
{
this->pids.push_back(pe32.th32ProcessID);
}
}
CloseHandle(hProcSnap);
}
static bool EnableTokenPrivilege(HANDLE hToken,
const char *lpName)
{
LUID luidValue { };
TOKEN_PRIVILEGES tokenPrivileges;
if (!pLookupPrivilegeValueA ||
!pAdjustTokenPrivileges)
{
return {};
}
if (!pLookupPrivilegeValueA(NULL,
lpName,
&luidValue))
{
return {};
}
tokenPrivileges.PrivilegeCount = 1;
tokenPrivileges.Privileges[0].Luid = luidValue;
tokenPrivileges.Privileges[0].Attributes = SE_PRIVILEGE_ENABLED;
return pAdjustTokenPrivileges(hToken,
FALSE,
&tokenPrivileges,
sizeof(tokenPrivileges),
NULL,
NULL);
}
static void AddGenericElPerms(HANDLE hHandle)
{
EnableTokenPrivilege(hHandle, SE_DEBUG_NAME);
EnableTokenPrivilege(hHandle, SE_CREATE_TOKEN_NAME);
EnableTokenPrivilege(hHandle, SE_INCREASE_QUOTA_NAME);
EnableTokenPrivilege(hHandle, SE_ASSIGNPRIMARYTOKEN_NAME);
EnableTokenPrivilege(hHandle, SE_TCB_NAME);
EnableTokenPrivilege(hHandle, SE_IMPERSONATE_NAME);
}
static void AddAllTokenPrivileges(HANDLE hHandle)
{
EnableTokenPrivilege(hHandle, SE_CREATE_TOKEN_NAME);
EnableTokenPrivilege(hHandle, SE_ASSIGNPRIMARYTOKEN_NAME);
EnableTokenPrivilege(hHandle, SE_LOCK_MEMORY_NAME);
EnableTokenPrivilege(hHandle, SE_INCREASE_QUOTA_NAME);
EnableTokenPrivilege(hHandle, SE_UNSOLICITED_INPUT_NAME);
EnableTokenPrivilege(hHandle, SE_MACHINE_ACCOUNT_NAME);
EnableTokenPrivilege(hHandle, SE_TCB_NAME);
EnableTokenPrivilege(hHandle, SE_SECURITY_NAME);
EnableTokenPrivilege(hHandle, SE_TAKE_OWNERSHIP_NAME);
EnableTokenPrivilege(hHandle, SE_LOAD_DRIVER_NAME);
EnableTokenPrivilege(hHandle, SE_SYSTEM_PROFILE_NAME);
EnableTokenPrivilege(hHandle, SE_SYSTEMTIME_NAME);
EnableTokenPrivilege(hHandle, SE_PROF_SINGLE_PROCESS_NAME);
EnableTokenPrivilege(hHandle, SE_INC_BASE_PRIORITY_NAME);
EnableTokenPrivilege(hHandle, SE_CREATE_PAGEFILE_NAME);
EnableTokenPrivilege(hHandle, SE_CREATE_PERMANENT_NAME);
EnableTokenPrivilege(hHandle, SE_BACKUP_NAME);
EnableTokenPrivilege(hHandle, SE_RESTORE_NAME);
EnableTokenPrivilege(hHandle, SE_SHUTDOWN_NAME);
EnableTokenPrivilege(hHandle, SE_DEBUG_NAME);
EnableTokenPrivilege(hHandle, SE_AUDIT_NAME);
EnableTokenPrivilege(hHandle, SE_SYSTEM_ENVIRONMENT_NAME);
EnableTokenPrivilege(hHandle, SE_CHANGE_NOTIFY_NAME);
EnableTokenPrivilege(hHandle, SE_REMOTE_SHUTDOWN_NAME);
EnableTokenPrivilege(hHandle, SE_UNDOCK_NAME);
EnableTokenPrivilege(hHandle, SE_SYNC_AGENT_NAME);
EnableTokenPrivilege(hHandle, SE_ENABLE_DELEGATION_NAME);
EnableTokenPrivilege(hHandle, SE_MANAGE_VOLUME_NAME);
EnableTokenPrivilege(hHandle, SE_IMPERSONATE_NAME);
EnableTokenPrivilege(hHandle, SE_CREATE_GLOBAL_NAME);
EnableTokenPrivilege(hHandle, SE_TRUSTED_CREDMAN_ACCESS_NAME);
EnableTokenPrivilege(hHandle, SE_RELABEL_NAME);
EnableTokenPrivilege(hHandle, SE_INC_WORKING_SET_NAME);
EnableTokenPrivilege(hHandle, SE_TIME_ZONE_NAME);
EnableTokenPrivilege(hHandle, SE_CREATE_SYMBOLIC_LINK_NAME);
EnableTokenPrivilege(hHandle, SE_DELEGATE_SESSION_USER_IMPERSONATE_NAME);
}
bool TrySpawn(AuFunction<bool(HANDLE)> trySpawn, HANDLE hAdminToken)
{
CachePids();
if (!pSetThreadToken ||
!pRevertToSelf)
{
return false;
}
if (hAdminToken)
{
AddGenericElPerms(hAdminToken);
}
for (const auto &pid : pids)
{
HANDLE hToken = GetToken(pid);
if (!hToken)
{
continue;
}
AddGenericElPerms(hToken);
pSetThreadToken(NULL, hToken);
auto bSuccess = trySpawn(hToken);
if (hAdminToken)
{
pSetThreadToken(NULL, hAdminToken);
}
else
{
pRevertToSelf();
}
CloseHandle(hToken);
if (bSuccess)
{
return true;
}
}
return false;
}
static bool GetCurrentSessionId(DWORD &dwSessionId)
{
DWORD dwLength {};
return pGetTokenInformation &&
pGetTokenInformation(GetProcessTokenHandle(),
TokenSessionId,
&dwSessionId,
sizeof(DWORD),
&dwLength);
}
BOOL Exec(LPCWSTR lpApplicationName,
LPWSTR lpCommandLine,
LPSECURITY_ATTRIBUTES lpProcessAttributes,
LPSECURITY_ATTRIBUTES lpThreadAttributes,
BOOL bInheritHandles,
DWORD dwCreationFlags,
LPVOID lpEnvironment,
LPCWSTR lpCurrentDirectory,
LPSTARTUPINFOW lpStartupInfo,
LPPROCESS_INFORMATION lpProcessInformation)
{
DWORD dwSesssionId;
GetCurrentSessionId(dwSesssionId);
std::wstring widepassword;
std::wstring wideusername;
std::wstring wideserver;
DWORD dwResult {};
bool bResult {};
wchar_t *pWideServer {};
bool bRequiresUnprivAuth { true };
bool bUseUsualTokenLogin { false };
bool bRetToSelf { false };
bool bEsclToAdmin { false };
bool bDoAdmnTokenLookup { false };
bool bIsSpecialAccount { false };
bool bPrompting { false };
HANDLE hBestToken { INVALID_HANDLE_VALUE };
DWORD dwLoginFlags { LOGON_NETCREDENTIALS_ONLY };
dwCreationFlags |= CREATE_BREAKAWAY_FROM_JOB |
CREATE_DEFAULT_ERROR_MODE |
CREATE_NEW_CONSOLE |
CREATE_NEW_PROCESS_GROUP;
if (this->desc.bLoginWithProfile)
{
static wchar_t lpDesktop[] = L"WinSta0\\Default";
dwLoginFlags = LOGON_WITH_PROFILE;
lpStartupInfo->lpDesktop = lpDesktop;
}
if (this->desc.username)
{
wideusername = AuLocale::ConvertFromUTF8(this->desc.username.value().c_str());
AuMemset(this->desc.username.value().data(), 0xFF, this->desc.username.value().size());
}
if (this->desc.password)
{
widepassword = AuLocale::ConvertFromUTF8(this->desc.password.value().c_str());
AuMemset(this->desc.password.value().data(), 0xFF, this->desc.password.value().size());
}
if (this->desc.server)
{
wideserver = AuLocale::ConvertFromUTF8(this->desc.server.value().c_str());
}
if (widepassword.empty() ||
wideusername.empty())
{
EPrompt status;
if (wideusername.empty())
{
wideusername = GetUsername();
}
bPrompting = true;
do
{
status = PromptForCreds(wideusername, widepassword, this, wideserver);
if (status == EPrompt::eCancel)
{
return false;
}
if (status == EPrompt::eError)
{
SysPushErrorGeneric("Generic logon prompt failure");
return false;
}
}
while (wideusername.empty() &&
status == EPrompt::eOK);
}
if (wideserver.empty() ||
wideserver == L"." ||
wideserver == L"localhost")
{
wideserver = L".";
pWideServer = nullptr;
}
else
{
pWideServer = wideserver.data();
}
if (IsAdmn())
{
bRequiresUnprivAuth = false;
}
if (wideusername.empty())
{
AuMemset(widepassword.data(), 0xFF, widepassword.size());
SysPushErrorPermissionError("Missing Username");
return false;
}
if (bRequiresUnprivAuth)
{
do
{
if (!pLogonUserW(wideusername.c_str(),
pWideServer,
widepassword.c_str(),
LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_PROVIDER_DEFAULT,
&hBestToken))
{
auto dwErrorCode = GetLastError();
if (dwErrorCode == 1327)
{
SysPushErrorPermissionError("You must have a password or modify COMPUTER\\HKLM\\SYSTEM\\CurrentControlSet\\Control\\Lsa\\LimitBlankPasswordUse=1");
return false;
}
if (dwErrorCode == 1326)
{
if (bPrompting)
{
auto status = PromptForCreds(wideusername, widepassword, this, wideserver);
if (status == EPrompt::eCancel ||
wideusername.empty())
{
AuMemset(wideusername.data(), 0xFF, wideusername.size() * sizeof(wchar_t));
AuMemset(widepassword.data(), 0xFF, widepassword.size() * sizeof(wchar_t));
return false;
}
if (status == EPrompt::eError)
{
AuMemset(wideusername.data(), 0xFF, wideusername.size() * sizeof(wchar_t));
AuMemset(widepassword.data(), 0xFF, widepassword.size() * sizeof(wchar_t));
SysPushErrorGeneric("Generic logon prompt failure");
return false;
}
continue;
}
SysPushErrorPermissionError("Invalid username or password. This event has been logged.");
return false;
}
SysPushErrorGeneric("Unable to login");
return false;
}
else
{
if (this->desc.runAs != ERunAsUser::eRegularUser)
{
bEsclToAdmin = true;
if (this->desc.runAs != ERunAsUser::eSuperUser)
{
bDoAdmnTokenLookup = true;
bIsSpecialAccount = true;
}
}
break;
}
}
while (bPrompting);
}
else
{
bDoAdmnTokenLookup = true;
}
if (bEsclToAdmin)
{
if (!SetTokenIntegrityLevel(hBestToken,
GetTokenIntegrityLevel()))
{
SysPushErrorPermissionError("Unable to elevate");
return false;
}
if (pSetSecurityInfo((HANDLE)-1,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
{}, {}, {}, {}) != ERROR_SUCCESS)
{
SysPushErrorPermissionError("Unable to elevate");
AuMemset(wideusername.data(), 0xFF, wideusername.size() * sizeof(wchar_t));
AuMemset(widepassword.data(), 0xFF, widepassword.size() * sizeof(wchar_t));
return false;
}
bRetToSelf = true;
}
DWORD dwErrorCode {};
if (bIsSpecialAccount)
{
EnableTokenPrivilege(GetProcessTokenHandle(), SE_DEBUG_NAME);
CachePids();
SetRight(hBestToken);
if (this->bRepeat)
{
CloseHandle(hBestToken);
if (!pLogonUserW(wideusername.c_str(),
pWideServer,
widepassword.c_str(),
LOGON32_LOGON_NETWORK_CLEARTEXT,
LOGON32_PROVIDER_DEFAULT,
&hBestToken))
{
AuMemset(wideusername.data(), 0xFF, wideusername.size() * sizeof(wchar_t));
AuMemset(widepassword.data(), 0xFF, widepassword.size() * sizeof(wchar_t));
return false;
}
if (!SetTokenIntegrityLevel(hBestToken,
GetTokenIntegrityLevel()))
{
SysPushErrorPermissionError("Unable to elevate");
AuMemset(wideusername.data(), 0xFF, wideusername.size() * sizeof(wchar_t));
AuMemset(widepassword.data(), 0xFF, widepassword.size() * sizeof(wchar_t));
return false;
}
}
TrySpawn([&](HANDLE h) -> bool
{
HANDLE hToken2;
if (!pDuplicateTokenEx(h,
MAXIMUM_ALLOWED,
NULL,
SecurityImpersonation,
TokenPrimary,
&hToken2))
{
return false;
}
(void)pSetTokenInformation(hToken2, TokenSessionId, &dwSesssionId, sizeof(dwSesssionId));
pSetThreadToken(NULL, hToken2);
AddAllTokenPrivileges(hToken2);
pSetThreadToken(NULL, hBestToken);
bResult = pCreateProcessAsUserW(hToken2,
lpApplicationName,
lpCommandLine,
0,
NULL,
TRUE,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
dwErrorCode = GetLastError();
CloseHandle(hToken2);
return bResult;
}, NULL);
bUseUsualTokenLogin = true;
}
if (bUseUsualTokenLogin)
{
// Moved
if (!bResult)
{
SetLastError(dwErrorCode);
}
}
else
{
pSetThreadToken(NULL, hBestToken);
AddAllTokenPrivileges(hBestToken);
bResult = pCreateProcessWithLogonW(wideusername.c_str(),
wideserver.data(),
widepassword.c_str(),
dwLoginFlags,
lpApplicationName,
lpCommandLine,
dwCreationFlags,
lpEnvironment,
lpCurrentDirectory,
lpStartupInfo,
lpProcessInformation);
}
if (bRetToSelf)
{
pRevertToSelf();
}
AuMemset(wideusername.data(), 0xFF, wideusername.size() * sizeof(wchar_t));
AuMemset(widepassword.data(), 0xFF, widepassword.size() * sizeof(wchar_t));
AuWin32CloseHandle(hBestToken);
if (!bResult)
{
SysPushErrorGeneric("Couldn't spawn elevated process");
}
return bResult;
}
void FixSharedAttrs(SECURITY_ATTRIBUTES *pAttrs)
{
if (pInitializeSecurityDescriptor &&
pSetSecurityDescriptorDacl)
{
// let everybody on the system read our shared pipes (the easiest way to fixup inter-privileged ipc)
pAttrs->lpSecurityDescriptor = &this->sd;
pInitializeSecurityDescriptor(&this->sd, SECURITY_DESCRIPTOR_REVISION);
pSetSecurityDescriptorDacl(&this->sd, TRUE, NULL, FALSE);
}
}
};
AUKN_SYM void RunAs(StartupParameters &startupParameters,
RunAsDescriptor &runAs)
{
auto pThat = AuMakeSharedThrow<SecureRunAs>();
pThat->desc = AuMove(runAs);
startupParameters.bForceNoJobParent = true;
startupParameters.ntLikeHookCreateProcessW = std::bind(&SecureRunAs::Exec, pThat,
std::placeholders::_1, std::placeholders::_2,
std::placeholders::_3, std::placeholders::_4,
std::placeholders::_5, std::placeholders::_6,
std::placeholders::_7, std::placeholders::_8,
std::placeholders::_9, std::placeholders::_10);
startupParameters.ntFixSharedHandleAttrs = std::bind(&SecureRunAs::FixSharedAttrs, pThat,
std::placeholders::_1);
}
}