Odpowiedź Process Explorer działa raz, ale prawdopodobnie chcesz, aby to się stało nawet po ponownym uruchomieniu komputera. Aby to zrobić, możesz użyć programu 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)
}
}
Opiera się na odpowiedzi na przepełnienie stosu . Zasadniczo udostępniasz mu listę procesów do ochrony i użytkownika, przed którym ma się zabezpieczyć, i odpowiednio poprawia listy ACL procesów. Zapisz go jako .ps1
plik (gdzieś użytkownik może czytać, ale nie pisać), a następnie umieść plik wsadowy zawierający coś takiego w Autostartie użytkownika:
powershell \path\to\script.ps1 ('snippingtool', 'mspaint') 'Guest' -executionpolicy bypass
To chroni snippingtool.exe
i mspaint.exe
(narzędzie wycinania i farbę) przed zabiciem przez gościa.
Pamiętaj, że musi to działać po uruchomieniu tych procesów. Być może trzeba dodać sleep 10
mniej więcej po Param
bloku skryptu PowerShell. Po zakończeniu próba zabicia tych procesów za pomocą Menedżera zadań spowoduje:
Pamiętaj też, że nie przyniesie to żadnego pożytku, jeśli konto, na którym go testujesz, jest administratorem, a ściślej ma SeDebugPrivilege
.
Kliknięcie X w ich oknach lub użycie własnej funkcji zamykania aplikacji nadal spowoduje zamknięcie procesów, ponieważ wszystkie procesy mogą zdecydować o zatrzymaniu działania. Może być konieczne ukrycie obszaru powiadomień, jak opisano w innej odpowiedzi. Ponadto, ponieważ te ważne procesy są uruchamiane jako użytkownik-gość, użytkownik ten jest właścicielem obiektów procesów i będzie mógł zrezygnować z ACL z powrotem, lub może użyć PROCESS_VM_WRITE
umiejętności do wypisania się na pamięci procesów i ich awarii. Można je rozwiązać, dodając odpowiednio pustą pozycję ACE OWNER RIGHTS
i zmieniając 'PROCESS_TERMINATE, PROCESS_SUSPEND_RESUME, WRITE_DAC'
na 'PROCESS_ALL_ACCESS'
.
Odmowa dostępu do Menedżera zadań przez GPO uniemożliwiłaby użytkownikowi korzystanie z Menedżera zadań (oczywiście) i jest najprostszym rozwiązaniem, ale nic nie powstrzymuje ich przed uruchomieniem własnego programu (lub taskkill
), który nie przestrzega zasad grupy. Byłoby najlepiej, gdyby procesy, które próbujesz bronić, działały jako inny użytkownik niż ten, przed którym próbujesz się bronić.
Oczywiście, jeśli gość jest gotów podjąć wszelkie trudy, aby obejść te różne „zabezpieczenia”, możesz mieć więcej problemów społecznych niż technicznych.