#!/usr/local/bin/perl
# SPS.pl (Simples Perl Scanner) by lovemeorleaveme@mvmail.com.br
# Simples scanner que mostra os banners das seguinte portas:
# 80, 21, 22, 25, 110, RPCs, e a versão do dns.
# Testado no linux.
# OpenSource.
# v. 0.2 - 10/04/2001
use Net::DNS;
use Socket;
use LWP::Simple;

die "usage: $0 hostname\n" unless @ARGV;

print "\n=========================================================\n";
print "HST: $ARGV[0]\n";
send_probe();
dns($ARGV[0]);
rpc();

sub rpc
{
$pat = 'S n C4 x8';
$stream = 1;
$datagram = 2;
$inet = 2;
$tcp = 6;
$udp = 17;

print "RPC:\n";

my $TIMEOUT = 10;
eval {
local $SIG{ALRM} = sub { die "Timeout Alarm" };
alarm $TIMEOUT;

srand($$^time&$ENV{RANDOM});

%rpc_serv=qw(100000 portmapper
             100001 rstatd
             100002 rusersd
             100003 nfs
             100004 ypserv
             100005 mountd
             100007 ypbind
             100008 walld
             100009 yppasswdd
             100010 etherstatd
             100011 rquotad
             100012 sprayd
             100013 3270_mapper
             100014 rje_mapper
             100015 selection_svc
             100016 database_svc
             100017 rexd
             100018 alis
             100019 sched
             100020 llockmgr
             100021 nlockmgr
             100022 x25.inr
             100023 statmon
             100024 status
             100026 bootparam
             100028 ypupdated
             100029 keyserv
             100232 sadmind
             100033 sunlink_mapper
             100037 tfsd
             100038 nsed
             100039 nsemntd
             100043 showfhd
             100068 cmsd
             100069 ypxfrd
             100078 kerbd
             100083 ttdbserverd
             100087 admind
             100099 autofs
             150001 pcnfsd
             390103 nsrd
             390109 nsrstat
             390113 nsrexec
             390107 nsrmmdbd
             390104 nsrmmd
             390105 nsrindexd
	     300019 amd
             );

($name,$aliases,$port) = getservbyname('sunrpc','udp');
$host=$ARGV[0];
        if ($host =~ /^\d+\./) {
                @bytes = split(/\./,$host);
        } else {
                ($name,$aliases,$addrtype,$length,@addrs) = gethostbyname($host);
                die "Can't lookup $host\n" unless $name;
                @bytes = unpack("C4",$addrs[0]);
        }
        $this = pack($pat,$inet,0,0,0,0,0);
        $that = pack($pat,$inet,$port,@bytes);
        socket(S,2,$datagram,$udp) || die "socket: $!\n";
        bind(S,$this) || die "bind: $!\n";
        connect(S,$that) || die "connect: $!\n";
        select(S); $| = 1; select(STDOUT); $| = 1;
        $trx=int(rand(10000));

        print S pack("N13",
                     $trx,      # transaction
                     0,         # call
                     2,         # RPC Version
                     100000,    # portmap program number
                     2,         # version number
                     4,         # procedure number
                     );

        sysread(S, $_, 32767);
        $"=" ";
        @r = unpack("N" . length($_)/4, $_);
        if ($r[0] != $trx) {
                die "xid error\n";
        } elsif ($r[1] != 1) {
                die "Not a reply!\n";
        } elsif ($r[2] == 1) {
                if ($r[3] == 0) {
                        die "Rejected - RPC_MISMATCH\n";
                } elsif ($r[3] == 1) {
                        die "Rejected - AUTH_ERROR\n";
                } else {
                        die "Rejected - unknown code\n";
                }
        } else {
#               print '', (("SUCCESS", "PROG_UNAVAIL", "PROG_MISMATCH", "PROC_UNAVAIL",
#                       "GARBAGE_ARGS")[$r[5]]), "\n";
        }
        close S;

shift(@r);shift(@r);shift(@r);shift(@r);shift(@r);shift(@r);shift(@r);
print "   program vers proto   port  program       owner\n";
while (@r) {
    $r[$_+2] = "tcp" if ($r[$_+2] == 6);
    $r[$_+2] = "udp" if ($r[$_+2] == 17);
    $r[$_+4] = (getpwuid($r[$_+4]))[0];
    write;
    shift(@r);shift(@r);shift(@r);shift(@r);shift(@r);
}

format STDOUT=
@>>>>>>>>> @>>> @>>>> @>>>>>  @<<<<<<<<<<<< @<<<<<<<<
$r[$_],$r[$_+1],$r[$_+2],$r[$_+3],$rpc_serv{$r[$_]},$r[$_+4]
.
alarm 0;
};
}

