首页 > 解决方案 > 访问被拒绝从 Windows Server 2019 上作为 IIS APPPOOL 帐户运行的进程调用 OpenProcess

问题描述

在IIS APPPOOL\Content Server帐户下运行的用于收集诊断信息的工具正在尝试进行以下调用:

hProcess = OpenProcess(PROCESS_QUERY_INFORMATION, false, <process id>);

进程 ID是指在NT AUTHORITY\IUSR帐户下运行的进程。hProcess 将返回 NULL,在 WinDbg 中!gle显示:

0:000> !gle
LastErrorValue: (Win32) 0x5 (5) - Access is denied.
LastStatusValue: (NTSTATUS) 0xc0000022 - {Access Denied}  A process has requested access to an object, but has not been granted those access rights.

使用 SysInternals AccessChk显示以下用户权限分配:

  SeCreateTokenPrivilege (Create a token object):
  SeAssignPrimaryTokenPrivilege (Replace a process level token):
    IIS APPPOOL\DefaultAppPool
    IIS APPPOOL\Content Server
    NT AUTHORITY\NETWORK SERVICE
    NT AUTHORITY\LOCAL SERVICE
  SeLockMemoryPrivilege (Lock pages in memory):
  SeIncreaseQuotaPrivilege (Adjust memory quotas for a process):
    IIS APPPOOL\DefaultAppPool
    IIS APPPOOL\Content Server
    BUILTIN\Administrators
    NT AUTHORITY\NETWORK SERVICE
    NT AUTHORITY\LOCAL SERVICE
  SeMachineAccountPrivilege (Add workstations to domain):
  SeTcbPrivilege (Act as part of the operating system):
  SeSecurityPrivilege (Manage auditing and security log):
    BUILTIN\Administrators
  SeTakeOwnershipPrivilege (Take ownership of files or other objects):
    BUILTIN\Administrators
  SeLoadDriverPrivilege (Load and unload device drivers):
    BUILTIN\Administrators
  SeSystemProfilePrivilege (Profile system performance):
    NT SERVICE\WdiServiceHost
    BUILTIN\Administrators
  SeSystemtimePrivilege (Change the system time):
    BUILTIN\Administrators
    NT AUTHORITY\LOCAL SERVICE
  SeProfileSingleProcessPrivilege (Profile single process):
    BUILTIN\Administrators
  SeIncreaseBasePriorityPrivilege (Increase scheduling priority):
    Window Manager\Window Manager Group
    BUILTIN\Administrators
  SeCreatePagefilePrivilege (Create a pagefile):
    BUILTIN\Administrators
  SeCreatePermanentPrivilege (Create permanent shared objects):
  SeBackupPrivilege (Back up files and directories):
    BUILTIN\Backup Operators
    BUILTIN\Administrators
  SeRestorePrivilege (Restore files and directories):
    BUILTIN\Backup Operators
    BUILTIN\Administrators
  SeShutdownPrivilege (Shut down the system):
    BUILTIN\Backup Operators
    BUILTIN\Administrators
  SeDebugPrivilege (Debug programs):
    BUILTIN\Administrators
  SeAuditPrivilege (Generate security audits):
    IIS APPPOOL\DefaultAppPool
    IIS APPPOOL\Content Server
    NT AUTHORITY\NETWORK SERVICE
    NT AUTHORITY\LOCAL SERVICE
  SeSystemEnvironmentPrivilege (Modify firmware environment values):
    BUILTIN\Administrators
  SeChangeNotifyPrivilege (Bypass traverse checking):
    BUILTIN\Backup Operators
    BUILTIN\Users
    BUILTIN\Administrators
    NT AUTHORITY\NETWORK SERVICE
    NT AUTHORITY\LOCAL SERVICE
    Everyone
  SeRemoteShutdownPrivilege (Force shutdown from a remote system):
    BUILTIN\Administrators
  SeUndockPrivilege (Remove computer from docking station):
    BUILTIN\Administrators
  SeSyncAgentPrivilege (Synchronize directory service data):
  SeEnableDelegationPrivilege (Enable computer and user accounts to be trusted for delegation):
  SeManageVolumePrivilege (Perform volume maintenance tasks):
    BUILTIN\Administrators
  SeImpersonatePrivilege (Impersonate a client after authentication):
    NT AUTHORITY\SERVICE
    BUILTIN\IIS_IUSRS
    BUILTIN\Administrators
    NT AUTHORITY\NETWORK SERVICE
    NT AUTHORITY\LOCAL SERVICE
  SeCreateGlobalPrivilege (Create global objects):
    NT AUTHORITY\SERVICE
    BUILTIN\Administrators
    NT AUTHORITY\NETWORK SERVICE
    NT AUTHORITY\LOCAL SERVICE
  SeTrustedCredManAccessPrivilege (Access Credential Manager as a trusted caller):
  SeRelabelPrivilege (Modify an object label):
  SeIncreaseWorkingSetPrivilege (Increase a process working set):
    BUILTIN\Users
  SeTimeZonePrivilege (Change the time zone):
    BUILTIN\Administrators
    NT AUTHORITY\LOCAL SERVICE
  SeCreateSymbolicLinkPrivilege (Create symbolic links):
    BUILTIN\Administrators
  SeDelegateSessionUserImpersonatePrivilege (Obtain an impersonation token for another user in the same session):
    BUILTIN\Administrators
  SeBatchLogonRight:
    BUILTIN\IIS_IUSRS
    BUILTIN\Performance Log Users
    BUILTIN\Backup Operators
    BUILTIN\Administrators
  SeInteractiveLogonRight:
    BUILTIN\Backup Operators
    BUILTIN\Users
    BUILTIN\Administrators
  SeNetworkLogonRight:
    BUILTIN\Backup Operators
    BUILTIN\Users
    BUILTIN\Administrators
    Everyone
  SeServiceLogonRight:
    IIS APPPOOL\DefaultAppPool
    IIS APPPOOL\Content Server
    NT SERVICE\ALL SERVICES
  SeDenyBatchLogonRight:
  SeDenyInteractiveLogonRight:
  SeDenyNetworkLogonRight:
  SeDenyServiceLogonRight:
  SeRemoteInteractiveLogonRight:
    BUILTIN\Remote Desktop Users
    BUILTIN\Administrators
  SeDenyRemoteInteractiveLogonRight:

