Remove-Variable * -ErrorAction SilentlyContinue; Remove-Module *; $error.Clear();

$MethodDefinition = @’

[DllImport("Secur32.dll", CharSet = CharSet.Unicode)]
public static extern uint LsaEnumerateLogonSessions(out UInt64 LogonSessionCount, out IntPtr LogonSessionList);

[DllImport("Secur32.dll", CharSet = CharSet.Unicode)]
public static extern uint LsaGetLogonSessionData(IntPtr luid, out IntPtr ppLogonSessionData);

‘@
$Secur32 = Add-Type -MemberDefinition $MethodDefinition -Name ‘Secur32’ -Namespace ‘Secur32’ -PassThru

add-type -PassThru -TypeDefinition @"
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.InteropServices;
using System.Security.Principal;
using System.Text;
namespace Ansible
   {

[StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
        public struct LSA_UNICODE_STRING
        {
            public UInt16 Length;
            public UInt16 MaximumLength;
            public IntPtr buffer;
        }

[StructLayout(LayoutKind.Sequential)]
        public struct LUID
        {
            public UInt32 LowPart;
            public Int32 HighPart;
        }

[StructLayout(LayoutKind.Sequential)]
public class 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;
}}
"@


function LsaEnumerateLogonSessions
{
    <#
    .SYNOPSIS
    The LsaEnumerateLogonSessions function retrieves the set of existing logon session identifiers (LUIDs) and the number of sessions.
    .DESCRIPTION
    To retrieve information about the logon sessions returned by LsaEnumerateLogonSessions, call the LsaGetLogonSessionData function.
    .NOTES
    Author: Jared Atkinson (@jaredcatkinson)
    License: BSD 3-Clause
    Required Dependencies: None
    Optional Dependencies: None
    .LINK
    https://msdn.microsoft.com/en-us/library/windows/desktop/aa378275(v=vs.85).aspx
    .EXAMPLE
    LsaEnumerateLogonSessions
    8
    2390553591808
    .EXAMPLE
    $SessionCount, $LogonSessionListPtr = LsaEnumerateLogonSessions
    #>

    <#
    (func secur32 LsaEnumerateLogonSessions ([UInt32]) @(
        [UInt64].MakeByRefType(), #_Out_ PULONG LogonSessionCount,
        [IntPtr].MakeByRefType()  #_Out_ PLUID  *LogonSessionList
    ))
    #>

    $LogonSessionCount = [UInt64]0
    $LogonSessionList = [IntPtr]::Zero

    $SUCCESS = $Secur32::LsaEnumerateLogonSessions([ref]$LogonSessionCount, [ref]$LogonSessionList)

    if($SUCCESS -ne 0)
    {
        $WinErrorCode = LsaNtStatusToWinError -NtStatus $success
        $LastError = [ComponentModel.Win32Exception]$WinErrorCode
        throw "LsaEnumerateLogonSessions Error: $($LastError.Message)"
    }

    return $LogonSessionCount, $LogonSessionList
}



