/// <summary> /// Get a safer token. /// </summary> /// <param name="token">The base token.</param> /// <param name="level">The safer level to use.</param> /// <param name="make_inert">True to make the token inert.</param> /// <returns>The safer token.</returns> public static NtToken GetTokenFromSaferLevel(NtToken token, SaferLevel level, bool make_inert) { IntPtr level_handle; if (!Win32NativeMethods.SaferCreateLevel(SaferScope.User, level, Win32NativeMethods.SAFER_LEVEL_OPEN, out level_handle, IntPtr.Zero)) { throw new SafeWin32Exception(); } try { using (NtToken duptoken = token.Duplicate(TokenAccessRights.GenericRead | TokenAccessRights.GenericExecute)) { SafeKernelObjectHandle handle; if (Win32NativeMethods.SaferComputeTokenFromLevel(level_handle, duptoken.Handle, out handle, make_inert ? SaferFlags.MakeInert : 0, IntPtr.Zero)) { return(NtToken.FromHandle(handle)); } else { throw new SafeWin32Exception(); } } } finally { Win32NativeMethods.SaferCloseLevel(level_handle); } }
/// <summary> /// Get tokens for all logged on sessions. /// </summary> /// <remarks>Needs SeTcbPrivilege to work.</remarks> /// <returns>The list of session tokens.</returns> public static IEnumerable <NtToken> GetSessionTokens() { List <NtToken> tokens = new List <NtToken>(); IntPtr pSessions = IntPtr.Zero; int dwSessionCount = 0; try { if (Win32NativeMethods.WTSEnumerateSessions(IntPtr.Zero, 0, 1, out pSessions, out dwSessionCount)) { IntPtr current = pSessions; for (int i = 0; i < dwSessionCount; ++i) { WTS_SESSION_INFO session_info = (WTS_SESSION_INFO)Marshal.PtrToStructure(current, typeof(WTS_SESSION_INFO)); if (session_info.State == WTS_CONNECTSTATE_CLASS.WTSActive && Win32NativeMethods.WTSQueryUserToken(session_info.SessionId, out SafeKernelObjectHandle handle)) { tokens.Add(NtToken.FromHandle(handle)); } current += Marshal.SizeOf(typeof(WTS_SESSION_INFO)); } } } finally { if (pSessions != IntPtr.Zero) { Win32NativeMethods.WTSFreeMemory(pSessions); } } return(tokens); }
private static NtResult <NtToken> LsaLogonUser(SecurityLogonType type, string auth_package, string origin_name, SafeBuffer buffer, IEnumerable <UserGroup> local_groups, bool throw_on_error) { using (var list = new DisposableList()) { var hlsa = list.AddResource(SafeLsaLogonHandle.Connect(throw_on_error)); if (!hlsa.IsSuccess) { return(hlsa.Cast <NtToken>()); } var auth_pkg = hlsa.Result.LookupAuthPackage(auth_package, throw_on_error); if (!auth_pkg.IsSuccess) { return(auth_pkg.Cast <NtToken>()); } var groups = local_groups == null ? SafeTokenGroupsBuffer.Null : list.AddResource(SafeTokenGroupsBuffer.Create(local_groups)); TOKEN_SOURCE tokenSource = new TOKEN_SOURCE("NT.NET"); SecurityNativeMethods.AllocateLocallyUniqueId(out tokenSource.SourceIdentifier); QUOTA_LIMITS quota_limits = new QUOTA_LIMITS(); return(SecurityNativeMethods.LsaLogonUser(hlsa.Result, new LsaString(origin_name), type, auth_pkg.Result, buffer, buffer.GetLength(), groups, tokenSource, out SafeLsaReturnBufferHandle profile, out int cbProfile, out Luid logon_id, out SafeKernelObjectHandle token_handle, quota_limits, out NtStatus subStatus).CreateResult(throw_on_error, () => { using (profile) { return NtToken.FromHandle(token_handle); } })); } }
/// <summary> /// Logon a user. /// </summary> /// <param name="type">The type of logon.</param> /// <param name="auth_package">The authentication package to use.</param> /// <param name="origin_name">The name of the origin.</param> /// <param name="source_context">The token source context.</param> /// <param name="buffer">The authentication credentials buffer.</param> /// <param name="local_groups">Additional local groups.</param> /// <param name="throw_on_error">True to throw on error.</param> /// <returns>The LSA logon result.</returns> public NtResult <LsaLogonResult> LsaLogonUser(SecurityLogonType type, string auth_package, string origin_name, TokenSource source_context, SafeBuffer buffer, IEnumerable <UserGroup> local_groups, bool throw_on_error) { using (var list = new DisposableList()) { var auth_pkg = _handle.LookupAuthPackage(auth_package, throw_on_error); if (!auth_pkg.IsSuccess) { return(auth_pkg.Cast <LsaLogonResult>()); } var groups = local_groups == null ? SafeTokenGroupsBuffer.Null : list.AddResource(SafeTokenGroupsBuffer.Create(local_groups)); QUOTA_LIMITS quota_limits = new QUOTA_LIMITS(); return(SecurityNativeMethods.LsaLogonUser(_handle, new LsaString(origin_name), type, auth_pkg.Result, buffer, buffer.GetLength(), groups, source_context, out SafeLsaReturnBufferHandle profile, out int cbProfile, out Luid logon_id, out SafeKernelObjectHandle token_handle, quota_limits, out NtStatus subStatus).CreateResult(throw_on_error, () => { profile.InitializeLength(cbProfile); return new LsaLogonResult(NtToken.FromHandle(token_handle), profile, logon_id, quota_limits); })); } }
/// <summary> /// Logon a user with a username and password. /// </summary> /// <param name="user">The username.</param> /// <param name="domain">The user's domain.</param> /// <param name="password">The user's password.</param> /// <param name="type">The type of logon token.</param> /// <returns>The logged on token.</returns> public static NtToken Logon(string user, string domain, string password, SecurityLogonType type) { if (!Win32NativeMethods.LogonUser(user, domain, password, type, 0, out SafeKernelObjectHandle handle)) { throw new SafeWin32Exception(); } return(NtToken.FromHandle(handle)); }
private static NtToken CreateToken(long handle) { if (handle == 0) { return(null); } return(NtToken.FromHandle(new IntPtr(handle), true)); }
/// <summary> /// Get session token for a session ID. /// </summary> /// <param name="session_id">The session ID.</param> /// <returns>The session token.</returns> public static NtToken GetSessionToken(int session_id) { if (!Win32NativeMethods.WTSQueryUserToken(session_id, out SafeKernelObjectHandle handle)) { throw new SafeWin32Exception(); } return(NtToken.FromHandle(handle)); }
/// <summary> /// Open the current clipboard token. /// </summary> /// <param name="desired_access"></param> /// <param name="throw_on_error"></param> /// <returns></returns> public static NtResult <NtToken> OpenClipboardToken(TokenAccessRights desired_access, bool throw_on_error) { if (Win32NativeMethods.GetClipboardAccessToken(out SafeKernelObjectHandle handle, desired_access)) { return(NtToken.FromHandle(handle).CreateResult()); } return(NtStatus.STATUS_NO_TOKEN.CreateResultFromError <NtToken>(throw_on_error)); }
internal static ExportedSecurityContext ExportContext(SecHandle context, SecPkgContextExportFlags export_flags, string package) { using (SecBuffer buffer = new SecBuffer(SecurityBufferType.Empty, 64 * 1024)) { SecurityNativeMethods.ExportSecurityContext(context, SecPkgContextExportFlags.None, buffer, out SafeKernelObjectHandle token).CheckResult(); return(new ExportedSecurityContext(package, buffer.ToArray(), NtToken.FromHandle(token))); } }
/// <summary> /// Get the token from the clipboard. /// </summary> /// <param name="desired_access">The access rights for the opened token.</param> /// <returns>The clipboard token.</returns> public static NtToken GetTokenFromClipboard(TokenAccessRights desired_access) { try { return(NtToken.FromHandle(OpenClipboardToken(desired_access))); } catch (NtException) { throw; } catch { throw new InvalidOperationException("GetClipboardAccessToken doesn't exist"); } }
static Form GetFormFromArgs(string[] args) { try { int pid = -1; int handle = -1; string text = string.Empty; bool show_help = false; OptionSet opts = new OptionSet() { { "p|pid=", "Specify a process ID to view the token.", v => pid = int.Parse(v) }, { "handle=", "Specify an inherited handle to view.", v => handle = int.Parse(v) }, { "text=", "Specify a text string for the token window.", v => text = v }, { "h|help", "Show this message and exit", v => show_help = v != null }, }; opts.Parse(args); if (show_help || (handle <= 0 && pid <= 0)) { ShowHelp(opts); } else if (handle > 0) { using (NtToken token = NtToken.FromHandle(new SafeKernelObjectHandle(new IntPtr(handle), true))) { if (token.NtType != NtType.GetTypeByType <NtToken>()) { throw new ArgumentException("Passed handle is not a token"); } return(new TokenForm(token.Duplicate(), text)); } } else if (pid > 0) { using (NtProcess process = NtProcess.Open(pid, ProcessAccessRights.QueryLimitedInformation)) { return(new TokenForm(process.OpenToken(), $"{process.Name}:{pid}")); } } } catch (Exception ex) { MessageBox.Show(ex.Message, "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } return(null); }
public static NtResult <NtToken> CreateAppContainerToken(NtToken token, Sid appcontainer_sid, IEnumerable <Sid> capabilities, bool throw_on_error) { using (var resources = new DisposableList()) { SECURITY_CAPABILITIES caps = Win32Utils.CreateSecuityCapabilities(appcontainer_sid, capabilities ?? new Sid[0], resources); if (!Win32NativeMethods.CreateAppContainerToken(token.GetHandle(), ref caps, out SafeKernelObjectHandle new_token)) { return(Win32Utils.GetLastWin32Error().CreateResultFromDosError <NtToken>(throw_on_error)); } return(NtToken.FromHandle(new_token).CreateResult()); } }
public static NtToken LogonS4U(string user, string realm, SecurityLogonType type) { SafeLsaHandle hlsa = null; LsaString pkgName = new LsaString("Negotiate"); LsaConnectUntrusted(out hlsa).ToNtException(); using (hlsa) { uint authnPkg; LsaLookupAuthenticationPackage(hlsa, pkgName, out authnPkg).ToNtException(); byte[] user_bytes = Encoding.Unicode.GetBytes(user); byte[] realm_bytes = Encoding.Unicode.GetBytes(realm); using (var buffer = new SafeStructureInOutBuffer <KERB_S4U_LOGON>(user_bytes.Length + realm_bytes.Length, true)) { KERB_S4U_LOGON logon_struct = new KERB_S4U_LOGON(); logon_struct.MessageType = KERB_LOGON_SUBMIT_TYPE.KerbS4ULogon; SafeHGlobalBuffer data_buffer = buffer.Data; logon_struct.ClientUpn.Buffer = data_buffer.DangerousGetHandle(); data_buffer.WriteArray(0, user_bytes, 0, user_bytes.Length); logon_struct.ClientUpn.Length = (ushort)user_bytes.Length; logon_struct.ClientUpn.MaximumLength = (ushort)user_bytes.Length; logon_struct.ClientRealm.Buffer = data_buffer.DangerousGetHandle() + user_bytes.Length; data_buffer.WriteArray((ulong)user_bytes.Length, realm_bytes, 0, realm_bytes.Length); logon_struct.ClientRealm.Length = (ushort)realm_bytes.Length; logon_struct.ClientRealm.MaximumLength = (ushort)realm_bytes.Length; Marshal.StructureToPtr(logon_struct, buffer.DangerousGetHandle(), false); TOKEN_SOURCE tokenSource = new TOKEN_SOURCE("NtLmSsp"); AllocateLocallyUniqueId(out tokenSource.SourceIdentifier); LsaString originName = new LsaString("S4U"); IntPtr profile; int cbProfile; Luid logon_id; NtStatus subStatus; QUOTA_LIMITS quota_limits; SafeKernelObjectHandle token_handle; LsaLogonUser(hlsa, originName, type, authnPkg, buffer, buffer.Length, IntPtr.Zero, tokenSource, out profile, out cbProfile, out logon_id, out token_handle, out quota_limits, out subStatus).ToNtException(); LsaFreeReturnBuffer(profile); return(NtToken.FromHandle(token_handle)); } } }
public static NtToken GetTokenFromClipboard() { try { return(NtToken.FromHandle(OpenClipboardToken())); } catch (SafeWin32Exception) { throw; } catch { throw new InvalidOperationException("GetClipboardAccessToken doesn't exist"); } }
/// <summary> /// The main entry point for the application. /// </summary> public static void Main(string[] args) { string database_file = null; string save_file = null; bool do_enum = false; bool enum_clsid = false; bool enum_runtime = false; bool show_help = false; bool query_interfaces = false; int concurrent_queries = Environment.ProcessorCount; bool refresh_interfaces = false; bool enable_activation_filter = false; string symbol_dir = null; bool delete_database = false; string view_access_sd = null; string view_launch_sd = null; string view_name = null; COMRegistryMode mode = COMRegistryMode.Merged; IEnumerable <COMServerType> server_types = new COMServerType[] { COMServerType.InProcHandler32, COMServerType.InProcServer32, COMServerType.LocalServer32 }; NtToken token = null; OptionSet opts = new OptionSet() { { "i|in=", "Open a database file.", v => database_file = v }, { "o|out=", "Save database and exit.", v => save_file = v }, { "e|enum", "Enumerate the provided CLSID (GUID).", v => enum_clsid = v != null }, { "r|rt", "Enumerate the provided Runtime Class.", v => enum_runtime = v != null }, { "q|query", "Query all interfaces for database", v => query_interfaces = v != null }, { "c|conn=", "Number of concurrent interface queries", v => concurrent_queries = int.Parse(v) }, { "s|server=", "Specify server types for query", v => server_types = ParseServerTypes(v) }, { "refresh", "Refresh interfaces in query", v => refresh_interfaces = v != null }, { "m", "Loading mode is machine only.", v => mode = COMRegistryMode.MachineOnly }, { "u", "Loading mode is user only.", v => mode = COMRegistryMode.UserOnly }, { "a", "Enable activation filter.", v => enable_activation_filter = v != null }, { "g=", "Generate a symbol file in the specified directory.", v => symbol_dir = v }, { "d", "Delete the input database once loaded", v => delete_database = v != null }, { "v=", "View a COM access security descriptor (specify the SDDL)", v => view_access_sd = v }, { "l=", "View a COM launch security descriptor (specify the SDDL)", v => view_launch_sd = v }, { "n=", "Name any simple form display such as security descriptor", v => view_name = v }, { "t=", "Specify a token to use when enumerating interfaces", v => token = NtToken.FromHandle(new IntPtr(int.Parse(v))) }, { "h|help", "Show this message and exit.", v => show_help = v != null }, }; List <string> additional_args = new List <string>(); try { additional_args = opts.Parse(args); } catch { show_help = true; } do_enum = enum_clsid || enum_runtime; if (show_help || (do_enum && additional_args.Count < 4) || (symbol_dir != null && !Directory.Exists(symbol_dir))) { StringWriter writer = new StringWriter(); writer.WriteLine("Usage: OleViewDotNet [options] [enum args]"); writer.WriteLine(); writer.WriteLine("Options:"); opts.WriteOptionDescriptions(writer); MessageBox.Show(writer.ToString(), "Help", MessageBoxButtons.OK, MessageBoxIcon.Information); Environment.Exit(1); } if (do_enum) { try { Environment.Exit(EnumInterfaces(new Queue <string>(additional_args), enum_runtime, token)); } catch { Environment.Exit(42); } } else if (symbol_dir != null) { try { COMUtilities.GenerateSymbolFile(symbol_dir, Environment.Is64BitProcess ? Properties.Settings.Default.DbgHelpPath64 : Properties.Settings.Default.DbgHelpPath32, Properties.Settings.Default.SymbolPath); Environment.Exit(0); } catch (Exception) { Environment.Exit(1); } } else { AutoSaveLoadConfiguration autoload_config = new AutoSaveLoadConfiguration(); AppDomain.CurrentDomain.UnhandledException += UnhandledExceptionHandler; Application.EnableVisualStyles(); Application.SetCompatibleTextRenderingDefault(false); try { if (view_access_sd != null || view_launch_sd != null) { bool access = view_access_sd != null; SecurityDescriptor sd = new SecurityDescriptor(view_access_sd ?? view_launch_sd); bool has_container = false; if (sd.DaclPresent) { foreach (var ace in sd.Dacl) { if (ace.Mask.IsAccessGranted(COMAccessRights.ActivateContainer | COMAccessRights.ExecuteContainer)) { has_container = true; break; } } } AccessMask valid_access = access ? 0x7 : 0x1F; if (has_container) { valid_access |= (access ? 0x20 : 0x60); } SecurityDescriptorViewerControl control = new SecurityDescriptorViewerControl(); DocumentForm frm = new DocumentForm(control); string title = $"{(access ? "Access Security" : "Launch Security")}"; if (!string.IsNullOrWhiteSpace(view_name)) { title = $"{view_name} {title}"; } frm.Text = title; control.SetSecurityDescriptor(sd, typeof(COMAccessRights), new GenericMapping() { GenericExecute = valid_access, GenericRead = valid_access, GenericWrite = valid_access, GenericAll = valid_access }, valid_access); Application.Run(frm); return; } COMRegistry registry = null; if (database_file == null && autoload_config.AutoLoad && File.Exists(autoload_config.DatabasePath)) { try { registry = COMUtilities.LoadRegistry(null, autoload_config.DatabasePath); } catch { MessageBox.Show($"Error loading database {autoload_config.DatabasePath}", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error); } } if (registry == null) { registry = database_file != null?COMUtilities.LoadRegistry(null, database_file) : COMUtilities.LoadRegistry(null, mode); } if (delete_database && database_file != null) { File.Delete(database_file); } if (query_interfaces) { if (!COMUtilities.QueryAllInterfaces(null, registry.Clsids.Values, server_types, concurrent_queries, refresh_interfaces)) { Environment.Exit(1); } } if (save_file != null) { registry.Save(save_file); Environment.Exit(0); } _appContext = new MultiApplicationContext(new MainForm(registry)); if (enable_activation_filter) { COMUtilities.CoRegisterActivationFilter(new ActivationFilter()); } Application.Run(_appContext); autoload_config = new AutoSaveLoadConfiguration(); if (autoload_config.AutoSave) { registry.Save(autoload_config.DatabasePath); } } catch (Exception ex) { if (!(ex is OperationCanceledException)) { ShowError(null, ex); } } } }
/// <summary> /// Get an access token for the authenticated user. /// </summary> /// <returns>The user's access token.</returns> public NtToken GetAccessToken() { SecurityNativeMethods.QuerySecurityContextToken(_context, out SafeKernelObjectHandle token).CheckResult(); return(NtToken.FromHandle(token)); }
internal static ExportedSecurityContext ExportContext(SecHandle context, SecPkgContextExportFlags export_flags, string package, bool client) { if (context is null) { throw new ArgumentNullException(nameof(context)); } SecBuffer buffer = new SecBuffer(SecurityBufferType.Empty); try { SecurityNativeMethods.ExportSecurityContext(context, export_flags, buffer, out SafeKernelObjectHandle token).CheckResult(); return(new ExportedSecurityContext(package, buffer.ToArray(), !token.IsInvalid ? NtToken.FromHandle(token) : null, client)); } finally { if (buffer.pvBuffer != IntPtr.Zero) { SecurityNativeMethods.FreeContextBuffer(buffer.pvBuffer); } } }