Exemplo n.º 1
0
 public static extern bool LogonUserW(
     string lpszUsername,
     string lpszDomain,
     string lpszPassword,
     LogonType dwLogonType,
     NativeHelpers.LogonProvider dwLogonProvider,
     out SafeNativeHandle phToken);
Exemplo n.º 2
0
 public static extern bool DuplicateTokenEx(
     SafeNativeHandle hExistingToken,
     TokenAccessLevels dwDesiredAccess,
     IntPtr lpTokenAttributes,
     NativeHelpers.SECURITY_IMPERSONATION_LEVEL ImpersonationLevel,
     NativeHelpers.TOKEN_TYPE TokenType,
     out SafeNativeHandle phNewToken);
Exemplo n.º 3
0
 private static SecurityIdentifier GetTokenUserSID(SafeNativeHandle hToken)
 {
     using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, NativeHelpers.TokenInformationClass.TokenUser))
     {
         NativeHelpers.TOKEN_USER tokenUser = (NativeHelpers.TOKEN_USER)Marshal.PtrToStructure(tokenInfo.DangerousGetHandle(),
                                                                                               typeof(NativeHelpers.TOKEN_USER));
         return(new SecurityIdentifier(tokenUser.User.Sid));
     }
 }
Exemplo n.º 4
0
 public static extern bool CreateProcessWithTokenW(
     SafeNativeHandle hToken,
     LogonFlags dwLogonFlags,
     [MarshalAs(UnmanagedType.LPWStr)] string lpApplicationName,
     StringBuilder lpCommandLine,
     Process.NativeHelpers.ProcessCreationFlags dwCreationFlags,
     Process.SafeMemoryBuffer lpEnvironment,
     [MarshalAs(UnmanagedType.LPWStr)] string lpCurrentDirectory,
     Process.NativeHelpers.STARTUPINFOEX lpStartupInfo,
     out Process.NativeHelpers.PROCESS_INFORMATION lpProcessInformation);
Exemplo n.º 5
0
        private static List <string> GetTokenPrivileges(SafeNativeHandle hToken)
        {
            using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, NativeHelpers.TokenInformationClass.TokenPrivileges))
            {
                NativeHelpers.TOKEN_PRIVILEGES tokenPrivileges = (NativeHelpers.TOKEN_PRIVILEGES)Marshal.PtrToStructure(
                    tokenInfo.DangerousGetHandle(), typeof(NativeHelpers.TOKEN_PRIVILEGES));

                NativeHelpers.LUID_AND_ATTRIBUTES[] luidAndAttributes = new NativeHelpers.LUID_AND_ATTRIBUTES[tokenPrivileges.PrivilegeCount];
                PtrToStructureArray(luidAndAttributes, IntPtr.Add(tokenInfo.DangerousGetHandle(), Marshal.SizeOf(tokenPrivileges.PrivilegeCount)));

                return(luidAndAttributes.Select(x => GetPrivilegeName(x.Luid)).ToList());
            }
        }
Exemplo n.º 6
0
        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);
        }
Exemplo n.º 7
0
 public static extern UInt32 LsaLogonUser(
     SafeLsaHandle LsaHandle,
     NativeHelpers.LSA_STRING OriginName,
     LogonType LogonType,
     UInt32 AuthenticationPackage,
     IntPtr AuthenticationInformation,
     UInt32 AuthenticationInformationLength,
     IntPtr LocalGroups,
     NativeHelpers.TOKEN_SOURCE SourceContext,
     out SafeLsaMemoryBuffer ProfileBuffer,
     out UInt32 ProfileBufferLength,
     out Luid LogonId,
     out SafeNativeHandle Token,
     out IntPtr Quotas,
     out UInt32 SubStatus);
