Como posso criar um processo difícil de matar

10

Eu quero criar um programa que será difícil de parar (mesmo para o administrador) depois que ele for iniciado (com privilégios de root). Uma vez iniciado, o processo deve continuar sendo iniciado na inicialização até que seja solicitado a parar. O processo de parada deve levar algum tempo (ou seja, deve ser caro).

Sei que isso pode parecer um software malicioso, mas quero-o por um motivo genuíno. Quero executar bloqueadores de sites no meu laptop (no qual sou o administrador). E quero tornar difícil para mim pará-los.

A solução que pensei é a seguinte:

  1. O processo deve ser executado com um nome diferente cada vez que é executado, para que eu não possa prever o nome do processo e matá-lo.

  2. O processo se salvará em /etc/rc5.d no desligamento

  3. O processo criptografará seu nome usando um código em algum local conhecido. O processo de parada precisará usar o bruteforce para recuperar o nome do programa e matá-lo.

Gostaria de encontrar uma boa solução para esta tarefa.

Miheer
fonte
2
você está realmente certo, ele faz soar como um programa muito média
kiwy
sites culturais ... sim, eu entendo. Eu acho que a compilação do DNS com uma lista de DNS incorrecto poderia ajudá-lo
kiwy
@ Kiwy Sim, essa é uma opção, mas depois posso reinstalar o DNS, certo?
Miheer
Você sempre pode ter um caminho para tudo. Talvez pedir a um amigo que mantenha a senha de root do seu computador é uma boa maneira de cumprir o que você está pedindo: D porque você acabará usando uma chave USB inicializável, se você gosta tanto de conteúdo cultural.
Kiwy
Sim, mas não deve ser um trabalho simples de 2 minutos.
Miheer

Respostas:

8

Uma abordagem poderia ser usar namespaces do PID:

Inicialize seu sistema com um init=/some/cmdparâmetro as kernel, onde /some/cmdbifurca um processo em um novo espaço para nome ( CLONE_NEWPID) e é executado /sbin/initnele (ele terá o PID 1 nesse novo espaço para nome e o pid 2 no espaço para nome raiz) e, em seguida, no pai, execute seu " programa".

Você provavelmente desejará uma maneira de controlar seu programa de uma maneira ou de outra (soquete TCP ou ABSTRACT Unix, por exemplo).

Você provavelmente desejará bloquear seu programa na memória e fechar a maioria das referências ao sistema de arquivos para que ele não dependa de nada.

Esse processo não será visto no resto do sistema. O restante do sistema será executado como em um contêiner.

Se esse processo morrer, o kernel entrará em pânico, o que lhe dará uma garantia extra.

Um efeito colateral inconveniente é que não veremos os threads do kernel na saída de ps.

Como prova de conceito (usando este truque para inicializar uma cópia do seu sistema em uma máquina virtual qemu):

Crie um /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"

(você precisa unsharede uma versão recente do util-linux (2.14)). Acima, estamos usando socatcomo o "programa" que apenas responde nas conexões TCP na porta 1234 com a saída de ps -efH.

Em seguida, inicialize sua VM como:

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'

Então, vemos:

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
fonte
Mas então não posso mudar o arquivo de inicialização para não iniciar / some / cmd?
Miheer
1
@ Miheer, e você pode inicializar a partir de uma chave USB ou instalar um sistema operacional diferente ... Para evitar isso, seria necessário bloquear fisicamente a máquina e o BIOS, o carregador de inicialização, o kernel e o initrd (e iniciar o programa desse initrd) em algum dispositivo somente leitura. Caso contrário, faça o que fizer, sempre será possível remover o disco rígido e remover o que inicia o processo.
Stéphane Chazelas
1

Não tenho certeza se é a solução final ou se é a melhor maneira de fazê-lo. Minhas opiniões:

  • Modifique, initpois é o primeiro processo se morrer todos os outros também morrerão. Portanto, sua máquina só poderá ser utilizada com ela.

  • Crie um módulo do kernel e carregue os módulos críticos, dependendo dele (se for morto, causará uma reação em cadeia como o initexemplo).

  • Modifique o kernel para ignorar solicitações de interrupção para um determinado processo.

Lembre-se de que os dois últimos serão executados no modo kernel (que é muito limitado em termos de bibliotecas e um). A modificação initserá executada no espaço do usuário, permitindo que você use muitos recursos.

Tinti
fonte
1
Não tenho certeza se é realmente seguro.
Tinti
E como parar o processo?
Miheer 12/12/13
Isso precisaria ser feito no próprio software. Você precisaria criar uma maneira de solicitar que o software parasse. Vamos supor que ele tenha um thread que verifique um arquivo como: /var/lib/stop.request. Se esse arquivo contiver uma senha X, o software interromperá o TRABALHO que está realizando e entrará em um tipo de modo de suspensão. Você pode reativá-lo criando outro arquivo /var/lib/start.request.
Tinti