nashr has asked for the wisdom of the Perl Monks concerning the following question:

I'm trying to learn more Perl. I've wanted to recreate the functionality of dsniff in Perl. I'm still relatively new to Perl, and not all that familiar with regex, but I think that's what I'll need to use. My current code is:
#!/usr/bin/perl -w use strict; use Net::PcapUtils; use NetPacket::Ethernet qw(:strip); use NetPacket::IP qw(:strip); use NetPacket::TCP; sub process_pkt { my($arg, $hdr, $pkt) = @_; my $tcp_obj = NetPacket::TCP->decode(ip_strip(eth_strip($pkt))); if (($tcp_obj->{src_port} == 80) or ($tcp_obj->{dest_port} == 80)) + { print ($tcp_obj->{data}); } } Net::PcapUtils::loop(\&process_pkt, FILTER => 'tcp');
This prints ALL the data going via HTTP. How would/should I go about parsing out JUST the GET string with the full URL information? Your help is greatly appreciated.

Replies are listed 'Best First'.
Re: recreate dsniff in perl
by gaal (Parson) on Jan 21, 2005 at 17:44 UTC
    I'm not familiar with NetPacket specifically, but it looks like it processes, well, packets when what you need is to look at assembled TCP conversations, the packets of which may be fragmented and arrive out-of-sequence.

    Unless you find a module that does that work for you, you need to accumulate packets and associate them with HTTP requests yourself.

    In the simple case, you can stop accumulating data from a particular connection once you successfully match a GET header, and then clear it from the temporary store. This is not true for HTTP/1.1 connections though, since they may have several requests in them.

    That said, a very quick'n'dirty and unreliable way that may work some of the time is to match the payload of each packet with something that looks like a GET request:

    print "Requested: $1\n" if $payload =~ /GET (\S+)/;

    Here too there is place for added robustness; many things can look like a URI and you only want to match the ones from an actual header.

    Oh: and if you know which end of the connection is the web client, only look for GETs in packets sent from that end :)

Re: recreate dsniff in perl
by traveler (Parson) on Jan 21, 2005 at 21:57 UTC
    If you are familiar with, say, C, you could consider the (possibly non-trivial) task of creating Perl bindings for the ethereal dlls/shared libraries.

    They have a developers' list where you can get help and support. It might make a nice contribution to the Community.

      Actually, everything I want to do is already done in Ethereal. I'm writing my own sniffer engine in Perl. I'm not doing full decode of data, only gathering stats into a MySQL database for evaluation via SQL. The dsniff idea is a spinoff of that project. All I want to do is take the tcp payload data and figure out how to grab the GETs out of the stream. If you take my sample code and run it, you'll see what I'm faced with. I believe a regex would do the trick, but I just don't know that much about it yet. I guess that's where I'll start my reading. If you want to check out my sniffer project, go here. Thanks for the feedback.