// --------------------------------------------------------------------------
        // RDP / TS Session Hijack Functions

        //Slightly modified code from James Forshaw's COM Session Moniker EoP Exploit + several P-Invoke definitions [https://www.exploit-db.com/exploits/41607]
        static int GetActiveSession()
        {
            List <int> sids           = new List <int>();
            IntPtr     pSessions      = IntPtr.Zero;
            int        dwSessionCount = 0;
            int        activeSession  = 0;

            try
            {
                if (Win32.WTSEnumerateSessions(IntPtr.Zero, 0, 1, out pSessions, out dwSessionCount))
                {
                    IntPtr current = pSessions;
                    for (int i = 0; i < dwSessionCount; ++i)
                    {
                        Win32.WTS_SESSION_INFO session_info = (Win32.WTS_SESSION_INFO)Marshal.PtrToStructure(current, typeof(Win32.WTS_SESSION_INFO));
                        if (session_info.State == Win32.WTS_CONNECTSTATE_CLASS.WTSActive)
                        {
                            activeSession = session_info.SessionId;
                        }
                        current += Marshal.SizeOf(typeof(Win32.WTS_SESSION_INFO));
                    }
                }
            }
            finally
            {
                if (pSessions != IntPtr.Zero)
                {
                    Win32.WTSFreeMemory(pSessions);
                }
            }
            return(activeSession);
        }
        // --------------------------------------------------------------------------
        // RDP / TS Session Query Functions

        public static void GetTSSessions(string serverName)
        {
            IntPtr        serverHandle = IntPtr.Zero;
            List <string> resultList   = new List <string>();

            serverHandle = Win32.WTSOpenServer(serverName);

            try
            {
                IntPtr pSessions      = IntPtr.Zero;
                IntPtr userPtr        = IntPtr.Zero;
                IntPtr domainPtr      = IntPtr.Zero;
                Int32  dwSessionCount = 0;
                bool   retVal         = Win32.WTSEnumerateSessions(serverHandle, 0, 1, out pSessions, out dwSessionCount);
                Int32  dataSize       = Marshal.SizeOf(typeof(Win32.WTS_SESSION_INFO));
                IntPtr currentSession = pSessions;

                //if (retVal != 0)
                if (retVal)
                {
                    for (int i = 0; i < dwSessionCount; i++)
                    {
                        Win32.WTS_SESSION_INFO si = (Win32.WTS_SESSION_INFO)Marshal.PtrToStructure((System.IntPtr)currentSession, typeof(Win32.WTS_SESSION_INFO));
                        currentSession += dataSize;

                        //Session Id
                        Console.WriteLine("\nSession ID: " + si.SessionId.ToString());

                        //Session State
                        string state = "Unknown";
                        if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSActive)
                        {
                            state = "Active";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSConnected)
                        {
                            state = "Connecting";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSConnectQuery)
                        {
                            state = "ConnectQuery";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSDisconnected)
                        {
                            state = "Disconnected";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSDown)
                        {
                            state = "Down due to error";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSIdle)
                        {
                            state = "Idle and waiting for connection";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSInit)
                        {
                            state = "initializing";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSListen)
                        {
                            state = "Listening for a connection";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSReset)
                        {
                            state = "Resetting a connection";
                        }
                        else if (si.State == Win32.WTS_CONNECTSTATE_CLASS.WTSShadow)
                        {
                            state = "Shadowing";
                        }
                        Console.WriteLine("Session State: " + state);

                        //Session User
                        string username = "";
                        username = GetUsernameBySessionId(serverHandle, si.SessionId);
                        Console.WriteLine("Identity: " + username);

                        Win32.WTSFreeMemory(userPtr);
                        Win32.WTSFreeMemory(domainPtr);
                    }

                    Win32.WTSFreeMemory(pSessions);
                }
                Console.WriteLine("");
            }
            catch (Exception e)
            {
                Console.WriteLine("\n [-] Error: " + e.Message + "\n");
            }
            finally
            {
                Win32.WTSCloseServer(serverHandle);
            }
        }