private static IEnumerable<int> GetSessionIDs(IntPtr server)
        {
            // Buffer which contains the SessionInfo structs
            IntPtr buffer = IntPtr.Zero;

            // Count of structs in this buffer
            int count = 0;

            // Retrieve all sessions
            try
            {
                if (!Wtsapi32.WtsEnumerateSessions(server, 0, 1, ref buffer, ref count))
                    throw new Win32Exception("Cannot enumerate wts sessions.");

                // Set start of memory location to buffer beginning
                IntPtr currentIndex = buffer;

                // Iterate over all sessions
                for (int i = 0; i < count; i++)
                {
                    var sessionInfo = (Wtsapi32.WtsSessionInfo?) Marshal.PtrToStructure(currentIndex, typeof(Wtsapi32.WtsSessionInfo));
                    if (sessionInfo == null)
                        throw new Win32Exception(
                            "Cannot not marshal session info structure.");
                    currentIndex += Marshal.SizeOf(typeof(Wtsapi32.WtsSessionInfo));
                    yield return sessionInfo.Value.SessionId;
                }
            }
            finally
            {
                // Free memory buffer
                Wtsapi32.WtsFreeMemory(buffer);
            }
        }
Exemple #2
0
        private static string GetSessionUser(int sessionId)
        {
            string domainUser = null;

            try
            {
                StringBuilder sbDomain   = new StringBuilder(50);
                StringBuilder sbUsername = new StringBuilder(50);
                int           bsCount;
                if (Wtsapi32.WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSDomainName, out sbDomain, out bsCount))
                {
                    if (Wtsapi32.WTSQuerySessionInformation(IntPtr.Zero, sessionId, WTS_INFO_CLASS.WTSUserName, out sbUsername, out bsCount))
                    {
                        if (!string.Equals(Environment.MachineName, sbDomain.ToString(), StringComparison.OrdinalIgnoreCase))
                        {
                            domainUser = string.Format(@"{0}\{1}", sbDomain, sbUsername);
                        }
                        else
                        {
                            domainUser = sbUsername.ToString();
                        }
                    }
                }
            }
            catch (Exception ex) { TraceLog.WriteException(ex); throw; }
            return(domainUser);
        }
Exemple #3
0
        /// <summary>
        /// Gets the primary token from a session ID. Only possible if the caller has LocalSystem rights
        /// </summary>
        /// <param name="sessionId">Session ID</param>
        /// <returns></returns>
        public static SafeAccessTokenHandle GetPrimaryTokenFromSessionId(uint sessionId)
        {
            if (!Wtsapi32.WTSQueryUserToken(sessionId, out SafeAccessTokenHandle currentUserToken))
            {
                throw new Win32Exception(Marshal.GetLastWin32Error());
            }

            return(currentUserToken);
        }
        /// <summary>
        /// Retrieves a handle to the primary token connected to a session ID.
        /// </summary>
        /// <param name="sessionId"></param>
        /// <returns></returns>
        public static AccessTokenHandle FromSessionId(uint sessionId)
        {
            IntPtr hToken;

            if (!Wtsapi32.WTSQueryUserToken(sessionId, out hToken))
            {
                Logger.GetInstance().Error($"Failed to retrieve the primary access token for session '{sessionId}'. WTSQueryUserToken failed with error: {Kernel32.GetLastError()}");
                throw new OpenProcessTokenException();
            }
            return(new AccessTokenHandle(hToken, TokenAccess.TOKEN_ALL_ACCESS));
        }
