예제 #1
0
 // ReSharper disable once TooManyArguments
 internal static extern bool AdjustTokenPrivileges(
     [In] SafeNativeHandle tokenHandle,
     [In] bool disableAllPrivileges,
     [In] ref TokenPrivileges newState,
     [In] uint bufferLength,
     IntPtr previousState,
     IntPtr returnLength
     );
예제 #2
0
 // ReSharper disable once TooManyArguments
 public static extern bool DuplicateTokenEx(
     [In] SafeNativeHandle hExistingToken,
     [In] TokenAccessLevels dwDesiredAccess,
     [In] IntPtr lpTokenAttributes,
     [In] TokenImpersonationLevel impersonationLevel,
     [In] TokenType tokenType,
     [Out] out SafeNativeHandle newToken
     );
예제 #3
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);
예제 #4
0
 public static extern bool CreateProcessWithTokenW(
     SafeNativeHandle token,
     LogonFlags logonFlags,
     [MarshalAs(UnmanagedType.LPWStr)] string applicationName,
     [MarshalAs(UnmanagedType.LPWStr)] string commandLine,
     ProcessCreationFlags creationFlags,
     IntPtr environment,
     [MarshalAs(UnmanagedType.LPWStr)] string currentDirectory,
     [In] ref StartupInfo startupInfo,
     out ProcessInformation processInformation);
예제 #5
0
 public static extern bool CreateProcessAsUserW(
     SafeNativeHandle token,
     [MarshalAs(UnmanagedType.LPWStr)] string applicationName,
     [MarshalAs(UnmanagedType.LPWStr)] string commandLine,
     IntPtr processAttributes,
     IntPtr threadAttributes,
     bool inheritHandles,
     ProcessCreationFlags creationFlags,
     IntPtr environment,
     [MarshalAs(UnmanagedType.LPWStr)] string currentDirectory,
     [In] ref StartupInfo startupInfo,
     out ProcessInformation processInformation);
예제 #6
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);
예제 #7
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);
            }
        }
예제 #8
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);
            }
        }
예제 #9
0
        /// <summary>
        ///     Starts a new <see cref="Process" /> with the start info provided and with the same rights as the mentioned
        ///     <see cref="Process" />
        /// </summary>
        /// <param name="process">The <see cref="Process" /> to copy rights from</param>
        /// <param name="startInfo">Contains the information about the <see cref="Process" /> to be started</param>
        /// <returns>Returns the newly started <see cref="Process" /></returns>
        /// <exception cref="InvalidOperationException">This method needs administrative access rights.-or-UAC is not enable</exception>
        /// <exception cref="NotSupportedException">Current version of Windows does not meets the needs of this method</exception>
        public static Process StartAndCopyProcessPermission(Process process, ProcessStartInfo startInfo)
        {
            if (!string.IsNullOrWhiteSpace(startInfo.UserName))
            {
                throw new InvalidOperationException(Resources.Error_StartWithUsername);
            }

            if (!IsElevated)
            {
                throw new InvalidOperationException(Resources.Error_AccessDenied);
            }

            Tokens.EnablePrivilegeOnProcess(Process.GetCurrentProcess(), SecurityEntities.SeImpersonatePrivilege);
            using (var primaryToken = Tokens.DuplicatePrimaryToken(process))
            {
                var lockTaken = false;
                try
                {
                    Monitor.Enter(startInfo, ref lockTaken);
                    var unicode       = Environment.OSVersion.Platform == PlatformID.Win32NT;
                    var creationFlags = startInfo.CreateNoWindow
                        ? ProcessCreationFlags.CreateNoWindow
                        : ProcessCreationFlags.None;
                    if (unicode)
                    {
                        creationFlags |= ProcessCreationFlags.UnicodeEnvironment;
                    }
                    var commandLine      = IOPath.BuildCommandLine(startInfo.FileName, startInfo.Arguments);
                    var workingDirectory = string.IsNullOrEmpty(startInfo.WorkingDirectory)
                        ? Environment.CurrentDirectory
                        : startInfo.WorkingDirectory;
                    var startupInfo = StartupInfo.GetOne();
                    var gcHandle    = new GCHandle();
                    try
                    {
                        gcHandle =
                            GCHandle.Alloc(
                                IOPath.EnvironmentBlockToByteArray(startInfo.EnvironmentVariables, unicode),
                                GCHandleType.Pinned);
                        var environmentPtr = gcHandle.AddrOfPinnedObject();
                        var logonFlags     = startInfo.LoadUserProfile ? LogonFlags.LogonWithProfile : LogonFlags.None;
                        ProcessInformation processInfo;
                        bool processCreationResult;
                        if (IsUACSupported) // Vista +
                        {
                            processCreationResult = AdvancedAPI.CreateProcessWithTokenW(primaryToken, logonFlags,
                                                                                        null,
                                                                                        commandLine,
                                                                                        creationFlags, environmentPtr, workingDirectory, ref startupInfo, out processInfo);
                        }
                        else
                        {
                            Tokens.EnablePrivilegeOnProcess(Process.GetCurrentProcess(),
                                                            SecurityEntities.SeIncreaseQuotaPrivilege);
                            processCreationResult = AdvancedAPI.CreateProcessAsUserW(primaryToken, null,
                                                                                     commandLine, IntPtr.Zero,
                                                                                     IntPtr.Zero, false, creationFlags, environmentPtr, workingDirectory, ref startupInfo,
                                                                                     out processInfo);
                        }
                        if (!processCreationResult)
                        {
                            throw new Win32Exception();
                        }
                        SafeNativeHandle.CloseHandle(processInfo.Thread);
                        SafeNativeHandle.CloseHandle(processInfo.Process);
                        if (processInfo.ProcessId <= 0)
                        {
                            throw new InvalidOperationException(Resources.Error_Unknown);
                        }
                        return(Process.GetProcessById(processInfo.ProcessId));
                    }
                    catch (EntryPointNotFoundException)
                    {
                        throw new NotSupportedException();
                    }
                    finally
                    {
                        if (gcHandle.IsAllocated)
                        {
                            gcHandle.Free();
                        }
                    }
                }
                finally
                {
                    if (lockTaken)
                    {
                        Monitor.Exit(startInfo);
                    }
                }
            }
        }
예제 #10
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);
        }
예제 #11
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/assible/assible/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);
        }
예제 #12
0
 public static extern bool OpenProcessToken(
     IntPtr processHandle,
     TokenAccessLevels desiredAccess,
     out SafeNativeHandle tokenHandle
     );