Как я могу создать процесс, который трудно убить

10

Я хочу создать программу, которую будет трудно остановить (даже администратору) после запуска (с правами суперпользователя). После запуска процесс должен продолжать запускаться при запуске до тех пор, пока его не попросят остановить. Процесс остановки должен занять некоторое время (т.е. должно быть дорого).

Я знаю, что это может звучать как вредоносное программное обеспечение, но я хочу по подлинной причине. Я хочу запускать блокировщики сайта на своем ноутбуке (на котором я являюсь администратором). И я хочу, чтобы мне было трудно их остановить.

Решение, о котором я подумал, заключается в следующем:

  1. Процесс должен запускаться с другим именем при каждом запуске, так что я не могу предсказать имя процесса и уничтожить его.

  2. Процесс сохранит себя в /etc/rc5.d при завершении работы

  3. Процесс зашифрует свое имя, используя шифр в известном месте. Процесс остановки должен будет использовать bruteforce, чтобы восстановить имя программы и убить его.

Я хотел бы найти хорошее решение для этой задачи.

Miheer
источник
2
вы на самом деле правы, это звучит как очень скупая программа
Kiwy
культурные сайты ... да, я понимаю. Я думаю, что составление DNS со списком неправильных DNS может помочь вам
Kiwy
@Kiwy Да, это вариант, но тогда я могу просто переустановить DNS правильно?
Михее
Вы всегда можете найти способ для каждой вещи. Может быть, попросить друга сохранить пароль root вашего компьютера - это хороший способ выполнить то, что вы просите: D, потому что в конечном итоге вы будете использовать загрузочный USB-ключ, если вам так нравится культурный контент.
Kiwy
Да, но это не должно быть простой 2-минутной работой.
Михее

Ответы:

8

Одним из подходов может быть использование пространств имен PID:

Загрузите вашу систему с init=/some/cmdпараметром ядра as, где /some/cmdразветвляется процесс в новом пространстве имен ( CLONE_NEWPID) и запускается /sbin/initв нем (у него будет PID 1 в этом новом пространстве имен и pid 2 в корневом пространстве имен), а затем в родительском файле выполните ваше " программа».

Возможно, вам понадобится способ так или иначе управлять вашей программой (например, сокет TCP или ABSTRACT Unix).

Возможно, вы захотите заблокировать вашу программу в памяти и закрыть большинство ссылок на файловую систему, чтобы она ни на что не опиралась.

Этот процесс не будет видно из остальной системы. Остальная часть системы будет работать, как в контейнере.

Если этот процесс умирает, ядро ​​будет паниковать, что дает вам дополнительную гарантию.

Однако неудобным побочным эффектом является то, что мы не увидим потоков ядра в выводе ps.

В качестве подтверждения концепции (используя этот трюк для загрузки копии вашей системы на виртуальной машине qemu):

Создать /tmp/initлайк:

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

(вам нужна unshareпоследняя версия util-linux (2.14)). Выше мы используем socatв качестве «программы», которая просто отвечает на TCP-соединения через порт 1234 с выводом ps -efH.

Затем загрузите вашу виртуальную машину как:

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'

Затем мы видим:

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
Стефан Шазелас
источник
Но тогда я не могу просто изменить загрузочный файл, чтобы он не запускался / some / cmd?
Михеер
1
@Miheer, и вы можете загрузиться с USB-ключа или установить другую операционную систему ... Чтобы избежать этого, вам нужно физически заблокировать машину и BIOS, а также загрузчик, ядро ​​и initrd (и запустить программу от этого initrd) на каком-то устройстве только для чтения. В противном случае, что бы вы ни делали, вы всегда сможете снять жесткий диск и удалить то, что запускает ваш процесс.
Стефан Шазелас
1

Не уверен, является ли это окончательным решением или это лучший способ сделать это. Мои мнения:

  • Изменить, initтак как это первый процесс, если он умирает, все остальные тоже умирают. Таким образом, ваша машина будет использоваться только с ним.

  • Создайте модуль ядра и загружайте критические модули в зависимости от него (если его убьют, это вызовет цепную реакцию, как в initпримере).

  • Модифицируйте ядро, чтобы игнорировать запросы на удаление для определенного процесса.

Имейте в виду, что последние два будут работать в режиме ядра (который очень ограничен с точки зрения библиотек и т. Д.). Модификация initбудет выполняться в пользовательском пространстве, что позволит вам использовать многие его функции.

Tinti
источник
1
Не уверен, действительно ли это безопасно.
Tinti
И как остановить процесс?
Михее
Это должно быть сделано в самом программном обеспечении. Вам нужно будет создать способ запросить остановку программного обеспечения. Предположим, что у него есть поток, который проверяет файл вроде: /var/lib/stop.request. Если этот файл содержит пароль X, программное обеспечение останавливает РАБОТУ, которую он выполняет, и входит в своего рода спящий режим. Вы можете включить его, создав другой файл /var/lib/start.request.
Tinti