function LsaGetLogonSessionData
{
    <#
    .SYNOPSIS

    The LsaGetLogonSessionData function retrieves information about a specified logon session.

    .DESCRIPTION

    .Parameter LuidPtr

    .Parameter SessionCount

    .NOTES

    Author: Jared Atkinson (@jaredcatkinson)
    License: BSD 3-Clause
    Required Dependencies: LsaNtStatusToWinError, SECURITY_LOGON_SESSION_DATA (Struct), SECURITY_LOGON_TYPE (Enum)
    Optional Dependencies: None

    (func secur32 LsaGetLogonSessionData ([UInt32]) @(
        [IntPtr], #_In_ PLUID LogonId,
        [IntPtr].MakeByRefType() #_Out_ PSECURITY_LOGON_SESSION_DATA *ppLogonSessionData
    ) -EntryPoint LsaGetLogonSessionData)

    .LINK

    https://msdn.microsoft.com/en-us/library/windows/desktop/aa378290(v=vs.85).aspx

    .EXAMPLE

    #>

    param
    (
        [Parameter(Mandatory = $true)]
        [IntPtr]
        $LuidPtr,

        [Parameter(Mandatory = $true)]
        [UInt32]
        $SessionCount
    )

    $CurrentLuidPtr = $LuidPtr

    for($i = 0; $i -lt $SessionCount; $i++)
    {
        $sessionDataPtr = [IntPtr]::Zero
        $SUCCESS = $Secur32::LsaGetLogonSessionData($CurrentLuidPtr, [ref]$sessionDataPtr)

        if($SUCCESS -ne 0)
        {
            $WinErrorCode = LsaNtStatusToWinError -NtStatus $success
            $LastError = [ComponentModel.Win32Exception]$WinErrorCode
            throw "LsaGetLogonSessionData Error: $($LastError.Message)"
        }

        try
        {
            Write-Host $sessionDataPtr.GetType()
            #$SECURITY_LOGON_SESSION_DATA
            $SECURITY_LOGON_SESSION_DATA = new-object Ansible.SECURITY_LOGON_SESSION_DATA
            #Write-Host $SECURITY_LOGON_SESSION_DATA.GetType()
            [Ansible.SECURITY_LOGON_SESSION_DATA]$sessionData = [system.runtime.interopservices.marshal]::PtrToStructure($sessionDataPtr,[type]$SECURITY_LOGON_SESSION_DATA)
            #$sessionData = $sessionDataPtr -as Ansible.SECURITY_LOGON_SESSION_DATA

            [Ansible.SECURITY_LOGON_SESSION_DATA]$sessionData = $sessionDataPtr
            Write-Host $sessionData.Username

            $props = @{
                LogonId = $sessionData.LogonId.LowPart
                UserName = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.Username.Buffer, $sessionData.Username.Length / 2)
                LogonDomain = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.LogonDomain.Buffer, $sessionData.LognDomain.Length / 2)
                AuthenticationPackage = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.AuthenticationPackage.Buffer, $sessionData.AuthenticationPackage.Length / 2)
                LogonType = $sessionData.LogonType -as $SECURITY_LOGON_TYPE
                Session = $sessionData.Session
                Sid = New-Object -TypeName System.Security.Principal.SecurityIdentifier($sessionData.PSiD)
                LogonTime = [datetime]::FromFileTime($sessionData.LogonTime)
                LogonServer = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.LogonServer.Buffer, $sessionData.LogonServer.Length / 2)
                DnsDomainName = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.DnsDomainName.Buffer, $sessionData.DnsDomainName.Length / 2)
                Upn =  [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.Upn.Buffer, $sessionData.Upn.Length / 2)
                UserFlags = $sessionData.UserFlags
                LastSuccessfulLogon = $sessionData.LastLogonInfo.LastSuccessfulLogon
                LastFailedLogon = $sessionData.LastLogonInfo.LastFailedLogon
                FailedAttemptCountSinceLastSuccessfulLogon = $sessionData.LastLogonInfo.FailedAttemptCountSinceLastSuccessfulLogon
                LogonScript = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.LogonScript.Buffer, $sessionData.LogonScript.Length / 2)
                ProfilePath = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.ProfilePath.Buffer, $sessionData.ProfilePath.Length / 2)
                HomeDirectory = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.HomeDirectory.Buffer, $sessionData.HomeDirectory.Length / 2)
                HomeDirectoryDrive = [System.Runtime.InteropServices.Marshal]::PtrToStringUni($sessionData.HomeDirectoryDrive.Buffer, $sessionData.HomeDirectoryDrive.Length / 2)
                LogoffTime = $sessionData.LogoffTime
                KickOffTime = $sessionData.KickOffTime
                PasswordLastSet = [datetime]::FromFileTime($sessionData.PasswordLastSet)
                PasswordCanChange = [datetime]::FromFileTime($sessionData.PasswordCanChange)
                PasswordMustChange = $sessionData.PasswordMustChange
            }

            $obj = New-Object -TypeName psobject -Property $props

            Write-Output $obj
        }
        catch
        {
            write-host $_
            exit
        }

        #LsaFreeReturnBuffer -Buffer $sessionDataPtr
        $CurrentLuidPtr = [IntPtr]($CurrentLuidPtr.ToInt64() + $LUID::GetSize())
    }
}
$SessionCount, $LuidPtr = LsaEnumerateLogonSessions
$Sessions = LsaGetLogonSessionData -LuidPtr $LuidPtr -SessionCount $SessionCount

Leave a Reply

Your email address will not be published. Required fields are marked *

To create code blocks or other preformatted text, indent by four spaces:

    This will be displayed in a monospaced font. The first four 
    spaces will be stripped off, but all other whitespace
    will be preserved.
    
    Markdown is turned off in code blocks:
     [This is not a link](http://example.com)

To create not a block, but an inline code span, use backticks:

Here is some inline `code`.

For more help see http://daringfireball.net/projects/markdown/syntax