使用Process Explorer检查该过程显示以下内容:

在此处输入图像描述

对于一个实验,我尝试通过 SecPol.msc(未加入域的计算机)授予应用程序 SeDebugPrivilege 虽然出于安全原因我不想永久应用此设置,但它未能解决问题。应用此策略并重新启动计算机后,在 Process Explorer 中,该进程现在显示 SeDebugPrivilege,但它被列为“已禁用”

在此处输入图像描述

最后,我使用以下 XML 配置文件启用了SysMon的“进程访问”日志记录:

<Sysmon schemaversion="4.22">
<EventFiltering>
    <RuleGroup name="ProcessAccess" groupRelation="or">
        <ProcessAccess onmatch="include">
            <SourceImage condition="contains">TargetProcess.exe</SourceImage>
        </ProcessAccess>
    </RuleGroup>
</EventFiltering>
</Sysmon>

由此我观察到,如果尝试从在SYSTEM下运行的进程调用 OpenProcess是成功的,而作为IIS APPPOOL\Content Server运行失败。

作为系统运行

RuleName: ProcessAccess
UtcTime: 2020-06-16 11:39:35.620
SourceProcessGUID: {4cfe3c55-85e5-5ee8-0000-0010be161600}
SourceProcessId: 5728
SourceThreadId: 5680
SourceImage: c:\TEST\source.exe
TargetProcessGUID: {4cfe3c55-af77-5ee8-0000-0010af547d00}
TargetProcessId: 4004
TargetImage: c:\TEST\target.exe
GrantedAccess: 0x1400

作为IIS APPPOOL\Content Server运行

RuleName: ProcessAccess
UtcTime: 2020-06-16 08:21:41.015
SourceProcessGUID: {4cfe3c55-8100-5ee8-0000-0010a5107500}
SourceProcessId: 3740
SourceThreadId: 1532
SourceImage: c:\TEST\source.exe
TargetProcessGUID: {4cfe3c55-8114-5ee8-0000-0010e1a87500}
TargetProcessId: 3992
TargetImage: c:\TEST\target.exe
GrantedAccess: 0x12367B

