Friday, December 23, 2011

Perl Packet Playback Part 2

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.

Net::Frame

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

Thursday, December 22, 2011

IPv6 Packet Crafting in Perl

I refuse to learn a new programming language just so I can use a tool developed in it. Scapy - a packet crafting tool written in Python - seems like a pretty cool utility when doing testing, as I have been with IPv6 recently. On a Windows machine, options are severely limited when it comes to crafting packets unless you use the WinPcap libraries, and Scapy does this.

However, I don't know Python and have no desire to learn or install it just to get the use of Scapy for the limited testing I'm doing. I do however know Perl and when I found Scaperl I was delighted. It's a port of Scapy from Python to Perl but with very limited feature set and a release date of 2006. At least enough for what I wanted - until I read:

  • there is no support for IPv6.

in the "Known limitations" section of the site. A little more searching lead me to a revived Scaperl site so I grabbed that copy and started testing.

The first step was the install of a few required modules that I didn't yet have - no problems. You will need Net::Pcap installed and there were some issues with the latest version for Windows (cleared up with available patches) back when I installed this long ago. I got Scaperl running and sent a test packet.

The code is a little 'buggy' that is to say not so much incorrect, but it doesn't quite perform the way one would expect. Checksum calculation is one such example. If I don't set the checksum (say in an IP header) I expect Scaperl to calculate for me - which it does. However, if I make some modifications to the packet and then resend, the checksum is incorrect. Scaperl uses the previously calculated checksum. This could be fixed by checking for a "calcualte_checksum" flag versus testing if the checksum value is 0 (which it is originally, but not so much after a first calculation). Minor annoyances which have their workarounds.

More importantly, this Scaperl version has some IPv6 support. I was quickly able to complete the code needed and was sending IPv6 test packets soon after. There isn't yet support for IPv6 Extension Headers, but I was able to cobble together some code that lets me send the routing extension header (IPv6 loose source routing). More work on this when time allows.

Monday, December 19, 2011

The Adventures of Rich and Vince




Characters courtesy of SP Studio

Thursday, December 15, 2011

Cat with 10 Lives

Netcat - that trusty command line utility that's the "Swiss Army Knife of networking" - works very well on IPv4. Since IPv6 is getting hot now, I looked for an IPv6 capable version of netcat and there are plenty out there. The problem is that they are all for Linux based OSs. I have Windows 7. I did find ncat from Nmap.org, but it was a bit lacking in the "GAPING_SECURITY_HOLE" feature on Windows.

Some searching lead me to a Windows version of IPv6 netcat from Sphinx Software.  It was the 1.10 NT (Windows) port of netcat upgraded from IPv4 to IPv6.  Also, it was 1 revision back as the 'latest' Windows version is 1.11.  Ultimately, I wanted an address family agnostic version of netcat, one that would do both IPv4 and IPv6 and have a switch to force either version.

Since my wife was busy writing her Master's thesis and baby is in bed by 8p, I took to editing the source of both netcat and netcat6 to combine them into the ultimate IPv4/v6 capable netcat for Windows - nc64.  It was not as easy as I expected.

I'm not a C expert, but I know it enough to edit existing source code to do what I want.  I also understand socket (winsock) progamming to a degree and with the source code for an IPv4 and an IPv6 version of a small utility like netcat (just over 2000 lines with ample comments) I expected to be done in a few days.  A week and half later I finished.

What was so hard?  Upgrading an IPv4 application to support IPv4/v6 is not that easy.  All name resolution calls need to be rewritten.  In the case of netcat, it needs to be able to resolve a hostname given in the command string to an IPv4/v6 address to connect to.  The orginal netcat source code used gethostby*() functions which don't support IPv6.  I changed those to the newer get*info() calls, but of course the return structures are not the same so I needed to update those.  Worst, netcat uses a custom structure to hold the resolution information and the structure will only hold IPv4 information (netcat) or IPv6 information (netcat6).  I needed to support both.  Enter sockaddr_structure.

The sockaddr_structure can hold both IPv4 and IPv6 socket information - but the documentation and examples were very lacking. Again, not being a C expert, this was a problem for me. Once I finally got it working, I needed to comb through the entire code and replace the original accessors with the new accessors that understoood the sockaddr_storage structure.

Ultimately, the approach I took was an upgraded name resolution routine capable of IPv4 and IPv6 and one that will determine which to use if the user doesn't force a version.  Beyond that, separate connect and listen routines were ported from each of the original netcat and netcat6 sources to support IPv4 and IPv6 connectivity.

My answer isn't the most streamlined or efficient code, but it works perfectly. This experience showed how challenging upgrading existing IPv4 code for IPv6 support is. Writing a new applications to support both address families is becoming more trivial, but adding in support for IPv6 on existing applications without breaking backward compatibility is certainly a challenge.

So now, my Windows NetCat supports both IPv4 and IPv6 -> 4+6=10.

I also took the time to add a few bug fixes, incorporate some extra options usually found in Unix versions and enable multicast listener and sender features for both IPv4 and IPv6.  The compiled versions (64-bit and 32-bit) along with the source code and MinGW Makefile can be found in the software section.

The Adventures of Rich and Vince




Characters courtesy of SP Studio

Friday, December 09, 2011

The Adventures of Rich and Vince




Characters courtesy of SP Studio
 

Copyright © VinsWorld. All Rights Reserved.