#!/usr/bin/perl
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#
#  ************************************************** !!! WARNING !!! ***********************************************************
#  *                                            FOR SECURITY TESTiNG ONLY!                                                      *
#  ******************************************************************************************************************************
#  * By using this code you agree that I makes no warranties or representations, express or implied, about the                  *
#  * accuracy, timeliness or completeness of this, including without limitations the implied warranties of                      *
#  * merchantability and fitness for a particular purpose.                                                                      *
#  * I makes NO Warranty of non-infringement. This code may contain technical inaccuracies or typographical errors.             *
#  * This code can never be copyrighted or owned by any commercial company, under no circumstances what so ever.                *
#  * but can be use for as long the developer, are giving explicit approval of the usage, and the user understand               *
#  * and approve of all the parts written in this notice.                                                                       *
#  * This program may NOT be used by any Danish company, unless explicit written permission from the developer .                *
#  * Neither myself nor any of my Affiliates shall be liable for any direct, incidental, consequential, indirect                *
#  * or punitive damages arising out of access to, inability to access, or any use of the content of this code,                 *
#  * including without limitation any PC, other equipment or other property, even if I am Expressly advised of                  *
#  * the possibility of such damages. I DO NOT encourage criminal activities. If you use this code or commit                    *
#  * criminal acts with it, then you are solely responsible for your own actions and by use, downloading,transferring,          *
#  * and/or reading anything from this code you are considered to have accepted the terms and conditions and have read          *
#  * this disclaimer. Once again this code is for penetration testing purposes only.                                            *
#  ******************************************************************************************************************************
# 
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#
#  Author/Developer:  Dennis Rand - CIRT.DK
#  Website:           http://www.cirt.dk
#  Copyright:         (c)2006 by Dennis Rand
#  Remember:          This program may NOT be used, published or downloaded by any Danish company, unless explicit written permission.
#                     This would be violation of the law on intellectual property rights, and legal actions will be taken.
#  Remember:
#                     Features / Bugs should be reported to Dennis Rand for fix or creation
#                     All ideas are higly welcome to make this as complete as possible.
#                     And remember this may never be used to earn money, so KEEP IT FREE.
#
# What this tool does:
# "Fuzzing" is an automated software testing technique that generates and submits random or sequential data to various 
#  areas of an application in an attempt to uncover security vulnerabilities. 
#  For example, when searching for buffer overflows, a tester can simply generate data of various sizes and send it to one 
#  of the application entry points to observe how the application handles it.
#
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
# 
#  Version 1.0
#    This is the first version, and it is damn simple, and will take long time, but I have had 
#    some luck with it.
#
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#
#  Usage example (string overflow):
#     fuzz.pl -host 192.168.1.2 -port 80 -type string -load template.txt
#
#  Making the template:
#     Make a file where you can put any request into, and the place you want to Fuzz insert the tag <FUZZER>
#
#     if you need to count size of data you eg. like in a POST request of a HTTP server, use the tags <COUNT>data<COUNT>
#     and <SIZE>, it could be done as follows:
#
#        POST /cgi-sys/FormMail.cgi HTTP/1.1
#        Host: 127.0.0.1
#        User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-US; rv:1.7.5) Gecko/20041128 Firefox/1.0 (Debian package 1.0-4)
#        Keep-Alive: 300
#        Connection: keep-alive
#        Referer: http://127.0.0.1/
#        Content-Type: application/x-www-form-urlencoded
#        Content-Length: <SIZE>
#
#        <COUNT>recipient=test%40127.0.0.1&subject=Fuzzing&Name=test&email=test%40localhost&request=test<FUZZER>&redirect=/<COUNT>
#
#        You can also use hex values like \x41 or 0x41 values in the template if the protocol is binary
#
#
#

use IO::Socket;
use Getopt::Long;
use Algorithm::GenerateSequence;
use Net::SSLeay::Handle qw/shutdown/;
use Time::HiRes qw(usleep);


