1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 |
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 |