Exemple #5
0
        /// <summary>
        /// Gets the primary token of the first found active user session.
        /// </summary>
        /// <returns>A <see cref="TokenHelper"/> or null if no valid sessions was found.</returns>
        /// <exception cref="Win32Exception"></exception>
        public static SafeAccessTokenHandle GetPrimaryTokenOfFirstActiveSession()
        {
            //!!! Parts are from Copyright (c) 2014 Justin Murray - MIT-License, thanks to him !!!
            // https://github.com/murrayju/CreateProcessAsUser, 18.08.2019

            uint   activeSessionId = Wtsapi32.InvalidSessionId;
            IntPtr sessionInfos    = IntPtr.Zero;
            var    sessionCount    = 0;

            try
            {
                //Get a handle to the user access token for the current active session.
                if (Wtsapi32.WTSEnumerateSessions(Wtsapi32.WtsCurrentServerHandle, 0, 1, ref sessionInfos, ref sessionCount))
                {
                    int    arrayElementSize = Marshal.SizeOf <Wtsapi32.WtsSessionInfo>();
                    IntPtr current          = sessionInfos;

                    for (var i = 0; i < sessionCount; i++)
                    {
                        var sessionInfo = Marshal.PtrToStructure <Wtsapi32.WtsSessionInfo>(current);
                        current += arrayElementSize;

                        if (sessionInfo.State == Wtsapi32.WtsConnectstateClass.WTSActive)
                        {
                            activeSessionId = (uint)sessionInfo.SessionID;
                            break;
                        }
                    }
                }
            }
            finally
            {
                if (sessionInfos != IntPtr.Zero)
                {
                    Wtsapi32.WTSFreeMemory(sessionInfos);
                }
            }

            //If enumerating not working use the fall back method
            if (activeSessionId == Wtsapi32.InvalidSessionId)
            {
                activeSessionId = Kernel32.WTSGetActiveConsoleSessionId();

                if (activeSessionId == Wtsapi32.InvalidSessionId)
                {
                    return(null);
                }
            }

            return(GetPrimaryTokenFromSessionId(activeSessionId));
        }
 public static bool AreAllUsersLoggedOut()
 {
     // Open local server
     IntPtr server = Wtsapi32.WtsOpenServer(Environment.MachineName);
     try
     {
         // Get user sessions and logout each user
         return GetSessionIDs(server).All(id => WellKnownSessionIds.Contains(id));
     }
     finally
     {
         Wtsapi32.WtsCloseServer(server);
     }
 }
        private static string? GetUsername(IntPtr server, int sessionId)
        {
            IntPtr buffer = IntPtr.Zero;

            try
            {
                // Check is method returns success
                if (!Wtsapi32.WtsQuerySessionInformation(server, sessionId, Wtsapi32.WtsInfoClass.WtsUserName, out buffer,
                    out uint _))
                    return null;

                return Marshal.PtrToStringAnsi(buffer)?.ToUpper().Trim();
            }
            finally
            {
                Wtsapi32.WtsFreeMemory(buffer);
            }
        }
        public static void LogoutAllUsers()
        {
            // Open local server
            IntPtr server = Wtsapi32.WtsOpenServer(Environment.MachineName);

            try
            {
                // Get user sessions and logout each user
                foreach (int sessionId in GetSessionIDs(server).Where(id => !WellKnownSessionIds.Contains(id)))
                {
                    // Get Username
                    string? username = GetUsername(server, sessionId);
                    if (string.IsNullOrWhiteSpace(username))
                        continue;

                    Wtsapi32.WtsLogoffSession(server, sessionId, false);
                }
            }
            finally
            {
                Wtsapi32.WtsCloseServer(server);
            }
        }
