Jak mogę stworzyć proces trudny do zabicia

10

Chcę stworzyć program, który będzie trudny do zatrzymania (nawet dla administratora) po uruchomieniu (z uprawnieniami roota). Po uruchomieniu proces powinien zacząć się od samego początku, dopóki nie zostanie poproszony o zatrzymanie. Proces zatrzymywania powinien zająć trochę czasu (tj. Powinien być drogi).

Wiem, że może to brzmieć jak złośliwe oprogramowanie, ale chcę go z prawdziwego powodu. Chcę uruchomić blokowanie witryn na moim laptopie (na którym jestem administratorem). I chcę utrudnić sobie ich powstrzymanie.

Rozwiązanie, o którym myślałem, to:

  1. Proces powinien być uruchamiany z inną nazwą za każdym razem, gdy jest uruchamiany, aby nie mogłem przewidzieć nazwy procesu i zabić go.

  2. Proces zapisze się w /etc/rc5.d przy wyłączaniu

  3. Proces zaszyfruje swoją nazwę za pomocą szyfru w znanej lokalizacji. Proces zatrzymania będzie musiał użyć bruteforce do odzyskania nazwy programu i zabicia go.

Chciałbym znaleźć dobre rozwiązanie dla tego zadania.

Miheer
źródło
2
masz rację, to brzmi jak bardzo podły program
Kiwy,
kulturalne strony internetowe ... tak, rozumiem. Myślę, że kompilacja DNS z listą niepoprawnych dns mogłaby ci pomóc
Kiwy
@ Kiwi Tak, to jest opcja, ale potem mogę ponownie zainstalować DNS, prawda?
Miheer,
Zawsze możesz mieć sposób na wszystko. Może poproś znajomego, aby zachował hasło root twojego komputera, to dobry sposób na spełnienie tego, o co prosisz: D, ponieważ skończysz na rozruchowym kluczu usb, jeśli tak bardzo lubisz treści kulturalne.
Kiwy,
Tak, ale nie powinno to być proste 2-minutowe zadanie.
Miheer,

Odpowiedzi:

8

Jednym z podejść może być użycie przestrzeni nazw PID:

Uruchom system z init=/some/cmdparametrem jądra jako, w którym /some/cmdforksuje proces w nowej przestrzeni nazw ( CLONE_NEWPID) i uruchamia się /sbin/initw nim (będzie miał PID 1 w tej nowej przestrzeni nazw i pid 2 w głównej przestrzeni nazw), a następnie w rodzicu, wykonaj polecenie „ program".

Prawdopodobnie będziesz chciał mieć sposób kontrolowania swojego programu w taki czy inny sposób (na przykład gniazdo TCP lub ABSTRACT Unix).

Prawdopodobnie będziesz chciał zablokować swój program w pamięci i zamknąć większość odniesień do systemu plików, aby na niczym nie polegał.

Ten proces nie będzie widoczny z reszty systemu. Reszta systemu będzie działać tak jak w kontenerze.

Jeśli ten proces umrze, jądro wpadnie w panikę, co daje dodatkową gwarancję.

Niewygodnym efektem ubocznym jest jednak to, że nie zobaczymy wątków jądra na wyjściu ps.

Jako dowód koncepcji (używając tej sztuczki, aby uruchomić kopię systemu na maszynie wirtualnej qemu):

Utwórz /tmp/initpodobny:

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

(potrzebujesz unsharez najnowszej wersji util-linux (2.14)). Powyżej używamy socatjako „program”, który po prostu odpowiada na połączeniach TCP na porcie 1234 z wyjściem ps -efH.

Następnie uruchom maszynę wirtualną jako:

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'

Następnie widzimy:

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
źródło
Ale czy nie mogę po prostu zmienić pliku rozruchowego, aby się nie uruchamiał / some / cmd?
Miheer,
1
@ Miheer, możesz uruchomić komputer z klucza USB lub zainstalować inny system operacyjny ... Aby tego uniknąć, musisz fizycznie zablokować maszynę i system BIOS oraz moduł ładujący i jądro oraz initrd (i uruchomić program z tej initrd) na niektórych urządzeniach tylko do odczytu. W przeciwnym razie, cokolwiek zrobisz, zawsze będziesz mógł zdjąć dysk twardy i usunąć rzecz, która rozpoczyna proces.
Stéphane Chazelas,
1

Nie jestem pewien, czy jest to ostateczne rozwiązanie, czy też jest to najlepszy sposób. Moje opinie:

  • Zmodyfikuj, initponieważ jest to pierwszy proces, jeśli umiera, wszyscy inni też umierają. Dzięki temu Twoja maszyna będzie nadawać się tylko do użytku.

  • Utwórz moduł jądra i załaduj moduły krytyczne w zależności od niego (jeśli zostanie zabity, spowoduje reakcję łańcuchową jak w initprzykładzie).

  • Zmodyfikuj jądro, aby ignorować żądania zabicia dla określonego procesu.

Pamiętaj, że dwa ostatnie będą działały w trybie jądra (który jest bardzo ograniczony pod względem bibliotek i tak dalej). Modyfikacja initbędzie działać w przestrzeni użytkownika, umożliwiając korzystanie z wielu jej funkcji.

Tinti
źródło
1
Nie jestem pewien, czy to naprawdę bezpieczne.
Tinti,
I jak zatrzymać proces?
Miheer,
Trzeba to zrobić w samym oprogramowaniu. Będziesz musiał stworzyć sposób, aby zażądać zatrzymania oprogramowania. Załóżmy, że ma wątek, który sprawdza plik taki jak: /var/lib/stop.request. Jeśli plik zawiera hasło X, oprogramowanie zatrzymuje wykonywaną PRACĘ i przechodzi w rodzaj trybu uśpienia. Możesz go ponownie włączyć, tworząc inny plik /var/lib/start.request.
Tinti,