#!/usr/bin/perl -w
#
# Product:  BotJuper v1.3, (c) pasky 2001 <pasky@pasky.ji.cz>
# Based on: [REJECTOR] v2.0, (c) yanek 2000 <janek@isse.lipniknb.cz>
#
# No warranty and so on, spreading under GNU GPL license.
#
# Simply edit thingies here, add this bot on $remotehost bot (+add pass
# to him), and run it. Then link to it / unlink from it bots and it will
# be fine [to you, propably not to another ones ;]...
#
# Saving userlist:  .me >> mybotjupername >> save /path/where/to
# Loading userlist: .me >> mybotjupername >> load /path/where/from
#
# Derived from [REJECTOR] by yanek, hardly modified.
#
# Changelog:
#
# 1.3 -- slavelist saving, logging, commandline parameters
# 1.2 -- better permission system (@masters), better interface, [REJECTOR]'s
#        old code cleanup, verbose errors, pack of more bugfixes
# 1.1 -- permissions, bugfixes
# 1.0 -- link/unlink/who/trace, basic functionality
#
# TODO:
#
# -- even better permission system
# -- dynamic userlist
# -- telnet interface, partyline
# -- IRC interface
# -- automatic bots juping
# -- better system of bots advertising
#
# This script is mainly intended as sentinel in our l-botnet and as my
# learning material for networking in perl and botnet communication system.
#

print "\nBotJuper v1.3 by pasky - based on [REJECTOR] v2.0 by yanek\n\n";

## DEFAULTS

$thisbot = "n1ghtm4r3";
$thisbotpass = ",.;')4#q";
$remotehost = "127.0.0.1:3334";
$logfile = "/home/pasky/bj.log";
$loglevel = 1;

@masters = qw(pasky Dragon [brano] yanek); # ones allowed to link/unlink bots

use IO::Socket;

while (@ARGV) {
  $switch=shift;
  if ($switch eq '-n') {
    if (! ($val=shift)) { print "Error: '$switch' switch requires parameter\n"; exit; }
    $thisbot=$val;
  } elsif ($switch eq '-p') {
    if (! ($val=shift)) { print "Error: '$switch' switch requires parameter\n"; exit; }
    $thisbotpass=$val;
  } elsif ($switch eq '-h') {
    if (! ($val=shift)) { print "Error: '$switch' switch requires parameter\n"; exit; }
    $remotehost=$val;
  } elsif ($switch eq '-u') {
    if (! ($val=shift)) { print "Error: '$switch' switch requires parameter\n"; exit; }
    @masters=split(/,/,$val);
  } elsif ($switch eq '-l') {
    if (! ($val=shift)) { print "Error: '$switch' switch requires parameter\n"; exit; }
    $logfile=$val;
  } elsif ($switch eq '-L') {
    if (! ($val=shift)) { print "Error: '$switch' switch requires parameter\n"; exit; }
    $loglevel=$val;
  } else {
    print <<EOT;
Is used in IRC bots botnets to jupe bots from it - prevents even connecting to
it. Acts as standalone bot there.

Usage: $0 [-n botname] [-p password] [-h hubaddr] [-u user1,user2] [-l logfile]
	  [-L loglevel]

-n	botnet nick - max. 9 letters
-p	password on hub
-h	hub's address (host:port)
-u	nicks of masters separated by ','
-l	name of file where everything will be logged (as well as on stdout)
-L	level of logging - 0:nothing, 1:normal 2:debug 3:raw
EOT
	exit;
  }
}

if ($loglevel > 0) {
print "Configuring...\n";
print "   Local name: $thisbot\n";
# XXX: Comment this?
print "   Remote pass: $thisbotpass\n";
print "   Remote host: $remotehost\n";
print "   Master list: @masters\n";
print "   Log file: $logfile\n";
print "   Logging level: $loglevel\n"; }

sub connect {
    $socket = IO::Socket::INET->new($remotehost); # or return 0;
}

