OSTRZEŻENIE NIE PRÓBUJ URUCHOMIĆ TEGO NA MASZYNIE PRODUKCYJNEJ. TYLKO NIE.
Ostrzeżenie: aby wypróbować „bomby”, upewnij się, że ulimit -u
jest w użyciu. Przeczytaj poniżej [a] .
Zdefiniujmy funkcję, aby uzyskać PID i datę (czas):
bize:~$ d(){ printf '%7s %07d %s\n' "$1" "$BASHPID" "$(date +'%H:%M:%S')"; }
Prosta, bezproblemowa bomb
funkcja dla nowego użytkownika (chroń się: przeczytaj [a] ):
bize:~$ bomb() { d START; echo "yes"; sleep 1; d END; } >&2
Po wywołaniu tej funkcji do wykonania działa ona tak:
bize:~$ bomb
START 0002786 23:07:34
yes
END 0002786 23:07:35
bize:~$
Polecenie date
jest wykonywane, następnie drukowane jest „tak”, uśpienie przez 1 sekundę, następnie polecenie zamknięcia date
, a na koniec funkcja kończy drukowanie nowego wiersza polecenia. Nic fajnego.
| rura
Kiedy wywołujemy funkcję w ten sposób:
bize:~$ bomb | bomb
START 0003365 23:11:34
yes
START 0003366 23:11:34
yes
END 0003365 23:11:35
END 0003366 23:11:35
bize:~$
Dwa polecenia zaczynają się w pewnym momencie, dwa kończą się 1 sekundę później, a następnie monit powraca.
To jest powód, dla którego rura |
rozpoczyna równolegle dwa procesy.
& tło
Jeśli zmienimy połączenie dodając zakończenie &
:
bize:~$ bomb | bomb &
[1] 3380
bize:~$
START 0003379 23:14:14
yes
START 0003380 23:14:14
yes
END 0003379 23:14:15
END 0003380 23:14:15
Monit natychmiast wraca (cała akcja jest wysyłana do tła) i dwa polecenia są wykonywane jak poprzednio. Zwróć uwagę na wartość „numeru zadania” [1]
wydrukowanego przed PID procesu 3380
. Później ten sam numer zostanie wydrukowany, aby wskazać, że rura się zakończyła:
[1]+ Done bomb | bomb
Taki jest efekt &
.
Właśnie dlatego &
: aby procesy były uruchamiane szybciej.
Prostsza nazwa
Możemy stworzyć funkcję wywoływaną po prostu w b
celu wykonania dwóch poleceń. Wpisany w trzech wierszach:
bize:~$ b(){
> bomb | bomb
> }
I wykonywane jako:
bize:~$ b
START 0003563 23:21:10
yes
START 0003564 23:21:10
yes
END 0003564 23:21:11
END 0003563 23:21:11
Zauważ, że ;
w definicji nie użyliśmy b
(nowych linii użyto do oddzielenia elementów). Jednak w przypadku definicji w jednym wierszu zwykle stosuje się ;
:
bize:~$ b(){ bomb | bomb ; }
Większość spacji również nie jest obowiązkowa, możemy napisać ekwiwalent (ale mniej wyraźny):
bize:~$ b(){ bomb|bomb;}
Możemy również użyć a, &
aby oddzielić }
(i wysłać dwa procesy do tła).
Bomba.
Jeśli sprawimy, że funkcja ugryzie się w ogon (nazywając siebie), otrzymamy „bombę widelcową”:
bize:~$ b(){ b|b;} ### May look better as b(){ b | b ; } but does the same.
Aby przyspieszyć wywoływanie większej liczby funkcji, wyślij potok do tła.
bize:~$ b(){ b|b&} ### Usually written as b(){ b|b& }
Jeśli dołączymy pierwsze wywołanie do funkcji po wymaganym ;
i zmienimy nazwę :
, otrzymamy:
bize:~$ :(){ :|:&};:
Zwykle napisane jako :(){ :|:& }; :
Lub, napisany w zabawny sposób, pod jakimś innym imieniem (snow-man):
☃(){ ☃|☃&};☃
Ulimit (który powinieneś ustawić przed uruchomieniem tego) spowoduje, że monit powróci dość szybko po wielu błędach (naciśnij Enter, gdy lista błędów zatrzyma się, aby otrzymać monit).
Powodem tego, że nazywany jest „bombą widełkową”, jest to, że sposób, w jaki powłoka uruchamia podpowłokę, polega na rozwidleniu działającej powłoki, a następnie wywołaniu exec () do rozwidlonego procesu za pomocą polecenia uruchomienia.
Rura „rozwidli” dwa nowe procesy. Robienie tego do nieskończoności powoduje bombę.
Lub królika, jak pierwotnie nazywano, ponieważ rozmnaża się tak szybko.
Wyczucie czasu:
:(){ (:) | (:) }; time :
Zakończone
prawdziwe 0m45.627s
:(){ : | :; }; time :
Zakończone
prawdziwe 0m15.283s
:(){ : | :& }; time :
real 0m00.002 s
Nadal działa
Twoje przykłady:
:(){ (:) | (:) }; :
Tam, gdzie )
oddziela się drugie zamknięcie, }
jest to bardziej złożona wersja :(){ :|:;};:
. W każdym razie każde polecenie w potoku jest wywoływane wewnątrz podpowłoki. Który jest efektem ()
.
:(){ : | :& }; :
Jest to szybsza wersja, napisana bez spacji: :(){(:)|:&};:
(13 znaków).
:(){ : | : }; :
### działa w Zsh, ale nie w bash.
Ma błąd składniowy (w bash), metaznak jest potrzebny przed zamknięciem }
,
ponieważ:
:(){ : | :; }; :
[a]
Utwórz nowego czystego użytkownika (zadzwonię do mojegobize
). Zaloguj się do tego nowego użytkownika w konsoli albosudo -i -u bize
:
$ su - bize
Password:
bize:~$
Sprawdź, a następnie zmień max user processes
limit:
bize:~$ ulimit -a ### List all limits (I show only `-u`)
max user processes (-u) 63931
bize:~$ ulimit -u 10 ### Low
bize:~$ ulimit -a
max user processes (-u) 1000
Przy użyciu tylko 10 działa jako tylko jeden samotny nowy użytkownik: bize
. Ułatwia dzwonienie killall -u bize
i pozbycie się systemu większości (nie wszystkich) bomb. Proszę nie pytać, które nadal działają, nie powiem. Ale nadal: jest dość niski, ale po bezpiecznej stronie, dostosuj się do swojego systemu .
Zapewni to, że „bomba widełkowa” nie zawali twojego systemu .
Dalsza lektura:
:(){ : | :; }; :