#!/usr/bin/perl
use IO::Socket;
use Net::hostent;
use Getopt::Std;


my $VERSION = "0.1";

my $brutefile = $ARGV[1];
if ($brutefile eq "") {
$brutefile="/usr/share/tftp-bruteforce/brutefile.txt";
}

my $max_processes = $ARGV[2];
if ($max_processes eq "") {
$max_processes = 150;
}


sub usage { # print a short 'usage` message and exit
  print "usage: perl $0  <tftpserver> <filelist> <maxprocesses> \n";
  print  "example  ./tftpbrute.pl 192.168.66.202 brutefile.txt 100 \n";
  exit;
}

use vars qw($opt_h ); # command line options


print "$0, $PgmName, V $VERSION \n";
  # handle the commandline options
  getopts('h');            # look for -h and -c
  $opt_h && usage;          # -h print usage message and exit
  
  (!$ARGV[0]) && usage;     # no server: print usage message and exit

  my $server = $ARGV[0];
  
 if ($server =~ /[a-zA-Z]/) {
  my $i = gethostbyname($server);
  $server = inet_ntoa($i);
}
 
  
  print "TFTP file word database: $brutefile \n";  
  print "TFTP server $server \n";
  print "Max processes $max_processes \n";
 
$timeout = 2;
$port = 69;
$retries=2;
 

my @pids;
my $npids=0;
 open( BRUTEFILE,  "<$brutefile") || die " Cannot open the  word file : $bruteyfile ! \n";
        chomp(@brutefile = <BRUTEFILE>);
close(BRUTEFILE);

	foreach $file (@brutefile)
	{
	my $pid;
	$pid=fork();
	if($pid>0){
		$npids++;
		print " Processes are: $npids\n" ;
		if($npids>=$max_processes){
			for(1..($max_processes)){
				my $wait_ret=wait();
				if($wait_ret>0){
					$npids--;
				}
			}
		}
		next;
	}elsif(undef $pid){
		print " Fork error!\n";
		exit(0);
	}else{
		local $SIG{'ALRM'} = sub { exit(0); };
		alarm 0;

	eval {
	
		tftp_brute($file);
	};  


		exit(0);
	}
}

for(1..$npids){
	my $wt=wait();
	if($wt==-1){
		print " is  $!\n";
		redo;
	}
}


	

	


	
sub tftp_brute {      
 
 my $file =shift;
 my $MAXLEN=2;
 my $op=01;
 my $mode = "netascii";

 
 
		my $count=$retries;
		my $pkt  = pack("n a* c a* c", $op, $file, 0, $mode, 0);
       if ( $count != 0 && $treturn !="03") {
             my $sock = IO::Socket::INET->new(Proto => 'udp');
             send($sock,$pkt,0,pack_sockaddr_in($port,inet_aton($server)));
             undef($treturn);
		     undef($rpkt);
        eval {
    local $SIG{ALRM} = \&timed_out;
    alarm $timeout;
    $sock->recv($rpkt, $MAXLEN);
    close $sock;
    alarm 0;
    
}  ;
    $count--;
@rets = split( //, $rpkt );
foreach $currentret (@rets) { $treturn .= ord($currentret); }
         
                 if ($treturn =="03") 
                 {
                     
                                                          
       print "*** Found  TFTP server remote filename : $file \n";    

                 return 1;
                 } 
                
       }
     $count=$retries; 
	
 
}  