虽然 0x1400 是预期的PROCESS_QUERY_INFORMATION + PROCESS_QUERY_LIMITED_INFORMATION,但返回授予访问权限 0x12367B 的结果似乎与此处记录的访问权限不完全匹配

缺乏什么特权会阻止这种访问?此处OpenProcess 的文档似乎没有指定所需的任何特定权限,除非请求 PROCESS_ALL_ACCESS。目标进程不是“受保护”进程。

配置此帐户以在目标进程上打开进程的任何选项?

标签: winapiiispermissionsopenprocess

解决方案


其原因是缺少目标进程的权限。为了测试所需的权限,可以使用Process Explorer查看并右键单击目标进程并选择Properties然后选择Security选项卡并选择Permissions按钮,您可以添加所需的权限Process Query Information Allow为调用 OpenProcess 的进程运行的用户帐户允许。由于进程强制完整性控制,权限也可能被拒绝,即中等完整性进程不能访问高完整性进程。即使为用户帐户添加了正确的权限,但由于强制完整性控制您无权访问,您也会被拒绝访问。

在此处输入图像描述

在代码中,这可以通过修改对象的 ACL 来实现,如此处所述

这是我为测试不同场景而编写的 PowerShell 脚本,例如添加所需的权限。

$code = @'
using System;
using System.Security;
using System.Diagnostics;
using System.Security.AccessControl;
using System.Runtime.InteropServices;
using System.Runtime.ConstrainedExecution;
using System.Security.Principal;
namespace CSharp
{
    public class ProcessSecurity : NativeObjectSecurity
    {
        public ProcessSecurity(SafeHandle processHandle)
            : base(false, ResourceType.KernelObject, processHandle, AccessControlSections.Access)
        {

        }

        public void AddAccessRule(ProcessAccessRule rule)
        {
            base.AddAccessRule(rule);
        }

        // this is not a full impl- it only supports writing DACL changes
        public void SaveChanges(SafeHandle processHandle)
        {
            Persist(processHandle, AccessControlSections.Access);
        }

        public override Type AccessRightType
        {
            get { return typeof(ProcessAccessRights); }
        }

        public override AccessRule AccessRuleFactory(System.Security.Principal.IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
        {
            return new ProcessAccessRule(identityReference, (ProcessAccessRights)accessMask, isInherited, inheritanceFlags, propagationFlags, type);
        }

        public override Type AccessRuleType
        {
            get { return typeof(ProcessAccessRule); }
        }

        public override AuditRule AuditRuleFactory(System.Security.Principal.IdentityReference identityReference, int accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AuditFlags flags)
        {
            throw new NotImplementedException();
        }

        public override Type AuditRuleType
        {
            get { throw new NotImplementedException(); }
        }
    }

    public class ProcessAccessRule : AccessRule
    {
        public ProcessAccessRule(IdentityReference identityReference, ProcessAccessRights accessMask, bool isInherited, InheritanceFlags inheritanceFlags, PropagationFlags propagationFlags, AccessControlType type)
            : base(identityReference, (int)accessMask, isInherited, inheritanceFlags, propagationFlags, type)
        {
        }

        public ProcessAccessRights ProcessAccessRights { get { return (ProcessAccessRights)AccessMask; } }
    }

    [Flags]
    public enum ProcessAccessRights
    {
        STANDARD_RIGHTS_REQUIRED = (0x000F0000),
        DELETE = (0x00010000), // Required to delete the object. 
        READ_CONTROL = (0x00020000), // Required to read information in the security descriptor for the object, not including the information in the SACL. To read or write the SACL, you must request the ACCESS_SYSTEM_SECURITY access right. For more information, see SACL Access Right. 
        WRITE_DAC = (0x00040000), // Required to modify the DACL in the security descriptor for the object. 
        WRITE_OWNER = (0x00080000), // Required to change the owner in the security descriptor for the object. 