sub dns
{
my $TIMEOUT = 10;

eval {
local $SIG{ALRM} = sub { die "Timeout Alarm" };
alarm $TIMEOUT;

my $res = new Net::DNS::Resolver;
$res->nameservers(shift);        #query the nameserver on the command line.
my $packet = $res->query('VERSION.BIND', 'TXT', 'CH');
if(defined($packet)) {
my @answers = $packet->answer;
foreach my $rr (@answers) {
if($rr->type eq 'TXT') {
print "DNS: ";
print $rr->txtdata . "\n";
        }
    }
} else {
    print "DNS: No.\n";
}
alarm 0;
};
}

sub send_probe
{

$port = 21;
$NETFD = &makeconn($ARGV[0], $port);
sysread $NETFD, $message_ftp,100 ;
close $NETFD;

$port = 22;
$NETFD = &makeconn($ARGV[0], $port);
sysread $NETFD, $message_ssh,100 ;
close $NETFD;

$port = 25;
$NETFD = &makeconn($ARGV[0], $port);
sysread $NETFD, $message_mta,100 ;
close $NETFD;

$port = 110;
$NETFD = &makeconn($ARGV[0], $port);
sysread $NETFD, $message_pop,100 ;
close $NETFD;

www_svr($ARGV[0]);

if ($message_ftp) { print "FTP: $message_ftp" }
else { print "FTP: No.\n" }

if ($message_ssh) { print "SSH: $message_ssh" }
else { print "SSH: No.\n" }

if ($message_mta) { print "MTA: $message_mta" }
else { print "MTA: No.\n" }

if ($message_pop) { print "POP: $message_pop" }
else { print "POP: No.\n" }

}


sub makeconn
{
my $TIMEOUT = 10;

eval {
local $SIG{ALRM} = sub { die "Timeout Alarm" };
alarm $TIMEOUT;

my ($host, $portname, $server, $pt,$pts, $proto, $servaddr);
$host = $_[0];
$pt = $_[1];
$server = gethostbyname($host) or die "gethostbyname: cannot locate host: $!";
$pts = getservbyport($pt, 'tcp');
$proto = getprotobyname('tcp') or die " : $!";
$servaddr = sockaddr_in($pt, $server);
socket(CONNFD, PF_INET, SOCK_STREAM, $proto);
connect(CONNFD, $servaddr) ;
$proto = getprotobyname('tcp') or die " : $!";
$servaddr = sockaddr_in($pt, $server);
socket(CONNFD, PF_INET, SOCK_STREAM, $proto);
connect(CONNFD, $servaddr) ;
return CONNFD;
alarm 0;
};
}

sub www_svr {

my $TIMEOUT = 10;

eval {
local $SIG{ALRM} = sub { die "Timeout Alarm" };
alarm $TIMEOUT;

 my ($host) = @_;
  ($content_type, $document_length, $modified_time,$expires,
    $server) = head("http://$host");

if ($server) { print "WWW: $server\n" }
else { print "WWW: No.\n" }

alarm 0;
};
}
print "=========================================================\n";
