Ответ Process Explorer срабатывает один раз, но вы, вероятно, хотите, чтобы он применялся даже после перезагрузки компьютера. Для этого вы можете использовать PowerShell:
Param (
[string[]]$ProcessNames,
[string]$DenyUsername
)
$cscode = @"
using System;
using System.Security;
using System.Security.AccessControl;
using System.Security.Principal;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
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.
}
"@
Add-Type -TypeDefinition $cscode
$ProcessNames | % {
Get-Process -ProcessName $_ | % {
$handle = $_.SafeHandle
$acl = New-Object ProcessSecurity $handle
$ident = New-Object System.Security.Principal.NTAccount $DenyUsername
$ace = New-Object ProcessAccessRule ($ident, 'PROCESS_TERMINATE, PROCESS_SUSPEND_RESUME, WRITE_DAC', $false, 'None', 'None', 'Deny')
$acl.AddAccessRule($ace)
$acl.SaveChanges($handle)
}
}
Это основано на этом ответе переполнения стека. По сути, вы предоставляете ему список процессов, которые нужно защитить, и пользователя, от которого нужно защищаться, и он соответствующим образом изменяет списки ACL процессов. Сохраните его как файл .ps1
(где пользователь может читать, но не может писать), затем поместите пакетный файл, содержащий что-то вроде этого, в автозагрузку пользователя:
powershell \path\to\script.ps1 ('snippingtool', 'mspaint') 'Guest' -executionpolicy bypass
Это защищает snippingtool.exe
и mspaint.exe
( Snipping Tool и Paint) от уничтожения гостем.
Обратите внимание, что это должно выполняться после запуска этих процессов. Возможно, вам придется добавить sleep 10
или около того сна после блока Param
сценария PowerShell. Как только он завершится, попытка уничтожить эти процессы с помощью диспетчера задач приведет к следующему:
Также обратите внимание, что ничего полезного не получится, если учетная запись, с которой вы тестируете учетную запись, является администратором или, точнее, имеет SeDebugPrivilege
.
Нажатие X на их окнах или использование собственной функции закрытия приложений по-прежнему приводит к завершению процессов, поскольку все процессы могут свободно останавливаться. Возможно, вам придется скрыть область уведомлений, как описано в другом ответе. Кроме того, поскольку эти важные процессы выполняются в качестве гостевого пользователя, этот пользователь является владельцем объектов процесса и в любом случае сможет откорректировать ACL-список или использовать возможности PROCESS_VM_WRITE
для записи в памяти процессов и сбоя их. Это можно решить, добавив пустой ACE для OWNER RIGHTS
и изменив 'PROCESS_TERMINATE, PROCESS_SUSPEND_RESUME, WRITE_DAC'
на 'PROCESS_ALL_ACCESS'
соответственно.
Отказ в доступе к диспетчеру задач через объект групповой политики может помешать пользователю использовать диспетчер задач (очевидно) и является наиболее простым решением, но ничто не мешает им запускать собственную программу (или taskkill
), которая не подчиняется групповой политике. Было бы лучше, если бы процессы, которые вы пытаетесь защитить, запускались от имени другого пользователя, а не от того, от которого вы пытаетесь защищаться.
Конечно, если ваш гость готов пойти на все эти неприятности, чтобы обойти эти различные «средства защиты», у вас может быть больше социальной проблемы, чем технической.