        PROCESS_ALL_ACCESS = STANDARD_RIGHTS_REQUIRED | SYNCHRONIZE | 0xFFF, //All possible access rights for a process object.
        PROCESS_CREATE_PROCESS = (0x0080), // Required to create a process. 
        PROCESS_CREATE_THREAD = (0x0002), // Required to create a thread. 
        PROCESS_DUP_HANDLE = (0x0040), // Required to duplicate a handle using DuplicateHandle. 
        PROCESS_QUERY_INFORMATION = (0x0400), // Required to retrieve certain information about a process, such as its token, exit code, and priority class (see OpenProcessToken, GetExitCodeProcess, GetPriorityClass, and IsProcessInJob). 
        PROCESS_QUERY_LIMITED_INFORMATION = (0x1000),
        PROCESS_SET_INFORMATION = (0x0200), // Required to set certain information about a process, such as its priority class (see SetPriorityClass). 
        PROCESS_SET_QUOTA = (0x0100), // Required to set memory limits using SetProcessWorkingSetSize. 
        PROCESS_SUSPEND_RESUME = (0x0800), // Required to suspend or resume a process. 
        PROCESS_TERMINATE = (0x0001), // Required to terminate a process using TerminateProcess. 
        PROCESS_VM_OPERATION = (0x0008), // Required to perform an operation on the address space of a process (see VirtualProtectEx and WriteProcessMemory). 
        PROCESS_VM_READ = (0x0010), // Required to read memory in a process using ReadProcessMemory. 
        PROCESS_VM_WRITE = (0x0020), // Required to write to memory in a process using WriteProcessMemory. 
        SYNCHRONIZE = (0x00100000), // Required to wait for the process to terminate using the wait functions. 
    }

    public static class NativeMethods
    {
        private const Int32 ANYSIZE_ARRAY        = 0x00000001;
        public const int SE_PRIVILEGE_ENABLED    = 0x00000002;

        //Use these for DesiredAccess
        public const UInt32 STANDARD_RIGHTS_REQUIRED = 0x000F0000;
        public const UInt32 STANDARD_RIGHTS_READ = 0x00020000;
        public const UInt32 TOKEN_ASSIGN_PRIMARY = 0x0001;
        public const UInt32 TOKEN_DUPLICATE = 0x0002;
        public const UInt32 TOKEN_IMPERSONATE = 0x0004;
        public const UInt32 TOKEN_QUERY = 0x0008;
        public const UInt32 TOKEN_QUERY_SOURCE = 0x0010;
        public const UInt32 TOKEN_ADJUST_PRIVILEGES = 0x0020;
        public const UInt32 TOKEN_ADJUST_GROUPS = 0x0040;
        public const UInt32 TOKEN_ADJUST_DEFAULT = 0x0080;
        public const UInt32 TOKEN_ADJUST_SESSIONID = 0x0100;
        public const UInt32 TOKEN_READ = (STANDARD_RIGHTS_READ | TOKEN_QUERY);
        public const UInt32 TOKEN_ALL_ACCESS = (STANDARD_RIGHTS_REQUIRED | TOKEN_ASSIGN_PRIMARY |
            TOKEN_DUPLICATE | TOKEN_IMPERSONATE | TOKEN_QUERY | TOKEN_QUERY_SOURCE |
            TOKEN_ADJUST_PRIVILEGES | TOKEN_ADJUST_GROUPS | TOKEN_ADJUST_DEFAULT |
            TOKEN_ADJUST_SESSIONID);

       public enum SecurityEntity
       {
          SE_CREATE_TOKEN_NAME,
          SE_ASSIGNPRIMARYTOKEN_NAME,
          SE_LOCK_MEMORY_NAME,
          SE_INCREASE_QUOTA_NAME,
          SE_UNSOLICITED_INPUT_NAME,
          SE_MACHINE_ACCOUNT_NAME,
          SE_TCB_NAME,
          SE_SECURITY_NAME,
          SE_TAKE_OWNERSHIP_NAME,
          SE_LOAD_DRIVER_NAME,
          SE_SYSTEM_PROFILE_NAME,
          SE_SYSTEMTIME_NAME,
          SE_PROF_SINGLE_PROCESS_NAME,
          SE_INC_BASE_PRIORITY_NAME,
          SE_CREATE_PAGEFILE_NAME,
          SE_CREATE_PERMANENT_NAME,
          SE_BACKUP_NAME,
          SE_RESTORE_NAME,
          SE_SHUTDOWN_NAME,
          SE_DEBUG_NAME,
          SE_AUDIT_NAME,
          SE_SYSTEM_ENVIRONMENT_NAME,
          SE_CHANGE_NOTIFY_NAME,
          SE_REMOTE_SHUTDOWN_NAME,
          SE_UNDOCK_NAME,
          SE_SYNC_AGENT_NAME,
          SE_ENABLE_DELEGATION_NAME,
          SE_MANAGE_VOLUME_NAME,
          SE_IMPERSONATE_NAME,
          SE_CREATE_GLOBAL_NAME,
          SE_CREATE_SYMBOLIC_LINK_NAME,
          SE_INC_WORKING_SET_NAME,
          SE_RELABEL_NAME,
          SE_TIME_ZONE_NAME,
          SE_TRUSTED_CREDMAN_ACCESS_NAME
       }