Exemplo n.º 8
0
        private static SafeNativeHandle GetElevatedToken(SafeNativeHandle hToken)
        {
            // First determine if the current token is a limited token
            using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, NativeHelpers.TokenInformationClass.TokenElevationType))
            {
                NativeHelpers.TokenElevationType tet = (NativeHelpers.TokenElevationType)Marshal.ReadInt32(tokenInfo.DangerousGetHandle());
                // We already have the best token we can get, just use it
                if (tet != NativeHelpers.TokenElevationType.TokenElevationTypeLimited)
                {
                    return(hToken);
                }
            }

            // We have a limited token, get the linked elevated token
            using (SafeMemoryBuffer tokenInfo = GetTokenInformation(hToken, NativeHelpers.TokenInformationClass.TokenLinkedToken))
                return(new SafeNativeHandle(Marshal.ReadIntPtr(tokenInfo.DangerousGetHandle())));
        }
Exemplo n.º 9
0
        private static SafeMemoryBuffer GetTokenInformation(SafeNativeHandle hToken, NativeHelpers.TokenInformationClass tokenClass)
        {
            UInt32 tokenLength;
            bool   res = NativeMethods.GetTokenInformation(hToken, tokenClass, new SafeMemoryBuffer(IntPtr.Zero), 0, out tokenLength);

            if (!res && tokenLength == 0)  // res will be false due to insufficient buffer size, we ignore if we got the buffer length
            {
                throw new Win32Exception(String.Format("GetTokenInformation({0}) failed to get buffer length", tokenClass.ToString()));
            }

            SafeMemoryBuffer tokenInfo = new SafeMemoryBuffer((int)tokenLength);

            if (!NativeMethods.GetTokenInformation(hToken, tokenClass, tokenInfo, tokenLength, out tokenLength))
            {
                throw new Win32Exception(String.Format("GetTokenInformation({0}) failed", tokenClass.ToString()));
            }

            return(tokenInfo);
        }
