To follow on from yesterday's post, I did some more searching today and found a whole suite of Perl modules to assist in creating custom packets.
Patrice Auffret is a genius. This expandable module framework assists in crafting just about any type of packet you want simply by building the layers from the modules used. If a protocol doesn't exist, not to worry, you can create a new module that fits easily into the framework and continue testing.
Some of the more advance routines allow for device identification and automate the sending and receiving, but they also rely on Net::Libdnet which won't compile in Strawberry Perl for Windows for me. Not to worry, I simply use the Net::Pcap module to handle the sending and receiving of the frames I create with the Net::Frame library of modules.
The only thing that's missing is the nice wrapper script like Scapy (or Scaperl) that makes it an interactive tool. But with an interface as easy as:
#!/usr/bin/perl use strict; use warnings; # load modules we'll need for ICMPv6 ping use Net::Frame::Simple; use Net::Frame::Layer::ETH qw(:consts); use Net::Frame::Layer::IPv6 qw(:consts); use Net::Frame::Layer::ICMPv6 qw(:consts); use Net::Frame::Layer::ICMPv6::Echo; # create ethernet header my $ether = Net::Frame::Layer::ETH->new( src => '00:00:00:00:00:11', dst => 'ab:cd:ef:00:11:22', # Router MAC type => NF_ETH_TYPE_IPv6 ); # create IPv6 header my $ipv6 = Net::Frame::Layer::IPv6->new( src => '2001::1', dst => '2001:4860:800e::68', nextHeader => NF_IPv6_PROTOCOL_ICMPv6 ); # create ICMPv6 header my $icmpv6 = Net::Frame::Layer::ICMPv6->new( type => NF_ICMPv6_TYPE_ECHO_REQUEST, code => NF_ICMPv6_CODE_ZERO ); # create ICMPv6 echo request my $echo = Net::Frame::Layer::ICMPv6::Echo->new( payload => 'echo' ); # put it all together, this automatically # calculates and populates length and # checksum fields in all headers - SWEET! my $packet = Net::Frame::Simple->new( layers => [ $ether, $ipv6, $icmpv6, $echo] ); #################### # send with Net::Pcap use Net::Pcap qw(:functions); my %devinfo; my $err; my $interface = pcap_open($ARGV[0], 100, 0, 1000, \%devinfo, \$err); if (!defined($interface)) { printf "Unable to open adapter '%s'\n", $ARGV[0]; exit 1; } if (pcap_sendpacket($interface, $packet->raw) != 0) { printf "Error sending packet: %s\n", pcap_geterr($interface); exit 1; }
I think I'm good to go!
Even tcpdump thinks so:
tcpdump: listening on \Device\NPF_{12345678-ABCD} 19:36:29.686987 00:00:00:00:00:11 > ab:cd:ef:00:11:22, ethertype IPv6 (0x86dd), length 66: (hlim 255, next-header: ICMPv6 (58), length: 12) 2001::1 > 2001:4860:800E::68: [icmp6 sum ok] ICMP6, echo request, length 12, seq 10299 0x0000: abcd ef00 1122 0000 0000 0011 86dd 6000 ....."........`. 0x0010: 0000 000c 3aff 2001 0000 0000 0000 0000 ....:........... 0x0020: 0000 0000 0001 2001 4860 800e 0000 0000 ........H`...... 0x0030: 0000 0000 0068 8000 0084 804d 283b 6563 .....h.....M(;ec 0x0040: 686f ho