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