sub lprint {
        my $id = shift;
        my @data = @_;
	my @mcat = ("Introducing me","Sending pass","Sending version","Remote bot is \%s","Pong","Link by \%s for \%s",
		    "Squit","Who from \%s by \%s\@\%s for \%s [\%s]","Trace from \%s by \%s\@\%s for \%s path \%s",
		    "Unlink by \%s for \%s (\%s)","Reconnecting","Unauthorized link by \%s for \%s",
		    "Unauthorized unlink by \%s for \%s (\%s)","Slavelist save performed by \%s to \%s (\%d slaves saved)",
		    "Unauthorized slavelist save by \%s to \%s");
	if ($id == -2 and $loglevel > 1) {
		print "Position: @data\n";
		print LOG "Position: @data\n";
	} elsif ($id == -1 and $loglevel > 2) {
                print "Input: @data\n";
                print LOG "Input: @data\n";
	} elsif ($id >= 0 and $id <= 14 and $loglevel > 0) {
		printf $mcat[$id]."\n",@data;
		printf LOG $mcat[$id]."\n",@data;
	} elsif ($loglevel > 1) {
                print "Got unknown message (type $id) : @data\n";
                print LOG "Got unknown message (type $id) : @data\n";
        }
}

if ($loglevel>0) { open LOG, '>'.$logfile; }

