Что означает эта загадочная команда Bash?

23

Я читал предупреждение Ubuntu Forum о вредоносных командах и нашел этот интересный камень:

:(){ :|:& };:

ПРЕДУПРЕЖДЕНИЕ. Приведенный выше код приведет к сбою на вашей машине, если только вы не установили строгие ограничения процедур (что, вероятно, нет), что приведет к принудительной перезагрузке.

Считайте, что этот код похож на запуск sudo rm -rf /.

Но что это значит? Даже с моим опытом программирования я никогда не видел загадочную команду, которая не является языком ассемблера.

TheLQ
источник
16
Дополнительный момент: это действительно ни на что не похоже sudo rm -rf /. Эта команда удаляет все ваши файлы; этот просто забивает ресурсы вашей машины, пока он не станет непригодным для использования, и вам придется перезагрузить.
jtbandes
@jtban: Тогда отредактируйте это. Обе части кода - это то, что я считаю «опасным» для запуска. Да, sudo rm -rf /это более опасно, но я видел, как люди выполняли это на удаленных серверах, «просто хотели посмотреть, что они сделали», когда вам трудно перезапустить компьютер без доступа к панели управления.
Джош К
7
Эмо-бомба: P
RCIX
Обратите внимание, что это может быть arbitrary_name(){ arbitrary_name|arbitrary_name& };arbitrary_name. Имя :не только делает эту команду короткой и загадочной, но и превращает :встроенную функцию , которая ничего не делает, в функцию, которая делает много . Если вы добавите его определение :(){ :|:& }в чужую среду и оставите его там, оно ударит, когда жертва этого меньше всего ожидает .
Камиль Мачоровски

Ответы:

40

Это, как вы сказали, вилочная бомба. Что он делает, так это определяет функцию, а затем вызывает ее. Функция называется :.

Давайте forkbombназовем это, чтобы мы могли лучше видеть, что происходит:

forkbomb(){ forkbomb|forkbomb& };forkbomb

Как вы можете видеть и, вероятно, догадываетесь из своего опыта программирования, первая часть - это определение функции ( forkbomb(){ ... }), а самая последняя :- то, где вызывается функция ( ;оператор just разделяет в Bash).

Теперь, что делает эта функция? Если вы знакомы с Bash, вы будете знать, что |персонаж передает стандартный вывод одной команды / программы на стандартный ввод другой. Таким образом, в основном :|:запускаются два экземпляра функции (именно здесь она «разветвляется»).

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

jtbandes
источник
1
Отличный ответ! Я не понимал, что вы можете использовать: как имя функции. Переименование помогает. Примут через 3 минуты.
TheLQ
1
+1 Круто ... Отличное объяснение. Это похоже на переполнение стека для переключателя задач ОС. Действительно ли это приводит к краху ядра или просто поглощает ресурсы, пока не станет слишком невыносимым для использования?
Эван Плейс
Я не думаю, что это на самом деле ломает ядро, по крайней мере, не напрямую. Он просто продолжает создавать экспоненциально больше процессов, каждый из которых занимает процессор и память, а процессор, пытающийся справиться со всеми из них, становится по-настоящему невозможным для использования. Может случиться так, что ядро ​​со временем вылетает под нагрузкой (я не уверен), но до этого оно будет непригодным для использования.
2010 года
3
Не забудьте объяснить финал :, который фактически выполняет функцию!
Фоши
@Phoshi: думал, что сделал, но я отредактирую, чтобы уточнить!
jtbandes
9

Взято из статьи Википедии Forkbomb :

:()      # define ':' -- whenever we say ':', do this:
{        # beginning of what to do when we say ':'
    :    # load another copy of the ':' function into memory...
    |    # ...and pipe its output to...
    :    # ...another copy of ':' function, which has to be loaded into memory
         # (therefore, ':|:' simply gets two copies of ':' loaded whenever ':' is called)
    &    # disown the functions -- if the first ':' is killed,
         #     all of the functions that it has started should NOT be auto-killed
}        # end of what to do when we say ':'
;        # Having defined ':', we should now...
:        # ...call ':', initiating a chain-reaction: each ':' will start two more.
Джеймс Т
источник
7

Сломано:

: () // Define ':' as a function. When you type ':' do the following
{
    : // Call ':' 
    | // Redirect output
    : // Into ':'
    & // Push process to the background
}; // End of ':' def
: // Now do ':'

Изменить :на bombи у вас есть:

bomb(){ bomb|bomb& };bomb

Это действительно довольно элегантно.

Джош К
источник