#!/usr/bin/perl -Tw
#
#################################
#
# Copyright (C) 2001, Jon Hart
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation; either version 2 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
#################################
#
#
# Used to send icmp packets of various types/codes to any host from any host
#
# Requires: Net::RawIP (www.cpan.org)
# root
#
#
# (jhart@ccs.neu.edu) work/school
# and/or
# (warchild@spoofed.org) home/play
#################################
use strict;
use diagnostics;
use Net::RawIP;
use Tie::RefHash;
use Getopt::Long;
$ENV{'PATH'} = "/usr/bin:/bin";
delete @ENV{qw(IFS CDPATH ENV BASH_ENV)};
# get our options in place
GetOptions( "src=s" => \(my $opt_saddr),
"dest=s" => \(my $opt_daddr),
"type=i" => \(my $opt_icmptype),
"code=i" => \(my $opt_icmpcode),
"num=i" => \(my $opt_num),
"delay=i" => \(my $opt_delay),
"help" => \(my $opt_help),
"debug" => \(my $opt_debug)) or die "$!\n";
for(1..($opt_num ? $opt_num : 5)) {
&send($opt_saddr, $opt_daddr);
#sleep($opt_delay ? $opt_delay : 1);
if( defined($opt_delay)) {
sleep($opt_delay);
} else {
sleep(1);
}
}
sub send {
my $packet = new Net::RawIP{icmp =>{}};
my %ip_hdr;
my %icmp_hdr = &icmp_gen;
$ip_hdr{saddr} = shift;
$ip_hdr{daddr} = shift;
$ip_hdr{tos} = 0;
$ip_hdr{ttl} = 255;
$ip_hdr{version} = 4;
$packet->set({ip => \%ip_hdr, icmp => \%icmp_hdr});
if (defined($opt_debug)) {
print "#"x20, "\n";
print "###IP Header###\n";
foreach (sort keys %ip_hdr) { print "$_ = $ip_hdr{$_}\n"; }
print "###ICMP Header###\n";
foreach (sort keys %icmp_hdr) { print "$_ = $icmp_hdr{$_}\n"; }
print "#"x20, "\n";
}
$packet->send;
}
sub icmp_gen {
# Net::RawIP requires at a minimum, one of the following:
# gateway (int)
# id (short) and sequence (short)
# mtu (short) and unused (short)
my %icmp_packet;
my %ip_header;
tie %icmp_packet, 'Tie::RefHash';
tie %ip_header, 'Tie::RefHash';
$icmp_packet{type} = $opt_icmptype ? $opt_icmptype : int rand(2**8);
$icmp_packet{code} = $opt_icmpcode ? $opt_icmpcode : int rand(2**8);
# generate the original IP header (128-bit) + 64-bit dgram
# the IP header doesn't have to make sense, it just has to be
# syntactically correct
#############################
# IP header
# int rand(5) might also work
#$ip_header{version} = substr(unpack("B32", pack("N", 2)), -4);
$ip_header{version} = 2;
# the size in 32-bit words. min size is 5, max is 6. pick one.
#$ip_header{ihl} = substr(unpack("B32", pack("N", 5 + int rand(2))), -4);
$ip_header{ihl} = 5 + int rand(2);
#$ip_header{tos} = substr(unpack("B32", pack("N", int rand(2**8))), -8);
$ip_header{tos} = int rand(2**8);
#$ip_header{tot_len} = substr(unpack("B32", pack("N", int rand(2**16))), -16);
$ip_header{tot_len} = int rand(2**16);
#$ip_header{id} = substr(unpack("B32", pack("N", int rand(2**16))), -16);
$ip_header{id} = int rand(2**16);
#$ip_header{frag_off} = substr(unpack("B32", pack("N", int rand(2**13))), -13);
$ip_header{frag_off} = int rand(2**13);
#$ip_header{ttl} = substr(unpack("B32", pack("N", int rand(2**8))), -8);
$ip_header{ttl} = int rand(2**8);
# either pick a random protocol
#$ip_header{protocol} = substr("B32", pack("N", int rand(2**8))), -8);
# or play nice and pick one of udp, tcp, icmp
$ip_header{protocol} = ("1", "6", "17")[int rand(3)];
# "the 16-bit ones complement of the ones complement of
# all 16-bit words in the header". sure.
#$ip_header{check} = substr(unpack("B32", pack("N", int rand(2**16))), -16);
# make up source/dest
$ip_header{saddr} = substr(unpack("B32", pack("N", int rand(2**32))), -32);
$ip_header{daddr} = substr(unpack("B32", pack("N", int rand(2**32))), -32);
my $ip_packet = new Net::RawIP;
$ip_packet->set({ip => %ip_header});
$icmp_packet{data} = \$ip_packet;
return %icmp_packet;
}