Un enfoque, si pudiera acceder al ID del proceso en un contexto administrativo, es denegar el permiso PROCESS_TERMINATE en el proceso a los usuarios finales. La finalización del proceso (a través del administrador de tareas u otros contextos) se otorga por defecto al propietario, pero se puede denegar explícitamente. Cuando se deniega, la finalización del proceso requeriría que el propietario cambie manualmente la ACL y luego finalice el proceso. Si el usuario no es ni el administrador ni el propietario del proceso, no podrá finalizar el proceso por la fuerza (por ejemplo, a través del Administrador de tareas), aunque se permitirá que el proceso se cierre normalmente.
El siguiente código pone una ACE denegación explícita en el proceso con el PID processid
para los miembros del grupo Todos.
#include "Aclapi.h"
#include "Sddl.h"
DWORD RestrictTerminateOnProcessId(DWORD processid)
{
PACL dacl = NULL, newdacl = NULL;
HANDLE ph = NULL;
PSECURITY_DESCRIPTOR* desc = NULL;
PSID everyonesid = NULL;
ph = OpenProcess(WRITE_DAC | READ_CONTROL, false, processid);
if (!ph) goto cleanup;
if (ERROR_SUCCESS != GetSecurityInfo(ph,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
&dacl,
NULL,
desc)) goto cleanup;
SID_IDENTIFIER_AUTHORITY WorldAuth = SECURITY_WORLD_SID_AUTHORITY;
if (!AllocateAndInitializeSid(
&WorldAuth,1,SECURITY_WORLD_RID,
0,0,0,0,0,0,0,&everyonesid)) goto cleanup;
// begin copy dacl
_ACL_SIZE_INFORMATION si;
GetAclInformation(dacl,
&si,
sizeof(si),
AclSizeInformation);
DWORD dwNewAclSize = si.AclBytesInUse +
(2*sizeof(ACCESS_DENIED_ACE)) + (2*GetLengthSid(everyonesid)) -
(2*sizeof(DWORD));
newdacl = (PACL)HeapAlloc(
GetProcessHeap(),
HEAP_ZERO_MEMORY,
dwNewAclSize);
if (newdacl == NULL) goto cleanup;
if (!InitializeAcl(newdacl, dwNewAclSize, ACL_REVISION_DS))
goto cleanup;
if (!AddAccessDeniedAce(newdacl,
ACL_REVISION_DS,
PROCESS_TERMINATE,
everyonesid)) goto cleanup;
for (int i = 0; i < si.AceCount; i++)
{
LPVOID pace = NULL;
if (!GetAce(dacl, i, &pace)) goto cleanup;
if (!AddAce(newdacl, ACL_REVISION_DS,
MAXDWORD, pace, ((PACE_HEADER)pace)->AceSize))
goto cleanup;
}
// end copy dacl
if (!SetSecurityInfo(ph,
SE_KERNEL_OBJECT,
DACL_SECURITY_INFORMATION,
NULL,
NULL,
newdacl,
NULL)) goto cleanup;
SetLastError(0);
cleanup:
DWORD ret = GetLastError();
if (desc) LocalFree(desc);
if (newdacl) HeapFree(GetProcessHeap(), 0, (LPVOID)newdacl);
if (ph) CloseHandle(ph);
if (everyonesid) FreeSid(everyonesid);
return !ret;
}
Como alternativa siempre se puede desactivar el Administrador de tareas –
@Wiiliam No estoy seguro, algunos programas no pueden cerrarse a través de administrador de tareas, tales como la seguridad e incluso algunos virus –
@ Mr.DDD Estos generalmente solo ocultan el proceso del administrador de tareas al interceptar las funciones de bajo nivel del sistema operativo que devuelven listas de procesos; aún es posible matarlos. – mdm