//
// 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);
}
}
}
}