Exemple #9
0
        /// <summary>
        /// Gets the primary token from an first active user session with the given username.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <returns>A <see cref="SafeAccessTokenHandle"/> or null if no valid sessions was found.</returns>
        /// <exception cref="Win32Exception">
        /// </exception>
        public static SafeAccessTokenHandle GetPrimaryTokenByUsername(string username)
        {
            //!!! Parts are from Copyright (c) 2014 Justin Murray - MIT-License, thanks to him !!!
            // https://github.com/murrayju/CreateProcessAsUser, 18.08.2019

            uint   activeSessionId = Wtsapi32.InvalidSessionId;
            IntPtr sessionInfos    = IntPtr.Zero;
            var    sessionCount    = 0;

            try
            {
                //Get a handle to the user access token for the current active session.
                if (Wtsapi32.WTSEnumerateSessions(Wtsapi32.WtsCurrentServerHandle, 0, 1, ref sessionInfos,
                                                  ref sessionCount))
                {
                    int    arrayElementSize = Marshal.SizeOf <Wtsapi32.WtsSessionInfo>();
                    IntPtr current          = sessionInfos;

                    for (var i = 0; i < sessionCount; i++)
                    {
                        IntPtr usernamePtr = IntPtr.Zero;
                        IntPtr domainPtr   = IntPtr.Zero;
                        try
                        {
                            var sessionInfo = Marshal.PtrToStructure <Wtsapi32.WtsSessionInfo>(current);
                            current += arrayElementSize;

                            //If the session is not active, go to the next
                            if (sessionInfo.State != Wtsapi32.WtsConnectstateClass.WTSActive)
                            {
                                continue;
                            }

                            //Get the username
                            if (!Wtsapi32.WTSQuerySessionInformation(Wtsapi32.WtsCurrentServerHandle, sessionInfo.SessionID, Wtsapi32.WtsInfoClass.WtsUserName, out usernamePtr, out uint bytesReturnedUsername))
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error());
                            }

                            //continue when no bytes returned
                            if (bytesReturnedUsername <= 0)
                            {
                                continue;
                            }

                            string sessionUsername = Marshal.PtrToStringUni(usernamePtr);

                            //Get the domain name
                            if (!Wtsapi32.WTSQuerySessionInformation(Wtsapi32.WtsCurrentServerHandle, sessionInfo.SessionID, Wtsapi32.WtsInfoClass.WtsDomainName, out domainPtr, out uint bytesReturnedDomainName))
                            {
                                throw new Win32Exception(Marshal.GetLastWin32Error());
                            }

                            //continue when no bytes returned
                            if (bytesReturnedDomainName <= 0)
                            {
                                continue;
                            }

                            string sessionDomainName = Marshal.PtrToStringUni(domainPtr);

                            //If the username is not the same, go to the next
                            string sessionFullUsername = sessionDomainName.ConvertNullTerminatedStringToString() + "\\" + sessionUsername.ConvertNullTerminatedStringToString();


                            //If the session is found break the for
                            if (!string.IsNullOrWhiteSpace(sessionFullUsername) && sessionFullUsername.Equals(username.Trim(), StringComparison.OrdinalIgnoreCase))
                            {
                                activeSessionId = (uint)sessionInfo.SessionID;
                                break;
                            }
                        }
                        finally
                        {
                            if (usernamePtr != IntPtr.Zero)
                            {
                                Wtsapi32.WTSFreeMemory(usernamePtr);
                            }

                            if (domainPtr != IntPtr.Zero)
                            {
                                Wtsapi32.WTSFreeMemory(domainPtr);
                            }
                        }
                    }
                }
                else
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                if (sessionInfos != IntPtr.Zero)
                {
                    Wtsapi32.WTSFreeMemory(sessionInfos);
                }
            }

            //If enumerating not working throw an exception
            if (activeSessionId == Wtsapi32.InvalidSessionId)
            {
                return(null);
            }

            return(GetPrimaryTokenFromSessionId(activeSessionId));
        }
Exemple #10
0
        /// <summary>
        /// Gets the active session user token.
        /// </summary>
        /// <param name="userToken">The user token.</param>
        /// <returns></returns>
        /// <exception cref="Win32Exception"></exception>
        public static TokenHandle GetActiveSessionUserToken()
        {
            //!!! Parts are from Copyright (c) 2014 Justin Murray - MIT-License, thanks to him !!!
            // https://github.com/murrayju/CreateProcessAsUser, 18.08.2019

            var    primTokenHandle = new TokenHandle();
            uint   activeSessionId = Wtsapi32.InvalidSessionId;
            IntPtr sessionInfos    = IntPtr.Zero;
            var    sessionCount    = 0;

            try
            {
                //Get a handle to the user access token for the current active session.
                if (Wtsapi32.WTSEnumerateSessions(Wtsapi32.WtsCurrentServerHandle, 0, 1, ref sessionInfos, ref sessionCount))
                {
                    int    arrayElementSize = Marshal.SizeOf(typeof(Wtsapi32.WtsSessionInfo));
                    IntPtr current          = sessionInfos;

                    for (var i = 0; i < sessionCount; i++)
                    {
                        var sessionInfo = (Wtsapi32.WtsSessionInfo)Marshal.PtrToStructure(current, typeof(Wtsapi32.WtsSessionInfo));
                        current += arrayElementSize;

                        if (sessionInfo.State == Wtsapi32.WtsConnectstateClass.WTSActive)
                        {
                            activeSessionId = (uint)sessionInfo.SessionID;
                        }
                    }
                }
            }
            finally
            {
                if (sessionInfos != IntPtr.Zero)
                {
                    Wtsapi32.WTSFreeMemory(sessionInfos);
                }
            }

            //If enumerating not working use the fall back method
            if (activeSessionId == Wtsapi32.InvalidSessionId)
            {
                activeSessionId = Kernel32.WTSGetActiveConsoleSessionId();

                if (activeSessionId == Wtsapi32.InvalidSessionId)
                {
                    throw new Exception("No valid session found.");
                }
            }

            var impersonationToken = new TokenHandle();

            try
            {
                //Get token
                if (!Wtsapi32.WTSQueryUserToken(activeSessionId, out impersonationToken))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                //Convert the impersonation token to a primary token
                if (!Advapi32.DuplicateTokenEx(impersonationToken, 0, IntPtr.Zero, (int)Advapi32.SecurityImpersonationLevel.SecurityImpersonation, (int)Advapi32.TokenType.TokenPrimary, ref primTokenHandle))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                impersonationToken.Close();
            }

            return(primTokenHandle);
        }
