Çatal bombadaki çatal () nerede: () {: |: &};:?


25

Uyarı: Bu komutu çoğu mermide çalıştırmak, düzeltmek için zorla kapatmaya ihtiyaç duyan bozuk bir sisteme neden olur

Özyinelemeli işlevi :(){ :|: & };:ve ne yaptığını anlıyorum. Ama çatal sisteminin nerde olduğunu bilmiyorum. Emin değilim ama borudan şüpheleniyorum |.


İlgili (ve bir okumaya değer): Bir çatal bomba nasıl çalışır?
terdon

Yanıtlar:


30

Boru x | ygirişinin bir sonucu olarak, ön plan işlem grubunun bir parçası olarak boru hattını içerecek bir alt kabuk oluşturulur. Bu fork()süresiz olarak alt kabuklar yaratmaya devam eder , böylece çatal bomba yaratır.

$ for (( i=0; i<3; i++ )); do
>     echo "$BASHPID"
> done
16907
16907
16907
$ for (( i=0; i<3; i++ )); do
>     echo "$BASHPID" | cat
> done
17195
17197
17199

Çatal, kod çalıştırılana kadar gerçekleşmez, ancak kodunuzdaki son çağrıdır :.

Çatal bombalarının nasıl çalıştığını sökmek için:

  • :() - denilen yeni bir işlev tanımlamak :
  • { :|: & } - çağıran işlevi tekrarlayan bir şekilde arka planda çalışan çağıran fonksiyonun bir başka örneğine yönlendiren bir fonksiyon tanımı
  • : - çatal bomba işlevini çağırın

Bu, fazla bellek yoğun olma eğiliminde değildir, ancak PID'leri emer ve CPU çevrimlerini tüketir.


İçinde x | yneden bir alt-kabuk var? Anladığım kadarıyla bash a gördüğünde pipe, pipe()iki tane döndüren sistem çağrısını yürütür fds. Şimdi command_left komutu ediniyor execve çıkış command_right'a girdi olarak besleniyor. Şimdi command_right execed. Peki neden BASHPIDher seferinde farklı?
Abhijeet Rastogi

2
@shadyabhi Çok basit - xve y2 ayrı işlemle çalışan 2 ayrı komut, bu nedenle 2 ayrı alt kabuğunuz var. Eğer xkabuk olarak aynı süreçte çalışır, yani araç xyerleşik olması gerekir.
jw013

24

Kodun son biti ;:işlevi çalıştırıyor :(){ ... }. Çatalın olduğu yer burası.

Noktalı virgül ilk komutu sonlandırır ve başka bir taneye başlıyoruz, yani işlevi çağırmak :. Bu işlevin tanımı, kendisine yapılan bir çağrıyı ( :) içerir ve bu çağrının çıkışı arka planlı bir sürüme aktarılır :. Bu, süreci süresiz olarak ilerletir.

Fonksiyonu :()her aradığınızda C fonksiyonunu çağırıyorsunuz fork(). Sonunda bu, sistemdeki tüm işlem kimliklerini (PID) tüketecektir.

Örnek

|:&Başka bir şeyle değiş tokuş edebilirsiniz, böylece neler olup bittiği hakkında bir fikir edinebilirsiniz.

Bir izleyici kur

Bir terminal penceresinde bunu yapın:

$ watch "ps -eaf|grep \"[s]leep 61\""

"Sigorta ertelendi" çatal bombasını ayarlayın

Başka bir pencerede, çatal bombanın biraz değiştirilmiş bir versiyonunu çalıştıracağız. Bu sürüm kendini boğmaya çalışacak, böylece ne yaptığını inceleyebiliriz. Fonksiyonu çağırmadan önce sürümümüz 61 saniye boyunca uyuyacaktır :().

Ayrıca ilk çağrının çağrılmasından sonra da arkaplanınız. Ctrl+ z, Sonra yazın bg.

$ :(){ sleep 61; : | : & };:

# control + z
[1]+  Stopped                 sleep 61
[2] 5845
$ bg
[1]+ sleep 61 &

Şimdi jobskomutu ilk pencerede çalıştırırsak şunu göreceğiz:

$ jobs
[1]-  Running                 sleep 61 &
[2]+  Running                 : | : &

Birkaç dakika sonra:

$ jobs
[1]-  Done                    sleep 61
[2]+  Done                    : | :

Watcher ile kontrol edin

Bu arada koştuğumuz diğer pencerede watch:

Every 2.0s: ps -eaf|grep "[s]leep 61"                                                                                                                                             Sat Aug 31 12:48:14 2013

saml      6112  6108  0 12:47 pts/2    00:00:00 sleep 61
saml      6115  6110  0 12:47 pts/2    00:00:00 sleep 61
saml      6116  6111  0 12:47 pts/2    00:00:00 sleep 61
saml      6117  6109  0 12:47 pts/2    00:00:00 sleep 61
saml      6119  6114  0 12:47 pts/2    00:00:00 sleep 61
saml      6120  6113  0 12:47 pts/2    00:00:00 sleep 61
saml      6122  6118  0 12:47 pts/2    00:00:00 sleep 61
saml      6123  6121  0 12:47 pts/2    00:00:00 sleep 61

İşlem hiyerarşisi

Ve bir ps -auxfde bu süreç hiyerarşisini gösterir:

$ ps -auxf
saml      6245  0.0  0.0 115184  5316 pts/2    S    12:48   0:00 bash
saml      6247  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
....
....
saml      6250  0.0  0.0 115184  5328 pts/2    S    12:48   0:00 bash
saml      6268  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
saml      6251  0.0  0.0 115184  5320 pts/2    S    12:48   0:00 bash
saml      6272  0.0  0.0 100988   468 pts/2    S    12:48   0:00  \_ sleep 61
saml      6252  0.0  0.0 115184  5324 pts/2    S    12:48   0:00 bash
saml      6269  0.0  0.0 100988   464 pts/2    S    12:48   0:00  \_ sleep 61
...
...

Temizlik zamanı

A killall bash, işleri ellerinden almadan önce durduracaktır. Temizlemenizi bu şekilde yapmak biraz ağır teslim olabilir, potansiyel olarak her bashkabuğu yırtılamayacak daha yumuşak bir yöntem aşağıdakileri yapmak olacaktır:

  1. Çatal bombasının hangi sahte terminalde çalışacağını belirleyin

    $ tty
    /dev/pts/4
  2. Sahte terminali öldür

    $ pkill -t pts/4

Yani, ne oluyor?

İyi her çağırma bashve sleepCı işlevine bir çağrı fork()ile ilgili bashkomut çalıştırıldığı yerden kabuk.


7
bashayrı terminallerde çalışıyor olabilir. Kullanmak daha iyi olur pkill -t pts/2.
Maciej Piechotka

@ MaciejPiechotka - bahşiş için teşekkürler. Bunu daha önce hiç görmedim, cevaba ekledim!
slm
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.