Exemplo n.º 10
0
        private static NativeHelpers.SECURITY_LOGON_TYPE GetTokenLogonType(SafeNativeHandle hToken)
        {
            TokenStatistics stats = TokenUtil.GetTokenStatistics(hToken);

            SafeLsaMemoryBuffer sessionDataPtr;
            UInt32 res = NativeMethods.LsaGetLogonSessionData(ref stats.AuthenticationId, out sessionDataPtr);

            if (res != 0)
            {
                // 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
                return(NativeHelpers.SECURITY_LOGON_TYPE.Network);
            }

            using (sessionDataPtr)
            {
                NativeHelpers.SECURITY_LOGON_SESSION_DATA sessionData = (NativeHelpers.SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure(
                    sessionDataPtr.DangerousGetHandle(), typeof(NativeHelpers.SECURITY_LOGON_SESSION_DATA));
                return(sessionData.LogonType);
            }
        }
Exemplo n.º 11
0
        /// <summary>
        /// Creates a process as another user account. This method will attempt to run as another user with the
        /// highest possible permissions available. The main privilege required is the SeDebugPrivilege, without
        /// this privilege you can only run as a local or domain user if the username and password is specified.
        /// </summary>
        /// <param name="username">The username of the runas user</param>
        /// <param name="password">The password of the runas user</param>
        /// <param name="logonFlags">LogonFlags to control how to logon a user when the password is specified</param>
        /// <param name="logonType">Controls what type of logon is used, this only applies when the password is specified</param>
        /// <param name="lpApplicationName">The name of the executable or batch file to executable</param>
        /// <param name="lpCommandLine">The command line to execute, typically this includes lpApplication as the first argument</param>
        /// <param name="lpCurrentDirectory">The full path to the current directory for the process, null will have the same cwd as the calling process</param>
        /// <param name="environment">A dictionary of key/value pairs to define the new process environment</param>
        /// <param name="stdin">Bytes sent to the stdin pipe</param>
        /// <returns>Ansible.Process.Result object that contains the command output and return code</returns>
        public static Result CreateProcessAsUser(string username, string password, LogonFlags logonFlags, LogonType logonType,
                                                 string lpApplicationName, string lpCommandLine, string lpCurrentDirectory, IDictionary environment, byte[] stdin)
        {
            // While we use STARTUPINFOEX having EXTENDED_STARTUPINFO_PRESENT causes a parameter validation error
            Process.NativeHelpers.ProcessCreationFlags creationFlags = Process.NativeHelpers.ProcessCreationFlags.CREATE_UNICODE_ENVIRONMENT;
            Process.NativeHelpers.PROCESS_INFORMATION  pi            = new Process.NativeHelpers.PROCESS_INFORMATION();
            Process.NativeHelpers.STARTUPINFOEX        si            = new Process.NativeHelpers.STARTUPINFOEX();
            si.startupInfo.dwFlags = Process.NativeHelpers.StartupInfoFlags.USESTDHANDLES;

            SafeFileHandle stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinRead, stdinWrite;

            ProcessUtil.CreateStdioPipes(si, out stdoutRead, out stdoutWrite, out stderrRead, out stderrWrite,
                                         out stdinRead, out stdinWrite);
            FileStream stdinStream = new FileStream(stdinWrite, FileAccess.Write);

            // $null from PowerShell ends up as an empty string, we need to convert back as an empty string doesn't
            // make sense for these parameters
            if (lpApplicationName == "")
            {
                lpApplicationName = null;
            }

            if (lpCurrentDirectory == "")
            {
                lpCurrentDirectory = null;
            }

            using (Process.SafeMemoryBuffer lpEnvironment = ProcessUtil.CreateEnvironmentPointer(environment))
                using (SafeNativeHandle hToken = GetUserToken(username, password, logonType))
                {
                    StringBuilder commandLine = new StringBuilder(lpCommandLine);
                    if (!NativeMethods.CreateProcessWithTokenW(hToken, logonFlags, lpApplicationName, commandLine,
                                                               creationFlags, lpEnvironment, lpCurrentDirectory, si, out pi))
                    {
                        throw new Process.Win32Exception("CreateProcessWithTokenW() failed");
                    }
                }
            return(ProcessUtil.WaitProcess(stdoutRead, stdoutWrite, stderrRead, stderrWrite, stdinStream, stdin, pi.hProcess));
        }
Exemplo n.º 12
0
        private static SafeNativeHandle GetElevatedToken(SafeNativeHandle hToken)
        {
            TokenElevationType tet = TokenUtil.GetTokenElevationType(hToken);

            // We already have the best token we can get, no linked token is really available.
            if (tet != TokenElevationType.Limited)
            {
                return(null);
            }

            SafeNativeHandle linkedToken = TokenUtil.GetTokenLinkedToken(hToken);
            TokenStatistics  tokenStats  = TokenUtil.GetTokenStatistics(linkedToken);

            // We can only use a token if it's a primary one (we had the SeTcbPrivilege set)
            if (tokenStats.TokenType == TokenType.Primary)
            {
                return(linkedToken);
            }
            else
            {
                return(null);
            }
        }
Exemplo n.º 13
0
        private static List <SafeNativeHandle> GetUserTokens(string username, string password, LogonType logonType)
        {
            List <SafeNativeHandle> userTokens = new List <SafeNativeHandle>();

            SafeNativeHandle systemToken  = null;
            bool             impersonated = false;
            string           becomeSid    = username;

            if (logonType != LogonType.NewCredentials)
            {
                // If prefixed with .\, we are becoming a local account, strip the prefix
                if (username.StartsWith(".\\"))
                {
                    username = username.Substring(2);
                }

                NTAccount account = new NTAccount(username);
                becomeSid = ((SecurityIdentifier)account.Translate(typeof(SecurityIdentifier))).Value;

                // Grant access to the current Windows Station and Desktop to the become user
                GrantAccessToWindowStationAndDesktop(account);

                // Try and impersonate a SYSTEM token, we need a SYSTEM token to either become a well known service
                // account or have administrative rights on the become access token.
                // If we ultimately are becoming the SYSTEM account we want the token with the most privileges available.
                // https://github.com/ansible/ansible/issues/71453
                bool mostPrivileges = becomeSid == "S-1-5-18";
                systemToken = GetPrimaryTokenForUser(new SecurityIdentifier("S-1-5-18"),
                                                     new List <string>()
                {
                    "SeTcbPrivilege"
                }, mostPrivileges);
                if (systemToken != null)
                {
                    try
                    {
                        TokenUtil.ImpersonateToken(systemToken);
                        impersonated = true;
                    }
                    catch (Process.Win32Exception) { }  // We tried, just rely on current user's permissions.
                }
            }

            // We require impersonation if becoming a service sid or becoming a user without a password
            if (!impersonated && (SERVICE_SIDS.Contains(becomeSid) || String.IsNullOrEmpty(password)))
            {
                throw new Exception("Failed to get token for NT AUTHORITY\\SYSTEM required for become as a service account or an account without a password");
            }

            try
            {
                if (becomeSid == "S-1-5-18")
                {
                    userTokens.Add(systemToken);
                }
                // Cannot use String.IsEmptyOrNull() as an empty string is an account that doesn't have a pass.
                // We only use S4U if no password was defined or it was null
                else if (!SERVICE_SIDS.Contains(becomeSid) && password == null && logonType != LogonType.NewCredentials)
                {
                    // If no password was specified, try and duplicate an existing token for that user or use S4U to
                    // generate one without network credentials
                    SecurityIdentifier sid         = new SecurityIdentifier(becomeSid);
                    SafeNativeHandle   becomeToken = GetPrimaryTokenForUser(sid);
                    if (becomeToken != null)
                    {
                        userTokens.Add(GetElevatedToken(becomeToken));
                        userTokens.Add(becomeToken);
                    }
                    else
                    {
                        becomeToken = GetS4UTokenForUser(sid, logonType);
                        userTokens.Add(null);
                        userTokens.Add(becomeToken);
                    }
                }
                else
                {
                    string domain = null;
                    switch (becomeSid)
                    {
                    case "S-1-5-19":
                        logonType = LogonType.Service;
                        domain    = "NT AUTHORITY";
                        username  = "******";
                        break;

                    case "S-1-5-20":
                        logonType = LogonType.Service;
                        domain    = "NT AUTHORITY";
                        username  = "******";
                        break;

                    default:
                        // Trying to become a local or domain account
                        if (username.Contains(@"\"))
                        {
                            string[] userSplit = username.Split(new char[1] {
                                '\\'
                            }, 2);
                            domain   = userSplit[0];
                            username = userSplit[1];
                        }
                        else if (!username.Contains("@"))
                        {
                            domain = ".";
                        }
                        break;
                    }

                    SafeNativeHandle hToken = TokenUtil.LogonUser(username, domain, password, logonType,
                                                                  LogonProvider.Default);

                    // Get the elevated token for a local/domain accounts only
                    if (!SERVICE_SIDS.Contains(becomeSid))
                    {
                        userTokens.Add(GetElevatedToken(hToken));
                    }
                    userTokens.Add(hToken);
                }
            }
            finally
            {
                if (impersonated)
                {
                    TokenUtil.RevertToSelf();
                }
            }

            return(userTokens);
        }
Exemplo n.º 14
0
        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);
        }
Exemplo n.º 15
0
 public static extern bool GetTokenInformation(
     SafeNativeHandle TokenHandle,
     NativeHelpers.TokenInformationClass TokenInformationClass,
     SafeMemoryBuffer TokenInformation,
     UInt32 TokenInformationLength,
     out UInt32 ReturnLength);
Exemplo n.º 16
0
 public static extern bool ImpersonateLoggedOnUser(
     SafeNativeHandle hToken);
Exemplo n.º 17
0
 public static extern bool OpenProcessToken(
     SafeNativeHandle ProcessHandle,
     TokenAccessLevels DesiredAccess,
     out SafeNativeHandle TokenHandle);
Exemplo n.º 18
0
        private static List <SafeNativeHandle> GetUserTokens(string username, string password, LogonType logonType)
        {
            List <SafeNativeHandle> userTokens = new List <SafeNativeHandle>();

            SafeNativeHandle systemToken  = null;
            bool             impersonated = false;
            string           becomeSid    = username;

            if (logonType != LogonType.LOGON32_LOGON_NEW_CREDENTIALS)
            {
                // If prefixed with .\, we are becoming a local account, strip the prefix
                if (username.StartsWith(".\\"))
                {
                    username = username.Substring(2);
                }

                NTAccount account = new NTAccount(username);
                becomeSid = ((SecurityIdentifier)account.Translate(typeof(SecurityIdentifier))).Value;

                // Grant access to the current Windows Station and Desktop to the become user
                GrantAccessToWindowStationAndDesktop(account);

                // Try and impersonate a SYSTEM token, we need a SYSTEM token to either become a well known service
                // account or have administrative rights on the become access token.
                systemToken = GetPrimaryTokenForUser(new SecurityIdentifier("S-1-5-18"), new List <string>()
                {
                    "SeTcbPrivilege"
                });
                if (systemToken != null)
                {
                    impersonated = NativeMethods.ImpersonateLoggedOnUser(systemToken);
                }
            }

            // We require impersonation if becoming a service sid or becoming a user without a password
            if (!impersonated && (SERVICE_SIDS.Contains(becomeSid) || String.IsNullOrEmpty(password)))
            {
                throw new Exception("Failed to get token for NT AUTHORITY\\SYSTEM required for become as a service account or an account without a password");
            }

            try
            {
                if (becomeSid == "S-1-5-18")
                {
                    userTokens.Add(systemToken);
                }
                // Cannot use String.IsEmptyOrNull() as an empty string is an account that doesn't have a pass.
                // We only use S4U if no password was defined or it was null
                else if (!SERVICE_SIDS.Contains(becomeSid) && password == null && logonType != LogonType.LOGON32_LOGON_NEW_CREDENTIALS)
                {
                    // If no password was specified, try and duplicate an existing token for that user or use S4U to
                    // generate one without network credentials
                    SecurityIdentifier sid         = new SecurityIdentifier(becomeSid);
                    SafeNativeHandle   becomeToken = GetPrimaryTokenForUser(sid);
                    if (becomeToken != null)
                    {
                        userTokens.Add(GetElevatedToken(becomeToken));
                        userTokens.Add(becomeToken);
                    }
                    else
                    {
                        becomeToken = GetS4UTokenForUser(sid, logonType);
                        userTokens.Add(becomeToken);
                    }
                }
                else
                {
                    string domain = null;
                    switch (becomeSid)
                    {
                    case "S-1-5-19":
                        logonType = LogonType.LOGON32_LOGON_SERVICE;
                        domain    = "NT AUTHORITY";
                        username  = "******";
                        break;

                    case "S-1-5-20":
                        logonType = LogonType.LOGON32_LOGON_SERVICE;
                        domain    = "NT AUTHORITY";
                        username  = "******";
                        break;

                    default:
                        // Trying to become a local or domain account
                        if (username.Contains(@"\"))
                        {
                            string[] userSplit = username.Split(new char[1] {
                                '\\'
                            }, 2);
                            domain   = userSplit[0];
                            username = userSplit[1];
                        }
                        else if (!username.Contains("@"))
                        {
                            domain = ".";
                        }
                        break;
                    }

                    SafeNativeHandle hToken;
                    if (!NativeMethods.LogonUserW(username, domain, password, logonType,
                                                  NativeHelpers.LogonProvider.LOGON32_PROVIDER_DEFAULT, out hToken))
                    {
                        throw new Win32Exception("LogonUserW() failed");
                    }

                    // Get the elevated token for a local/domain accounts only
                    if (!SERVICE_SIDS.Contains(becomeSid))
                    {
                        userTokens.Add(GetElevatedToken(hToken));
                    }
                    userTokens.Add(hToken);
                }
            }
            finally
            {
                if (impersonated)
                {
                    NativeMethods.RevertToSelf();
                }
            }

            return(userTokens);
        }
Exemplo n.º 19
0
        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);
        }