// // Copyright © Nick Lowe 2009 // // Nick Lowe // nick@int-r.net // http://processprivileges.codeplex.com/ namespace ProcessPrivileges { using System.Diagnostics; using System.Runtime.CompilerServices; using System.Security.Permissions; /// Provides extension methods to the class, implementing the functionality necessary to query, enable, disable or remove privileges on a process. /// /// /// using System; /// using System.Diagnostics; /// using System.Linq; /// using ProcessPrivileges; /// /// internal static class ProcessPrivilegesExample /// { /// public static void Main() /// { /// // Get the current process. /// Process process = Process.GetCurrentProcess(); /// /// // Get the privileges and associated attributes. /// PrivilegeAndAttributesCollection privileges = process.GetPrivileges(); /// /// int maxPrivilegeLength = privileges.Max(privilege => privilege.Privilege.ToString().Length); /// /// foreach (PrivilegeAndAttributes privilegeAndAttributes in privileges) /// { /// // The privilege. /// Privilege privilege = privilegeAndAttributes.Privilege; /// /// // The privilege state. /// PrivilegeState privilegeState = privilegeAndAttributes.PrivilegeState; /// /// // Write out the privilege and its state. /// Console.WriteLine( /// "{0}{1} => {2}", /// privilege, /// GetPadding(privilege.ToString().Length, maxPrivilegeLength), /// privilegeState); /// } /// /// Console.WriteLine(); /// /// // Privileges can only be enabled on a process if they are disabled. /// if (process.GetPrivilegeState(Privilege.TakeOwnership) == PrivilegeState.Disabled) /// { /// // Enable the TakeOwnership privilege on it. /// AdjustPrivilegeResult result = process.EnablePrivilege(Privilege.TakeOwnership); /// /// // Get the state of the TakeOwnership privilege. /// PrivilegeState takeOwnershipState = process.GetPrivilegeState(Privilege.TakeOwnership); /// /// // Write out the TakeOwnership privilege, its state and the result. /// Console.WriteLine( /// "{0}{1} => {2} ({3})", /// Privilege.TakeOwnership, /// GetPadding(Privilege.TakeOwnership.ToString().Length, maxPrivilegeLength), /// takeOwnershipState, /// result); /// } /// } /// /// private static string GetPadding(int length, int maxLength) /// { /// int paddingLength = maxLength - length; /// char[] padding = new char[paddingLength]; /// for (int i = 0; i < paddingLength; i++) /// { /// padding[i] = ' '; /// } /// /// return new string(padding); /// } /// } /// /// /// using System; /// using System.Diagnostics; /// using ProcessPrivileges; /// /// internal static class ReusingAccessTokenHandleExample /// { /// public static void Main() /// { /// // Access token handle reused within the using block. /// using (AccessTokenHandle accessTokenHandle = /// Process.GetCurrentProcess().GetAccessTokenHandle( /// TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query)) /// { /// // Enable privileges using the same access token handle. /// AdjustPrivilegeResult backupResult = accessTokenHandle.EnablePrivilege(Privilege.Backup); /// AdjustPrivilegeResult restoreResult = accessTokenHandle.EnablePrivilege(Privilege.Restore); /// /// Console.WriteLine( /// "{0} => {1} ({2})", /// Privilege.Backup, /// accessTokenHandle.GetPrivilegeState(Privilege.Backup), /// backupResult); /// /// Console.WriteLine( /// "{0} => {1} ({2})", /// Privilege.Restore, /// accessTokenHandle.GetPrivilegeState(Privilege.Restore), /// restoreResult); /// } /// } /// } /// /// /// /// For more information on privileges, see: /// Privileges /// Privilege Constants /// public static class ProcessExtensions { /// Disables the specified on a . /// The for a on which the operation should be performed. /// The to be disabled. /// /// Result from the privilege adjustment. /// If the is already disabled, is returned. /// /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// The caller must have permission to query and adjust token privileges on the target process. [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AdjustPrivilegeResult DisablePrivilege(this AccessTokenHandle accessTokenHandle, Privilege privilege) { return Privileges.DisablePrivilege(accessTokenHandle, privilege); } /// Disables the specified on a . /// The on which the operation should be performed. /// The to be disabled. /// /// Result from the privilege adjustment. /// If the is already disabled, is returned. /// /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// If you are adjusting multiple privileges on a process, consider using with an access token handle for the process. /// The caller must have permission to query and adjust token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AdjustPrivilegeResult DisablePrivilege(this Process process, Privilege privilege) { using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle( new ProcessHandle(process.Handle, false), TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query)) { return DisablePrivilege(accessTokenHandle, privilege); } } /// Enables the specified on a . /// The for a on which the operation should be performed. /// The to be enabled. /// /// Result from the privilege adjustment. /// If the is already enabled, is returned. /// /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Enabling a privilege allows a process to perform system-level actions that it could not previously. /// Before enabling a privilege, many potentially dangerous, thoroughly verify that functions or operations in your code actually require them. /// It is not normally appropriate to hold privileges for the lifetime of a process. Use sparingly; enable when needed, disable when not. /// Consider using that enables privileges on a process in a safe way, ensuring that they are returned to their original state when an operation that requires a privilege completes. /// The caller must have permission to query and adjust token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AdjustPrivilegeResult EnablePrivilege(this AccessTokenHandle accessTokenHandle, Privilege privilege) { return Privileges.EnablePrivilege(accessTokenHandle, privilege); } /// Enables the specified on a . /// The on which the operation should be performed. /// The to be enabled. /// /// Result from the privilege adjustment. /// If the is already enabled, is returned. /// If a is removed from a process, it cannot be enabled. /// /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Enabling a privilege allows a process to perform system-level actions that it could not previously. /// Before enabling a privilege, many potentially dangerous, thoroughly verify that functions or operations in your code actually require them. /// It is not normally appropriate to hold privileges for the lifetime of a process. Use sparingly; enable when needed, disable when not. /// Consider using that enables privileges on a process in a safe way, ensuring that they are returned to their original state when an operation that requires a privilege completes. /// If you are adjusting multiple privileges on a process, consider using with an access token handle for the process. /// The caller must have permission to query and adjust token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AdjustPrivilegeResult EnablePrivilege(this Process process, Privilege privilege) { using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle( new ProcessHandle(process.Handle, false), TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query)) { return EnablePrivilege(accessTokenHandle, privilege); } } /// Gets an access token handle for a . /// The on which an access token handle should be retrieved. /// An access token handle for a with access rights. /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// The caller must have permission to acquire an access token handle with all access rights. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AccessTokenHandle GetAccessTokenHandle(this Process process) { return GetAccessTokenHandle(process, TokenAccessRights.AllAccess); } /// Gets an access token handle for a . /// The on which an access token handle should be retrieved. /// The desired access rights for the access token handle. /// An access token handle for a . /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// The caller must have permission to acquire an access token handle with the desired access rights. /// To query permissions, the access token handle must have permission to query and adjust token privileges: /// TokenAccessRights.Query /// To enable, disable or remove a permission, the access token handle must have permission to query and adjust token privileges: /// TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AccessTokenHandle GetAccessTokenHandle(this Process process, TokenAccessRights tokenAccessRights) { return new AccessTokenHandle(new ProcessHandle(process.Handle, false), tokenAccessRights); } /// Gets the attributes for a on a . /// The for a on which the operation should be performed. /// The on which the attributes should be retrieved. /// The for a on a . /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Consider using as it avoids the need to work with a flags based enumerated type. /// The caller must have permission to query token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static PrivilegeAttributes GetPrivilegeAttributes(this AccessTokenHandle accessTokenHandle, Privilege privilege) { return Privileges.GetPrivilegeAttributes(privilege, GetPrivileges(accessTokenHandle)); } /// Gets the attributes for a on a . /// The on which the operation should be performed. /// The on which the attributes should be retrieved. /// The for a on a . /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Consider using as it avoids the need to work with a flags based enumerated type. /// The caller must have permission to query token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static PrivilegeAttributes GetPrivilegeAttributes(this Process process, Privilege privilege) { return Privileges.GetPrivilegeAttributes(privilege, GetPrivileges(process)); } /// Gets the privileges and associated attributes from a . /// The for a on which the operation should be performed. /// The privileges associated with a process. /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Consider using on attributes within the collection as it avoids the need to work with a flags based enumerated type. /// The caller must have permission to query token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static PrivilegeAndAttributesCollection GetPrivileges(this AccessTokenHandle accessTokenHandle) { return Privileges.GetPrivileges(accessTokenHandle); } /// Gets the privileges and associated attributes from a . /// The on which the operation should be performed. /// The privileges associated with a process. /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Consider using method on attributes within the collection as it avoids the need to work with a flags based enumerated type. /// The caller must have permission to query token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static PrivilegeAndAttributesCollection GetPrivileges(this Process process) { using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle( new ProcessHandle(process.Handle, false), TokenAccessRights.Query)) { return Privileges.GetPrivileges(accessTokenHandle); } } /// Gets the state of a . /// The for a on which the operation should be performed. /// The that should be checked. /// The of the . /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Derives to establish the of a . /// The caller must have permission to query token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static PrivilegeState GetPrivilegeState(this AccessTokenHandle accessTokenHandle, Privilege privilege) { return GetPrivilegeState(GetPrivilegeAttributes(accessTokenHandle, privilege)); } /// Gets the state of a . /// The on which the operation should be performed. /// The that should be checked. /// The of the . /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// Derives to establish the of a . /// The caller must have permission to query token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static PrivilegeState GetPrivilegeState(this Process process, Privilege privilege) { return GetPrivilegeState(GetPrivilegeAttributes(process, privilege)); } /// Gets the state of a . /// The privilege attributes. /// The of the . /// Thrown when an underlying Win32 function call does not succeed. /// Derives to establish the of a . [MethodImpl(MethodImplOptions.Synchronized)] public static PrivilegeState GetPrivilegeState(PrivilegeAttributes privilegeAttributes) { if ((privilegeAttributes & PrivilegeAttributes.Enabled) == PrivilegeAttributes.Enabled) { return PrivilegeState.Enabled; } if ((privilegeAttributes & PrivilegeAttributes.Removed) == PrivilegeAttributes.Removed) { return PrivilegeState.Removed; } return PrivilegeState.Disabled; } /// Removes the specified from a . /// The for a on which the operation should be performed. /// The to be removed. /// /// Result from the privilege adjustment. /// Once a privilege has been removed from a process, it cannot be restored afterwards. /// /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// The caller must have permission to query and adjust token privileges on the target process. [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AdjustPrivilegeResult RemovePrivilege(this AccessTokenHandle accessTokenHandle, Privilege privilege) { return Privileges.RemovePrivilege(accessTokenHandle, privilege); } /// Removes the specified from a . /// The on which the operation should be performed. /// The to be removed. /// /// Result from the privilege adjustment. /// Once a privilege has been removed from a process, it cannot be restored afterwards. /// /// Thrown when an underlying Win32 function call does not succeed. /// Requires the immediate caller to have FullTrust. /// /// If you are adjusting multiple privileges on a process, consider using with an access token handle for the process. /// The caller must have permission to query and adjust token privileges on the target process. /// [MethodImpl(MethodImplOptions.Synchronized), PermissionSetAttribute(SecurityAction.LinkDemand, Name = "FullTrust")] public static AdjustPrivilegeResult RemovePrivilege(this Process process, Privilege privilege) { using (AccessTokenHandle accessTokenHandle = new AccessTokenHandle( new ProcessHandle(process.Handle, false), TokenAccessRights.AdjustPrivileges | TokenAccessRights.Query)) { return RemovePrivilege(accessTokenHandle, privilege); } } } }