private static NativeHelpers.SECURITY_LOGON_TYPE GetTokenLogonType(SafeNativeHandle hToken) { UInt64 tokenLuidId; using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, NativeHelpers.TokenInformationClass.TokenStatistics)) { NativeHelpers.TOKEN_STATISTICS stats = (NativeHelpers.TOKEN_STATISTICS)Marshal.PtrToStructure( tokenInfo.DangerousGetHandle(), typeof(NativeHelpers.TOKEN_STATISTICS)); tokenLuidId = (UInt64)stats.AuthenticationId; } // Default to Network, if we weren't able to get the actual type treat it as an error and assume // we don't want to run a process with the token NativeHelpers.SECURITY_LOGON_TYPE logonType = NativeHelpers.SECURITY_LOGON_TYPE.Network; UInt32 sessionCount; SafeLsaMemoryBuffer sessionPtr; UInt32 res = NativeMethods.LsaEnumerateLogonSessions(out sessionCount, out sessionPtr); if (res != 0) { throw new Win32Exception((int)NativeMethods.LsaNtStatusToWinError(res), "LsaEnumerateLogonSession() failed"); } using (sessionPtr) { for (IntPtr p = sessionPtr.DangerousGetHandle(); p != IntPtr.Add(sessionPtr.DangerousGetHandle(), (int)(IntPtr.Size * sessionCount)); p = IntPtr.Add(p, Marshal.SizeOf(typeof(NativeHelpers.LUID)))) { SafeLsaMemoryBuffer sessionDataPtr; res = NativeMethods.LsaGetLogonSessionData(p, out sessionDataPtr); if (res != 0) { continue; } using (sessionDataPtr) { NativeHelpers.SECURITY_LOGON_SESSION_DATA sessionData = (NativeHelpers.SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure( sessionDataPtr.DangerousGetHandle(), typeof(NativeHelpers.SECURITY_LOGON_SESSION_DATA)); UInt64 sessionId = (UInt64)sessionData.LogonId; if (sessionId == tokenLuidId) { logonType = sessionData.LogonType; break; } } } } return(logonType); }
private static SafeNativeHandle GetPrimaryTokenForUser(SecurityIdentifier sid, List <string> requiredPrivileges = null) { // According to CreateProcessWithTokenW we require a token with // TOKEN_QUERY, TOKEN_DUPLICATE and TOKEN_ASSIGN_PRIMARY // Also add in TOKEN_IMPERSONATE so we can get an impersonated token TokenAccessLevels dwAccess = TokenAccessLevels.Query | TokenAccessLevels.Duplicate | TokenAccessLevels.AssignPrimary | TokenAccessLevels.Impersonate; foreach (SafeNativeHandle hToken in TokenUtil.EnumerateUserTokens(sid, dwAccess)) { // Filter out any Network logon tokens, using become with that is useless when S4U // can give us a Batch logon NativeHelpers.SECURITY_LOGON_TYPE tokenLogonType = GetTokenLogonType(hToken); if (tokenLogonType == NativeHelpers.SECURITY_LOGON_TYPE.Network) { continue; } // Check that the required privileges are on the token if (requiredPrivileges != null) { List <string> actualPrivileges = TokenUtil.GetTokenPrivileges(hToken).Select(x => x.Name).ToList(); int missing = requiredPrivileges.Where(x => !actualPrivileges.Contains(x)).Count(); if (missing > 0) { continue; } } // Duplicate the token to convert it to a primary token with the access level required. try { return(TokenUtil.DuplicateToken(hToken, TokenAccessLevels.MaximumAllowed, SecurityImpersonationLevel.Anonymous, TokenType.Primary)); } catch (Process.Win32Exception) { continue; } } return(null); }
private static SafeNativeHandle GetPrimaryTokenForUser(SecurityIdentifier sid, List <string> requiredPrivileges = null, bool mostPrivileges = false) { // According to CreateProcessWithTokenW we require a token with // TOKEN_QUERY, TOKEN_DUPLICATE and TOKEN_ASSIGN_PRIMARY // Also add in TOKEN_IMPERSONATE so we can get an impersonated token TokenAccessLevels dwAccess = TokenAccessLevels.Query | TokenAccessLevels.Duplicate | TokenAccessLevels.AssignPrimary | TokenAccessLevels.Impersonate; SafeNativeHandle userToken = null; int privilegeCount = 0; foreach (SafeNativeHandle hToken in TokenUtil.EnumerateUserTokens(sid, dwAccess)) { // Filter out any Network logon tokens, using become with that is useless when S4U // can give us a Batch logon NativeHelpers.SECURITY_LOGON_TYPE tokenLogonType = GetTokenLogonType(hToken); if (tokenLogonType == NativeHelpers.SECURITY_LOGON_TYPE.Network) { continue; } List <string> actualPrivileges = TokenUtil.GetTokenPrivileges(hToken).Select(x => x.Name).ToList(); // If the token has less or the same number of privileges than the current token, skip it. if (mostPrivileges && privilegeCount >= actualPrivileges.Count) { continue; } // Check that the required privileges are on the token if (requiredPrivileges != null) { int missing = requiredPrivileges.Where(x => !actualPrivileges.Contains(x)).Count(); if (missing > 0) { continue; } } // Duplicate the token to convert it to a primary token with the access level required. try { userToken = TokenUtil.DuplicateToken(hToken, TokenAccessLevels.MaximumAllowed, SecurityImpersonationLevel.Anonymous, TokenType.Primary); privilegeCount = actualPrivileges.Count; } catch (Process.Win32Exception) { continue; } // If we don't care about getting the token with the most privileges, escape the loop as we already // have a token. if (!mostPrivileges) { break; } } return(userToken); }
private static SafeNativeHandle GetPrimaryTokenForUser(SecurityIdentifier sid, List <string> requiredPrivileges = null) { NativeHelpers.ProcessAccessFlags accessFlags = NativeHelpers.ProcessAccessFlags.PROCESS_QUERY_INFORMATION; // According to CreateProcessWithTokenW we require a token with // TOKEN_QUERY, TOKEN_DUPLICATE and TOKEN_ASSIGN_PRIMARY // Also add in TOKEN_IMPERSONATE so we can get an impersonated token TokenAccessLevels dwAccess = TokenAccessLevels.Query | TokenAccessLevels.Duplicate | TokenAccessLevels.AssignPrimary | TokenAccessLevels.Impersonate; foreach (System.Diagnostics.Process process in System.Diagnostics.Process.GetProcesses()) { using (process) { using (SafeNativeHandle hProcess = NativeMethods.OpenProcess(accessFlags, false, (UInt32)process.Id)) { if (hProcess.IsInvalid) { continue; } SafeNativeHandle hToken; NativeMethods.OpenProcessToken(hProcess, dwAccess, out hToken); if (hToken.IsInvalid) { continue; } using (hToken) { if (!sid.Equals(GetTokenUserSID(hToken))) { continue; } // Filter out any Network logon tokens, using become with that is useless when S4U // can give us a Batch logon NativeHelpers.SECURITY_LOGON_TYPE tokenLogonType = GetTokenLogonType(hToken); if (tokenLogonType == NativeHelpers.SECURITY_LOGON_TYPE.Network) { continue; } // Check that the required privileges are on the token if (requiredPrivileges != null) { List <string> actualPrivileges = GetTokenPrivileges(hToken); int missing = requiredPrivileges.Where(x => !actualPrivileges.Contains(x)).Count(); if (missing > 0) { continue; } } SafeNativeHandle dupToken; if (!NativeMethods.DuplicateTokenEx(hToken, TokenAccessLevels.MaximumAllowed, IntPtr.Zero, NativeHelpers.SECURITY_IMPERSONATION_LEVEL.SecurityImpersonation, NativeHelpers.TOKEN_TYPE.TokenPrimary, out dupToken)) { continue; } return(dupToken); } } } } return(null); }