mirror of
https://github.com/snltty/linker.git
synced 2025-10-23 17:13:12 +08:00
378 lines
14 KiB
C#
378 lines
14 KiB
C#
using Microsoft.Win32.SafeHandles;
|
||
using System;
|
||
using System.Runtime.InteropServices;
|
||
using System.Runtime.Versioning;
|
||
|
||
|
||
namespace linker.libs.winapis;
|
||
|
||
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
|
||
{
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_USER structure that contains the user account of the token.
|
||
/// </summary>
|
||
TokenUser = 1,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_GROUPS structure that contains the group accounts associated with the token.
|
||
/// </summary>
|
||
TokenGroups,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_PRIVILEGES structure that contains the privileges of the token.
|
||
/// </summary>
|
||
TokenPrivileges,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_OWNER structure that contains the default owner security identifier (SID) for newly created objects.
|
||
/// </summary>
|
||
TokenOwner,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_PRIMARY_GROUP structure that contains the default primary group SID for newly created objects.
|
||
/// </summary>
|
||
TokenPrimaryGroup,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_DEFAULT_DACL structure that contains the default DACL for newly created objects.
|
||
/// </summary>
|
||
TokenDefaultDacl,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_SOURCE structure that contains the source of the token. TOKEN_QUERY_SOURCE access is needed to retrieve this information.
|
||
/// </summary>
|
||
TokenSource,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_TYPE value that indicates whether the token is a primary or impersonation token.
|
||
/// </summary>
|
||
TokenType,
|
||
|
||
/// <summary>
|
||
/// 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.
|
||
/// </summary>
|
||
TokenImpersonationLevel,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_STATISTICS structure that contains various token statistics.
|
||
/// </summary>
|
||
TokenStatistics,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_GROUPS structure that contains the list of restricting SIDs in a restricted token.
|
||
/// </summary>
|
||
TokenRestrictedSids,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a DWORD value that indicates the Terminal Services session identifier that is associated with the token.
|
||
/// </summary>
|
||
TokenSessionId,
|
||
|
||
/// <summary>
|
||
/// 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.
|
||
/// </summary>
|
||
TokenGroupsAndPrivileges,
|
||
|
||
/// <summary>
|
||
/// Reserved.
|
||
/// </summary>
|
||
TokenSessionReference,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a DWORD value that is nonzero if the token includes the SANDBOX_INERT flag.
|
||
/// </summary>
|
||
TokenSandBoxInert,
|
||
|
||
/// <summary>
|
||
/// Reserved.
|
||
/// </summary>
|
||
TokenAuditPolicy,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_ORIGIN value.
|
||
/// </summary>
|
||
TokenOrigin,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_ELEVATION_TYPE value that specifies the elevation level of the token.
|
||
/// </summary>
|
||
TokenElevationType,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_LINKED_TOKEN structure that contains a handle to another token that is linked to this token.
|
||
/// </summary>
|
||
TokenLinkedToken,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_ELEVATION structure that specifies whether the token is elevated.
|
||
/// </summary>
|
||
TokenElevation,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a DWORD value that is nonzero if the token has ever been filtered.
|
||
/// </summary>
|
||
TokenHasRestrictions,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_ACCESS_INFORMATION structure that specifies security information contained in the token.
|
||
/// </summary>
|
||
TokenAccessInformation,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a DWORD value that is nonzero if virtualization is allowed for the token.
|
||
/// </summary>
|
||
TokenVirtualizationAllowed,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a DWORD value that is nonzero if virtualization is enabled for the token.
|
||
/// </summary>
|
||
TokenVirtualizationEnabled,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_MANDATORY_LABEL structure that specifies the token's integrity level.
|
||
/// </summary>
|
||
TokenIntegrityLevel,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a DWORD value that is nonzero if the token has the UIAccess flag set.
|
||
/// </summary>
|
||
TokenUIAccess,
|
||
|
||
/// <summary>
|
||
/// The buffer receives a TOKEN_MANDATORY_POLICY structure that specifies the token's mandatory integrity policy.
|
||
/// </summary>
|
||
TokenMandatoryPolicy,
|
||
|
||
/// <summary>
|
||
/// The buffer receives the token's logon security identifier (SID).
|
||
/// </summary>
|
||
TokenLogonSid,
|
||
|
||
/// <summary>
|
||
/// The maximum value for this enumeration
|
||
/// </summary>
|
||
MaxTokenInfoClass
|
||
}
|
||
[StructLayout(LayoutKind.Sequential)]
|
||
public 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);
|
||
}
|
||
} |