Exemple #11
0
        /// <summary>
        /// Gets the session token by the username.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <returns></returns>
        /// <exception cref="Exception">No valid session found.</exception>
        /// <exception cref="Win32Exception">
        /// </exception>
        public static TokenHandle GetSessionTokenByUsername(string username)
        {
            //!!! Parts are from Copyright (c) 2014 Justin Murray - MIT-License, thanks to him !!!
            // https://github.com/murrayju/CreateProcessAsUser, 18.08.2019

            var    primTokenHandle = new TokenHandle();
            uint   activeSessionId = Wtsapi32.InvalidSessionId;
            IntPtr sessionInfos    = IntPtr.Zero;
            IntPtr usernamePtr     = IntPtr.Zero;
            IntPtr domainPtr       = IntPtr.Zero;
            var    sessionCount    = 0;

            try
            {
                //Get a handle to the user access token for the current active session.
                if (Wtsapi32.WTSEnumerateSessions(Wtsapi32.WtsCurrentServerHandle, 0, 1, ref sessionInfos, ref sessionCount))
                {
                    int    arrayElementSize = Marshal.SizeOf(typeof(Wtsapi32.WtsSessionInfo));
                    IntPtr current          = sessionInfos;

                    for (var i = 0; i < sessionCount; i++)
                    {
                        var sessionInfo = (Wtsapi32.WtsSessionInfo)Marshal.PtrToStructure(current, typeof(Wtsapi32.WtsSessionInfo));
                        current += arrayElementSize;

                        //If the session is not active, go to the next
                        if (sessionInfo.State != Wtsapi32.WtsConnectstateClass.WTSActive)
                        {
                            continue;
                        }

                        //Get the username
                        if (!Wtsapi32.WTSQuerySessionInformation(Wtsapi32.WtsCurrentServerHandle, sessionInfo.SessionID, Wtsapi32.WtsInfoClass.WtsUserName, out usernamePtr, out uint bytesReturnedUsername))
                        {
                            throw new Win32Exception(Marshal.GetLastWin32Error());
                        }

                        //continue when no bytes returned
                        if (bytesReturnedUsername <= 0)
                        {
                            continue;
                        }

                        string sessionUsername = Marshal.PtrToStringUni(usernamePtr);

                        //Get the domain name
                        if (!Wtsapi32.WTSQuerySessionInformation(Wtsapi32.WtsCurrentServerHandle, sessionInfo.SessionID, Wtsapi32.WtsInfoClass.WtsDomainName, out domainPtr, out uint bytesReturnedDomainName))
                        {
                            throw new Win32Exception(Marshal.GetLastWin32Error());
                        }

                        //continue when no bytes returned
                        if (bytesReturnedDomainName <= 0)
                        {
                            continue;
                        }

                        string sessionDomainName = Marshal.PtrToStringUni(domainPtr);

                        //If the username is not the same, go to the next
                        string sessionFullUsername = sessionDomainName.ConvertNullTerminatedStringToString() + "\\" + sessionUsername.ConvertNullTerminatedStringToString();
                        if (sessionUsername == null || !string.Equals(username.Trim(), sessionFullUsername, StringComparison.CurrentCultureIgnoreCase))
                        {
                            continue;
                        }

                        //If the session is found break the for
                        activeSessionId = (uint)sessionInfo.SessionID;
                        break;
                    }
                }
                else
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                if (usernamePtr != IntPtr.Zero)
                {
                    Wtsapi32.WTSFreeMemory(usernamePtr);
                }

                if (domainPtr != IntPtr.Zero)
                {
                    Wtsapi32.WTSFreeMemory(domainPtr);
                }

                if (sessionInfos != IntPtr.Zero)
                {
                    Wtsapi32.WTSFreeMemory(sessionInfos);
                }
            }

            //If enumerating not working throw an exception
            if (activeSessionId == Wtsapi32.InvalidSessionId)
            {
                throw new Exception("No valid session found.");
            }

            var impersonationToken = new TokenHandle();

            try
            {
                //Get token
                if (!Wtsapi32.WTSQueryUserToken(activeSessionId, out impersonationToken))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }

                //Convert the impersonation token to a primary token
                if (!Advapi32.DuplicateTokenEx(impersonationToken, 0, IntPtr.Zero, (int)Advapi32.SecurityImpersonationLevel.SecurityImpersonation, (int)Advapi32.TokenType.TokenPrimary, ref primTokenHandle))
                {
                    throw new Win32Exception(Marshal.GetLastWin32Error());
                }
            }
            finally
            {
                impersonationToken.Close();
            }

            return(primTokenHandle);
        }
