Result<ExitCode> ProcessAsUser::Run(const Settings& settings, ProcessTracker& processTracker) const { Trace trace(settings.GetLogLevel()); trace < L"ProcessAsUser::Attempt to log a user on to the local computer"; StringBuffer userName(settings.GetUserName()); StringBuffer domain(settings.GetDomain()); StringBuffer password(settings.GetPassword()); StringBuffer workingDirectory(settings.GetWorkingDirectory()); StringBuffer commandLine(settings.GetCommandLine()); SecurityManager securityManager; auto setPrivilegesResult = securityManager.SetPrivileges(trace, { SE_TCB_NAME, SE_ASSIGNPRIMARYTOKEN_NAME }, true); if(setPrivilegesResult.HasError()) { return setPrivilegesResult.GetError(); } auto newUserSecurityTokenHandle = Handle(L"New user security token"); unsigned long logonTypeCount = sizeof(allLogonTypes) / sizeof(allLogonTypes[0]); for (unsigned long logonTypeIndex = 0; logonTypeIndex < logonTypeCount; logonTypeIndex++) { auto logonType = allLogonTypes[logonTypeIndex]; trace < L"::LogonUser using logon type "; switch (logonType) { case LOGON32_LOGON_INTERACTIVE: trace << L"LOGON32_LOGON_INTERACTIVE"; break; case LOGON32_LOGON_NETWORK: trace << L"LOGON32_LOGON_NETWORK"; break; case LOGON32_LOGON_BATCH: trace << L"LOGON32_LOGON_BATCH"; break; case LOGON32_LOGON_SERVICE: trace << L"LOGON32_LOGON_SERVICE"; break; } if (LogonUser( userName.GetPointer(), domain.GetPointer(), password.GetPointer(), logonType, LOGON32_PROVIDER_DEFAULT, &newUserSecurityTokenHandle)) { break; } auto error = Error(L"LogonUser"); trace << L" - "; trace << error.GetDescription(); if(logonTypeIndex == logonTypeCount -1) { return error; } } trace < L"ProcessAsUser::InitializeConsoleRedirection a new security descriptor"; trace < L"::InitializeSecurityDescriptor"; SECURITY_DESCRIPTOR securityDescriptor = {}; if (!InitializeSecurityDescriptor( &securityDescriptor, SECURITY_DESCRIPTOR_REVISION)) { return Error(L"InitializeSecurityDescriptor"); } trace < L"::SetSecurityDescriptorDacl"; if (!SetSecurityDescriptorDacl( &securityDescriptor, true, nullptr, false)) { return Error(L"SetSecurityDescriptorDacl"); } trace < L"ProcessAsUser::Creates a new access primary token that duplicates new process's token"; auto primaryNewUserSecurityTokenHandle = Handle(L"Primary new user security token"); SECURITY_ATTRIBUTES processSecAttributes = {}; processSecAttributes.lpSecurityDescriptor = &securityDescriptor; processSecAttributes.nLength = sizeof(SECURITY_DESCRIPTOR); processSecAttributes.bInheritHandle = true; trace < L"::DuplicateTokenEx"; if (!DuplicateTokenEx( newUserSecurityTokenHandle, 0, // MAXIMUM_ALLOWED &processSecAttributes, SecurityImpersonation, TokenPrimary, &primaryNewUserSecurityTokenHandle)) { return Error(L"DuplicateTokenEx"); } SECURITY_ATTRIBUTES threadSecAttributes = {}; threadSecAttributes.lpSecurityDescriptor = nullptr; threadSecAttributes.nLength = 0; threadSecAttributes.bInheritHandle = false; STARTUPINFO startupInfo = {}; trace < L"ProcessTracker::InitializeConsoleRedirection"; auto error = processTracker.InitializeConsoleRedirection(processSecAttributes, startupInfo); if(error.HasError()) { return Result<ExitCode>(error.GetError()); } trace < L"::LoadUserProfile"; PROFILEINFO profileInfo = {}; profileInfo.dwSize = sizeof(PROFILEINFO); profileInfo.lpUserName = userName.GetPointer(); if (!LoadUserProfile(primaryNewUserSecurityTokenHandle, &profileInfo)) { return Error(L"LoadUserProfile"); } auto newProcessEnvironmentResult = GetEnvironment(settings, primaryNewUserSecurityTokenHandle, settings.GetInheritanceMode(), trace); if (newProcessEnvironmentResult.HasError()) { UnloadUserProfile(primaryNewUserSecurityTokenHandle, profileInfo.hProfile); return Result<ExitCode>(newProcessEnvironmentResult.GetError()); } auto setIntegrityLevelResult = securityManager.SetIntegrityLevel(settings.GetIntegrityLevel(), primaryNewUserSecurityTokenHandle, trace); if (setIntegrityLevelResult.HasError()) { return Result<ExitCode>(setIntegrityLevelResult.GetError()); } trace < L"ProcessAsUser::Create a new process and its primary thread. The new process runs in the security context of the user represented by the specified token."; PROCESS_INFORMATION processInformation = {}; startupInfo.dwFlags = STARTF_USESHOWWINDOW; startupInfo.wShowWindow = ShowModeConverter::ToShowWindowFlag(settings.GetShowMode()); auto cmdLine = settings.GetCommandLine(); trace < L"::CreateProcessAsUser"; if (!CreateProcessAsUser( primaryNewUserSecurityTokenHandle, nullptr, commandLine.GetPointer(), &processSecAttributes, &threadSecAttributes, true, CREATE_UNICODE_ENVIRONMENT, newProcessEnvironmentResult.GetResultValue().CreateEnvironment(), workingDirectory.GetPointer(), &startupInfo, &processInformation)) { auto result = Error(L"CreateProcessAsUser"); UnloadUserProfile(primaryNewUserSecurityTokenHandle, profileInfo.hProfile); return result; } // ReSharper disable CppInitializedValueIsAlwaysRewritten // ReSharper disable CppEntityAssignedButNoRead auto processHandle = Handle(L"Service Process"); processHandle = processInformation.hProcess; auto threadHandle = Handle(L"Thread"); threadHandle = processInformation.hThread; auto exitCode = processTracker.WaiteForExit(processInformation.hProcess, trace); UnloadUserProfile(primaryNewUserSecurityTokenHandle, profileInfo.hProfile); return exitCode; }
Result<SelfTestStatistic> SelfTest::GetStatistic(const Settings& settings) const { Trace trace(settings.GetLogLevel()); trace < L"SelfTest::GetStatistic"; Handle processToken(L"Process token"); if (!::OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &processToken)) { return Error(L"OpenProcessToken"); } trace < L"Token groups:"; auto tokenGroupsResult = _securityManager.GetTokenGroups(trace, processToken); if (!tokenGroupsResult.HasError()) { auto tokenGroups = tokenGroupsResult.GetResultValue(); for (auto groupsIterator = tokenGroups.begin(); groupsIterator != tokenGroups.end(); ++groupsIterator) { trace < groupsIterator->ToString(); } } auto isServiceResult = IsService(trace, processToken); if (isServiceResult.HasError()) { return isServiceResult.GetError(); } trace < L"SelfTest::IsService: "; trace << isServiceResult.GetResultValue(); auto hasAdministrativePrivilegesResult = HasAdministrativePrivileges(trace); if (hasAdministrativePrivilegesResult.HasError()) { return hasAdministrativePrivilegesResult.GetError(); } trace < L"SelfTest::HasAdministrativePrivileges: "; trace << hasAdministrativePrivilegesResult.GetResultValue(); auto hasSeAssignPrimaryTokenPrivilegeResult = HasPrivilege(trace, processToken, SE_ASSIGNPRIMARYTOKEN_NAME); if (hasSeAssignPrimaryTokenPrivilegeResult.HasError()) { return hasSeAssignPrimaryTokenPrivilegeResult.GetError(); } trace < L"SelfTest::HasPrivilege(SE_ASSIGNPRIMARYTOKEN_NAME): "; trace << hasSeAssignPrimaryTokenPrivilegeResult.GetResultValue(); auto hasSeTcbPrivilegeResult = HasPrivilege(trace, processToken, SE_TCB_NAME); if (hasSeTcbPrivilegeResult.HasError()) { return hasSeTcbPrivilegeResult.GetError(); } trace < L"SelfTest::HasPrivilege(SE_TCB_NAME): "; trace << hasSeTcbPrivilegeResult.GetResultValue(); auto integrityLevelResult = GetIntegrityLevel(trace, processToken); if (integrityLevelResult.HasError()) { return integrityLevelResult.GetError(); } trace < L"SelfTest::GetIntegrityLevel: "; trace << integrityLevelResult.GetResultValue(); return SelfTestStatistic( isServiceResult.GetResultValue(), hasAdministrativePrivilegesResult.GetResultValue(), hasSeAssignPrimaryTokenPrivilegeResult.GetResultValue(), hasSeTcbPrivilegeResult.GetResultValue(), integrityLevelResult.GetResultValue()); }
Result<ExitCode> ProcessWithLogon::Run(const Settings& settings, ProcessTracker& processTracker) const { Trace trace(settings.GetLogLevel()); trace < L"ProcessWithLogon::Run"; if (_changeIntegrityLevel) { trace << L" elevated"; } Environment callingProcessEnvironment; Environment targetUserEnvironment; Environment environment; if (settings.GetInheritanceMode() != INHERITANCE_MODE_OFF) { trace < L"ProcessWithLogon::Get calling process Environment"; auto callingProcessEnvironmentResult = Environment::CreateForCurrentProcess(trace); if (callingProcessEnvironmentResult.HasError()) { return Result<ExitCode>(callingProcessEnvironmentResult.GetError()); } callingProcessEnvironment = callingProcessEnvironmentResult.GetResultValue(); environment = callingProcessEnvironment; } if (settings.GetInheritanceMode() != INHERITANCE_MODE_ON) { trace < L"ProcessWithLogon::Get target user environment"; Settings getEnvVarsProcessSettings( settings.GetUserName(), settings.GetDomain(), settings.GetPassword(), L"cmd.exe", settings.GetWorkingDirectory(), EXIT_CODE_BASE, { L"/U", L"/C", L"SET" }, { }, INHERITANCE_MODE_OFF, INTEGRITY_LEVEL_AUTO, SHOW_MODE_HIDE, false); if(settings.GetLogLevel() == LOG_LEVEL_DEBUG) { getEnvVarsProcessSettings.SetLogLevel(LOG_LEVEL_DEBUG); } else { getEnvVarsProcessSettings.SetLogLevel(LOG_LEVEL_OFF); } wstringstream getEnvVarsStream; StringWriter getEnvVarsWriter(getEnvVarsStream); StubWriter nullWriter; ProcessTracker getEnvVarsProcessTracker(getEnvVarsWriter, nullWriter); auto getEnvVarsResult = RunInternal(trace, getEnvVarsProcessSettings, getEnvVarsProcessTracker, targetUserEnvironment, false); if (getEnvVarsResult.HasError() || getEnvVarsResult.GetResultValue() != 0) { return getEnvVarsResult; } targetUserEnvironment = Environment::CreateFormString(getEnvVarsStream.str(), trace); environment = targetUserEnvironment; } if (settings.GetInheritanceMode() == INHERITANCE_MODE_AUTO) { environment = Environment::Override(callingProcessEnvironment, targetUserEnvironment, trace); } environment = Environment::Apply(environment, Environment::CreateFormList(settings.GetEnvironmentVariables(), L"from command line", trace), trace); return RunInternal(trace, settings, processTracker, environment, _changeIntegrityLevel); }