Comment puis-je créer un processus difficile à tuer

10

Je veux créer un programme qui sera difficile à arrêter (même pour l'administrateur) une fois qu'il sera démarré (avec les privilèges root). Une fois démarré, le processus devrait continuer à démarrer au démarrage jusqu'à ce qu'il vous soit demandé de l'arrêter. Le processus d'arrêt devrait prendre un certain temps (c'est-à-dire qu'il devrait être coûteux).

Je sais que cela peut ressembler à un logiciel malveillant, mais je le veux pour une vraie raison. Je veux exécuter des bloqueurs de site sur mon ordinateur portable (dont je suis l'administrateur). Et je veux qu'il soit difficile pour moi de les arrêter.

La solution à laquelle j'ai pensé est la suivante-

  1. Le processus doit s'exécuter avec un nom différent chaque fois qu'il est exécuté, de sorte que je ne peux pas prédire le nom du processus et le tuer.

  2. Le processus se sauvera dans /etc/rc5.d à l'arrêt

  3. Le processus chiffrera son nom à l'aide d'un chiffre dans un emplacement connu. Le processus d'arrêt devra utiliser bruteforce pour récupérer le nom du programme et le tuer.

Je voudrais trouver une bonne solution pour cette tâche.

Miheer
la source
2
vous avez en fait raison, cela ressemble à un programme très méchant
Kiwy
sites web culturels ... oui je comprends. Je pense que la compilation du DNS avec une liste de DNS incorrects pourrait vous aider
Kiwy
@Kiwy Oui, c'est une option, mais je peux simplement réinstaller DNS à droite?
Miheer
Vous pouvez toujours avoir un moyen pour tout. Peut-être que demander à un ami de conserver le mot de passe root de votre ordinateur est un bon moyen de se conformer à ce que vous demandez: D parce que vous finirez par utiliser une clé USB amorçable, si vous aimez tant le contenu culturel.
Kiwy
Oui, mais cela ne devrait pas être un simple travail de 2 minutes.
Miheer

Réponses:

8

Une approche pourrait être d'utiliser des espaces de noms PID:

Démarrez votre système avec un init=/some/cmdparamètre en tant que noyau, où /some/cmdbifurque un processus dans un nouvel espace de noms ( CLONE_NEWPID) et y s'exécute /sbin/init(il aura PID 1 dans ce nouvel espace de noms et pid 2 dans l'espace de noms racine), puis dans le parent, exécutez votre " programme".

Vous voudrez probablement un moyen de contrôler votre programme d'une manière ou d'une autre (socket TCP ou ABSTRACT Unix par exemple).

Vous voudrez probablement verrouiller votre programme en mémoire et fermer la plupart des références au système de fichiers afin qu'il ne repose sur rien.

Ce processus ne sera pas vu du reste du système. Le reste du système fonctionnera en effet comme dans un conteneur.

Si ce processus meurt, le noyau panique, ce qui vous donne une garantie supplémentaire.

Cependant, un effet secondaire gênant est que nous ne verrons pas les threads du noyau dans la sortie de ps.

Comme preuve de concept (en utilisant cette astuce pour démarrer une copie de votre système dans une machine virtuelle qemu):

Créez un /tmp/initcomme:

#! /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"

(vous avez besoin unshared'une version récente d'util-linux (2.14)). Ci-dessus, nous utilisons socatcomme le "programme" qui répond simplement sur les connexions TCP sur le port 1234 avec la sortie de ps -efH.

Ensuite, démarrez votre machine virtuelle en tant que:

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'

Ensuite, nous voyons:

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
la source
Mais ne puis-je pas simplement changer le fichier de démarrage pour ne pas démarrer / certains / cmd?
Miheer
1
@Miheer, et vous pouvez démarrer à partir d'une clé USB, ou installer un système d'exploitation différent ... Pour éviter cela, vous devez verrouiller physiquement la machine et le BIOS et le chargeur de démarrage et le noyau et initrd (et faire démarrer le programme à partir de ce initrd) sur un périphérique en lecture seule. Sinon, quoi que vous fassiez, vous pourrez toujours retirer le disque dur et retirer la chose qui démarre votre processus.
Stéphane Chazelas
1

Je ne sais pas si c'est la solution finale ou si c'est la meilleure façon de le faire. Mes opinions:

  • Modifier initcar c'est le premier processus s'il meurt tous les autres meurent aussi. Votre machine ne sera donc utilisable qu'avec elle.

  • Créez un module du noyau et chargez les modules critiques en fonction de lui (s'il est tué, cela provoquera une réaction en chaîne comme dans l' initexemple).

  • Modifiez le noyau pour ignorer les demandes de suppression pour un certain processus.

Gardez à l'esprit que les deux derniers s'exécuteront en mode noyau (ce qui est très limité en termes de bibliothèques et ainsi de suite). La modification inits'exécutera dans l'espace utilisateur vous permettant d'utiliser de nombreuses fonctionnalités de celui-ci.

Tinti
la source
1
Je ne sais pas si c'est vraiment sûr.
Tinti
Et comment arrêter le processus?
Miheer
Cela devrait être fait dans le logiciel lui-même. Vous devez créer un moyen de demander l'arrêt du logiciel. Supposons qu'il ait un thread qui vérifie un fichier comme: /var/lib/stop.request. Si ce fichier contient un mot de passe X, le logiciel arrête le TRAVAIL en cours et entre dans une sorte de mode veille. Vous pouvez le réactiver en créant un autre fichier /var/lib/start.request.
Tinti