$version         = "Version 1.0";
$copyright       = "(c)2006 by Dennis Rand - CIRT.DK";
$host            = "127.0.0.1";
$port            = "80";
$timeout         = "15";
$delay           = "0";
@overflowstrings = ("A" x 33, "A" x 254, "A" x 255, "A" x 511,"A" x 1023, "A" x 1024, "A" x 2047, "A" x 2048, "A" x 4096, "A" x 5000, "A" x 10000, "A" x 20000, "A" x 30000, "A" x 40000, "A" x 65530, "A" x 65536, "A" x 75536);
@formatstrings   = ("%s" x 4, "%s" x 8, "%s" x 15, "%s" x 30, "%x" x 1024, "%n" x 1025 , "%s" x 2048, "%s%n%x%d" x 5000, "%s" x 30000, "%s" x 40000, "%.1024d", "%.2048d", "%.4096d", "%.8200d", "%99999999999s", "%99999999999d", "%99999999999x", "%99999999999n", "%99999999999s" x 1000, "%99999999999d" x 1000, "%99999999999x" x 1000, "%99999999999n" x 1000, "%08x" x 100, "%%20s" x 1000,"%%20x" x 1000,"%%20n" x 1000,"%%20d" x 1000, "%#0123456x%08x%x%s%p%n%d%o%u%c%h%l%q%j%z%Z%t%i%e%g%f%a%C%S%08x%%#0123456x%%x%%s%%p%%n%%d%%o%%u%%c%%h%%l%%q%%j%%z%%Z%%t%%i%%e%%g%%f%%a%%C%%S%%08x");
@specchars       = ("\x00","\x01","\x02","\x03","\x04","\x05","\x06","\x07","\x08","\x09","\x0A","\x0B","\x0C","\x0D","\x0E","\x0F","\x10","\x11","\x12","\x13","\x14","\x15","\x16","\x17","\x18","\x19","\x1A","\x1B","\x1C","\x1D","\x1E","\x1F","\x20","\x21","\x22","\x23","\x24","\x25","\x26","\x27","\x28","\x29","\x2A","\x2B","\x2C","\x2D","\x2E","\x2F","\x30","\x3A","\x3B","\x3C","\x3D","\x3E","\x3F","\x40","\x41","\x5B","\x5C","\x5D","\x5E","\x5F","\x60", "\x7B","\x7C","\x7D","\x7E","\x7F","\x80","\x81","\x82","\x83","\x84","\x85","\x86","\x87","\x88","\x89","\x8A","\x8B","\x8C","\x8D","\x8E","\x8F","\x90","\x91","\x92","\x93","\x94","\x95","\x96","\x97","\x98","\x99","\x9A","\x9B","\x9C","\x9D","\x9E","\x9F","\xA0","\xA1","\xA2","\xA3","\xA4","\xA5","\xA6","\xA7","\xA8","\xA9","\xAA","\xAB","\xAC","\xAD","\xAE","\xAF","\xB0","\xB1","\xB2","\xB3","\xB4","\xB5","\xB6","\xB7","\xB8","\xB9","\xBA","\xBB","\xBC","\xBD","\xBE","\xBF","\xC0","\xC1","\xC2","\xC3","\xC4","\xC5","\xC6","\xC7","\xC8","\xC9","\xCA","\xCB","\xCC","\xCD","\xCE","\xCF","\xD0","\xD1","\xD2","\xD3","\xD4","\xD5","\xD6","\xD7","\xD8","\xD9","\xDA","\xDB","\xDC","\xDD","\xDE","\xDF","\xE0","\xE1","\xE2","\xE3","\xE4","\xE5","\xE6","\xE7","\xE8","\xE9","\xEA","\xEB","\xEC","\xED","\xEE","\xEF","\xF0","\xF1","\xF2","\xF3","\xF4","\xF5","\xF6","\xF7","\xF8","\xF9","\xFA","\xFB","\xFC","\xFD","\xFE","\xFF");
$count           = 0;
$proto           = "tcp";
$delay           = "50000"; # Half a milisecond delay as standard between each test.
$wait            = "500000"; # Half a second
$noresponse      = ": The server answers very slow or is dead ==> Retry number: ";
$brute;
$template_fuzz;