Exemple #12
0
        public static List <Dictionary <string, string> > GetRDPSessions()
        {
            List <Dictionary <string, string> > results = new List <Dictionary <string, string> >();
            // adapted from http://www.pinvoke.net/default.aspx/wtsapi32.wtsenumeratesessions
            IntPtr        server = IntPtr.Zero;
            List <String> ret    = new List <string>();

            server = OpenServer("localhost");

            try
            {
                IntPtr ppSessionInfo = IntPtr.Zero;

                Int32 count    = 0;
                Int32 level    = 1;
                Int32 retval   = Wtsapi32.WTSEnumerateSessionsEx(server, ref level, 0, ref ppSessionInfo, ref count);
                Int32 dataSize = Marshal.SizeOf(typeof(WTS_SESSION_INFO_1));
                Int64 current  = (Int64)ppSessionInfo;

                if (retval != 0)
                {
                    for (int i = 0; i < count; i++)
                    {
                        Dictionary <string, string> rdp_session = new Dictionary <string, string>();
                        WTS_SESSION_INFO_1          si          = (WTS_SESSION_INFO_1)Marshal.PtrToStructure((System.IntPtr)current, typeof(WTS_SESSION_INFO_1));
                        current += dataSize;
                        if (si.pUserName == null || si.pUserName == "")
                        {
                            continue;
                        }

                        rdp_session["SessionID"]    = string.Format("{0}", si.SessionID);
                        rdp_session["pSessionName"] = string.Format("{0}", si.pSessionName);
                        rdp_session["pUserName"]    = string.Format("{0}", si.pUserName);
                        rdp_session["pDomainName"]  = string.Format("{0}", si.pDomainName);
                        rdp_session["State"]        = string.Format("{0}", si.State);
                        rdp_session["SourceIP"]     = "";

                        // Now use WTSQuerySessionInformation to get the remote IP (if any) for the connection
                        IntPtr addressPtr = IntPtr.Zero;
                        uint   bytes      = 0;

                        Wtsapi32.WTSQuerySessionInformation(server, (uint)si.SessionID, WTS_INFO_CLASS.WTSClientAddress, out addressPtr, out bytes);
                        WTS_CLIENT_ADDRESS address = (WTS_CLIENT_ADDRESS)Marshal.PtrToStructure((System.IntPtr)addressPtr, typeof(WTS_CLIENT_ADDRESS));

                        if (address.Address[2] != 0)
                        {
                            string sourceIP = string.Format("{0}.{1}.{2}.{3}", address.Address[2], address.Address[3], address.Address[4], address.Address[5]);
                            rdp_session["SourceIP"] = string.Format("{0}", sourceIP);
                        }
                        results.Add(rdp_session);
                    }

                    Wtsapi32.WTSFreeMemory(ppSessionInfo);
                }
            }
            catch (Exception ex)
            {
                Beaprint.GrayPrint(string.Format("  [X] Exception: {0}", ex));
            }
            finally
            {
                CloseServer(server);
            }
            return(results);
        }
Exemple #13
0
        public static IntPtr OpenServer(String Name)
        {
            IntPtr server = Wtsapi32.WTSOpenServer(Name);

            return(server);
        }
Exemple #14
0
 public static void CloseServer(IntPtr ServerHandle)
 {
     Wtsapi32.WTSCloseServer(ServerHandle);
 }