¿Cómo puedo crear un proceso difícil de matar?

10

Quiero crear un programa que será difícil de detener (incluso para el administrador) una vez que se inicie (con privilegios de root). Una vez iniciado, el proceso debe continuar iniciando en el inicio hasta que se le solicite que se detenga. El proceso de detención debería llevar algún tiempo (es decir, debería ser costoso).

Sé que esto puede sonar como un software malicioso, pero lo quiero por una razón genuina. Quiero ejecutar bloqueadores de sitios en mi computadora portátil (en la que soy administrador). Y quiero que sea difícil para mí detenerlos.

La solución que pensé es la siguiente:

  1. El proceso debe ejecutarse con un nombre diferente cada vez que se ejecuta, para que no pueda predecir el nombre del proceso y eliminarlo.

  2. El proceso se guardará en /etc/rc5.d al cerrar

  3. El proceso cifrará su nombre usando un cifrado en alguna ubicación conocida. El proceso de detención tendrá que usar fuerza bruta para recuperar el nombre del programa y matarlo.

Me gustaría encontrar una buena solución para esta tarea.

Miheer
fuente
2
tienes razón, suena como un programa muy malo
Kiwy
sitios web culturales ... sí, lo entiendo. Creo que compilar el DNS con una lista de DNS incorrectos podría ayudarlo
Kiwy
@ Kiwi Sí, esa es una opción, pero luego puedo reinstalar DNS, ¿verdad?
Miheer
Siempre puedes tener una manera para cada cosa. Tal vez pedirle a un amigo que mantenga la contraseña de root de su computadora es una buena manera de cumplir con lo que está pidiendo: D porque terminará usando una clave usb de arranque, si le gusta tanto el contenido cultural.
Kiwy
Sí, pero no debería ser un simple trabajo de 2 minutos.
Miheer

Respuestas:

8

Un enfoque podría ser usar espacios de nombres PID:

Arranque su sistema con un init=/some/cmdparámetro como kernel, donde /some/cmdbifurca un proceso en un nuevo espacio de nombres ( CLONE_NEWPID) y se ejecuta /sbin/initen él (tendrá PID 1 en ese nuevo espacio de nombres y pid 2 en el espacio de nombres raíz), luego en el padre, ejecute su " programa".

Probablemente desee una forma de controlar su programa de una forma u otra (TCP o ABSTRACT Unix socket, por ejemplo).

Probablemente querrás bloquear tu programa en la memoria y cerrar la mayoría de las referencias al sistema de archivos para que no dependa de nada.

Ese proceso no se verá desde el resto del sistema. El resto del sistema se ejecutará como en un contenedor.

Si ese proceso muere, el núcleo entrará en pánico, lo que le brinda una garantía adicional.

Sin embargo, un efecto secundario inconveniente es que no veremos los hilos del núcleo en la salida de ps.

Como prueba de concepto (usando este truco para iniciar una copia de su sistema en una máquina virtual qemu):

Crea un me /tmp/initgusta:

#! /bin/sh -
echo Starting
/usr/local/bin/unshare -fmp -- sh -c '
  umount /proc
  mount -nt proc p /proc
  exec bash <&2' &
ifconfig lo 127.1/8
exec socat tcp-listen:1234,fork,reuseaddr system:"ps -efH; echo still running"

(necesita unsharede una versión reciente de util-linux (2.14)). Arriba estamos usando socatcomo el "programa" que solo responde en conexiones TCP en el puerto 1234 con la salida de ps -efH.

Luego, inicie su VM como:

kvm -kernel /boot/vmlinuz-$(uname -r) -initrd /boot/initrd.img-$(uname -r) \
    -m 1024 -fsdev local,id=r,path=/,security_model=none \
    -device virtio-9p-pci,fsdev=r,mount_tag=r -nographic -append \
    'root=r rootfstype=9p rootflags=trans=virtio console=ttyS0 init=/tmp/init rw'

Entonces, vemos:

Begin: Running /scripts/init-bottom ... done.
Starting
[...]
root@(none):/# ps -efH
UID        PID  PPID  C STIME TTY          TIME CMD
root         1     0  0 14:24 ?        00:00:00 bash
root         4     1  0 14:24 ?        00:00:00   ps -efH
root@(none):/# telnet localhost 1234
Trying ::1...
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
UID        PID  PPID  C STIME TTY          TIME CMD
root         2     0  0 14:24 ?        00:00:00 [kthreadd]
root         3     2  0 14:24 ?        00:00:00   [ksoftirqd/0]
[...]
root         1     0  2 14:24 ?        00:00:00 socat tcp-listen:1234,fork,reuseaddr system:ps -efH; echo still running
root       204     1  0 14:24 ?        00:00:00   /usr/local/bin/unshare -fmp -- sh -c    umount /proc   mount -nt proc p /proc   exec bash <&2
root       206   204  0 14:24 ?        00:00:00     bash
root       212   206  0 14:25 ?        00:00:00       telnet localhost 1234
root       213     1  0 14:25 ?        00:00:00   socat tcp-listen:1234,fork,reuseaddr system:ps -efH; echo still running
root       214   213  0 14:25 ?        00:00:00     socat tcp-listen:1234,fork,reuseaddr system:ps -efH; echo still running
root       215   214  0 14:25 ?        00:00:00       sh -c ps -efH; echo still running
root       216   215  0 14:25 ?        00:00:00         ps -efH
still running
Connection closed by foreign host.
root@(none):/# QEMU: Terminated
Stéphane Chazelas
fuente
Pero entonces, ¿no puedo cambiar el archivo de arranque para que no se inicie / some / cmd?
Miheer
1
@Miheer, y podría arrancar desde una llave USB, o instalar un sistema operativo diferente ... Para evitar eso, necesitaría bloquear físicamente la máquina y el BIOS y el cargador de arranque y el núcleo e initrd (y comenzar el programa desde ese initrd) en algún dispositivo de solo lectura. De lo contrario, haga lo que haga, siempre podrá quitar el disco duro y eliminar lo que inicia su proceso.
Stéphane Chazelas
1

No estoy seguro si es la solución final o si es la mejor manera de hacerlo. Mis opiniones:

  • Modifique initya que es el primer proceso si muere, todos los demás también mueren. Por lo tanto, su máquina solo podrá utilizarse con ella.

  • Cree un módulo de núcleo y cargue módulos críticos dependiendo de él (si se mata, provocará una reacción en cadena como en el initejemplo).

  • Modifique el núcleo para ignorar las solicitudes de eliminación de un determinado proceso.

Tenga en cuenta que los dos últimos se ejecutarán en modo kernel (que es muy limitado en términos de libs, etc.). La modificación initse ejecutará en el espacio de usuario, lo que le permite utilizar muchas funciones.

Tinti
fuente
1
No estoy seguro si es realmente seguro.
Tinti
¿Y cómo detener el proceso?
Miheer
Esto debería hacerse en el propio software. Tendría que crear una forma de solicitar que el software se detenga. Supongamos que tiene un hilo que verifica un archivo como: /var/lib/stop.request. Si este archivo contiene una contraseña X, el software detiene el TRABAJO que está haciendo y entra en una especie de modo de suspensión. Puede volver a habilitarlo creando otro archivo /var/lib/start.request.
Tinti