      public static string GetSecurityEntityValue(SecurityEntity securityEntity)
      {
         switch (securityEntity)
         {
            case SecurityEntity.SE_ASSIGNPRIMARYTOKEN_NAME:
               return "SeAssignPrimaryTokenPrivilege";
            case SecurityEntity.SE_AUDIT_NAME:
               return "SeAuditPrivilege";
            case SecurityEntity.SE_BACKUP_NAME:
               return "SeBackupPrivilege";
            case SecurityEntity.SE_CHANGE_NOTIFY_NAME:
               return "SeChangeNotifyPrivilege";
            case SecurityEntity.SE_CREATE_GLOBAL_NAME:
               return "SeCreateGlobalPrivilege";
            case SecurityEntity.SE_CREATE_PAGEFILE_NAME:
               return "SeCreatePagefilePrivilege";
            case SecurityEntity.SE_CREATE_PERMANENT_NAME:
               return "SeCreatePermanentPrivilege";
            case SecurityEntity.SE_CREATE_SYMBOLIC_LINK_NAME:
               return "SeCreateSymbolicLinkPrivilege";
            case SecurityEntity.SE_CREATE_TOKEN_NAME:
               return "SeCreateTokenPrivilege";
            case SecurityEntity.SE_DEBUG_NAME:
               return "SeDebugPrivilege";
            case SecurityEntity.SE_ENABLE_DELEGATION_NAME:
               return "SeEnableDelegationPrivilege";
            case SecurityEntity.SE_IMPERSONATE_NAME:
               return "SeImpersonatePrivilege";
            case SecurityEntity.SE_INC_BASE_PRIORITY_NAME:
               return "SeIncreaseBasePriorityPrivilege";
            case SecurityEntity.SE_INCREASE_QUOTA_NAME:
               return "SeIncreaseQuotaPrivilege";
            case SecurityEntity.SE_INC_WORKING_SET_NAME:
               return "SeIncreaseWorkingSetPrivilege";
            case SecurityEntity.SE_LOAD_DRIVER_NAME:
               return "SeLoadDriverPrivilege";
            case SecurityEntity.SE_LOCK_MEMORY_NAME:
               return "SeLockMemoryPrivilege";
            case SecurityEntity.SE_MACHINE_ACCOUNT_NAME:
               return "SeMachineAccountPrivilege";
            case SecurityEntity.SE_MANAGE_VOLUME_NAME:
               return "SeManageVolumePrivilege";
            case SecurityEntity.SE_PROF_SINGLE_PROCESS_NAME:
               return "SeProfileSingleProcessPrivilege";
            case SecurityEntity.SE_RELABEL_NAME:
               return "SeRelabelPrivilege";
            case SecurityEntity.SE_REMOTE_SHUTDOWN_NAME:
               return "SeRemoteShutdownPrivilege";
            case SecurityEntity.SE_RESTORE_NAME:
               return "SeRestorePrivilege";
            case SecurityEntity.SE_SECURITY_NAME:
               return "SeSecurityPrivilege";
            case SecurityEntity.SE_SHUTDOWN_NAME:
               return "SeShutdownPrivilege";
            case SecurityEntity.SE_SYNC_AGENT_NAME:
               return "SeSyncAgentPrivilege";
            case SecurityEntity.SE_SYSTEM_ENVIRONMENT_NAME:
               return "SeSystemEnvironmentPrivilege";
            case SecurityEntity.SE_SYSTEM_PROFILE_NAME:
               return "SeSystemProfilePrivilege";
            case SecurityEntity.SE_SYSTEMTIME_NAME:
               return "SeSystemtimePrivilege";
            case SecurityEntity.SE_TAKE_OWNERSHIP_NAME:
               return "SeTakeOwnershipPrivilege";
            case SecurityEntity.SE_TCB_NAME:
               return "SeTcbPrivilege";
            case SecurityEntity.SE_TIME_ZONE_NAME:
               return "SeTimeZonePrivilege";
            case SecurityEntity.SE_TRUSTED_CREDMAN_ACCESS_NAME:
               return "SeTrustedCredManAccessPrivilege";
            case SecurityEntity.SE_UNDOCK_NAME:
               return "SeUndockPrivilege";
            default:
               throw new ArgumentOutOfRangeException(typeof(SecurityEntity).Name);
            }
        }

