访问被拒绝从进程 运行 作为 IIS APPPOOL 帐户在 Windows Server 2019 上调用 OpenProcess

Access Denied Calling OpenProcess From Process Running As IIS APPPOOL Account on Windows Server 2019

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

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

进程ID指的是NTAUTHORITY\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 虽然这是一个出于安全原因我不想永久应用的设置,但它未能解决问题.应用此策略并重新启动计算机后,进程资源管理器中的进程现在显示 SeDebugPrivilege,但它被列为 "Disabled"

最后,我使用以下 XML 配置文件启用了 "Process Access" 日志记录 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 服务器 失败。

运行 作为 系统

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 服务器

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 似乎与记录的访问权限不完全匹配 here

缺少什么权限阻止了此访问? OpenProcess here 的文档似乎没有指定所需的任何特定权限,除非请求 PROCESS_ALL_ACCESS。目标进程不是 "protected" 进程。

是否有配置此帐户以在目标进程上打开进程的选项?

原因是缺少对目标进程的权限。为了测试所需的权限,可以使用 Process Explorer and right clicking target process and selecting Properties then Security tab and selecting Permissions button, you can add the required permission Process Query Information Allow for the user account the process calling OpenProcess is running as. Permission can also be denied due to process mandatory integrity control 查看,即中等完整性进程无法访问高完整性进程。即使用户帐户被添加了正确的权限,但由于强制完整性控制而您无权访问,您将被拒绝访问。

在代码中,这可以通过修改记录的对象的 ACL 来实现 here

这是我写的一个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