while (1) {
        &lprint(-2,"core loop");

while (not defined($socket)) {
        &lprint(-2,"connect loop");
        &connect;
}

        &lprint(-2,"core loop II.");

        # state: 0 - not connected
        #        1 - connected but not logged in
        #        2 - remote wait for password
        #        3 - connected, waiting in loop

        $state = 1;
core2:  while ($state) {
                if ($state == 0) {
                        &lprint(10);
			sleep 1; # if we are caught in ignore or so
                        &connect;
                        $state = 1;
                }
                $msg = $socket->getline or last;
                chomp($msg);
                &lprint(-1,"'$msg'");
                if ($state == 1) {
                        &lprint(0);
                        print $socket "$thisbot\n" or last;
                        $state = 2;
                }
                if ($state == 2) {
                        if ($msg =~ /passreq/) {
                                &lprint(1);
                                print $socket "$thisbotpass\n" or last;
                                $state = 3;
                        }
                        if ($msg =~ /handshake/) {
                                &lprint(1);
                                print $socket "$thisbotpass\n" or last;
                                $state = 3;
                        }
                }
                if ($state == 3) {
                        if ($msg eq '*hello!') {
                                &lprint(2);
                                print $socket "version 2000000 9 BJ v1.3.0 <evil-net>\n" or last;
				foreach $slave (@slaves) {
				  print $socket "n $slave $thisbot -EAcg\n" or last core2;
				}
                                $state = 4;
                        }
                }
                if ($state == 4) {
                        if ($msg =~ /^tb (.*)/) {
                                $remotebot = $1;
                                &lprint(3,$remotebot);
                        }
                        elsif ($msg =~ /^pi/) {
                                print $socket "po\n" or last;
                                &lprint(4);
                        }
			elsif ($msg =~ /^a (.*)\@(.*) (.) >> $thisbot >> save (.*)/i ) {
				if (&lookfor($1,@masters)+1) {
				  print $socket "p $thisbot $1\@$2 Yes, sir!\n";
				  open SLAVELIST, '>'.$4; $slaves=@slaves; $slavelist=join(',',@slaves);
				  print SLAVELIST $slavelist; close SLAVELIST;
				  print $socket "p $thisbot $1\@$2 $slaves records saved, sir!\n";
				  &lprint(13,$1."\@".$2,$4,$slaves);
                                } else { &lprint(14,$1."\@".$2,$4);
                                         print $socket "p $thisbot $2\@$3 Permission denied, babe! :P\n"; }
			}
			elsif ($msg =~ /^a (.*)\@(.*) (.) >> $thisbot >> load (.*)/i ) {
				if (&lookfor($1,@masters)+1) {
				  print $socket "p $thisbot $1\@$2 Yes, sir!\n";
				  open SLAVELIST, $4; $slavelist=<SLAVELIST>; close SLAVELIST;
				  @slaves=split(/,/, $slavelist); $slaves=@slaves;
				  print $socket "p $thisbot $1\@$2 $slaves records loaded, sir!\n";
				  &lprint(13,$1."\@".$2,$4,$slaves);
				  print $socket "bye\n"; $state = 0; # This is far simplest way and we will be fast >:)
                                } else { &lprint(14,$1."\@".$2,$4);
                                         print $socket "p $thisbot $2\@$3 Permission denied, babe! :P\n"; }
			}
			elsif ($msg =~ /^l (.*):(.*)\@(.*) $thisbot (.*)/i) {
				if (&lookfor($2,@masters)+1) {
				  $bot=substr($4,0,9);
				  if (! grep(/^$bot$/i, @slaves) ) {
				    push(@slaves,$bot);
				    print $socket "n $bot $thisbot !D[AQ\n" or last;
				    &lprint(5,$2."\@".$3,$bot);
				  }
				} else { &lprint(11,$2."\@".$3,$4);
					 print $socket "p $thisbot $2\@$3 Permission denied, babe! :P\n"; }
			}
			elsif ($msg =~ /^ul (.*):(.*)\@(.*) $thisbot (.*) (.*)/i) { if (&lookfor($2,@masters)+1) {
				$bot=substr($4,0,9); if (grep(/^$bot$/i, @slaves) ) { splice(@slaves,&lookfor($bot,@slaves),1);
				print $socket "un $bot Freed slave: $bot ($5)\n" or last;
				&lprint(9,$2."\@".$3,$bot,$5); } } else { &lprint(12,$2."\@".$3,$4,$5);
				print $socket "p $thisbot $2\@$3 Permission denied, babe! :P\n"; }
			}
                        elsif ($msg eq 'bye') {
                                &lprint(6);
                                $state = 0;
#                                last;
                        }
                        # w 14:yanek@LiNUX rejector A && m !11:yanek@SySTEM rejector

                        elsif ((($msg =~ /^w (.*):(.*)\@(.*) (.*) (.*)/) or ($msg =~ /^m .(.*):(.*)\@(.*) (.*)/)) and
				&lookfor($4,@slaves)+1 or uc($4) eq uc($thisbot)) {
                                &lprint(7,$1,$2,$3,$4,$5);
				if (uc($4) eq uc($thisbot)) {
                                print $socket "p $thisbot $1:$2\@$3 Hi, kid. I'm the one. The one chosen to be hated by everyone\n";
                                print $socket "p $thisbot $1:$2\@$3 everywhere in this botnet. The one who should put penalty\n";
                                print $socket "p $thisbot $1:$2\@$3 on the most evil bots here. You should fear me. Now. Because\n";
                                print $socket "p $thisbot $1:$2\@$3 i'm your worst nightmare. Digital IRC nightmare.\n";
                                print $socket "p $thisbot $1:$2\@$3 And I'm spreading my fear via my feeder, $remotebot.\n";
				} else {
				print $socket "p $4 $1:$2\@$3 I'm the part of unique large virtual hallucination in this botnet.\n";
				print $socket "p $4 $1:$2\@$3 The times are changing. You should start fear. Shadow is coming.\n";
				} if (&lookfor($2,@masters)+1) {
				print $socket "p $4 $1:$2\@$3 \n";
				print $socket "p $4 $1:$2\@$3 ---\n";
				print $socket "p $4 $1:$2\@$3 \n";
				print $socket "p $4 $1:$2\@$3 You are master! You can link/unlink bots from me. Be careful.\n";
				}
                        }
                        # t 11:yanek@SySTEM rejector :976467255:SySTEM
                        # td 14:yanek@LiNUX :976467277:LiNUX:system
                        # t 14:yanek@LiNUX rejector :976467277:LiNUX:SySTEM
                        elsif ($msg =~ /^t (.*):(.*)\@(.*) (.*) (.*)/ and &lookfor($4,@slaves)+1 or uc($4) eq uc($thisbot)) {
				$m=$5; if (uc($4) ne uc($thisbot)) { $m.=":$thisbot"; }
                                &lprint(8,$1,$2,$3,$4,$m);
                                print $socket "td $1:$2\@$3 $m:$4\n";
                        }
                }
        }
        $socket = undef;
        $state = 0;
        &lprint(-2,"core loop III.");
}
&lprint(-2,"Singing off with joy...");
close $main_sock;

sub lookfor {
  my($pos, $f);
  $f=shift;
  for ($pos=0; $pos<@_; $pos++) { if (uc( $_[$pos] )eq uc $f) { return $pos; } }
  return -1;
}

# [system] t 11:yanek@SySTEM bot_hub5 :976467573:SySTEM
# [bot_HUB] td 14:yanek@LiNUX :976467406:LiNUX:bot_HUB:bot_HUB1:bot_HUB2
# [bot_HUB] td 14:yanek@LiNUX :976467406:LiNUX:bot_HUB:bot_HUB1:bot_HUB2:bot_HUB3
# [bot_HUB] td 14:yanek@LiNUX :976467406:LiNUX:bot_HUB:bot_HUB1:bot_HUB2:bot_HUB3:bot_HUB4
# [bot_HUB] td 14:yanek@LiNUX :976467406:LiNUX:bot_HUB:bot_HUB1:bot_HUB2:bot_HUB3:bot_HUB4:bot_HUB5