        [StructLayout(LayoutKind.Sequential)]
        public struct LUID {
           public UInt32 LowPart;
           public Int32 HighPart;
        }

        public struct TOKEN_PRIVILEGES {
           public int PrivilegeCount;
           [MarshalAs(UnmanagedType.ByValArray, SizeConst=ANYSIZE_ARRAY)]
           public LUID_AND_ATTRIBUTES [] Privileges;
        }

        [StructLayout(LayoutKind.Sequential, Pack = 4)]
        public struct LUID_AND_ATTRIBUTES {
           public LUID Luid;
           public UInt32 Attributes;
        }

        [Flags]
        public enum ProcessAccessFlags : uint
        {
            All = 0x001F0FFF,
            Terminate = 0x00000001,
            CreateThread = 0x00000002,
            VirtualMemoryOperation = 0x00000008,
            VirtualMemoryRead = 0x00000010,
            VirtualMemoryWrite = 0x00000020,
            DuplicateHandle = 0x00000040,
            CreateProcess = 0x000000080,
            SetQuota = 0x00000100,
            SetInformation = 0x00000200,
            QueryInformation = 0x00000400,
            QueryLimitedInformation = 0x00001000,
            Synchronize = 0x00100000
        }

        [DllImport("kernel32.dll", SetLastError=true)]
        [ReliabilityContract(Consistency.WillNotCorruptState, Cer.Success)]
        [SuppressUnmanagedCodeSecurity]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool CloseHandle(IntPtr hObject);

        // Use this signature if you want the previous state information returned
        [DllImport("advapi32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
           [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
           ref TOKEN_PRIVILEGES NewState,
           UInt32 BufferLengthInBytes,
           ref TOKEN_PRIVILEGES PreviousState,
           out UInt32 ReturnLengthInBytes);

        // Use this signature if you do not want the previous state
        [DllImport("advapi32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool AdjustTokenPrivileges(IntPtr TokenHandle,
           [MarshalAs(UnmanagedType.Bool)]bool DisableAllPrivileges,
           ref TOKEN_PRIVILEGES NewState,
           UInt32 Zero,
           IntPtr Null1,
           IntPtr Null2);

        [DllImport("advapi32.dll")]
        public static extern bool LookupPrivilegeValue(string lpSystemName, string lpName,
           ref LUID lpLuid);

        [DllImport("advapi32.dll", SetLastError=true)]
        [return: MarshalAs(UnmanagedType.Bool)]
        public static extern bool OpenProcessToken(IntPtr ProcessHandle,
            UInt32 DesiredAccess, out IntPtr TokenHandle);

        [DllImport("kernel32.dll", SetLastError = true)]
        public static extern IntPtr OpenProcess(
            ProcessAccessFlags processAccess,
            bool bInheritHandle,
            int processId
        );

        public static IntPtr OpenProcess(Process proc, ProcessAccessFlags flags)
        {
            return OpenProcess(flags, false, proc.Id);
        }
    }
}
'@

Add-Type -TypeDefinition $code -IgnoreWarnings 

Function Enable-DebugPrivilege
{
    $hToken = New-Object System.IntPtr
    $luidSEDebugNameValue = New-Object CSharp.NativeMethods+LUID
    $tkpPrivileges = New-Object CSharp.NativeMethods+TOKEN_PRIVILEGES

    if (![CSharp.NativeMethods]::OpenProcessToken([System.Diagnostics.Process]::GetCurrentProcess().Handle, [CSharp.NativeMethods]::TOKEN_ADJUST_PRIVILEGES -bor [CSharp.NativeMethods]::TOKEN_QUERY, [ref]$hToken))
    {
        $win32exception = New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())
        "OpenProcessToken Failed ERROR #$($win32exception.NativeErrorCode) HRESULT: 0x{0:X8} Message: $($win32exception.Message) " -f $($win32exception.HResult)
        return
    }
    else
    {
        "OpenProcessToken SUCCESS!"
    }

    if (![CSharp.NativeMethods]::LookupPrivilegeValue($null, [CSharp.NativeMethods]::GetSecurityEntityValue([CSharp.NativeMethods+SecurityEntity]::SE_DEBUG_NAME), [ref]$luidSEDebugNameValue))
    {
      $win32exception = New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())
        "LookupPrivilegeValue Failed ERROR #$($win32exception.NativeErrorCode) HRESULT: 0x{0:X8} Message: $($win32exception.Message) " -f $($win32exception.HResult)
        return
        [CSharp.NativeMethods]::CloseHandle($hToken)
        return
    }
    else
    {
       "LookupPrivilegeValue() SUCCESS!"
    }


