using Microsoft.Win32.SafeHandles; using System.Runtime.InteropServices; using System.Runtime.Versioning; namespace Insight.Remote.Shared.Native.Windows; public static class SECUR32 { public enum WinStatusCodes : uint { STATUS_SUCCESS = 0 } public enum WinErrors : uint { NO_ERROR = 0, } public enum WinLogonType { LOGON32_LOGON_INTERACTIVE = 2, LOGON32_LOGON_NETWORK = 3, LOGON32_LOGON_BATCH = 4, LOGON32_LOGON_SERVICE = 5, LOGON32_LOGON_UNLOCK = 7, LOGON32_LOGON_NETWORK_CLEARTEXT = 8, LOGON32_LOGON_NEW_CREDENTIALS = 9 } // SECURITY_LOGON_TYPE public enum SecurityLogonType { Interactive = 2, // Interactively logged on (locally or remotely) Network, // Accessing system via network Batch, // Started via a batch queue Service, // Service started by service controller Proxy, // Proxy logon Unlock, // Unlock workstation NetworkCleartext, // Network logon with cleartext credentials NewCredentials, // Clone caller, new default credentials RemoteInteractive, // Remote, yet interactive. Terminal server CachedInteractive, // Try cached credentials without hitting the net. CachedRemoteInteractive, // Same as RemoteInteractive, this is used internally for auditing purpose CachedUnlock // Cached Unlock workstation } [StructLayout(LayoutKind.Sequential)] public struct LSA_UNICODE_STRING { public UInt16 Length; public UInt16 MaximumLength; public IntPtr Buffer; } [StructLayout(LayoutKind.Sequential)] public struct TOKEN_SOURCE { public TOKEN_SOURCE(string name) { SourceName = new byte[8]; System.Text.Encoding.GetEncoding(1252).GetBytes(name, 0, name.Length, SourceName, 0); if (!ADVAPI32.AllocateLocallyUniqueId(out SourceIdentifier)) throw new System.ComponentModel.Win32Exception(); } [MarshalAs(UnmanagedType.ByValArray, SizeConst = 8)] public byte[] SourceName; public IntPtr SourceIdentifier; } [StructLayout(LayoutKind.Sequential)] public struct KERB_INTERACTIVE_LOGON { public KERB_LOGON_SUBMIT_TYPE MessageType; public string LogonDomainName; public string UserName; public string Password; } public enum KERB_LOGON_SUBMIT_TYPE { KerbInteractiveLogon = 2, KerbSmartCardLogon = 6, KerbWorkstationUnlockLogon = 7, KerbSmartCardUnlockLogon = 8, KerbProxyLogon = 9, KerbTicketLogon = 10, KerbTicketUnlockLogon = 11, KerbS4ULogon = 12, KerbCertificateLogon = 13, KerbCertificateS4ULogon = 14, KerbCertificateUnlockLogon = 15 } public enum TOKEN_INFORMATION_CLASS { ///     /// The buffer receives a TOKEN_USER structure that contains the user account of the token.     /// TokenUser = 1, ///     /// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token.     /// TokenGroups, ///     /// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token.     /// TokenPrivileges, ///     /// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects.     /// TokenOwner, ///     /// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects.     /// TokenPrimaryGroup, ///     /// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects.     /// TokenDefaultDacl, ///     /// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information.     /// TokenSource, ///     /// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token.     /// TokenType, ///     /// The buffer receives a SECURITY_IMPERSONATION_LEVEL value that indicates the impersonation level of the token. If the access token is not an impersonation token, the function fails.     /// TokenImpersonationLevel, ///     /// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics.     /// TokenStatistics, ///     /// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token.     /// TokenRestrictedSids, ///     /// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token.     /// TokenSessionId, ///     /// The buffer receives a TOKEN_GROUPS_AND_PRIVILEGES structure that contains the user SID, the group accounts, the restricted SIDs, and the authentication ID associated with the token.     /// TokenGroupsAndPrivileges, ///     /// Reserved.     /// TokenSessionReference, ///     /// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag.     /// TokenSandBoxInert, ///     /// Reserved.     /// TokenAuditPolicy, ///     /// The buffer receives a TOKEN_ORIGIN value.     /// TokenOrigin, ///     /// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.     /// TokenElevationType, ///     /// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token.     /// TokenLinkedToken, ///     /// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated.     /// TokenElevation, ///     /// The buffer receives a DWORD value that is nonzero if the token has ever been filtered.     /// TokenHasRestrictions, ///     /// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token.     /// TokenAccessInformation, ///     /// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token.     /// TokenVirtualizationAllowed, ///     /// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token.     /// TokenVirtualizationEnabled, ///     /// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level.     /// TokenIntegrityLevel, ///     /// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set.     /// TokenUIAccess, ///     /// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy.     /// TokenMandatoryPolicy, ///     /// The buffer receives the token's logon security identifier (SID).     /// TokenLogonSid, ///     /// The maximum value for this enumeration     /// MaxTokenInfoClass } [StructLayout(LayoutKind.Sequential)] public readonly struct QUOTA_LIMITS { readonly UInt32 PagedPoolLimit; readonly UInt32 NonPagedPoolLimit; readonly UInt32 MinimumWorkingSetSize; readonly UInt32 MaximumWorkingSetSize; readonly UInt32 PagefileLimit; readonly Int64 TimeLimit; } [StructLayout(LayoutKind.Sequential)] public struct LSA_STRING { public UInt16 Length; public UInt16 MaximumLength; public /*PCHAR*/ IntPtr Buffer; } [DllImport("secur32.dll", SetLastError = true)] public static extern WinStatusCodes LsaLogonUser( [In] IntPtr LsaHandle, [In] ref LSA_STRING OriginName, [In] SecurityLogonType LogonType, [In] UInt32 AuthenticationPackage, [In] IntPtr AuthenticationInformation, [In] UInt32 AuthenticationInformationLength, [In] /*PTOKEN_GROUPS*/ IntPtr LocalGroups, [In] ref TOKEN_SOURCE SourceContext, [Out] /*PVOID*/ out IntPtr ProfileBuffer, [Out] out UInt32 ProfileBufferLength, [Out] out Int64 LogonId, [Out] out IntPtr Token, [Out] out QUOTA_LIMITS Quotas, [Out] out WinStatusCodes SubStatus ); [DllImport("secur32.dll", SetLastError = true)] public static extern WinStatusCodes LsaRegisterLogonProcess( IntPtr LogonProcessName, out IntPtr LsaHandle, out ulong SecurityMode ); [DllImport("secur32.dll", SetLastError = false)] public static extern WinStatusCodes LsaLookupAuthenticationPackage([In] IntPtr LsaHandle, [In] ref LSA_STRING PackageName, [Out] out UInt32 AuthenticationPackage); [DllImport("secur32.dll", CharSet = CharSet.Auto, SetLastError = true)] [ResourceExposure(ResourceScope.None)] internal static extern int LsaConnectUntrusted( [In, Out] ref SafeLsaLogonProcessHandle LsaHandle); [DllImport("secur32.dll", SetLastError = false)] public static extern WinStatusCodes LsaConnectUntrusted([Out] out IntPtr LsaHandle); [System.Security.SecurityCritical] // auto-generated internal sealed class SafeLsaLogonProcessHandle : SafeHandleZeroOrMinusOneIsInvalid { private SafeLsaLogonProcessHandle() : base(true) { } // 0 is an Invalid Handle internal SafeLsaLogonProcessHandle(IntPtr handle) : base(true) { SetHandle(handle); } internal static SafeLsaLogonProcessHandle InvalidHandle { get { return new SafeLsaLogonProcessHandle(IntPtr.Zero); } } [System.Security.SecurityCritical] protected override bool ReleaseHandle() { // LsaDeregisterLogonProcess returns an NTSTATUS return LsaDeregisterLogonProcess(handle) >= 0; } } [DllImport("secur32.dll", SetLastError = true)] [ResourceExposure(ResourceScope.None)] internal static extern int LsaDeregisterLogonProcess(IntPtr handle); public static void CreateNewSession() { var kli = new SECUR32.KERB_INTERACTIVE_LOGON() { MessageType = SECUR32.KERB_LOGON_SUBMIT_TYPE.KerbInteractiveLogon, UserName = "", Password = "" }; IntPtr kerbLogInfo; SECUR32.LSA_STRING logonProc = new() { Buffer = Marshal.StringToHGlobalAuto("InstaLogon"), Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")), MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")) }; SECUR32.LSA_STRING originName = new() { Buffer = Marshal.StringToHGlobalAuto("InstaLogon"), Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")), MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("InstaLogon")) }; SECUR32.LSA_STRING authPackage = new() { Buffer = Marshal.StringToHGlobalAuto("MICROSOFT_KERBEROS_NAME_A"), Length = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("MICROSOFT_KERBEROS_NAME_A")), MaximumLength = (ushort)Marshal.SizeOf(Marshal.StringToHGlobalAuto("MICROSOFT_KERBEROS_NAME_A")) }; IntPtr hLogonProc = Marshal.AllocHGlobal(Marshal.SizeOf(logonProc)); Marshal.StructureToPtr(logonProc, hLogonProc, false); ADVAPI32.AllocateLocallyUniqueId(out IntPtr pluid); LsaConnectUntrusted(out IntPtr lsaHan); //SECUR32.LsaRegisterLogonProcess(hLogonProc, out lsaHan, out secMode); SECUR32.LsaLookupAuthenticationPackage(lsaHan, ref authPackage, out uint authPackID); kerbLogInfo = Marshal.AllocHGlobal(Marshal.SizeOf(kli)); Marshal.StructureToPtr(kli, kerbLogInfo, false); var ts = new SECUR32.TOKEN_SOURCE("Insta"); SECUR32.LsaLogonUser( lsaHan, ref originName, SECUR32.SecurityLogonType.Interactive, authPackID, kerbLogInfo, (uint)Marshal.SizeOf(kerbLogInfo), IntPtr.Zero, ref ts, out IntPtr profBuf, out uint profBufLen, out long logonID, out IntPtr logonToken, out QUOTA_LIMITS quotas, out WinStatusCodes subStatus); } }