GetOptions( 

        "host=s"          => \$host,
        "port=i"          => \$port,
        "ssl"             => \$ssl,
        "timeout=i"       => \$timeout,
        "delay=i"         => \$delay,
        "minimum=i"       => \$inc_minimum,
        "maximum=i"       => \$inc_maximum,
        "protocol=s"      => \$proto,
        "wait=i"          => \$wait,
        "load=s"          => \$template,   
        "type=s"          => \$overflowtype,
        "noupdate"        => \$noupdate,
        
        "help|?"          => sub { 
        print "\n" x 2; 
        print "\t\too00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00\n";
        print "\t\to  Simple TCP/UDP Protocol Fuzzer $version  o\n";
        print "\t\t0  ************* !!! WARNING !!! ************  0\n";
        print "\t\t0  ******* FOR PENETRATION USE ONLY *********  0\n";
        print "\t\t0  ******************************************  0\n";
        print "\t\to       $copyright       o\n";
        print "\t\too00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00\n\n";
        print "\t\t Basic settings\r\n";
        print "\t\t  -host\t\t Set the host ip or hostname to scan\r\n";
        print "\t\t  -port\t\t Set the port where the webserver are located\r\n";
        print "\t\t  -protocol\t Set if connection is TCP or UDP\r\n";
        print "\t\t  -timeout\t Set a maximum timeout for each try\r\n";
        print "\t\t  -delay\t Set a delay between each attempt\r\n";
        print "\t\t  -wait\t\t Set the wait time after data sent before killing connection\r\n";
        print "\t\t  -load\t\t Load template file\r\n";
        print "\t\t  -ssl\t\t Run against SSL ports\r\n";
        print "\t\t  -noupdate\t Do not check for updates of Protocol Fuzzer\r\n";
        print "\r\n";
        print "\t\t  -type\t\t Use: string, format or special\r\n";
        print "\t\t  -minimum\t Set the min chars for special\r\n";
        print "\t\t  -maximum\t Set the max chars for special\r\n\r\n\r\n";

        exit;
        }
);

   if ($port >= 0 and $port <= 65535){} else { print "Error: Port number invalid, please use from 1-65535\r\n"; exit;}
   if (($inc_minimum) > ($inc_maximum)) {print "Error: The Maximum are larger then the Minimum\r\n"; exit;} 
   if (!$inc_minimum){$inc_minimum = "1"};
   if (!$inc_maximum){$inc_maximum = "1"};

#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
# Catch Interupt - CTRL + C

sub catchInterrupt {
  $SIG{INT} = sub {exit;};
  print "\n\n ", "oo00" x 12, "\n [X] Interrupted\t\t\t - DONE\n ", "oo00" x 12, "\r\n\r\n";
  exit;
};

$SIG{INT} = \&catchInterrupt;

# verify that interrupt handler was installed properly

unless(defined($SIG{INT})){print "Unable to install signal handler, contact $copyright";}
unless($SIG{INT} == \&catchInterrupt){print "There was an unexpected error installing the signal handler, contact $copyright";}

print "\n\n\n oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00\n";
print " o  Simple TCP/UDP Protocol Fuzzer $version  o\n";
print " 0  ************* !!! WARNING !!! ************  0\n";
print " 0  ******* FOR PENETRATION USE ONLY *********  0\n";
print " 0  ******************************************  0\n";
print " o       $copyright       o\n";
print " oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00\n\n";
print " ","oo00" x 12, "\r\n\r\n [X] Host: $host\r\n [X] Port: $port\r\n [X] Protocol: $proto \r\n";

#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
# Check for updates at www.cirt.dk
sub ChkUpdatesCon
{
   $| = 1;
   $updates = IO::Socket::INET->new(
   Proto    => "tcp",
   PeerAddr => "www.cirt.dk", 
   PeerPort => "80", 
   Reuse    => 1,
   Timeout  => 10,) || print "\t\t - NO ROUTE TO WWW.CIRT.DK";
}  