    $tkpPrivileges.PrivilegeCount = 1

    $luid = New-Object CSharp.NativeMethods+LUID_AND_ATTRIBUTES
    $luid.Luid = $luidSEDebugNameValue
    $luid.Attributes =  [CSharp.NativeMEthods]::SE_PRIVILEGE_ENABLED
    $tkpPrivileges.Privileges = @($luid)

    if (![CSharp.NativeMethods]::AdjustTokenPrivileges($hToken,$false,[ref]$tkpPrivileges, 0,[IntPtr]::Zero,[IntPtr]::Zero))
    {
      $win32exception = New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())
        "AdjustTokenPriviles Failed ERROR #$($win32exception.NativeErrorCode) HRESULT: 0x{0:X8} Message: $($win32exception.Message) " -f $($win32exception.HResult)
        return
        [CSharp.NativeMethods]::CloseHandle($hToken)
        return

    }
    else
    {
        "SeDebugPrivilege is now available!";
    }

    [CSharp.NativeMethods]::CloseHandle($hToken);


}

Function Open-Process($Process)
{
    $hProcess = [CSharp.NativeMethods]::OpenProcess($Process,[CSharp.NativeMethods+ProcessAccessFlags]::QueryInformation)

    if ($hProcess -eq 0 )
    {
        $win32exception = New-Object System.ComponentModel.Win32Exception([System.Runtime.InteropServices.Marshal]::GetLastWin32Error())
        "ERROR #$($win32exception.NativeErrorCode) HRESULT: 0x{0:X8} Message: $($win32exception.Message) " -f $($win32exception.HResult)
    }
    else
    {
        "Handle to process $hProcess opened ok!"
    }
}


Function Add-ProcessQueryInfoPermission($Process,$IdentityReference)
{
    $procSec = New-Object CSharp.ProcessSecurity($Process.SafeHandle)
    $accessRule = New-Object CSharp.ProcessAccessRule($IdentityReference, [CSharp.ProcessAccessRights]::PROCESS_QUERY_INFORMATION, $true, [System.Security.AccessControl.InheritanceFlags]::None, [System.Security.AccessControl.PropagationFlags]::None, [System.Security.AccessControl.AccessControlType]::Allow)
    $procSec.AddAccessRule($accessRule)
    $procSec.SaveChanges($Process.SafeHandle)
}


# change to hold your target process
$targetProcess = (Get-process | Where-Object { $_.Id -eq 3700  })

Add-Type -AssemblyName System.DirectoryServices.AccountManagement

# change for appropriate account to add
$ctx = New-Object System.DirectoryServices.AccountManagement.PrincipalContext([System.DirectoryServices.AccountManagement.ContextType]::Machine)  
$usr = [ System.DirectoryServices.AccountManagement.UserPrincipal]::FindByIdentity($ctx,[System.DirectoryServices.AccountManagement.IdentityType]::SamAccountName,"test")  

# add process query information (This may need to be run elevated / run from different acct then open-process line depending on target process)
Add-ProcessQueryInfoPermission -Process $targetProcess -IdentityReference $usr.Sid

# test open process
Open-Process -Process  $targetProcess

推荐阅读