How to know if a Windows session is an interactive one?

后端 未结 3 1079
面向向阳花
面向向阳花 2020-12-18 11:27

I\'m creating a service that will run processes on user interactive session. I found how to start process from session 0 in a service, I found how to catch when a user is lo

3条回答
  •  我在风中等你
    2020-12-18 11:58

    First setup your interop declarations. This is the hardest part

    DllImport("secur32.dll", SetLastError = false)]
    private static extern uint LsaFreeReturnBuffer(IntPtr buffer);
    
    [DllImport("Secur32.dll", SetLastError = false)]
    private static extern uint LsaEnumerateLogonSessions
            (out UInt64 LogonSessionCount, out IntPtr LogonSessionList);
    
    [DllImport("Secur32.dll", SetLastError = false)]
    private static extern uint LsaGetLogonSessionData(IntPtr luid, 
        out IntPtr ppLogonSessionData);
    
    [StructLayout(LayoutKind.Sequential)]
    private struct LSA_UNICODE_STRING
    {
        public UInt16 Length;
        public UInt16 MaximumLength;
        public IntPtr buffer;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    private struct LUID
    {
        public UInt32 LowPart;
        public UInt32 HighPart;
    }
    
    [StructLayout(LayoutKind.Sequential)]
    private struct SECURITY_LOGON_SESSION_DATA
    {
        public UInt32 Size;
        public LUID LoginID;
        public LSA_UNICODE_STRING Username;
        public LSA_UNICODE_STRING LoginDomain;
        public LSA_UNICODE_STRING AuthenticationPackage;
        public UInt32 LogonType;
        public UInt32 Session;
        public IntPtr PSiD;
        public UInt64 LoginTime;
        public LSA_UNICODE_STRING LogonServer;
        public LSA_UNICODE_STRING DnsDomainName;
        public LSA_UNICODE_STRING Upn;
    }
    
    private enum SECURITY_LOGON_TYPE : uint
    {
        Interactive = 2,        //The security principal is logging on 
                                //interactively.
        Network,                //The security principal is logging using a 
                                //network.
        Batch,                  //The logon is for a batch process.
        Service,                //The logon is for a service account.
        Proxy,                  //Not supported.
        Unlock,                 //The logon is an attempt to unlock a workstation.
        NetworkCleartext,       //The logon is a network logon with cleartext 
                                //credentials.
        NewCredentials,         //Allows the caller to clone its current token and
                                //specify new credentials for outbound connections.
        RemoteInteractive,      //A terminal server session that is both remote 
                                //and interactive.
        CachedInteractive,      //Attempt to use the cached credentials without 
                                //going out across the network.
        CachedRemoteInteractive,// Same as RemoteInteractive, except used 
                                // internally for auditing purposes.
        CachedUnlock            // The logon is an attempt to unlock a workstation.
    }
    

    Next Enumerate and extract the information

      UInt64 count;
      IntPtr luidPtr = IntPtr.Zero;
      LsaEnumerateLogonSessions(out count, out luidPtr);  //gets an array of 
                                                          //pointers to LUIDs
    
      IntPtr iter = luidPtr;                              //set the pointer to the
                                                          //start of the array
    
      for (ulong i = 0; i < count; i++)                   //for each pointer in the
                                                          //array
      {
          IntPtr sessionData;
    
          LsaGetLogonSessionData(iter, out sessionData);
          SECURITY_LOGON_SESSION_DATA data =(
              SECURITY_LOGON_SESSION_DATA)Marshal.PtrToStructure
                    (sessionData, typeof(SECURITY_LOGON_SESSION_DATA));
    
          //if we have a valid logon
          if (data.PSiD != IntPtr.Zero)
          {
              //get the security identifier for further use
              System.Security.Principal.SecurityIdentifier sid = 
              new System.Security.Principal.SecurityIdentifier(data.PSiD);
    
              SECURITY_LOGON_TYPE secType = (SECURITY_LOGON_TYPE)data.LogonType;
    
              //Look at sectype to see if interactive or remote interactive
              Console.WriteLine(secType.ToString())
              If (secType == SECURITY_LOGON_TYPE.Interactive || secType ==    SECURITY_LOGON_TYPE.RemoteInteractive)
              {
                //do something
              }
    
           }
    
           iter = (IntPtr)((int)iter + Marshal.SizeOf(typeof(LUID))); 
           //move the pointer forward
           LsaFreeReturnBuffer(sessionData);
           //free the SECURITY_LOGON_SESSION_DATA memory in the struct
      }
      LsaFreeReturnBuffer(luidPtr);       //free the array of LUIDs
    

提交回复
热议问题