print " [X] Checking for updates";
if(!$noupdate)
{
   ChkUpdatesCon();
   $response = undef;
   print $updates "GET /tools/fuzzer/fz_update.txt HTTP/1.0\r\nHost: www.cirt.dk\r\nUser-Agent: Mozilla/4.0 (Fuzzer Update Check)\r\n\r\n";
   while(<$updates>)
   {
      if(!defined($response)){$response = $_;}
      $result .= $_;
   }
   if ($result =~ m/200 OK/mgsi)
   {   
      if($result !~ m/$version/mgsi) 
      {
         ($result) = $result =~ m/Update_Info:\s+(.*)/;
         $result   =~ s/<CN>/\r\n\t/g;
         print "\t\t - FOUND\r\noo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00\r\nINFORMATION:\r\nCIRT.DK Simple TCP/UDP Protocol Fuzzer has been updated,\r\nget the latest version at www.cirt.dk\r\nUpdate includes following features: $result\r\nThe scan will continue in 5 seconds\r\noo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00oo00\r\n"; 
         close(updates); 
         sleep(5);
      }
      else
      {
         print "\t\t - NO UPDATES";
      }
   } 
}
else 
{
   print "\t\t - NO CHECK";
}
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
sub read_template
{
  foreach (split(/,/, $template))
   {
      print "\r\n [X] Loading Template";
      if (-f $_)
      {
         print "\t\t\t - DONE\n";
         print " [X] Starting Fuzzer\t\t\t - OK\n";
         open(_FILE, $_);
         while (<_FILE>)
         {
            $template_fuzz .= $_;
         }
         $template_fuzz =~ s/\\x(..)/pack("C",hex($1))/egi; # Converts if \x41
         $template_fuzz =~ s/0x(..)/pack("C",hex($1))/egi; # Converts if 0x41

         close(_FILE);
      }
      else
      { 
         print "\t\t\t - FAILED\n";
         print "     The template file you are trying to use: '$_' could not be found\n";
         exit;
      }
   }
}
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
read_template();
print " [X] Load Fuzzer with";
@choice = split(/,/, $overflowtype);
foreach $input (@choice)
{
   if    ($input eq "string")  {@do_choice = @overflowstrings;$inc_maximum = 1;$input_txt = "string";}
   elsif ($input eq "format")  {@do_choice = @formatstrings;$inc_maximum = 1;$input_txt = "format";}
   elsif ($input eq "special") {@do_choice = @specchars;$input_txt = "special";break;}      
   else 
   {
      print "\t\t - FAILED\n";
      print "     Error: You have to specify the -type with string, format or special\r\n\r\n"; exit;
   }
} 
print " \"$input_txt\" attack\t - OK\r\n";

$start_pos = ($inc_minimum - 1);
do
{
   my $len = $start_pos;
   my $gen = Algorithm::GenerateSequence->new(
   map {[@do_choice]} (0 .. $len)
   );

   local $" = "";
   while(my @c = $gen->next)
   {
      $fuzz        = $template_fuzz;
      $brute       = join("",@c);
      $log         = $brute;
      $fuzz        =~ s/<FUZZER>/$brute/g;
      ($counter)   = $fuzz =~ m/<COUNT>([^\]]*)<COUNT>/g;
      $fuzz        =~ s/<SIZE>/length($counter)/egi;
      $fuzz        =~ s/<COUNT>//egi;
      $log         =~ s/(.|\n)/sprintf("%02lx", ord $1)/eg;
      start_fuzzing();
      usleep($delay);
      $fuzz = "";
   }
   $start_pos++;
} until ($start_pos >= $inc_maximum);




#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
# The connection are setup here.
sub connection { 
   $| = 1;
   $remote  = IO::Socket::INET->new(
   Proto    => $proto,
   PeerAddr => $host, 
   PeerPort => $port, 
   Reuse    => 1,
   Timeout  => $timeout,);
}


#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
#ooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOOooOO
# Let the start_fuzzing begin
sub start_fuzzing
{
   $firsttimeout = 0;
   connection();
   while(!defined $remote)
   {
      connection();
      if(!defined $remote)
      {
         if($ssl)
         {
        $whattime = localtime;
            print STDERR "\r [X] $whattime$noresponse" . $failed++ ;
            sleep 5;
    $firsttimeout = 1;
         }
 else
 {
        $whattime = localtime;
            print STDERR "\r [X] $whattime$noresponse" . $failed++ ;
            sleep 5;
           $firsttimeout = 1;
         }
      }
   }
   $count++;   
   if($ssl)
   { 
      $ssl=1;
      eval 
      {
         tie(*SSL, "Net::SSLeay::Handle", $target,$port);
      };
      print SSL "";
      print SSL "$fuzz";
      usleep($wait);
      shutdown(\*SSL, 2);
   }
   else
   {
      print $remote "";
      print $remote "$fuzz";
      usleep($wait);
      shutdown($remote,2);
   }
   #Progressbar
   printf STDERR "\r [X] Running attack count \t\t - $count";
}
close($remote);
print "\r\n\r\n";
print " ","oo00" x 12, "\n [X] Scan complete\t\t\t - DONE\n ", "oo00" x 12, "\r\n\r\n";
