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

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

Je sais que cela peut sembler un logiciel malveillant, mais je le veux pour une vraie raison. Je veux exécuter des bloqueurs de site sur mon ordinateur portable (sur lequel 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 process devrait fonctionner avec un nom différent chaque fois qu'il est exécuté, de sorte que je ne peux pas prédire le nom du process et le tuer.

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

  3. Le process cryptera son nom en utilisant un chiffrement dans un location connu. Le process d'arrêt devra utiliser bruteforce pour récupérer le nom du programme et le tuer.

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

Une approche pourrait être d'utiliser les namespaces PID:

/some/cmd forks un process dans un nouvel espace de noms ( CLONE_NEWPID ) et exécute /sbin/init dedans (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 aurez probablement besoin d'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 mélanger votre programme en memory et fermer la plupart des references au système de files afin qu'il ne repose sur rien.

Ce process ne sera pas vu du rest du système. Le rest du système fonctionnera comme dans un conteneur.

Si ce process meurt, le kernel va paniquer ce qui vous donne une garantie supplémentaire.

Un effet secondaire gênant est cependant que nous ne verrons pas les threads du kernel dans la sortie de ps .

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

Créez un /tmp/init comme:

 #! /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-listn:1234,fork,reuseaddr system:"ps -efH; echo still running" 

(vous devez vous unshare d'une version récente d'util-linux (2.14)). Au-dessus, nous utilisons socat comme "programme" qui répond simplement sur les connections 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-listn: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-listn:1234,fork,reuseaddr system:ps -efH; echo still running root 214 213 0 14:25 ? 00:00:00 socat tcp-listn: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 

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

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

  • Créez un module kernel et chargez les modules critiques en fonction de celui-ci (s'il est tué, cela provoquera une réaction en string comme l'exemple init ).

  • Modifiez le kernel pour ignorer les requests de kill pour un certain process.

Gardez à l'esprit que les deux derniers s'exécuteront en mode kernel (ce qui est très limité en termes de libs et donc un). La modification d' init s'exécute dans l'espace user, ce qui vous permet d'utiliser de nombreuses fonctionnalités.