Wie kann ich einen schwer zu tötenden Prozess erstellen?

10

Ich möchte ein Programm erstellen, das nach dem Start (mit Root-Rechten) nur schwer zu stoppen ist (selbst für den Administrator). Nach dem Start sollte sich der Prozess beim Start selbst fortsetzen, bis er zum Stoppen aufgefordert wird. Der Stoppvorgang sollte einige Zeit dauern (dh teuer sein).

Ich weiß, dass dies wie eine schädliche Software klingt, aber ich möchte es aus einem echten Grund. Ich möchte Site-Blocker auf meinem Laptop ausführen (auf dem ich der Administrator bin). Und ich möchte es mir schwer machen, sie aufzuhalten.

Die Lösung, an die ich gedacht habe, ist die folgende:

  1. Der Prozess sollte jedes Mal mit einem anderen Namen ausgeführt werden, damit ich den Prozessnamen nicht vorhersagen und beenden kann.

  2. Der Prozess speichert sich beim Herunterfahren in /etc/rc5.d

  3. Der Prozess verschlüsselt seinen Namen mit einer Chiffre an einem bekannten Ort. Der Stoppvorgang muss Bruteforce verwenden, um den Programmnamen wiederherzustellen und zu beenden.

Ich würde gerne eine gute Lösung für diese Aufgabe finden.

Miheer
quelle
2
Sie haben tatsächlich Recht, es klingt wie ein sehr gemeines Programm
Kiwy
kulturelle Websites ... ja, ich verstehe. Ich denke, das Kompilieren des DNS mit einer Liste falscher DNS könnte Ihnen helfen
Kiwy
@ Kiwy Ja, das ist eine Option, aber dann kann ich DNS einfach neu installieren, oder?
Miheer
Sie können immer einen Weg für alles haben. Bitten Sie vielleicht einen Freund, das Root-Passwort Ihres Computers zu behalten, um das zu erfüllen, wonach Sie fragen: D, weil Sie am Ende einen bootfähigen USB-Schlüssel verwenden, wenn Sie kulturelle Inhalte so sehr mögen.
Kiwy
Ja, aber es sollte kein einfacher 2-Minuten-Job sein.
Miheer

Antworten:

8

Ein Ansatz könnte darin bestehen, PID-Namespaces zu verwenden:

Starten Sie Ihr System mit einem init=/some/cmdas-Kernel-Parameter, in dem /some/cmdein Prozess in einem neuen Namespace ( CLONE_NEWPID) gegabelt und ausgeführt /sbin/initwird (PID 1 in diesem neuen Namespace und PID 2 im Root-Namespace). Führen Sie dann im übergeordneten Namespace Ihren " Programm".

Sie möchten wahrscheinlich eine Möglichkeit, Ihr Programm auf die eine oder andere Weise zu steuern (z. B. TCP- oder ABSTRACT Unix-Socket).

Wahrscheinlich möchten Sie Ihr Programm im Speicher speichern und die meisten Verweise auf das Dateisystem schließen, damit es auf nichts angewiesen ist.

Dieser Prozess wird vom Rest des Systems nicht gesehen. Der Rest des Systems läuft praktisch wie in einem Container.

Wenn dieser Prozess abbricht, gerät der Kernel in Panik, was Ihnen eine zusätzliche Garantie gibt.

Ein unangenehmer Nebeneffekt ist jedoch, dass wir die Kernel-Threads in der Ausgabe von nicht sehen ps.

Als Proof of Concept (mit diesem Trick können Sie eine Kopie Ihres Systems in einer virtuellen qemu-Maschine starten):

Erstellen Sie ein /tmp/initLike:

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

(Sie benötigen unshareeine neuere Version von util-linux (2.14)). Oben verwenden wir socatals "Programm", das nur auf TCP-Verbindungen an Port 1234 mit der Ausgabe von antwortet ps -efH.

Starten Sie dann Ihre VM wie folgt:

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'

Dann sehen wir:

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
quelle
Aber kann ich dann nicht einfach die Bootdatei so ändern, dass / some / cmd nicht gestartet wird?
Miheer
1
@Miheer, und Sie könnten von einem USB-Stick booten oder ein anderes Betriebssystem installieren ... Um dies zu vermeiden, müssten Sie den Computer und das BIOS sowie den Bootloader und den Kernel und initrd physisch sperren (und das Programm starten lassen) von diesem initrd) auf einem schreibgeschützten Gerät. Andernfalls können Sie, was auch immer Sie tun, immer die Festplatte abnehmen und das Element entfernen, das Ihren Prozess startet.
Stéphane Chazelas
1

Ich bin mir nicht sicher, ob es die endgültige Lösung ist oder ob es der beste Weg ist, dies zu tun. Meine Meinungen:

  • Ändern Sie, initda dies der erste Prozess ist, wenn er stirbt. Alle anderen sterben ebenfalls. Ihre Maschine kann also nur damit verwendet werden.

  • Erstellen Sie ein Kernelmodul und laden Sie abhängig davon kritische Module (wenn es getötet wird, führt dies zu einer Kettenreaktion wie im initBeispiel).

  • Ändern Sie den Kernel so, dass Kill-Anforderungen für einen bestimmten Prozess ignoriert werden.

Denken Sie daran, dass die letzten beiden im Kernel-Modus ausgeführt werden (der in Bezug auf Bibliotheken und so einen sehr begrenzt ist). Das Ändern initwird im Benutzerbereich ausgeführt, sodass Sie viele Funktionen davon verwenden können.

Tinti
quelle
1
Ich bin mir nicht sicher, ob es wirklich sicher ist.
Tinti
Und wie kann man den Prozess stoppen?
Miheer
Dies müsste in der Software selbst erfolgen. Sie müssten eine Möglichkeit erstellen, um die Software zum Stoppen aufzufordern. Nehmen wir an, es gibt einen Thread, der eine Datei wie die folgende überprüft: /var/lib/stop.request. Wenn diese Datei ein Passwort X enthält, stoppt die Software die von ihr ausgeführte ARBEIT und wechselt in eine Art Schlafmodus. Sie können es wieder aktivieren, indem Sie eine andere Datei /var/lib/start.request erstellen.
Tinti