Отказано в доступе Вызов OpenProcess из процесса, запущенного как учетная запись IIS APPPOOL на сервере Windows 2019 - PullRequest
1 голос
/ 16 июня 2020

Инструмент для сбора информации c диагностики, работающий под учетной записью 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 процесс показывает следующее:

enter image description here

Для эксперимента я попытался предоставить приложению SeDebugPrivilege через SecPol.ms c (компьютер, не присоединенный к домену) Хотя это параметр, который я не хотел применять постоянно по соображениям безопасности, он не помог решить проблему. После применения этой политики и перезагрузки компьютера в Process Explorer процесс теперь показывал SeDebugPrivilege, но он был указан как «Отключено»

enter image description here

Наконец, я включил " «Доступ к процессу» с помощью SysMon с использованием следующего профиля XML:

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

Из этого я наблюдал, пытаясь вызвать OpenProcess из процесса, запущенного под SYSTEM , это был успешным, при работе 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 здесь , похоже, не указывает каких-либо конкретных c необходимых привилегий, за исключением запроса PROCESS_ALL_ACCESS. Целевой процесс не является «защищенным» процессом.

Можно ли настроить эту учетную запись для открытия процесса в целевом процессе?

1 Ответ

0 голосов
/ 18 июня 2020

Причиной этого является отсутствие разрешения для целевого процесса. Для тестирования необходимое разрешение можно просмотреть с помощью Process Explorer , щелкнув правой кнопкой мыши целевой процесс и выбрав Свойства затем Безопасность вкладку и выбрав кнопку Разрешения, вы можете добавить необходимое разрешение Информация о запросе процесса Разрешить для учетной записи пользователя, под которой запущен процесс, вызывающий OpenProcess. В разрешении также может быть отказано из-за процесса обязательного контроля целостности , т. Е. Процесс целостности среднего уровня не может получить доступ к процессу высокой целостности. Даже если в учетную запись пользователя добавлено правильное разрешение, но у вас нет доступа из-за обязательного контроля целостности, вам будет отказано в доступе.

enter image description here

В коде это может быть достигнуто путем изменения списков ACL объекта, как описано здесь

Вот сценарий PowerShell, который я написал для тестирования различных сценариев ios, таких как добавление необходимого разрешения.

$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
...