#!/usr/pkg/bin/perl my $version = "2.15"; # Copyright (c) 2000 - 2002 Marco van Berkum # This library is free software; you can redistribute it and/or # modify it under the terms of the GNU Lesser General Public # License as published by the Free Software Foundation; either # version 2.1 of the License, or (at your option) any later version. # This library is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU # Lesser General Public License for more details. # You should have received a copy of the GNU Lesser General Public # License along with this library; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # Programmed by: # Marco van Berkum, m.v.berkum@obit.nl # Kristian Vlaardingerbroek, kris@obit.nl # Pepijn Vissers, zoef@zoefdehaas.nl # Herman Poortermans, herman@ofzo.nl # # Website: http://ws.obit.nl # # Hackbot is also a freshmeat project # http://freshmeat.net/projects/hackbot/ use IO::Socket; use Net::hostent; use Getopt::Std; # core functionality &getopts('AitfmsSdrVl:w:z:a:XF:M:O:P:'); use vars qw($opt_A $opt_i $opt_t $opt_f $opt_m $opt_s $opt_S $opt_d $opt_r $opt_V $opt_l $opt_w $opt_z $opt_a $opt_X $opt_F $opt_O $opt_P); if (!$opt_F) { $host = $ARGV[0]; } else {chomp $opt_F; $targetfile = $opt_F}; if($opt_V) { print("Hackbot version $version\n"); exit(0); } if ( ( !$host && !$opt_F ) || ( $host && $opt_F ) || ( !$opt_A && !$opt_i && !$opt_t && !$opt_f && !$opt_m && !$opt_s && !$opt_S && !$opt_d && !$opt_r && !$opt_w && !$opt_z && !$opt_a && !$opt_X && !$opt_F && !$opt_P && !$ARGV[1]) ) { print("Hackbot version $version\nusage: ./hackbot.pl \n\n"); print("or: ./hackbot.pl -F \n\n"); print("Available options:\n"); print("-O \n"); print("-A\t\tAll scan types\n"); print("-i\t\tidentd scan\n"); print("-t\t\tSimple Telnet Fingerprint\n"); print("-f\t\tFTP scan\n"); print("-m\t\tMTA scan\n"); print("-s\t\tSSH scan\n"); print("-S\t\tSpammer check\n"); print("-d\t\tDNS scan\n"); print("-r\t\tRegistrar whois lookup\n"); print("-V\t\tPrint version and exit\n"); print("-P \tUse proxy for scanning\n"); print("-l \tloglevel\n"); print("\t\tc critical (default)\n"); print("\t\tv verbose\n"); print("\t\td debug\n"); print("-w \tWebserver scan\n"); print("\t\ta All scans\n"); print("\t\tv Version scan\n"); print("\t\to HTTP Options scan\n"); print("\t\tc CGI scan\n"); print("\t\ti IDA scan\n"); print("\t\tu Unicode scan\n"); print("\t\tn Nimda scan\n"); print("-z \t\tSet time in seconds between each CGI poll \(to be less conspicuous\)\n"); print("-a \t\tSet alternative webserver port\n"); print("-X\t\tX allow check\n\n"); print("examples:\t./hackbot.pl -f -m -w oci localhost\n"); print("\t\t./hackbot.pl -A 192.168.75.3 195.0.0.255\n"); print("\t\t./hackbot.pl -s 192.168.75.0\/26\n\n"); exit(0); } $database = "/usr/pkg/share/hackbot/cgi.db"; $fingerprintdb = "/usr/pkg/share/hackbot/fingerprint.db"; # print(`clear`); print("\n"); &banner; $noprint = 1; log_print(`date`,"c"); log_print("\n","c"); undef($noprint); if($opt_l) { if(($opt_l !~ /^[cdv]+$/ )) { print "Unknown loglevel defenition: " . $opt_l . "\n"; exit(0); } } if($opt_w) { if(($opt_w !~ /^[aociunv]+$/ )) { print "Unknown webserver scan type: " . $opt_w . "\n"; exit(0); } } if($opt_a) { if(!$opt_A && !$opt_w) { print("Please define more options\n"); print("Quitting...\n"); unlink "output.$host"; exit(0); } chomp($opt_a); $port = $opt_a; } else { $port = "80"; } if($opt_z) { if(!$opt_A && !$opt_w) { print("Please define more options\n"); print("Quitting...\n"); unlink "output.$host"; exit(0); } chomp($opt_z); } if($opt_P) { ($proxy, $proxyport) = split(/:/, $opt_P); chomp($proxy); chomp($proxyport); $userinputproxythingy = $proxy; if ($proxy =~ /[A-z]/) { log_print("Trying to resolve proxyhost $proxy\n","h"); my $handler = gethost($proxy); if(!$handler) { log_print("proxyhost $proxy does not resolve, will continue scan without using a proxy\n\n","i"); undef($proxy); undef($proxyport); } else { $proxy = inet_ntoa(@{$handler->addr_list}[0]); log_print("Resolved $userinputproxythingy to $proxy\n","c"); log_print("Testing if the proxy works..\n\n","h"); &proxytest($proxy, $host); $tested = 1; } } if ($proxy !~ /[A-z]/) { log_print("Testing if the proxy works..\n","h") unless($tested); &proxytest($proxy, $host) unless($tested); } undef($tested); } if($opt_F) { $date = `date`; open(TARGETLIST,"$targetfile") || die "$0: Could not read from $targetfile! ($!)"; while () { chomp; push(@targetlist, $_); } foreach $host (@targetlist) { log_print("Checking $host ...\n\n","h"); &scanit } } else { if ($host=~/[A-z]/) { log_print("Checking named host $host ...","c"); &scanit; } else { &GetRange; $range = "1"; unless("$start" eq "$end") { log_print("Range Scan from $start to $end\n","c"); } foreach $host (@targetlist) { log_print("\nChecking $host ...\n\n","c"); &scanit; } } } &endbanner; # end core ############### # Subroutines # ############### sub scanit { if (!&check_ip($host)) { log_print(" trying to resolve hostname $host\n\n","c"); my $handler = gethost($host); if(!$handler) { log_print("$host does not resolve, I died\n\n","c"); if($opt_O) { unlink $opt_O; } else { unlink "output.$host"; } exit(0); } $target = inet_ntoa(@{$handler->addr_list}[0]); log_print("resolved host to: $target\n\n","i"); $host_resolves = 1; } else { $target = $host; $host_resolves = 0; } if($opt_A){ $opt_i="1";$opt_t="1"; $opt_f="1";$opt_m="1"; $opt_s="1";$opt_S="1"; $opt_d="1";$opt_r="1"; $opt_w="a";$opt_X="1"; #now you can undef opt_A in case of no web. # undef after this line } if($opt_S) { header_reset(); &spamcheck; } if($opt_i) { header_reset(); &ident; } if($opt_t) { header_reset(); &telnetfprint; } if($opt_f) { header_reset(); &ftp; } if($opt_m) { header_reset(); &mta; } if($opt_s) { header_reset(); &ssh; } if($opt_d) { header_reset(); &dns; } if($opt_r) { header_reset(); &whois unless ($nowhois); $nowhois = $range; } if($opt_X) { header_reset(); &xcheck; } if($opt_w) { header_reset(); &checkweb; if(($opt_w =~ /o/)||($opt_w =~ /a/)) { header_reset(); &http_options unless $noweb; } if(($opt_w =~ /c/)||($opt_w =~ /a/)) { header_reset(); log_print("\n","c"); &cgi unless $noweb; &netscape unless $noweb; } if(($opt_w =~ /i/)||($opt_w =~ /a/)) { header_reset(); &ida unless $noweb; } if(($opt_w =~ /u/)||($opt_w =~ /a/)) { header_reset(); &unicode unless $noweb; &unicode2 unless $noweb; } if(($opt_w =~ /n/)||($opt_w =~ /a/)) { header_reset(); &nimda unless $noweb; } } } sub check_ip { my $ipaddr = shift; if ($ipaddr !~ /^[0-9\.]+$/) { return 0 } if ($ipaddr !~ /^(\d+)\.(\d+)\.(\d+)\.(\d+)$/) { return 0 } for ($1, $2, $3, $4) { return 0 if ($_ > 255) } return 1; } sub banner { log_print("###############################################################\n","c"); log_print("# HackBot v$version 2002 / http://ws.obit.nl/hackbot/ #\n","c"); log_print("# (c) 2000-2002 Marco van Berkum #\n","c"); log_print("# #\n","c"); log_print("# Marco van Berkum - m.v.berkum\@obit.nl #\n","c"); log_print("# Kristian Vlaardingerbroek - kris\@obit.nl #\n","c"); log_print("# Pepijn Vissers - zoef\@zoefdehaas.nl #\n","c"); log_print("# Martijn Mooijman - foobar\@obit.nl #\n","c"); log_print("# Herman Poortermans - herman\@ofzo.nl #\n","c"); log_print("###############################################################\n","c"); log_print("\n","c"); } sub cgi { if (!-e $database) { $nodb = 1; } open CGI, "<$database" unless($nodb); # potential bugfix undef($exploit); undef($description); undef($advisory); # actual code log_print("Checking the webserver on port $port for various potential problems\n","h") unless($nodb); log_print("------------------------------------------------------------------\n","h") unless($nodb); while(1) { if($nodb) { log_print("No db found it should be in $database, skipping CGI scan\n","c"); last; } if($proxy) { print("Scanning via proxy $proxy\n\n"); while() { if($opt_z) { sleep($opt_z); } ($exploit, $description, $advisory) = split(/\!/, $_); chomp($exploit, $description, $advisory); my $sock = new IO::Socket::INET (PeerAddr => $proxy, PeerPort => $proxyport, Proto => 'tcp', Timeout => '5'); if($sock && $exploit) { if($host_resolves == 1) { print $sock "GET http://$host$exploit HTTP/1.0\r\n\r\n"; } else { print $sock "GET http://$target$exploit HTTP/1.0\r\n\r\n"; } sysread($sock, $buff, 15000); if($buff =~ /200 OK/) { log_print("* $exploit found!\n","c"); log_print("* $description\n","c") unless (!$description); log_print("* $advisory\n","c") unless (!$advisory); log_print("\n","c"); close($sock); } } }} else { while() { if($opt_z) { sleep($opt_z); } ($exploit, $description, $advisory) = split(/\!/, $_); chomp($exploit, $description, $advisory); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if($sock) { if($host_resolves == 1) { print $sock "GET http://$host$exploit HTTP/1.0\r\n\r\n"; } else { print $sock "GET $exploit HTTP/1.0\r\n\r\n"; } sysread($sock, $buff, 15000); if($buff =~ /200 OK/) { log_print("* $exploit found!\n","c"); log_print("* $description\n","c") unless (!$description); log_print("* $advisory\n","c") unless (!$advisory); log_print("\n","c"); close($sock); } } } } close CGI; last; } } sub mta { log_print("Trying MTA - Relaying, VRFY and EXPN\n","h"); log_print("------------------------------------\n","h"); my $sock = new IO::Socket::INET ( PeerAddr => $target, PeerPort => '25', Proto => 'tcp', Timeout => '7' ); if(!$sock) { log_print("No MTA\n\n","i"); } while($sock) { $cnt = sysread($sock, $buff, 15000); if(!$cnt) { log_print("Hmmm weird socket error, I died\n\n","c"); close($sock); last; } log_print("$buff","c"); if($buff =~ /^220 \*\*\*\*\*\*\*\*\*/) { log_print("This mailserver is probably protected by a Cisco Pix Firewall with MailGuard enabled\n","c"); log_print("\nLets try to outsmart it \:\)\_\n\n","c"); print $sock "data\r\n"; sleep(3); sysread($sock, $buff, 1500); print("return after DATA command is: $buff\n"); if($buff !~ /^500/) { log_print("Sending EHLO command\n","h"); print $sock "EHLO hackbot\r\n"; sleep(3); sysread($sock, $buff, 1500); if($buff !~ /^500/) { log_print("worked..\n\n","c"); log_print("$buff\n","c"); } else { log_print("didn't work..\n\n","i"); } log_print("Sending HELP command\n","h"); print $sock "HELP\r\n"; sleep(3); sysread($sock, $buff, 1500); if($buff !~ /^500/) { log_print("worked..\n\n","c"); log_print("$buff\n"); } else { log_print("didn't work..\n\n","i"); } log_print("Trying VRFY command\n","h"); print $sock "vrfy root\r\n"; sleep(3); sysread($sock, $buff, 1500); if ($buff =~ /^250/) { log_print("worked..\n\n","c"); log_print("$buff\n"); } else { log_print("didn't work..\n\n","i"); } log_print("Trying EXPN command\n","h"); print $sock "expn root\r\n"; sleep(3); sysread($sock, $buff, 1500); if ($buff =~ /^250/) { log_print("worked..\n\n","c"); log_print("$buff\n","c"); } else { log_print("didn't work..\n\n","i"); } log_print("Done playing with PIX for now, let's continue with the normal commands\n\n","i"); print $sock "RSET\r\n"; } } undef($buff); sleep(1); print $sock "helo bla\r\n"; sleep(2); sysread($sock, $buff, 150); log_print("$buff\n","d"); print $sock "mail from: bill.gates\@microsoft.com\r\n"; sleep(1); sysread($sock, $buff, 150); log_print("$buff\n","d"); print $sock "rcpt to: bill.gates\@microsoft.com\r\n"; sleep(1); sysread($sock, $buff, 150); log_print("$buff\n","d"); if ($buff =~ /^250/) { log_print("Relaying allowed\n\n","c"); } else { log_print("Relaying not allowed\n\n","i"); } print $sock "vrfy root\r\n"; sleep(1); sysread($sock, $buff, 15000); log_print("$buff\n","d"); if ($buff =~ /^250/) { log_print("VRFY enabled\n\n","c"); log_print("$buff\n"); } else { log_print("VRFY not enabled\n\n","i"); } print $sock "expn root\r\n"; sleep(1); sysread($sock, $buff, 15000); log_print("$buff","d"); if ($buff =~ /^250/) { log_print("EXPN enabled\n\n","c"); print "$buff\n" } else { log_print("EXPN not enabled\n\n","i"); } log_print("\n","c"); close(!$sock); last; } } sub checkweb { undef($noweb); log_print("Checking for webserver on port $port\n","h"); log_print("-----------------------------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if ($sock) { if($host_resolves == 1) { print $sock "HEAD http://$host/ HTTP/1.0\r\n\r\n"; } else { print $sock "HEAD / HTTP/1.0\r\n\r\n"; } sleep(2); sysread($sock, $httpversion, 15000); if($opt_w =~ /v/ || $opt_w =~ /a/ || $opt_A) { log_print("$httpversion\n","c"); if ($httpversion =~ /Apache/) { &modphpssl($httpversion); } } else { log_print("Webserver found\n\n","c"); } } else { $noweb = 1; log_print("No webserver\n","i"); } } sub http_options { log_print("HTTP options\n","h"); log_print("------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); # potential bugfix undef($allow); undef($public); # actual code if ($sock) { if($host_resolves == 1) { print $sock "OPTIONS http://$host/ HTTP/1.0\r\n\r\n"; } else { print $sock "OPTIONS / HTTP/1.0\r\n\r\n"; } sysread($sock, $buff, 5000); $allow = $buff; $public = $buff; ($tmp, $allow) = split(/Allow:(.*)/, $buff); ($tmp, $public) = split(/Public:(.*)/, $buff); log_print("Allow options : $allow\n","c") unless(!$allow); log_print("Public options: $public\n","c") unless(!$public); close($sock); } if ($httpversion =~ /IIS/) { log_print("\n","c"); &propfind($target); &isapi($target); } } sub ida { @idas = ('ida','idq','idc'); log_print("\nChecking for ida\n","h"); log_print("----------------\n","h"); foreach(@idas) { my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if ($sock) { if($host_resolves == 1) { print $sock "GET http://$host/blabla.$_ HTTP/1.0\r\n\r\n"; } else { print $sock "GET /blabla.$_ HTTP/1.0\r\n\r\n"; } sleep(3); sysread($sock, $buff, 1000); if ($buff =~ /\:\\/) { ($temp, $lastline) = split(/file\ /,$buff); ($path) = split(/\ /,$lastline); log_print("$path\n","c"); } close($sock); } } #log_print("\n","c"); } sub unicode { @vuln = ('msadc','scripts'); log_print("Unicode tests\n","h"); log_print("-------------\n","h"); log_print("Checking for unicode with ..\%c0\%af..\n","h"); foreach(@vuln) { my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if ($sock) { $buff = ""; $current = $_; if($host_resolves == 1) { print $sock "GET http://$host/$current/..\%c0\%af../..\%c0\%af../..\%c0\%af../..\%c0\%af../..\%c0\%af../winnt/system32/cmd.exe\?\/c+bla HTTP/1.0\n\n"; } else { print $sock "GET /$current/..\%c0\%af../..\%c0\%af../..\%c0\%af../..\%c0\%af../..\%c0\%af../winnt/system32/cmd.exe\?\/c+bla HTTP/1.0\n\n"; } sysread($sock, $buff, 9000); close($sock); if ($buff =~ /Content-Type: application\/octet-stream/) { log_print("Unicode vulnerable with $current and ..\%c0\%af.. \n","c"); } close($sock); } } undef($current); } sub unicode2 { log_print("Checking for unicode with ..\%255c..\n","h"); foreach(@vuln) { my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if ($sock) { $buff = ""; $current = $_; if($host_resolves == 1) { print $sock "GET http://$host/$current/..\%255c../..\%255c../..\%255c../..\%255c../..\%255c../winnt/system32/cmd.exe\?\/c+bla HTTP/1.0\n\n"; } else { print $sock "GET /$current/..\%255c../..\%255c../..\%255c../..\%255c../..\%255c../winnt/system32/cmd.exe\?\/c+bla HTTP/1.0\n\n"; } sysread($sock, $buff, 9000); close($sock); if ($buff =~ /Content-Type: application\/octet-stream/) { log_print("Unicode vulnerable with $current and ..\%255c.. \n","c"); } close($sock); } } } sub nimda { my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if ($sock) { log_print("\nchecking for nimda infection\n","h"); log_print("----------------------------\n","h"); if($host_resolves == 1) { print $sock "GET http://$host/blaat HTTP/1.0\n\r\n\r"; } else { print $sock "GET /blaat HTTP/1.0\n\r\n\r"; } sleep(5); sysread($sock, $buff, 15000); if ($buff =~ /eml/ig) { log_print("eml found at $target, it's probably infected\n","c"); } close($sock); } header_reset(); } sub dns { log_print("Checking for DNS\n","h"); log_print("----------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => 53, Proto => 'tcp', Timeout => '5'); if ($sock) { $nsversion = `dig \@$target version.bind chaos txt`; ($temp, $bind) = split(/\"/, $nsversion); $temp = ""; log_print("Bindversion: $bind\n\n","c") unless !$bind; if(!$bind) { log_print("Name daemon is running but returned no version\n\n","c"); } } else { log_print("No DNS\n\n","i"); } close($sock); } sub ssh { log_print("Checking for SSH\n","h"); log_print("----------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => 22, Proto => 'tcp', Timeout => '5'); if(!$sock) { log_print("No SSH\n\n","i"); } while($sock) { sleep(5); $cnt = sysread($sock, $buff, 10000); if(!$cnt) { log_print("huh, fscking TCP wrappers, I died\n\n","i"); last; } log_print("$buff\n","c"); close($sock); last; } } sub netscape { if ($httpversion =~ /Netscape/) { @netscape = ('/?wp-cs-dump','?PageServices'); foreach(@netscape) { my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if (!$sock) { log_print("Webserver died?\n\n","i"); } while($sock) { if($host_resolves == 1) { print $sock "GET http://$host/$_ HTTP/1.0\r\n\r\n"; } else { print $sock "GET /$_ HTTP/1.0\r\n\r\n"; } $cnt = sysread($sock, $buff, 15000); if (!$cnt) { log_print("Webserver died?\n\n","i"); close($sock); last; } if ($buff =~ /200 OK/) { log_print("$_ found\!\n* Netscape $_ bug, try http://www.somehost.com/$_\n","c"); } } } } } sub ftp { log_print("\nChecking for FTP server\n","h"); log_print("-----------------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => 21, Proto => 'tcp', Timeout => '5'); if (!$sock) { log_print("No FTP server\n\n","i"); } while($sock) { print $sock "user anonymous\r\n"; sleep(2); $cnt = sysread($sock, $buff, 10000); if(!$cnt) { log_print("huh, fscking TCP wrappers, I died\n\n","i"); last; } undef($cnt); log_print("FTP Server Found:\n$buff\n","c"); print $sock "pass bla\@bla.com\r\n"; sleep(2); $cnt = sysread($sock, $buff, 1000); if(!$cnt) { last; } if ($buff =~ /230/) { log_print("Anonymous login allowed\!\n\n","c"); log_print("Checking for upload/ directory\n\n","h"); print $sock "CWD upload\r\n"; sleep(2); undef($cnt); $cnt = sysread($sock, $buff, 1000); print $buff,"\n"; if(!$cnt){ last; } if ($buff =~ /250/) { log_print("Got it... checking write possibilities\n\n","c"); print $sock "STOR hackbotwashere.bla\r\n"; sleep(2); $cnt = sysread($sock, $buff, 100); if ($buff =~ /553/){ log_print("nope, no write-access\n\n","c"); } else { log_print("yup... write-access\n\n","c"); } } } else { log_print("Anonymous login NOT allowed\n\n","c"); } close($sock); last; } } sub GetRange { $start = $ARGV[0]; $end = $ARGV[1]; if ($start=~/\*/){ @target=split/\./,$start; $start= ( &genipstart ); $end= ( &genipend); } ($ippart, $bit) = split(/\//,$start); #CIDR if($bit ne "") { ($a,$b,$c,$d) = split(/\./,$ippart); if ($bit <= 23) { die "Error: CIDR Mask < /24 currently unsupported.\n"; } elsif ($bit >= 31) { die "Error: CIDR Mask '$bit' is invalid.\n"; } $prefix = "$a.$b.$c."; $network = $d; $nhosts = (2 ** (32 - $bit)); $netmask = (256 - $nhosts); unless ($netmask > 0 && $netmask / $nhosts) { die "Invalid Network: Netmask $netmask, Hosts $nhosts\n" unless($netmask eq 0); } $start=$ippart; $end="$prefix".($nhosts + $network - 1); } if($start ne "" && $end eq "") { $end=$start; } if($start eq "" || $end eq "" ) { &InputError; }; @IPstart = split(/\./,$start); @IPend = split(/\./,$end); &Check_Start_and_EndIP; #converts "short" (dotted) IPs to "long" (undotted) IPs $IPstart = (($IPstart[0]*16777216)+($IPstart[1]*65536)+($IPstart[2]*256)+$IPstart[3]); $IPend = (($IPend[0]*16777216)+($IPend[1]*65536)+($IPend[2]*256)+$IPend[3]); if($IPend < $IPstart) { die "Can't scan backwards"; } $CountIp = $IPstart; $EndIp = $IPend+1; while($CountIp ne $EndIp) { @Class = &GetIP($CountIp); push(@targetlist, "$Class[1]\.$Class[2]\.$Class[3]\.$Class[4]"); $CountIp++; } } sub GetIP{ # converts "long" (undotted) IPs into "short" (dotted) IPs my($ip) = @_; $Class[1] = int ( $ip / 256**3); $Class[2] = int ( $ip % 256**3 / 256**2 ); $Class[3] = int ( $ip % 256**3 % 256**2 / 256**1 ); $Class[4] = int ( $ip % 256**3 % 256**2 % 256**1 ); @Class; } sub InputError { print "need [starting IP] [ending IP]\n\n"; die "Wrong input"; } sub Check_Start_and_EndIP{ if (!&check_ip($start)) { print "\nStarting IP is not valid\n"; die "Exiting on bad starting IP"; } if (!&check_ip($end)) { print "\nEnding IP is not valid\n"; die "Exiting on bad ending IP"; } } sub genipstart { for(@target){ if( $_=~/\*/){ push(@tmp, 0);} else {push(@tmp, $_);} } "$tmp[0].$tmp[1].$tmp[2].$tmp[3]" } sub genipend { for(@target){if( $_=~/\*/){ push(@tmp2, 255);} else {push(@tmp2, $_);} } "$tmp2[0].$tmp2[1].$tmp2[2].$tmp2[3]" } sub log_print{ (my $logstring, $_ )= @_; Msg_Indexer:{ /h/ and header($logstring), last Msg_Indexer; /c/ and critical($logstring), last Msg_Indexer; /i/ and info($logstring), last Msg_Indexer; /d/ and debug($logstring), last Msg_Indexer; final_print ("Def.:$logstring"); } } sub header{ if($opt_l =~ /[d]/){$header.="header:\t";} $header.=shift; } sub header_reset{ undef $header; } sub critical{ final_print("$header"); undef $header; if($opt_l =~ /[d]/){ final_print("critic:\t".shift) }else { final_print(shift); } } sub info{ if($opt_l =~ /[vd]/){ final_print($header); undef $header; if($opt_l =~ /[d]/){ final_print("info:\t".shift) } else{ final_print(shift) } } } sub debug { if($opt_l =~ /[d]/){ final_print("$header"); undef $header; final_print("debug:\t".shift); } } sub final_print{ my $logstring = shift; if($opt_O){ open LOGFILE, ">>$opt_O"; } else { open LOGFILE, ">>output.$host"; } print LOGFILE "$logstring"; print("$logstring") unless($noprint); close LOGFILE; } sub telnetfprint { if($telnet ne "0") { log_print("Trying simple Telnet fingerprint\n","h"); log_print("--------------------------------\n","h"); if (!-e $fingerprintdb) { log_print("HUH db not found, it should be in $fingerprintdb\n","c"); log_print("Skipping Telnet fingerprint\n","c"); $nofp = 1; } my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => 23, Proto => 'tcp', Timeout => '5') unless($nofp); undef($fingerprint); undef($description); undef($return); undef($submitter); if(!$sock) { log_print("No telnet\n","i") unless($nofp); } while($sock) { sleep(3); $cnt = sysread($sock, $buff, 14); if(!$cnt) { log_print("Hmmm, probably TCP wrappers\n","i") unless($nofp); last; } @rets = split(//, $buff); foreach $currentret (@rets){ $fingerprint = $fingerprint . ord($currentret); } close($sock); log_print("Possible OS's\n\n","h"); log_print("Fingerprint:\t\t\t$fingerprint\n","c") unless($nofp); last; } if($fingerprint) { open FINGERPRINTDB, "<$fingerprintdb" || last("No fingerprint database, should be /usr/pkg/share/hackbot/fingerprint.db\n"); while() { ($description, $return, $submitter) = split(/\!/, $_); if("$fingerprint" eq "$return") { $hit = 1; log_print("Description:\t\t\t$description\n","c") unless($nofp); chomp($submitter); log_print("Fingerprint submission by:\t$submitter\n\n","c") unless($nofp); } } close FINGERPRINTDB; if(!$hit) { log_print("Fingerprint not found in database. If you know what it is please\nsubmit it to fingerprint\@obit.nl\n","c") unless($nofp); undef($nofp); } } } } sub ident { log_print("Identd\n","h"); log_print("------\n","h"); my $sock = new IO::Socket::INET( PeerAddr => $target, PeerPort => '113', Proto => 'tcp', Timeout => '5' ); if ($sock) { # hmmz we got signal, why not use the same socket for getting the user of ident ($lp,undef) = unpack_sockaddr_in(getsockname($sock)) ; #get source port of local conection. print $sock "113,$lp\r\n"; sysread($sock, $buff, 50); (undef, undef, undef, $undef) = split (/:/, $buff); log_print ("Port\tState\tService\tOwner\n","h"); log_print ("----\t-----\t-------\t-----\n","h"); log_print ("113\tOpen\tident\t$undef","c"); close($sock); undef $lp; &full_identd_scan; } else { # skip rest of tests.. no identd no glory log_print("No Identd on $target, skipping full identd scan\n\n","i"); } }; sub full_identd_scan { # full ident scan first setup target service. if it exists check ident for owner # hashed for easy maintanance. %ports_and_servicenames = ( 21 => "ftp", 23 => "telnet", 25 => "mail", 80 => "www", 110 => "pop3" ); #todo sorting order. so output will be incremental. # All your ports are belong to us! while (($identport, $service) = each(%ports_and_servicenames)) # its geting hard to come up with usefull variable names these days { my $sock = new IO::Socket::INET( PeerAddr => $target, PeerPort => $identport, Proto => 'tcp', Timeout => '5' ); if(!$sock and $identport eq "23") { $telnet = "0"; } if ($sock) { #And now for something completely similar. # setup sock2 my $sock2 = new IO::Socket::INET( PeerAddr => $target, PeerPort => '113', Proto => 'tcp', Timeout => '5' ); ($lp,undef) = unpack_sockaddr_in(getsockname($sock)); print $sock2 "$identport,$lp\r\n"; sysread($sock2, $buff2, 50); if ($buff2 =~ /ERROR/) { log_print ("$identport\tError\t$service\tError\n","c"); } else { #undef defined! (undef, undef, undef, $undef) = split (/:/, $buff2); # third entry is systype, 99,9% its UNIX) log_print ("$identport\tOpen\t$service\t$undef","c"); undef $buff;undef $buff2;undef $lp;undef $undef; close($sock);#undef undef undef... and undef. close($sock2);#today is definetly my undef day. #todo code cleanup ;) } } else { log_print ("$identport\tClosed\t$service\t---\n","i"); } } log_print("\n","c"); } sub whois { @RESERVEDA = ('0','1','2','5','7','10','23','27','31','36','37','39','41','42','58','59','60', '69','70','71','72','73','74','75','76','77','78','79','82','83','84', '85','86','87','88','89','90','91','92','93','94','95','96','97','98', '99','100','101','102','103','104','105','106','107','108','109','110', '111','112','113','114','115','116','117','118','119','120','121','122', '123','124','125','126','127','197','221','222','223','224','225','226', '227','228','229','230','231','232','233','234','235','236','237','238','239', '240','241','242','243','244','245','246','247','248','249','250','251','252', '253','254','255'); @RESERVEDB = ('172.16','172.17','172.18','172.19','172.20','172.21','172.22','172.23', '172.24','172.25','172.26','172.27','172.28','172.29','172.30','172.31', '192.168','169.254'); @RIPE = ('62','80','81','193','194','195','212','213','217'); @ARIN = ('24','63','64','65','66','67','68','199','200','204','205','206','207', '208','209','216'); @APNIC = ('61','202','203','210','211','218','219','220'); # determine range to be RESERVED, RIPE, ARIN or APNIC ($firstoct, $secoct) = split(/\./, $target); if($ipmap = grep(/$firstoct!/, @RESERVEDA) or $ipmap = grep(/$firstoct\.$secoct/, @RESERVEDB)) { log_print "reserved by IANA\n","i"; $IANA = 1; } elsif ($ipmap = grep(/$firstoct/, @RIPE)) { log_print("RIPE registrar\n","i"); $RIPE = 1; } elsif ($ipmap = grep(/$firstoct/, @ARIN)) { log_print("ARIN registrar\n","i"); $ARIN = 1; } elsif ($ipmap = grep(/$firstoct/, @APNIC)) { log_print("APNIC registrar\n","i"); $APNIC = 1; } else { log_print("Don't know where to search whois data, could be anywhere, canceling whois checkup\n\n","c"); $IANA = 1; } if(!$IANA) { if($RIPE) { &ripe; } elsif($APNIC) { &apnic; } elsif($ARIN) { &arin; } undef($IANA); } } sub ripe { log_print("Checking Whois info \@RIPE\n","h"); log_print("-------------------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => 'whois.ripe.net', PeerPort => 43, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "$target\n"; sleep(5); sysread($sock, $buff, 15000); log_print("$buff\n","d"); close($sock); } ($foobar, $inetnum) = split(/inetnum\:\s/, $buff); ($inetnum, $foobar) = split(/\n/, $inetnum); ($foobar, $netname) = split(/netname\:\s/, $buff); ($netname, $foobar) = split(/\n/, $netname); ($foobar, $descr) = split(/descr\:\s/, $buff); ($descr, $foobar) = split(/\n/, $descr); $descr =~ s/^\s{2}//; ($foobar, $country) = split(/country\:\s/, $buff); ($country, $foobar) = split(/\n/, $country); ($foobar, $adminc) = split(/admin\-c\:\s/, $buff); ($adminc, $foobar) = split(/\n/, $adminc); if($adminc) { my $sock = new IO::Socket::INET (PeerAddr => 'whois.ripe.net', PeerPort => 43, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "$adminc\n"; sleep(5); sysread($sock, $buff, 1500); log_print("$buff\n","d"); close($sock); } } ($foobar, $email) = split(/e\-mail\:\s/, $buff); ($email, $foobar) = split(/\n/, $email); $email =~ s/^\s//; log_print("Range:\t\t$inetnum\n","c") unless !$inetnum; log_print("Netname:\t$netname\n","c") unless !$netname; log_print("Description:\t$descr\n","c") unless !$descr; log_print("Country:\t$country\n","c") unless !$country; log_print("Admin-C:\t$adminc\n","c") unless !$adminc; log_print("Email:\t\t$email\n\n","c") unless !$email; if (!$inetnum && !$netname && !$descr && !$country && !$adminc && !$email) { log_print("RIPE could not be reached or no information was returned\n\n","c"); } undef($RIPE); undef($inetnum); undef($netname); undef($descr); undef($country); undef($adminc); undef($email); undef($foobar); } sub arin { log_print("Checking Whois info \@ARIN\n","h"); log_print("--------------------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => 'whois.arin.net', PeerPort => 43, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "$target\n"; sleep(3); sysread($sock, $buff, 5000); log_print("$buff\n","d"); ($temp, $netrange) = split(/NetRange\:(.*)/, $buff); log_print("Netrange: $netrange\n","c") unless !$netrange; ($temp, $netname) = split(/NetName\:(.*)/, $buff); log_print("Netname: $netname\n","c") unless !$netname; ($temp, $comment) = split(/Comment\:(.*)/, $buff); log_print("Comment: $comment\n","c") unless !$comment; ($temp, $handle) = split(/TechHandle\:(.*)/, $buff); log_print("TechHandle: $handle\n","c") unless !$handle; ($temp, $email) = split(/TechEmail\:(.*)/, $buff); log_print("TechEmail: $email\n","c") unless !$email; } } sub apnic { log_print("Checking Whois info \@APNIC\n","h"); log_print("--------------------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => 'whois.apnic.net', PeerPort => 43, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "$target\n"; sleep(5); sysread($sock, $buff, 15000); log_print("$buff\n","d"); close($sock); } ($foobar, $inetnum) = split(/inetnum\:\s/, $buff); ($inetnum, $foobar) = split(/\n/, $inetnum); ($foobar, $netname) = split(/netname\:\s/, $buff); ($netname, $foobar) = split(/\n/, $netname); ($foobar, $descr) = split(/descr\:\s/, $buff); ($descr, $foobar) = split(/\n/, $descr); $descr =~ s/^\s{2}//; ($foobar, $country) = split(/country\:\s/, $buff); ($country, $foobar) = split(/\n/, $country); ($foobar, $adminc) = split(/admin\-c\:\s/, $buff); ($adminc, $foobar) = split(/\n/, $adminc); if($adminc) { my $sock = new IO::Socket::INET (PeerAddr => 'whois.apnic.net', PeerPort => 43, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "$adminc\n"; sleep(5); sysread($sock, $buff, 1500); log_print("$buff\n","d"); close($sock); } } ($foobar, $email) = split(/e\-mail\:\s/, $buff); ($email, $foobar) = split(/\n/, $email); $email =~ s/^\s//; log_print("Range:\t\t$inetnum\n","c"); log_print("Netname:\t$netname\n","c"); log_print("Description:\t$descr\n","c"); log_print("Country:\t$country\n","c"); log_print("Admin-C:\t$adminc\n","c"); log_print("Email:\t\t$email\n\n","c") unless(!$email); undef($APNIC); undef($inetnum); undef($netname); undef($descr); undef($country); undef($adminc); undef($email); undef($foobar); } sub modphpssl($) { my $versionstring = shift; # bad apache check $badapachenotification = "Evil buggy Apache found!\nSeveral vulnerabilities, check http://www.apache.org\n\n"; if($versionstring =~ /Apache\/1.3/) { ($temp1, $temp2) = split(/Apache\/1\.3\./, $versionstring); ($temp2, $temp1) = split(/\s/, $temp2); if($temp2 lt "27") { log_print("$badapachenotification","c"); undef($temp1); undef($temp2); } } if($versionstring =~ /Apache\/1.2/) { log_print("$badapachenotification","c"); } if($versionstring =~ /Apache\/2.0./) { ($temp1, $temp2) = split(/Apache\/2\.0\./, $versionstring); ($temp2, $temp1) = split(/\s/, $temp2); if($temp2 lt "43") { log_print("$badapachenotification","c"); undef($temp1); undef($temp2); } } # end bad apache check if($versionstring =~ /mod_ssl/) { ($temp1, $temp2) = split(/mod_ssl\//, $versionstring); ($modsslversion, $temp1) = split(/\s/, $temp2); log_print("mod_ssl $modsslversion found\n","c"); } if($versionstring =~ /PHP/) { ($temp2, $temp2) = split(/PHP\//, $versionstring); ($phpversion, $temp1) = split(/\s/, $temp2); log_print("PHP $phpversion found\n","c"); } log_print("\n","c"); undef($versionstring); undef($temp1); undef($temp2); undef($modsslversion); undef($phpversion); } sub isapi($) { my $target = shift; my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "GET /null.htr HTTP/1.0\r\n\r\n"; sleep(3); sysread($sock, $buff, 1000); if($buff =~ /Error: The requested file could not be found./) { log_print("* HTR ISAPI filter mapped\n","c"); log_print("* http://online.securityfocus.com/bid/4474/info/\n\n","c"); close($sock); } } my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "GET /null.printer HTTP/1.0\r\n\r\n"; sleep(3); sysread($sock, $buff, 1000); if($buff =~ /Error in web printer install/) { log_print("* Printer ISAPI filter mapped\n","c"); log_print("* http://online.securityfocus.com/bid/2674/info/\n\n","c"); close($sock); } } } sub propfind($) { my $target = shift; my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => $port, Proto => 'tcp', Timeout => '5'); if($sock) { if($host_resolves == 1) { print $sock "PROPFIND http://$host/ HTTP/1.1 Host: Content-Length: 0\r\n\r\n\r\n\r\n"; } else { print $sock "PROPFIND / HTTP/1.1 Host: Content-Length: 0\r\n\r\n\r\n\r\n"; } sleep(3); sysread($sock, $buff, 1000); if($buff =~ /207 Multi-Status/) { log_print("* PROPFIND Information\n","c"); log_print("* http://www.nextgenss.com/advisories/iisip.txt\n","c"); ($temp, $return) = split(/http\:\/\//, $buff); ($return, $temp) = split(/\//, $return); ($temp, $datereturn) = split(/rfc1123\"\>/, $buff); ($datereturn, $temp) = split(/\<\/a/, $datereturn); log_print("* Server gave host/ip address: $return\n","c"); log_print("* Server gave back date: $datereturn\n\n","c"); undef($temp); undef($return); undef($datereturn); } } close($sock); } sub endbanner { log_print("--->\n","c"); log_print("- All scans done. Hackbot $version -\n","c"); log_print("---> Exiting.\n","c"); } sub spamcheck { if (&check_ip($target)) { ($a, $b, $c, $d) = split(/\./, $target); $spamcop = ".bl.spamcop.net"; $spamhost = $d . "." . $c . "." . $b . "." . $a . $spamcop unless $a == "10"; if($spamhost) { my $spammer = gethost($spamhost); if($spammer) { log_print("This is a known spammer\!\!, thank you spamcop \(www.spamcop.net\)\n\n","c"); } if(!$spammer) { log_print("It is not a known spammer, thank you spamcop \(www.spamcop.net\)\n\n","i"); } } else { log_print("Not doing spamcop check on a private address\n","d"); } } undef($spammer); undef($spamhost); } sub proxytest { $proxytest = $_[0]; $target = $_[1]; my $sock = new IO::Socket::INET (PeerAddr => $proxytest, PeerPort => $proxyport, Proto => 'tcp', Timeout => '10'); if($sock) { log_print("Proxy responds.. now lets test if it can be used.\n\n","c"); $responds = 1; } else { log_print("Proxy connect failed, scanning without proxy\n\n","c"); undef($proxytest); undef($proxy); undef($proxyport); } if($responds) { print $sock "GET http://$target/_bla_\r\n\r\n"; sleep(5); sysread($sock, $buff, 1000); if($buff =~ /404/) { log_print("Proxying is allowed\n\n","c"); } else { log_print("Proxying is not allowed, will continue scan without using a proxy\n\n","c"); undef($proxy); undef($proxyport); undef($proxytest); } } } sub xcheck { log_print("\nChecking if we are allowed to connect to X\n","h"); log_print("------------------------------------------\n","h"); my $sock = new IO::Socket::INET (PeerAddr => $target, PeerPort => '6000', Proto => 'tcp', Timeout => '5'); if($sock) { print $sock "\x6c\x00\x0b\x00\x00\x00\x00\x00\x00\x00\x00\x00"; sleep(3); sysread($sock, $buff, 10000); if($buff !~ /protocol/i && $buff !~ /autho/i) { log_print("Allowed to connect!\n\n","c"); } else { log_print("Connection not allowed\n\n","i"); } } if(!$sock) { log_print("No X\n\n","i"); } }